Identity / Colour
Colour
Cream ground, ink type, one Forest. The palette is small on purpose. Every value below comes from tokens.json; never sample a colour from a screenshot.
01Core palette, light
--bgPage ground (cream)
--surfaceBands, figures, form panels
--cardCards only
--inkHeadings, wordmark
--ink-2Body text
--muteMono labels, secondary borders
--lineHairlines; decorative only
--primaryForest: action, owned, slash
--primary-tintOwned-panel tint
--primary-edgeTint edge
--accentChart secondary
--inverse-bgClose band
02Core palette, dark
--bgPage ground (cream)
--surfaceBands, figures, form panels
--cardCards only
--inkHeadings, wordmark
--ink-2Body text
--muteMono labels, secondary borders
--lineHairlines; decorative only
--primaryForest: action, owned, slash
--primary-tintOwned-panel tint
--primary-edgeTint edge
--accentChart secondary
--inverse-bgClose band
03Functional colours
--successStates only
--warningStates only
--dangerErrors only
--infoNotes, info states
Each has -bg and -edge partners for panels. Functional colours never decorate.
04Rules
- Forest means owned, or do this. The primary action, the owned element in a figure, the slash. Never a frame, a heading colour or a background block.
- At most three Forest uses per viewport (for example: the slash, one primary button, one owned marker). Markers in a single owned list count as one Forest use. The primary action counts as one use per viewport however many times it appears: a header button and a hero button are one use.
- Labels and headings are never Forest text. Use ink or mute. Link arrows inherit the link colour and are never Forest.
- Line colours are decorative. At 1.3:1 they never carry meaning or mark an interactive boundary; inputs and secondary buttons use
--mute. - White is for cards only. The page is cream. Never more than about six cards visible at once.
- Dark theme swaps every token; components never hard-code a hex value.
05Contrast pairings
WCAG 2.2 ratios, generated from tokens by build_tokens.py. Text needs 4.5:1, large text and UI boundaries 3:1.
Light
| Pairing | Ratio | Allowed use |
|---|---|---|
Aa ink on bg | 15.47:1 | any text size |
Aa ink on card | 17.82:1 | any text size |
Aa ink-2 on bg | 10.3:1 | any text size |
Aa ink-2 on surface | 9.76:1 | any text size |
Aa ink-2 on card | 11.87:1 | any text size |
Aa mute on bg | 4.92:1 | any text size |
Aa mute on surface | 4.66:1 | any text size |
Aa mute on card | 5.67:1 | any text size |
Aa primary on bg | 5.19:1 | any text size |
Aa primary on card | 5.98:1 | any text size |
Aa primary-fg on primary | 5.19:1 | any text size |
Aa primary-fg on primary-hover | 7.07:1 | any text size |
Aa inverse-fg on inverse-bg | 15.47:1 | any text size |
Aa ink on primary-tint | 15.16:1 | any text size |
Aa danger on bg | 7.43:1 | any text size |
Aa warning on warning-bg | 4.97:1 | any text size |
Aa info on info-bg | 5.49:1 | any text size |
Aa ink-2 on primary-tint | 10.1:1 | any text size |
Aa danger on danger-bg | 6.33:1 | any text size |
Aa warning on bg | 5.41:1 | any text size |
Aa info on bg | 6.02:1 | any text size |
Aa mute on bg | 4.92:1 | UI boundary OK (>=3:1) |
Aa mute on card | 5.67:1 | UI boundary OK (>=3:1) |
Aa line on bg | 1.29:1 | decorative only, never for meaning |
Aa line on card | 1.48:1 | decorative only, never for meaning |
Aa primary on bg | 5.19:1 | UI boundary OK (>=3:1) |
Dark
| Pairing | Ratio | Allowed use |
|---|---|---|
Aa ink on bg | 14.64:1 | any text size |
Aa ink on card | 11.9:1 | any text size |
Aa ink-2 on bg | 9.49:1 | any text size |
Aa ink-2 on surface | 8.74:1 | any text size |
Aa ink-2 on card | 7.71:1 | any text size |
Aa mute on bg | 5.58:1 | any text size |
Aa mute on surface | 5.14:1 | any text size |
Aa mute on card | 4.54:1 | any text size |
Aa primary on bg | 8.79:1 | any text size |
Aa primary on card | 7.14:1 | any text size |
Aa primary-fg on primary | 8.79:1 | any text size |
Aa primary-fg on primary-hover | 10.82:1 | any text size |
Aa inverse-fg on inverse-bg | 16.18:1 | any text size |
Aa ink on primary-tint | 11.68:1 | any text size |
Aa danger on bg | 5.74:1 | any text size |
Aa warning on warning-bg | 7.96:1 | any text size |
Aa info on info-bg | 7.55:1 | any text size |
Aa ink-2 on primary-tint | 7.57:1 | any text size |
Aa danger on danger-bg | 5.21:1 | any text size |
Aa warning on bg | 9.47:1 | any text size |
Aa info on bg | 8.49:1 | any text size |
Aa mute on bg | 5.58:1 | UI boundary OK (>=3:1) |
Aa mute on card | 4.54:1 | UI boundary OK (>=3:1) |
Aa line on bg | 1.45:1 | decorative only, never for meaning |
Aa line on card | 1.18:1 | decorative only, never for meaning |
Aa primary on bg | 8.79:1 | UI boundary OK (>=3:1) |
--warning is #7A5C12 (was #8B6915): 5.41:1 on cream and 4.97:1 on its own tint, so warning text passes AA at any size.Dark
--mute is #868F87 (was #828B83), the smallest lift that passes on dark cards: 4.54:1 on --card, up from 4.31:1.06Chart colours
--chart-c1Series 1: the comparison
--chart-c2Series 2: the owned or decision value
--chart-c3Series 3
--chart-c4Series 4: sand, the remainder