Household Ledger
Brown Family

Household Ledger · Design System

The theme sheet

Every visual part the application owns, before any page is built on top of them.

Awaiting sign-off
Locked from the original repository. The palette, radius, type scale and the hl-* component vocabulary are carried over token-for-token. A prototype contributes structure — which regions exist, what they are called, which actions they carry. It does not contribute colour, radius or type. Parts marked New did not exist in the original and are built only from the tokens below.

Colour

Sixteen tokens, and nothing else. Every colour in the app is one of these; none of them are written as a raw hex anywhere but in :root.

Ground
Paper
#f7f4ee · --hl-bg
The page. Warm, never white.
Surface
#ffffff · --hl-surface
Cards, menus, headers.
Surface 2
#f1ece3 · --hl-surface-2
Wells, table heads, meter tracks.
Line
#e4ddd0 · --hl-line
Every border in the app.
Text
Ink
#2b2723 · --hl-ink
Body text. Warm near-black.
Muted
#7a7266 · --hl-muted
Secondary text, labels.
Dim
#a89e8f · --hl-dim
Placeholders, disabled.
Identity
Ledger green
#2f7d5b · --hl-accent
Primary action, active nav, good.
Green soft
#e3f0e8 · --hl-accent-soft
Green backgrounds.
Gold
#a9852e · --hl-gold
Section labels, focus ring.
Gold soft
#f3ead0 · --hl-gold-soft
Gold backgrounds.
Dark bar
#28231e · --hl-dark
The global application bar.
Status
Good
#2f7d5b · --hl-good
Settled, on track, paid.
Warn
#c98a2b · --hl-warn
Due, needs attention.
Bad
#c0492f · --hl-bad
Overdue, failed, owed.
Link blue
#2d5b8a · --blue
Cross-system references only.
Blue soft
#e9eef6 · --blue-soft
Blue backgrounds.

Type

Two faces. The system sans carries everything that has to be read quickly or read a lot; the serif is reserved for page and area headlines, which is what gives the app its ledger-book feel without costing legibility where text gets dense.

Page title · serif 30px
Your household, at a glance.
Section title · sans 17px semibold
Upcoming this week
Gold label · 11px bold caps
Household Briefing
Muted label · 10.5px bold caps
Last reconciled
Body · 14px

The household’s money at the kitchen table. Warm paper tones, high legibility, generous touch targets — sized for a thumb first and a mouse second.

Tabular numerals · money always lines up
1,204.00
88,310.55
−417.98

Sans: ui-sans-serif / system-ui / Segoe UI. Serif: Georgia. No web fonts are loaded — the app renders instantly and identically offline.

Buttons

Minimum 44px tall — thumb-sized. One primary per screen region; if two things are green, neither is the primary.

Variants

Primary = ledger green, the one action the page is for. Ghost = everything else. Gold = money movement specifically. Danger New is outlined, not filled — a solid red would outshout the primary on every screen it appears on.

Disabled

40% opacity and a not-allowed cursor. The label never changes.

Compact — 38px New

For secondary actions inside a card whose primary already meets the 44px floor. Keeping all five at 44px is what made the original’s action band as tall as the record it belonged to.

Phone — primary owns its row
Focus ring

Tab to any control on this page. The ring is gold, deliberately not green — the green already means “active”, and a focus ring the same colour as the active state is a focus ring nobody can find.

Dropdowns

Two different controls that both get called a dropdown. Pick by the job: choosing a value from a list is a select; running a command is a menu.

Select — pick a value New

A real native <select>, restyled. On a phone that means the OS wheel picker, which is faster and more accessible than any custom list.

Menu — run a command New

Press it. Escape closes and returns focus, arrows move between items, Tab is trapped while it is open.

The menu is a small card — same radius, same border, same surface. It never looks like a browser widget dropped onto the page.

Fields

Fields are soft paper wells that turn white on focus, so the field you are typing in is the brightest thing on the form.

Repeat monthly New
Creates the next occurrence automatically.
Disabled switch

Status tags

Compact, uppercase, and the only way status is expressed. A status written as coloured body text is a status that cannot be scanned.

NeutralPaidDue in 3 daysOverdueLinkedVehicleTrustee

cls carries a classification (what a record is). rolecarries a person’s relationship to it. They are separate tokens because a record can be both, and they must never be read as the same kind of fact.

Callouts

For a sentence the household needs to read before acting. Four tones, matching the status colours exactly — a callout never introduces a colour a tag cannot.

On track. Every bill due this week is funded.
Needs attention. Two bills are due before the next paycheck lands.
Overdue. The water bill was due 6 days ago.
Linked from Records. This vehicle is also referenced by two open Matters.

Metrics and meters

Numbers first, label above, unit never abbreviated away.

Needs attention
3
Due this week
1,204.00
Runway
62 days
Household state
Stable
Groceries72%
Utilities91%
Auto repair108%

Meter severities are New. Without them a meter stayed green beside a card that had already gone red.

Local tabs

The second of the two navigation levels. These belong to the area you are in; they are never a second global hierarchy.

Cards

Two kinds. A plain card groups content. A record card represents one real thing and may carry a severity edge.

Right now

A plain card. Groups content, claims nothing about status.

No edge

Nothing remarkable about this record.

Water · City Utilities

Paid 4 days ago

Paid
Electric · Grid Co

Due in 3 days

Due
Internet · Fiber One

Overdue by 6 days

Overdue

A record with nothing remarkable about it gets no edge. If every card has a stripe, the stripe stops meaning anything.

Table

Desktop density. Scrolls inside its own frame rather than pushing the page sideways.

BillAccountDueAmountStatus
Water · City UtilitiesJoint checkingAug 1286.40Paid
Electric · Grid CoJoint checkingAug 26214.09Due
Internet · Fiber OneHousehold cardAug 1799.00Overdue

New — the original had no table part. Money columns are tabular-numeral and right-aligned; a column of figures that does not line up is a column nobody reads.

Page states

Five answers to “why is there nothing here”, sharing one shape so they never look like they came from different applications. The authority contract requires the last four on every slot.

Coming soon — every area today

Cash Flow is coming soon

The shell around this page is finished — navigation, theme and layout are locked. The page itself is next: its prototype gets translated into React, then connected to data.

Shell complete · page not built
Not connected — built, but no data source

Cash Flow is not connected yet

The shell around this page is real — navigation, theme and layout are final. The page itself is waiting on its prototype translation and its data source. Nothing is broken.

Shell only · no data source
Empty — working, nothing to show

No bills yet

When a bill is added it will appear here, sorted by what is due first.

Error — it failed

Bills did not load

The connection timed out. Nothing was changed, and trying again is safe.

Loading — a skeleton, not a spinner
Loading

Neither Coming soon nor Not connected is an error. Nothing is broken — one page has not been built, the other has been built and has no data source. Dressing an on-schedule build stage as a failure trains the household to ignore the words on a real one.

What changed from the original

Everything carried over is unchanged. These are the additions, and why each one exists.

AddedWhy it was needed
hl-selectThe original styled no native select; every dropdown was bespoke.
hl-menuThe one menu it had was hand-rolled inside the shell, not reusable.
hl-btn-danger--hl-bad existed as a status colour but never as a button.
hl-btn-smThe 38px secondary size existed inline in one card, unnamed.
hl-bar-warn / badMeters stayed green beside cards that had gone red.
hl-stateEmpty, error and not-connected had no shared shape.
hl-skeletonThere was no loading treatment at all.
hl-tableNo table part existed.
hl-switchNo toggle existed.
hl-page / sectionPage furniture was grown per-page and would drift across ten areas.
--hl-darkThe dark global bar comes from the accepted navigation prototype.
--hl-displayThe serif headline face, also from that prototype.

Twelve additions, zero new colours. Every one is composed from the sixteen tokens at the top of this page.