Design system
Rendered from the tokens, not written about them. Every swatch reads its value from packages/shared, and every component below is the one the product ships.
The mark
One geometry, simplified below 48px where the inner coil fills in.
Surfaces
Four grounds. Anything that sits on one must clear its contrast against the hardest of them.
Roles
Named by the job they do, not by the colour they are.
Contrast
Computed on render. A failure here is a failure in the product, not a stale note in a document.
| Pairing | Ratio | Needs | Light |
|---|---|---|---|
| text on background | 12.86 | 7 | pass |
| textMuted on surface | 7.66 | 4.5 | pass |
| primaryText on primary | 5.47 | 4.5 | pass |
| accentText on accent | 10.03 | 4.5 | pass |
| dangerText on danger | 6.14 | 4.5 | pass |
| success on successBg | 5.17 | 4.5 | pass |
| borderStrong on background | 3.59 | 3 | pass |
The dark theme is solved independently and asserted by src/lib/palette-contrast.test.ts, which also requires body text to stay under 16:1 — black on white is 21:1 and is the pairing most often reported as causing glare.
Buttons
Every variant, at the standing 44px minimum target.
Status
Never carried by hue alone — every state has a word in it.
Alerts
Fields
2px border at 3:1, 3px focus ring. Tab into it.
Empty state
Nothing here yet
What a list says before it has anything to show.
Cards
A card
A raised object among objects. A Panel — what every section on this page uses — is a region of the screen you are already on.
Dark
Solved independently. Not an inversion of the light theme.