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.

/
Schedule3 fields
$ substrate run --watch
12 records reconciled
Button finishes

flat is the default and is class-free; tinted and inset are opt-in per instance.

T1 edge-light / T6 rim

Raised devices. A rim is a border plus one quiet ring, never a radius change.

Edge-lit
Rimmed
T3 well / T4 socket

Recessed devices. A well is cut, not boxed — neither carries a border.

Well
Socket
T7 pressed

State-qualified only. A pressed control occupies a well: pressing and recession are one metaphor.

T5 seam

One 1px line between fused siblings, replacing two borders touching.

Fused instrument

Three segments render one housing and two seams, with one tinted end-cap.

Focused and invalid

The housing owns the ring and the error border; the segment adds an interior cue only.

Tile — the family's own device

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.

Pipeline 04
Reconciled 2 minutes ago
12 records · 0 conflicts
Illegal combinations

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.

finishdefaultdestructiveoutlinesecondaryghostlink
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.

Dark plateLight plate

1T1 · Edge light

shapes light, not fill

A 1px machined rim along the top of a raised surface.

Raised
Raised
--edge-light · from --foreground5% light · 7% dark

2T2 · Bevel

shapes light, not fill

The pressed-in shade at the top edge of anything recessed.

Recessed
Recessed
--bevel-shadeblur ≤ 3px

3T3 · Well

ΔL — / —

Well fill plus bevel — and no border at all, in either polarity.

Cut, not boxed
Cut, not boxed
--well · muted − 0.012 La well is cut, not boxed

4T4 · Socket, with T9 · Return light

ΔL — / —

The same operation, deeper — plus the light coming back off the far wall.

Deeper cut · return light
Deeper cut · return light
--socket · 1.5× bevel blur · --recess-return-strongmuted − 0.03 L

5T5 · Seam

shapes light, not fill

One line between fused siblings, in place of two borders touching.

cn-seam-x · cn-seam-y · from --border1px · drawn once

6T6 · Rim

shapes light, not fill

A structural border plus one quiet edge-light ring inside it.

Rimmed
Rimmed
border-border + ring var(--edge-light)never a radius change

7T7 · Pressed

ΔL — / —

A pressed control does not darken — it occupies a well.

cn-pressed:is([aria-pressed=true], [data-state=on])press-in 90ms · translate-only

8T8 · Tint ribbon

span — / —

The register's only gradient: same hue, L-only, two tints of one colour.

--tint-hi + --tint-lo, read liveribbon ΔL ≤ 0.07

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-lightA 1px machined top rim on raised surfaces. Raised only — never on the same element as a bevel.
T2 cn-bevelThe pressed-in shade at a recessed surface's top edge. Blur never exceeds 3px.
T3 cn-wellWell fill plus bevel, and no border: a well is cut, not boxed.
T4 cn-socketThe deeper cut of the same operation — socket fill at 1.5x the bevel blur, still borderless.
T5 cn-seam-x / cn-seam-yOne 1px line drawn once between fused siblings, replacing two borders touching.
T6 cn-rimA structural border plus one quiet edge-light ring. Never a radius change, and never fully round under substrate.
T7 cn-pressedState-qualified paint on aria-pressed or data-state=on: well fill, bevel, transparent border. A pressed control occupies a well.
T8 tint ribbonThe 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.

FamilyDevicePaintsLands onAgainst the core row
Caliberjewel-pivotcorner-dotcard · cardcomposes
Instrumentcorner-bracketcornercard · cardcomposes
Instrumentfocus-ringringcommand-palette · command-palettesupersedes
Instrumentrangefinder-ticktickstatus-bar · status-barcomposes
Intaglioplate-markinset-linecard · cardsupersedes

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

Aspectcompactcomfortablespacious
Press depth0.5px1px1px
Addon padding8 / 4px12 / 6px (frozen)14 / 8px
Fused housing28px36px44px
Hairline devices1px1px1px

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.

ColorwayT1 edge-lightT2 bevelT3/T4 fillsT5 seamT6 rimT7 pressedT8 ribbonTravel
default5% / 7%2pxonborderdoublewellon0.5 / 1px
substrate4% / 6%2pxonborderdoublewellon, quiet0.5 / 1px
blueprintfills onlydrafting rulesinglefill + rulerule1px
editorial5% / 7%1pxonborderdoublewellrest and press only0.5 / 1px
terminalfills onlysolidinversionoffoff
craft6% / 8%1pxonborderdoublewellon0.5 / 1px
ledger6% / 7%1pxonborderdoublewellon, quiet0.5 / 1px
cyanotypefills onlydrafting rulesinglefill + rulerule1px
bluelinefills onlydrafting rulesinglefill + rulerule1px
articlefills onlydrafting rulesinglefill + ruleruleoff
preprintfills onlydrafting rulesinglefill + ruleruleoff
gauge6% / 8%1pxonborderdoublewellon0.5 / 1px
caliber5% / 7%1pxonborderdoublewellrest and press only0.5 / 1px
intaglio5% / 7%2pxonborderdoublewellon0.5 / 1px

Reduced motion and forced colours

  • Under prefers-reduced-motion the 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.