Reactive CSSdesign system
00 · Concept

Static is ink. Reactive is vermilion.

The site is almost monochrome. One color is reserved for one meaning: something that can change at runtime. That covers Reactive CSS syntax in code, live values, and state readouts. Native CSS, navigation, buttons and prose never use it. When a reader sees vermilion, they are looking at the part this library adds.

Signature 1

Live values in code

Every state declaration shows its current value as an outlined chip at the end of the line. Code blocks are never just pictures of code.

Signature 2

The reaction trace

On interaction, the lines involved light up in order: the event, the state it wrote, then the declarations that changed. Unused when() branches fade.

Mark

A value in a block

A declaration block holding one live value. The same dot marks active state across the site.

specimen.cssspecimen · no runtimereactive
/* native CSS stays ink */.chip {  --open: state(false);false  rotate: when(--open, 45deg, 0deg);}.chip:on(click) { --open: toggle(); }.chip:when(--open) .menu {  display: block;}
state()Function · hover any red tokenMakes each matching element the owner of an independent state with an initial value.Reference →
Event line → state line → dependent lines, 120ms apart, then a 500ms fade. With reduced motion, all lines mark at once without fading.
01 · Color

Warm neutrals, one signal

Paper--color-paperPage background
Paper 2--color-paper-2Code, notes, inputs
Line--color-lineHairlines, dividers
Mute--color-muteMetadata, punctuation
Ink 2--color-ink-2Secondary text, values
Ink--color-inkText, primary buttons
Vermilion--color-rxReactive syntax and live values only
Trace--color-traceReacting line background
Demo on--color-demo-onComponent color inside examples
Dark mode · proposed, not shippedSurfaces oklch(0.2 0.008 80) and oklch(0.24 0.008 80). Ink oklch(0.93 0.005 85). Vermilion lifts to oklch(0.72 0.17 40) to hold 4.5:1.
RulesVermilion is never the only cue: reactive tokens also carry a dotted underline, chips are outlined, status uses text labels. Errors use ink, a border and a “!” mark, so they never read as reactive.
02 · Typography

Instrument Sans and Red Hat Mono

A compact grotesque with tight display tracking for headlines, and a mono with real weights so selectors and reactive tokens can be bolder than values without changing color. Mono also carries all metadata: kickers, labels, file names, statuses.

Display · 600 · −0.05emCSS that reacts.
H1 · 44/1 · −0.035emGetting started
H2 · 26 · −0.02emTruthy and falsy values
Lede · 19/1.6when() picks one of two values based on a reactive value.
Body · 17/1.7The browser sees a normal value change, so transitions work the way they always do.
Code · Mono 14–15/1.72background: when(--on, #f2542d, #d9d5cf);
Meta · Mono 12.502 · What it makes possible
03 · Code highlighting

Weight for structure, color for reaction

Selector.switch::afterInk, 600
PropertybackgroundInk, 400
Custom property--onInk, 500. Native, so not colored
Value / native fncalc(200ms)Ink 2
Punctuation{ } ( ) ; :Mute
Comment/* note */Mute, italic
Reactive extensionstate() when() onVermilion, 600, dotted underline
Inactive branch#d9d5cf30% opacity while the other branch applies
04 · Space, grid, shape

A 4px base and hairlines

Spacing scale
4icon gaps
8tight groups
12block gaps
16card padding
24column gaps
32group spacing
48after headings
72between docs sections
112marketing sections
Grid
  • Marketing: 12 columns, 1280px max, gutter clamp(16px, 4vw, 40px).
  • Docs: nav 264px · article max 960px · TOC 220px. TOC folds into the article below 1300px, nav into a menu below 900px.
  • Layouts wrap with flex-basis and container queries instead of breakpoints wherever possible.
Borders and radii
2px · tag
3px · block
1px ink · emphasis
dashed · prototype
No shadows on content. One soft shadow is allowed for overlays (search dialog). Dashed borders mark anything prototype-only or not yet built.
05 · Components and states

Components

Every component, with all its states and editable props, is in Storybook: npm run storybook.

Buttons · default / hover / focus / disabled
Min height 40px desktop, 44px touch. Focus ring 2px ink, 2px offset, on every interactive element.
Status labels and live chips
stableexpnewrequires runtimeexperimental
falsetrueresting · just changed
Statuses are text, never color alone. Chips are the only filled vermilion on the site, and only for ~500ms.
Navigation item · default / hover / current
Events & ActionsDynamic SelectorsConditionsstate()
API entries are set in mono and vermilion because they are reactive syntax.
Callouts
Note

Tinted surface, hairline border.

Caution

Paper surface, ink border.

! Warning

Errors name the declaration that failed and what happens next.

06 · Motion

Motion only answers input

Nothing moves on its own, except examples that demonstrate periodic motion such as wave(). Every other animation on the site is caused by something the reader did, which is the product's point.

Feedback120msHover and press changes on controls.
State change200ms · (.2,0,0,1)Switch knobs, branch fades, chip fills. Matches the example code.
Trace step120ms apartEvent → state → dependents, lit in that order.
Trace fade500msLines return to rest. Instant on, slow off.
Reduced motion0msAll transitions off. The trace marks all lines at once and clears without fading.