Radius
--radius-sm6px · chips--radius-md10px · buttons, inputs--radius-lg16px · cards
6 editable tokens. 3 depth levels. 1 card. 1 input. Every component derives from these — pick a token,
the whole system responds. Spec lives in design.md.
Six tokens, three depth levels, one polish scale. Everything below is derived from these — nothing here is a one-off.
Click any swatch to recolor live. Picks persist to localStorage.
Surface tokens (background · foreground · font) flip with mode — picks apply to the dark mode you're viewing. Brand tokens apply to both.
#1a1a1a#212121#ffffff#1d3a66#3d4451#324e32on-{primary,secondary,tertiary} · border · muted · page Page (L0) → card (L1) → content (L2). No 4th level. Sidebar = L1. Inputs = L2.
--color-page --color-background --color-foreground Baked into components. Not editable. Snap to scale or polish breaks.
--radius-sm6px · chips--radius-md10px · buttons, inputs--radius-lg16px · cards--shadow-cardcards, popovers--shadow-popmenus, modals4 · 8 · 12 · 16 · 20 · 24 · 32 — every padding/gap lands here.
A theme is six colours per mode and nothing else. The border, the page, the muted surface and the focus ring are all derived from those six — which is why a palette can invert the card/page ladder and every surface still lands correctly. Press one and the page you are reading repaints.
Defined once in src/lib/themes.ts. They are the same object a stored brand
is — six triples per mode — so they go through the same apply() below and
the picker does not know which kind it is wearing. Your pick persists to
localStorage; saving a workspace brand clears it, because a workspace's
palette outranks a personal one.
· ships by default Warm stock and espresso ink. The card sits BELOW the page, so a panel reads as a sheet laid on a desk rather than a box floating over grey.
The original neutral. A white card on a grey page — the conventional ladder, kept selectable so the pre-Paper look is one click away rather than a git revert.
The same vocabulary, worn by two workspaces. Press Wear this brand and every surface on this page repaints — that is the claim at the top of the page, run rather than asserted.
The 6 tokens, per workspace, read from <slug>/site.md in R2 at request
time — the same object Layout.astro reads to paint every branded page.
Nothing here is transcribed, so a value shown is a value served.
one.ie12 values stored · 6 light · 6 dark
ehc.one.ie12 values stored · 6 light · 6 dark
The workspace context decides, not the path. ehc.one.ie wears
EHC's palette because its workspace context is ehc; one.ie/ehc
wears ONE's, because that route is on the one host. Both are correct, and which
one a given surface should wear is a product decision rather than a defect.
What the vocabulary builds. One card, one input, two icon registries — each reading the tokens above, never a colour of its own.
Header · body · footer share one card surface
Sidebar = L1 (card pinned to edge)
All inputs share one shape · L2 surface · 10px radius
6 variants. on-* labels auto-contrast.
One source: lucide-react. 1.5px stroke · round caps · token-driven color. Wrap with <Icon> or <IconBadge>.
Used in feature grids, list items, profile rows.
primary tertiary secondary neutral Sizes — sm · md · lg
Inline icons. Inherit color from parent via currentColor.
sm · 14 md · 16 lg · 20 xl · 24 In context
6 families, each derived from a surface that already existed and had no icon — nothing
was invented to round out a pack. Real Lucide components, so they inherit the 1.5px stroke
and paint with currentColor: no hex can enter the set.
Source: lib/ehc-icons.ts.
Three states told apart by silhouette only. Fill and hue both die at 16px under a six-token palette, so neither may carry the meaning.
ehc-locked Only the people in my meeting can see this ehc-open Anyone with my plan can see this ehc-interpreted Someone wrote this down for me — these are not my own words ehc-interpreted is not a lock. It is a provenance claim that
this came through an adult, it sits beside the lock, and it must never fuse with it — it
is the glyph that stops “the CYP agrees” being written. And the lock never means
you are denied access; it means your circle is small, which is a promise
to the child rather than a refusal to the reader.
ehc-interpreted ehc-locked ehc-open voice-aac voice-audio voice-drawing voice-helper voice-photo voice-showing voice-video voice-writing cohort-complex-communication cohort-complex-medical cohort-early-years cohort-looked-after cohort-post-16 cohort-primary cohort-secondary stage-assess stage-decide stage-deliver stage-draft stage-finalise stage-request stage-review stage-transition domain-care domain-education domain-health role-chairman role-cyp-voice role-doctor role-keyworker role-local-authority role-parents role-senco role-social-worker role-therapist 1 of 7 EHC document templates are built —
the minutes, at lib/ehc/minutes.ts. The rest are specs in
text/ehc-templates-plan.md and text/ehc-deck-ui.md;
lib/ehc/templates.ts is the registry that counts them.
A cohort icon names the duty owed, never a body. No wheelchair, no ear, no
signing hands, no child figure — complex-medical is the s.42 obligation,
complex-communication a speech mark and not a mouth,
looked-after the corporate parent. The test is one line: if the glyph names a
person's body it is wrong; if it names the duty, it is right.
13 card types. Every surface in the product derives from one of these shapes.
Handle refund requests
1200 ms
3 checks passed
What would you like to do?
No agents yet
Create your first agent to get started
A field of paths. A pulse takes one. Unused recede. The field holds. Live tokens.