Craft & Texture
The product-surface craft layer: buttons that feel machined rather than painted, a special gradient tier that produces richness from a single hue, eight quiet texture devices, surfaces that sit into the page instead of on it, and inputs that fuse into one instrument. Everything below is token-derived and reproduces today’s exact baseline when the craft tokens are zeroed.
flat is the default and is class-free; tinted and inset are opt-in per instance.
Raised devices. A rim is a border plus one quiet ring, never a radius change.
Recessed devices. A well is cut, not boxed — neither carries a border.
State-qualified only. A pressed control occupies a well: pressing and recession are one metaphor.
One 1px line between fused siblings, replacing two borders touching.
Three segments render one housing and two seams, with one tinted end-cap.
The housing owns the ring and the error border; the segment adds an interior cue only.
The core rim lights a tile from above. A family may supersede it or annotate it: intaglio strikes the plate into the page, caliber sets jewels at the pivots, gauge sights the corners. Switch colorway to see the same element change vocabulary.
tinted + destructive/outline/ghost/link and inset + default/destructive/link are documented, never rendered as guidance.
The five laws
- Token derivation only
- Every craft colour is an L-or-alpha move on an existing token, or a color-mix between two of them. Chroma and hue are always inherited, so a theme patch restyles the whole craft system for free and no variant can drift into a new palette.
- Two registers, one grammar
- The marketing vocabulary and this product register share their physics and not their volume. Product edge-lights cap at 6% light and 8% dark, gradients are same-hue L-only with a 0.07 ribbon ceiling, and washes, patterns, and grain do not exist in product chrome at all.
- Pixel-frozen comfortable baseline
- Nothing here moves a resting metric at the comfortable tier. A press is a state change, not a metric change; finish classes are paint only; the fused housings reuse the existing border boxes.
- One focal point
- At most one tinted control per surface region. Wells never nest — a socket inside a well is the maximum. A composite control has exactly one housing border. Texture is hierarchy support, never noise.
- Motion budget
- Press-in runs at 90ms and release at the theme's fast duration, both inside the 200ms app-UI cap. Travel is translate-only: 0.5px for controls at or below 28px, 1px above. Scale reads playful; product is mechanical.
Finish legality
finish is a third CVA axis beside variant and size, defaulting to flat, which is class-free — the resting paint of a default button is byte-identical to before the axis existed. Illegal pairs still render exactly what you asked for and warn once in development; they are never silently rewritten. Emphasis belongs to this axis, never to a second font weight.
| finish | default | destructive | outline | secondary | ghost | link |
|---|---|---|---|---|---|---|
| flat | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| tinted | ✓ | ✗ | ✗ | ✓ | ✗ | ✗ |
| inset | ✗ | ✗ | ✓ | ✓ | ✓ | ✗ |
The eight devices
At most one texture device per element, plus its structural border or ring. Devices compose across levels — a well containing a rimmed tile — never stacked on one element. Removing every craft token yields the exact reUI baseline, which is also the rollback story.
1T1 · Edge light
shapes light, not fillA 1px machined rim along the top of a raised surface.
2T2 · Bevel
shapes light, not fillThe pressed-in shade at the top edge of anything recessed.
3T3 · Well
ΔL — / —Well fill plus bevel — and no border at all, in either polarity.
4T4 · Socket, with T9 · Return light
ΔL — / —The same operation, deeper — plus the light coming back off the far wall.
5T5 · Seam
shapes light, not fillOne line between fused siblings, in place of two borders touching.
6T6 · Rim
shapes light, not fillA structural border plus one quiet edge-light ring inside it.
7T7 · Pressed
ΔL — / —A pressed control does not darken — it occupies a well.
8T8 · Tint ribbon
span — / —The register's only gradient: same hue, L-only, two tints of one colour.
Nothing above is drawn. Every specimen is the real cn-* class on a real element, rendered twice — once inside a dark polarity island and once inside a light one — and every number is measured on load, from the computed fill against the surface the device is applied to. The light column repaints only because law 01 holds: the craft tokens are all derived from --foreground, --muted and --background, so re-declaring the base tokens on a subtree is enough. Three devices cut fill and carry a delta, three shape light, one is structural, and the ribbon reports a span rather than a displacement because its two stops live inside one control.
The two polarities do not recede the same way, and the numbers say so. In light the fill is cut: the well and the socket sit below their card. In dark they sit slightly above it — the dark theme mixes both from --muted, which is lighter than --card, and lets --bevel-shade carry the recession instead at background − 0.1 L and 80% alpha. That is a veil, not a cut, and it is deliberate: a shade-led recess survives on a near-black ground where a darker fill would have nowhere left to go. It is also why the geometry, not the direction of travel, is the thing the law holds invariant.
| T1 cn-edge-light | A 1px machined top rim on raised surfaces. Raised only — never on the same element as a bevel. |
|---|---|
| T2 cn-bevel | The pressed-in shade at a recessed surface's top edge. Blur never exceeds 3px. |
| T3 cn-well | Well fill plus bevel, and no border: a well is cut, not boxed. |
| T4 cn-socket | The deeper cut of the same operation — socket fill at 1.5x the bevel blur, still borderless. |
| T5 cn-seam-x / cn-seam-y | One 1px line drawn once between fused siblings, replacing two borders touching. |
| T6 cn-rim | A structural border plus one quiet edge-light ring. Never a radius change, and never fully round under substrate. |
| T7 cn-pressed | State-qualified paint on aria-pressed or data-state=on: well fill, bevel, transparent border. A pressed control occupies a well. |
| T8 tint ribbon | The register's only gradient, carried by cn-button-finish-tinted. Buttons only. |
What a family adds
The eight above are the core register: every family inherits them. A family may also contribute devices of its own, declared as paint operations over the same tokens and compiled into family-scoped CSS — never hand-written. Two tiers decide what happens where a contribution meets a core row. A mark — a jewel, a bracket, a graduation — composes: the machining underneath is untouched. A device that paints a machining layer supersedes instead, because a tile cannot be lit from above and struck into the page at once. Everything below is read from the family registry, so a row exists only if the stylesheet carries it.
| Family | Device | Paints | Lands on | Against the core row |
|---|---|---|---|---|
| Caliber | jewel-pivot | corner-dot | card · card | composes |
| Instrument | corner-bracket | corner | card · card | composes |
| Instrument | focus-ring | ring | command-palette · command-palette | supersedes |
| Instrument | rangefinder-tick | tick | status-bar · status-bar | composes |
| Intaglio | plate-mark | inset-line | card · card | supersedes |
One registered mark is still unexpressed: the instrument family’s reticle is a centre crosshair, which is neither a corner, an edge, nor a ring, and the paint algebra will grow the operation when a family actually places it rather than before.
The fused-control protocol
InputGroup, ButtonGroup, and SegmentedInput share one protocol. Each stamps its visible children with a position, and the housing owns every piece of chrome: one border, one radius, one fill, one shadow. A three-segment composite therefore draws one housing and two seams rather than six border edges.
- The ring moves to the housing, so the instrument focuses as a unit; the active segment adds an interior tint as a supplementary cue, never a replacement for the ring.
- An invalid segment turns the whole housing destructive and tints its own interior, so multi-segment errors stay locatable. Seams beside it stay neutral: an error is a fill, because lines are structure.
- Hidden children never consume a position. Stamping counts only what renders, which removes the class of bug that order-based corner stripping needed a special case for.
- A trailing action may take the tinted finish — the one juice allowance per composite, producing a search-and-go instrument with a lit end-cap.
Density
| Aspect | compact | comfortable | spacious |
|---|---|---|---|
| Press depth | 0.5px | 1px | 1px |
| Addon padding | 8 / 4px | 12 / 6px (frozen) | 14 / 8px |
| Fused housing | 28px | 36px | 44px |
| Hairline devices | 1px | 1px | 1px |
Per-theme behaviour
Every row below is derived from the theme parameters themselves — the same authorities the token build compiles — so a colorway appears here by existing and no cell can drift from what ships. Blueprint draws instead of lighting: its special tier is a hairline double rule rather than a ribbon. Terminal is flat and instant — state changes are fill inversions with no travel. Editorial keeps the ribbon at rest and on press but paints its hover flat, because its accent sits close enough to the contrast floor that a lightened hover fill would cost the label its legibility. The machined families — craft, ledger, gauge, caliber, intaglio — all cut wells rather than tint them; they differ in bevel crispness, edge-light volume, and ribbon richness. Contrast outranks craft everywhere.
| Colorway | T1 edge-light | T2 bevel | T3/T4 fills | T5 seam | T6 rim | T7 pressed | T8 ribbon | Travel |
|---|---|---|---|---|---|---|---|---|
| default | 5% / 7% | 2px | on | border | double | well | on | 0.5 / 1px |
| substrate | 4% / 6% | 2px | on | border | double | well | on, quiet | 0.5 / 1px |
| blueprint | — | — | fills only | drafting rule | single | fill + rule | rule | 1px |
| editorial | 5% / 7% | 1px | on | border | double | well | rest and press only | 0.5 / 1px |
| terminal | — | — | fills only | solid | — | inversion | off | off |
| craft | 6% / 8% | 1px | on | border | double | well | on | 0.5 / 1px |
| ledger | 6% / 7% | 1px | on | border | double | well | on, quiet | 0.5 / 1px |
| cyanotype | — | — | fills only | drafting rule | single | fill + rule | rule | 1px |
| blueline | — | — | fills only | drafting rule | single | fill + rule | rule | 1px |
| article | — | — | fills only | drafting rule | single | fill + rule | rule | off |
| preprint | — | — | fills only | drafting rule | single | fill + rule | rule | off |
| gauge | 6% / 8% | 1px | on | border | double | well | on | 0.5 / 1px |
| caliber | 5% / 7% | 1px | on | border | double | well | rest and press only | 0.5 / 1px |
| intaglio | 5% / 7% | 2px | on | border | double | well | on | 0.5 / 1px |
Reduced motion and forced colours
- Under
prefers-reduced-motionthe press transform is removed outright, not merely shortened. The fill and shadow response remain, so the state is still visible without motion. - Forced-colours mode strips every shadow natively. Borders, rings, and seams come back as real edges, so the structural layer carries the full meaning — craft is always additive to a complete flat design.
- Browsers without relative colour syntax render the tinted finish as a flat fill with identical geometry. There is no layout difference and no JavaScript detection anywhere.
Coming to the playground
Finish and device knobs arrive in the theme playground once the playground wave lands; the craft ceilings already bound its editors, so a user-authored theme cannot exceed the restraint law either.