Input Lab

Seventy-six field recipes — fill, rim, depth, focus, disclosure, label, placeholder and density — rendered on the real saved-query form, light and dark side by side, next to the production buttons they have to live with.

Recipe B2 shipped on 2026-08-23and now lives in .field-paint: the rim drops to border-default so the fill step separates the field. B4 is the before-picture — a loud neutral rim around a fill that did no work, so a closed dropdown read as an empty outline. The raised end-cap (G6) shipped alongside it and was pulled back the same day for reading as a split button; the disclosure is a bare glyph. Heights were deliberately left alone — the change is paint only. The rest of the matrix stays as the argument, and as the bench for whatever the next field question turns out to be.

Each specimen is pinned to its theme with a theme scope, so both render at once regardless of the app-wide display mode, and each recipe is a bag of semantic-token references — nothing on this page hardcodes a colour, so a winner can graduate straight into global.css. Selection controls are the one documented exception to the shipped recipe: they keep border-line-interactive, because the quiet rim buys its legibility from a fill step and text that a 20px box does not have. The reasoning and the measurements are inglobal.css.

State · every specimen
Show family

Tuner

Build a recipe

Eight axes, resolved in a fixed order (size first, so a later axis can override its geometry). The preview is the full form in both themes; the readout tells you when the combination you just built is one of the named recipes below.

FillThe surface the value sits on.

BorderThe rim, and whether there is one.

DepthRecessed, flat, or standing off the card.

FocusWhat changes when the field takes keyboard focus.

DisclosureHow a select announces that it opens.

LabelWhere the label lives and how loud it is.

PlaceholderHow empty reads.

SizeHeight, radius, and type size together.

Light
Query name
Criterion
Value
Find a route
Bell time
Use a 12-hour time, e.g. 7:09 AM.
Notes for dispatch
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Find a route
Bell time
Use a 12-hour time, e.g. 7:09 AM.
Notes for dispatch
Would match 22 of 22 routes right now
Matches B4 · Flat · interactive rim — SHIPPED

Recessed wells

If the button stands out, should the field press in?

A1

Soft well · canvas

fill:canvasborder:defaultdepth:well-soft

The lead candidate. Canvas fill, quiet default rim, and the soft inner shadow the top-bar search already uses — the field reads as a slot cut into the card while the button beside it stands proud.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
A2

Soft well · no rim

fill:canvasborder:nonedepth:well-soft

The same recess with the rim removed. Proves how much of the silhouette the shadow alone can carry — clean on dark, nearly invisible on light.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
A3

Deep well · canvas

fill:canvasborder:defaultdepth:well

Full recess. Unmistakably editable, and heavy enough that a form of eight fields starts to look pitted.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
A4

Deep well · sunken

fill:sunkenborder:subtledepth:well

The deepest fill under the deepest shadow. The strongest "type here" signal available; check the light panel before believing it.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
A5

Well gradient · soft

fill:well-gradborder:defaultdepth:well-soft

Fill and shadow agree: a top-dark gradient under a soft inner shadow. The literal inverse of the button face, and the most physically coherent option on the page.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
A6

Well gradient · rimless

fill:well-gradborder:nonedepth:well-soft

The recess gradient with no outline at all. Softest of the wells — a good default if the form is long.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
A7

Bottom lip only

fill:canvasborder:defaultdepth:lip

A single inset line under the top edge. The lightest recess that still survives the light theme, where deeper wells turn to mud.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
A8

Inset frame · sunken

fill:sunkenborder:defaultdepth:frame

An even inner shadow all the way round — glass set into a bezel. Too much for a form; right for one hero field (a command bar, a big search).

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
A9

Soft well · interactive rim

fill:canvasborder:interactivedepth:well-soft

The shipped rim over a soft well. Shows exactly how much the loud neutral-600 rim fights the recess it now sits on.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
A10

Well + light-catch

fill:canvasborder:defaultdepth:well-soft

A soft well with a machined highlight on the top edge. The extra hairline is what stops a dark well from looking like a printing error.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now

Flat + bordered

Today's approach. Which rim token is actually right?

B1

Flat · subtle rim

fill:canvasborder:subtledepth:flat

The quietest bordered field. Eight of these stacked read as a list, not as eight objects.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
B2

Flat · default rim — SHIPPED

fill:canvasborder:defaultdepth:flat

What ships as of 2026-08-23, live in `.field-paint`. The rim every card and divider already uses, so fields became part of the page rather than things sitting on it, and the FILL step does the separating. Paint only — heights were deliberately left alone, so no screen shifted density. Two documented exceptions: selection controls keep the louder rim, and the disclosure stayed a bare glyph (see G6).

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
B3

Flat · strong rim

fill:canvasborder:strongdepth:flat

One step up from default. The most rim you can spend before the field starts to outrank its own value.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
B4

Flat · interactive rim — REPLACED 2026-08-23

fill:canvasborder:interactivedepth:flat

The before-picture. Canvas fill, neutral-600 rim, no depth: the rim was the loudest thing in the panel while the fill did nothing, so a closed control read as an empty outline floating on the card. Superseded by B11.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
B5

Flat · sunken fill

fill:sunkenborder:defaultdepth:flat

Drop the fill a step instead of raising the rim. Same separation, far less line noise.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
B6

Flat · subtle fill

fill:subtleborder:defaultdepth:flat

The gentlest step down from the card. On light this is the classic off-white field.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
B7

Flat · surface fill

fill:surfaceborder:strongdepth:flat

Field and card share a fill; only the rim separates them. Correct inside an already-dark panel, ambiguous everywhere else.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
B8

Flat · elevated fill

fill:elevatedborder:defaultdepth:flat

The field sits ABOVE the card. Reads as a control to press, not a slot to fill — useful for selects, wrong for text.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
B9

Flat · muted fill

fill:mutedborder:nonedepth:flat

The neutral chip fill. Note it flips direction between themes — a lift on dark, a recess on light — which is either a feature or a bug depending on the screen.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
B10

Flat · brand-tinted rim

fill:canvasborder:brand-tintdepth:flat

The default rim pulled a quarter toward brand. Warms a cold form without spending the focus colour.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now

Fill only, no rim

Can the fill carry the field without any outline?

C1

Alpha wash

fill:alphaborder:nonedepth:flat

A translucent lift instead of a fixed step, so the same recipe works on a card, in a popover, and over a map. The most portable field on the page.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
C2

Alpha wash + lip

fill:alphaborder:nonedepth:lip

The portable wash with one inset line to stop it reading as a hover state that got stuck.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
C3

Sunken, rimless

fill:sunkenborder:nonedepth:flat

Pure depth by fill. Beautiful on dark, and the single riskiest option on light, where sunken is a mid grey.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
C4

Canvas, rimless

fill:canvasborder:nonedepth:flat

Only works when the field sits on surface or higher. Inside a canvas-coloured panel it disappears completely — worth seeing.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
C5

Muted, rimless, soft well

fill:mutedborder:nonedepth:well-soft

Fill plus recess with no outline anywhere. The quietest field here that still reads as a field.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
C6

Elevated, rimless, top-catch

fill:elevatedborder:nonedepth:top-catch

A lifted fill with a highlight along the top edge and no rim. Reads as an object, not a hole.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now

Raised / chip fields

What if the field simply IS the button paint?

D1

Button paint · exact

fill:raised-gradborder:defaultdepth:raised

The production Secondary button, wholesale: its gradient, its rim, its shadow. Maximum cohesion with the button row — and now the select and the Reset button are indistinguishable, which is the real cost.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
D2

Button paint · interactive rim

fill:raised-gradborder:interactivedepth:raised

The chip with the operable rim. Keeps the field distinguishable from the buttons beside it while sharing the surface.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
D3

Button paint · rimless

fill:raised-gradborder:nonedepth:raised

Gradient and shadow only. The softest chip; good for a read-mostly filter bar.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
D4

Elevated + drop-sm

fill:elevatedborder:defaultdepth:drop-sm

A flat lifted fill with a small cast shadow. Floats over busy backgrounds — the map overlays are the case for this.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
D5

Surface + drop-md

fill:surfaceborder:defaultdepth:drop-md

A full card shadow on a field. Almost always too much; here so the ceiling is visible.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
D6

Chip select, well text

fill:raised-gradborder:defaultdepth:raisedchev:capped

Deliberately inconsistent: the button paint on a select, so only the OPENABLE controls look raised and typed fields stay recessed. Compare the two rows below carefully.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now

Underline + minimal

How little box can a field get away with?

E1

Underline · transparent

fill:clearborder:underlinedepth:flat

Bottom rule only, no fill. The cheapest way to fit an editable value into running text or a tight table.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
E2

Underline · default rule

fill:clearborder:underlinedepth:flat

The same, dropped to the quiet rim so a column of them does not read as ruled paper.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
E3

Filled underline

fill:mutedborder:underlinedepth:flat

The Material pattern: a muted fill with a rule under it, square on top, rounded at the top corners.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
E4

Underline · brand focus

fill:clearborder:underlinedepth:flatfocus:border-only

A near-invisible rule at rest that becomes a 2px brand rule on focus. Highest signal-to-ink ratio here.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
E5

Ghost field

fill:clearborder:nonedepth:flat

No rim, no fill, no shadow — the value alone until you hover it. For inline editing inside a table cell, where a visible box per cell would be unreadable.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
E6

Underline · sunken

fill:sunkenborder:underlinedepth:lip

A recessed strip with a rule. Half underline, half well — reads as a slot without drawing a box.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now

Outlined

When is a loud rim the right answer?

F1

Outline · 2px strong

fill:clearborder:heavydepth:flat

A deliberate heavyweight outline on a transparent fill. Reads at a distance — the tablet and in-vehicle case — and is far too loud in a dense panel.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
F2

Outline · 2px interactive

fill:canvasborder:heavydepth:flat

The operable rim at full weight over a canvas fill. Where a field must survive a photo or map behind it.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
F3

Outline · brand tint

fill:canvasborder:heavydepth:flat

A warm heavy rim. Good for a single primary field (the query name) when everything else stays quiet.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
F4

Double rim

fill:canvasborder:strongdepth:flat

An outer rim plus an inner hairline in the fill colour. Machined, precise, and only affordable once per screen.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
F5

Outline · full brand

fill:canvasborder:defaultdepth:flat

The brand rim at rest, not just on focus. Shows why a resting brand outline destroys the focus signal — every field looks focused.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
F6

Outline + soft well

fill:canvasborder:heavydepth:well-soft

A heavy rim over a recess. The two treatments fight; included because the combination looks reasonable in a spec and wrong on screen.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now

Disclosure

How should a select say "I open"?

G1

Bare chevron · subtle — SHIPPED

fill:canvasborder:defaultdepth:well-softchev:subtle

The shipped disclosure: a bare glyph inside the field at fg-subtle. Shown here on the well base so only the disclosure varies across this family. The open question it leaves is real — the glyph is quieter than the placeholder beside it — but every louder answer below costs more than it returns.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
G2

Bare chevron · muted

fill:canvasborder:defaultdepth:well-softchev:muted

One step brighter, matching the value text. The smallest possible fix to the screenshot.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
G3

Bare chevron · full

fill:canvasborder:defaultdepth:well-softchev:strong

The glyph at full foreground. Strongest affordance, and a lot of contrast to spend on a marker.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
G4

Bare chevron · brand

fill:canvasborder:defaultdepth:well-softchev:brand

Brand disclosure. Instantly openable, and it competes with the real brand action ("Save query") on the same panel.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
G5

Divided cap

fill:canvasborder:defaultdepth:well-softchev:capped

A full-height divider before the glyph — the native select silhouette. The end of the field becomes unmistakably a button.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
G6

Divided cap · raised — TRIED AND REJECTED

fill:canvasborder:defaultdepth:well-softchev:capped-raised

Shipped 2026-08-23 and pulled back the same day. On paper it is the clearest statement of "typed value here, trigger there"; in the product it reads as a SPLIT BUTTON, so the eye hunts for two separate actions on a control that has one target. Giving the arrow its own rim and its own raised surface promotes a marker into a button. Kept as the record of why the glyph stays bare.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
G7

Boxed glyph

fill:canvasborder:defaultdepth:well-softchev:boxed

A small centred tile behind the glyph instead of a full-height cap. Marks the trigger while leaving the silhouette clean.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now

Label + placeholder

Where does the label go, and how loud is empty?

H1

Label above · sentence

fill:canvasborder:defaultdepth:well-softlabel:above

Body-small, medium weight, sentence case. Scans fastest in a one-column form.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
H2

Label above · eyebrow

fill:canvasborder:defaultdepth:well-softlabel:eyebrow

The house eyebrow role: tiny bold caps, wide tracking. Compresses the label into chrome so the VALUE is the loudest thing in the row.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
H3

Label leading

fill:canvasborder:defaultdepth:well-softlabel:leading

A fixed left column, so every control starts on the same x — the alignment DESIGN.md Rule 6 asks for. Costs horizontal room, which a two-up criteria row cannot always spare.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
H4

Label inside

fill:canvasborder:defaultdepth:well-softlabel:inside

Label tucked into the top of the field. Halves the vertical rhythm of a dense panel; needs a 56px field and cannot coexist with a placeholder.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
H5

Placeholder · subtle

fill:canvasborder:defaultdepth:well-softplaceholder:subtle

Placeholder one step brighter than the token. Easier to read — and an empty field now looks full, which is the trade.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
H6

Placeholder · faint

fill:canvasborder:defaultdepth:well-softplaceholder:disabled

The disabled foreground as a placeholder. Maximum "no value yet", real legibility risk on light.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
H7

Placeholder · surface-mixed

fill:canvasborder:defaultdepth:well-softplaceholder:mixed

Muted mixed into the fill, so the placeholder tracks whatever surface the field lands on instead of holding a fixed step.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now

Density + radius

Which height and corner pair with our buttons?

I1

32 · radius-sm

size:smfill:canvasborder:defaultdepth:well-soft

Grid density, matching the sm Button so a filter row lands on one 32px baseline.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
I2

36 · radius-sm

size:mdfill:canvasborder:defaultdepth:well-soft

The in-between step. Comfortable in a panel without eating a form's vertical budget.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
I3

40 · radius-sm

size:lgfill:canvasborder:defaultdepth:well-soft

Shipped, and the height of the default Button. The safe default for a real form.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
I4

40 · radius-md

size:lg-mdfill:canvasborder:defaultdepth:well-soft

Same height, one radius step softer. 4px corners read friendlier and slightly less technical than the house 2px.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
I5

32 · radius-md

size:sm-mdfill:canvasborder:defaultdepth:well-soft

Dense but rounded — where a compact field must not look sharper than the chips beside it.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
I6

48 · radius-md

size:xlfill:canvasborder:defaultdepth:well-soft

Touch scale, for the tablet and in-vehicle surfaces: body-size text and generous padding.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now

Focus

What should keyboard focus actually do?

J1

Halo · focus-subtle — today's ring

fill:canvasborder:defaultdepth:well-softfocus:halo

The focus ring that ships today: the focus border plus a 2px halo in the dedicated token. Quiet — on dark, amber-950 against neutral-950 is very nearly invisible, which is the bug worth confirming here.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
J2

Halo · brand 30%

fill:canvasborder:defaultdepth:well-softfocus:halo-brand

The same ring mixed from brand. One obvious colour in both themes; an amber ring on light is the price.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
J3

Border only

fill:canvasborder:defaultdepth:well-softfocus:border-only

Focus recolours the rim and nothing else. Zero layout noise; fails when the resting rim is already strong.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
J4

Brand glow

fill:canvasborder:defaultdepth:well-softfocus:glow

The brand glow shadow. Unmissable on dark; on light it reads as a smudge — the reason both panels exist.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
J5

Offset ring

fill:canvasborder:defaultdepth:well-softfocus:offset

A canvas gap then a solid ring — the exact focus-visible treatment the production Button ships. Pick this if fields and buttons must focus identically.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
J6

Inset brand line

fill:canvasborder:defaultdepth:well-softfocus:inset-brand

Focus paints a brand hairline INSIDE the rim, so the field never grows by a pixel. The only option that cannot disturb a tight grid.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now

Status + non-editable

How do invalid, disabled, and read-only read?

K1

Invalid · rim only

fill:canvasborder:defaultdepth:well-soft

Danger rim, fill untouched. The restrained version — pairs with a message below the field.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
K2

Invalid · rim + wash

fill:canvasborder:defaultdepth:well-soft

Danger rim over the danger-subtle fill. Impossible to miss in a long form; heavy if three fields fail at once.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
K3

Warning

fill:canvasborder:defaultdepth:well-soft

The soft-fail rim — "this will match nothing", not "this is wrong". Distinct from danger at a glance.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
K4

Valid / confirmed

fill:canvasborder:defaultdepth:well-soft

A success rim after a check passes. Use sparingly — a form of green fields is as noisy as a form of red ones.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
K5

Disabled

fill:canvasborder:defaultdepth:well-soft

The whole control at the disabled opacity, hover suppressed. Confirm it still reads as a field and not as a rendering failure.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now
K6

Read-only

fill:surfaceborder:subtledepth:flat

Not editable, but not broken: fill drops to the card, the rim goes subtle, the value stays at full contrast. The distinction from disabled is the point.

Light
Query name
Criterion
Value
Would match 22 of 22 routes right now
Dark
Query name
Criterion
Value
Would match 22 of 22 routes right now