Liquid today
£5,043,995
up £225,780this week to date
£3,748,600 on notice or ring-fenced, and not counted here
Clearing is 7 routes and 27 parts on 120 design tokens, every one re-authored for dark. Every figure on this page and on every route resolves through one fixture file, so nothing here can disagree with anything there.
Fixture spine: 13 weeks, 3 closed, 10 open, 2 under the covenant floor — consistent.
--background
--card
--surface-sunken
--surface-raised
--muted
--border
--border-strong
--foreground
--primary
--primary-hover
--primary-soft
--accent
--ring
--selection
--positive
--warning
--critical
--info
--horizon-actual
--horizon-forecast
--horizon-floor
--chart-3
rounded-themed-sm
rounded-themed
rounded-themed-lg
rounded-themed-xl
rounded-themed-pill
One thirteen-week horizon, drawn three times at three sizes. All three call weekFor(), which throws on a week outside the window, so no drawing can disagree with another about where the money runs out.
src/components/ui/horizon.tsx
Closed weeks are solid, open weeks are hatched, a week under the covenant floor takes the breach ground. The distinction is a texture rather than a hue, so it survives greyscale and a projector.
HorizonStrip — inside a row or a card
HorizonColumn — the head of a page about one week
Closing, w/c 5 Oct
£1,084,780
£915,220 below the £2.0m floor
HorizonLegend
HorizonGrid — the full instrument
| Week | 3 Augclosed | 10 Augclosed | 17 Augclosed | 24 Augopen | 31 Augopen | 7 Sepopen | 14 Sepopen | 21 Sepopen | 28 Sepopen | 5 Octopen | 12 Octopen | 19 Octopen | 26 Octopen |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Receipts | £4.1m | £3.0m | £3.7m | £3.4m | £2.9m | £4.0m | £3.2m | £3.6m | £2.9m | £3.4m | £3.9m | £4.0m | £3.7m |
| Payments | −£3.9m | −£4.4m | −£3.2m | −£3.2m | −£4.0m | −£3.3m | −£3.4m | −£3.7m | −£4.1m | −£6.4m | −£3.0m | −£3.2m | −£3.5m |
| Closing | £6.8m | £5.4m | £5.9m | £6.1m | £5.0m | £5.7m | £5.4m | £5.3m | £4.1m | £1.1m | £1.9m | £2.8m | £3.0m |
| Headroom | £4.8m | £3.4m | £3.9m | £4.1m | £3.0m | £3.7m | £3.4m | £3.3m | £2.1m | −£915k | −£57k | £775k | £988k |
| v forecast | +£122k | −£271k | +£128k | — | — | — | — | — | — | — | — | — | — |
src/components/ui/ (primitives)
The primitives together, at the density the console actually uses them: a control bar, a figure column, the states a row can be in. Every interactive element shows rest, hover-equivalent, disabled and focus; focus is never transitioned.
a control bar
unavailable, with the reason in the title
the focus ring, on every control
what a row can say about itself
a money column, tabular by construction
src/components/ui/money.tsx
A figure a reader compares is tabular; the one hero figure at the head of a card is not. Direction is never colour alone — every delta carries an arrow whose angle means what the colour means, and zero gets its own glyph.
DisplayFigure
£4,352,940Figure — tabular
£1,842,300£90,514£2,486Delta
up £124,000down £41,800unchanged £0up 4.2%DualFigure — foreign currency
€1,236,410£1.1m$612,880£485ksrc/components/ui/button.tsx
Every state is a token, never an alpha modifier: the hover and active steps move lightness in the direction that raises the label's contrast, and they move a different way in each mode.
src/components/ui/badge.tsx
Status colour is reserved: it is never a chart series and never a brand surface. Every badge carries an icon whose shape differs from its neighbours', so the row still reads with the colour removed. 'Awaiting' is deliberately not a status colour — it is the absence of a decision, not a warning.
payment state
tones
covenant
Eyebrow and FigureLabel
Operations
Liquid todaysrc/components/ui/panel.tsx
The console's one container: a hairline, a card ground, one radius, and no shadow. Every header carries a mark, because on a route with six panels of identical weight the icon is what lets the eye find the table it wants. A coloured ground is earned — it appears only when the panel is reporting a condition this theme already colours.
Meta line — what the panel is of
Panel body.
Only when the panel reports a condition the theme already colours
€356,400 is past terms. The ground is the critical soft, the same one the Overdue badge takes, because the panel is that status — not because a header wanted decorating.
Small on purpose — on a console the page title is a wayfinding label, and the largest thing on screen should be a number the reader came for.
src/components/ui/table.tsx
Numeric columns are right-aligned and tabular in one decision, because separating them is how a column ends up right-aligned with proportional digits. The empty state names the filter that produced it — an empty result is not an empty run.
rows, totals
| Beneficiary | Amount | State |
|---|---|---|
| Solvay Chemicals BV | €612,400 | Approved |
| Brenntag UK | £286,400 | Awaiting |
| Total | £814,600 |
empty
No held instructions
The run has 12 instructions in it. Nothing matches this filter — the run is not empty, the view is.
src/components/ui/dashboard-layout.tsx
Three navigation planes, picked in the header and remembered. The theme shipped two for a day on the argument that a desk uses one shape — which was right about the desk and wrong about the buyer, who is building their own console and needs the shell to be the part they can decide.
sidebar
Header
Main
rail
Header
Main
topbar
Top bar
Header
Main
the picker itself
src/components/app-shell.tsx
Navigation, the freshness line, and the covenant count riding the Forecast item — a standing fact in a standing place, never a dismissible notification. Rendered here at panel scale; on a route it claims the viewport.
Cash position
Balances as at 09:14 on 27 Aug
The route’s own content.
src/components/account-index.tsx
The page's top edge on / — hero archetype A9. The column that makes it an index rather than a list is 'what it is for'.
Seven accounts · five banks · three currencies
| Account | Cleared |
|---|---|
| Lloyds · Operating | £1,842,300 |
| Lloyds · Deposit | £3,500,000 |
| BNP Paribas · Operating EUR | €1,236,410£1.1m |
| BNP Paribas · Collections EUR | €864,220£745k |
| Wells Fargo · Operating USD | $612,880£485k |
| HSBC · Duty deferment | £248,600 |
| Handelsbanken · Payroll | £905,140 |
| Total, sterling equivalent | £8,792,595 |
src/components/position-summary.tsx
Each card is one number, its movement, and one clause saying what it excludes — the part most stat rows leave out and the part a treasurer needs.
Liquid today
£5,043,995
up £225,780this week to date
£3,748,600 on notice or ring-fenced, and not counted here
Committed, not yet moved
−£1,536,707
Payroll, duty deferment and the approved half of run R-2634
Releases Thursday
−£1,429,920
Two held items and one returned item are outside this figure
Lowest week in the window
£1,084,780
down £915,220against the floor
w/c 5 Oct, and 1 more under the floor
Thirteen weeks from w/c 3 Aug
Trough £1,084,780 in w/c 5 Oct · floor £2,000,000
src/components/movements-table.tsx
8 entries · newest first
| Date | Entry | Amount | State |
|---|---|---|---|
| 27 Augw/c 24 Aug | Customer receiptIneos Composites | up £842,000 | Cleared |
| 27 Augw/c 24 Aug | Payroll fundingHandelsbanken sweep | down £882,000 | In flight |
| 26 Augw/c 24 Aug | Customer receiptCroda Europe | up €416,000 | Cleared |
| 26 Augw/c 24 Aug | Duty defermentHMRC | down £248,600 | In flight |
| 25 Augw/c 24 Aug | Supplier paymentSolvay Chemicals BV | down €182,400 | Cleared |
| 25 Augw/c 24 Aug | FX settlementLloyds Markets | up $392,000 | Cleared |
| 24 Augw/c 24 Aug | Customer receiptSynthomer | up £624,000 | Cleared |
| 21 Augw/c 17 Aug | Supplier run R-263342 beneficiaries | down £2,914,000 | Cleared |
src/components/payment-run.tsx
The theme's state surface: selection, a filter whose empty state names itself, an approval that leaves a durable receipt rather than a toast, a hold that carries its reason, and a permission boundary written as a sentence.
Supplier run R-2634 · releases Thursday 27 August
£1,429,920
12 instructions · 2 awaiting approval
You can approve individual instructions. Releasing the run needs a second signature — Paul Osei, Financial controller — under the two-eyes policy for runs above £250k.
Filtered: All
| Select | Beneficiary | Amount |
|---|---|---|
| Not selectable in this state | Solvay Chemicals BVINV-88214 · caustic soda Q3Approved | €612,400£528k |
| Not selectable in this state | Warrington Borough CouncilBusiness rates, SeptApproved | £48,200 |
| Brenntag UKINV-31907 · solvent recoveryAwaiting | £286,400 | |
| Not selectable in this state | Kuehne + NagelFreight, week 34Approved | €121,800£105k |
| Not selectable in this state | Redhill EngineeringPO-4471 · reactor sealsHeldGoods receipt not matched — 40 of 60 seals | £89,400 |
| Not selectable in this state | Univar SolutionsINV-77301 · glycolApproved | $194,200£154k |
| Not selectable in this state | Sellafield AnalyticsQ3 testing retainerApproved | £31,500 |
| Aker Insulation ASINV-2211 · plant laggingAwaiting | €73,600£63k | |
| Not selectable in this state | Northgate Vehicle HireFleet, AugustApproved | £22,800 |
| Not selectable in this state | Ellesmere Port TerminalsStorage, Aug — disputed volumeHeldVolume queried with the terminal, 18 Aug | £117,000 |
| Not selectable in this state | Grieg MaritimeCharter, MV TorstenApproved | $241,000£191k |
| Not selectable in this state | Hays Specialist RecruitmentContract shift cover, wk 33–34ReturnedBeneficiary account closed — new details requested | £56,400 |
src/components/account-statement.tsx
Lloyds · Operating
GB29 LOYD 3096 5502 2201 14
4 entries · running ledger balance, in the account's own currency
| Date | Entry | Amount |
|---|---|---|
| 27 Aug | Payroll fundingHandelsbanken sweep · in flight | down £882,000 |
| 27 Aug | Customer receiptIneos Composites | up £842,000 |
| 24 Aug | Customer receiptSynthomer | up £624,000 |
| 21 Aug | Supplier run R-263342 beneficiaries | down £2,914,000 |
6 instructions · £595,300
Warrington Borough Council
Business rates, Sept
£48,200
Approved
Brenntag UK
INV-31907 · solvent recovery
£286,400
Awaiting
Redhill Engineering
PO-4471 · reactor seals
£89,400
Held
Sellafield Analytics
Q3 testing retainer
£31,500
Approved
Northgate Vehicle Hire
Fleet, August
£22,800
Approved
Ellesmere Port Terminals
Storage, Aug — disputed volume
£117,000
Held
src/components/counterparty-detail.tsx
One name, both ledgers, one net. A disputed invoice is in the exposure and out of the forecast — it counts against the credit limit because the money is still ours, and it is absent from the horizon because we cannot name a week we expect to bank it.
Rotterdam, NL · EUR · 45-day terms
Customer and supplierTrading since 2019 · Marieke de Vries · credit control
They owe us
€701,100
£605k
We owe them
€612,400
£528k
Net exposure
€88,700
in our favour
Receivable against a €750,000 credit limit
93% used · €48,900 of headroom
The thirteen-week horizon, with only this counterparty's weeks marked
3 Aug
10 Aug
17 Aug
24 Aug
31 Aug
7 Sep
14 Sep
21 Sep
28 Sep
5 Oct
12 Oct
19 Oct
26 Oct
45-day terms · EUR throughout
| Invoice | Due | Amount |
|---|---|---|
| BC-4471compound BX-40, 12tOverdue11d | 16 Augw/c 10 Aug | €284,000£245k |
| BC-4488compound BX-40, 8tOpen | 11 Septw/c 7 Sep | €196,500£169k |
| BC-4502compound BX-55, 6tOpen | 28 Septw/c 28 Sep | €148,200£128k |
| BC-4460compound BX-40, 3tCertificate of analysis rejected on batch 22-114; retest booked for 2 SeptemberDisputed | 2 Augoutside the window | €72,400£62k |
| Outstanding | €701,100 |
Against 45-day terms, as at 27 Aug
src/components/console-menus.tsx
Every standing condition is derived — the covenant count from breachWeeks(), the overdue receivable from the sales ledger, the approval count from the run. Nothing here is dismissible: these are conditions, not events, and a dismiss button teaches people to clear the list rather than the condition.
src/components/exposure-charts.tsx
No hex reaches a recharts prop — every series is a CSS variable, which is why a rebrand recolours the charts and why both modes are right without a second chart config. Every chart has its numbers in text one disclosure away.
Group, sterling equivalent · the dashed line is the covenant floor
| Week | Closing | Against the floor |
|---|---|---|
| w/c 3 Augclosed | £6,832,000 | £4,832,000 |
| w/c 10 Augclosed · Q3 VAT, £1.42m | £5,394,000 | £3,394,000 |
| w/c 17 Augclosed | £5,876,000 | £3,876,000 |
| w/c 24 Augforecast · Run R-2634 goes Thursday | £6,101,780 | £4,101,780 |
| w/c 31 Augforecast · August payroll, £882k | £4,975,780 | £2,975,780 |
| w/c 7 Sepforecast | £5,679,780 | £3,679,780 |
| w/c 14 Sepforecast | £5,422,780 | £3,422,780 |
| w/c 21 Sepforecast | £5,314,780 | £3,314,780 |
| w/c 28 Sepforecast · September payroll | £4,132,780 | £2,132,780 |
| w/c 5 Octforecast · EIB development loan, €4.10m | £1,084,780 | −£915,220 |
| w/c 12 Octforecast | £1,942,780 | −£57,220 |
| w/c 19 Octforecast | £2,774,780 | £774,780 |
| w/c 26 Octforecast | £2,987,780 | £987,780 |
What comes in against what goes out — the shape behind the closing line
Net position by currency, sterling equivalent, split by what is already bought
Struck rate against this morning's fix
| Currency | Net position | Hedged | Cover | Mark |
|---|---|---|---|---|
| EURNet payer | −€4,128,000 | −€3,300,000 | 80% | −£47,190 |
| USDNet receiver | $1,284,000 | $640,000 | 50% | −£6,976 |
src/components/ui/popover.tsx · ui/hint.tsx
The control behind this theme's helper rule: a panel's helper text is one clause, and the reasoning lives one press away. A popover and not a tooltip, because this holds sentences — a tooltip is for a label too short to fit, is unreachable on touch, and is hostile to a screen reader when it holds a paragraph.
the surface
in place — a helper line and its hint
src/components/ui/dropdown-menu.tsx
Behaviour vendored from tt-ui 1.4.0; every class is this theme's. The hover surface is the achromatic accent, because a tinted row would be the only brand-coloured surface on a screen whose argument is that colour means money — and a disabled row keeps its reason under the list, where an explanation long enough to be useful actually fits.
the surface, opened
live — drive them
src/components/ui/dialog.tsx
The console's own card, raised by one shadow token and stopped behind a neutral scrim — no bounce, no scale-up from nothing. The width is `surface`'s and the ground is `panel`'s, which is what lets the photograph below sit at the live width instead of a layer's.
the surface, no layer
live — open it
src/components/ui/confirm-dialog.tsx
`ui/dialog`'s recipe plus three slots for the typed gate, so there is one dialog appearance in this theme rather than two that drift. What is typed is the run's own id — the second signature is a policy this product printed on three routes and never actually asked for.
the surface, gate unsatisfied
live — the run's own gate
src/components/ui/tabs.tsx
Selection is a 2px rule under the tab, not a pill: every other selected thing in this console is identified by a ground, and a fourth ground would make the strip compete with the panel it sits in. The travelling indicator stays off — it measures wrong for one frame on mount, and these strips are at the top of a panel that renders on load.
the strip, at rest
Four open invoices, one of them disputed.
a tab out of play
Four open invoices.
live — the counterparty's three ledgers
€701,100 open, €284,000 of it past terms.
src/components/ui/field.tsx
The label is always there and never a placeholder. The supporting line and the message share one row, so a field does not grow when it fails — a form whose rows jump as they validate moves the control the reader was about to fix.
rest
What the month-end hold report counts this under.
invalid
Choose the category this hold is counted under.
valid
Checked against the bank's directory this morning.
read-only
Set when the run opened; it cannot be changed from here.
disabled
Assigned by policy, not by this form.
src/components/ui/form.tsx
Not a visible object — a `<form>` around fields that already know how to look. `core/form` owns the flow: validate on submit, focus the summary or the first invalid control, keep every valid value, disable the fieldset while in flight, refuse a second submit, and name where focus goes when the receipt arrives.
live — submit it empty, then fill it
src/components/ui/form-error-summary.tsx
The only alert region in the theme, and the one panel a failed submit puts focus into. The links are underlined rather than coloured-and-bare: everything in this list is already critical, so colour cannot also be what says clickable.
two fields still owed
2 fields still need an answer
src/components/ui/search-input.tsx
The console's field, sat on the list it searches rather than in the shell's header — a search 200px above its own results is a worse control even when it works. The clear is a real button with a name that returns focus to the input; WebKit's native one has none of the three, so it is hidden.
live — type, then clear it
rest
filled
1 of 12 instructions match \u201csolvay\u201d
no result
0 of 12 instructions match \u201cineos\u201d
disabled