Identity

What the j3w1 theme is, where it came from, and the five rules that keep a port recognisable.

True-black canvas (#000000), near-black panels (#100c0c) and chrome (#090707), with dark-red raised layers, rose interface text (#e99499), near-white reading text (#f4eeee), dark-red selections (#531310), a bright red focus ring (#e53935), 1px square borders, zero radii, one monospace family for chrome, reading and code. Red marks interaction: focus, selection, active borders, primary actions. It is not a decoration and it is not applied to everything. Darkness is the canvas; readable content is the priority.

Five rules keep an implementation recognisable:

  1. Preserve the warm-black / rose / red identity. Never substitute a charcoal-and-blue dark theme because the target ships one.
  2. Use the role assigned to a token, never the token whose colour happens to look closest.
  3. Keep content, selection, keyboard focus, diagnostics and changed text distinguishable from one another. Selection is a fill; focus is a ring.
  4. Nothing is rounded, blurred, glowing or gradient-filled. Elevation is a 1px border and, for modals, a backdrop.
  5. Preserve the host application’s behaviour, keyboard handling and accessibility settings. Geometry and typography limits of a host are documented deviations, not reasons to rewrite it.

Where it came from

The palette began as a Manjaro i3 workstation preserved in j3w1/1w3j: a pywal ramp pulled from a red wallpaper, then frozen and hand-tuned slot by slot in config/Xresources while watching what ls, vim and the agnoster prompt actually rendered. The i3 configuration supplied the rest of the idiom: 1px pixel borders, 14/−2 gaps, tabbed layouts, a hidden top bar with Chinese status labels, dunst toasts framed in #ae1914, dmenu selections in #630f0d.

The contemporary reference is j3w1/j3w1.github.io, a working web reinterpretation of that workstation. Its stylesheet named the roles this specification adopts (--terminal, --surface-raised, --selection, --focus, --prose, --muted …) and wrote the first contrast contract. Both sources are pinned by revision in references/sources.json; after adoption this repository is the authority and later changes in either source are proposals, not automatic updates.

What “modern” means here

Clear organisation, responsive behaviour, strong keyboard and screen-reader support, precisely specified states, and controls that are pleasant to operate. It does not mean pill buttons, glass panels, gradients, neon glows, a Material-style redesign, or red on every surface. Sixteen concrete misreadings are rendered as labelled non-examples on the site.

The specification page’s generated literal-color previews have the narrow geometry, checkerboard and motion exception recorded in D-014; the component and consumer rules remain as written.

Profiles

  • default — the approved everyday composition. Monochrome red/rose for chrome, text, borders, interaction and actions; three bounded hues (amber, green, blue) for status, diagnostics and diffs (D-001); monochrome syntax.
  • heritage-ansi — the sixteen Xresources slots and the historical assignments, exact, including the ones that fail the contrast floor. For terminals, archives and fidelity; never for new interface text.
  • extended — a proposed overlay that colours syntax, a full sixteen-slot semantic terminal palette and chart series with the same three hues. Not approved; the site labels it.

Naming

Roles are color.<group>.<role> with a closed group list: surface, text, border, interaction, action, status, code, diagnostic, diff, terminal, chart, icon. Primitives are color.primitive.<family>.<step> where the step rises with luminance. A CSS custom property is the path with dots replaced by dashes: color.interaction.focus.ring--color-interaction-focus-ring. Roles alias primitives; primitives carry provenance.

Foundations

Surfaces, text ladder, borders, interaction states, focus, typography, spacing, density, elevation, motion, icons and layout, with the rules that govern each role.

Values live in tokens/; this document says what each role means and where it may be used. Every rule below is normative for the default profile.

Surfaces

surface.desktop and surface.canvas use true black (#000000). Readable content sits on the canvas or default (#100c0c) panels and cards, raised (#160b0b) for sticky headers, menus and popovers, overlay for dialogs and drawers, sunken (#000000) for reading and detail panes, input for form-control fills, chrome and chrome-alt for window frames and bars. Layering is subtle by design; it may not erase the boundary of a control, which is why controls also carry border.control.

Never tint photographs, video, document content or user-defined data colours to put more red on screen.

Text ladder

RoleValueContrast on canvas / default / raisedUse
text.prose#f4eeee18.31 / 16.96 / 15.83long-form reading, on-fill text
text.bright#ffa2a710.98 / 10.17 / 9.49headings and emphasis
text.default#e994999.16 / 8.48 / 7.92interface and body text
text.muted#bd787d6.15 / 5.69 / 5.31secondary text; the darkest colour permitted for chrome text
text.subtle#ad71755.40 / 5.00 / 4.66metadata, comments, line numbers
text.disabled#8a55593.52 / 3.26 / 3.05disabled controls only (exempt under WCAG 1.4.3; at least 3:1 by policy)
text.accent#e539354.97 / 4.60 / 4.30accent text on canvas and default surfaces only
text.accent-strong#f73f355.72 / 5.29 / 4.94accent text safe on every surface

Ordinary text must reach 4.5:1 against its actual background in every state. #a3676b and #7d1310 are never text roles in default, even when a particular darker background improves their ratio; they remain in service as border.control, icon.decorative, status.neutral.fill and border.disabled. Metadata and comments that a person needs to read are not decorative and use text.subtle, not a graphic colour.

The specification page’s generated literal-color previews have the narrow geometry, checkerboard and motion exception recorded in D-014; the component and consumer rules remain as written.

Borders

Every border is 1px (border.width.default); 2px (border.width.emphasis) is reserved for the selected indicator bar, the sticky-header rule and the invalid border. The quote rule is the one wider edge, at twice the emphasis width, because it marks a block rather than bounding a control. border.divider (#2b0e0d) separates rows and sections; border.default (#531310) is decorative and may never be the only visible edge of a control; border.control (#a3676b, 4.71:1) is the boundary of every form control at rest; border.active (#e53935) marks the focused or active control; border.overlay (#e53935) frames every floating layer. Styles: solid by default; dashed only for focus, drop targets and read-only fields; dotted for hints; double for conflicts. Radius is 0 everywhere, including checkboxes, switches, chips, avatars, badges and tooltips.

Interaction states

Every interactive component declares which of these apply and demonstrates every applicable one, including the combinations. Precedence when several apply: disabled > loading > invalid > selected > pressed > hover; focus-visible is always drawn on top and never suppressed by another state.

StateVisualNon-colour channel
defaultrest tokens
hover (@media (hover: hover) only)background → interaction.hover.bg; links use it too with text.link-hover, menu items → interaction.hover.bg-stronglink underline thickens 1px → 2px; cursor
active / pressedbackground → interaction.pressed.bg; border → border.activeborder change; no translation
focus-visiblethe ring (below)the ring itself; never a glow or a colour shift alone
selectedfill interaction.selection.bg with interaction.selection.text; tabs and navigation use a 2px border.selected-indicatoraria-selected / aria-current; a check glyph in lists
selected + focus-visiblethe selection fill and a ring in the fill’s on-fill colour (interaction.focus.ring-container, 7.48:1 on the selection)both visible at once
selected, container inactiveinteraction.selection.inactive-bg with interaction.selection.inactive-text; no ringlightness drop between the two fills
disabledtext.disabled, border.disabled, interaction.disabled.bg; no hover or pressed styling; still focusable when aria-disableddisabled / aria-disabled; cursor: not-allowed; never opacity
invalidborder → status.danger.border at 2px; message in status.danger.text with the glyph; aria-invalid; aria-describedbyborder width 1 → 2px; glyph; message
invalid + focus-visiblethe 2px danger border and the ring in interaction.focus.ring-container at focus.offset-invaliddouble boundary
read-onlytext.default; 1px dotted border.divider bottom; no fill; focusable; selectablereadonly; dotted edge
loadingsize unchanged; a static glyph replaces the leading icon; aria-busyglyph; no animation under reduced motion
busy / indeterminatestatic 45° stripes of action.primary.bg on interaction.pressed.bg; aria-valuetextstripes
checked / mixedfill action.primary.bg, glyph or in action.primary.textglyph
expanded / collapsedSVG chevron rotated 0 / 90° within the motion budgetaria-expanded
current2px border.selected-indicator and text.brightindicator bar
drop-target / draggingdashed interaction.drop-target border; interaction.marquee filldashed pattern

Rules that apply everywhere:

  1. Selection is a fill; focus is a ring. Neither borrows the other’s form. A ring still has to be visible on whatever it sits over: #e53935 measures 2.52:1 on action.primary.bg and 1.13:1 on status.danger.fill, which is why the ring recolours on those fills instead of relying on hue. It measures 3.38:1 on the interaction.selection.bg recessed by D-027, so a selected row keeps the ordinary control ring.
  2. Focus ring (D-006; component mapping clarification D-015). Controls and rows: outline: 1px dashed {color.interaction.focus.ring}; outline-offset: -2px. Focusable containers (panes, windows, dialogs, cards): outline: 2px solid {color.interaction.focus.ring-container}; outline-offset: -3px. On filled surfaces use the component’s explicit ring mapping: primary buttons and checked controls use interaction.focus.ring-container where declared; destructive buttons use their declared on-fill text role. The selection fill is the exception and takes the ordinary ring, on the measurement in rule 1. Keep the control or container geometry independently of the colour mapping. :focus:not(:focus-visible) draws nothing. Forced-colors mode uses Highlight. A host focus indicator is never removed without this replacement.
  3. Never colour-only. Every state and every status carries a second channel: a glyph (✕ ! ✓ i ·), a border width, an underline pattern, or an ARIA state. Charts carry pattern fills.
  4. Hover changes fills and borders, never text colour alone, and only on hover-capable pointers.
  5. Disabled never uses opacity. Opacity leaks the background and breaks contrast accounting.
  6. Contrast floor. Text ≥ 4.5:1 and control boundaries, rings and meaningful graphics ≥ 3:1 against the actual background of the state, measured after compositing translucent colours.
  7. Motion. Durations are 80 / 120 / 150 ms at most, on opacity, transform and background only; under prefers-reduced-motion: reduce every duration is 0.01 ms, nothing slides or shimmers, and no behaviour waits on transitionend.

Actions

Four button tones. primary is the only filled button at rest (action.primary.bg #7d1310 with text.prose, 9.28:1); secondary is an outline (border.control, text text.bright); tertiary is a ghost or icon button (text.default, hover interaction.hover.bg); destructive is an outline in action.destructive.text (#f73f35) that fills with action.destructive.hover-bg (#dc282e) and #f9faf9 text (4.58:1) on hover, and a filled variant for confirm dialogs. Destructive actions also require a confirmation step or an undo affordance; the colour is not the safeguard.

Status, diagnostics and diffs (D-001)

Five statuses: danger (#f73f35 text, #dc282e fill), warning (#c9973f), success (#86a46f), info (#7e9ebb), neutral (#bd787d text, #a3676b fill). Each has text, fill, on-fill, tint and border roles, a mandatory glyph (✕ ! ✓ i ·) and a distinct underline or border pattern (wavy, dashed, solid, dotted, double). The three extension hues are desaturated and warm-shifted so they sit inside the identity, all between 6.5:1 and 7.6:1 on every surface, and are forbidden in surface, text, border, interaction and action. Purple, cyan and magenta do not exist in the theme.

Diagnostics: error = wavy #e53935 underline, #f73f35 text, #e53935 stripe, #2b0e0d line background; warning = wavy amber; info = dotted blue; hint = dotted text.subtle; unused = text.muted with a dotted underline. Diffs: added = #0f1a0e line background, green gutter mark and +, word-level additions as a 2px green underline (no fill, so text contrast is untouched); removed = #2b0e0d background, red gutter mark and , word-level removals underlined and struck through; modified = #1f1a0c background, amber gutter mark and ~; conflicts = a double #f73f35 border. Textual markers and existing status icons are always preserved.

Code and terminal

Editor surfaces use code.bg (#0c0909), code.current-line (#1c0a09), code.line-number (text.subtle, replacing the site’s #7d1310), caret #e99499, selection #420f0c (muted text stays 4.71:1 inside it), search matches #630f0d with the current match inverted (#ffa2a7 on #0c0909), bracket match as a 1px #e53935 border, indent guides #531310, rendered whitespace #7d1310 (decorative). Syntax in default is monochrome: keywords #f73f35, strings #bd787d, comments #ad7175 italic, numbers and constants #d4868b, functions #ffa2a7, variables and operators #e99499, types #b37175, properties and headings #e53935, tags #f73f35, attributes and escapes #d4868b; invalid text takes a wavy underline, deprecated text a line-through. Languages inherit these roles; a language-specific override needs a documented reason.

Terminal roles carry the sixteen slots exactly in every profile. Slots 1, 4, 6, 8, 9, 10, 12, 13, 14 and 15 do not reach 4.5:1 on the terminal background (slot 15, #a3676b, measures 4.45:1; slot 0 is the background itself); the theme documents this rather than normalising it, because programs, not the theme, choose which slot means what. Inside an editor selection (code.selection-bg, #420f0c) muted text stays at 4.71:1 but the keyword, type, property and comment roles fall below 4.5:1; a selection is a transient state and the limitation is recorded, not hidden. The extended overlay proposes a semantic sixteen-slot palette that all reaches 4.5:1.

Links use strong red text.link (#f73f35) and a persistent underline, distinct from the rose body and heading ladder (D-024). Hover uses near-white text.link-hover on interaction.hover.bg (D-027; the strong fill read louder than the link itself and stays with menu items). Current-page and selected navigation use their explicit indicator and on-fill roles.

Typography

One family: SauceCodePro NFM (Source Code Pro through the Nerd Fonts build), falling back to Source Code Pro, Cascadia Mono, Consolas, Liberation Mono, DejaVu Sans Mono and monospace. The site records size-adjust metrics for the fallbacks; no font file is distributed. Weights 400 and 700 plus italic. Scale (size/line-height in px): ui-sm 12/16, ui-md 13/18, ui-lg 14/20, reading 15/24, code 13/19, terminal 13/19 with −0.5px letter-spacing, h1 20/28 bold, h2 16/24 bold, h3 13/18 bold in text.accent, caption 11/16 only with text.muted or lighter. Hosts keep the user’s chosen size; tiny UI text is a reference-implementation metric, not a rule.

Spacing and density (D-009)

Spacing steps: 0, 1, 2, 4, 8, 12, 16, 24, 32, 48 px. Two density modes applied with data-density on any subtree: compact (control 24px, row 28px, ui-sm type, 8px horizontal padding, 2px gaps) matches the workstation; comfortable (control 32px, row 36px, ui-md type, 12px padding, 4px gaps) suits everyday applications. Both meet the 24×24 CSS-pixel target minimum; compact requires 4px between adjacent targets. Table rows are exempt and always take the comfortable row height: a data row is content rather than chrome, and compacting it costs scannability where it is needed most. Controls inside a row still follow the page density. The site’s 3px i3 gap, 14/−2 window gaps and 28px bar are window-manager geometry, not theme tokens.

Elevation and layering

There are no shadows except shadow.floating (0 6px 22px rgb(0 0 0 / 55%)) on the i3 floating-window specimen. Floating layers are a 1px border.overlay on surface.raised; modals add surface.backdrop (rgb(0 0 0 / 65%)). Stacking: canvas 0 < raised 1 < popover 10 < drawer 20 < dialog 30 < toast 40 < skip link 1000.

A popup opened by hovering follows the pointer: it sits 8px from the cursor, flips to the other side of it rather than crossing a viewport edge, keeps an 8px margin from every edge, and is repositioned on pointer move, scroll and resize. A popup with nothing to operate takes no pointer events, so it cannot stand between the cursor and what opened it; one that carries a control or a link stays reachable and holds while the pointer is inside it. Either closes when the pointer leaves both the trigger and the popup.

The same popup opened from the keyboard anchors to its trigger instead — below it, or above when there is no room below — because focus has no pointer to follow. This is a placement rule only: what opens a popup, and whether it is a tooltip, a preview or an inspector, is the component’s own contract.

Icons

SVG line icons on a 16px grid, 1.5px stroke, stroke: currentColor, fill: none, sizes 12 / 16 / 20. No icon font is required; Nerd Font glyphs appear only in terminal and heritage specimens. Icon-only controls carry aria-label and a tooltip. icon.decorative (#a3676b) is for glyphs that convey nothing on their own.

Layout

Reading measure 72ch, content column 680px, application layout 1440px. Breakpoints 320 (reflow floor), 600, 900, 1280. Components use container queries; sidebars collapse to drawers below 900px; data tables scroll horizontally with a sticky first column below 600px; the page never scrolls horizontally at 320px. Right-to-left mirrors breadcrumb separators, pagination, sidebar and drawer sides, wizard progression, affixes and tree indentation.

Tokens

Surfaces

desktop#000000observeduse — Behind every window.
canvas#000000approveduse — Page and terminal background.
chrome#090707approveduse — Window chrome, title bars, bars.
chrome-alt#1c0a09observeduse — Alternate chrome.
sunken#000000approveduse — Reading and detail panes set below the canvas.
default#100c0capproveduse — Panels and cards.
raised#160b0bapproveduse — Sticky headers, menus, popovers; D-027 recessed it so an open list reads as depth rather than a lighter panel.
overlay#241010observeduse — Dialogs and drawers.
input#000000approveduse — Form-control fill.
backdroprgb(0 0 0 / 65%)proposeduse-and-reportD-008 — Behind modal dialogs.
code#000000approveduse — Editor background.
terminal#000000approveduse — Terminal background.

Text

default#e99499observeduse — Interface and body text.
bright#ffa2a7observeduse — Headings and emphasis. Links use color.text.link.
prose#f4eeeeobserveduse — Long-form reading text.
muted#bd787dobserveduse — Secondary text; the darkest colour permitted for chrome text.
subtle#ad7175approveduse — Metadata, comments, line numbers.
disabled#8a5559approveduse — Disabled control text.
placeholder#a3676bapproveduse — Placeholder text, italic; D-027 darkened it to 4.71:1, just clear of the 4.5:1 floor.
accent#e53935observeduse — Accent text on canvas and default surfaces only.
accent-strong#f73f35observeduse — Accent text safe on every surface.
on-selection#f4eeeeobserveduse — Text on the selection fill.
on-action#f4eeeeobserveduse — Text on the primary action fill.
on-danger#f9faf9observeduse — Text on the danger fill.
on-light#0c0909observeduse — Text on light fills: bright rose, amber, green, blue.
inverse#0c0909observeduse — Text on inverted surfaces.

Text ladder on each surface

Measured ratios; ordinary text needs 4.5:1, disabled text is exempt but held to 3:1.

surface.canvas
text.prose18.31:1
text.bright10.98:1
text.default9.16:1
text.muted6.15:1
text.subtle5.40:1
text.accent4.97:1
text.accent-strong5.72:1
surface.default
text.prose16.96:1
text.bright10.17:1
text.default8.48:1
text.muted5.69:1
text.subtle5.00:1
text.accent4.60:1
text.accent-strong5.29:1
surface.raised
text.prose16.85:1
text.bright10.10:1
text.default8.43:1
text.muted5.66:1
text.subtle4.96:1
text.accent4.57:1
text.accent-strong5.26:1

Selection is a fill; focus is a ring

The four combinations every list, table and tab strip must show. Focus rings on fills take the on-fill text colour.

plain row
hovered row
focused row (ring only)
selected row (fill only)
selected + focused row (fill and on-fill ring)
selected while the container is not focused

Borders and radii

divider · decorative hairline between rows
default · decorative, never a control's only edge
control · every form control at rest (≥ 3:1)
active · focused or active control
strong · 2px rules
overlay · every floating layer
disabled
dashed · focus, drop target, read-only only

Status set

Each status has text, fill, tint and border roles and a mandatory glyph. The three extension hues (D-001) exist only here, in diagnostics, in diffs and in the proposed overlay.

✕ danger text
✕ danger fill
✕ danger tint with border
! warning text
! warning fill
! warning tint with border
✓ success text
✓ success fill
✓ success tint with border
i info text
i info fill
i info tint with border
· neutral text
· neutral fill
· neutral tint with border

Terminal slots by profile

The sixteen slots are exact in every profile; only the proposed extended overlay reassigns them. Use the page's profile control to switch specimens, or read the columns.

Slotdefaultheritage-ansiextended
ansi.0#0c0909#0c0909#0c0909proposed
ansi.1#c81a1a#c81a1a#e53935proposed
ansi.2#bd787d#bd787d#86a46fproposed
ansi.3#d4868b#d4868b#c9973fproposed
ansi.4#8c1212#8c1212#7e9ebbproposed
ansi.5#f73f35#f73f35#b37175proposed
ansi.6#9e474a#9e474a#bd787dproposed
ansi.7#ffa2a7#ffa2a7#e99499proposed
ansi.8#7d1310#7d1310#ad7175proposed
ansi.9#ab1612#ab1612#f73f35proposed
ansi.10#ad2721#ad2721#7fbf7aproposed
ansi.11#b37175#b37175#d6a24bproposed
ansi.12#871f19#871f19#9ab3c9proposed
ansi.13#e82132#e82132#d4868bproposed
ansi.14#e0292f#e0292f#ffa2a7proposed
ansi.15#a3676b#a3676b#f4eeeeproposed

Borders

Tokendefaultheritage-ansiextendedUse
color.border.divider#2b0e0dproposeduse-and-reportD-008#2b0e0dproposedhistorical-onlyD-008#2b0e0dproposedblockedD-008Hairline between rows and sections.
color.border.default#531310observeduse#531310observedhistorical-only#531310observedblockedDecorative border (1.39:1; never the only edge of a control).
color.border.strong#9e231fobserveduse#9e231fobservedhistorical-only#9e231fobservedblockedEmphasised 2px rule: sticky headers, section ends.
color.border.control#a3676bproposeduse-and-reportD-007#a3676bproposedhistorical-onlyD-007#a3676bproposedblockedD-007Form-control boundary (4.45:1, meets the 3:1 non-text minimum).
color.border.active#e53935observeduse#e53935observedhistorical-only#e53935observedblockedActive or focused control border.
color.border.overlay#e53935proposeduse-and-reportD-008#ae1914heritagehistorical-only#e53935proposedblockedD-008Every floating layer's 1px border.
color.border.disabled#7d1310observeduse#7d1310observedhistorical-only#7d1310observedblockedDisabled control border (exempt).
color.border.selected-indicator#e53935observeduse#e53935observedhistorical-only#e53935observedblocked2px indicator bar on the selected tab or nav item.
color.border.selected-indicator-inactive#9e231fobserveduse#9e231fobservedhistorical-only#9e231fobservedblockedIndicator bar when the container is not focused.

Interaction

Tokendefaultheritage-ansiextendedUse
color.interaction.focus.ring#e53935observeduse#e53935observedhistorical-only#e53935observedblocked1px dashed focus ring on controls and rows.
color.interaction.focus.ring-container#ffa2a7observeduse#ffa2a7observedhistorical-only#ffa2a7observedblockedFocus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
color.interaction.selection.bg#531310approveduse#531310approvedhistorical-only#531310approvedblockedSelected row, tab, workspace; D-027 recessed the fill, leaving the 2px indicator and the check to carry selection.
color.interaction.selection.text#f4eeeeobserveduse#f4eeeeobservedhistorical-only#f4eeeeobservedblockedText on the selection.
color.interaction.selection.inactive-bg#420f0cobserveduse#420f0cobservedhistorical-only#420f0cobservedblockedSelection while the container is not focused.
color.interaction.selection.inactive-text#e99499observeduse#e99499observedhistorical-only#e99499observedblockedText on the inactive selection (7.02:1).
color.interaction.text-selection.bg#911410observeduse#911410observedhistorical-only#911410observedblocked::selection background.
color.interaction.text-selection.text#f4eeeeobserveduse#f4eeeeobservedhistorical-only#f4eeeeobservedblocked::selection text.
color.interaction.hover.bg#1c0a09observeduse#1c0a09observedhistorical-only#1c0a09observedblockedHover on rows, ghost buttons, list items.
color.interaction.hover.bg-strong#630f0dobserveduse#630f0dobservedhistorical-only#630f0dobservedblockedHover on menu items; D-027 moved links to interaction.hover.bg.
color.interaction.pressed.bg#420f0cobserveduse#420f0cobservedhistorical-only#420f0cobservedblockedPressed fill.
color.interaction.disabled.bg#160b0bobserveduse#160b0bobservedhistorical-only#160b0bobservedblockedDisabled control fill.
color.interaction.marqueergb(145 20 16 / 12%)observedusergb(145 20 16 / 12%)observedhistorical-onlyrgb(145 20 16 / 12%)observedblockedDrag marquee and ghost.
color.interaction.drop-target#e53935observeduse#e53935observedhistorical-only#e53935observedblockedDashed drop-target border.
color.interaction.scrollbar.track#0c0909observeduse#0c0909observedhistorical-only#0c0909observedblockedScrollbar track.
color.interaction.scrollbar.thumb#420f0cobserveduse#420f0cobservedhistorical-only#420f0cobservedblockedScrollbar thumb.
color.interaction.scrollbar.thumb-hover#911410observeduse#911410observedhistorical-only#911410observedblockedScrollbar thumb on hover.

Actions

Tokendefaultheritage-ansiextendedUse
color.action.primary.bg#7d1310approveduse#7d1310approvedhistorical-only#7d1310approvedblockedPrimary button fill; D-026 darkened it off color12, which stays fixed as heritage ANSI 12.
color.action.primary.text#f4eeeeobserveduse#f4eeeeobservedhistorical-only#f4eeeeobservedblockedPrimary button text (9.28:1).
color.action.primary.hover-bg#911410observeduse#911410observedhistorical-only#911410observedblockedPrimary button hover (7.92:1 with prose).
color.action.primary.pressed-bg#630f0dobserveduse#630f0dobservedhistorical-only#630f0dobservedblockedPrimary button pressed.
color.action.primary.border#9e231fobserveduse#9e231fobservedhistorical-only#9e231fobservedblockedPrimary button border.
color.action.secondary.bgrgb(0 0 0 / 0%)observedusergb(0 0 0 / 0%)observedhistorical-onlyrgb(0 0 0 / 0%)observedblockedSecondary button has no fill.
color.action.secondary.text#ffa2a7observeduse#ffa2a7observedhistorical-only#ffa2a7observedblockedSecondary button text.
color.action.secondary.border#a3676bobserveduse#a3676bobservedhistorical-only#a3676bobservedblockedSecondary button border (meets 3:1).
color.action.secondary.hover-bg#630f0dobserveduse#630f0dobservedhistorical-only#630f0dobservedblockedSecondary button hover.
color.action.secondary.pressed-bg#420f0cobserveduse#420f0cobservedhistorical-only#420f0cobservedblockedSecondary button pressed.
color.action.tertiary.text#e99499observeduse#e99499observedhistorical-only#e99499observedblockedGhost and icon button text.
color.action.tertiary.hover-bg#1c0a09observeduse#1c0a09observedhistorical-only#1c0a09observedblockedGhost and icon button hover.
color.action.destructive.text#f73f35observeduse#f73f35observedhistorical-only#f73f35observedblockedDestructive button text at rest (outline style).
color.action.destructive.border#e53935observeduse#e53935observedhistorical-only#e53935observedblockedDestructive button border.
color.action.destructive.hover-bg#dc282eobserveduse#dc282eobservedhistorical-only#dc282eobservedblockedDestructive button hover fill.
color.action.destructive.hover-text#f9faf9observeduse#f9faf9observedhistorical-only#f9faf9observedblockedDestructive button text on hover (4.58:1).
color.action.destructive.pressed-bg#ae1914observeduse#ae1914observedhistorical-only#ae1914observedblockedDestructive button pressed fill.
color.action.destructive.filled-bg#dc282eobserveduse#dc282eobservedhistorical-only#dc282eobservedblockedConfirm-dialog destructive fill.
color.action.destructive.filled-text#f9faf9observeduse#f9faf9observedhistorical-only#f9faf9observedblockedText on the destructive fill.

Status

Tokendefaultheritage-ansiextendedUse
color.status.danger.text#f73f35observeduse#f73f35observedhistorical-only#f73f35observedblockedDanger text (5.40:1).
color.status.danger.fill#dc282eobserveduse#dc282eobservedhistorical-only#dc282eobservedblockedDanger fill.
color.status.danger.on-fill#f9faf9observeduse#f9faf9observedhistorical-only#f9faf9observedblockedText on the danger fill (4.58:1).
color.status.danger.tint#2b0e0dobserveduse#2b0e0dobservedhistorical-only#2b0e0dobservedblockedDanger background tint.
color.status.danger.border#e53935observeduse#e53935observedhistorical-only#e53935observedblockedDanger border, 2px on invalid inputs.
color.status.warning.text#c9973fapproveduse#c9973fapprovedhistorical-only#c9973fapprovedblockedWarning text (7.54:1).
color.status.warning.fill#c9973fapproveduse#c9973fapprovedhistorical-only#c9973fapprovedblockedWarning fill.
color.status.warning.on-fill#0c0909approveduse#0c0909approvedhistorical-only#0c0909approvedblockedText on the warning fill (7.54:1).
color.status.warning.tint#1f1a0capproveduse#1f1a0capprovedhistorical-only#1f1a0capprovedblockedWarning background tint.
color.status.warning.border#c9973fapproveduse#c9973fapprovedhistorical-only#c9973fapprovedblockedWarning border.
color.status.success.text#86a46fapproveduse#86a46fapprovedhistorical-only#86a46fapprovedblockedSuccess text (7.13:1).
color.status.success.fill#86a46fapproveduse#86a46fapprovedhistorical-only#86a46fapprovedblockedSuccess fill.
color.status.success.on-fill#0c0909approveduse#0c0909approvedhistorical-only#0c0909approvedblockedText on the success fill (7.13:1).
color.status.success.tint#0f1a0eapproveduse#0f1a0eapprovedhistorical-only#0f1a0eapprovedblockedSuccess background tint.
color.status.success.border#86a46fapproveduse#86a46fapprovedhistorical-only#86a46fapprovedblockedSuccess border.
color.status.info.text#7e9ebbapproveduse#7e9ebbapprovedhistorical-only#7e9ebbapprovedblockedInfo text (7.08:1).
color.status.info.fill#7e9ebbapproveduse#7e9ebbapprovedhistorical-only#7e9ebbapprovedblockedInfo fill.
color.status.info.on-fill#0c0909approveduse#0c0909approvedhistorical-only#0c0909approvedblockedText on the info fill (7.08:1).
color.status.info.tint#0f141capproveduse#0f141capprovedhistorical-only#0f141capprovedblockedInfo background tint.
color.status.info.border#7e9ebbapproveduse#7e9ebbapprovedhistorical-only#7e9ebbapprovedblockedInfo border.
color.status.neutral.text#bd787dobserveduse#bd787dobservedhistorical-only#bd787dobservedblockedNeutral status text.
color.status.neutral.fill#a3676bobserveduse#a3676bheritagehistorical-only#a3676bobservedblockedNeutral fill (dunst urgency_low).
color.status.neutral.on-fill#000000observeduse#0c0909heritagedeprecatedhistorical-only#000000observedblockedText on the neutral fill (4.71:1).
color.status.neutral.tint#241010observeduse#241010observedhistorical-only#241010observedblockedNeutral background tint.
color.status.neutral.border#a3676bobserveduse#a3676bobservedhistorical-only#a3676bobservedblockedNeutral border.

Code

Tokendefaultheritage-ansiextendedUse
color.code.bg#0c0909observeduse#0c0909observedhistorical-only#0c0909observedblockedEditor background.
color.code.current-line#1c0a09observeduse#1c0a09observedhistorical-only#1c0a09observedblockedCurrent line background.
color.code.gutter-bg#0c0909observeduse#0c0909observedhistorical-only#0c0909observedblockedGutter background.
color.code.line-number#ad7175approveduse#7d1310heritagedeprecatedhistorical-only#ad7175approvedblockedLine numbers (5.10:1; replaces the site's #7d1310).
color.code.line-number-active#e99499observeduse#e99499observedhistorical-only#e99499observedblockedLine number of the current line.
color.code.gutter-rule#2b0e0dobserveduse#2b0e0dobservedhistorical-only#2b0e0dobservedblockedRule between gutter and text.
color.code.caret#e99499observeduse#e99499observedhistorical-only#e99499observedblockedCaret (Xresources *cursorColor).
color.code.selection-bg#420f0cobserveduse#420f0cobservedhistorical-only#420f0cobservedblockedEditor selection background (muted text stays 4.71:1).
color.code.search-match-bg#630f0dobserveduse#630f0dobservedhistorical-only#630f0dobservedblockedOther search matches.
color.code.search-current-bg#ffa2a7observeduse#ffa2a7observedhistorical-only#ffa2a7observedblockedCurrent search match background.
color.code.search-current-text#0c0909observeduse#0c0909observedhistorical-only#0c0909observedblockedCurrent search match text.
color.code.bracket-match#e53935observeduse#e53935observedhistorical-only#e53935observedblockedMatching bracket 1px border.
color.code.indent-guide#531310observeduse#531310observedhistorical-only#531310observedblockedIndent guides.
color.code.whitespace#7d1310observeduse#7d1310observedhistorical-only#7d1310observedblockedRendered whitespace (decorative).
color.code.syntax.keyword#f73f35observeduse#f73f35observedhistorical-only#f73f35observedblockedKeywords (Xresources color5 lineage).
color.code.syntax.string#bd787dobserveduse#bd787dobservedhistorical-only#86a46fproposedblockedD-001Strings (color2 lineage).
color.code.syntax.comment#ad7175approveduse#7d1310heritagedeprecatedhistorical-only#ad7175approvedblockedComments, italic (color8 lineage, corrected for contrast).
color.code.syntax.number#d4868bobserveduse#d4868bobservedhistorical-only#c9973fproposedblockedD-001Numbers.
color.code.syntax.constant#d4868bobserveduse#d4868bobservedhistorical-only#c9973fproposedblockedD-001Constants and booleans.
color.code.syntax.function#ffa2a7observeduse#ffa2a7heritagehistorical-only#c9973fproposedblockedD-001Function names and calls (color7 lineage).
color.code.syntax.variable#e99499observeduse#ab1612heritagedeprecatedhistorical-only#e99499observedblockedVariables and default text.
color.code.syntax.type#b37175observeduse#b37175observedhistorical-only#7e9ebbproposedblockedD-001Types.
color.code.syntax.operator#e99499observeduse#ffa2a7heritagehistorical-only#ffa2a7proposedblockedD-001Operators.
color.code.syntax.punctuation#e99499observeduse#d4868bheritagehistorical-only#b37175proposedblockedD-001Punctuation.
color.code.syntax.property#e53935observeduse#e53935observedhistorical-only#7e9ebbproposedblockedD-001Properties and keys (site .syntax-key).
color.code.syntax.heading#e53935observeduse#e53935observedhistorical-only#e53935observedblockedMarkup headings (site .syntax-heading).
color.code.syntax.tag#f73f35observeduse#f73f35observedhistorical-only#f73f35observedblockedMarkup tags.
color.code.syntax.attribute#d4868bobserveduse#d4868bobservedhistorical-only#c9973fproposedblockedD-001Markup attributes.
color.code.syntax.escape#d4868bobserveduse#d4868bobservedhistorical-only#c9973fproposedblockedD-001Escape sequences and regex, bold.
color.code.syntax.invalid#e53935observeduse#e53935observedhistorical-only#e53935observedblockedInvalid text: wavy underline.
color.code.syntax.deprecated#ad7175observeduse#ad7175observedhistorical-only#ad7175observedblockedDeprecated symbol: line-through.

Diagnostics

Tokendefaultheritage-ansiextendedUse
color.diagnostic.error.underline#e53935observeduse#e53935observedhistorical-only#e53935observedblockedError wavy underline.
color.diagnostic.error.text#f73f35observeduse#f73f35observedhistorical-only#f73f35observedblockedError message text.
color.diagnostic.error.stripe#e53935observeduse#e53935observedhistorical-only#e53935observedblockedError stripe mark.
color.diagnostic.error.bg#2b0e0dobserveduse#2b0e0dobservedhistorical-only#2b0e0dobservedblockedError line background.
color.diagnostic.warning.underline#c9973fapproveduse#c9973fapprovedhistorical-only#c9973fapprovedblockedWarning wavy underline.
color.diagnostic.warning.text#c9973fapproveduse#c9973fapprovedhistorical-only#c9973fapprovedblockedWarning message text.
color.diagnostic.warning.stripe#c9973fapproveduse#c9973fapprovedhistorical-only#c9973fapprovedblockedWarning stripe mark.
color.diagnostic.info.underline#7e9ebbapproveduse#7e9ebbapprovedhistorical-only#7e9ebbapprovedblockedInfo dotted underline.
color.diagnostic.info.text#7e9ebbapproveduse#7e9ebbapprovedhistorical-only#7e9ebbapprovedblockedInfo message text.
color.diagnostic.hint.underline#ad7175observeduse#ad7175observedhistorical-only#ad7175observedblockedHint dotted underline.
color.diagnostic.unused.text#bd787dobserveduse#bd787dobservedhistorical-only#bd787dobservedblockedUnused symbol, dotted underline.

Diffs

Tokendefaultheritage-ansiextendedUse
color.diff.added.bg#0f1a0eapproveduse#0f1a0eapprovedhistorical-only#0f1a0eapprovedblockedAdded line background.
color.diff.added.gutter#86a46fapproveduse#86a46fapprovedhistorical-only#86a46fapprovedblockedAdded gutter mark and +.
color.diff.added.emphasis#86a46fapproveduse#86a46fapprovedhistorical-only#86a46fapprovedblockedWord-level addition: 2px underline.
color.diff.removed.bg#2b0e0dobserveduse#2b0e0dobservedhistorical-only#2b0e0dobservedblockedRemoved line background.
color.diff.removed.gutter#e53935observeduse#e53935observedhistorical-only#e53935observedblockedRemoved gutter mark and −.
color.diff.removed.emphasis#e53935observeduse#e53935observedhistorical-only#e53935observedblockedWord-level removal: underline and line-through.
color.diff.modified.bg#1f1a0capproveduse#1f1a0capprovedhistorical-only#1f1a0capprovedblockedModified line background.
color.diff.modified.gutter#c9973fapproveduse#c9973fapprovedhistorical-only#c9973fapprovedblockedModified gutter mark and ~.
color.diff.conflict-border#f73f35observeduse#f73f35observedhistorical-only#f73f35observedblockedConflict block: double 1px border.
color.diff.header-bg#241010observeduse#241010observedhistorical-only#241010observedblockedHunk header background.

Terminal

Tokendefaultheritage-ansiextendedUse
color.terminal.bg#0c0909observeduse#0c0909observedhistorical-only#0c0909observedblockedTerminal background.
color.terminal.fg#e99499observeduse#e99499observedhistorical-only#e99499observedblockedTerminal foreground.
color.terminal.cursor#e99499observeduse#e99499observedhistorical-only#e99499observedblockedTerminal cursor.
color.terminal.selection-bg#911410observeduse#911410observedhistorical-only#911410observedblockedTerminal selection.
color.terminal.selection-text#f4eeeeobserveduse#f4eeeeobservedhistorical-only#f4eeeeobservedblockedTerminal selection text.
color.terminal.ansi.0#0c0909observeduse#0c0909observedhistorical-only#0c0909proposedblockedD-001ANSI slot 0, exact heritage value.
color.terminal.ansi.1#c81a1aobserveduse#c81a1aobservedhistorical-only#e53935proposedblockedD-001ANSI slot 1, exact heritage value.
color.terminal.ansi.2#bd787dobserveduse#bd787dobservedhistorical-only#86a46fproposedblockedD-001ANSI slot 2, exact heritage value.
color.terminal.ansi.3#d4868bobserveduse#d4868bobservedhistorical-only#c9973fproposedblockedD-001ANSI slot 3, exact heritage value.
color.terminal.ansi.4#8c1212observeduse#8c1212observedhistorical-only#7e9ebbproposedblockedD-001ANSI slot 4, exact heritage value.
color.terminal.ansi.5#f73f35observeduse#f73f35observedhistorical-only#b37175proposedblockedD-001ANSI slot 5, exact heritage value.
color.terminal.ansi.6#9e474aobserveduse#9e474aobservedhistorical-only#bd787dproposedblockedD-001ANSI slot 6, exact heritage value.
color.terminal.ansi.7#ffa2a7observeduse#ffa2a7observedhistorical-only#e99499proposedblockedD-001ANSI slot 7, exact heritage value.
color.terminal.ansi.8#7d1310observeduse#7d1310observedhistorical-only#ad7175proposedblockedD-001ANSI slot 8, exact heritage value.
color.terminal.ansi.9#ab1612observeduse#ab1612observedhistorical-only#f73f35proposedblockedD-001ANSI slot 9, exact heritage value.
color.terminal.ansi.10#ad2721observeduse#ad2721observedhistorical-only#7fbf7aproposedblockedD-001ANSI slot 10, exact heritage value.
color.terminal.ansi.11#b37175observeduse#b37175observedhistorical-only#d6a24bproposedblockedD-001ANSI slot 11, exact heritage value.
color.terminal.ansi.12#871f19observeduse#871f19observedhistorical-only#9ab3c9proposedblockedD-001ANSI slot 12, exact heritage value.
color.terminal.ansi.13#e82132observeduse#e82132observedhistorical-only#d4868bproposedblockedD-001ANSI slot 13, exact heritage value.
color.terminal.ansi.14#e0292fobserveduse#e0292fobservedhistorical-only#ffa2a7proposedblockedD-001ANSI slot 14, exact heritage value.
color.terminal.ansi.15#a3676bobserveduse#a3676bobservedhistorical-only#f4eeeeproposedblockedD-001ANSI slot 15, exact heritage value.

Charts

Tokendefaultheritage-ansiextendedUse
color.chart.series-1#ffa2a7observeduse#ffa2a7observedhistorical-only#ffa2a7observedblockedFirst series.
color.chart.series-2#f73f35observeduse#f73f35observedhistorical-only#86a46fproposedblockedD-001Second series.
color.chart.series-3#bd787dobserveduse#bd787dobservedhistorical-only#c9973fproposedblockedD-001Third series.
color.chart.series-4#a3676bobserveduse#a3676bobservedhistorical-only#7e9ebbproposedblockedD-001Fourth series (non-text, 4.45:1).
color.chart.axis#9e231fobserveduse#9e231fobservedhistorical-only#9e231fobservedblockedAxis lines.
color.chart.grid#2b0e0dobserveduse#2b0e0dobservedhistorical-only#2b0e0dobservedblockedGrid lines.
color.chart.label#bd787dobserveduse#bd787dobservedhistorical-only#bd787dobservedblockedAxis labels.

Icons

Tokendefaultheritage-ansiextendedUse
color.icon.default#e99499observeduse#e99499observedhistorical-only#e99499observedblockedIcons take the text colour (currentColor in CSS).
color.icon.decorative#a3676bobserveduse#a3676bobservedhistorical-only#a3676bobservedblockedDecorative glyphs (3:1 as graphics, never text).

Spacing

Tokendefaultheritage-ansiextendedUse
space.00pxobserveduse0pxobservedhistorical-only0pxobservedblocked
space.11pxobserveduse1pxobservedhistorical-only1pxobservedblocked
space.22pxobserveduse2pxobservedhistorical-only2pxobservedblocked
space.44pxobserveduse4pxobservedhistorical-only4pxobservedblocked
space.88pxobserveduse8pxobservedhistorical-only8pxobservedblocked
space.1212pxobserveduse12pxobservedhistorical-only12pxobservedblocked
space.1616pxobserveduse16pxobservedhistorical-only16pxobservedblocked
space.2424pxobserveduse24pxobservedhistorical-only24pxobservedblocked
space.3232pxobserveduse32pxobservedhistorical-only32pxobservedblocked
space.4848pxobserveduse48pxobservedhistorical-only48pxobservedblocked

Density

Tokendefaultheritage-ansiextendedUse
density.compact.control-height24pxobserveduse24pxobservedhistorical-only24pxobservedblocked
density.compact.row-height28pxobserveduse28pxobservedhistorical-only28pxobservedblocked
density.compact.control-padding-x8pxobserveduse8pxobservedhistorical-only8pxobservedblocked
density.compact.icon12pxobserveduse12pxobservedhistorical-only12pxobservedblocked
density.compact.gap2pxobserveduse2pxobservedhistorical-only2pxobservedblocked
density.comfortable.control-height32pxobserveduse32pxobservedhistorical-only32pxobservedblocked
density.comfortable.row-height36pxobserveduse36pxobservedhistorical-only36pxobservedblocked
density.comfortable.control-padding-x12pxobserveduse12pxobservedhistorical-only12pxobservedblocked
density.comfortable.icon16pxobserveduse16pxobservedhistorical-only16pxobservedblocked
density.comfortable.gap4pxobserveduse4pxobservedhistorical-only4pxobservedblocked

Border widths

Tokendefaultheritage-ansiextendedUse
border.width.default1pxobserveduse1pxobservedhistorical-only1pxobservedblockedEvery border is 1px.
border.width.emphasis2pxobserveduse2pxobservedhistorical-only2pxobservedblockedSelected indicator, sticky header rule, invalid border.

Radius

Tokendefaultheritage-ansiextendedUse
radius.none0pxobserveduse0pxobservedhistorical-only0pxobservedblockedThe only radius. Nothing is rounded.

Typography

Tokendefaultheritage-ansiextendedUse
font.family.mono"SauceCodePro NFM", "Source Code Pro", "Cascadia Mono", "Consolas", "Liberation Mono", "DejaVu Sans Mono", monospaceobserveduse"SauceCodePro NFM", "Source Code Pro", "Cascadia Mono", "Consolas", "Liberation Mono", "DejaVu Sans Mono", monospaceobservedhistorical-only"SauceCodePro NFM", "Source Code Pro", "Cascadia Mono", "Consolas", "Liberation Mono", "DejaVu Sans Mono", monospaceobservedblockedOne family for chrome, reading and code. Not bundled; see theme.json font.
font.weight.regular400observeduse400observedhistorical-only400observedblocked
font.weight.bold700observeduse700observedhistorical-only700observedblocked
font.size.ui-sm12pxobserveduse12pxobservedhistorical-only12pxobservedblocked
font.size.ui-md13pxobserveduse13pxobservedhistorical-only13pxobservedblocked
font.size.ui-lg14pxobserveduse14pxobservedhistorical-only14pxobservedblocked
font.size.reading15pxobserveduse15pxobservedhistorical-only15pxobservedblocked
font.size.code13pxobserveduse13pxobservedhistorical-only13pxobservedblocked
font.size.terminal13pxobserveduse13pxobservedhistorical-only13pxobservedblockedURxvt pixelsize 13.
font.size.h120pxobserveduse20pxobservedhistorical-only20pxobservedblocked
font.size.h216pxobserveduse16pxobservedhistorical-only16pxobservedblocked
font.size.h313pxobserveduse13pxobservedhistorical-only13pxobservedblocked
font.size.caption11pxobserveduse11pxobservedhistorical-only11pxobservedblockedOnly with text.muted or lighter.
font.line-height.ui-sm16pxobserveduse16pxobservedhistorical-only16pxobservedblocked
font.line-height.ui-md18pxobserveduse18pxobservedhistorical-only18pxobservedblocked
font.line-height.ui-lg20pxobserveduse20pxobservedhistorical-only20pxobservedblocked
font.line-height.reading24pxobserveduse24pxobservedhistorical-only24pxobservedblocked
font.line-height.code19pxobserveduse19pxobservedhistorical-only19pxobservedblocked
font.line-height.terminal19pxobserveduse19pxobservedhistorical-only19pxobservedblocked
font.line-height.h128pxobserveduse28pxobservedhistorical-only28pxobservedblocked
font.line-height.h224pxobserveduse24pxobservedhistorical-only24pxobservedblocked
font.line-height.h318pxobserveduse18pxobservedhistorical-only18pxobservedblocked
font.line-height.caption16pxobserveduse16pxobservedhistorical-only16pxobservedblocked
font.letter-spacing.terminal-0.5pxobserveduse-0.5pxobservedhistorical-only-0.5pxobservedblockedURxvt letterSpace -1 at pixelsize 13, as the site renders it.

Focus

Tokendefaultheritage-ansiextendedUse
focus.ring1px dashed #e53935observeduse1px dashed #e53935observedhistorical-only1px dashed #e53935observedblockedoutline on controls and rows.
focus.ring-container2px solid #ffa2a7observeduse2px solid #ffa2a7observedhistorical-only2px solid #ffa2a7observedblockedoutline on focusable containers.
focus.offset-2pxobserveduse-2pxobservedhistorical-only-2pxobservedblockedoutline-offset for controls.
focus.offset-container-3pxobserveduse-3pxobservedhistorical-only-3pxobservedblockedoutline-offset for containers.
focus.offset-invalid-4pxobserveduse-4pxobservedhistorical-only-4pxobservedblockedoutline-offset inside the 2px invalid border.

Motion

Tokendefaultheritage-ansiextendedUse
motion.duration.fast80msobserveduse80msobservedhistorical-only80msobservedblocked
motion.duration.base120msobserveduse120msobservedhistorical-only120msobservedblocked
motion.duration.slow150msobserveduse150msobservedhistorical-only150msobservedblockedThe maximum. Reduced motion sets every duration to 0.01ms.

Elevation

Tokendefaultheritage-ansiextendedUse
shadow.floating0px 6px 22px 0px rgb(0 0 0 / 55%)observeduse0px 6px 22px 0px rgb(0 0 0 / 55%)observedhistorical-only0px 6px 22px 0px rgb(0 0 0 / 55%)observedblockedThe only shadow: the i3 floating window.

Layout

Tokendefaultheritage-ansiextendedUse
layout.measure72observeduse72observedhistorical-only72observedblockedReading measure in ch.
layout.content-max680pxobserveduse680pxobservedhistorical-only680pxobservedblockedReading column maximum.
layout.app-max1440pxobserveduse1440pxobservedhistorical-only1440pxobservedblockedApplication layout maximum.

Breakpoints

Tokendefaultheritage-ansiextendedUse
breakpoint.xs320pxobserveduse320pxobservedhistorical-only320pxobservedblockedReflow floor (WCAG 1.4.10).
breakpoint.sm600pxobserveduse600pxobservedhistorical-only600pxobservedblocked
breakpoint.md900pxobserveduse900pxobservedhistorical-only900pxobservedblocked
breakpoint.lg1280pxobserveduse1280pxobservedhistorical-only1280pxobservedblockedThe site's bar breaks below this.

Icon sizes

Tokendefaultheritage-ansiextendedUse
icon.size.sm12pxobserveduse12pxobservedhistorical-only12pxobservedblocked
icon.size.md16pxobserveduse16pxobservedhistorical-only16pxobservedblocked
icon.size.lg20pxobserveduse20pxobservedhistorical-only20pxobservedblocked
icon.stroke1.5pxobserveduse1.5pxobservedhistorical-only1.5pxobservedblockedSVG line icons, currentColor, no fill.

Stacking

Tokendefaultheritage-ansiextendedUse
z.canvas0observeduse0observedhistorical-only0observedblocked
z.raised1observeduse1observedhistorical-only1observedblocked
z.popover10observeduse10observedhistorical-only10observedblocked
z.drawer20observeduse20observedhistorical-only20observedblocked
z.dialog30observeduse30observedhistorical-only30observedblocked
z.toast40observeduse40observedhistorical-only40observedblocked

Primitives (inspection only; consume roles, not primitives)

Tokendefaultheritage-ansiextendedUse
color.primitive.ink.0#000000observedblocked#000000observedhistorical-only#000000observedblockedThe desktop behind every window.
color.primitive.ink.14#090707approvedblocked#090707approvedhistorical-only#090707approvedblockedTrue Black / Rose surface primitive; D-023.
color.primitive.ink.15#0a0707observedblocked#0a0707observedhistorical-only#0a0707observedblockedSunken reading and detail panes.
color.primitive.ink.20#0c0909observedblocked#0c0909observedhistorical-only#0c0909observedblockedTerminal and canvas background; Xresources color0 and *background.
color.primitive.ink.25#100909observedblocked#100909observedhistorical-only#100909observedblockedWindow chrome and title bars.
color.primitive.ink.28#100c0capprovedblocked#100c0capprovedhistorical-only#100c0capprovedblockedTrue Black / Rose surface primitive; D-023.
color.primitive.ink.30#160b0bobservedblocked#160b0bobservedhistorical-only#160b0bobservedblockedDefault panel surface.
color.primitive.ink.40#1c0a09observedblocked#1c0a09observedhistorical-only#1c0a09observedblockedAlternate chrome; hover rows; current line.
color.primitive.ink.52#241010observedblocked#241010observedhistorical-only#241010observedblockedRaised surface: sticky headers, menus, popovers.
color.primitive.ink.60#2b0e0dobservedblocked#2b0e0dobservedhistorical-only#2b0e0dobservedblockedHairline divider; folds the site's six near-identical hairlines.
color.primitive.red.50#420f0cobservedblocked#420f0cobservedhistorical-only#420f0cobservedblockedSoft selection; inactive selection; scrollbar thumb.
color.primitive.red.100#531310observedblocked#531310observedhistorical-only#531310observedblockedDecorative hairline border.
color.primitive.red.150#630f0dobservedblocked#630f0dobservedhistorical-only#630f0dobservedblockedDark selection; dmenu selected background.
color.primitive.red.200#7d1310observedblocked#7d1310observedhistorical-only#7d1310observedblockedXresources color8. Never text.
color.primitive.red.250#8c1212observedblocked#8c1212observedhistorical-only#8c1212observedblockedXresources color4; i3 focused child border.
color.primitive.red.300#871f19observedblocked#871f19observedhistorical-only#871f19observedblockedXresources color12; the button fill.
color.primitive.red.350#911410observedblocked#911410observedhistorical-only#911410observedblockedSelection fill.
color.primitive.red.400#9e231fobservedblocked#9e231fobservedhistorical-only#9e231fobservedblockedStrong border; sticky header rule.
color.primitive.red.450#ab1612observedblocked#ab1612observedhistorical-only#ab1612observedblockedXresources color9.
color.primitive.red.500#ad2721observedblocked#ad2721observedhistorical-only#ad2721observedblockedXresources color10.
color.primitive.red.550#ae1914observedblocked#ae1914observedhistorical-only#ae1914observedblockeddunst frame and conky accent.
color.primitive.red.650#c81a1aobservedblocked#c81a1aobservedhistorical-only#c81a1aobservedblockedXresources color1; i3 focused workspace background.
color.primitive.red.750#dc282eobservedblocked#dc282eobservedhistorical-only#dc282eobservedblockeddunst critical background; link underline.
color.primitive.red.760#e0292fobservedblocked#e0292fobservedhistorical-only#e0292fobservedblockedXresources color14; i3 focused border.
color.primitive.red.770#e82132observedblocked#e82132observedhistorical-only#e82132observedblockedXresources color13.
color.primitive.red.800#e53935observedblocked#e53935observedhistorical-only#e53935observedblockedFocus ring; active border; accent text on dark surfaces.
color.primitive.red.850#f73f35observedblocked#f73f35observedhistorical-only#f73f35observedblockedXresources color5; strong accent; danger text.
color.primitive.rose.300#8a5559approvedblocked#8a5559approvedhistorical-only#8a5559approvedblockedDisabled text (3.33:1 on canvas; exempt, at least 3:1 by policy).
color.primitive.rose.320#9e474aobservedblocked#9e474aobservedhistorical-only#9e474aobservedblockedXresources color6.
color.primitive.rose.350#a3676bobservedblocked#a3676bobservedhistorical-only#a3676bobservedblockedXresources color15; 4.45:1 on canvas, so not ordinary text.
color.primitive.rose.450#ad7175approvedblocked#ad7175approvedhistorical-only#ad7175approvedblockedSubtle text: metadata, comments, line numbers (5.10:1).
color.primitive.rose.550#b37175observedblocked#b37175observedhistorical-only#b37175observedblockedXresources color11.
color.primitive.rose.600#bd787dobservedblocked#bd787dobservedhistorical-only#bd787dobservedblockedXresources color2; muted text, the floor for chrome text (5.81:1).
color.primitive.rose.650#d4868bobservedblocked#d4868bobservedhistorical-only#d4868bobservedblockedXresources color3.
color.primitive.rose.700#e99499observedblocked#e99499observedhistorical-only#e99499observedblockedXresources *foreground; interface text.
color.primitive.rose.800#ffa2a7observedblocked#ffa2a7observedhistorical-only#ffa2a7observedblockedXresources color7; bright text, links, headings.
color.primitive.paper.90#f4eeeeobservedblocked#f4eeeeobservedhistorical-only#f4eeeeobservedblockedProse and on-fill text.
color.primitive.paper.100#f9faf9observedblocked#f9faf9observedhistorical-only#f9faf9observedblockedText on the critical toast.
color.primitive.amber.500#c9973fapprovedblocked#c9973fapprovedhistorical-only#c9973fapprovedblockedWarning text, border and fill (7.54:1 on canvas).
color.primitive.amber.600#d6a24bproposedblocked#d6a24bproposedhistorical-only#d6a24bproposedblockedBright yellow slot in the extended terminal palette.
color.primitive.amber.tint#1f1a0capprovedblocked#1f1a0capprovedhistorical-only#1f1a0capprovedblockedWarning and modified backgrounds.
color.primitive.green.500#86a46fapprovedblocked#86a46fapprovedhistorical-only#86a46fapprovedblockedSuccess text, border and fill (7.13:1 on canvas).
color.primitive.green.600#7fbf7aobservedblocked#7fbf7aobservedhistorical-only#7fbf7aobservedblockedThe greeter's systemd OK; bright green slot in the extended terminal palette.
color.primitive.green.tint#0f1a0eapprovedblocked#0f1a0eapprovedhistorical-only#0f1a0eapprovedblockedAdded-line background.
color.primitive.blue.500#7e9ebbapprovedblocked#7e9ebbapprovedhistorical-only#7e9ebbapprovedblockedInfo text, border and fill (7.08:1 on canvas).
color.primitive.blue.600#9ab3c9proposedblocked#9ab3c9proposedhistorical-only#9ab3c9proposedblockedBright blue slot in the extended terminal palette.
color.primitive.blue.tint#0f141capprovedblocked#0f141capprovedhistorical-only#0f141capprovedblockedInfo background.
color.primitive.alpha.transparentrgb(0 0 0 / 0%)observedblockedrgb(0 0 0 / 0%)observedhistorical-onlyrgb(0 0 0 / 0%)observedblockedNo fill.
color.primitive.alpha.black-55rgb(0 0 0 / 55%)observedblockedrgb(0 0 0 / 55%)observedhistorical-onlyrgb(0 0 0 / 55%)observedblockedFloating-window shadow.
color.primitive.alpha.black-65rgb(0 0 0 / 65%)observedblockedrgb(0 0 0 / 65%)observedhistorical-onlyrgb(0 0 0 / 65%)observedblockedModal backdrop; unifies the site's 62–72% backdrops.
color.primitive.alpha.red-6rgb(145 20 16 / 6%)observedblockedrgb(145 20 16 / 6%)observedhistorical-onlyrgb(145 20 16 / 6%)observedblockedWallpaper stripe.
color.primitive.alpha.red-12rgb(145 20 16 / 12%)observedblockedrgb(145 20 16 / 12%)observedhistorical-onlyrgb(145 20 16 / 12%)observedblockedDrag marquee.
color.primitive.ansi.0#0c0909observedblocked#0c0909observedhistorical-only#0c0909observedblockedcolor0
color.primitive.ansi.1#c81a1aobservedblocked#c81a1aobservedhistorical-only#c81a1aobservedblockedcolor1
color.primitive.ansi.2#bd787dobservedblocked#bd787dobservedhistorical-only#bd787dobservedblockedcolor2
color.primitive.ansi.3#d4868bobservedblocked#d4868bobservedhistorical-only#d4868bobservedblockedcolor3
color.primitive.ansi.4#8c1212observedblocked#8c1212observedhistorical-only#8c1212observedblockedcolor4
color.primitive.ansi.5#f73f35observedblocked#f73f35observedhistorical-only#f73f35observedblockedcolor5
color.primitive.ansi.6#9e474aobservedblocked#9e474aobservedhistorical-only#9e474aobservedblockedcolor6
color.primitive.ansi.7#ffa2a7observedblocked#ffa2a7observedhistorical-only#ffa2a7observedblockedcolor7
color.primitive.ansi.8#7d1310observedblocked#7d1310observedhistorical-only#7d1310observedblockedcolor8
color.primitive.ansi.9#ab1612observedblocked#ab1612observedhistorical-only#ab1612observedblockedcolor9
color.primitive.ansi.10#ad2721observedblocked#ad2721observedhistorical-only#ad2721observedblockedcolor10
color.primitive.ansi.11#b37175observedblocked#b37175observedhistorical-only#b37175observedblockedcolor11
color.primitive.ansi.12#871f19observedblocked#871f19observedhistorical-only#871f19observedblockedcolor12
color.primitive.ansi.13#e82132observedblocked#e82132observedhistorical-only#e82132observedblockedcolor13
color.primitive.ansi.14#e0292fobservedblocked#e0292fobservedhistorical-only#e0292fobservedblockedcolor14
color.primitive.ansi.15#a3676bobservedblocked#a3676bobservedhistorical-only#a3676bobservedblockedcolor15

Actions

Buttons, links, icon buttons, button groups, segmented controls, destructive treatment.

Button button

  • Family: Actions
  • Maturity: stable
  • Priority: R1
  • Since: 0.1.0
  • Native control: native <button type="button">APG pattern
  • specified
  • demonstrated
  • tested

The native push button in the four action tones; primary is the only filled button at rest, destructive fills on hover and always needs a confirmation or an undo.

Report an issue with this component

Open component workbench

View source and copy recipe · Download standalone example

Tokens

PartRoleValueUse
root.bgcolor.action.primary.bgapproveduse#7d1310Primary button fill; D-026 darkened it off color12, which stays fixed as heritage ANSI 12.
root.textcolor.action.primary.textobserveduse#f4eeeePrimary button text (9.28:1).
root.bordercolor.action.primary.borderobserveduse#9e231fPrimary button border.
root.bg-hovercolor.action.primary.hover-bgobserveduse#911410Primary button hover (7.92:1 with prose).
root.bg-activecolor.action.primary.pressed-bgobserveduse#630f0dPrimary button pressed.
root.ringcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
secondary.bgcolor.action.secondary.bgobservedusergb(0 0 0 / 0%)Secondary button has no fill.
secondary.textcolor.action.secondary.textobserveduse#ffa2a7Secondary button text.
secondary.bordercolor.action.secondary.borderobserveduse#a3676bSecondary button border (meets 3:1).
secondary.bg-hovercolor.action.secondary.hover-bgobserveduse#630f0dSecondary button hover.
secondary.bg-activecolor.action.secondary.pressed-bgobserveduse#420f0cSecondary button pressed.
secondary.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
tertiary.textcolor.action.tertiary.textobserveduse#e99499Ghost and icon button text.
tertiary.bg-hovercolor.action.tertiary.hover-bgobserveduse#1c0a09Ghost and icon button hover.
tertiary.bg-activecolor.interaction.pressed.bgobserveduse#420f0cPressed fill.
destructive.textcolor.action.destructive.textobserveduse#f73f35Destructive button text at rest (outline style).
destructive.bordercolor.action.destructive.borderobserveduse#e53935Destructive button border.
destructive.bg-hovercolor.action.destructive.hover-bgobserveduse#dc282eDestructive button hover fill.
destructive.text-hovercolor.action.destructive.hover-textobserveduse#f9faf9Destructive button text on hover (4.58:1).
destructive.bg-activecolor.action.destructive.pressed-bgobserveduse#ae1914Destructive button pressed fill.
destructive.bg-filledcolor.action.destructive.filled-bgobserveduse#dc282eConfirm-dialog destructive fill.
destructive.text-filledcolor.action.destructive.filled-textobserveduse#f9faf9Text on the destructive fill.
root.border-activecolor.action.primary.borderobserveduse#9e231fPrimary button border.
secondary.border-activecolor.border.activeobserveduse#e53935Active or focused control border.
tertiary.border-activecolor.border.activeobserveduse#e53935Active or focused control border.
destructive.border-activecolor.action.destructive.borderobserveduse#e53935Destructive button border.
root.text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
root.bg-disabledcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
root.border-disabledcolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
loading.glyphcolor.action.primary.textobserveduse#f4eeeePrimary button text (9.28:1).

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StatePrimarySecondaryTertiaryDestructive
default
hover
focus-visible
active
disabled
loading

Purpose

The push button that triggers an action. Four tones and no more: primary is the single filled button in a view, secondary is the outline for every other action, tertiary is the ghost for low-emphasis and toolbar actions, destructive is an outline in the danger tone that fills on hover. A destructive button also requires a confirmation step or an undo affordance; the colour is not the safeguard. Navigation is a link, not a button.

Anatomy

A native <button>; optional leading icon; the label. The loading glyph occupies the icon slot so the size never changes. A filled destructive modifier (.button-destructive-filled, color.action.destructive.filled-bg with color.action.destructive.filled-text) exists only inside confirm dialogs.

States

StateVisualNon-colour channel
defaultprimary: color.action.primary.bg fill, color.action.primary.text, 1px color.action.primary.border; secondary: 1px color.action.secondary.border, color.action.secondary.text; tertiary: color.action.tertiary.text, no border; destructive: 1px color.action.destructive.border, color.action.destructive.text
hoverprimary → color.action.primary.hover-bg; secondary → color.action.secondary.hover-bg; tertiary → color.action.tertiary.hover-bg; destructive fills color.action.destructive.hover-bg with color.action.destructive.hover-textcursor: pointer; hover-capable pointers only
focus-visiblering 1px dashed at −2px: color.interaction.focus.ring-container on the primary fill, color.interaction.focus.ring on the outline tones, color.action.destructive.hover-text on the destructive hover fillthe ring
activeprimary → color.action.primary.pressed-bg; secondary → color.action.secondary.pressed-bg; tertiary → color.interaction.pressed.bg; destructive → color.action.destructive.pressed-bg; primary keeps color.action.primary.border, secondary and tertiary use color.border.active, destructive keeps color.action.destructive.border (D-015)border change on secondary and tertiary; no translation or scale
disabledcolor.text.disabled on color.interaction.disabled.bg with 1px color.border.disabled, every tone alike; no hover or active stylingdisabled; cursor: not-allowed; never opacity
loadingsize unchanged; the static glyph replaces the icon; the button keeps its tone and stays focusable but ignores activationglyph; aria-busy

Precedence: disabled > loading > active > hover; focus-visible is always drawn.

The primary edge stays unchanged when pressed (D-015). Its exact role is root.border-active in the part map, just as root.border names the rest edge. The default-tone state contrast map checks the text against the pressed fill; it does not substitute color.border.active for this unchanged edge. The existing primary-action contrast declaration identifies the labelled button through its text, not through the fill’s boundary.

Keyboard

Native. Enter and Space activate; nothing else is bound. A loading button stays in the tab order so focus is not lost mid-action, and the host ignores activation until aria-busy clears.

Accessibility

The accessible name is the label text; an icon-only button is the icon-button component. Never aria-disabled on a button that should be skipped, and never disabled on a button whose reason a user needs to discover: prefer keeping it enabled and explaining on activation. Contrast: primary 9.28:1, secondary 10.37:1, tertiary 8.65:1, destructive 5.40:1 at rest and 4.58:1 on the hover fill; every outline border ≥ 4.45:1; rings ≥ 3:1 on every fill they sit on. The target is at least 24×24 CSS pixels in compact density with 4px between neighbours.

Portability

Fill, border and outline express every state; no gradient, shadow or transform is used. Hosts without dashed outlines draw a solid 1px ring in the same colour and record the deviation. Hosts that cannot recolour the ring on a fill draw it outside the fill at +1px.

Non-examples

Rounded corners or pill shapes. Two filled buttons in one view. A red filled destructive button at rest. A hover that only changes text colour. Translating or scaling the button on press. A spinner inside the button. Disabling with opacity. A <div> or <a> styled as a button. A gradient or shadow to suggest depth.

Keys

KeyAction
Tab / Shift+TabMoves focus to and from the button in document order.
Enter / SpaceActivates (native); Space activates on key up.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Related: icon-button link button-group segmented-control dialog

Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

Icon button icon-button

  • Family: Actions
  • Maturity: stable
  • Priority: R1
  • Since: 0.1.0
  • Native control: native <button> with aria-label; aria-pressed for the toggleAPG pattern
  • specified
  • demonstrated

A square ghost button whose only content is a 16px line icon; it always carries an accessible name and, as a toggle, aria-pressed.

Report an issue with this component

Tokens

PartRoleValueUse
root.bgcolor.action.secondary.bgobservedusergb(0 0 0 / 0%)Secondary button has no fill.
root.textcolor.action.tertiary.textobserveduse#e99499Ghost and icon button text.
root.bg-hovercolor.action.tertiary.hover-bgobserveduse#1c0a09Ghost and icon button hover.
root.bg-activecolor.interaction.pressed.bgobserveduse#420f0cPressed fill.
root.border-activecolor.border.activeobserveduse#e53935Active or focused control border.
root.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
root.bg-toggledcolor.interaction.selection.bgapproveduse#531310Selected row, tab, workspace; D-027 recessed the fill, leaving the 2px indicator and the check to carry selection.
root.text-toggledcolor.interaction.selection.textobserveduse#f4eeeeText on the selection.
root.border-toggledcolor.border.selected-indicatorobserveduse#e539352px indicator bar on the selected tab or nav item.
root.ring-toggledcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
root.text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
root.bg-disabledcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
root.border-disabledcolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
icon.strokecolor.icon.defaultobserveduse#e99499Icons take the text colour (currentColor in CSS).

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateActionToggle
default
hover
focus-visible
active
disabled
toggled
toggled+focus-visible

Purpose

A button whose whole content is one icon: toolbar actions, close and clear affordances, and boolean toggles such as pin, mute or wrap. It is the tertiary tone constrained to a square. Any icon button needs an accessible name and a tooltip; if the label must be visible it is a button.

Anatomy

A native <button> sized to the density control height in both axes with a single 16px inline SVG inside. The border is 1px and transparent at rest so the active and toggled borders do not shift the layout.

States

StateVisualNon-colour channel
defaultcolor.action.tertiary.text icon on nothing; transparent 1px border
hoverbackground → color.action.tertiary.hover-bgcursor: pointer; hover-capable pointers only
focus-visiblering 1px dashed color.interaction.focus.ring at −2pxthe ring
activebackground → color.interaction.pressed.bg; border → color.border.activeborder change; no translation
disabledcolor.text.disabled on color.interaction.disabled.bg with 1px color.border.disabled; no hoverdisabled; cursor: not-allowed
toggledfill color.interaction.selection.bg with color.interaction.selection.text; border color.border.selected-indicator; the icon draws in its filled formaria-pressed="true"; the filled icon shape; the border
toggled+focus-visiblethe selection fill and a ring in color.interaction.focus.ring-containerboth visible at once

Precedence: disabled > toggled > active > hover; focus-visible is always drawn.

Keyboard

Native. The toggle variant flips aria-pressed on Enter and Space and does not move focus. Inside a toolbar the host applies roving tabindex; the button itself binds nothing.

Accessibility

aria-label (or aria-labelledby) names the button; the tooltip repeats the same text and is not the name. The SVG is aria-hidden="true" and focusable="false". A toggle uses aria-pressed, whose value is announced; the name never changes with the state (“Mute”, not “Mute” / “Unmute”). Contrast: icon 8.65:1 at rest, 12.47:1 on the selection fill; ring 4.69:1, container ring 7.48:1 on the selection fill. Target ≥ 24×24 CSS pixels with 4px between neighbours in compact density.

Portability

Square, fill, border, outline; the icon is currentColor so it follows every state without its own colour. Hosts without inline SVG use their icon theme at 16px and record the substitution. Hosts without dashed outlines draw a solid 1px ring.

Non-examples

A circle. An icon button without an accessible name. A toggle that changes its label instead of aria-pressed. A hover that recolours the icon alone. An emoji or icon-font glyph in place of the SVG. A toggled state shown by colour alone with a line icon. A shadow or scale on press.

Keys

KeyAction
Tab / Shift+TabMoves focus to and from the button.
Enter / SpaceActivates; the toggle variant flips aria-pressed.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Related: button toolbar tooltip segmented-control

Stress fixtures: FX-320 FX-ZOOM-200 FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

Button group button-group

  • Family: Actions
  • Maturity: stable
  • Priority: R2
  • Since: 1.0.0
  • Native control: Labelled native button group
  • specified
  • demonstrated

Related independent native actions with individual tab stops.

Report an issue with this component

Tokens

PartRoleValueUse
root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
root.textcolor.text.defaultobserveduse#e99499Interface and body text.
root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
heading.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
secondary.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
control.bgcolor.surface.inputapproveduse#000000Form-control fill.
control.focuscolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
dependency.role-border-width-defaultborder.width.defaultobserveduse1pxEvery border is 1px.
dependency.role-color-border-disabledcolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
dependency.role-color-interaction-disabled-bgcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
dependency.role-color-text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
dependency.role-density-comfortable-control-heightdensity.comfortable.control-heightobserveduse32px
dependency.role-density-compact-control-heightdensity.compact.control-heightobserveduse24px
dependency.role-radius-noneradius.noneobserveduse0pxThe only radius. Nothing is rounded.
dependency.role-space-12space.12observeduse12px
dependency.role-space-2space.2observeduse2px
dependency.role-space-4space.4observeduse4px
dependency.role-space-8space.8observeduse8px

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateDefault
default
focus-visible
disabled

Purpose

Group related independent actions without turning them into an exclusive choice. Each button keeps its native type, accessible name and tab stop. Application effects belong to the host.

Anatomy

  • group: Labelled group that wraps its buttons.
  • actions: Independent buttons in source order.

States

StatePresentationNon-colour channel
defaultNamed content on the default surface.Native text and structure.
focus-visibleDashed focus ring.Native keyboard focus position.
disabledDisabled semantic foreground, background and border at full opacity.Native disabled state blocks activation.

Keyboard

  • Tab / Shift+Tab: Visit each enabled button.
  • Enter / Space: Activate the focused native button.

Accessibility

Use role=group with a visible or accessible label. Buttons retain distinct names and native disabled behavior. A button group does not add arrow-key navigation or selection semantics.

Portability

Wrap labels and actions without changing source order. Use logical spacing in RTL. Preserve native target sizes at both densities; only bounded data regions may scroll horizontally. Use equivalent native semantics and approved roles; record any unsupported behavior as a mapping deviation. The host owns application data, persistence, permissions and services.

Non-examples

Unlabelled controls, color-only status, drag-only operations, hidden required instructions, stolen focus or an invented service success.

Keys

KeyAction
Tab / Shift+TabVisit each enabled button.
Enter / SpaceActivate the focused native button.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Stress fixtures: FX-320 FX-360 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

Segmented control segmented-control

  • Family: Actions
  • Maturity: stable
  • Priority: R2
  • Since: 1.0.0
  • Native control: Native fieldset, legend and radio inputs
  • specified
  • demonstrated

A short exclusive choice implemented with labelled native radios.

Report an issue with this component

Tokens

PartRoleValueUse
root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
root.textcolor.text.defaultobserveduse#e99499Interface and body text.
root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
heading.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
secondary.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
control.bgcolor.surface.inputapproveduse#000000Form-control fill.
control.focuscolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
dependency.role-border-width-defaultborder.width.defaultobserveduse1pxEvery border is 1px.
dependency.role-border-width-emphasisborder.width.emphasisobserveduse2pxSelected indicator, sticky header rule, invalid border.
dependency.role-color-action-primary-bgcolor.action.primary.bgapproveduse#7d1310Primary button fill; D-026 darkened it off color12, which stays fixed as heritage ANSI 12.
dependency.role-color-action-primary-hover-bgcolor.action.primary.hover-bgobserveduse#911410Primary button hover (7.92:1 with prose).
dependency.role-color-action-primary-textcolor.action.primary.textobserveduse#f4eeeePrimary button text (9.28:1).
dependency.role-color-border-disabledcolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
dependency.role-color-interaction-disabled-bgcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
dependency.role-color-interaction-focus-ring-containercolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
dependency.role-color-interaction-hover-bgcolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
dependency.role-color-interaction-selection-bgcolor.interaction.selection.bgapproveduse#531310Selected row, tab, workspace; D-027 recessed the fill, leaving the 2px indicator and the check to carry selection.
dependency.role-color-interaction-selection-textcolor.interaction.selection.textobserveduse#f4eeeeText on the selection.
dependency.role-color-status-danger-bordercolor.status.danger.borderobserveduse#e53935Danger border, 2px on invalid inputs.
dependency.role-color-status-danger-textcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).
dependency.role-color-text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
dependency.role-density-comfortable-control-heightdensity.comfortable.control-heightobserveduse32px
dependency.role-density-compact-control-heightdensity.compact.control-heightobserveduse24px
dependency.role-focus-offsetfocus.offsetobserveduse-2pxoutline-offset for controls.
dependency.role-focus-ringfocus.ringobserveduse1px dashed #e53935outline on controls and rows.
dependency.role-font-line-height-ui-mdfont.line-height.ui-mdobserveduse18px
dependency.role-font-line-height-ui-smfont.line-height.ui-smobserveduse16px
dependency.role-font-size-ui-mdfont.size.ui-mdobserveduse13px
dependency.role-font-size-ui-smfont.size.ui-smobserveduse12px
dependency.role-icon-size-mdicon.size.mdobserveduse16px
dependency.role-radius-noneradius.noneobserveduse0pxThe only radius. Nothing is rounded.
dependency.role-space-12space.12observeduse12px
dependency.role-space-16space.16observeduse16px
dependency.role-space-2space.2observeduse2px
dependency.role-space-24space.24observeduse24px
dependency.role-space-4space.4observeduse4px
dependency.role-space-8space.8observeduse8px

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateDefault
default
View density
checked
focus-visible
disabled

Purpose

Choose one value from a short labelled set using native radios. This changes a value; use tabs for associated content panels. Native names, required checks, disabled fieldsets and form reset are preserved.

Anatomy

  • fieldset: Legend names the choice.
  • options: Native radios sharing one name, each with a visible label.

States

StatePresentationNon-colour channel
defaultNamed content on the default surface.Native text and structure.
checkedSelected fill and a check indicator.Native checked state.
focus-visibleDashed focus ring.Native keyboard focus position.
disabledDisabled semantic foreground, background and border at full opacity.Native disabled state blocks activation.

Keyboard

  • Tab / Shift+Tab: Enter the native radio group once and leave it.
  • Arrow keys / Space: Use native radio selection and wrapping.

Accessibility

Keep native radios and labels. A checked value has both a visible native indicator and its programmatic checked state. Do not hide all radios from assistive technology or put role=tab on the labels.

Portability

Wrap labels and actions without changing source order. Use logical spacing in RTL. Preserve native target sizes at both densities; only bounded data regions may scroll horizontally. Use equivalent native semantics and approved roles; record any unsupported behavior as a mapping deviation. The host owns application data, persistence, permissions and services.

Non-examples

Unlabelled controls, color-only status, drag-only operations, hidden required instructions, stolen focus or an invented service success.

Keys

KeyAction
Tab / Shift+TabEnter the native radio group once and leave it.
Arrow keys / SpaceUse native radio selection and wrapping.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Stress fixtures: FX-320 FX-360 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

Basic forms

Text, password, number, search, textarea, select, checkbox, radio, switch, range, fieldsets, labels, help text, validation.

Field field

  • Family: Basic forms
  • Maturity: stable
  • Priority: R1
  • Since: 0.1.0
  • Native control: native <label for> with aria-describedby on the controlAPG pattern
  • specified
  • demonstrated

The label, control, help and message wrapper that every form control sits in; it fixes the stacking order, the required mark, the description links and the invalid message.

Report an issue with this component

Tokens

PartRoleValueUse
root.textcolor.text.defaultobserveduse#e99499Interface and body text.
label.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
label.required-markcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).
control.bgcolor.surface.inputapproveduse#000000Form-control fill.
control.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
control.border-invalidcolor.status.danger.borderobserveduse#e53935Danger border, 2px on invalid inputs.
control.text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
control.bg-disabledcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
control.border-disabledcolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
help.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
message.textcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateDefault
default

Letters, digits and hyphens; shown in the bar.

✕ Hyphens cannot start or end the name.

required
invalid
disabled

Purpose

The wrapper that gives every control the same label, description and error treatment. Controls specify their box; the field specifies what sits above and below it and how they are linked. Every form control in this theme is rendered inside a field or a fieldset.

Anatomy

Label above the control, always stacked; the control slot; help text below in color.text.muted; the validation message, which takes the help slot visually while help stays in the DOM and aria-describedby lists both. The required mark is present in the markup and shown only when the control is required.

States

StateVisualNon-colour channel
defaultlabel color.text.bright; help color.text.muted; control as its own component
required* after the label in color.status.danger.text plus visually hidden “required”required attribute; the mark
invalidthe control’s 2px color.status.danger.border; message with the ✕ glyph in color.status.danger.text; help visually hiddenborder width 1 → 2px; glyph; aria-invalid
disabledlabel and control text color.text.disabled; control color.interaction.disabled.bg with 1px color.border.disabled; help unchangeddisabled; cursor: not-allowed

Precedence: disabled > invalid; required is shown in every state.

Keyboard

The field adds no behaviour. Clicking the label focuses the control (native for). Focus order inside the field is the control’s own.

Accessibility

Every control has a programmatic label; placeholder text is never the label. Help and message are linked with aria-describedby in that order so the description is read before the error. aria-invalid="true" is set only after interaction or submit. The message keeps its glyph so the state is not colour-only. Contrast: label 10.10:1, help 5.66:1, message 5.26:1 on the panel surface; disabled label 3.24:1 (exempt).

Portability

Plain block layout; the only pseudo-element is nothing, the mark is real markup. Hosts without aria-describedby put help and message in the control’s tooltip or accessible description and record it.

Non-examples

A floating label inside the control. A label to the left of the control. Placeholder text as the only label. An error shown by a red border alone. A message that replaces the help text in the DOM. A required mark that is only a colour change. An asterisk with no text alternative. Two controls in one field.

Keys

KeyAction
Tab / Shift+TabReaches the control; the label is not a tab stop.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Related: text-field textarea select checkbox radio-group fieldset number-field search-field

Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-DENSITY FX-STATE-MATRIX

Text field text-field

  • Family: Basic forms
  • Maturity: stable
  • Priority: R1
  • Since: 0.1.0
  • Native control: native <input> with <label>APG pattern
  • specified
  • demonstrated
  • tested

Single-line free-text entry, covering every native input type that renders as a line box; search, number and password are variants, not separate components.

Report an issue with this component

Open component workbench

View source and copy recipe · Download standalone example

Tokens

PartRoleValueUse
root.bgcolor.surface.inputapproveduse#000000Form-control fill.
root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
root.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
root.border-focuscolor.border.activeobserveduse#e53935Active or focused control border.
root.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
root.ring-invalidcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
root.border-invalidcolor.status.danger.borderobserveduse#e53935Danger border, 2px on invalid inputs.
root.border-disabledcolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
root.bg-disabledcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
root.border-readonlycolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
input.textcolor.text.defaultobserveduse#e99499Interface and body text.
input.text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
input.placeholdercolor.text.placeholderapproveduse#a3676bPlaceholder text, italic; D-027 darkened it to 4.71:1, just clear of the 4.5:1 floor.
input.caretcolor.code.caretobserveduse#e99499Caret (Xresources *cursorColor).
input.selection-bgcolor.interaction.text-selection.bgobserveduse#911410::selection background.
input.selection-textcolor.interaction.text-selection.textobserveduse#f4eeee::selection text.
label.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
label.required-markcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).
help.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
message.textcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).
affix.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
affix.bordercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
action.textcolor.action.tertiary.textobserveduse#e99499Ghost and icon button text.
action.bg-hovercolor.action.tertiary.hover-bgobserveduse#1c0a09Ghost and icon button hover.
loading.glyphcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateTextPassword with revealSearch with clearNumber with stepperWith prefix and suffix
default

Shown on your profile and in the window title.

✕ Use 2 to 32 characters.

Twelve characters or more; spaces allowed.

✕ Too short.

Escape clears the query.

✕ No such path.

Up and Down step by one; Shift steps by ten.

✕ Between 0 and 64.

Host only; the path is fixed.

✕ Not a valid host.

hover
focus-visible
placeholder-shown
filled
required
invalid
invalid+focus-visible
invalid+hover
disabled
disabled+filled
read-only
read-only+focus-visible
loading

Purpose

Single-line free-text entry. Every native type that renders as a line box (text, password, search, number, email, url, tel) is this component; date and time inputs are the date-picker and time-picker components because their popups are host surfaces.

Anatomy

Label above the control; the control box; optional prefix and suffix inside the box separated by a color.border.divider rule; the input; optional trailing actions (clear, reveal, stepper); help text below; the validation message, which takes the help slot visually while help stays in the DOM and aria-describedby lists both.

States

StateVisualNon-colour channel
default1px color.border.control on color.surface.input; text color.text.default
hoverbackground → color.interaction.hover.bg; border unchangedcursor: text
focus-visibleborder → color.border.active; ring 1px dashed color.interaction.focus.ring at −2pxthe ring
placeholder-shownplaceholder in color.text.placeholder, italicitalic
filledas default with a value
required* after the label in color.status.danger.text plus visually hidden “required”required attribute; the mark
invalidborder 2px color.status.danger.border; message with the ✕ glyphborder width 1 → 2px; glyph; aria-invalid
invalid+focus-visiblethe 2px danger border and a 1px dashed ring in color.interaction.focus.ring-container at −4px (the control form, recoloured; never the 2px container form)double boundary
invalid+hoveras invalid with the hover backgroundcursor
disabledtext color.text.disabled; border color.border.disabled; background color.interaction.disabled.bg; no hover; the label and help keep their coloursdisabled; cursor: not-allowed
disabled+filledas disabled with a valuedisabled
read-onlyno box: 1px dotted color.border.divider bottom edge on color.surface.canvas; text color.text.default; focusable and selectablereadonly; dotted edge
read-only+focus-visiblethe dotted color.border.divider edge unchanged, plus the dashed ring at −2pxthe ring
loadingsize unchanged; a static glyph in color.text.muted inside the box after the input and before any trailing action; input remains editableglyph; aria-busy

Precedence when several apply: disabled > loading > invalid > hover; focus-visible is always drawn.

Keyboard

Focus order is label (not focusable) → input → clear or reveal → stepper buttons. The clear button is type="button" with aria-label="Clear <label>"; the reveal button toggles type between password and text and its own aria-pressed. Escape in the search variant clears a non-empty value.

Accessibility

A programmatic label is required (<label for>). Help and message are linked through aria-describedby in that order. aria-invalid="true" is set only after the user interacted with the field or submitted the form, never on first paint. The message is announced on submit through the form’s live region, not on every keystroke. Contrast: text 8.65:1 on the input surface, placeholder 5.81:1, disabled text 3.33:1 (exempt), control border 4.45:1 (≥ 3:1), invalid border 4.69:1, danger message 5.40:1. The box is at least 24×24 CSS pixels in compact density.

Portability

Everything is expressible with border, background and outline; the only pseudo-element is the required mark. Toolkits without dashed outlines draw a solid 1px ring in the same colour and record the deviation. Toolkits without a read-only style treat read-only as default text and record it.

Non-examples

Rounded corners. A floating or animated label. An underline-only field with no box. A glow instead of the dashed ring. Placeholder text in red. Disabling by opacity. Using colour alone for the invalid state. A hover that changes the text colour.

Keys

KeyAction
Tab / Shift+TabMoves focus in and out; affix actions (clear, reveal, stepper) are separate tab stops after the input.
EscapeClears the value in the search variant when it is non-empty; otherwise nothing.
EnterSubmits the owning form (native).
Up / DownNumber variant steps by the step attribute; Shift multiplies by ten.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Related: textarea select combobox search-field number-field field

Stress fixtures: FX-LONG FX-320 FX-360 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

Textarea textarea

  • Family: Basic forms
  • Maturity: stable
  • Priority: R1
  • Since: 0.1.0
  • Native control: native <textarea> with <label>APG pattern
  • specified
  • demonstrated

Multi-line free-text entry in the same box as the text field; resizes vertically only and can show a character count.

Report an issue with this component

Tokens

PartRoleValueUse
root.bgcolor.surface.inputapproveduse#000000Form-control fill.
root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
root.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
root.border-focuscolor.border.activeobserveduse#e53935Active or focused control border.
root.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
root.ring-invalidcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
root.border-invalidcolor.status.danger.borderobserveduse#e53935Danger border, 2px on invalid inputs.
root.border-disabledcolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
root.bg-disabledcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
root.border-readonlycolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
root.bg-readonlycolor.surface.canvasapproveduse#000000Page and terminal background.
input.textcolor.text.defaultobserveduse#e99499Interface and body text.
input.text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
input.placeholdercolor.text.placeholderapproveduse#a3676bPlaceholder text, italic; D-027 darkened it to 4.71:1, just clear of the 4.5:1 floor.
input.caretcolor.code.caretobserveduse#e99499Caret (Xresources *cursorColor).
input.selection-bgcolor.interaction.text-selection.bgobserveduse#911410::selection background.
input.selection-textcolor.interaction.text-selection.textobserveduse#f4eeee::selection text.
label.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
label.required-markcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).
help.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
count.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
count.text-overcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).
message.textcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateDefaultWith character count
default

Plain text; one change per line.

✕ Say why, not only what.

46 / 200

Counts characters, not bytes.

✕ Over the limit.

hover
focus-visible
placeholder-shown
filled
required
invalid
invalid+focus-visible
disabled
read-only

Purpose

Free text longer than a line: descriptions, messages, notes. It shares the text field’s box, states and message so a form reads as one system. Code goes in the code-editor component, not a textarea.

Anatomy

Label above; the box with the native <textarea> inside, at least three rows tall, resizable downwards only; the optional count; help; the validation message that takes the help slot visually while help stays in the DOM.

States

StateVisualNon-colour channel
default1px color.border.control on color.surface.input; text color.text.default
hoverbackground → color.interaction.hover.bg; border unchangedcursor: text
focus-visibleborder → color.border.active; ring 1px dashed color.interaction.focus.ring at −2pxthe ring
placeholder-shownplaceholder in color.text.placeholder, italicitalic
filledas default with a value
required* after the label in color.status.danger.text plus visually hidden “required”required; the mark
invalidborder 2px color.status.danger.border; message with the ✕ glyph; a count past its limit turns color.status.danger.text with the glyphborder width 1 → 2px; glyph; aria-invalid
invalid+focus-visiblethe 2px danger border and the ring in color.interaction.focus.ring-container at −4pxdouble boundary
disabledtext color.text.disabled; border color.border.disabled; background color.interaction.disabled.bg; no resize handledisabled; cursor: not-allowed
read-onlyno box: 1px dotted color.border.divider bottom edge on color.surface.canvas; no resize handle; selectablereadonly; dotted edge

Precedence: disabled > invalid > hover; focus-visible is always drawn.

Keyboard

Native editing. Enter inserts a line break and never submits. Tab leaves the control; a host that needs literal tabs provides a separate command and documents it. The count is not focusable.

Accessibility

A programmatic label is required. Help, count and message are linked through aria-describedby in that order. The count is aria-live="polite" and throttled so it does not announce every keystroke; the limit is stated in the help text so it is known before typing. aria-invalid="true" only after interaction or submit. Contrast as the text field: text 8.65:1, placeholder 5.81:1, control border 4.45:1, invalid border 4.69:1, message 5.40:1.

Portability

Border, background, outline and resize: vertical. Hosts without a resize handle grow the box with content up to a maximum and record it. Hosts without dashed outlines draw a solid 1px ring.

Non-examples

Horizontal or free resizing. A box narrower than its label column. A count that only changes colour past the limit. A glow instead of the dashed ring. Rounded corners. An auto-growing box with no maximum. Tab inserting a character. Placeholder text as the label. Disabling by opacity.

Keys

KeyAction
Tab / Shift+TabMoves focus in and out; Tab never inserts a tab character.
EnterInserts a line break; never submits.
Ctrl+Enter / Cmd+EnterMay submit the owning form when the host binds it; announced in the help text.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Related: text-field field code-editor

Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-OVERFLOW FX-STATE-MATRIX

Select select

  • Family: Basic forms
  • Maturity: stable
  • Priority: R1
  • Since: 0.1.0
  • Custom widget: Select-only combobox with listbox popup; multiple variant is a multiselectable listboxAPG pattern
  • specified
  • demonstrated
  • tested

A themed single-choice combobox or multiple-choice list backed by a native select for forms and the no-JavaScript fallback.

Report an issue with this component

Tokens

PartRoleValueUse
root.bgcolor.surface.inputapproveduse#000000Form-control fill.
root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
root.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
root.border-focuscolor.border.activeobserveduse#e53935Active or focused control border.
root.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
root.ring-invalidcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
root.border-invalidcolor.status.danger.borderobserveduse#e53935Danger border, 2px on invalid inputs.
root.border-disabledcolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
root.bg-disabledcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
control.textcolor.text.defaultobserveduse#e99499Interface and body text.
control.text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
chevron.strokecolor.icon.defaultobserveduse#e99499Icons take the text colour (currentColor in CSS).
option.bgcolor.surface.raisedapproveduse#160b0bSticky headers, menus, popovers; D-027 recessed it so an open list reads as depth rather than a lighter panel.
option.textcolor.text.defaultobserveduse#e99499Interface and body text.
option.bg-selectedcolor.interaction.selection.bgapproveduse#531310Selected row, tab, workspace; D-027 recessed the fill, leaving the 2px indicator and the check to carry selection.
option.text-selectedcolor.interaction.selection.textobserveduse#f4eeeeText on the selection.
group.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
label.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
label.required-markcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).
help.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
message.textcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateSingleWith option groupsMultiple
default

New windows open here.

✕ Choose a workspace.

Fallbacks use recorded size-adjust metrics.

✕ That font is not installed.

Click or Space toggles an option; Shift+arrows selects a range. The native fallback uses Ctrl/Command+click.

✕ Choose at least one output.

hover
focus-visible
required
invalid
invalid+focus-visible
disabled

Purpose

Choosing one option, or several, from a fixed list. D-025 requires theme-owned choice surfaces in web applications. The native select remains the form-value and constraint source. A searchable or asynchronous list is the separate combobox component.

Anatomy

Label above; a theme-owned trigger and listbox for single choices, or an always-visible multiselectable listbox. Each selected option has a check mark and the canonical selection fill. The hidden native <select> retains its name, options, current values and defaults. Help and validation are linked to the visible control. Without JavaScript the original native control is visible.

States

StateVisualNon-colour channel
default1px color.border.control on color.surface.input; value color.text.default; chevron color.icon.defaultthe chevron
hoverbackground → color.interaction.hover.bg; border unchangedcursor: default; hover-capable pointers only
focus-visibleborder → color.border.active; ring 1px dashed color.interaction.focus.ring at −2pxthe ring
required* after the label in color.status.danger.text plus visually hidden “required”required; the mark
invalidborder 2px color.status.danger.border; message with the ✕ glyphborder width 1 → 2px; glyph; aria-invalid
invalid+focus-visiblethe 2px danger border and the ring in color.interaction.focus.ring-container at −4pxdouble boundary
disabledtext and chevron color.text.disabled; border color.border.disabled; background color.interaction.disabled.bgdisabled; cursor: not-allowed

Inside the theme-owned list, a selected option is color.interaction.selection.bg with color.interaction.selection.text and group labels are color.text.muted on color.surface.raised. Precedence: disabled > invalid > hover; focus-visible is always drawn.

Keyboard

The single control follows the select-only combobox pattern: arrows open and move the active option, Home/End reach the ends, typing finds an option, and Enter/Space commits. Escape and Tab close without committing. Multiple choices use arrows, Space or click to toggle, Shift with arrows for a range, and Ctrl/Command+A to select or clear all enabled choices. No modifier is required for ordinary multiple selection. The native fallback uses host keyboard behavior.

Accessibility

A programmatic label is required; the first option is a real choice or a placeholder option that is disabled and selected with text such as “Choose a workspace”, never an empty string. aria-invalid="true" only after interaction or submit. Help and message through aria-describedby. The themed popup uses the declared contrast roles. The visible control receives the label, required/invalid state and descriptions. A failed native constraint focuses that visible control and exposes a theme-owned error. Disabled options, optgroups and fieldsets remain unavailable. Current values and defaults survive reconnection, programmatic updates and form reset. Automated evidence records its actual environments; it does not imply a manual screen-reader pass.

Portability

Use the packaged behavior and complete copy closure for web implementations. The supported enhancement can apply the same renderer to existing selects without moving them or duplicating form values. Native platforms keep the mappings listed above; no-JavaScript pages expose the native fallback.

Non-examples

An unthemed browser popup presented as a fully themed implementation. A background-image chevron in a literal colour. Rounded corners. A select whose first option is blank. A select that triggers navigation on change. Invalid shown by colour alone. A glow instead of the ring. Disabling by opacity.

Keys

KeyAction
Tab / Shift+TabMoves focus in and out.
Space / Alt+DownOpens the themed popup without committing a choice.
Up / DownOpens the single list or moves its active option; Enter or Space commits. In the multiple list, moves the active option.
TypingMoves to an enabled option starting with the typed characters.
Space / click; Shift+Up / Shift+Down; Ctrl+Command+AToggles a multiple option; extends a range; selects or clears all enabled options.
Escape / TabCloses the single popup without committing the active option.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Related: combobox multiselect text-field field menu

Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

Checkbox checkbox

  • Family: Basic forms
  • Maturity: stable
  • Priority: R1
  • Since: 0.1.0
  • Native control: native <input type="checkbox"> with <label>; fieldset and legend for a groupAPG pattern
  • specified
  • demonstrated
  • tested

The native checkbox drawn as a 16px square that fills with the primary action colour and a ✓ or – glyph; single, or a fieldset group of independent choices.

Report an issue with this component

Open component workbench

Tokens

PartRoleValueUse
box.bgcolor.surface.inputapproveduse#000000Form-control fill.
box.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
box.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
box.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
box.bg-checkedcolor.action.primary.bgapproveduse#7d1310Primary button fill; D-026 darkened it off color12, which stays fixed as heritage ANSI 12.
box.bg-checked-hovercolor.action.primary.hover-bgobserveduse#911410Primary button hover (7.92:1 with prose).
box.glyphcolor.action.primary.textobserveduse#f4eeeePrimary button text (9.28:1).
box.ring-checkedcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
box.border-invalidcolor.status.danger.borderobserveduse#e53935Danger border, 2px on invalid inputs.
box.bg-disabledcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
box.border-disabledcolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
box.glyph-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
text.defaultcolor.text.defaultobserveduse#e99499Interface and body text.
text.disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
legend.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
legend.required-markcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).
message.textcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateSingleGroup
default

✕ Confirm before continuing.

Bar modules required

✕ Choose at least one module.

hover
focus-visible
checked
mixed
checked+focus-visible
checked+disabled
disabled
invalid
required

Purpose

An independent yes/no choice, or several of them under one legend. A setting that takes effect immediately is a switch; one of several exclusive options is a radio group. A parent checkbox over a partly selected set shows the mixed state.

Anatomy

The box is the native input itself with appearance: none, so it keeps native focus, form and keyboard behaviour. The ✓ and – glyphs are inline SVGs stacked over it in the same 16px cell. The option row is a <label>, at least 24px tall, which makes the text part of the target. A group is a <fieldset> with a <legend>.

States

StateVisualNon-colour channel
default16px box, 1px color.border.control on color.surface.input; text color.text.default
hoverbox background → color.interaction.hover.bg; checked box → color.action.primary.hover-bgcursor: pointer; hover-capable pointers only
focus-visiblering 1px dashed color.interaction.focus.ring at −2px around the boxthe ring
checkedbox fills color.action.primary.bg; ✓ in color.action.primary.text; border stays color.border.controlthe ✓ glyph; checked
mixedbox fills color.action.primary.bg; – in color.action.primary.textthe – glyph; indeterminate / aria-checked="mixed"
checked+focus-visiblethe fill and a ring in color.interaction.focus.ring-containerglyph and ring
checked+disabledbox color.interaction.disabled.bg with 1px color.border.disabled; ✓ and text in color.text.disabledglyph; disabled; cursor: not-allowed
disabledbox color.interaction.disabled.bg with 1px color.border.disabled; text color.text.disableddisabled; cursor: not-allowed
invalidbox border 2px color.status.danger.border; message with the ✕ glyphborder width 1 → 2px; glyph; aria-invalid
required* after the text or legend in color.status.danger.text plus visually hidden “required”required; the mark

Precedence: disabled > invalid > checked > hover; focus-visible is always drawn.

Keyboard

Native. Space toggles; Enter does nothing. Every checkbox in a group is a separate tab stop, unlike radios. A mixed parent becomes checked on the first Space and unchecked on the second, never mixed again by keyboard.

Accessibility

The text is the label through the wrapping <label>; a group has its legend read before each option. indeterminate is a DOM property with no attribute, so the host mirrors it to data-state-mixed for styling and the state reads as “mixed” natively. A required group marks the legend, not every option, and validates on submit. Contrast: text 8.43:1, glyph 9.28:1 on the fill, box edge 4.45:1 on the input surface and 4.33:1 against the panel when checked, ring 4.69:1, container ring 5.57:1 on the fill.

Portability

A square with a border and a fill plus two glyphs. Hosts that draw their own indicator set it square, 16px, and use the same fill and glyph colours; a host without a mixed indicator draws the dash itself or records the gap.

Non-examples

Rounded or circular boxes. A tick drawn with a border trick or an icon font. A checked state shown by border colour alone with no glyph. A box smaller than 16px or a row shorter than 24px. The mixed state used as a third value. A checkbox that saves on change. Disabling by opacity. A div with role="checkbox".

Keys

KeyAction
Tab / Shift+TabMoves through every checkbox; each is its own tab stop.
SpaceToggles; a mixed box becomes checked.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Related: radio-group switch fieldset field list

Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

Radio group radio-group

  • Family: Basic forms
  • Maturity: stable
  • Priority: R1
  • Since: 0.1.0
  • Native control: native <input type="radio"> inside <fieldset> with <legend>APG pattern
  • specified
  • demonstrated
  • tested

A fieldset of native radios for one exclusive choice; each radio is a 16px square that fills with the primary action colour and an inner square when checked.

Report an issue with this component

Tokens

PartRoleValueUse
box.bgcolor.surface.inputapproveduse#000000Form-control fill.
box.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
box.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
box.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
box.bg-checkedcolor.action.primary.bgapproveduse#7d1310Primary button fill; D-026 darkened it off color12, which stays fixed as heritage ANSI 12.
box.bg-checked-hovercolor.action.primary.hover-bgobserveduse#911410Primary button hover (7.92:1 with prose).
box.dotcolor.action.primary.textobserveduse#f4eeeePrimary button text (9.28:1).
box.ring-checkedcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
box.border-invalidcolor.status.danger.borderobserveduse#e53935Danger border, 2px on invalid inputs.
box.bg-disabledcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
box.border-disabledcolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
box.dot-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
text.defaultcolor.text.defaultobserveduse#e99499Interface and body text.
text.disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
legend.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
legend.required-markcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).
message.textcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateVerticalHorizontal
default
Default layout required

✕ Choose a layout.

Density required

✕ Choose a density.

hover
focus-visible
checked
checked+focus-visible
disabled
invalid
required

Purpose

One choice out of a few visible options. Below two options a checkbox or switch is used; above roughly six, a select. The radios are square, as every control in this theme is, and are told apart from checkboxes by the inner square instead of the ✓ glyph and by arrow-key movement instead of separate tab stops.

Anatomy

A <fieldset> whose <legend> asks the question; a list of <label> rows each holding the native input, drawn as a 16px square with appearance: none, and its text; the validation message at the end. The inner square is a real element stacked over the input in the same cell.

States

StateVisualNon-colour channel
default16px square, 1px color.border.control on color.surface.input; text color.text.default
hoverbox background → color.interaction.hover.bg; a checked box → color.action.primary.hover-bgcursor: pointer; hover-capable pointers only
focus-visiblering 1px dashed color.interaction.focus.ring at −2px around the boxthe ring
checkedbox fills color.action.primary.bg; an 8px inner square in color.action.primary.text; border stays color.border.controlthe inner square; checked
checked+focus-visiblethe fill and a ring in color.interaction.focus.ring-containerinner square and ring
disabledboxes color.interaction.disabled.bg with 1px color.border.disabled; inner square and text color.text.disableddisabled; cursor: not-allowed
invalidevery box border 2px color.status.danger.border; message with the ✕ glyphborder width 1 → 2px; glyph; aria-invalid
required* after the legend in color.status.danger.text plus visually hidden “required”required; the mark

Precedence: disabled > invalid > checked > hover; focus-visible is always drawn.

Keyboard

Native. The group is one tab stop; the arrow keys move both focus and the check, so moving through a group changes the value. That is why a radio group never triggers navigation or a request on change; the value is read on submit or through an explicit action.

Accessibility

The legend is read before each option and is the group’s name. Options share a name. The message is linked with aria-describedby on the fieldset and aria-invalid is set on the inputs after submit. A group with no default checked radio must have a required mark or a “none” option, so the empty state is intentional. Contrast: text 8.43:1, inner square 9.28:1 on the fill, box edge 4.45:1 on the input surface and 4.33:1 against the panel when checked, ring 4.69:1, container ring 5.57:1.

Portability

Square, border, fill and one inner square; no pseudo-element is needed. Hosts that insist on a circular radio indicator record the deviation rather than replacing the control with a custom widget.

Non-examples

Circular radios. A checked state shown by border colour alone with no inner square. Radios that submit or navigate on change. A group with no legend or with the legend rendered as a label on one option. Separate tab stops per radio. One radio on its own. Disabling by opacity. A div with role="radiogroup" built from spans.

Keys

KeyAction
Tab / Shift+TabEnters the group on the checked radio, or the first when none is checked; leaves it entirely.
Up / Down / Left / RightMoves the check to the previous or next radio and selects it (native); wraps at the ends.
SpaceChecks the focused radio when none is checked.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Related: checkbox switch segmented-control fieldset field select

Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

Switch switch

  • Family: Basic forms
  • Maturity: stable
  • Priority: R1
  • Since: 0.1.0
  • Custom widget: <button type="button" role="switch" aria-checked>APG pattern
  • specified
  • demonstrated

An on/off control that takes effect immediately; a button with role switch and aria-checked, drawn as a square-cornered track with a square thumb that fills with the primary colour when on.

Report an issue with this component

Tokens

PartRoleValueUse
track.bgcolor.surface.inputapproveduse#000000Form-control fill.
track.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
track.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
track.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
track.bg-checkedcolor.action.primary.bgapproveduse#7d1310Primary button fill; D-026 darkened it off color12, which stays fixed as heritage ANSI 12.
track.bg-checked-hovercolor.action.primary.hover-bgobserveduse#911410Primary button hover (7.92:1 with prose).
track.ring-checkedcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
track.bg-disabledcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
track.border-disabledcolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
thumb.bgcolor.text.defaultobserveduse#e99499Interface and body text.
thumb.bg-checkedcolor.action.primary.textobserveduse#f4eeeePrimary button text (9.28:1).
thumb.bg-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
name.textcolor.text.defaultobserveduse#e99499Interface and body text.
state.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
name.text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateDefaultWith labels
default
Follow system theme
hover
focus-visible
checked
checked+focus-visible
disabled
checked+disabled

Purpose

A setting that turns on or off the moment it is toggled: notifications, wrap lines, follow system theme. A choice that is only applied on submit is a checkbox. The switch is a button because it acts; it is not a form field.

Anatomy

A <button role="switch">; inside it the track, a 32×16px box with square corners, and the thumb, a 10px square that sits at the start when off and at the end when on. The with-labels variant adds a visible name before the button and an “Off” / “On” word after the track.

States

StateVisualNon-colour channel
defaulttrack 1px color.border.control on color.surface.input; thumb color.text.default at the startthumb position
hovertrack background → color.interaction.hover.bg; on track → color.action.primary.hover-bgcursor: pointer; hover-capable pointers only
focus-visiblering 1px dashed color.interaction.focus.ring at −2px on the trackthe ring
checkedtrack fills color.action.primary.bg; thumb color.action.primary.text moves to the end; border stays color.border.control; the word reads “On”aria-checked="true"; thumb position; the word
checked+focus-visiblethe fill and a ring in color.interaction.focus.ring-container on the trackposition and ring
disabledtrack color.interaction.disabled.bg with 1px color.border.disabled; thumb and name color.text.disableddisabled; cursor: not-allowed
checked+disabledas disabled with the thumb at the enddisabled; aria-checked="true"; thumb position

The thumb moves without animation by default; a host may transition transform for at most 120ms under prefers-reduced-motion: no-preference. Precedence: disabled > checked > hover; focus-visible is always drawn.

Keyboard

Space and Enter toggle. Nothing else is bound; there is no arrow-key movement between switches. Focus never moves as a result of toggling.

Accessibility

role="switch" on a native button gives the correct name, role and value with the button’s own keyboard handling; only aria-checked is scripted. The name states what is on (“Wrap long lines”), never the current value; the “Off” / “On” word is aria-hidden because assistive technology reads aria-checked. The state is also carried by thumb position and, in the with-labels variant, the word. Contrast: thumb 8.65:1 on the off track, 9.28:1 on the on track; track edge 4.45:1; ring 4.69:1 off, 5.57:1 on.

Portability

Two nested rectangles, a border and a fill; the thumb position is layout, not a transform, so it survives hosts with no animation. Hosts with a native switch use it, square it, and map the two fills.

Non-examples

A pill-shaped track or a round thumb. A switch that only takes effect on submit. A checkbox input styled as a switch. Colour as the only difference between on and off. A green on colour. A label that reads “On” as the name. Disabling by opacity. A sliding animation longer than 120ms or one that runs under reduced motion.

Keys

KeyAction
Tab / Shift+TabMoves focus to and from the switch.
Space / EnterToggles aria-checked and applies the change at once.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Related: checkbox radio-group icon-button field

Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

Fieldset fieldset

  • Family: Basic forms
  • Maturity: stable
  • Priority: R1
  • Since: 0.1.0
  • Native control: native <fieldset> with <legend>APG pattern
  • specified
  • demonstrated

The native fieldset that groups related fields under a legend inside a 1px divider border; disabling it disables everything inside.

Report an issue with this component

Tokens

PartRoleValueUse
root.bordercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
legend.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
body.textcolor.text.defaultobserveduse#e99499Interface and body text.
legend.text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
field.bgcolor.surface.inputapproveduse#000000Form-control fill.
field.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
field.bg-disabledcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
field.border-disabledcolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
field.text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
help.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateDefault
default
Window gaps

Pixels between windows.

Negative values overlap the screen edge.

disabled

Purpose

Grouping fields that belong together: an address, a set of credentials, the options of one feature. The legend names the group for sighted users and assistive technology alike, and disabling the fieldset disables every control inside it in one step. Checkbox and radio groups use their own components, which are fieldsets too.

Anatomy

The native <fieldset> with a 1px color.border.divider border and 16px padding; the <legend> in color.text.bright sitting in the top border; the fields stacked inside. The border is a section rule, decorative by design; the legend and the spacing carry the grouping.

States

StateVisualNon-colour channel
default1px color.border.divider border; legend color.text.bright; fields as their own componentsthe border and the legend
disabledlegend and labels color.text.disabled; every control inside takes its own disabled treatment (color.interaction.disabled.bg, color.border.disabled); the border unchangeddisabled on the fieldset; cursor: not-allowed on the controls

Keyboard

None of its own. Disabled fieldsets remove their controls from the tab order natively, so a disabled group is skipped rather than walked.

Accessibility

The legend is the accessible name of the group and is announced before the first field inside; it says what the group is, not what to do. A group never nests deeper than two levels. Disabling a group hides its controls from keyboard users, so a disabled group states why in text before it or keeps its controls enabled. Contrast: legend 10.10:1, labels 8.43:1, help 5.66:1 on the panel surface.

Portability

A border and a heading. Hosts without a legend-in-border draw the heading above the box and record it. Disabled propagation is native on the web and in GTK and Qt; a host without it disables each control.

Non-examples

A fieldset with no legend or with a legend hidden visually. A card used instead of a fieldset for form controls. Rounded corners. A 2px or border.control border on the group, which would read as a control. A legend in accent red. Disabling only the legend. Nesting three levels deep.

Keys

KeyAction
Tab / Shift+TabMoves through the fields inside in document order; the legend is not a tab stop.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Related: field checkbox radio-group text-field card

Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-DENSITY FX-STATE-MATRIX

Number field number-field

  • Family: Basic forms
  • Maturity: stable
  • Priority: R1
  • Since: 0.1.0
  • Native control: native <input type="number"> with <label>; stepper buttons are separate <button>sAPG pattern
  • specified
  • demonstrated

The text-field box around a native number input with right-aligned tabular digits, an optional unit affix and two square stepper buttons that replace the host spinner.

Report an issue with this component

Tokens

PartRoleValueUse
root.bgcolor.surface.inputapproveduse#000000Form-control fill.
root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
root.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
root.border-focuscolor.border.activeobserveduse#e53935Active or focused control border.
root.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
root.ring-invalidcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
root.border-invalidcolor.status.danger.borderobserveduse#e53935Danger border, 2px on invalid inputs.
root.border-disabledcolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
root.bg-disabledcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
root.border-readonlycolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
root.bg-readonlycolor.surface.canvasapproveduse#000000Page and terminal background.
input.textcolor.text.defaultobserveduse#e99499Interface and body text.
input.text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
input.caretcolor.code.caretobserveduse#e99499Caret (Xresources *cursorColor).
unit.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
unit.bordercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
action.textcolor.action.tertiary.textobserveduse#e99499Ghost and icon button text.
action.bg-hovercolor.action.tertiary.hover-bgobserveduse#1c0a09Ghost and icon button hover.
action.bordercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
label.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
help.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
message.textcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateDefaultWith unit
default

Between 1 and 20.

✕ Between 1 and 20.

Between 0 and 64 pixels; Up and Down step by one.

✕ Between 0 and 64.

hover
focus-visible
invalid
invalid+focus-visible
disabled
read-only

Purpose

Entering a bounded number: a gap in pixels, a timeout in milliseconds, a count. The theme replaces the host spinner, which is tiny and inconsistent, with two square buttons that are real tab stops. Free-form numeric text such as a version or an identifier is a text field with inputmode.

Anatomy

Label above; the box; the input with digits aligned to the end; the optional unit; the stepper with + over −, each button half the control height and at least 24px wide; help stating the range; the validation message.

States

StateVisualNon-colour channel
default1px color.border.control on color.surface.input; digits color.text.default; unit color.text.muted; stepper glyphs color.action.tertiary.text
hoverbackground → color.interaction.hover.bg; a hovered stepper button → color.action.tertiary.hover-bgcursor: text on the input, pointer on the buttons
focus-visibleborder → color.border.active; ring 1px dashed color.interaction.focus.ring at −2px on the box, or on the focused stepper buttonthe ring
invalidborder 2px color.status.danger.border; message with the ✕ glyphborder width 1 → 2px; glyph; aria-invalid
invalid+focus-visiblethe 2px danger border and the ring in color.interaction.focus.ring-container at −4pxdouble boundary
disabledtext, unit and glyphs color.text.disabled; border color.border.disabled; background color.interaction.disabled.bg; buttons disableddisabled; cursor: not-allowed
read-onlyno box: 1px dotted color.border.divider bottom edge on color.surface.canvas; the stepper is hiddenreadonly; dotted edge; no buttons

Precedence: disabled > invalid > hover; focus-visible is always drawn.

Keyboard

Native arrow stepping inside the input; the stepper buttons are ordinary buttons after it in the tab order and call stepUp() / stepDown(). Typing a value outside the range is allowed and reported as invalid on blur or submit, never clamped silently.

Accessibility

A programmatic label is required. The unit is aria-hidden and repeated in the label or help (“Inner gap (px)”), so it is never lost. Stepper buttons are named “Increase

Portability

The text field’s box plus two buttons; the host spinner is hidden with the engine’s pseudo-elements and appearance: textfield. Hosts whose spin buttons cannot be replaced style them square in the same colours and record it.

Non-examples

The host’s default spinner. Round or overlapping stepper buttons. A value clamped silently on blur. Left-aligned digits. A unit typed into the value. A number field for phone numbers, postcodes or identifiers. Invalid shown by colour alone. Disabling by opacity.

Keys

KeyAction
Tab / Shift+TabInput, then the increase button, then the decrease button.
Up / DownSteps by the step attribute (native); Shift+Up / Shift+Down step by ten where the host binds it.
Page Up / Page DownSteps by ten times the step where the host binds it.
Home / EndJumps to min or max where the host binds it.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Related: text-field field range search-field

Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

Search field search-field

  • Family: Basic forms
  • Maturity: stable
  • Priority: R1
  • Since: 0.1.0
  • Native control: native <input type="search"> with <label> inside a role="search" landmark; status through role="status"APG pattern
  • specified
  • demonstrated

The text-field box around a native search input with a magnifier, a clear button that appears with a value, an optional shortcut hint, a loading glyph and a no-results status line.

Report an issue with this component

Tokens

PartRoleValueUse
root.bgcolor.surface.inputapproveduse#000000Form-control fill.
root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
root.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
root.border-focuscolor.border.activeobserveduse#e53935Active or focused control border.
root.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
root.border-disabledcolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
root.bg-disabledcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
input.textcolor.text.defaultobserveduse#e99499Interface and body text.
input.text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
input.placeholdercolor.text.placeholderapproveduse#a3676bPlaceholder text, italic; D-027 darkened it to 4.71:1, just clear of the 4.5:1 floor.
input.caretcolor.code.caretobserveduse#e99499Caret (Xresources *cursorColor).
icon.strokecolor.icon.defaultobserveduse#e99499Icons take the text colour (currentColor in CSS).
loading.glyphcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
clear.textcolor.action.tertiary.textobserveduse#e99499Ghost and icon button text.
clear.bg-hovercolor.action.tertiary.hover-bgobserveduse#1c0a09Ghost and icon button hover.
kbd.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
kbd.bordercolor.border.defaultobserveduse#531310Decorative border (1.39:1; never the only edge of a control).
label.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
help.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
status.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateDefaultWith shortcut hint
default
hover
focus-visible
placeholder-shown
filled
loading
disabled
no-results

Purpose

Filtering a list or table or searching a site. It is the text field’s box with the parts a search needs: an icon that says what the box is for, a clear button, a place for the shortcut that reaches it, a loading glyph while results arrive and a status line when nothing matches. A search that offers suggestions as you type is the combobox component.

Anatomy

Label above (or visually hidden); the box with the magnifier, the input, the clear button and the optional hint; help; the status line. The loading glyph takes the magnifier’s slot so the box never changes size.

States

StateVisualNon-colour channel
default1px color.border.control on color.surface.input; magnifier color.icon.default; text color.text.defaultthe magnifier
hoverbackground → color.interaction.hover.bg; the clear button → color.action.tertiary.hover-bg when hoveredcursor: text
focus-visibleborder → color.border.active; ring 1px dashed color.interaction.focus.ring at −2px; the hint hidesthe ring
placeholder-shownplaceholder in color.text.placeholder, italic; no clear buttonitalic; the clear button is absent
filledas default with a value; the clear button is presentthe clear button
loadingthe static glyph in color.text.muted replaces the magnifier; the input stays editableglyph; aria-busy
disabledtext and icon color.text.disabled; border color.border.disabled; background color.interaction.disabled.bg; no clear buttondisabled; cursor: not-allowed
no-resultsthe status line “No results for …” in color.text.muted below the help; the box unchangedthe status text; role="status"

Precedence: disabled > loading > hover; focus-visible is always drawn. A search field is never invalid; an empty result is a status, not an error.

Keyboard

Escape clears a non-empty value and keeps focus, which is native for type="search" in most engines and scripted where it is not. The clear button is a separate tab stop only while it is visible. The shortcut in the hint is bound by the host and never captured while another field has focus.

Accessibility

A programmatic label is required even when hidden. The landmark role="search" lets users jump to it. The status line is role="status" so “No results” is announced once, after the query settles, and the result count is announced there too (“12 results”). The magnifier and hint are aria-hidden; the clear button is named “Clear

Portability

The text field plus icons and a status line. Hosts hide their own cancel button; hosts that cannot draw the hint omit it and keep the shortcut in the tooltip.

Non-examples

Rounded or pill-shaped search boxes. A magnifier button that submits instead of an icon. A spinner while loading. Results announced on every keystroke. “No results” in red or with the ✕ glyph. A clear button that is always visible. A search field without a label. Disabling by opacity.

Keys

KeyAction
Tab / Shift+TabInput, then the clear button when it is visible.
EscapeClears a non-empty value and keeps focus; with an empty value, nothing.
EnterRuns the search when the host does not search as you type.
/ or Ctrl+KFocuses the field from anywhere on the page when the host binds the shortcut shown in the hint.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Related: text-field combobox command-palette toolbar empty-state kbd

Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

Range range

  • Family: Basic forms
  • Maturity: stable
  • Priority: R2
  • Since: 1.0.0
  • Native control: Native labelled range input and output
  • specified
  • demonstrated

A bounded native numeric slider with visible output.

Report an issue with this component

Tokens

PartRoleValueUse
root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
root.textcolor.text.defaultobserveduse#e99499Interface and body text.
root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
heading.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
secondary.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
control.bgcolor.surface.inputapproveduse#000000Form-control fill.
control.focuscolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
dependency.role-border-width-defaultborder.width.defaultobserveduse1pxEvery border is 1px.
dependency.role-color-action-primary-bgcolor.action.primary.bgapproveduse#7d1310Primary button fill; D-026 darkened it off color12, which stays fixed as heritage ANSI 12.
dependency.role-color-border-disabledcolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
dependency.role-color-interaction-disabled-bgcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
dependency.role-color-text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
dependency.role-density-comfortable-control-heightdensity.comfortable.control-heightobserveduse32px
dependency.role-density-compact-control-heightdensity.compact.control-heightobserveduse24px
dependency.role-radius-noneradius.noneobserveduse0pxThe only radius. Nothing is rounded.
dependency.role-space-12space.12observeduse12px
dependency.role-space-2space.2observeduse2px
dependency.role-space-8space.8observeduse8px

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateDefault
default
40
focus-visible
disabled

Purpose

Set a numeric value with a native range input and a visible output. The input retains min, max, step, disabled, name/value submission and form reset. Platform track geometry is a native rendering boundary; the semantic accent and focus roles remain explicit.

Anatomy

  • label: Visible label linked to the input.
  • input: Native range control with caller-specified bounds.
  • output: Current numeric value linked using for.

States

StatePresentationNon-colour channel
defaultNamed content on the default surface.Native text and structure.
focus-visibleDashed focus ring.Native keyboard focus position.
disabledDisabled semantic foreground, background and border at full opacity.Native disabled state blocks activation.

Keyboard

  • Tab / Shift+Tab: Reach and leave the slider.
  • Arrow keys / Home / End: Use native stepping, minimum and maximum behavior.

Accessibility

Retain the input’s accessible name and native value semantics. The visible output does not replace its label. Put units in the label or help text. No value changes solely from receiving focus.

Portability

Wrap labels and actions without changing source order. Use logical spacing in RTL. Preserve native target sizes at both densities; only bounded data regions may scroll horizontally. Use equivalent native semantics and approved roles; record any unsupported behavior as a mapping deviation. The host owns application data, persistence, permissions and services.

Non-examples

Unlabelled controls, color-only status, drag-only operations, hidden required instructions, stolen focus or an invented service success.

Keys

KeyAction
Tab / Shift+TabReach and leave the slider.
Arrow keys / Home / EndUse native stepping, minimum and maximum behavior.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Stress fixtures: FX-320 FX-360 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

Advanced forms

Combobox, multiselect, date and time, file selection, repeaters, wizard, bounded form-builder specimen.

Combobox combobox

  • Family: Advanced forms
  • Maturity: stable
  • Priority: R1
  • Since: 0.1.0
  • Custom widget: APG combobox with list autocomplete: input role combobox owning a listbox of optionsAPG pattern
  • specified
  • demonstrated

A text input that filters a listbox of suggestions; the APG combobox with list autocomplete, rendered with the list open.

Report an issue with this component

Tokens

PartRoleValueUse
root.bgcolor.surface.inputapproveduse#000000Form-control fill.
root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
root.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
root.border-focuscolor.border.activeobserveduse#e53935Active or focused control border.
root.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
root.ring-invalidcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
root.border-invalidcolor.status.danger.borderobserveduse#e53935Danger border, 2px on invalid inputs.
root.border-disabledcolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
root.bg-disabledcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
input.textcolor.text.defaultobserveduse#e99499Interface and body text.
input.text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
input.placeholdercolor.text.placeholderapproveduse#a3676bPlaceholder text, italic; D-027 darkened it to 4.71:1, just clear of the 4.5:1 floor.
input.caretcolor.code.caretobserveduse#e99499Caret (Xresources *cursorColor).
toggle.textcolor.action.tertiary.textobserveduse#e99499Ghost and icon button text.
toggle.bg-hovercolor.action.tertiary.hover-bgobserveduse#1c0a09Ghost and icon button hover.
label.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
listbox.bgcolor.surface.raisedapproveduse#160b0bSticky headers, menus, popovers; D-027 recessed it so an open list reads as depth rather than a lighter panel.
listbox.bordercolor.border.overlayproposeduse-and-reportD-008#e53935Every floating layer's 1px border.
option.textcolor.text.defaultobserveduse#e99499Interface and body text.
option.bg-hovercolor.interaction.hover.bg-strongobserveduse#630f0dHover on menu items; D-027 moved links to interaction.hover.bg.
option.text-hovercolor.text.link-hoverobserveduse#f4eeeeLink text on hover, over interaction.hover.bg-strong.
option.bg-selectedcolor.interaction.selection.bgapproveduse#531310Selected row, tab, workspace; D-027 recessed the fill, leaving the 2px indicator and the check to carry selection.
option.text-selectedcolor.interaction.selection.textobserveduse#f4eeeeText on the selection.
option.ring-selectedcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
group.textcolor.text.subtleapproveduse#ad7175Metadata, comments, line numbers.
group.bordercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
empty.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
help.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
message.textcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateFlat listGrouped optionsNo results
default
  • Cascadia Mono
  • SauceCodePro NFM
  • Source Code Pro
  • No fonts match.

Down opens the list; Enter accepts.

✕ Choose a font from the list.

  • Recent
  • Known
  • No hosts match.

Recent hosts first.

✕ Choose a known host.

  • No tags match.

Escape clears the filter.

✕ Choose an existing tag.

hover
focus-visible
open
closed
selected
invalid
invalid+focus-visible
disabled
no-results

Purpose

A text input whose value is completed from a list of suggestions. It is the right control when the set is large or open-ended (fonts, hosts, tags); a closed set of a dozen values is the select component. The demonstration renders the list open so every option state is visible without a script.

Anatomy

Label above the box; the box with the input and an optional toggle; the listbox directly below, on color.surface.raised behind a 1px color.border.overlay; options in color.text.default, an optional group heading in color.text.subtle above a color.border.divider rule; the empty message in color.text.muted; help and validation message below, as in the text field.

States

StateVisualNon-colour channel
default1px color.border.control on color.surface.input; list on color.surface.raised with a 1px color.border.overlay
hoverbox background → color.interaction.hover.bg; the hovered option → color.interaction.hover.bg-strong with color.text.link-hovercursor: text on the box, default on the list
focus-visiblebox border → color.border.active; ring 1px dashed color.interaction.focus.ring at −2pxthe ring
openlist visible below the box; toggle glyph rotated 180°aria-expanded="true"; the toggle glyph
closedlist absent; the box unchangedaria-expanded="false"; nothing below the box
selectedthe active option filled color.interaction.selection.bg with color.interaction.selection.text and a 1px dashed ring in color.interaction.focus.ring-containeraria-selected="true"; aria-activedescendant; the ring
invalidbox border 2px color.status.danger.border; message with the ✕ glyphborder width 1 → 2px; glyph; aria-invalid
invalid+focus-visiblethe 2px danger border and the ring in color.interaction.focus.ring-container at −4pxdouble boundary
disabledtext color.text.disabled; border color.border.disabled; background color.interaction.disabled.bg; list never opensdisabled; cursor: not-allowed
no-resultsthe list holds only the empty row in color.text.muted, italicaria-disabled row; italic; a polite announcement of zero matches

Precedence when several apply: disabled > invalid > selected > hover; focus-visible is always drawn on the box, and the selection ring on the option.

Keyboard

DOM focus never leaves the input. Down and Up open the list and move the active option, which the input reports through aria-activedescendant; Enter accepts it; Escape closes the list and, when the list is already closed, clears the value. Alt+Down and Alt+Up open and close without changing the active option. Home and End move the caret. Tab closes the list and keeps whatever is typed. Typing filters the list on every keystroke; the number of matches is announced through a polite live region, not by re-reading the list.

Accessibility

The input carries role="combobox", aria-autocomplete="list", aria-expanded, aria-controls pointing at the listbox and, while an option is active, aria-activedescendant. The listbox has an accessible name (aria-label or aria-labelledby the field label); options are role="option" with aria-selected on the active one only; groups are role="group" with aria-labelledby their heading. The empty row is a disabled option so the list is never empty; the zero-match count is announced through the same polite live region as every other count. Contrast: option text 8.43:1 on the raised surface, selection text 12.47:1 on the selection fill, the selection ring 7.48:1 on the fill, the list border 4.57:1 on the raised surface, group headings 4.96:1.

Portability

Everything is expressible with background, border and outline; the toggle rotation is a transform inside the motion budget. Toolkits with a native completion popup use it and map the option fill to the selection roles; the list border is the popover frame. Toolkits without aria-activedescendant move real focus to the option and record the deviation.

Non-examples

A select restyled as a combobox. Moving DOM focus into the list on Down. A list that floats over the page with a shadow or a rounded frame. Highlighting the active option with a colour change of the text alone. A no-results state that silently shows the full list. Opening on hover. A list that slides or fades in for longer than 150 ms.

Keys

KeyAction
Down / UpOpens the list if closed; moves the active option, wrapping at either end; the input keeps DOM focus.
EnterAccepts the active option into the input and closes the list.
EscapeCloses the list; a second Escape clears the input.
Alt+Down / Alt+UpOpens or closes the list without moving the active option.
Home / EndMoves the caret inside the input, never the active option.
TabLeaves the control; an open list closes and the typed text stays.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Related: text-field select multiselect search-field menu command-palette

Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-OVERFLOW FX-STATE-MATRIX

Date picker date-picker

  • Family: Advanced forms
  • Maturity: stable
  • Priority: R1
  • Since: 0.1.0
  • Custom widget: Labeled textbox with calendar dialog and roving date grid; native backing inputAPG pattern
  • specified
  • demonstrated

A themed date editor and calendar, alone or as a from/to pair, backed by native form values and constraints.

Report an issue with this component

Tokens

PartRoleValueUse
root.bgcolor.surface.inputapproveduse#000000Form-control fill.
root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
root.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
root.border-focuscolor.border.activeobserveduse#e53935Active or focused control border.
root.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
root.ring-invalidcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
root.border-invalidcolor.status.danger.borderobserveduse#e53935Danger border, 2px on invalid inputs.
root.border-disabledcolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
root.bg-disabledcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
root.border-readonlycolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
root.bg-readonlycolor.surface.canvasapproveduse#000000Page and terminal background.
input.textcolor.text.defaultobserveduse#e99499Interface and body text.
input.text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
input.caretcolor.code.caretobserveduse#e99499Caret (Xresources *cursorColor).
label.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
legend.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
separator.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
help.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
message.textcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).
calendar.bgcolor.surface.raisedapproveduse#160b0bSticky headers, menus, popovers; D-027 recessed it so an open list reads as depth rather than a lighter panel.
calendar.bordercolor.border.overlayproposeduse-and-reportD-008#e53935Every floating layer's 1px border.
calendar.textcolor.text.defaultobserveduse#e99499Interface and body text.
calendar.selected-bgcolor.interaction.selection.bgapproveduse#531310Selected row, tab, workspace; D-027 recessed the fill, leaving the 2px indicator and the check to carry selection.
calendar.selected-textcolor.interaction.selection.textobserveduse#f4eeeeText on the selection.

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateSingle dateFrom / to
default

Within 2026.

✕ Choose a date in 2026.

Report period

Inclusive; at most 92 days.

✕ The end date is before the start date.

hover
focus-visible
invalid
invalid+focus-visible
disabled
read-only

Purpose

Choose a date by explicit text entry or a themed calendar. A range is two separately labeled date controls. D-025 requires theme-owned web controls rather than browser popup styling.

Anatomy

A label, editor, calendar trigger, format hint and validation message. The native date input remains the successful form control and owns its value, defaults and constraints. It is hidden only after enhancement.

States

StateTreatment
defaultInput surface, default text and control border.
hoverThe declared hover fill.
focus-visibleActive border and the canonical focus ring.
invalidDanger border and a linked message.
invalid+focus-visibleDanger border plus the container focus ring.
disabledDisabled colors; editor and calendar actions unavailable.
read-onlyReadable canvas text and bottom edge; calendar action unavailable.

Use the declared state tokens: default input surface and control border; hover fill; the canonical focus ring; danger border and message for invalid input; disabled colors and unavailable actions. Read-only values remain readable and cannot open a picker or change through step buttons. The date read-only treatment retains the canvas surface and unobtrusive bottom edge.

Keyboard

Alt+Down opens the calendar. Arrows move by a day or week, Home/End reach week boundaries, and PageUp/PageDown change months. Enter/Space chooses a focused date. Escape closes and restores editor focus. Tab leaves normally; the calendar is a nonmodal popup.

Accessibility

The visible editor receives the original label, descriptions, required state and error state. Format hints are always available. Native min, max, step and required constraints remain authoritative. Invalid entry focuses the visible editor and exposes a theme-owned message. Calendar selection is a fill; keyboard focus is a separate ring. Disabled dates cannot be selected. The range validates that its end is not before its start. Form reset restores the native defaults.

Automated evidence records its actual browser, states and limitations; it is not a manual screen-reader acceptance.

Portability

The package and complete copy distribution include the renderer. The public control enhancement applies the same behavior to existing native markup. The no-JavaScript fallback and non-web platform mappings remain native.

Non-examples

An unthemed host popup presented as fully themed. A second named input that duplicates form values. Discarding native constraints, labels or reset behavior. Literal colors, rounded corners, or a selected fill with no distinguishable focus boundary.

Keys

KeyAction
Tab / Shift+TabMoves through the editor, calendar trigger and other controls.
Alt+DownOpens the calendar from the editor.
Arrows / Home / EndMoves among dates; Home and End reach the beginning and end of the week.
PageUp / PageDownMoves to the previous or next month.
Enter / SpaceChooses a focused calendar date or activates a month button.
EscapeCloses the calendar and returns focus to the editor.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Related: text-field time-picker field fieldset

Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-STATE-MATRIX

Time picker time-picker

  • Family: Advanced forms
  • Maturity: stable
  • Priority: R1
  • Since: 0.1.0
  • Custom widget: Labeled textbox with native time constraints and named step buttonsAPG pattern
  • specified
  • demonstrated

A themed time editor with explicit step buttons, backed by native time values and constraints.

Report an issue with this component

Tokens

PartRoleValueUse
root.bgcolor.surface.inputapproveduse#000000Form-control fill.
root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
root.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
root.border-focuscolor.border.activeobserveduse#e53935Active or focused control border.
root.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
root.border-invalidcolor.status.danger.borderobserveduse#e53935Danger border, 2px on invalid inputs.
root.border-disabledcolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
root.bg-disabledcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
input.textcolor.text.defaultobserveduse#e99499Interface and body text.
input.text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
input.caretcolor.code.caretobserveduse#e99499Caret (Xresources *cursorColor).
label.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
help.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
message.textcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateTime
default

Between 06:00 and 22:00, in five-minute steps.

✕ Choose a time between 06:00 and 22:00.

hover
focus-visible
invalid
disabled

Purpose

Enter a time explicitly or adjust it using themed step buttons. D-025 requires theme-owned web controls rather than browser popup styling.

Anatomy

A label, editor, increase/decrease buttons, format hint and validation message. The native time input remains the successful form control and owns its value, defaults and constraints. It is hidden only after enhancement.

States

StateTreatment
defaultInput surface, default text and control border.
hoverThe declared hover fill.
focus-visibleActive border and the canonical focus ring.
invalidDanger border and a linked message.
disabledDisabled colors; editor and step actions unavailable.

Use the declared state tokens: default input surface and control border; hover fill; the canonical focus ring; danger border and message for invalid input; disabled colors and unavailable actions. Read-only values remain readable and cannot open a picker or change through step buttons. The date read-only treatment retains the canvas surface and unobtrusive bottom edge.

Keyboard

Type HH:MM or HH:MM:SS in the editor. Tab reaches the named step buttons; Enter/Space activates them. Each step uses the native input step attribute. With step=“any”, use direct entry and the step buttons remain unavailable.

Accessibility

The visible editor receives the original label, descriptions, required state and error state. Format hints are always available. Native min, max, step and required constraints remain authoritative. Invalid entry focuses the visible editor and exposes a theme-owned message. No host clock popup or browser segment selection is used in the enhanced control. Form reset restores the native defaults.

Automated evidence records its actual browser, states and limitations; it is not a manual screen-reader acceptance.

Portability

The package and complete copy distribution include the renderer. The public control enhancement applies the same behavior to existing native markup. The no-JavaScript fallback and non-web platform mappings remain native.

Non-examples

An unthemed host popup presented as fully themed. A second named input that duplicates form values. Discarding native constraints, labels or reset behavior. Literal colors, rounded corners, or a selected fill with no distinguishable focus boundary.

Keys

KeyAction
Tab / Shift+TabMoves between the time editor, step buttons and other controls.
TypingEdits HH:MM or HH:MM:SS text; native min, max and step validate it.
Enter / Space on a step buttonIncreases or decreases by the native step. With step=any, buttons are disabled.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Related: text-field date-picker number-field field

Stress fixtures: FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-STATE-MATRIX

File input file-input

  • Family: Advanced forms
  • Maturity: stable
  • Priority: R1
  • Since: 0.1.0
  • Native control: native <input type=file> named by two <label>s; the drop zone is a plain region, never a roleAPG pattern
  • specified
  • demonstrated

A native file input behind a label styled as a secondary button, optionally inside a drop zone, with a list of chosen files and per-file errors.

Report an issue with this component

Tokens

PartRoleValueUse
button.bgcolor.action.secondary.bgobservedusergb(0 0 0 / 0%)Secondary button has no fill.
button.textcolor.action.secondary.textobserveduse#ffa2a7Secondary button text.
button.bordercolor.action.secondary.borderobserveduse#a3676bSecondary button border (meets 3:1).
button.bg-hovercolor.action.secondary.hover-bgobserveduse#630f0dSecondary button hover.
button.bg-pressedcolor.action.secondary.pressed-bgobserveduse#420f0cSecondary button pressed.
button.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
button.border-invalidcolor.status.danger.borderobserveduse#e53935Danger border, 2px on invalid inputs.
button.text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
button.border-disabledcolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
button.bg-disabledcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
zone.bordercolor.interaction.drop-targetobserveduse#e53935Dashed drop-target border.
zone.bg-drop-targetcolor.interaction.marqueeobservedusergb(145 20 16 / 12%)Drag marquee and ghost.
zone.hintcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
label.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
status.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
list.textcolor.text.defaultobserveduse#e99499Interface and body text.
list.dividercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
list.sizecolor.text.subtleapproveduse#ad7175Metadata, comments, line numbers.
list.errorcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).
remove.textcolor.action.tertiary.textobserveduse#e99499Ghost and icon button text.
remove.bg-hovercolor.action.tertiary.hover-bgobserveduse#1c0a09Ghost and icon button hover.
progress.trackcolor.interaction.pressed.bgobserveduse#420f0cPressed fill.
progress.stripecolor.action.primary.bgapproveduse#7d1310Primary button fill; D-026 darkened it off color12, which stays fixed as heritage ANSI 12.
help.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
message.textcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateButtonDrop zoneWith chosen files
default
No file chosen

Up to five files, 10 MB each.

✕ Choose at least one file.

or drop PNG or WebP files here

PNG or WebP, 4 MB each.

✕ Only PNG or WebP files.

3 files chosen
  • theme.json 12 KB
  • wallpaper.psd 48 MB ✕ Larger than 10 MB.
  • i3-config 3 KB

Up to five files, 10 MB each.

✕ One file could not be added.

hover
focus-visible
drop-target
invalid
disabled
loading

Purpose

Choosing one or more files from the host. The native input keeps the host chooser, its keyboard behaviour and its security model; the theme replaces only the input’s own rendering with a button-styled label, adds an optional drop zone, and lists what was chosen with any per-file error.

Anatomy

The field label; the root row (or the drop zone) holding the button-styled label and the status text; the hidden-but-focusable native input; an optional list of chosen files, each with name, size in color.text.subtle and a remove button, one of which may carry the ✕ glyph and an error in color.status.danger.text; a static striped progress bar while uploading; help and validation message below.

States

StateVisualNon-colour channel
defaultbutton: 1px color.action.secondary.border outline, text color.action.secondary.text; zone: 1px dashed color.interaction.drop-target
hoverbutton background → color.action.secondary.hover-bg; border unchangedcursor: pointer
focus-visiblering 1px dashed color.interaction.focus.ring at −2px on the button (the input has focus)the ring
drop-targetroot fill color.interaction.marquee; border 1px dashed color.interaction.drop-targetdashed pattern; the hint text changes to “Release to add”
invalidbutton border 2px color.status.danger.border; message with the ✕ glyph; a failed row shows its own ✕border width 1 → 2px; glyphs; aria-invalid
disabledbutton text color.text.disabled, border color.border.disabled, background color.interaction.disabled.bg; the zone’s dashes take color.border.disabled; no hoverdisabled; cursor: not-allowed
loadinga static bar of 45° stripes, color.action.primary.bg on color.interaction.pressed.bg, below the row; the button stays enabledaria-busy; the status text reads “Uploading n files”; no animation

Precedence when several apply: disabled > loading > invalid > drop-target > hover; focus-visible is always drawn.

Keyboard

Tab reaches the native input, which is drawn as the button; Enter or Space opens the host chooser; Escape in the chooser returns to the input. Each remove button in the list is its own tab stop after the input, and Delete or Backspace on it acts like Enter. Dropping is a pointer gesture only and never the sole way to add a file.

Accessibility

The native input is hidden with the sr-only pattern, never display: none or visibility: hidden, so it keeps focus and the host chooser. It is named by both labels (“Attachments” and “Choose files”), and aria-describedby lists help and message. The status text and the list are announced through a polite live region after a choice; per-file errors are in the row text, not only in colour. The drop zone has no role and no tabindex; aria-busy on the root marks uploading. Contrast: button text 10.37:1 on the canvas and 6.84:1 on the hover fill, button border 4.45:1, drop-target border 4.69:1 on the canvas and 4.52:1 on the marquee fill, status and help 5.81:1, sizes 5.10:1, danger text 5.40:1.

Portability

The button is the secondary button of the actions family; the zone is a dashed border and a translucent fill; the stripes are a repeating gradient (or a hatched brush). Toolkits without drag-and-drop omit the zone and keep the button; toolkits without a translucent fill composite the marquee over the canvas and record the value.

Non-examples

A hidden input with display: none and a button that clicks it by script. A drop zone that is the only way to add files. A rounded, dotted, animated “pulsing” zone. A spinner while uploading. A progress bar that animates its stripes. Errors shown by a red file name alone. Disabling by opacity.

Keys

KeyAction
Tab / Shift+TabReaches the native input (drawn as the button), then each remove button in the list.
Enter / SpaceOpens the host file chooser from the input.
Delete / BackspaceOn a focused remove button, same as activating it.
EscapeCloses the host chooser (host behaviour).

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Related: button text-field progress list field

Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-OVERFLOW FX-STATE-MATRIX

Wizard wizard

  • Family: Advanced forms
  • Maturity: stable
  • Priority: R1
  • Since: 0.1.0
  • Native control: native <button>s in an <ol>; the current step carries aria-current=step; the panel is a section named by its headingAPG pattern
  • specified
  • demonstrated

A multi-step form with a stepper header, the current panel and back/next actions; native buttons with aria-current="step".

Report an issue with this component

Tokens

PartRoleValueUse
steps.dividercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
step.textcolor.text.defaultobserveduse#e99499Interface and body text.
step.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
step.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
step.text-currentcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
step.indicator-currentcolor.border.selected-indicatorobserveduse#e539352px indicator bar on the selected tab or nav item.
step.text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
step.marker-completecolor.status.success.textapproveduse#86a46fSuccess text (7.13:1).
step.marker-invalidcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).
step.indicator-invalidcolor.status.danger.borderobserveduse#e53935Danger border, 2px on invalid inputs.
panel.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
panel.bordercolor.border.defaultobserveduse#531310Decorative border (1.39:1; never the only edge of a control).
title.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
text.textcolor.text.defaultobserveduse#e99499Interface and body text.
message.textcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).
next.bgcolor.action.primary.bgapproveduse#7d1310Primary button fill; D-026 darkened it off color12, which stays fixed as heritage ANSI 12.
next.textcolor.action.primary.textobserveduse#f4eeeePrimary button text (9.28:1).
next.bg-hovercolor.action.primary.hover-bgobserveduse#911410Primary button hover (7.92:1 with prose).
next.bg-pressedcolor.action.primary.pressed-bgobserveduse#630f0dPrimary button pressed.
next.bordercolor.action.primary.borderobserveduse#9e231fPrimary button border.
next.ringcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
back.textcolor.action.secondary.textobserveduse#ffa2a7Secondary button text.
back.bordercolor.action.secondary.borderobserveduse#a3676bSecondary button border (meets 3:1).
back.bg-hovercolor.action.secondary.hover-bgobserveduse#630f0dSecondary button hover.
busy.glyphcolor.action.primary.textobserveduse#f4eeeePrimary button text (9.28:1).

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateNumbered stepsGlyph markers
default

Step 2 of 3: Tokens

Choose the profile the tokens resolve against. The extended overlay can be added later.

✕ Choose a profile before continuing.

Step 3 of 4: Bindings

Keep the existing hjkl bindings or replace them with the imported set.

✕ Two bindings conflict.

hover
focus-visible
current
disabled
invalid
busy

Purpose

A form too long for one screen, split into ordered steps that are validated one at a time. The stepper shows where the person is and which steps are complete; the panel holds the current step; Back and Next move through the sequence. Steps are not tabs: a future step is unreachable until the steps before it pass.

Anatomy

The stepper, an ordered list of step buttons over a color.border.divider rule; each step’s marker and name; the panel on color.surface.default with its “Step n of m” heading in color.text.bright; the actions row with Back (secondary) and Next (primary, color.action.primary.bg with color.action.primary.text).

States

StateVisualNon-colour channel
defaultsteps in color.text.default; complete steps carry the ✓ in color.status.success.textthe ✓ glyph; the numbers
hoverstep background → color.interaction.hover.bg; Next → color.action.primary.hover-bg; Back → color.action.secondary.hover-bgcursor: pointer
focus-visiblering 1px dashed color.interaction.focus.ring at −2px; on Next’s fill the ring takes color.interaction.focus.ring-containerthe ring
current2px color.border.selected-indicator under the step; name in color.text.brightaria-current="step"; the indicator bar; the heading reads “Step n of m”
disableda future step in color.text.disabled; no hoverdisabled; cursor: not-allowed; skipped by Tab
invalidthe step’s marker becomes ✕ in color.status.danger.text; its indicator takes color.status.danger.border; the panel shows the messageglyph; message text; aria-invalid on the failing fields
busyNext shows the static ⋯ glyph before its label and does not respond; size unchangedaria-busy on the wizard; the glyph; cursor: progress

Precedence when several apply: disabled > busy > invalid > current > hover; focus-visible is always drawn.

Keyboard

Tab walks the enabled step buttons in order, then the panel’s fields, then Back and Next. Enter or Space on a reachable step goes to it; on Next it validates the panel, and on failure moves focus to the first invalid field, on success advances and moves focus to the new panel heading. Back never validates. There is no arrow-key navigation between steps, because the stepper is a list of buttons, not a tablist.

Accessibility

The wizard is a region named by aria-label; the stepper is an <ol> so count and position are announced; the current step carries aria-current="step"; complete steps append visually hidden ”, complete”; unreachable steps are disabled, not aria-disabled, because they cannot be activated. The panel is a <section> named by its heading, which receives focus after each step change. Validation failures are announced through the form’s live region and the ✕ marker; aria-busy marks the wizard while Next is in progress. Contrast: step text 8.65:1, current name 10.37:1, complete marker 7.13:1, indicator 4.69:1, Next text 9.28:1 on its fill, ring 5.57:1 on the primary fill, future step text 3.33:1 (exempt).

Portability

Everything is text, a 2px bottom border and the button tones; no icon font (the markers are text glyphs). Toolkits with a native assistant use its page list and map the indicator to the current page; toolkits with none draw the stepper as a row of buttons and record any deviation in the indicator width.

Non-examples

Tabs restyled as steps. A progress bar in place of the stepper. Circles with connecting lines that need a rounded radius. Future steps that look enabled and reject the click. A spinner on Next. Colour-only completion marks. Validation that blocks Back. Animated slides between panels.

Keys

KeyAction
Tab / Shift+TabReaches each enabled step button, the panel's fields, then Back and Next; future steps are disabled and skipped.
Enter / SpaceOn a step button, goes to that step if it is reachable; on Next, validates the panel and advances; on Back, returns without validating.
EscapeNothing; leaving a wizard is an explicit Cancel or the host's navigation.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Related: button fieldset tabs breadcrumbs progress admin-form

Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-STATE-MATRIX

Form builder form-builder

  • Family: Advanced forms
  • Maturity: draft
  • Priority: L
  • Since: 0.1.0
  • Native control: Native buttons, labelled inputs, fieldsets and ordered field definitions; no drag-only operations.
  • specified
  • demonstrated
  • tested
  • draft

A bounded reference editor for five canonical field kinds, with keyboard ordering, local preview and explicit JSON definition import and export.

Report an issue with this component

Tokens

PartRoleValueUse
root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
root.textcolor.text.defaultobserveduse#e99499Interface and body text.
root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
status.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateReference definition
default

Draft reference · 3 fields · default profile

  1. Name — text, required; stable ID: name
  2. Notes — textarea, optional; stable ID: notes
  3. Notify me — checkbox, optional; stable ID: notify

The interactive builder provides native add, edit, move and remove controls, canonical previews, and explicit JSON transfer. This static specimen does not submit data.

empty
invalid
disabled

Purpose

Build a bounded reference form from text, textarea, select, checkbox and radio fields in the interactive builder. D-021 remains proposed. This draft component does not promote new tokens, roles, profiles or native ports.

Anatomy

Each field has a stable ID, label, help, required flag and, for select/radio, stable option IDs and labels. Add and remove fields, edit definitions and move them with explicit Move up / Move down buttons. Saving an edit validates the complete proposed definition before replacing the current one.

The preview uses the same canonical field renderer and validation model as the validation-recovery composition. Changing a definition clears preview values and errors. Merely moving focus or typing a preview value does not change the definition. Preview state is separate from schema state.

States

The empty state displays an explanation and an add action. An invalid import or definition edit reports a corrective message and leaves the current definition intact. Unavailable movement buttons are disabled at the list boundaries. The default state shows the ordered definition and preview. The static specimen represents the definition; interactive execution evidence is recorded separately.

Keyboard

All operations use native controls. No drag operation is required. Move actions keep focus on the moved field’s controls. Removing a field focuses the next remaining field or the add control. Import and reset return to the add control. Preview submit focuses its error summary; links target stable field control IDs.

Accessibility

Use the canonical label, help and error associations, required markers and radio fieldset/legend semantics. Stable IDs survive JSON round trips and field reordering. Imported strings are text, never markup. No manual screen-reader pass is claimed by test presence.

Portability

Definition schema version 1 pins theme name, version, default profile and constituent component content digest. Accept at most 64 KiB, 20 fields, 20 options per choice field, 120-character labels and 400-character help. Preview text is limited to 2000 characters. Unknown keys, duplicate IDs, unsupported kinds, invalid choices and mismatched theme identity are rejected atomically. An old content identity requires an explicit migration outside this tool.

Everything stays in memory. Only explicit Download definition creates a file, containing the schema and no entered values. Reset clears the definition and preview. There is no autosave, network submission, schema execution, arbitrary HTML/CSS/JavaScript or imported validation expression.

Non-examples

A production backend, conditional logic engine, drag-only editor, arbitrary code generator, persistent account form, or native application port.

Keys

KeyAction
Tab / Shift+TabReach add, field editor, ordering, removal, preview and transfer controls in document order.
Enter / SpaceActivate the focused native button. Move up and Move down preserve stable identity and focus.
Arrow keysUse native select and radio choices in the preview.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Related: admin-form text-field textarea select checkbox radio-group button

Stress fixtures: FX-360 FX-ZOOM-200 FX-DENSITY

Multiple selection multiselect

  • Family: Advanced forms
  • Maturity: stable
  • Priority: R2
  • Since: 1.0.0
  • Native control: Fieldset, legend, search input and native checkboxes
  • specified
  • demonstrated

A searchable native checkbox group that preserves all selected form values.

Report an issue with this component

Tokens

PartRoleValueUse
root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
root.textcolor.text.defaultobserveduse#e99499Interface and body text.
root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
heading.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
secondary.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
control.bgcolor.surface.inputapproveduse#000000Form-control fill.
control.focuscolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
dependency.role-border-width-defaultborder.width.defaultobserveduse1pxEvery border is 1px.
dependency.role-border-width-emphasisborder.width.emphasisobserveduse2pxSelected indicator, sticky header rule, invalid border.
dependency.role-color-action-primary-bgcolor.action.primary.bgapproveduse#7d1310Primary button fill; D-026 darkened it off color12, which stays fixed as heritage ANSI 12.
dependency.role-color-action-primary-hover-bgcolor.action.primary.hover-bgobserveduse#911410Primary button hover (7.92:1 with prose).
dependency.role-color-action-primary-textcolor.action.primary.textobserveduse#f4eeeePrimary button text (9.28:1).
dependency.role-color-border-activecolor.border.activeobserveduse#e53935Active or focused control border.
dependency.role-color-border-disabledcolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
dependency.role-color-interaction-disabled-bgcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
dependency.role-color-interaction-focus-ring-containercolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
dependency.role-color-interaction-hover-bgcolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
dependency.role-color-status-danger-bordercolor.status.danger.borderobserveduse#e53935Danger border, 2px on invalid inputs.
dependency.role-color-status-danger-textcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).
dependency.role-color-text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
dependency.role-density-comfortable-control-heightdensity.comfortable.control-heightobserveduse32px
dependency.role-density-compact-control-heightdensity.compact.control-heightobserveduse24px
dependency.role-focus-offsetfocus.offsetobserveduse-2pxoutline-offset for controls.
dependency.role-focus-ringfocus.ringobserveduse1px dashed #e53935outline on controls and rows.
dependency.role-font-line-height-ui-mdfont.line-height.ui-mdobserveduse18px
dependency.role-font-line-height-ui-smfont.line-height.ui-smobserveduse16px
dependency.role-font-size-ui-mdfont.size.ui-mdobserveduse13px
dependency.role-font-size-ui-smfont.size.ui-smobserveduse12px
dependency.role-icon-size-mdicon.size.mdobserveduse16px
dependency.role-radius-noneradius.noneobserveduse0pxThe only radius. Nothing is rounded.
dependency.role-space-12space.12observeduse12px
dependency.role-space-2space.2observeduse2px
dependency.role-space-24space.24observeduse24px
dependency.role-space-4space.4observeduse4px
dependency.role-space-8space.8observeduse8px

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateDefault
default
Notification topics

3 topics; 1 selected

checked
focus-visible
disabled
no-results

Purpose

Select zero or more named values using a labelled native checkbox list. Local search filters visible choices without clearing selections. Successful checkboxes retain repeated native form keys. Clear selection is an explicit action.

Anatomy

  • group: Fieldset and legend name the choice.
  • filter: Labelled search input filters option labels.
  • options: Native checkboxes remain selected when filtered out.
  • status: Visible count distinguishes matching options from selected values.

States

StatePresentationNon-colour channel
defaultNamed content on the default surface.Native text and structure.
checkedSelected fill and a check indicator.Native checked state.
focus-visibleDashed focus ring.Native keyboard focus position.
disabledDisabled semantic foreground, background and border at full opacity.Native disabled state blocks activation.
no-resultsMuted result count.Zero-results text; existing selected values remain selected.

Keyboard

  • Tab / Shift+Tab: Visit search, clear and each visible enabled checkbox.
  • Space: Toggle the focused checkbox.
  • Escape: Clear a non-empty query without clearing selection.

Accessibility

Keep labels and native checkbox semantics. Hidden choices leave the focus order but retain checked form values. Announce matching and selected counts, including zero. Required selection policy belongs to the host; marking every checkbox required would require every option.

Portability

Wrap labels and actions without changing source order. Use logical spacing in RTL. Preserve native target sizes at both densities; only bounded data regions may scroll horizontally. Use equivalent native semantics and approved roles; record any unsupported behavior as a mapping deviation. The host owns application data, persistence, permissions and services.

Non-examples

Unlabelled controls, color-only status, drag-only operations, hidden required instructions, stolen focus or an invented service success.

Keys

KeyAction
Tab / Shift+TabVisit search, clear and each visible enabled checkbox.
SpaceToggle the focused checkbox.
EscapeClear a non-empty query without clearing selection.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Stress fixtures: FX-320 FX-360 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

Repeater repeater

  • Family: Advanced forms
  • Maturity: stable
  • Priority: R2
  • Since: 1.0.0
  • Native control: Ordered list, inert template and native controls
  • specified
  • demonstrated

Repeat native field rows with stable identities and keyboard ordering.

Report an issue with this component

Tokens

PartRoleValueUse
root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
root.textcolor.text.defaultobserveduse#e99499Interface and body text.
root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
heading.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
secondary.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
control.bgcolor.surface.inputapproveduse#000000Form-control fill.
control.focuscolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
dependency.role-border-width-defaultborder.width.defaultobserveduse1pxEvery border is 1px.
dependency.role-color-border-disabledcolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
dependency.role-color-interaction-disabled-bgcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
dependency.role-color-text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
dependency.role-density-comfortable-control-heightdensity.comfortable.control-heightobserveduse32px
dependency.role-density-compact-control-heightdensity.compact.control-heightobserveduse24px
dependency.role-radius-noneradius.noneobserveduse0pxThe only radius. Nothing is rounded.
dependency.role-space-12space.12observeduse12px
dependency.role-space-2space.2observeduse2px
dependency.role-space-24space.24observeduse24px
dependency.role-space-8space.8observeduse8px

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateDefault
default

    No contacts added.

    empty
    focus-visible
    disabled

    Purpose

    Repeat native fields from trusted inert HTML. Add, remove and reorder preserve row identities. The host supplies fields and handles submission; the component does not execute a schema or provide persistence. A max attribute bounds the number of rows; the supplied example is limited to ten.

    Anatomy

    • rows: Ordered list of independently named field rows.
    • template: Trusted native markup cloned on explicit Add.
    • actions: Add, remove, move up and move down; no drag-only behavior.

    States

    StatePresentationNon-colour channel
    defaultNamed content on the default surface.Native text and structure.
    emptyA muted empty message.Explicit text and retained Add action.
    focus-visibleDashed focus ring.Native keyboard focus position.
    disabledDisabled semantic foreground, background and border at full opacity.Native disabled state blocks activation.

    Keyboard

    • Tab / Shift+Tab: Visit fields and row actions in source order.
    • Enter / Space: Add, remove or move a row. Focus follows the affected row or nearest survivor.

    Accessibility

    Namespace IDs and label/ARIA references for each row. Row identities do not change during reordering. Actions have names and disabled boundary states. Removing a focused row restores focus to a surviving row or Add; announce each explicit operation.

    Portability

    Wrap labels and actions without changing source order. Use logical spacing in RTL. Preserve native target sizes at both densities; only bounded data regions may scroll horizontally. Use equivalent native semantics and approved roles; record any unsupported behavior as a mapping deviation. The host owns application data, persistence, permissions and services.

    Non-examples

    Unlabelled controls, color-only status, drag-only operations, hidden required instructions, stolen focus or an invented service success.

    Keys

    KeyAction
    Tab / Shift+TabVisit fields and row actions in source order.
    Enter / SpaceAdd, remove or move a row. Focus follows the affected row or nearest survivor.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Stress fixtures: FX-320 FX-360 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

    Navigation

    Tabs, breadcrumbs, pagination, sidebar, toolbar, menus, command palette, tree.

    Tabs tabs

    • Family: Navigation
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Custom widget: APG tabs (tablist, tab, tabpanel) with roving tabindexAPG pattern
    • specified
    • demonstrated
    • tested

    A tablist of buttons that switches between panels in place; the selected tab carries a 2px indicator bar and bright text, never a fill.

    Report an issue with this component

    Open component workbench

    Tokens

    PartRoleValueUse
    list.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    list.bordercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
    tab.textcolor.text.defaultobserveduse#e99499Interface and body text.
    tab.text-selectedcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    tab.text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
    tab.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
    tab.bg-pressedcolor.interaction.pressed.bgobserveduse#420f0cPressed fill.
    tab.indicatorcolor.border.selected-indicatorobserveduse#e539352px indicator bar on the selected tab or nav item.
    tab.indicator-inactivecolor.border.selected-indicator-inactiveobserveduse#9e231fIndicator bar when the container is not focused.
    tab.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    panel.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    panel.textcolor.text.defaultobserveduse#e99499Interface and body text.

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateDefaultOverflow
    default

    Window gaps, bar height and the focus follows mouse setting.

    Values live in tokens; this document says what each role means.

    hover
    focus-visible
    selected
    selected+focus-visible
    selected+container-inactive
    disabled

    Purpose

    Switches between peer panels in place without leaving the page. Tabs are navigation within one view; for moving between views use sidebar-nav, for mutually exclusive options inside a form use radio-group or segmented-control.

    Anatomy

    A tablist strip on color.surface.default with a 1px color.border.divider rule beneath it; tab buttons in color.text.default; the selected tab in color.text.bright with a 2px color.border.selected-indicator bottom bar that sits on the rule; the panel below in color.text.default. Tabs carry no fill and no box; the bar is the only ornament.

    States

    StateVisualNon-colour channel
    defaulttext color.text.default; transparent 2px bottom edge
    hoverbackground → color.interaction.hover.bg; text unchangedcursor: pointer
    focus-visiblering 1px dashed color.interaction.focus.ring at −2pxthe ring
    selectedtext color.text.bright; 2px color.border.selected-indicator bararia-selected="true"; the bar; tabindex 0
    selected+focus-visiblethe bar and the ring togetherboth visible
    selected+container-inactivebar → color.border.selected-indicator-inactive; text stays brightlightness drop of the bar; the container’s own inactive state
    disabledtext color.text.disabled; no hover; bar hidden unless selecteddisabled or aria-disabled; cursor: not-allowed

    Precedence: disabled > selected > hover; focus-visible is always drawn. Pressing a tab uses color.interaction.pressed.bg for the duration of the press only.

    Keyboard

    One tab stop for the whole strip: the selected tab has tabindex="0", every other tab tabindex="-1" (roving tabindex). Left and Right move focus and wrap; Home and End jump to the ends; Enter and Space activate when activation is manual. Automatic activation is the default in this theme because panels are cheap; use manual activation when a panel is expensive to render. The panel is a tab stop only when it has no focusable content.

    Accessibility

    The tablist carries aria-label or aria-labelledby; each tab has aria-controls pointing at its panel and each panel aria-labelledby pointing back. Vertical tablists set aria-orientation="vertical" and swap the arrow keys. Contrast: tab text 8.43:1, selected text 10.10:1, indicator 4.57:1 (≥ 3:1) and ring 4.57:1 on the panel surface. Each tab is at least 24×24 CSS pixels in compact density with 4px between neighbours. The indicator is never the only signal: aria-selected and the bright text travel with it.

    Portability

    A border-bottom that changes colour and an outline are all the drawing needed. Toolkits that cannot draw a partial bottom border draw a 2px rule across the full tab width. Hosts that have their own tab strip (browsers, editors) keep their keyboard model and take only the colours and the 2px bar.

    Non-examples

    Pill or filled tabs. A selected tab drawn with the selection fill. Rounded corners on the tab or the bar. A tab strip that wraps to two lines. A tab that changes only its text colour when selected. A glow instead of the dashed ring. Every tab in the tab order. Disabling by opacity.

    Keys

    KeyAction
    TabMoves focus to the selected tab (roving tabindex); a second Tab leaves the tablist for the panel.
    Left / RightMoves focus to the previous or next tab and wraps; with automatic activation the panel follows.
    Home / EndMoves focus to the first or last tab.
    Enter / SpaceActivates the focused tab when activation is manual.
    DeleteCloses the focused tab where tabs are closable (not in this reference).

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: sidebar-nav toolbar segmented-control disclosure

    Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-OVERFLOW FX-STATE-MATRIX

    Breadcrumbs breadcrumbs

    • Family: Navigation
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Native control: native nav > ol with aria-current="page" on the last itemAPG pattern
    • specified
    • demonstrated

    The path from the root to the current page as an ordered list of links separated by slashes; the last item is the current page and not a link.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    link.textcolor.text.linkapproveduse#f73f35Strong red link text, distinct from rose body text and headings; retain the underline.
    link.underlinecolor.text.link-underlineobserveduse#dc282eLink underline.
    link.text-hovercolor.text.link-hoverobserveduse#f4eeeeLink text on hover, over interaction.hover.bg-strong.
    link.bg-hovercolor.interaction.hover.bg-strongobserveduse#630f0dHover on menu items; D-027 moved links to interaction.hover.bg.
    link.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    current.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    separator.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    ellipsis.textcolor.text.defaultobserveduse#e99499Interface and body text.
    ellipsis.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.

    Purpose

    Shows where the current page sits in a hierarchy and lets the user jump to any ancestor. Breadcrumbs are secondary navigation: they never replace the sidebar or the page title, and they are omitted on the root page.

    Anatomy

    A nav labelled “Breadcrumb” wrapping an ol. Each ancestor is a link in color.text.link with a 1px color.text.link-underline; a / separator in color.text.muted follows every item but the last; the last item is the current page in color.text.bright with aria-current="page". When the trail is deeper than the space allows, the middle levels collapse behind an ellipsis button that names how many levels it hides.

    States

    StateVisualNon-colour channel
    defaultlinks color.text.link, 1px underline; separators color.text.muted; current color.text.brightunderline on links; none on the current page
    hoverlink background → color.interaction.hover.bg-strong; text → color.text.link-hoverunderline thickens 1px → 2px; cursor
    focus-visiblering 1px dashed color.interaction.focus.ring at −2px around the linkthe ring
    currenttext color.text.bright; no underline; no hoveraria-current="page"; no underline
    truncatedthe middle levels are replaced by an button in color.text.defaultaria-expanded="false" on the button; its label counts the hidden levels

    Keyboard

    Every ancestor link is a tab stop in trail order. The ellipsis button is a tab stop that discloses the hidden levels in place on Enter or Space and sets its own aria-expanded; focus stays on the button so the newly revealed links are the next Tab presses.

    Accessibility

    aria-label="Breadcrumb" on the nav, translated. The separator is aria-hidden so nothing voices “slash”; the list structure gives the count. aria-current="page" marks the last item whether or not it is a link. Hidden levels stay in the DOM under the ellipsis (hidden until disclosed) so a find-in-page still reaches them. Contrast: link text 10.10:1, current 10.10:1, separator 5.66:1, underline 4.57:1 on the panel surface. Each link is at least 24 CSS pixels tall through its line box and padding.

    Portability

    Plain inline links and text; the only requirement is an inline-start margin on the separator that flips in RTL. Toolkits without an underline draw the link in the link colour and record the deviation. The ellipsis disclosure is optional; hosts without it show the full trail and let it wrap.

    Non-examples

    Chevrons, arrows or bullets as separators. A trail that ends with the site name instead of the current page. The current page drawn as a link with an underline. Automatic truncation by text-overflow that hides levels without a way to reach them. A trail that scrolls horizontally. Uppercase or letter-spaced items. Separators that are read aloud.

    Keys

    KeyAction
    Tab / Shift+TabMoves through the links in order; the current page is skipped when it is not a link.
    EnterFollows the focused link, or discloses the hidden levels from the ellipsis button.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: link sidebar-nav pagination tree

    Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-STATE-MATRIX

    Pagination pagination

    • Family: Navigation
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Native control: native nav > ul of links with aria-current="page"
    • specified
    • demonstrated

    Page links for a long result set; the current page takes the selection fill and aria-current, and the compact form reads "3 of 12" between previous and next.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    link.textcolor.text.defaultobserveduse#e99499Interface and body text.
    link.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
    link.bg-pressedcolor.interaction.pressed.bgobserveduse#420f0cPressed fill.
    link.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    link.text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
    current.bgcolor.interaction.selection.bgapproveduse#531310Selected row, tab, workspace; D-027 recessed the fill, leaving the 2px indicator and the check to carry selection.
    current.textcolor.text.on-selectionobserveduse#f4eeeeText on the selection fill.
    current.ringcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
    gap.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    status.textcolor.text.defaultobserveduse#e99499Interface and body text.
    status.emphasiscolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateDefaultCompact
    default
    hover
    focus-visible
    current
    disabled

    Purpose

    Moves through a result set that is split into pages. Pagination is for sets whose size is known; use a “load more” button or infinite scroll for feeds, and a range field for jumping to an arbitrary offset.

    Anatomy

    A nav labelled “Pagination” holding a ul: previous, the page links with an aria-hidden gap where pages are skipped, next. Every page link is a square target in color.text.default with no border; the current page is filled with color.interaction.selection.bg and color.text.on-selection. The compact variant keeps previous and next and replaces the numbers with “3 of 12”, the current number in color.text.bright.

    States

    StateVisualNon-colour channel
    defaulttext color.text.default; no fill; no border
    hoverbackground → color.interaction.hover.bgcursor: pointer
    focus-visiblering 1px dashed color.interaction.focus.ring at −2px; on the current page the ring is color.interaction.focus.ring-containerthe ring
    currentfill color.interaction.selection.bg; text color.text.on-selection; no hoveraria-current="page"
    disabledtext color.text.disabled; no fill; no hoveraria-disabled="true"; no href; cursor: not-allowed

    Pressing a link uses color.interaction.pressed.bg for the duration of the press only.

    Keyboard

    Plain links in document order: previous, the pages, next. A disabled end has no href, so it is not a tab stop and cannot be activated. The current page remains a link to itself so a keyboard user can reload it.

    Accessibility

    aria-label="Pagination" on the nav; a second pagination on the same page gets a distinct label. Previous and next carry a visible word, not just a glyph, and aria-label gives the target page number when it is known (“Previous page, 2”). The gap is aria-hidden; the list count tells a screen reader how many links follow. Contrast: link text 8.43:1, current text 12.47:1 on the selection fill, ring-container 7.48:1 on the fill, disabled 3.24:1 (exempt). Targets are at least 24×24 CSS pixels in compact density.

    Portability

    Links with a background and an outline; nothing else. Hosts that cannot remove href from a disabled link use a disabled button for the ends and record it. The compact variant is plain text and two links and ports anywhere.

    Non-examples

    Rounded or circular page buttons. A border around every page link. The current page marked by colour or bold alone without aria-current. Previous and next as glyph-only links without a label. A disabled end that still has an href. Pagination that hides the last page number. A row that scrolls horizontally.

    Keys

    KeyAction
    Tab / Shift+TabMoves through previous, each page link and next in order; a disabled end has no href and is not a stop.
    EnterFollows the focused link.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: table data-table link button

    Stress fixtures: FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-STATE-MATRIX

    Sidebar navigation sidebar-nav

    • Family: Navigation
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Native control: native nav with nested ul lists; groups are buttons with aria-expandedAPG pattern
    • specified
    • demonstrated

    A vertical list of section links with optional nested groups; the current section carries a 2px inline-start indicator and bright text, and the rail collapses to icons.

    Report an issue with this component

    Open component workbench

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    root.bordercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
    link.textcolor.text.defaultobserveduse#e99499Interface and body text.
    link.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
    link.bg-pressedcolor.interaction.pressed.bgobserveduse#420f0cPressed fill.
    link.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    link.indicatorcolor.border.selected-indicatorobserveduse#e539352px indicator bar on the selected tab or nav item.
    link.indicator-inactivecolor.border.selected-indicator-inactiveobserveduse#9e231fIndicator bar when the container is not focused.
    current.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    selected.bgcolor.interaction.selection.bgapproveduse#531310Selected row, tab, workspace; D-027 recessed the fill, leaving the 2px indicator and the check to carry selection.
    selected.textcolor.interaction.selection.textobserveduse#f4eeeeText on the selection.
    selected.ringcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
    selected.inactive-bgcolor.interaction.selection.inactive-bgobserveduse#420f0cSelection while the container is not focused.
    selected.inactive-textcolor.interaction.selection.inactive-textobserveduse#e99499Text on the inactive selection (7.02:1).
    icon.strokecolor.icon.defaultobserveduse#e99499Icons take the text colour (currentColor in CSS).
    group.chevroncolor.icon.decorativeobserveduse#a3676bDecorative glyphs (3:1 as graphics, never text).

    Purpose

    Moves between the sections of an application. The sidebar is the primary navigation of a settings panel, an admin area or a documentation site; tabs switch views inside one section, and a tree browses data rather than sections.

    Anatomy

    A nav on color.surface.default with a 1px color.border.divider inline-end edge. Each link is one row: an icon slot, a label in color.text.default, and a transparent 2px inline-start edge. The current link colours that edge with color.border.selected-indicator and its text with color.text.bright. Groups are buttons with a chevron in color.icon.decorative; their children sit in a sublist indented by one icon width. Collapsed, the rail keeps the icons and hides the labels visually.

    States

    StateVisualNon-colour channel
    defaulttext color.text.default; no fill; transparent inline-start edge
    hoverbackground → color.interaction.hover.bgcursor: pointer
    focus-visiblering 1px dashed color.interaction.focus.ring at −2pxthe ring
    current2px color.border.selected-indicator inline-start bar; text color.text.brightaria-current="page"; the bar
    selectedfill color.interaction.selection.bg with color.interaction.selection.text; the ring in color.interaction.focus.ring-container when focusedaria-selected on a listbox-style rail; the fill’s on-fill text
    selected+container-inactivefill color.interaction.selection.inactive-bg with color.interaction.selection.inactive-text; no ringlightness drop between the two fills
    expandedthe group’s chevron rotated 90°; its sublist shownaria-expanded="true"; the children are present
    collapsedlabels visually hidden; icons centred; the current bar and fills unchangedthe labels remain for assistive technology and as tooltips

    current is where the user is; selected is what the user chose in a rail that drives a detail pane. A rail is one or the other, never both at once.

    Keyboard

    Every link and every group button is a tab stop in document order; children of a closed group are hidden and skipped. Enter follows a link; Enter or Space toggles a group and leaves focus on the button. There is no arrow-key model: the rail is a list of links, not a tree, so the native tab order is the whole contract.

    Accessibility

    aria-label on the nav distinguishes it from other landmarks. The current link carries aria-current="page"; a rail that drives a detail pane uses a listbox with aria-selected instead of links. Group buttons carry aria-expanded and aria-controls; the sublist is hidden until expanded so its links leave the tab order. Collapsed labels use a clip-rect hiding, not display: none, so names survive; icon-only links also get a title. Contrast: text 8.43:1, current text 10.10:1, indicator 4.57:1, selection text 12.47:1 on the fill, inactive selection 7.02:1. Rows are at least 24 CSS pixels tall in compact density.

    Portability

    A border-inline-start, a background and an outline; the chevron is an SVG. Toolkits without logical borders draw the bar on the left in LTR and on the right in RTL explicitly. The collapsed rail is a width change and a hidden label; hosts that cannot hide labels while keeping their names show the full rail.

    Non-examples

    A filled or rounded current item. The indicator on the inline-end edge. A current item marked by bold text alone. Labels removed from the DOM when collapsed. A group whose children stay in the tab order while hidden. A rail that scrolls horizontally. Icon-only links with no accessible name. Hover that changes the text colour.

    Keys

    KeyAction
    Tab / Shift+TabMoves through links and group buttons in document order; hidden children are skipped.
    EnterFollows a link or toggles a group.
    SpaceToggles a group.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: tabs breadcrumbs tree disclosure drawer

    Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-STATE-MATRIX

    Toolbar toolbar

    • Family: Navigation
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Custom widget: APG toolbar with roving tabindex; buttons, toggle buttons with aria-pressed, and a separatorAPG pattern
    • specified
    • demonstrated

    A row of related controls under one tab stop with arrow-key movement; ghost buttons, a vertical separator, and a "more" button when the row overflows.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.chromeapproveduse#090707Window chrome, title bars, bars.
    root.bordercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
    button.textcolor.text.defaultobserveduse#e99499Interface and body text.
    button.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
    button.bg-pressedcolor.interaction.pressed.bgobserveduse#420f0cPressed fill.
    button.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    button.text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
    toggled.bgcolor.interaction.pressed.bgobserveduse#420f0cPressed fill.
    toggled.bordercolor.border.activeobserveduse#e53935Active or focused control border.
    toggled.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    separator.colorcolor.border.defaultobserveduse#531310Decorative border (1.39:1; never the only edge of a control).
    more.chevroncolor.icon.decorativeobserveduse#a3676bDecorative glyphs (3:1 as graphics, never text).

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateDefaultOverflow
    default
    hover
    focus-visible
    disabled
    toggled

    Purpose

    Groups the frequent actions of a view into one row that costs one tab stop. A toolbar is for actions on the content beneath it; navigation between views belongs in tabs or the sidebar, and a set of mutually exclusive choices in a segmented control or radio group.

    Anatomy

    A div with role="toolbar" on color.surface.chrome with a 1px color.border.divider bottom edge. Inside, ghost buttons in color.text.default with a transparent 1px border, vertical separators in color.border.default between groups, and in the overflow variant a trailing “More” button that opens a menu with the controls that do not fit. Toggle buttons carry aria-pressed.

    States

    StateVisualNon-colour channel
    defaulttext color.text.default; no fill; transparent border
    hoverbackground → color.interaction.hover.bgcursor: pointer
    focus-visiblering 1px dashed color.interaction.focus.ring at −2pxthe ring
    disabledtext color.text.disabled; no fill; no hoverdisabled; cursor: not-allowed; skipped by the arrow keys
    toggledfill color.interaction.pressed.bg; 1px color.border.active border; text color.text.brightaria-pressed="true"; the border

    Pressing a button uses color.interaction.pressed.bg for the duration of the press only; a toggled button keeps it.

    Keyboard

    The toolbar is one tab stop: the last focused control (initially the first enabled one) has tabindex="0", every other control tabindex="-1". Left and Right move between controls and wrap; Home and End jump to the ends; Enter and Space activate. Disabled controls are skipped. Vertical toolbars declare aria-orientation="vertical" and use Up and Down. Without script every button is a tab stop, which is acceptable, not ideal.

    Accessibility

    aria-label names the toolbar; a page with several toolbars gives each a distinct name. Toggle buttons expose aria-pressed; their label does not change with the state. Separators are role="separator" with aria-orientation="vertical" and are never focusable. Icon-only buttons carry aria-label and a tooltip. Contrast: text 8.60:1 on the chrome surface, toggled text 8.41:1 on the pressed fill, the toggled border 3.81:1, ring 4.66:1. Every control is at least 24×24 CSS pixels with 4px between neighbours in compact density.

    Portability

    Ghost buttons with a background and a border; the separator is a 1px rule. Toolkits with a native toolbar keep their own keyboard model and take the colours. The overflow menu is a menu component; hosts without one wrap the row instead and record the deviation.

    Non-examples

    Buttons with a visible border at rest. A filled primary button inside the toolbar. Rounded buttons or a pill-shaped toolbar. Every button in the tab order when script is available. A toggled state shown by colour alone without aria-pressed. A toolbar that wraps to two lines. A separator that receives focus. Disabling by opacity.

    Keys

    KeyAction
    Tab / Shift+TabEnters or leaves the toolbar; one control has tabindex 0 (roving tabindex).
    Left / RightMoves focus to the previous or next enabled control; wraps at the ends; Up and Down when aria-orientation is vertical.
    Home / EndMoves focus to the first or last control.
    Enter / SpaceActivates the focused button or toggles a toggle button.
    EscapeRestores the previous value in a toolbar that edits, otherwise nothing.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: button icon-button menu tabs button-group

    Stress fixtures: FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-OVERFLOW FX-STATE-MATRIX

    Menu menu

    • Family: Navigation
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Custom widget: APG menu button (button with aria-haspopup="menu") opening a menu of menuitem, menuitemcheckbox and separatorAPG pattern
    • specified
    • demonstrated
    • tested

    A menu button that opens a list of actions on the raised surface inside a 1px overlay border; the active item is the selection fill and check items show a glyph.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    button.textcolor.text.defaultobserveduse#e99499Interface and body text.
    button.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    button.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    button.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
    button.bg-opencolor.interaction.pressed.bgobserveduse#420f0cPressed fill.
    button.border-opencolor.border.activeobserveduse#e53935Active or focused control border.
    button.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    surface.bgcolor.surface.raisedapproveduse#160b0bSticky headers, menus, popovers; D-027 recessed it so an open list reads as depth rather than a lighter panel.
    surface.bordercolor.border.overlayproposeduse-and-reportD-008#e53935Every floating layer's 1px border.
    item.textcolor.text.defaultobserveduse#e99499Interface and body text.
    item.bg-hovercolor.interaction.hover.bg-strongobserveduse#630f0dHover on menu items; D-027 moved links to interaction.hover.bg.
    item.text-hovercolor.text.link-hoverobserveduse#f4eeeeLink text on hover, over interaction.hover.bg-strong.
    item.text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
    active.bgcolor.interaction.selection.bgapproveduse#531310Selected row, tab, workspace; D-027 recessed the fill, leaving the 2px indicator and the check to carry selection.
    active.textcolor.interaction.selection.textobserveduse#f4eeeeText on the selection.
    active.ringcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
    check.glyphcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    shortcut.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    separator.colorcolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
    chevron.colorcolor.icon.decorativeobserveduse#a3676bDecorative glyphs (3:1 as graphics, never text).

    Purpose

    Offers a short list of actions behind one button. A menu is for commands; choosing a value belongs in select or combobox, and moving between views in tabs or the sidebar. Menus close as soon as an action runs.

    Anatomy

    A menu button, styled as a secondary button, that opens a list on color.surface.raised inside a 1px color.border.overlay frame. Items are buttons in color.text.default with a check gutter at the inline start, the label, and an optional shortcut hint in color.text.muted. Separators are 1px color.border.divider rules. The active item, whether reached by pointer or by arrow key, is the selection fill color.interaction.selection.bg with color.interaction.selection.text. The reference renders the menu open in flow beneath the button; a host positions it at z.popover.

    States

    StateVisualNon-colour channel
    defaultthe button at rest; the list on color.surface.raised with the color.border.overlay frame
    hoveritem background → color.interaction.hover.bg-strong; text → color.text.link-hovercursor: pointer
    focus-visiblering 1px dashed color.interaction.focus.ring at −2px on the button; on the active item the ring is color.interaction.focus.ring-containerthe ring
    openbutton fill color.interaction.pressed.bg with 1px color.border.active; the list shownaria-expanded="true"; the list is present
    closedthe button at rest; the list hiddenaria-expanded="false"; the list is absent from the tree
    disableditem text color.text.disabled; no hover; still focusable by arrow keys when aria-disabledaria-disabled="true"; cursor: not-allowed
    checkedthe ✓ glyph in color.text.bright in the gutteraria-checked="true"; the glyph
    selectedthe active item: fill color.interaction.selection.bg with color.interaction.selection.textfocus is on the item; aria-activedescendant where used

    Precedence: disabled > selected > hover; focus-visible is always drawn.

    Keyboard

    The button opens on Enter, Space or Down (focus on the first item) and on Up (focus on the last). Inside, Up and Down move and wrap, Home and End jump, Right opens a submenu and Left closes it, typing a letter jumps to the next matching item. Enter or Space activates; a check item toggles without closing. Escape closes and returns focus to the button; Tab closes and continues the tab order. Focus never rests on a separator.

    Accessibility

    The button carries aria-haspopup="menu", aria-expanded and aria-controls; the list role="menu" and aria-labelledby pointing at the button. Items are role="menuitem" or role="menuitemcheckbox" with aria-checked; disabled items use aria-disabled so they remain reachable and announced. Shortcut hints are text, not aria-keyshortcuts alone. Contrast: item text 8.43:1 and shortcut 5.66:1 on the raised surface, active text 12.47:1 on the fill, the frame 4.57:1, ring-container 7.48:1 on the fill. Items are the row height, at least 24 CSS pixels in compact density.

    Portability

    A framed box with rows; the active row is a fill, the frame a border, the ring an outline. Toolkits with native menus keep their keyboard model and take the surface, frame and fill colours. Hosts that cannot draw the frame in the overlay colour draw it in the strong border colour and record the deviation.

    Non-examples

    A shadow under the menu. Rounded corners on the menu or the items. An active item marked by text colour alone. A hover fill that differs from every other menu in the product. Icons in the check gutter of a plain menuitem. A menu that stays open after an action. Items that are links styled as menu items without role="menuitem". Disabling by opacity.

    Keys

    KeyAction
    Enter / Space / DownOn the button, opens the menu and focuses the first item; Up opens it and focuses the last.
    Down / UpMoves to the next or previous item and wraps.
    Home / EndMoves to the first or last item.
    Right / LeftOpens a submenu and focuses its first item; Left closes the submenu and returns to the parent item.
    Enter / SpaceActivates the focused item; a check item toggles and the menu stays open.
    EscapeCloses the menu and returns focus to the button.
    TabCloses the menu and moves focus to the next tab stop after the button.
    A-ZMoves focus to the next item starting with the typed character.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: button toolbar command-palette popover select

    Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-STATE-MATRIX

    Command palette command-palette

    • Family: Navigation
    • Maturity: stable
    • Priority: R2
    • Since: 1.0.0
    • Custom widget: comboboxAPG pattern
    • specified
    • demonstrated

    A compact square modal command prompt with local results and category labels.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    root.textcolor.text.defaultobserveduse#e99499Interface and body text.
    root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    heading.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    secondary.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    control.bgcolor.surface.inputapproveduse#000000Form-control fill.
    control.focuscolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    dependency.role-border-width-defaultborder.width.defaultobserveduse1pxEvery border is 1px.
    dependency.role-border-width-emphasisborder.width.emphasisobserveduse2pxSelected indicator, sticky header rule, invalid border.
    dependency.role-color-border-overlaycolor.border.overlayproposeduse-and-reportD-008#e53935Every floating layer's 1px border.
    dependency.role-color-border-selected-indicatorcolor.border.selected-indicatorobserveduse#e539352px indicator bar on the selected tab or nav item.
    dependency.role-color-interaction-selection-bgcolor.interaction.selection.bgapproveduse#531310Selected row, tab, workspace; D-027 recessed the fill, leaving the 2px indicator and the check to carry selection.
    dependency.role-color-interaction-selection-textcolor.interaction.selection.textobserveduse#f4eeeeText on the selection.
    dependency.role-color-surface-backdropcolor.surface.backdropproposeduse-and-reportD-008rgb(0 0 0 / 65%)Behind modal dialogs.
    dependency.role-color-surface-overlaycolor.surface.overlayobserveduse#241010Dialogs and drawers.
    dependency.role-density-comfortable-control-heightdensity.comfortable.control-heightobserveduse32px
    dependency.role-density-compact-control-heightdensity.compact.control-heightobserveduse24px
    dependency.role-radius-noneradius.noneobserveduse0pxThe only radius. Nothing is rounded.
    dependency.role-space-12space.12observeduse12px
    dependency.role-space-16space.16observeduse16px
    dependency.role-space-2space.2observeduse2px
    dependency.role-space-8space.8observeduse8px

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateDefault
    default

    Command prompt

    • SPEC Explore foundations
    • BUILD Browse components
    • AGENT Prepare a copy kit

    3 commands

    open
    closed
    focus-visible
    no-results

    Purpose

    Find and invoke local commands from a compact square floating utility panel. One prompt filters dense rows with category labels. Results are caller-supplied links or bounded actions; no remote search occurs. The host may opt into Ctrl+K or Cmd+K.

    Anatomy

    • trigger: Named native button opens the utility panel.
    • prompt: Labelled combobox input retains focus while navigating results.
    • results: Listbox results include category and command text.
    • dialog: Native modal dialog provides containment and return.

    States

    StatePresentationNon-colour channel
    defaultOne prompt and dense command rows.Visible names and categories.
    openSquare overlay surface and border.Native modal dialog and active-descendant relationship.
    closedPanel absent.Opener remains focusable.
    focus-visibleDashed input ring.Input retains DOM focus while results change.
    no-resultsMuted zero-results status.Explicit result count and no active descendant.

    Keyboard

    • Ctrl+K / Cmd+K: Open when the host explicitly enables the shortcut.
    • Up / Down: Move the active result while retaining input focus.
    • Enter: Invoke the active enabled result and close.
    • Escape: Close and restore the opener.
    • Tab / Shift+Tab: Cycle through native modal controls.

    Accessibility

    Combine native modal focus behavior with the editable combobox pattern. Result names include their category and command text; selection uses the approved selected roles. Escape closes once and restores focus. Required site navigation remains available outside the palette without JavaScript. Do not globally intercept shortcuts unless the host opts in.

    Portability

    Wrap labels and actions without changing source order. Use logical spacing in RTL. Preserve native target sizes at both densities; only bounded data regions may scroll horizontally. Use equivalent native semantics and approved roles; record any unsupported behavior as a mapping deviation. The host owns application data, persistence, permissions and services.

    Non-examples

    Unlabelled controls, color-only status, drag-only operations, hidden required instructions, stolen focus or an invented service success.

    Keys

    KeyAction
    Ctrl+K / Cmd+KOpen when the host explicitly enables the shortcut.
    Up / DownMove the active result while retaining input focus.
    EnterInvoke the active enabled result and close.
    EscapeClose and restore the opener.
    Tab / Shift+TabCycle through native modal controls.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Stress fixtures: FX-320 FX-360 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

    Tree tree

    • Family: Navigation
    • Maturity: stable
    • Priority: R2
    • Since: 1.0.0
    • Custom widget: treeviewAPG pattern
    • specified
    • demonstrated

    Hierarchical navigation with explicit expansion and one roving tab stop.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    root.textcolor.text.defaultobserveduse#e99499Interface and body text.
    root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    heading.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    secondary.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    control.bgcolor.surface.inputapproveduse#000000Form-control fill.
    control.focuscolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    dependency.role-border-width-defaultborder.width.defaultobserveduse1pxEvery border is 1px.
    dependency.role-border-width-emphasisborder.width.emphasisobserveduse2pxSelected indicator, sticky header rule, invalid border.
    dependency.role-color-border-selected-indicatorcolor.border.selected-indicatorobserveduse#e539352px indicator bar on the selected tab or nav item.
    dependency.role-color-interaction-selection-bgcolor.interaction.selection.bgapproveduse#531310Selected row, tab, workspace; D-027 recessed the fill, leaving the 2px indicator and the check to carry selection.
    dependency.role-color-interaction-selection-textcolor.interaction.selection.textobserveduse#f4eeeeText on the selection.
    dependency.role-color-text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
    dependency.role-density-comfortable-control-heightdensity.comfortable.control-heightobserveduse32px
    dependency.role-density-compact-control-heightdensity.compact.control-heightobserveduse24px
    dependency.role-radius-noneradius.noneobserveduse0pxThe only radius. Nothing is rounded.
    dependency.role-space-12space.12observeduse12px
    dependency.role-space-16space.16observeduse16px
    dependency.role-space-2space.2observeduse2px
    dependency.role-space-8space.8observeduse8px

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateDefault
    default
    • Source
      • App.vue
      • styles.css
    • README.md
    selected
    expanded
    collapsed
    focus-visible
    disabled

    Purpose

    Navigate hierarchical items with explicit expansion and a single roving tab stop. Selection differs from expansion. Caller-supplied nodes represent identities; activation emits an event and never invents file access.

    Anatomy

    • tree: Labelled tree with nested groups.
    • item: Named treeitems expose selection; parents also expose expansion.
    • children: A nested group hidden when the parent collapses.

    States

    StatePresentationNon-colour channel
    defaultVisible named tree items.Tree and group hierarchy.
    selectedSelected fill, text and start indicator.aria-selected.
    expandedDownward marker and visible children.aria-expanded=true.
    collapsedSide marker and hidden children.aria-expanded=false; children leave focus order.
    focus-visibleDashed ring on the item’s own label.Roving native focus.
    disabledDisabled text at full opacity.aria-disabled blocks selection.

    Keyboard

    • Up / Down / Home / End: Move through visible items in source order.
    • Right / Left: Expand or enter a parent, collapse it or return to its parent. Mirror these keys in RTL.
    • Enter / Space: Select the focused enabled item.
    • Typing: Move to the next visible label starting with the character.

    Accessibility

    Implement the linked tree pattern. Only one visible item has tabindex=0. Labels exclude descendant text. Collapsing a parent of the focused item moves focus to that parent. Selection has a programmatic state and border indicator; disabled items do not activate.

    Portability

    Wrap labels and actions without changing source order. Use logical spacing in RTL. Preserve native target sizes at both densities; only bounded data regions may scroll horizontally. Use equivalent native semantics and approved roles; record any unsupported behavior as a mapping deviation. The host owns application data, persistence, permissions and services.

    Non-examples

    Unlabelled controls, color-only status, drag-only operations, hidden required instructions, stolen focus or an invented service success.

    Keys

    KeyAction
    Up / Down / Home / EndMove through visible items in source order.
    Right / LeftExpand or enter a parent, collapse it or return to its parent. Mirror these keys in RTL.
    Enter / SpaceSelect the focused enabled item.
    TypingMove to the next visible label starting with the character.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Stress fixtures: FX-320 FX-360 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

    Disclosure disclosure

    • Family: Navigation
    • Maturity: stable
    • Priority: R2
    • Since: 1.0.0
    • Native control: Native details and summary
    • specified
    • demonstrated

    Native details and summary for supporting content.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    root.textcolor.text.defaultobserveduse#e99499Interface and body text.
    root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    heading.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    secondary.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    control.bgcolor.surface.inputapproveduse#000000Form-control fill.
    control.focuscolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    dependency.role-border-width-defaultborder.width.defaultobserveduse1pxEvery border is 1px.
    dependency.role-border-width-emphasisborder.width.emphasisobserveduse2pxSelected indicator, sticky header rule, invalid border.
    dependency.role-color-border-activecolor.border.activeobserveduse#e53935Active or focused control border.
    dependency.role-color-border-disabledcolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
    dependency.role-color-interaction-disabled-bgcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
    dependency.role-color-text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
    dependency.role-density-comfortable-control-heightdensity.comfortable.control-heightobserveduse32px
    dependency.role-density-compact-control-heightdensity.compact.control-heightobserveduse24px
    dependency.role-radius-noneradius.noneobserveduse0pxThe only radius. Nothing is rounded.
    dependency.role-space-12space.12observeduse12px
    dependency.role-space-2space.2observeduse2px
    dependency.role-space-8space.8observeduse8px

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateDefault
    default
    Additional connection settings

    This local example stores no credentials. Choose connection settings in the host application.

    expanded
    collapsed
    focus-visible

    Purpose

    Reveal supporting content with native details and summary. Essential instructions stay outside a collapsed disclosure. The summary supplies a complete accessible name; content remains in normal reading order.

    Anatomy

    • details: Native expanded state and content container.
    • summary: Visible name and native disclosure marker.

    States

    StatePresentationNon-colour channel
    defaultNamed content on the default surface.Native text and structure.
    expandedExpanded content and native marker.Native open state exposes the content.
    collapsedOnly the summary remains visible.Native closed content leaves the focus order.
    focus-visibleDashed focus ring.Native keyboard focus position.

    Keyboard

    • Tab / Shift+Tab: Reach the summary and expanded interactive content.
    • Enter / Space: Toggle native details.

    Accessibility

    Keep the native marker and summary semantics. Do not add a competing aria-expanded value. Required instructions and the portal’s normative content are never placed only inside a disclosure.

    Portability

    Wrap labels and actions without changing source order. Use logical spacing in RTL. Preserve native target sizes at both densities; only bounded data regions may scroll horizontally. Use equivalent native semantics and approved roles; record any unsupported behavior as a mapping deviation. The host owns application data, persistence, permissions and services.

    Non-examples

    Unlabelled controls, color-only status, drag-only operations, hidden required instructions, stolen focus or an invented service success.

    Keys

    KeyAction
    Tab / Shift+TabReach the summary and expanded interactive content.
    Enter / SpaceToggle native details.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Stress fixtures: FX-320 FX-360 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

    Information display

    Cards, lists, badges, chips, avatars, descriptions, tables, timelines, simple charts.

    Card card

    • Family: Information display
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Native control: native article or section; link cards are a single anchor; selectable cards are options inside a listboxAPG pattern
    • specified
    • demonstrated

    A bordered panel that groups a title, body and metadata; a link card makes the whole panel one link, a selectable card is an option with the selection fill.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    root.bordercolor.border.defaultobserveduse#531310Decorative border (1.39:1; never the only edge of a control).
    root.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
    root.border-hovercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    root.ringcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
    title.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    body.textcolor.text.defaultobserveduse#e99499Interface and body text.
    meta.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    selected.bgcolor.interaction.selection.bgapproveduse#531310Selected row, tab, workspace; D-027 recessed the fill, leaving the 2px indicator and the check to carry selection.
    selected.textcolor.interaction.selection.textobserveduse#f4eeeeText on the selection.
    selected.ringcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateDefaultLink cardSelectable
    default

    Window gaps

    Inner 14px, outer −2px; the bar sits above the gap and the border is 1px.

    Decided in D-009 · 3 fixtures

    Tiling Windows fill the screen without overlap; the gap is the only ornament. Default
    Floating Windows overlap and carry the one shadow the theme permits. Dialogs and tools
    hover
    focus-visible
    selected
    selected+focus-visible

    Purpose

    Groups a small unit of content — a title, a line or two, a metadata line — so it reads as one thing. A card is static by default; it becomes a link when the whole unit leads somewhere, and an option when the user picks among several units. A card is not a dialog, not a form and not a table row.

    Anatomy

    A 1px color.border.default edge on color.surface.default, no shadow, no radius. Inside, a title in color.text.bright, body text in color.text.default, metadata in color.text.muted. Padding is 12px in comfortable and 8px in compact density. A link card is one anchor around the same content; a selectable card is an option inside a listbox group.

    States

    StateVisualNon-colour channel
    default1px color.border.default on color.surface.default
    hoverlink and selectable cards only: background → color.interaction.hover.bg; border → color.border.controlcursor: pointer; the border lightens from decorative to control
    focus-visiblecontainer ring 2px solid color.interaction.focus.ring-container at −3pxthe ring
    selectedfill color.interaction.selection.bg with color.interaction.selection.text on every linearia-selected="true"; the fill’s on-fill text
    selected+focus-visiblethe fill and the 2px ring in color.interaction.focus.ring-containerboth visible at once

    A static card has no hover and no focus: nothing happens on a pointer and it is not in the tab order.

    Keyboard

    A link card is one tab stop and Enter follows it; controls inside a link card are not allowed (a link cannot contain a button). A selectable group is a listbox with roving tabindex: Tab lands on the selected card, the arrow keys move and select, Space toggles in a multi-select group. A static card that contains controls contributes those controls to the tab order and nothing else.

    Accessibility

    A static card is an article with a heading when it stands alone, or a section inside a list. A link card names itself from its content and the title comes first so it is read first. Selectable cards are role="option" inside role="listbox" with aria-label; aria-selected on each option. Contrast: title 10.10:1, body 8.43:1, metadata 5.66:1 on the card; on the selection fill every line switches to the on-fill text (12.47:1) because muted text would fall to 4.19:1. The ring is 10.10:1 on the card and 7.48:1 on the fill.

    Portability

    A bordered box with a background and an outline. Toolkits that add a shadow to their frames remove it. Hosts without container outlines draw the ring as a 2px inner border and record it.

    Non-examples

    A drop shadow or elevation. Rounded corners. A hover lift or scale. A static card with a hover fill. A card whose only clickable part is an invisible overlay. A link card containing buttons. A selected card shown by a border colour alone without the fill and aria-selected. Muted metadata left on the selection fill.

    Keys

    KeyAction
    TabReaches a link card as one stop; reaches a selectable group at its selected card (roving tabindex).
    EnterFollows a link card.
    Up / Down / Left / RightMoves between selectable cards in the group and selects the focused one.
    SpaceToggles the focused card in a multi-select group.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: list link button table

    Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-STATE-MATRIX

    List list

    • Family: Information display
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Custom widget: APG listbox with roving tabindex; options carry aria-selected, the list aria-multiselectable when several may be chosenAPG pattern
    • specified
    • demonstrated

    A selectable list of rows (an APG listbox) in single or multiple selection; the selected row is the selection fill with a check glyph and an optional metadata column.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    row.textcolor.text.defaultobserveduse#e99499Interface and body text.
    row.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
    row.dividercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
    row.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    row.text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
    selected.bgcolor.interaction.selection.bgapproveduse#531310Selected row, tab, workspace; D-027 recessed the fill, leaving the 2px indicator and the check to carry selection.
    selected.textcolor.interaction.selection.textobserveduse#f4eeeeText on the selection.
    selected.ringcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
    selected.inactive-bgcolor.interaction.selection.inactive-bgobserveduse#420f0cSelection while the container is not focused.
    selected.inactive-textcolor.interaction.selection.inactive-textobserveduse#e99499Text on the inactive selection (7.02:1).
    check.glyphcolor.interaction.selection.textobserveduse#f4eeeeText on the selection.
    meta.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateSingleMultiWith metadata
    default
    • default
    • extended
    • high-contrast
    • print
    • FX-320 reflow
    • FX-ZOOM-200 text zoom
    • FX-RM reduced motion
    • FX-TOUCH pointer
    • text-field14 states
    • tabs7 states
    • menu8 states
    • chartR2
    hover
    focus-visible
    selected
    selected+focus-visible
    selected+container-inactive
    disabled

    Purpose

    Lets the user choose one or several rows from a short, visible set. A list is a listbox: it holds a selection, it does not navigate. Rows that lead somewhere are sidebar-nav; rows with columns are a table; a long set that needs filtering is a combobox.

    Anatomy

    A ul with role="listbox" framed by 1px color.border.control on color.surface.default. Each option is one row: a check gutter, the label in color.text.default, and in the metadata variant a trailing column in color.text.muted. Rows are separated by 1px color.border.divider. A selected row is filled with color.interaction.selection.bg; every part of it, including the metadata and the ✓ glyph, takes color.interaction.selection.text.

    States

    StateVisualNon-colour channel
    defaulttext color.text.default; no fill; the check gutter empty
    hoverbackground → color.interaction.hover.bgcursor: pointer
    focus-visiblering 1px dashed color.interaction.focus.ring at −2px on the optionthe ring
    selectedfill color.interaction.selection.bg; text and glyph color.interaction.selection.textaria-selected="true"; the ✓ glyph
    selected+focus-visiblethe fill and the ring in color.interaction.focus.ring-containerboth visible at once
    selected+container-inactivefill color.interaction.selection.inactive-bg with color.interaction.selection.inactive-text; no ringlightness drop between the two fills; the glyph stays
    disabledtext color.text.disabled; no fill; no hover; still reachable by arrow keysaria-disabled="true"; cursor: not-allowed

    Precedence: disabled > selected > hover; focus-visible is always drawn.

    Keyboard

    Roving tabindex: the selected option (or the first) has tabindex="0", the rest -1, so the list costs one tab stop. Up and Down move; in single selection the selection follows focus, in multiple selection Space toggles and Shift with the arrows extends. Home and End jump; Ctrl+A selects all in a multi-select list; typing jumps to the next matching label. Disabled options are reachable and announced, never skipped silently.

    Accessibility

    aria-label or aria-labelledby on the listbox; aria-multiselectable when several may be chosen; aria-selected on every option, including "false". The ✓ glyph is aria-hidden; aria-selected is the state. Metadata is inside the option so it is read with the label. Contrast: text 8.43:1, metadata 5.66:1, selected text 12.47:1 on the fill, inactive selection 7.02:1, ring 4.57:1 on the surface and 7.48:1 on the fill, frame 4.33:1. Rows are at least 24 CSS pixels tall with the check gutter as the leading target area.

    Portability

    Rows with a background, a glyph gutter and an outline; nothing else. Hosts with a native list view take the fill, the inactive fill and the divider colour and keep their keyboard model. The inactive fill applies when the list’s window or pane loses focus, which a web page detects through :focus-within on the pane.

    Non-examples

    A selected row marked by a border or a check alone without the fill. Rounded row highlights. Muted metadata left on the selection fill. A list where every row is a tab stop. A list that navigates on selection. Disabled rows removed from the arrow-key order. Hover that changes the text colour. A list without a frame on the canvas.

    Keys

    KeyAction
    TabEnters the list at the selected option, or the first option when nothing is selected; a second Tab leaves the list.
    Down / UpMoves focus to the next or previous option; in single selection the selection follows focus.
    Home / EndMoves focus to the first or last option.
    SpaceToggles the focused option in a multi-select list.
    Shift+Down / Shift+UpExtends the selection by one in a multi-select list.
    Ctrl+ASelects every option in a multi-select list.
    A-ZMoves focus to the next option starting with the typed character.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: card select combobox tree table

    Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-DENSITY FX-STATE-MATRIX

    Badge badge

    • Family: Information display
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Native control: native span; an empty badge is role="img" with aria-label
    • specified
    • demonstrated

    A small square label for a status or a count; every status carries its glyph and its fill, the outline form uses the status border, and an empty badge is a dot with a name.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    danger.bgcolor.status.danger.fillobserveduse#dc282eDanger fill.
    danger.textcolor.status.danger.on-fillobserveduse#f9faf9Text on the danger fill (4.58:1).
    danger.bordercolor.status.danger.borderobserveduse#e53935Danger border, 2px on invalid inputs.
    danger.outline-textcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).
    warning.bgcolor.status.warning.fillapproveduse#c9973fWarning fill.
    warning.textcolor.status.warning.on-fillapproveduse#0c0909Text on the warning fill (7.54:1).
    warning.bordercolor.status.warning.borderapproveduse#c9973fWarning border.
    warning.outline-textcolor.status.warning.textapproveduse#c9973fWarning text (7.54:1).
    success.bgcolor.status.success.fillapproveduse#86a46fSuccess fill.
    success.textcolor.status.success.on-fillapproveduse#0c0909Text on the success fill (7.13:1).
    success.bordercolor.status.success.borderapproveduse#86a46fSuccess border.
    success.outline-textcolor.status.success.textapproveduse#86a46fSuccess text (7.13:1).
    info.bgcolor.status.info.fillapproveduse#7e9ebbInfo fill.
    info.textcolor.status.info.on-fillapproveduse#0c0909Text on the info fill (7.08:1).
    info.bordercolor.status.info.borderapproveduse#7e9ebbInfo border.
    info.outline-textcolor.status.info.textapproveduse#7e9ebbInfo text (7.08:1).
    neutral.bgcolor.status.neutral.fillobserveduse#a3676bNeutral fill (dunst urgency_low).
    neutral.textcolor.status.neutral.on-fillobserveduse#000000Text on the neutral fill (4.71:1).
    neutral.bordercolor.status.neutral.borderobserveduse#a3676bNeutral border.
    neutral.outline-textcolor.status.neutral.textobserveduse#bd787dNeutral status text.
    count.bgcolor.action.primary.bgapproveduse#7d1310Primary button fill; D-026 darkened it off color12, which stays fixed as heritage ANSI 12.
    count.textcolor.action.primary.textobserveduse#f4eeeePrimary button text (9.28:1).

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateStatusCountOutline
    default
    Failed Drifted Verified Proposed Deferred
    12 unread
    Failed Drifted Verified Proposed Deferred
    empty

    Purpose

    Names a status or shows a count next to the thing it describes. A badge is read-only: it never opens, toggles or removes anything. An interactive label is a chip; a message with a status is an alert.

    Anatomy

    An inline span in caption type with 2px by 8px padding and square corners. Status badges fill with color.status.<status>.fill and use the matching on-fill text, preceded by the status glyph: ✕ danger, ! warning, ✓ success, i info, · neutral. Outline badges have no fill, the text colour and a 1px border in the same status. The count badge is a number on color.action.primary.bg in color.action.primary.text with a visually hidden unit. An empty badge is an 8px square dot in the status fill with a name.

    States

    StateVisualNon-colour channel
    defaultfill, glyph and text for the status; or the outline formthe glyph; the text
    emptyan 8px square dot in the status fill; the glyph and text visually hiddenrole="img" with aria-label, or the hidden text; the dot’s position beside its subject

    A badge has no hover, focus, pressed or disabled state because it is not a control.

    Keyboard

    None. A badge is never focusable. When a badge summarises something the user can act on, the action lives in the neighbouring control and the badge is part of that control’s name or description.

    Accessibility

    The glyph is aria-hidden and the text carries the meaning, so a screen reader hears “Failed”, not “cross Failed”. Count badges include their unit as visually hidden text (“12 unread”). An empty badge, a dot, carries role="img" and aria-label or wraps hidden text; a dot with no name is decoration and must be aria-hidden. Contrast: on-fill text 4.58:1 (danger), 7.54:1 (warning), 7.13:1 (success), 7.08:1 (info), 4.71:1 (neutral); outline text 5.26:1 to 7.34:1; borders and dots at least 4.04:1 on the panel surface. Badges are not targets, so no minimum size applies beyond legibility at 11px caption type.

    Portability

    A filled or outlined span with a glyph. Toolkits without background colours on labels use the outline form. Hosts without the glyph characters use the nearest available (x, !, check mark, i, bullet) and record it.

    Non-examples

    Rounded or pill badges. A badge that is clickable. A status shown by colour without its glyph. A count badge that hides its unit from assistive technology. Purple, cyan or magenta statuses. A badge in body type. A badge whose text wraps. A dot without a name.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: chip alert table list

    Stress fixtures: FX-I18N FX-RTL FX-ZOOM-200 FX-320 FX-RM FX-HC FX-STATE-MATRIX

    Chip chip

    • Family: Information display
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Native control: native button with aria-pressed for filters; a span with a labelled remove button for values; a plain span for tags
    • specified
    • demonstrated

    A square bordered token for a filter, a removable value or a static tag; a pressed filter chip takes the selection fill and a check glyph.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    root.textcolor.text.defaultobserveduse#e99499Interface and body text.
    root.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
    root.bg-pressedcolor.interaction.pressed.bgobserveduse#420f0cPressed fill.
    root.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    root.text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
    root.border-disabledcolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
    root.bg-disabledcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
    selected.bgcolor.interaction.selection.bgapproveduse#531310Selected row, tab, workspace; D-027 recessed the fill, leaving the 2px indicator and the check to carry selection.
    selected.textcolor.interaction.selection.textobserveduse#f4eeeeText on the selection.
    selected.ringcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
    remove.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    remove.text-hovercolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    remove.bg-hovercolor.interaction.hover.bg-strongobserveduse#630f0dHover on menu items; D-027 moved links to interaction.hover.bg.

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateFilterRemovableStatic
    default
    tabs
    R1
    hover
    focus-visible
    selected
    selected+focus-visible
    disabled

    Purpose

    Represents one value the user can toggle or remove: a filter in a filterable table, a chosen item in a multiselect, a tag on a record. A chip that only informs is a badge; a chip that runs an action is a button.

    Anatomy

    A square control-height box with 1px color.border.control on color.surface.default and text in color.text.default. A filter chip is a button with a check gutter that shows ✓ while pressed. A removable chip is a span holding the label and a × button in color.text.muted. A static chip is a span with nothing else. When selected, the chip fills with color.interaction.selection.bg and its text becomes color.interaction.selection.text.

    States

    StateVisualNon-colour channel
    default1px color.border.control on color.surface.default; text color.text.default
    hoverbackground → color.interaction.hover.bg; the remove button → color.interaction.hover.bg-strong with color.text.brightcursor: pointer
    focus-visiblering 1px dashed color.interaction.focus.ring at −2px on the chip or on the remove buttonthe ring
    selectedfill color.interaction.selection.bg; text and glyph color.interaction.selection.text; the border takes the fill colouraria-pressed="true"; the ✓ glyph
    selected+focus-visiblethe fill and the ring in color.interaction.focus.ring-containerboth visible at once
    disabledtext color.text.disabled; border color.border.disabled; background color.interaction.disabled.bg; no hoverdisabled; cursor: not-allowed

    Pressing a filter chip uses color.interaction.pressed.bg for the duration of the press only. Precedence: disabled > selected > hover; focus-visible is always drawn.

    Keyboard

    A filter chip is one tab stop that toggles on Space or Enter. A removable chip contributes only its remove button to the tab order; the label is not focusable. A static chip is never focusable. Inside a token field the field owns Backspace and the arrow keys.

    Accessibility

    Filter chips expose aria-pressed and keep the same label in both states; the ✓ glyph is aria-hidden. The remove button is named “Remove ” so it is unambiguous out of context, and removing a chip moves focus to the next chip or the field. Contrast: text 8.43:1, border 4.33:1, selected text 12.47:1 on the fill, ring 4.57:1 on the surface and 7.48:1 on the fill, remove glyph 5.66:1. Chips and remove buttons are at least 24×24 CSS pixels in compact density with 4px between neighbours.

    Portability

    A bordered box with a background and an outline; the remove control is an ordinary small button. Toolkits with a native toggle button take the fill for the checked state. Hosts without a glyph draw the check as a 2px inset rule at the inline start and record it.

    Non-examples

    Pill or rounded chips. A selected chip shown by a border colour alone without the fill and aria-pressed. A removable chip whose × has no name. A chip that is a link. A static tag that reacts to hover. Disabling by opacity. A chip whose label clips inside the border. A chip in caption type (that is a badge).

    Keys

    KeyAction
    Tab / Shift+TabReaches a filter chip, or the remove button of a removable chip; static chips are skipped.
    Space / EnterToggles a filter chip; activates the remove button.
    Backspace / DeleteIn a token field, removes the chip before the caret (the field's contract, not the chip's).

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: badge button multiselect combobox toolbar

    Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-STATE-MATRIX

    Table table

    • Family: Information display
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Native control: native table with caption, thead, th scope, aria-sort on sorted headers and aria-busy while loading
    • specified
    • demonstrated
    • tested

    A native data table with a header rule, row dividers, hover and selection fills, sortable headers with a glyph, and static empty and loading rows.

    Report an issue with this component

    Open component workbench

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    header.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    header.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    header.rulecolor.border.strongobserveduse#9e231fEmphasised 2px rule: sticky headers, section ends.
    header.bg-stickycolor.surface.raisedapproveduse#160b0bSticky headers, menus, popovers; D-027 recessed it so an open list reads as depth rather than a lighter panel.
    sort.glyphcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    sort.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    row.textcolor.text.defaultobserveduse#e99499Interface and body text.
    row.dividercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
    row.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
    selected.bgcolor.interaction.selection.bgapproveduse#531310Selected row, tab, workspace; D-027 recessed the fill, leaving the 2px indicator and the check to carry selection.
    selected.textcolor.interaction.selection.textobserveduse#f4eeeeText on the selection.
    selected.ringcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
    selected.inactive-bgcolor.interaction.selection.inactive-bgobserveduse#420f0cSelection while the container is not focused.
    selected.inactive-textcolor.interaction.selection.inactive-textobserveduse#e99499Text on the inactive selection (7.02:1).
    caption.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    empty.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    loading.glyphcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateDefaultSticky headerNumericWith caption
    default
    tabsnavigationR17
    menunavigationR18
    tabledisplayR18
    chartdisplayR20
    tabsnavigationR17
    menunavigationR18
    tabledisplayR18
    chartdisplayR20
    tabsnavigationR17
    menunavigationR18
    tabledisplayR18
    chartdisplayR20
    Components in this batch, with their declared state counts
    tabsnavigationR17
    menunavigationR18
    tabledisplayR18
    chartdisplayR20
    hover
    selected
    selected+focus-visible
    selected+container-inactive
    sorted
    empty
    loading

    Purpose

    Shows records as rows and attributes as columns so they can be compared down a column. The table is for reading; a table with selection checkboxes, resizable columns and a toolbar is the data-table. A single column of rows is a list.

    Anatomy

    A collapsed native table on color.surface.default with no outer border. The header row is color.text.bright above a 1px color.border.strong rule (2px when the header is sticky, on color.surface.raised); sortable headers wrap their label in a button and show ▲ or ▼ when sorted. Body rows are the row height, separated by 1px color.border.divider, text in color.text.default; numeric cells are end-aligned with tabular numbers. An optional caption in color.text.muted sits above. Two special rows, hidden unless needed, span every column: the empty message and the loading glyph.

    States

    StateVisualNon-colour channel
    defaultrows on color.surface.default; header rule 1px color.border.strong
    hoverrow background → color.interaction.hover.bgcursor: default; only on hover-capable pointers
    selectedrow fill color.interaction.selection.bg; every cell color.interaction.selection.textaria-selected="true" on the row
    selected+focus-visiblethe fill and a ring in color.interaction.focus.ring-container around the rowboth visible at once
    selected+container-inactiverow fill color.interaction.selection.inactive-bg with color.interaction.selection.inactive-text; no ringlightness drop between the two fills
    sortedthe sorted header shows ▲ (ascending) or ▼ (descending) in color.text.brightaria-sort; the glyph
    emptythe body is one full-width cell in color.text.muted: “No rows match.”the message text
    loadingthe body is one full-width cell with the static glyph in color.text.muted; the header staysaria-busy="true"; the glyph; no animation

    Precedence: loading > empty; selected > hover; focus-visible is always drawn.

    Keyboard

    A plain table has no row focus: Tab reaches the sort buttons in the header and any control inside a cell. Enter or Space on a sort button cycles ascending, descending. Tables whose rows are targets (row links, row selection) are the data-table and add row focus there.

    Accessibility

    caption or aria-labelledby names the table; th scope="col" on every header and scope="row" on a row header column. aria-sort on the sorted th, none or absent elsewhere; the glyph is aria-hidden. The empty and loading rows are real rows so the table stays a table; aria-busy="true" on the table while loading and a live region for the outcome. Contrast: body text 8.43:1, header 10.10:1, caption and empty message 5.66:1, selected text 12.47:1 on the fill, inactive 7.02:1, ring 7.48:1 on the fill, sort ring 4.57:1. Rows are at least 24 CSS pixels tall; sort buttons fill the header cell.

    Portability

    Row backgrounds, one border under the header, one between rows, an outline on a selected row. Toolkits with a native table view take the rule, the divider and the two fills. Hosts that cannot draw an outline on a row draw the ring as an inset 1px border and record it.

    Non-examples

    Zebra striping. A rounded or bordered table frame. A selected row marked by a left bar (that is navigation, not selection). Header text in caption size or uppercase. Sorting shown by colour alone without aria-sort and a glyph. An animated spinner while loading. An empty state that removes the header. Text truncated with no way to read the full value. A hover fill on a touch device.

    Keys

    KeyAction
    Tab / Shift+TabMoves between the sort buttons and any controls inside cells; rows themselves are not tab stops in a plain table.
    Enter / SpaceToggles the sort of the focused header between ascending and descending.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: data-table list pagination badge filterable-table

    Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-DENSITY FX-OVERFLOW FX-STATE-MATRIX

    Data table data-table

    • Family: Information display
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Native control: native table with aria-selected rows, a select-all checkbox in the mixed state, aria-sort headers and aria-busy while loadingAPG pattern
    • specified
    • demonstrated

    A native table with controls: a selection column with a mixed select-all, sortable headers, row focus with the ring on the fill, and static resize handles.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    header.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    header.rulecolor.border.strongobserveduse#9e231fEmphasised 2px rule: sticky headers, section ends.
    sort.glyphcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    row.textcolor.text.defaultobserveduse#e99499Interface and body text.
    row.dividercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
    row.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
    row.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    selected.bgcolor.interaction.selection.bgapproveduse#531310Selected row, tab, workspace; D-027 recessed the fill, leaving the 2px indicator and the check to carry selection.
    selected.textcolor.interaction.selection.textobserveduse#f4eeeeText on the selection.
    selected.ringcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
    checkbox.bgcolor.surface.inputapproveduse#000000Form-control fill.
    checkbox.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    checkbox.checked-bgcolor.action.primary.bgapproveduse#7d1310Primary button fill; D-026 darkened it off color12, which stays fixed as heritage ANSI 12.
    checkbox.glyphcolor.action.primary.textobserveduse#f4eeeePrimary button text (9.28:1).
    resize.handlecolor.border.defaultobserveduse#531310Decorative border (1.39:1; never the only edge of a control).
    resize.handle-hovercolor.border.activeobserveduse#e53935Active or focused control border.
    empty.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    loading.glyphcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateDefaultSelectableResizable
    default
    tabsnavigationR17
    menunavigationR18
    tabledisplayR18
    chartdisplayR20
    tabsnavigationR17
    menunavigationR18
    tabledisplayR18
    chartdisplayR20
    tabsnavigationR17
    menunavigationR18
    tabledisplayR18
    chartdisplayR20
    hover
    focus-visible
    selected
    selected+focus-visible
    sorted
    mixed
    empty
    loading

    Purpose

    A table the user works in: selects rows, sorts, resizes columns. The plain table is for reading; this component adds the controls and the keyboard model. It stays a native table so its cells keep their header associations; hosts that need cell-level navigation promote it to a grid and record the change.

    Anatomy

    The table component’s structure with the same rule, dividers and fills, plus: a selection column whose header holds a select-all with aria-checked true, false or mixed, drawn on color.action.primary.bg with the ✓ or – glyph in color.action.primary.text; native checkboxes in each row on color.surface.input with a 1px color.border.control boundary; rows that can take focus; and in the resizable variant a 1px handle in color.border.default at the inline end of each header that turns color.border.active under the pointer.

    States

    StateVisualNon-colour channel
    defaultrows on color.surface.default; header rule 1px color.border.strong
    hoverrow background → color.interaction.hover.bg; a resize handle → color.border.activecursor: default on rows, col-resize on handles
    focus-visiblering 1px dashed color.interaction.focus.ring at −2px around the focused row or controlthe ring
    selectedrow fill color.interaction.selection.bg; every cell color.interaction.selection.text; the row checkbox checkedaria-selected="true"; the checked box
    selected+focus-visiblethe fill and the ring in color.interaction.focus.ring-containerboth visible at once
    sorted▲ or ▼ in color.text.bright on the sorted headeraria-sort; the glyph
    mixedthe select-all on color.action.primary.bg with the – glypharia-checked="mixed"; the glyph
    emptyone full-width cell in color.text.muted: “No rows match.”; the header and controls staythe message text
    loadingone full-width cell with the static glyph; the header staysaria-busy="true"; the glyph; no animation

    Precedence: loading > empty; selected > hover; focus-visible is always drawn. Selection is a fill; focus is a ring; they never borrow each other’s form.

    Keyboard

    Header controls first: the select-all, then each sort button. Rows use a roving tabindex so the body costs one tab stop; Up and Down move, Space toggles, Shift extends, Ctrl+A selects all. Controls inside the focused row are reached with Tab and left with Shift+Tab. Column widths are set from a header menu or by dragging the handle; the handle itself is never a tab stop.

    Accessibility

    Every row checkbox is labelled by the row’s first data cell (aria-labelledby); the select-all is named “Select all rows” and exposes aria-checked="mixed" when only some are selected. aria-selected on the row mirrors its checkbox. Sorted headers carry aria-sort; the table carries aria-busy while loading; the count of selected rows is announced through a live region owned by the surrounding toolbar. Contrast: text 8.43:1, header 10.10:1, selected text 12.47:1 on the fill, ring 4.57:1 on the surface and 7.48:1 on the fill, checkbox boundary 4.33:1, check glyph 9.28:1 on the primary fill. Checkboxes and handles are at least 24 CSS pixels tall in compact density.

    Portability

    The table component’s drawing plus a checkbox column and a header checkbox; the handle is a 1px rule. Toolkits with native table views map row selection to their selection model and the mixed state to their tristate checkbox. Hosts without row focus fall back to the checkbox as the only row control and record it.

    Non-examples

    A grid role on a table that is not navigated cell by cell. Zebra stripes. A select-all that is a native checkbox with a script-only indeterminate state and no aria-checked. Rows selected by clicking anywhere with no checkbox alternative. A selected row shown by a border alone. A resize handle that is a tab stop. An animated loading skeleton. Rounded checkboxes. Text truncated with no full-value affordance.

    Keys

    KeyAction
    Tab / Shift+TabMoves through the select-all, the sort buttons, then the rows (one row is the tab stop; roving tabindex) and any control inside the focused row.
    Down / UpMoves row focus; in a single-select table the selection follows focus.
    SpaceToggles the focused row's selection (the same as its checkbox).
    Shift+Down / Shift+UpExtends the selection by one row.
    Ctrl+ASelects every row; the select-all reflects it.
    Enter / SpaceOn a sort button, cycles the sort; on the select-all, toggles between all and none.
    Left / RightReserved for cell navigation in hosts that promote the table to a grid; not used here.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: table checkbox pagination toolbar filterable-table

    Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-DENSITY FX-OVERFLOW FX-TOUCH FX-STATE-MATRIX

    Description list description-list

    • Family: Information display
    • Maturity: stable
    • Priority: R2
    • Since: 1.0.0
    • Native control: Native dl, dt and dd
    • specified
    • demonstrated

    Semantic terms and values that wrap into a readable single column.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    root.textcolor.text.defaultobserveduse#e99499Interface and body text.
    root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    heading.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    secondary.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    control.bgcolor.surface.inputapproveduse#000000Form-control fill.
    control.focuscolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    dependency.role-border-width-defaultborder.width.defaultobserveduse1pxEvery border is 1px.
    dependency.role-color-border-dividercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
    dependency.role-radius-noneradius.noneobserveduse0pxThe only radius. Nothing is rounded.
    dependency.role-space-12space.12observeduse12px
    dependency.role-space-2space.2observeduse2px
    dependency.role-space-4space.4observeduse4px
    dependency.role-space-8space.8observeduse8px

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateDefault
    default
    Project
    Atlas library
    Owner
    Avery Kim
    Delivery
    Ready for review
    stacked

    Purpose

    Present named facts as semantic terms and descriptions. Terms remain adjacent to their values in source order. A narrow view stacks the term above its value.

    Anatomy

    • list: Native description list.
    • term: Concise name for a fact.
    • value: Text, links or semantic inline content.

    States

    StatePresentationNon-colour channel
    defaultTwo aligned columns.Native term and description relationships.
    stackedOne column at narrow widths.Each term immediately precedes its value.

    Keyboard

    • Tab / Shift+Tab: Visit links in values. Plain facts are not tab stops.

    Accessibility

    Use dt and dd rather than a grid of unrelated paragraphs. Long values wrap without clipping. Preserve meaningful link text and do not make every value keyboard focusable.

    Portability

    Wrap labels and actions without changing source order. Use logical spacing in RTL. Preserve native target sizes at both densities; only bounded data regions may scroll horizontally. Use equivalent native semantics and approved roles; record any unsupported behavior as a mapping deviation. The host owns application data, persistence, permissions and services.

    Non-examples

    Unlabelled controls, color-only status, drag-only operations, hidden required instructions, stolen focus or an invented service success.

    Keys

    KeyAction
    Tab / Shift+TabVisit links in values. Plain facts are not tab stops.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Stress fixtures: FX-320 FX-360 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

    Avatar avatar

    • Family: Information display
    • Maturity: stable
    • Priority: R2
    • Since: 1.0.0
    • Native control: Named image or text fallback
    • specified
    • demonstrated

    A square entity image with a named text fallback.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    root.textcolor.text.defaultobserveduse#e99499Interface and body text.
    root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    heading.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    secondary.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    control.bgcolor.surface.inputapproveduse#000000Form-control fill.
    control.focuscolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    dependency.role-border-width-defaultborder.width.defaultobserveduse1pxEvery border is 1px.
    dependency.role-font-weight-boldfont.weight.boldobserveduse700
    dependency.role-radius-noneradius.noneobserveduse0pxThe only radius. Nothing is rounded.
    dependency.role-space-12space.12observeduse12px
    dependency.role-space-2space.2observeduse2px
    dependency.role-space-32space.32observeduse32px

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateDefault
    default
    loading
    error

    Purpose

    Identify a person or entity with an optional caller-owned image and text fallback. The component ships no image service or assets. Failed images restore the fallback and retain the full accessible name.

    Anatomy

    • frame: Square bounded image area with a border.
    • fallback: Caller-supplied initials, backed by the full accessible name.
    • image: Optional image; failed loading restores the text fallback.

    States

    StatePresentationNon-colour channel
    defaultInitials or loaded image.Full name on the image container.
    loadingFallback remains visible.No loss of the full accessible name while loading.
    errorFallback remains visible.Image failure does not remove the entity name.

    Keyboard

    • Tab: No additional tab stop. An enclosing link remains native.

    Accessibility

    Use one full accessible name, avoiding duplicate announcements from image alt and fallback text. Initials alone do not adequately identify a person. A decorative avatar beside an equivalent visible name may be aria-hidden.

    Portability

    Wrap labels and actions without changing source order. Use logical spacing in RTL. Preserve native target sizes at both densities; only bounded data regions may scroll horizontally. Use equivalent native semantics and approved roles; record any unsupported behavior as a mapping deviation. The host owns application data, persistence, permissions and services.

    Non-examples

    Unlabelled controls, color-only status, drag-only operations, hidden required instructions, stolen focus or an invented service success.

    Keys

    KeyAction
    TabNo additional tab stop. An enclosing link remains native.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Stress fixtures: FX-320 FX-360 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

    Timeline timeline

    • Family: Information display
    • Maturity: stable
    • Priority: R2
    • Since: 1.0.0
    • Native control: Ordered list with time elements
    • specified
    • demonstrated

    Chronological events with explicit dates, descriptions and current state.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    root.textcolor.text.defaultobserveduse#e99499Interface and body text.
    root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    heading.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    secondary.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    control.bgcolor.surface.inputapproveduse#000000Form-control fill.
    control.focuscolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    dependency.role-border-width-defaultborder.width.defaultobserveduse1pxEvery border is 1px.
    dependency.role-border-width-emphasisborder.width.emphasisobserveduse2pxSelected indicator, sticky header rule, invalid border.
    dependency.role-color-border-activecolor.border.activeobserveduse#e53935Active or focused control border.
    dependency.role-color-border-dividercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
    dependency.role-radius-noneradius.noneobserveduse0pxThe only radius. Nothing is rounded.
    dependency.role-space-12space.12observeduse12px
    dependency.role-space-2space.2observeduse2px
    dependency.role-space-4space.4observeduse4px

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateDefault
    default
    1. Foundation prepared

      Completed · tokens generated.

    2. Components in review

      Current · interaction checks underway.

    current

    Purpose

    Read events as an ordered list with explicit time and status text. The caller supplies order; the component does not reorder unknown dates. Lines support the sequence without becoming the only status channel.

    Anatomy

    • list: Ordered events in reading order.
    • time: Native time element with machine-readable datetime.
    • event: Heading and status-bearing description.

    States

    StatePresentationNon-colour channel
    defaultDivider along the event sequence.Ordered list and visible time.
    currentEmphasized start border.aria-current and explicit Current text.

    Keyboard

    • Tab / Shift+Tab: Reach event links and actions. The sequence is not focusable.

    Accessibility

    Use real time values and visible dates. Identify the current event with aria-current and text. Avoid a color-only dot or an order that changes between visual presentation and reading order.

    Portability

    Wrap labels and actions without changing source order. Use logical spacing in RTL. Preserve native target sizes at both densities; only bounded data regions may scroll horizontally. Use equivalent native semantics and approved roles; record any unsupported behavior as a mapping deviation. The host owns application data, persistence, permissions and services.

    Non-examples

    Unlabelled controls, color-only status, drag-only operations, hidden required instructions, stolen focus or an invented service success.

    Keys

    KeyAction
    Tab / Shift+TabReach event links and actions. The sequence is not focusable.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Stress fixtures: FX-320 FX-360 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

    Chart chart

    • Family: Information display
    • Maturity: stable
    • Priority: R2
    • Since: 1.0.0
    • Native control: Native figure, accessible SVG and table
    • specified
    • demonstrated

    A one-series numeric chart with an always-visible complete data table.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    root.textcolor.text.defaultobserveduse#e99499Interface and body text.
    root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    heading.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    secondary.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    control.bgcolor.surface.inputapproveduse#000000Form-control fill.
    control.focuscolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    dependency.role-border-width-defaultborder.width.defaultobserveduse1pxEvery border is 1px.
    dependency.role-color-chart-axiscolor.chart.axisobserveduse#9e231fAxis lines.
    dependency.role-color-chart-gridcolor.chart.gridobserveduse#2b0e0dGrid lines.
    dependency.role-color-chart-labelcolor.chart.labelobserveduse#bd787dAxis labels.
    series.primarycolor.chart.series-2observeduse#f73f35Second series.
    header.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    row.textcolor.text.defaultobserveduse#e99499Interface and body text.
    dependency.role-radius-noneradius.noneobserveduse0pxThe only radius. Nothing is rounded.
    dependency.role-space-12space.12observeduse12px
    dependency.role-space-2space.2observeduse2px
    dependency.role-space-8space.8observeduse8px

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateDefault
    default
    Completed tasks by week
    Completed tasks
    WeekTasks
    Week 124
    Week 236
    Week 348
    empty
    loading

    Purpose

    Show one bounded numeric series with its complete textual data table. Labels and exact values carry the meaning without color. The API accepts finite non-negative values; it rejects invalid data rather than silently inventing missing numbers.

    Anatomy

    • figure: Caption identifies the measure and units.
    • plot: Responsive SVG with an accessible name.
    • table: Always-visible labels and exact values.
    • empty: Explicit message when the supplied series is empty.

    States

    StatePresentationNon-colour channel
    defaultRed primary series (color.chart.series-2), with canonical axis and label roles.Complete labelled data table.
    emptyPlot and rows are absent.Explicit No data available text.
    loadingExisting data remains readable under a busy indicator.aria-busy with named loading text from the host.

    Keyboard

    • Tab: Visit any scrollable data region. Points do not add unnecessary tab stops.

    Accessibility

    Keep the table visible without JavaScript. Do not replace it with tooltips or color-only legends. The single series uses the approved red chart role color.chart.series-2, as requested by the owner for graphs; foreground typography retains its rose roles. Each SVG bar has a text label. A loading status must distinguish old data from a completed refresh.

    Column headers use color.text.bright; body row labels and numeric values use color.text.default. Row-header semantics remain native th scope="row" even though their typography matches body values. Do not apply the column-header color to every th indiscriminately.

    Portability

    Wrap labels and actions without changing source order. Use logical spacing in RTL. Preserve native target sizes at both densities; only bounded data regions may scroll horizontally. Use equivalent native semantics and approved roles; record any unsupported behavior as a mapping deviation. The host owns application data, persistence, permissions and services.

    Non-examples

    Unlabelled controls, color-only status, drag-only operations, hidden required instructions, stolen focus or an invented service success.

    Keys

    KeyAction
    TabVisit any scrollable data region. Points do not add unnecessary tab stops.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Stress fixtures: FX-320 FX-360 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

    Keyboard key kbd

    • Family: Information display
    • Maturity: stable
    • Priority: R2
    • Since: 1.0.0
    • Native control: Native kbd
    • specified
    • demonstrated

    A literal key or short keyboard sequence rendered as native kbd text.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    root.textcolor.text.defaultobserveduse#e99499Interface and body text.
    root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    heading.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    secondary.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    control.bgcolor.surface.inputapproveduse#000000Form-control fill.
    control.focuscolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    dependency.role-border-width-defaultborder.width.defaultobserveduse1pxEvery border is 1px.
    dependency.role-border-width-emphasisborder.width.emphasisobserveduse2pxSelected indicator, sticky header rule, invalid border.
    dependency.role-radius-noneradius.noneobserveduse0pxThe only radius. Nothing is rounded.
    dependency.role-space-12space.12observeduse12px
    dependency.role-space-2space.2observeduse2px
    dependency.role-space-4space.4observeduse4px

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateDefault
    default
    Ctrl + K

    Purpose

    Show readable key names using native kbd text. This documents a shortcut; it does not bind one. State the platform when shortcuts differ.

    Anatomy

    • key: Native kbd containing a readable key name.
    • sequence: Separate keys joined by text in activation order.

    States

    StatePresentationNon-colour channel
    defaultNamed content on the default surface.Native text and structure.

    Keyboard

    • None: The keycap is documentation, not a button.

    Accessibility

    Write readable names such as Ctrl, Shift and Escape. Keep sequence punctuation as text. A shortcut hint does not replace an action’s accessible name.

    Portability

    Wrap labels and actions without changing source order. Use logical spacing in RTL. Preserve native target sizes at both densities; only bounded data regions may scroll horizontally. Use equivalent native semantics and approved roles; record any unsupported behavior as a mapping deviation. The host owns application data, persistence, permissions and services.

    Non-examples

    Unlabelled controls, color-only status, drag-only operations, hidden required instructions, stolen focus or an invented service success.

    Keys

    KeyAction
    NoneThe keycap is documentation, not a button.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Stress fixtures: FX-320 FX-360 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

    Feedback and overlays

    Alerts, toasts, progress, loading, skeletons, tooltips, popovers, dialogs, drawers, empty and error states.

    Alert alert

    • Family: Feedback and overlays
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Native control: native landmark-free block; role=alert for danger, role=status for every other status; an optional native close buttonAPG pattern
    • specified
    • demonstrated

    An inline status message with a mandatory glyph on the status tint behind a 1px status border; role alert for danger, status otherwise.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    danger.bgcolor.status.danger.tintobserveduse#2b0e0dDanger background tint.
    danger.bordercolor.status.danger.borderobserveduse#e53935Danger border, 2px on invalid inputs.
    danger.textcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).
    warning.bgcolor.status.warning.tintapproveduse#1f1a0cWarning background tint.
    warning.bordercolor.status.warning.borderapproveduse#c9973fWarning border.
    warning.textcolor.status.warning.textapproveduse#c9973fWarning text (7.54:1).
    success.bgcolor.status.success.tintapproveduse#0f1a0eSuccess background tint.
    success.bordercolor.status.success.borderapproveduse#86a46fSuccess border.
    success.textcolor.status.success.textapproveduse#86a46fSuccess text (7.13:1).
    info.bgcolor.status.info.tintapproveduse#0f141cInfo background tint.
    info.bordercolor.status.info.borderapproveduse#7e9ebbInfo border.
    info.textcolor.status.info.textapproveduse#7e9ebbInfo text (7.08:1).
    neutral.bgcolor.status.neutral.tintobserveduse#241010Neutral background tint.
    neutral.bordercolor.status.neutral.borderobserveduse#a3676bNeutral border.
    neutral.textcolor.status.neutral.textobserveduse#bd787dNeutral status text.
    body.textcolor.text.defaultobserveduse#e99499Interface and body text.
    close.textcolor.action.tertiary.textobserveduse#e99499Ghost and icon button text.
    close.bg-hovercolor.action.tertiary.hover-bgobserveduse#1c0a09Ghost and icon button hover.
    close.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateDangerWarningSuccessInfoNeutralDismissible
    default
    Unsaved changes

    The draft is kept locally until you publish.

    Saved

    The settings apply to new windows.

    Fonts

    The reference font is not distributed; a metric-compatible fallback is used.

    Read only

    This profile is approved; open a decision to change it.

    New version

    0.2.0 adds the extended overlay.

    hover
    focus-visible

    Purpose

    A status message that belongs to the page or form around it: a failed submit, a saved draft, a deprecation notice. It stays in flow, is never timed, and is announced once when it appears. Transient confirmations are toasts; blocking questions are dialogs.

    Anatomy

    The block on the status tint behind a 1px status border; the glyph in the status text colour; the title in the same colour and the message in color.text.default; an optional close button at the end. The five statuses use their own tint, border and text roles: color.status.danger.tint, color.status.warning.tint, color.status.success.tint, color.status.info.tint and color.status.neutral.tint behind color.status.danger.border, color.status.warning.border, color.status.success.border, color.status.info.border and color.status.neutral.border.

    States

    StateVisualNon-colour channel
    defaultstatus tint, 1px status border, glyph and title in the status text colourthe glyph ✕ ! ✓ i ·
    hoverclose button background → color.action.tertiary.hover-bg; the alert itself does not reactcursor: pointer on the button only
    focus-visiblering 1px dashed color.interaction.focus.ring at −2px on the close buttonthe ring

    The alert has no disabled, selected or loading state; a message that is no longer true is removed, not greyed.

    Keyboard

    Only the close button is in the tab order. Enter or Space dismisses and returns focus to where it was, or to the next focusable element after the alert when that element is gone. Escape does nothing, so a page-level Escape handler is never swallowed.

    Accessibility

    Danger uses role="alert" (assertive) because it needs attention now; the other four use role="status" (polite). The container exists before its text is set, so the live region fires; text is never injected together with the container. The glyph is aria-hidden and the title states the status in words (“Build failed”, “Saved”), so nothing depends on colour or on the glyph alone. The close button is aria-label="Dismiss" and at least 24×24 CSS pixels. Contrast: status text on its tint from 4.88:1 (danger) to 6.59:1 (warning, info); body text at least 7.56:1 on every tint; borders from 4.07:1 (neutral) to 6.59:1.

    Portability

    Everything is a tint, a 1px border and text; the glyph is a text character, not an icon font. Toolkits with a native info bar map its type to the five statuses and keep the glyph in the text; toolkits without a tint draw the border only and record the deviation.

    Non-examples

    A coloured left stripe with no border. A rounded, shadowed card. A banner that slides in or auto-dismisses. Colour-only status without the glyph and a worded title. Using role="alert" for success messages. A close button that is an icon with no accessible name. Fixed-position alerts covering content.

    Keys

    KeyAction
    TabReaches the close button when present; the alert itself is never focusable.
    Enter / SpaceDismisses; focus returns to the element that had it, or to the next focusable element after the alert.
    EscapeNothing; alerts are not dialogs.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: toast badge dialog empty-state error-state

    Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-STATE-MATRIX

    Toast toast

    • Family: Feedback and overlays
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Native control: native <div role=status> (role=alert for danger) inside a region named Notifications; native buttons for the action and dismissAPG pattern
    • specified
    • demonstrated

    A brief notification in a fixed corner stack; canvas surface behind a 1px overlay border, status tints for the four polite statuses and the danger fill for critical ones.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.canvasapproveduse#000000Page and terminal background.
    root.bordercolor.border.overlayproposeduse-and-reportD-008#e53935Every floating layer's 1px border.
    root.textcolor.text.defaultobserveduse#e99499Interface and body text.
    glyph.textcolor.status.info.textapproveduse#7e9ebbInfo text (7.08:1).
    warning.bgcolor.status.warning.tintapproveduse#1f1a0cWarning background tint.
    warning.bordercolor.status.warning.borderapproveduse#c9973fWarning border.
    warning.textcolor.status.warning.textapproveduse#c9973fWarning text (7.54:1).
    success.bgcolor.status.success.tintapproveduse#0f1a0eSuccess background tint.
    success.bordercolor.status.success.borderapproveduse#86a46fSuccess border.
    success.textcolor.status.success.textapproveduse#86a46fSuccess text (7.13:1).
    info.bgcolor.status.info.tintapproveduse#0f141cInfo background tint.
    info.bordercolor.status.info.borderapproveduse#7e9ebbInfo border.
    info.textcolor.status.info.textapproveduse#7e9ebbInfo text (7.08:1).
    neutral.bgcolor.status.neutral.tintobserveduse#241010Neutral background tint.
    neutral.bordercolor.status.neutral.borderobserveduse#a3676bNeutral border.
    neutral.textcolor.status.neutral.textobserveduse#bd787dNeutral status text.
    danger.bgcolor.status.danger.fillobserveduse#dc282eDanger fill.
    danger.textcolor.status.danger.on-fillobserveduse#f9faf9Text on the danger fill (4.58:1).
    danger.button-bg-hovercolor.action.destructive.pressed-bgobserveduse#ae1914Destructive button pressed fill.
    action.textcolor.text.linkapproveduse#f73f35Strong red link text, distinct from rose body text and headings; retain the underline.
    action.bg-hovercolor.interaction.hover.bg-strongobserveduse#630f0dHover on menu items; D-027 moved links to interaction.hover.bg.
    action.text-hovercolor.text.link-hoverobserveduse#f4eeeeLink text on hover, over interaction.hover.bg-strong.
    close.textcolor.action.tertiary.textobserveduse#e99499Ghost and icon button text.
    close.bg-hovercolor.action.tertiary.hover-bgobserveduse#1c0a09Ghost and icon button hover.
    close.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    count.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    stack.zz.toastobserveduse40

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StatePlainFive statuses stackedWith action
    default

    Settings saved.

    Battery at 10%.

    Screenshot copied.

    Workspace 3 moved to the left output.

    Layout locked.

    Window closed.

    hover
    focus-visible
    stacked
    reduced-motion

    Purpose

    A short confirmation or notice that does not belong to any one element on the page: “Saved”, “Copied”, “Connection lost”. It appears in a fixed corner stack, is announced politely, and leaves on its own after a pause or when dismissed. Anything that needs a decision is a dialog; anything tied to a form is an alert.

    Anatomy

    The stack region; each toast on color.surface.canvas behind a 1px color.border.overlay, or on a status tint with its status border; the glyph and the text; an optional action; the Dismiss button; the “+n” count. The danger toast is the historical critical notification: color.status.danger.fill with color.status.danger.on-fill for the text, the glyph and both buttons.

    States

    StateVisualNon-colour channel
    defaultcanvas surface, 1px overlay border, glyph in the status text colourthe glyph; the worded text
    hoveraction → color.interaction.hover.bg-strong with color.text.link-hover; Dismiss → color.action.tertiary.hover-bg; the timeout pausescursor: pointer; underline thickens on the action
    focus-visiblering 1px dashed color.interaction.focus.ring at −2px on the focused button; on the danger fill the ring takes color.status.danger.on-fill; the timeout pausesthe ring
    stackedtoasts sit in one column with a 4px gap, newest at the end; the last visible toast shows “+n” in color.text.muted for queued onesthe count text; at most three visible
    reduced-motionno transition; the toast is simply present or absentprefers-reduced-motion; nothing moves

    The toast has no disabled, selected or busy state.

    Keyboard

    Toasts never take focus when they appear. A host shortcut (F6 on the web reference) moves focus into the region; Tab then walks each toast’s action and Dismiss; Escape dismisses the focused toast. While any toast has focus or the pointer, its timeout is paused.

    Accessibility

    The region is named “Notifications”; each toast is role="status" so it is announced politely, and danger toasts are role="alert". The text states the outcome in words and the glyph is aria-hidden. Every toast has Dismiss and the timeout is at least 8 seconds, extended for toasts with an action; an action is never the only way to reach what it does. Contrast: text 8.65:1 on the canvas, the overlay border 4.69:1, status text on its tint from 5.31:1 (neutral) to 6.59:1, on-fill text 4.58:1 on the danger fill, which is itself 4.14:1 against the canvas.

    Portability

    A fixed region, tints, 1px borders and text glyphs. Hosts with a notification daemon send the text and urgency instead of drawing a toast; the danger fill maps to the critical urgency. Toolkits with a native toast overlay use it and record that the danger fill is not available.

    Non-examples

    A toast that slides in from an edge. A rounded, shadowed pill. A toast with no Dismiss that vanishes after two seconds. A toast that takes focus on appearance. Stacking more than three with no count. A form error shown as a toast. Colour-only status without the glyph and worded text.

    Keys

    KeyAction
    F6 / a host shortcutMoves focus into the notification region; toasts never steal focus when they appear.
    Tab / Shift+TabWithin the region, reaches the action and then Dismiss of each toast in order.
    Enter / SpaceActivates the action or dismisses.
    EscapeDismisses the focused toast and returns focus to the region, then to the page.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: alert dialog progress badge

    Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-OVERFLOW FX-STATE-MATRIX

    Progress progress

    • Family: Feedback and overlays
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Native control: native <progress> labelled by <label for>; aria-valuetext for indeterminate workAPG pattern
    • specified
    • demonstrated

    A native progress element with a label and value; determinate fills with the primary colour, indeterminate shows static 45° stripes, never an animation.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    track.bgcolor.interaction.pressed.bgobserveduse#420f0cPressed fill.
    track.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    value.bgcolor.action.primary.bgapproveduse#7d1310Primary button fill; D-026 darkened it off color12, which stays fixed as heritage ANSI 12.
    value.bg-errorcolor.status.danger.fillobserveduse#dc282eDanger fill.
    stripe.acolor.action.primary.bgapproveduse#7d1310Primary button fill; D-026 darkened it off color12, which stays fixed as heritage ANSI 12.
    stripe.bcolor.interaction.pressed.bgobserveduse#420f0cPressed fill.
    label.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    value.textcolor.text.defaultobserveduse#e99499Interface and body text.
    detail.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    error.textcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateDeterminateIndeterminateWith detail line
    default
    62%
    62%
    In progress
    14 of 67
    14 of 67

    Writing exports/components/date-picker.json

    busy
    error
    reduced-motion

    Purpose

    Shows how far a known task has gone, or that an unbounded one is running. It reports; it never blocks. A task that can be cancelled has a button beside the bar. A short wait with no bar is the loading indicator.

    Anatomy

    The header row with the label in color.text.bright and the value in color.text.default; the bar, a native progress element whose track is color.interaction.pressed.bg behind a 1px color.border.control and whose fill is color.action.primary.bg; an optional detail line in color.text.muted.

    States

    StateVisualNon-colour channel
    defaultfill color.action.primary.bg on the track; the value textthe native value; the percentage text
    busythe whole track shows static 45° stripes of color.action.primary.bg on color.interaction.pressed.bg; no value textaria-busy; aria-valuetext; the stripe pattern; no animation
    errorfill → color.status.danger.fill; the label gains the ✕ glyph in color.status.danger.text; the detail line says what failedglyph; worded detail
    reduced-motionidentical to default and busy: nothing animates in any stateprefers-reduced-motion

    Indeterminate work is the busy state; the determinate variant enters it while the total is unknown and leaves it once known.

    Keyboard

    None. The progress element is not focusable and receives no key. A cancel button next to the bar is an ordinary button with its own tab stop.

    Accessibility

    The label is a real <label for> on the progress element, so its name is programmatic; the value is in the native value and repeated in text. Indeterminate bars set aria-valuetext (“Preparing”), and the container sets aria-busy for the duration. Completion and failure are announced through a polite live region, not by the bar. Contrast: label 10.37:1, value 8.65:1, detail 5.81:1, track boundary 4.45:1, error fill 3.36:1 against the track. The primary fill against the track measures 1.51:1 and is waived because the value is stated in text; a host that must meet 3:1 graphically raises the track to color.surface.canvas.

    Portability

    A track, a fill and a hatched pattern. Toolkits with a native bar map the fill to the primary colour and disable pulse animation; toolkits without gradients draw the stripes with a hatched brush or alternating characters.

    Non-examples

    A spinner. Animated or “barber-pole” stripes. A shimmering skeleton in place of a bar. A circular ring. A rounded pill-shaped bar. Colour-only failure without the glyph and text. A bar with no label. A bar that blocks input.

    Keys

    KeyAction
    TabNothing; progress is not focusable and never traps a person.
    EscapeNothing; cancelling is a separate button next to the bar.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: loading-indicator file-input wizard toast

    Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-STATE-MATRIX

    Loading indicator loading-indicator

    • Family: Feedback and overlays
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Native control: native container with aria-busy=true and role=status; the glyph is aria-hidden and the label carries the meaningAPG pattern
    • specified
    • demonstrated

    A static ⋯ glyph with a worded label inside an aria-busy container; inline next to text or as a centred block. There is no spinner.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    glyph.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    label.textcolor.text.defaultobserveduse#e99499Interface and body text.
    block.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    block.bordercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateInlineBlock
    default
    Loading fonts
    Loading the component list
    reduced-motion

    Purpose

    Marks the moment between a request and its result when there is nothing to measure: a list that is being fetched, a field that is being validated. The theme has no spinner; the same static ⋯ glyph that a loading control shows appears here beside a worded label, and the container says it is busy.

    Anatomy

    The busy container; the glyph in color.text.muted; the label in color.text.default. Inline, the two follow the text they qualify; as a block, they sit centred on color.surface.default inside a color.border.divider edge where the content will appear.

    States

    StateVisualNon-colour channel
    defaultthe static ⋯ and the labelaria-busy="true"; the glyph; the worded label
    reduced-motionidentical: there is nothing to reduceprefers-reduced-motion

    The indicator has no hover, focus or disabled state; it is not a control.

    Keyboard

    None. The indicator is never focusable. When loading replaces content that had focus, focus moves to the container’s heading or to the indicator’s parent region, never to the indicator itself, and returns to the result when it arrives.

    Accessibility

    The container is role="status" with aria-busy="true" while loading, so assistive technology can wait for the subtree to settle and announce the label once. The glyph is aria-hidden; the label is a real sentence with the object named (“Loading fonts”) and is visible in both variants; a host that must hide it inline keeps it visually hidden, never absent. Because nothing moves, there is no prefers-reduced-motion branch to get wrong. Contrast: label 8.65:1 on the canvas and 8.43:1 on the panel surface; glyph 5.81:1 and 5.66:1.

    Portability

    Text only. Toolkits with a spinner widget do not use it; the glyph and label are a plain label. Hosts that insist on an activity indicator record the deviation and keep it under the 150 ms motion budget with a reduced-motion branch.

    Non-examples

    A spinner or rotating ring. Animated dots. A shimmering skeleton. A full-page overlay that blocks input for a fetch. A glyph with no label. An indicator that takes focus. A dimmed container at reduced opacity.

    Keys

    KeyAction
    TabNothing; the indicator is not focusable and never traps focus; the content it replaces keeps its tab stops when it returns.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: progress skeleton empty-state toast

    Stress fixtures: FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-STATE-MATRIX

    Tooltip tooltip

    • Family: Feedback and overlays
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Custom widget: APG tooltip: a trigger with aria-describedby pointing at an element with role=tooltip, shown on hover and focus, hidden on EscapeAPG pattern
    • specified
    • demonstrated

    A short description of a control shown on hover and focus; role tooltip linked by aria-describedby, a 1px overlay border on the raised surface, no arrow.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    popup.bgcolor.surface.raisedapproveduse#160b0bSticky headers, menus, popovers; D-027 recessed it so an open list reads as depth rather than a lighter panel.
    popup.bordercolor.border.overlayproposeduse-and-reportD-008#e53935Every floating layer's 1px border.
    popup.textcolor.text.defaultobserveduse#e99499Interface and body text.
    shortcut.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    shortcut.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    trigger.textcolor.action.tertiary.textobserveduse#e99499Ghost and icon button text.
    trigger.bg-hovercolor.action.tertiary.hover-bgobserveduse#1c0a09Ghost and icon button hover.
    trigger.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    popup.zz.popoverobserveduse10

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateDescriptionWith shortcut
    default
    hover
    focus-visible
    open
    closed

    Purpose

    A few words that explain a control without being its name: what an icon button does, which shortcut opens it, why it is disabled. It is a description only. Anything a person must read to use the control belongs in the control or its label, and anything interactive is a popover.

    Anatomy

    The trigger and the popup. The popup is color.surface.raised behind a 1px color.border.overlay, text in color.text.default, optional shortcut in a kbd with color.text.bright inside a 1px color.border.control; no arrow, no shadow, no radius. The demonstration renders it in flow below the trigger.

    States

    StateVisualNon-colour channel
    defaulttrigger at rest; the popup shown for the demonstrationaria-describedby on the trigger
    hovertrigger background → color.action.tertiary.hover-bg; the popup appears after 300 mscursor: pointer; the popup itself
    focus-visiblering 1px dashed color.interaction.focus.ring at −2px on the trigger; the popup appears at oncethe ring; the popup
    openthe popup visible, 1px color.border.overlay on color.surface.raisedthe popup is present in the accessibility tree
    closedthe popup absent; the trigger unchangedhidden; the description is still read from the DOM

    The popup itself has no hover, pressed or focus state: it is not interactive.

    Keyboard

    Focus on the trigger shows the tooltip without delay; moving focus away hides it. Escape hides it and does nothing else, so a dialog behind the trigger does not close. The popup never receives focus and contains no focusable element.

    Accessibility

    The trigger points at the popup with aria-describedby, so the description is available whether or not the popup is shown; the popup is role="tooltip". It opens on hover and on focus, stays open while the pointer is over the trigger or the popup (WCAG 1.4.13: hoverable, dismissible, persistent), and closes on Escape. The trigger has its own accessible name; the tooltip never supplies it. Touch has no hover: the description is available through a long-press or is shown inline. Contrast: text 8.43:1 on the raised surface, shortcut 10.10:1, border 4.57:1.

    Portability

    A box with a border and text; placement is the host’s positioning primitive. Toolkits with a native tooltip use it with the tokens for border and background and record any radius they cannot remove.

    Non-examples

    A rounded bubble with an arrow. A tooltip with a shadow or a fade longer than 150 ms. A tooltip as the only accessible name of an icon button. A tooltip with a link or a button inside. One that opens on focus but not on hover, or on hover with no delay. A title attribute. A tooltip that follows the pointer.

    Keys

    KeyAction
    TabFocusing the trigger shows the tooltip; leaving it hides the tooltip.
    EscapeHides the tooltip without moving focus; the trigger's own Escape behaviour is not triggered.
    Enter / SpaceAct on the trigger as usual; the tooltip hides on activation.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: icon-button popover kbd toolbar menu

    Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-OVERFLOW FX-STATE-MATRIX

    Dialog dialog

    • Family: Feedback and overlays
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Native control: native <dialog> opened with showModal; role=alertdialog for confirmations; named by its heading, described by its first paragraphAPG pattern
    • specified
    • demonstrated
    • tested

    A native dialog on the overlay surface behind a 1px overlay border and the backdrop; modal when shown, with trapped focus and Escape to close.

    Report an issue with this component

    Open component workbench

    View source and copy recipe · Download standalone example — visual-only; modal behavior is host-owned.

    Tokens

    PartRoleValueUse
    backdrop.bgcolor.surface.backdropproposeduse-and-reportD-008rgb(0 0 0 / 65%)Behind modal dialogs.
    root.bgcolor.surface.overlayobserveduse#241010Dialogs and drawers.
    root.bordercolor.border.overlayproposeduse-and-reportD-008#e53935Every floating layer's 1px border.
    root.ringcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
    root.zz.dialogobserveduse30
    title.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    text.textcolor.text.defaultobserveduse#e99499Interface and body text.
    close.textcolor.action.tertiary.textobserveduse#e99499Ghost and icon button text.
    close.bg-hovercolor.action.tertiary.hover-bgobserveduse#1c0a09Ghost and icon button hover.
    close.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    button.textcolor.action.secondary.textobserveduse#ffa2a7Secondary button text.
    button.bordercolor.action.secondary.borderobserveduse#a3676bSecondary button border (meets 3:1).
    button.bg-hovercolor.action.secondary.hover-bgobserveduse#630f0dSecondary button hover.
    primary.bgcolor.action.primary.bgapproveduse#7d1310Primary button fill; D-026 darkened it off color12, which stays fixed as heritage ANSI 12.
    primary.textcolor.action.primary.textobserveduse#f4eeeePrimary button text (9.28:1).
    primary.bg-hovercolor.action.primary.hover-bgobserveduse#911410Primary button hover (7.92:1 with prose).
    destructive.bgcolor.action.destructive.filled-bgobserveduse#dc282eConfirm-dialog destructive fill.
    destructive.textcolor.action.destructive.filled-textobserveduse#f9faf9Text on the destructive fill.
    destructive.bg-hovercolor.action.destructive.hover-bgobserveduse#dc282eDestructive button hover fill.
    field.bgcolor.surface.inputapproveduse#000000Form-control fill.
    field.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    field.labelcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    note.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateConfirmAlert dialogForm
    default

    Save changes?

    Three settings changed since the last save. Unsaved changes are kept locally until you publish.

    Focus is trapped: Tab cycles inside the dialog; Escape closes it.

    Delete profile "workstation"?

    The profile and its two overlays are removed. This cannot be undone.

    Focus is trapped: Tab cycles inside the dialog; Escape cancels.

    New profile

    The profile starts from the default tokens.

    Lowercase letters, digits and hyphens.

    Focus is trapped: Tab cycles inside the dialog; Enter submits; Escape cancels.

    open
    closed
    focus-trapped
    hover
    focus-visible
    reduced-motion

    Purpose

    A question or a small task that must be answered before the page continues: confirm a destructive action, name a new profile, sign in again. It takes the whole screen’s attention, so it is short, has a clear title, and always offers a way out. The demonstration renders the dialog open in flow, with a wrapper standing in for the backdrop; a host always uses showModal().

    Anatomy

    The backdrop, color.surface.backdrop over the page; the dialog on color.surface.overlay behind a 1px color.border.overlay; the header with the title in color.text.bright and Close; the body in color.text.default; the actions row. Confirmation semantics do not prescribe action tone (D-015): ordinary confirmations use primary. A destructive confirmation uses the filled destructive button, color.action.destructive.filled-bg with color.action.destructive.filled-text; the form dialog holds a labelled text field on color.surface.input.

    States

    StateVisualNon-colour channel
    defaultthe dialog open on its backdropopen; the page behind is inert
    openas default; opacity 0 → 1 within 150 ms on capable hostsopen; focus inside the dialog
    closednothing: the dialog and its backdrop are absentno open; focus back on the opener
    focus-trappedthe dialog itself carries the container ring, 2px solid color.interaction.focus.ring-container at −3px, when it holds focus; the note says Tab cyclesTab never leaves; the note text
    hoverClose background → color.action.tertiary.hover-bg; other buttons take their tone’s hovercursor: pointer
    focus-visiblering 1px dashed color.interaction.focus.ring at −2px on the focused control; primary uses color.interaction.focus.ring-container, destructive uses color.action.destructive.filled-text (D-015)the ring
    reduced-motionno opacity transition; the dialog is simply present or absentprefers-reduced-motion

    A dialog is never disabled; a busy dialog disables its confirm button and shows the ⋯ glyph on it.

    Keyboard

    Tab and Shift+Tab cycle inside the dialog; nothing behind it is reachable. Escape closes and cancels, and focus returns to the opener. Enter submits a form dialog; elsewhere it only activates the focused button, so a destructive confirm is never triggered by Enter on the dialog itself. On open, focus goes to the first focusable element, or to the dialog when the first element is destructive; on close, back to the opener.

    Accessibility

    The dialog is named by its title through aria-labelledby and described by its first paragraph through aria-describedby. Confirmations use role="alertdialog". showModal() makes the rest of the page inert and supplies the top layer; the theme never re-implements the trap on a non-modal dialog. The backdrop is decorative and not a click target for cancel unless Close is also present. Contrast: text 7.92:1 and title 9.49:1 on the overlay surface, the overlay border 4.30:1, secondary buttons 6.84:1 on hover, destructive confirm text 4.58:1 on its fill, the container ring 9.49:1.

    Portability

    A box, a border, a dimmed backdrop and the button tones. Toolkits with a native modal window use it with the overlay border on the frame and record that the backdrop is the host’s. Toolkits without a top layer draw the backdrop as a full-window overlay under the dialog.

    Non-examples

    A glowing or shadowed card. Rounded corners. A dialog that slides or scales in. <dialog> shown with show() and a hand-written focus trap. A dialog with no title, or with the title only in the accessible name. A destructive confirm as the default Enter action. A backdrop that closes the dialog with no Close button. A dialog stacked on a dialog.

    Keys

    KeyAction
    Tab / Shift+TabCycles through the dialog's focusable elements and never leaves it while open.
    EscapeCloses the dialog (cancel) and returns focus to the element that opened it.
    EnterIn a form dialog, submits; otherwise activates the focused button only.
    SpaceActivates the focused button.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: drawer alert toast button text-field popover

    Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-OVERFLOW FX-STATE-MATRIX

    Drawer drawer

    • Family: Feedback and overlays
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Native control: native <dialog> opened with showModal, anchored to an inline edge; named by its heading; Escape closesAPG pattern
    • specified
    • demonstrated

    A full-height modal panel anchored to the start or end edge; a native dialog on the overlay surface with a 1px overlay border on its inner edge.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    backdrop.bgcolor.surface.backdropproposeduse-and-reportD-008rgb(0 0 0 / 65%)Behind modal dialogs.
    root.bgcolor.surface.overlayobserveduse#241010Dialogs and drawers.
    root.bordercolor.border.overlayproposeduse-and-reportD-008#e53935Every floating layer's 1px border.
    root.ringcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
    root.zz.drawerobserveduse20
    title.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    text.textcolor.text.defaultobserveduse#e99499Interface and body text.
    body.dividercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
    item.textcolor.text.defaultobserveduse#e99499Interface and body text.
    item.bg-hovercolor.interaction.hover.bg-strongobserveduse#630f0dHover on menu items; D-027 moved links to interaction.hover.bg.
    item.text-hovercolor.text.link-hoverobserveduse#f4eeeeLink text on hover, over interaction.hover.bg-strong.
    close.textcolor.action.tertiary.textobserveduse#e99499Ghost and icon button text.
    close.bg-hovercolor.action.tertiary.hover-bgobserveduse#1c0a09Ghost and icon button hover.
    close.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    note.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateStart edgeEnd edge
    default

    Sections

    Focus is trapped: Tab cycles inside the drawer; Escape closes it.

    Filters

    Narrow the table to the rows that match every filter.

    Focus is trapped: Tab cycles inside the drawer; Escape closes it.

    open
    closed
    focus-trapped
    reduced-motion

    Purpose

    A panel that opens from the side to hold navigation or a task on narrow screens, or a secondary form on wide ones. It is a modal dialog with a different shape: full height, anchored to the start or end edge, with a single visible border on the edge that faces the page. Below 900px the sidebar collapses into a drawer; above it, a drawer holds tasks that need more room than a dialog.

    Anatomy

    The backdrop, color.surface.backdrop over the page; the panel on color.surface.overlay with a 1px color.border.overlay on its inner edge; the header with the title in color.text.bright and Close; the body, rows divided by color.border.divider. The demonstration renders the panel inside a stage of fixed height standing in for the viewport.

    States

    StateVisualNon-colour channel
    defaultthe panel open at its edge on the backdropopen; the page behind is inert
    openas default; opacity 0 → 1 within 150 ms on capable hosts; never a slideopen; focus inside the panel
    closednothing: the panel and the backdrop are absentno open; focus back on the opener
    focus-trappedthe panel carries the container ring, 2px solid color.interaction.focus.ring-container at −3px, when it holds focus; the note says Tab cyclesTab never leaves; the note text
    reduced-motionno opacity transition; the panel is simply present or absentprefers-reduced-motion

    Items inside the drawer take the states of the list or navigation they belong to; Close takes the tertiary button’s hover and ring.

    Keyboard

    Tab and Shift+Tab cycle inside the panel; the page behind is inert. Escape closes and returns focus to the opener. Enter or Space on a navigation item navigates and closes. On open, focus goes to the first focusable element, which is the first item or Close.

    Accessibility

    The panel is named by its title through aria-labelledby. showModal() supplies the top layer and inertness; the theme never re-implements the trap on a non-modal element or on a plain aside. The backdrop is decorative; a click on it may close the drawer only because Close is also present. Both edges use logical properties, so the panel and its border mirror in RTL with no extra rules. Contrast: text 7.92:1 and title 9.49:1 on the overlay surface, the border 4.30:1, the ring 4.30:1, hovered items 11.41:1 on the strong hover fill.

    Portability

    A full-height box with one border and a dimmed backdrop. Toolkits without a top layer draw the backdrop as a full-window overlay under the panel; toolkits with a native sidebar keep it non-modal and record that it is a sidebar, not a drawer.

    Non-examples

    A panel that slides in from the edge. A drawer with a shadow or a rounded inner corner. A drawer that is a plain aside with a hand-written focus trap. A bottom sheet with a drag handle. A drawer with no Close button. A drawer that stays open under a dialog. A translucent panel over page content.

    Keys

    KeyAction
    Tab / Shift+TabCycles inside the drawer and never leaves it while open.
    EscapeCloses the drawer and returns focus to the element that opened it.
    Enter / SpaceActivates the focused item or button; a navigation item closes the drawer after navigating.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: dialog sidebar-nav menu toolbar

    Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-OVERFLOW FX-STATE-MATRIX

    Empty state empty-state

    • Family: Feedback and overlays
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Native control: native block; a heading and a paragraph inside the region the content would fill; the action is a native <button> or <a>APG pattern
    • specified
    • demonstrated

    What a container shows when it has nothing to list; a glyph, a heading in the bright text colour, one sentence in the muted colour and an optional secondary action.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    root.bordercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
    glyph.textcolor.icon.decorativeobserveduse#a3676bDecorative glyphs (3:1 as graphics, never text).
    heading.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    text.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    action.textcolor.action.secondary.textobserveduse#ffa2a7Secondary button text.
    action.bordercolor.action.secondary.borderobserveduse#a3676bSecondary button border (meets 3:1).
    action.bg-hovercolor.action.secondary.hover-bgobserveduse#630f0dSecondary button hover.
    action.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateWith actionWithout action
    default

    No components match

    Three filters are active; none of the 67 components passes all of them.

    No notifications

    New ones appear here and in the corner of the screen.

    Purpose

    A region with nothing in it says so, and says what would fill it. It replaces a blank pane, an empty table body or a list with no rows after a filter, and it offers the one action that changes that when there is one. A failure is the error state; a wait is the loading indicator.

    Anatomy

    The block on color.surface.default inside a 1px color.border.divider, content centred; the glyph in color.icon.decorative; the heading in color.text.bright; the sentence in color.text.muted; the optional secondary action in color.action.secondary.text with a 1px color.action.secondary.border.

    States

    StateVisualNon-colour channel
    defaultglyph, heading and sentence centred; the action, when present, below themthe worded heading; the action is a real button

    The block has no states of its own; the action takes the secondary button’s hover and ring.

    Keyboard

    Only the action is in the tab order. When a filter empties a list that had focus inside it, focus moves to the heading of the region, not into the empty state, so the person hears where they are.

    Accessibility

    The heading is a real heading at the level the region uses, so the empty state appears in the outline; the sentence follows it in the reading order. The glyph is aria-hidden. When content becomes empty after an action (filter, delete), a polite live region announces the heading text. The action is never the only route: filters can also be cleared where they were set. Contrast: heading 10.10:1, sentence 5.66:1, action text 10.10:1 and its border 4.33:1 on the panel surface.

    Portability

    Text and one optional button. Toolkits with a status page use it with the glyph as text; toolkits with only a placeholder string add the action as a separate button below the view.

    Non-examples

    An illustration or mascot. A primary (filled) call to action. A blank pane. A greyed-out table header with no message. A message that only says “No data”. A heading in the accent red. An empty state that appears while loading. Centred text in a rounded card with a shadow.

    Keys

    KeyAction
    TabReaches the action when present; the block itself is never focusable.
    Enter / SpaceActivates the action.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: error-state loading-indicator list table data-table button

    Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-STATE-MATRIX

    Skeleton skeleton

    • Family: Feedback and overlays
    • Maturity: stable
    • Priority: R2
    • Since: 1.0.0
    • Native control: Native status text with aria-hidden decorative blocks
    • specified
    • demonstrated

    Static layout placeholders with a named loading status.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    root.textcolor.text.defaultobserveduse#e99499Interface and body text.
    root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    heading.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    secondary.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    control.bgcolor.surface.inputapproveduse#000000Form-control fill.
    control.focuscolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    dependency.role-border-width-defaultborder.width.defaultobserveduse1pxEvery border is 1px.
    dependency.role-color-border-dividercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
    dependency.role-color-surface-raisedcolor.surface.raisedapproveduse#160b0bSticky headers, menus, popovers; D-027 recessed it so an open list reads as depth rather than a lighter panel.
    dependency.role-radius-noneradius.noneobserveduse0pxThe only radius. Nothing is rounded.
    dependency.role-space-12space.12observeduse12px
    dependency.role-space-16space.16observeduse16px
    dependency.role-space-2space.2observeduse2px

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateDefault
    default

    Loading project details…

    loading
    reduced-motion

    Purpose

    Reserve approximate layout space while a named region loads. Decorative blocks are hidden from accessibility APIs. A separate status describes loading. The skeleton is static and never shimmers.

    Anatomy

    • status: Text names what is loading.
    • blocks: Decorative square placeholders retain approximate dimensions.

    States

    StatePresentationNon-colour channel
    defaultStatic decorative blocks.Named loading status.
    loadingRaised surface blocks; no opacity fade.aria-busy on the region.
    reduced-motionSame static presentation.No information depends on movement.

    Keyboard

    • Tab: No new tab stops or focus capture.

    Accessibility

    Apply aria-busy to the region being updated and provide a concise status. Decorative blocks are aria-hidden. Do not remove the focused control merely to show a skeleton. Replacement content must keep a sensible reading order.

    Portability

    Wrap labels and actions without changing source order. Use logical spacing in RTL. Preserve native target sizes at both densities; only bounded data regions may scroll horizontally. Use equivalent native semantics and approved roles; record any unsupported behavior as a mapping deviation. The host owns application data, persistence, permissions and services.

    Non-examples

    Unlabelled controls, color-only status, drag-only operations, hidden required instructions, stolen focus or an invented service success.

    Keys

    KeyAction
    TabNo new tab stops or focus capture.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Stress fixtures: FX-320 FX-360 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

    Popover popover

    • Family: Feedback and overlays
    • Maturity: stable
    • Priority: R2
    • Since: 1.0.0
    • Native control: Native button and named supporting section
    • specified
    • demonstrated

    A non-modal supporting panel with light dismissal and ordinary tab order.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    root.textcolor.text.defaultobserveduse#e99499Interface and body text.
    root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    heading.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    secondary.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    control.bgcolor.surface.inputapproveduse#000000Form-control fill.
    control.focuscolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    dependency.role-border-width-defaultborder.width.defaultobserveduse1pxEvery border is 1px.
    dependency.role-color-border-overlaycolor.border.overlayproposeduse-and-reportD-008#e53935Every floating layer's 1px border.
    dependency.role-color-surface-overlaycolor.surface.overlayobserveduse#241010Dialogs and drawers.
    dependency.role-density-comfortable-control-heightdensity.comfortable.control-heightobserveduse32px
    dependency.role-density-compact-control-heightdensity.compact.control-heightobserveduse24px
    dependency.role-radius-noneradius.noneobserveduse0pxThe only radius. Nothing is rounded.
    dependency.role-space-12space.12observeduse12px
    dependency.role-space-16space.16observeduse16px
    dependency.role-space-2space.2observeduse2px
    dependency.role-space-8space.8observeduse8px

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateDefault
    default

    This workspace uses synthetic local data.

    open
    closed
    focus-visible

    Purpose

    Disclose a non-modal supporting panel near its trigger. Interactive content follows ordinary tab order. Escape and outside activation dismiss; focus is not trapped. Use the native Popover API when available with an equivalent documented fallback.

    Anatomy

    • trigger: Native button with expanded state and panel relationship.
    • panel: Named supporting content and optional visible close action.

    States

    StatePresentationNon-colour channel
    defaultNamed trigger.Button semantics and accessible name.
    openSquare overlay surface and border.aria-expanded=true; panel is reachable.
    closedPanel hidden.aria-expanded=false; hidden controls leave focus order.
    focus-visibleDashed focus ring.Native keyboard focus.

    Keyboard

    • Enter / Space: Toggle from the trigger.
    • Tab / Shift+Tab: Move through ordinary controls without trapping focus.
    • Escape: Close and restore the trigger.

    Accessibility

    Keep essential instructions outside collapsed panels. Use a visible label or aria-label for the panel. Do not add aria-modal or a focus trap. Native automatic dismissal and the fallback both synchronize expanded state.

    Portability

    Wrap labels and actions without changing source order. Use logical spacing in RTL. Preserve native target sizes at both densities; only bounded data regions may scroll horizontally. Use equivalent native semantics and approved roles; record any unsupported behavior as a mapping deviation. The host owns application data, persistence, permissions and services.

    Non-examples

    Unlabelled controls, color-only status, drag-only operations, hidden required instructions, stolen focus or an invented service success.

    Keys

    KeyAction
    Enter / SpaceToggle from the trigger.
    Tab / Shift+TabMove through ordinary controls without trapping focus.
    EscapeClose and restore the trigger.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Stress fixtures: FX-320 FX-360 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

    Error state error-state

    • Family: Feedback and overlays
    • Maturity: stable
    • Priority: R2
    • Since: 1.0.0
    • Native control: Named section and native retry button
    • specified
    • demonstrated

    A specific failure explanation with an explicit recovery request.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    root.textcolor.text.defaultobserveduse#e99499Interface and body text.
    root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    heading.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    secondary.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    control.bgcolor.surface.inputapproveduse#000000Form-control fill.
    control.focuscolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    dependency.role-border-width-defaultborder.width.defaultobserveduse1pxEvery border is 1px.
    dependency.role-border-width-emphasisborder.width.emphasisobserveduse2pxSelected indicator, sticky header rule, invalid border.
    dependency.role-color-border-disabledcolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
    dependency.role-color-interaction-disabled-bgcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
    dependency.role-color-status-danger-bordercolor.status.danger.borderobserveduse#e53935Danger border, 2px on invalid inputs.
    dependency.role-color-status-danger-textcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).
    dependency.role-color-text-disabledcolor.text.disabledapproveduse#8a5559Disabled control text.
    dependency.role-density-comfortable-control-heightdensity.comfortable.control-heightobserveduse32px
    dependency.role-density-compact-control-heightdensity.compact.control-heightobserveduse24px
    dependency.role-radius-noneradius.noneobserveduse0pxThe only radius. Nothing is rounded.
    dependency.role-space-12space.12observeduse12px
    dependency.role-space-2space.2observeduse2px
    dependency.role-space-8space.8observeduse8px

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateDefault
    default

    ✕ Project list unavailable

    The demonstration request failed. Retry to load the local example records.

    error
    loading
    disabled
    focus-visible

    Purpose

    Explain a failed operation and offer a bounded recovery action. Retrying emits a request; the component does not claim that a service recovered. The host updates content when the actual operation completes.

    Anatomy

    • message: Heading, explanation and text error glyph.
    • recovery: Native retry action, disabled while the host request is pending.

    States

    StatePresentationNon-colour channel
    defaultDanger border and text heading.Specific written explanation and error glyph.
    errorSame explicit failure treatment.Failure text remains available.
    loadingBusy status accompanies the existing explanation.aria-busy and host-provided pending text.
    disabledDisabled roles at full opacity.Native retry button is disabled.
    focus-visibleDashed ring.Native keyboard focus.

    Keyboard

    • Tab / Shift+Tab: Reach the recovery action.
    • Enter / Space: Request a retry without moving focus.

    Accessibility

    Do not rely only on color or a glyph. Give the retry action a specific name. Announce a newly occurring error in an appropriate host status region, without repeatedly interrupting reading. Keep focus unless recovery requires an explicit next step.

    Portability

    Wrap labels and actions without changing source order. Use logical spacing in RTL. Preserve native target sizes at both densities; only bounded data regions may scroll horizontally. Use equivalent native semantics and approved roles; record any unsupported behavior as a mapping deviation. The host owns application data, persistence, permissions and services.

    Non-examples

    Unlabelled controls, color-only status, drag-only operations, hidden required instructions, stolen focus or an invented service success.

    Keys

    KeyAction
    Tab / Shift+TabReach the recovery action.
    Enter / SpaceRequest a retry without moving focus.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Stress fixtures: FX-320 FX-360 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

    Developer interfaces

    Editor syntax, gutters, caret, selections, search, diagnostics, diffs, terminal text and the historical ANSI slots.

    Code editor code-editor

    • Family: Developer interfaces
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Custom widget: presentation of <pre> inside role=textbox with aria-multiline and aria-readonly; a real editor is a host surfaceAPG pattern
    • specified
    • demonstrated

    The editor surface, gutter, caret, current line, selection, bracket match and monochrome syntax roles that every code-editing or code-viewing host maps onto.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.code.bgobserveduse#0c0909Editor background.
    root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    root.ringcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
    gutter.bgcolor.code.gutter-bgobserveduse#0c0909Gutter background.
    gutter.rulecolor.code.gutter-ruleobserveduse#2b0e0dRule between gutter and text.
    gutter.bg-read-onlycolor.surface.sunkenapproveduse#000000Reading and detail panes set below the canvas.
    line-number.textcolor.code.line-numberapproveduse#ad7175Line numbers (5.10:1; replaces the site's #7d1310).
    line-number.text-activecolor.code.line-number-activeobserveduse#e99499Line number of the current line.
    line.bg-currentcolor.code.current-lineobserveduse#1c0a09Current line background.
    caret.bgcolor.code.caretobserveduse#e99499Caret (Xresources *cursorColor).
    selection.bgcolor.code.selection-bgobserveduse#420f0cEditor selection background (muted text stays 4.71:1).
    selection.bg-inactivecolor.interaction.selection.inactive-bgobserveduse#420f0cSelection while the container is not focused.
    selection.text-inactivecolor.interaction.selection.inactive-textobserveduse#e99499Text on the inactive selection (7.02:1).
    bracket.outlinecolor.code.bracket-matchobserveduse#e53935Matching bracket 1px border.
    indent.guidecolor.code.indent-guideobserveduse#531310Indent guides.
    whitespace.textcolor.code.whitespaceobserveduse#7d1310Rendered whitespace (decorative).
    fold.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    fold.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    syntax.keywordcolor.code.syntax.keywordobserveduse#f73f35Keywords (Xresources color5 lineage).
    syntax.stringcolor.code.syntax.stringobserveduse#bd787dStrings (color2 lineage).
    syntax.commentcolor.code.syntax.commentapproveduse#ad7175Comments, italic (color8 lineage, corrected for contrast).
    syntax.numbercolor.code.syntax.numberobserveduse#d4868bNumbers.
    syntax.constantcolor.code.syntax.constantobserveduse#d4868bConstants and booleans.
    syntax.functioncolor.code.syntax.functionobserveduse#ffa2a7Function names and calls (color7 lineage).
    syntax.variablecolor.code.syntax.variableobserveduse#e99499Variables and default text.
    syntax.typecolor.code.syntax.typeobserveduse#b37175Types.
    syntax.operatorcolor.code.syntax.operatorobserveduse#e99499Operators.
    syntax.punctuationcolor.code.syntax.punctuationobserveduse#e99499Punctuation.
    syntax.propertycolor.code.syntax.propertyobserveduse#e53935Properties and keys (site .syntax-key).
    syntax.headingcolor.code.syntax.headingobserveduse#e53935Markup headings (site .syntax-heading).
    syntax.tagcolor.code.syntax.tagobserveduse#f73f35Markup tags.
    syntax.attributecolor.code.syntax.attributeobserveduse#d4868bMarkup attributes.
    syntax.escapecolor.code.syntax.escapeobserveduse#d4868bEscape sequences and regex, bold.
    syntax.invalidcolor.code.syntax.invalidobserveduse#e53935Invalid text: wavy underline.
    syntax.deprecatedcolor.code.syntax.deprecatedobserveduse#ad7175Deprecated symbol: line-through.

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateJavaScriptMarkupFolded region
    default
    // Compose the window title of the focused container.
    import { Container } from "./tree.js";
    const MAX_LENGTH = 48;
    export function title(container) {
      const name = container.name ?? "untitled";
      let label = `${name} (${container.children.length})`;
      if (label.length > MAX_LENGTH) {
        label = label.slice(0, MAX_LENGTH) + "…";
      }
      return escape(label); /* escape() is deprecated */
    }
    const broken = 0x1G;
    <!doctype html>
    <!-- window frame specimen -->
    <html lang="en">
      <head>
        <title>j3w1 &mdash; theme</title>
      </head>
      <body class="frame" data-density="compact">
        <h1>Window frame</h1>
        <marquee>obsolete</marquee>
        <p>Focus is a ring; selection is a fill.</p>
      </body>
    </html><
    export function title(container) {
      const name = container.name ?? "untitled";
      if (label.length > MAX_LENGTH) {  }
      return escape(label); /* escape() is deprecated */
    }
    focus-visible
    selected
    selected+container-inactive
    current
    read-only

    Purpose

    The reference rendering of source code: the surface, gutter, caret, current line, selection, bracket match, indent guides, rendered whitespace, fold markers and the seventeen monochrome syntax roles. It is the contract a real editor’s theme API is mapped onto; this component never edits.

    Anatomy

    Root .code-editor; parts .code-editor-<part>: -pre (the <pre>), -line, -ln (line number), -text, -indent, -ws (rendered whitespace), -caret, -sel (selection range), -bracket, -fold, and the gutter fold glyph -fold-gutter. Syntax spans are .code-editor-<role>: -kw keyword, -str string, -cm comment, -num number, -const constant, -fn function, -var variable, -type type, -op operator, -punct punctuation, -prop property, -heading heading, -tag tag, -attr attribute, -esc escape, -invalid invalid, -deprecated deprecated. Line numbers are color.code.line-number on color.code.gutter-bg, separated from the text by a 1px color.code.gutter-rule; indent guides are 1px color.code.indent-guide; rendered whitespace is color.code.whitespace. Every colour is a role variable, so the profile switch on the specimen recolours the sample without touching the markup.

    States

    StateVisualNon-colour channel
    defaultcode on color.code.bg; comments italic; invalid text wavy-underlined in color.code.syntax.invalid; deprecated text struck throughitalic, wavy underline, line-through
    focus-visiblecontainer ring 2px color.interaction.focus.ring-container at −3px; a 1px color.code.caret bar; the caret line filled color.code.current-line across gutter and text; its number in color.code.line-number-activethe ring; the caret bar
    selectedthe range filled color.code.selection-bg; syntax colours keptthe range is announced through the host’s selection; the fill spans line ends
    selected+container-inactivethe same range in color.interaction.selection.inactive-bg with color.interaction.selection.inactive-text; no caret, no ringlightness drop between the two fills
    currentboth characters of the matched pair outlined 1px solid color.code.bracket-matchthe outline is a box, not a colour change
    read-onlygutter drops to color.surface.sunken behind the same line numbers; the gutter rule becomes dotted; no caret is drawnaria-readonly; dotted rule; missing caret

    Precedence: selection is drawn under the text, the current line under the selection, the bracket outline and the caret above everything. The caret never blinks in the reference; a host that blinks it keeps the user’s cursor-blink setting and stops under reduced motion.

    Keyboard

    The host editor owns every binding. The theme states only what it draws in response: the caret and current line while focused, the selection fill for the host’s selection, the outline for the host’s bracket match. The reference markup is one Tab stop and, being read-only, consumes no key. A host that captures Tab for indentation must offer an escape route (Escape, then Tab) and announce it; the theme does not provide one.

    Accessibility

    Syntax colour is decoration: no meaning is carried by colour alone. Invalid text has the wavy underline, deprecated text the line-through, comments the italic. Selection is a fill and focus is a ring, drawn together and never substituted for one another. Every syntax role reaches 4.5:1 on color.code.bg (the lowest is color.code.syntax.property at 4.69:1) and color.text.default reaches 7.02:1 inside the selection fill. Comment, type, keyword and property text drop below 4.5:1 inside color.code.selection-bg (3.81–4.38:1); this is a recorded limitation of the selection value and is not to be fixed by recolouring the tokens locally. Line numbers are metadata people read and use color.text.subtle, not a graphic colour; indent guides, rendered whitespace and the gutter rule are decorative. In forced-colours mode the caret, selection and bracket outline take the system Highlight, and the syntax spans keep their text styles.

    Portability

    A real editor is a host surface: CodeMirror, Monaco, GtkSourceView, KSyntaxHighlighting, an .icls scheme or a terminal editor each expose a theme API, and the port maps the roles here onto that API without touching caret behaviour, keyboard handling or selection semantics. Where a host has no bracket-match outline it may use the bold weight and records the deviation; where a host cannot draw a 1px caret it uses its own caret in color.code.caret. The heritage-ansi and extended profiles change only role values; the mapping does not change.

    Non-examples

    Rainbow syntax in the default profile (the three extension hues are proposed only in extended). A blinking or animated caret in the reference. A selection that recolours the text to white and loses the syntax roles. A current-line highlight brighter than the selection. A bracket match drawn as a background fill, which reads as a selection. Line numbers in the decorative #7d1310. A glow, gradient or rounded corner on the editor box. Removing the host’s focus indicator without drawing the container ring.

    Keys

    KeyAction
    (host)The host editor owns every key; the theme changes no binding, no caret behaviour and no selection model.
    TabReaches the editor as one stop in the reference; whether Tab inserts or moves focus is the host's rule and is announced by the host.
    EscapeIn hosts that trap Tab, Escape must release focus to the next stop; the theme does not provide it.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: diagnostics diff-view terminal

    Stress fixtures: FX-STATE-MATRIX FX-320 FX-ZOOM-200 FX-RM FX-HC FX-LONG FX-RTL

    Diagnostics diagnostics

    • Family: Developer interfaces
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Custom widget: inline: decorated spans inside a read-only textbox presentation; panel: APG listbox with aria-activedescendantAPG pattern
    • specified
    • demonstrated

    Inline problem markers in code (underline patterns, an error line and an overview stripe) and the problems panel that lists them as a listbox, each severity carrying its glyph.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    code.bgcolor.code.bgobserveduse#0c0909Editor background.
    code.textcolor.text.defaultobserveduse#e99499Interface and body text.
    code.line-numbercolor.code.line-numberapproveduse#ad7175Line numbers (5.10:1; replaces the site's #7d1310).
    code.gutter-rulecolor.code.gutter-ruleobserveduse#2b0e0dRule between gutter and text.
    code.selection-bgcolor.code.selection-bgobserveduse#420f0cEditor selection background (muted text stays 4.71:1).
    error.underlinecolor.diagnostic.error.underlineobserveduse#e53935Error wavy underline.
    error.textcolor.diagnostic.error.textobserveduse#f73f35Error message text.
    error.stripecolor.diagnostic.error.stripeobserveduse#e53935Error stripe mark.
    error.line-bgcolor.diagnostic.error.bgobserveduse#2b0e0dError line background.
    warning.underlinecolor.diagnostic.warning.underlineapproveduse#c9973fWarning wavy underline.
    warning.textcolor.diagnostic.warning.textapproveduse#c9973fWarning message text.
    warning.stripecolor.diagnostic.warning.stripeapproveduse#c9973fWarning stripe mark.
    info.underlinecolor.diagnostic.info.underlineapproveduse#7e9ebbInfo dotted underline.
    info.textcolor.diagnostic.info.textapproveduse#7e9ebbInfo message text.
    hint.underlinecolor.diagnostic.hint.underlineobserveduse#ad7175Hint dotted underline.
    hint.textcolor.text.subtleapproveduse#ad7175Metadata, comments, line numbers.
    unused.textcolor.diagnostic.unused.textobserveduse#bd787dUnused symbol, dotted underline.
    deprecated.textcolor.code.syntax.deprecatedobserveduse#ad7175Deprecated symbol: line-through.
    row.textcolor.text.defaultobserveduse#e99499Interface and body text.
    row.locationcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    row.dividercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
    row.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
    row.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    row.bg-selectedcolor.interaction.selection.bgapproveduse#531310Selected row, tab, workspace; D-027 recessed the fill, leaving the 2px indicator and the check to carry selection.
    row.text-selectedcolor.interaction.selection.textobserveduse#f4eeeeText on the selection.
    row.ring-selectedcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
    header.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    status.textcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).
    empty.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    empty.glyphcolor.status.success.textapproveduse#86a46fSuccess text (7.13:1).

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateInline markersProblems panel
    default

    ✕ Language server stopped; markers may be stale.

    import { readFile } from "node:fs/promises";
    const title = document.title;
    function render(frame) {
      const count = frame.children.length;
      escape(title);
      return frmae.title + count;
    }
    render(document.body) == null;

    No problems in title.js

    Problems 1 error ! 1 warning i 1 info · 3 hints

    ✕ Language server stopped; the list may be stale.

    • Error: frmae is not defined title.js:6:10 no-undef
    • Warning: Expected === and instead saw == title.js:8:23 eqeqeq
    • Info: frame.children may be undefined; consider optional chaining title.js:4:17 ts-2532
    • Hint: readFile is declared but never used title.js:1:10 no-unused-vars
    • Hint: escape() is deprecated; use encodeURIComponent() title.js:5:3 deprecation

    No problems

    hover
    focus-visible
    selected
    selected+focus-visible
    error
    empty

    Purpose

    How problems appear on code and in the list that indexes them. Six kinds are distinguished by pattern and glyph as well as colour: error, warning, info, hint, unused and deprecated. The panel is the keyboard route to every marker.

    Anatomy

    Root .diagnostics with the variant class .diagnostics-inline or .diagnostics-panel. Inline parts: .diagnostics-code (the <pre>), -line, -ln, -text, -mark (the stripe cell), and the ranges .diagnostics-error, -warning, -info, -hint, -unused, -deprecated; .diagnostics-line-error marks the row filled color.diagnostic.error.bg; .diagnostics-target is the range that belongs to the selected row. Panel parts: -header, -title, -count, -status, -list, -row, -glyph (with -glyph-error and so on), -message, -loc, -rule, -empty. Patterns: error and warning wavy, info and hint dotted, unused dotted in color.diagnostic.unused.text, deprecated line-through in color.code.syntax.deprecated. Glyphs: error in color.diagnostic.error.text, ! warning in color.diagnostic.warning.text, i info in color.diagnostic.info.text, · hint in color.text.subtle. The stripe mark repeats the glyph in the stripe colour (color.diagnostic.error.stripe, color.diagnostic.warning.stripe).

    States

    StateVisualNon-colour channel
    defaultranges decorated as above on color.code.bg; the error row filled color.diagnostic.error.bg; panel rows on color.surface.default with 1px color.border.divider between themunderline pattern; glyph
    hoverpanel row background → color.interaction.hover.bg; inline ranges unchanged (the hover tooltip is a host surface)cursor: default on rows
    focus-visiblethe active row: 1px dashed color.interaction.focus.ring at −2px; inline box: the container ring 2px color.interaction.focus.ring-container at −3pxthe ring
    selectedrow filled color.interaction.selection.bg, text and glyph color.interaction.selection.text; the matching inline range filled color.code.selection-bg under its underlinearia-selected; the glyph stays; the fill spans the row
    selected+focus-visiblethe selection fill and a 1px dashed ring in color.interaction.focus.ring-containerboth at once
    errorthe provider failed: a role=status line with in color.status.danger.text above the stale rows; the inline stripe shows the same at its topglyph; live announcement
    emptyno problems: rows and stripe marks hidden; ✓ No problems in color.text.muted with the glyph in color.status.success.text; inline decorations removedglyph; the absence of decoration

    Precedence: selected > hover; focus-visible is drawn on top. A selected row recolours its glyph to the on-selection text so the shape, not the hue, carries the severity.

    Keyboard

    The panel follows the APG listbox pattern with aria-activedescendant: the list is one Tab stop, Up and Down move the active row, Home and End jump, type-ahead matches message text, Enter opens the location. Selection follows focus. Inline markers add no keys; next-problem and previous-problem navigation and the hover card are host bindings and host surfaces.

    Accessibility

    Never colour-only: every severity has its underline pattern in code and its glyph in the panel, and the glyph is part of the option’s accessible name (“Error: frmae is not defined, title.js line 6”). The error row background is an addition to the wavy underline, not a replacement. Contrast: color.diagnostic.error.text reaches 4.88:1 on the error row and 5.26:1 on the panel; every underline reaches 3:1 on its actual background including the selected range (the error underline measures 3.81:1 on the code selection fill); color.diagnostic.unused.text reaches 5.81:1 so unused code is still readable. aria-selected and aria-activedescendant carry the state; the status line is role=status, announced once. In forced-colours mode the underline patterns persist because they are text-decoration, not backgrounds.

    Portability

    Underline styles are native in Pango, Qt, JetBrains and most terminal emulators; where wavy is unavailable the port uses a plain underline plus the glyph and records the deviation. Hosts that draw their own overview ruler map the stripe colours; hosts without one omit the stripe and keep the glyphs. The listbox maps to any single-selection list widget.

    Non-examples

    Red-only errors without the glyph or the wavy pattern. A wavy underline for every severity, which leaves the pattern meaningless. Purple or cyan for info and hint. A hover on a panel row that changes only the text colour. A selected row whose glyph keeps its severity colour on the red fill (2.47:1). A panel row with a rounded highlight or a left accent bar instead of the fill. Removing the error line background to “calm” the editor.

    Keys

    KeyAction
    Tab / Shift+TabMoves focus to and from the list as one stop; the active row is restored.
    Down / UpMoves the active row; selection follows focus in this single-select listbox.
    Home / EndFirst or last row.
    EnterOpens the location in the editor and moves focus there.
    Type-aheadJumps to the next row whose message starts with the typed characters.
    (host)Inline markers have no keyboard of their own; navigation between problems (F8-style) is the host's binding.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: code-editor diff-view terminal

    Stress fixtures: FX-STATE-MATRIX FX-320 FX-ZOOM-200 FX-RM FX-HC FX-LONG FX-I18N

    Diff view diff-view

    • Family: Developer interfaces
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Native control: native <table> with a caption; one row per line; collapsed hunks are a <button> with aria-expanded controlling a hidden <tbody>APG pattern
    • specified
    • demonstrated

    Unified and split diffs as native tables; added, removed and modified rows keep their textual gutter marker, word-level changes are underlines, conflicts are double borders.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.code.bgobserveduse#0c0909Editor background.
    root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    root.textcolor.text.defaultobserveduse#e99499Interface and body text.
    line-number.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    line-number.rulecolor.code.gutter-ruleobserveduse#2b0e0dRule between gutter and text.
    row.dividercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
    added.bgcolor.diff.added.bgapproveduse#0f1a0eAdded line background.
    added.guttercolor.diff.added.gutterapproveduse#86a46fAdded gutter mark and +.
    added.emphasiscolor.diff.added.emphasisapproveduse#86a46fWord-level addition: 2px underline.
    removed.bgcolor.diff.removed.bgobserveduse#2b0e0dRemoved line background.
    removed.guttercolor.diff.removed.gutterobserveduse#e53935Removed gutter mark and −.
    removed.emphasiscolor.diff.removed.emphasisobserveduse#e53935Word-level removal: underline and line-through.
    modified.bgcolor.diff.modified.bgapproveduse#1f1a0cModified line background.
    modified.guttercolor.diff.modified.gutterapproveduse#c9973fModified gutter mark and ~.
    hunk.bgcolor.diff.header-bgobserveduse#241010Hunk header background.
    hunk.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    hunk.contextcolor.text.defaultobserveduse#e99499Interface and body text.
    conflict.bordercolor.diff.conflict-borderobserveduse#f73f35Conflict block: double 1px border.
    conflict.markercolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    fold.textcolor.text.linkapproveduse#f73f35Strong red link text, distinct from rose body text and headings; retain the underline.
    fold.bg-hovercolor.interaction.hover.bg-strongobserveduse#630f0dHover on menu items; D-027 moved links to interaction.hover.bg.
    row.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
    row.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    row.bg-selectedcolor.interaction.selection.bgapproveduse#531310Selected row, tab, workspace; D-027 recessed the fill, leaving the 2px indicator and the check to carry selection.
    row.text-selectedcolor.interaction.selection.textobserveduse#f4eeeeText on the selection.
    row.ring-selectedcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateUnifiedSplitWord-levelMerge conflict
    default
    title.js, old against new, unified
    Old lineNew lineChangeText
    @@ -3,7 +3,8 @@ export function title(container)
    33 const name = container.name ?? "untitled";
    4 removed let label = name;
    4+ added let label = `${name} (${container.children.length})`;
    55 if (label.length > MAX_LENGTH) {
    66~ modified label = label.slice(0, MAX_LENGTH) + "…";
    77 }
    title.js, old on the left, new on the right
    Old lineOld changeOld textNew lineNew changeNew text
    @@ -3,7 +3,8 @@ export function title(container)
    3 const name = container.name ?? "untitled"; 3 const name = container.name ?? "untitled";
    4 removed let label = name; 4+ added let label = `${name} (${container.children.length})`;
    5 if (label.length > MAX_LENGTH) { 5 if (label.length > MAX_LENGTH) {
    6~ modified label = label.slice(0, MAX_LENGTH); 6~ modified label = label.slice(0, MAX_LENGTH) + "…";
    7+ added label = label.trimEnd();
    title.js, unified with word-level changes
    Old lineNew lineChangeText
    @@ -4,3 +4,3 @@ export function title(container)
    4 removed let label = name;
    4+ added let label = `${name} (${count})`;
    5 removed if (label.length > 48) {
    5+ added if (label.length > MAX_LENGTH) {
    title.js, merge conflict between main and feature/gaps
    LineChangeText
    3 const name = container.name ?? "untitled";
    4 <<<<<<< HEAD (main)
    5 ours let label = name;
    6 =======
    7+ theirs let label = `${name} (${count})`;
    8 >>>>>>> feature/gaps
    9 if (label.length > MAX_LENGTH) {
    hover
    selected
    focus-visible
    expanded
    collapsed

    Purpose

    How changed text is shown: line rows with a fill and a textual marker, word-level changes as underlines that leave text contrast untouched, hunk headers, collapsible unchanged regions, and merge conflicts in a double border. The +, and ~ markers are content, present in every state and every profile.

    Anatomy

    Root .diff-view (the table) with the variant class .diff-view-unified, -split, -word-level or -conflict. Row classes: .diff-view-row, -row-context, -row-added, -row-removed, -row-modified, -row-hunk, -row-fold, -row-conflict with -row-conflict-start, -row-conflict-mid and -row-conflict-end for the marker lines. Cells: .diff-view-ln, -marker, -text, -fold-cell, and -range for the @@ span; the split variant adds -side-old and -side-new on cells and, on a -row-pair, -cell-removed and -cell-added per side (an empty -cell-blank faces an added line); the conflict variant adds -row-ours and -row-theirs. Word-level spans: .diff-view-word-added (2px underline in color.diff.added.emphasis) and .diff-view-word-removed (underline plus line-through in color.diff.removed.emphasis). The fold button is .diff-view-fold with an inline SVG chevron .diff-view-chevron and two labels, -fold-collapsed and -fold-expanded; the folded rows are a <tbody class="diff-view-folded" hidden>. Line numbers use color.text.muted rather than color.code.line-number because the modified fill would drop the subtle step to 4.45:1.

    States

    StateVisualNon-colour channel
    defaultadded rows color.diff.added.bg with + in color.diff.added.gutter; removed color.diff.removed.bg with in color.diff.removed.gutter; modified color.diff.modified.bg with ~ in color.diff.modified.gutter; hunk rows color.diff.header-bg; conflicts in a 3px double color.diff.conflict-borderthe markers; the double border
    hoverthe row’s number and marker cells → color.interaction.hover.bg; the text cell keeps its fillcursor: default; only on hover-capable pointers
    selectedthe whole row filled color.interaction.selection.bg with color.interaction.selection.text; the marker staysaria-current (or :target for a permalinked line); the marker glyph
    focus-visible1px dashed color.interaction.focus.ring at −2px around the row; on a selected row the ring is color.interaction.focus.ring-containerthe ring
    expandedthe folded <tbody> is shown; the chevron points down; the button reads “Hide 12 unchanged lines”aria-expanded="true"; the rows appear
    collapsedthe folded <tbody> is hidden; the chevron points to the inline end; ”… 12 unchanged lines”aria-expanded="false"; the ellipsis

    Precedence: selected > hover; focus-visible is always drawn. A selected row loses its diff fill but never its marker, which is why the marker is content.

    Keyboard

    A plain table has no row focus. The official web distribution places it in a named, focusable scroll region so keyboard users can inspect wide lines without page overflow. The region uses the canonical container focus ring. Within the table, the fold buttons are the only stops and toggle with Enter or Space, the chevron turning within the motion budget. Hosts that expose the diff as a grid own row navigation and draw the ring on the focused row; the theme adds no binding of its own.

    Accessibility

    The caption names both files. Every changed row carries its marker in a cell of its own, so a screen reader announces + or before the line and a monochrome print keeps the distinction. Word-level changes use text-decoration (underline, or underline and line-through), never a fill, so the row text stays at 7.56:1 or better on every diff fill. The marker measures 4.24:1 on the removed fill: it is bold, sits on its own fill and is a glyph, so it is held to the 3:1 graphics floor and recorded here. Folded hunks use aria-expanded and aria-controls on a real button; the hidden rows are hidden, not visually clipped, so they are not read while collapsed. Conflict markers are the literal <<<<<<<, ======= and >>>>>>> lines in color.text.bright on color.diff.header-bg, inside the double border.

    Portability

    A table with cell backgrounds, borders and text decoration is expressible in every toolkit. Hosts without double borders draw two 1px lines and record it; hosts without line-through keep the underline and the marker. The three extension hues are confined to the diff group here and change with the profile; the markers do not.

    Non-examples

    Red and green fills with no +/ marker. Word-level changes drawn as a bright fill that pushes the text below 4.5:1. A removed line rendered in text.disabled or struck through as a whole. Collapsed hunks that are only visually clipped and still read out. Conflict blocks in purple. Hover that recolours the code text. Round-cornered hunk cards floating on the page. A selected row that drops the marker because “the colour says it”.

    Keys

    KeyAction
    Tab / Shift+TabMoves between the fold buttons and any row the host makes focusable; rows are not stops in a plain table.
    Enter / SpaceOn a fold button toggles the hidden hunk; focus stays on the button.
    Down / UpIn grid hosts, moves the selected row; the theme draws the ring on whichever row the host focuses.
    (host)Next-change and previous-change navigation, staging and comment affordances are host bindings.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: code-editor diagnostics terminal

    Stress fixtures: FX-STATE-MATRIX FX-320 FX-ZOOM-200 FX-RM FX-HC FX-LONG FX-OVERFLOW

    Terminal terminal

    • Family: Developer interfaces
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Native control: native <pre role=log> for a transcript; a plain <pre> with aria-label for the slot grid and the attribute sheetAPG pattern
    • specified
    • demonstrated

    Terminal text on the terminal surface with the sixteen heritage ANSI slots carried exactly, the cursor, the selection and the six text attributes; a transcript, the slot grid and the attributes.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.terminal.bgobserveduse#0c0909Terminal background.
    root.textcolor.terminal.fgobserveduse#e99499Terminal foreground.
    root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    root.ringcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
    cursor.bgcolor.terminal.cursorobserveduse#e99499Terminal cursor.
    cursor.textcolor.terminal.bgobserveduse#0c0909Terminal background.
    selection.bgcolor.terminal.selection-bgobserveduse#911410Terminal selection.
    selection.textcolor.terminal.selection-textobserveduse#f4eeeeTerminal selection text.
    current.bgcolor.code.current-lineobserveduse#1c0a09Current line background.
    prompt.bgcolor.terminal.ansi.4observeduse#8c1212ANSI slot 4, exact heritage value.
    prompt.textcolor.terminal.selection-textobserveduse#f4eeeeTerminal selection text.
    prompt.branch-bgcolor.terminal.ansi.3observeduse#d4868bANSI slot 3, exact heritage value.
    prompt.branch-textcolor.terminal.bgobserveduse#0c0909Terminal background.
    dim.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    inverse.bgcolor.terminal.fgobserveduse#e99499Terminal foreground.
    inverse.textcolor.terminal.bgobserveduse#0c0909Terminal background.
    label.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    fail.glyphcolor.terminal.fgobserveduse#e99499Terminal foreground.
    slot.ansi-0color.terminal.ansi.0observeduse#0c0909ANSI slot 0, exact heritage value.
    slot.ansi-1color.terminal.ansi.1observeduse#c81a1aANSI slot 1, exact heritage value.
    slot.ansi-2color.terminal.ansi.2observeduse#bd787dANSI slot 2, exact heritage value.
    slot.ansi-3color.terminal.ansi.3observeduse#d4868bANSI slot 3, exact heritage value.
    slot.ansi-4color.terminal.ansi.4observeduse#8c1212ANSI slot 4, exact heritage value.
    slot.ansi-5color.terminal.ansi.5observeduse#f73f35ANSI slot 5, exact heritage value.
    slot.ansi-6color.terminal.ansi.6observeduse#9e474aANSI slot 6, exact heritage value.
    slot.ansi-7color.terminal.ansi.7observeduse#ffa2a7ANSI slot 7, exact heritage value.
    slot.ansi-8color.terminal.ansi.8observeduse#7d1310ANSI slot 8, exact heritage value.
    slot.ansi-9color.terminal.ansi.9observeduse#ab1612ANSI slot 9, exact heritage value.
    slot.ansi-10color.terminal.ansi.10observeduse#ad2721ANSI slot 10, exact heritage value.
    slot.ansi-11color.terminal.ansi.11observeduse#b37175ANSI slot 11, exact heritage value.
    slot.ansi-12color.terminal.ansi.12observeduse#871f19ANSI slot 12, exact heritage value.
    slot.ansi-13color.terminal.ansi.13observeduse#e82132ANSI slot 13, exact heritage value.
    slot.ansi-14color.terminal.ansi.14observeduse#e0292fANSI slot 14, exact heritage value.
    slot.ansi-15color.terminal.ansi.15observeduse#a3676bANSI slot 15, exact heritage value.

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateTranscriptANSI gridAttributes
    default
     ~/theme  main  ls -l ports
    total 5
    drwxr-xr-x  2 j3w1 j3w1  4096 Sep  6 09:12 alacritty
    drwx------  2 j3w1 j3w1  4096 Sep  6 09:12 gtk
    -rw-r--r--  1 j3w1 j3w1  1180 Sep  6 09:12 README.md
    -rwxr-xr-x  1 j3w1 j3w1   512 Sep  6 09:12 verify.sh
    lrwxrwxrwx  1 j3w1 j3w1    11 Sep  6 09:12 xresources -> ../tokens/
    -rw-r--r--  1 j3w1 j3w1 20480 Sep  6 09:12 evidence.tar.gz
     ~/theme  main  cat ports/gtk/port.json
    cat: ports/gtk/port.json: No such file or directory
     ~/theme  main  npm run validate
    slot    normal  bold    background
     0           
     1           
     2      normal  bold    
     3      normal  bold    
     4           
     5      normal  bold    
     6           
     7      normal  bold    
     8           
     9           
    10           
    11      normal  bold    
    12           
    13           
    14           
    15           
    ✕ fails 4.5:1 on the terminal background; the extended profile reassigns the slots
    bold       Warm-black surfaces, rose text.
    dim        Warm-black surfaces, rose text.
    italic     Warm-black surfaces, rose text.
    underline  Warm-black surfaces, rose text.
    inverse    Warm-black surfaces, rose text.
    strike     Warm-black surfaces, rose text.
    selected   Warm-black surfaces, rose text.
    focus-visible
    selected
    busy
    current

    Purpose

    The reference for terminal text: the surface, the default foreground, the cursor, the selection, the six attributes and the sixteen slots the workstation froze in Xresources. The slots are the origin of the theme and are carried exactly; what a program does with a slot is that program’s choice, and the theme documents where a choice fails rather than quietly fixing it.

    Anatomy

    Root .terminal (the <pre>) with a variant class .terminal-transcript, .terminal-ansi-grid or .terminal-attributes. Parts .terminal-<part>: -line, -prompt with -prompt-path, -prompt-branch and -prompt-arrow, -cursor, -sel, -label, -fail (the ), and the attributes -bold, -dim, -italic, -underline, -inverse, -strike. Slot classes are .terminal-fg-0.terminal-fg-15 and .terminal-bg-0.terminal-bg-15, each a single role variable color.terminal.ansi.0color.terminal.ansi.15, so the profile switch on the specimen recolours the grid without touching the markup. The foreground is color.terminal.fg on color.terminal.bg; the prompt path segment is color.terminal.selection-text on color.terminal.ansi.4 and the branch segment color.terminal.bg on color.terminal.ansi.3, the two agnoster backgrounds the workstation used.

    States

    StateVisualNon-colour channel
    defaulttext on color.terminal.bg; the cursor cell hollow, a 1px color.terminal.cursor outline; no ringthe hollow cursor
    focus-visiblecontainer ring 2px color.interaction.focus.ring-container at −3px; the cursor solid color.terminal.cursor with color.terminal.bg textthe ring; the cursor fills
    selectedthe run filled color.terminal.selection-bg with color.terminal.selection-text; slot colours inside the run give way to the selection textthe fill spans whole cells; the emulator exposes the selection
    busya command is running: the cursor is a solid static block at the end of the output; the transcript is aria-busyaria-busy; the cursor shape; no blink
    currentthe cursor line filled color.code.current-line across its width; the cursor as in focusthe row fill; the cursor cell

    The cursor never blinks in the reference. A host keeps the user’s own blink setting and stops blinking under reduced motion; the theme never turns it on.

    Keyboard

    The emulator and the shell own every key, including Tab, Escape and the selection modifiers. The reference transcript is a single focus stop that consumes nothing. The theme draws the ring when the host reports focus, the fill when the host reports a selection, and the block cursor where the host puts it.

    Accessibility

    The transcript is role=log so new output is announced politely; the grid and the attribute sheet are plain <pre> elements with a label. The sixteen slots are exact in every profile: slots 2, 3, 5, 7 and 11 reach 4.5:1 on the terminal background; slots 1, 4, 6, 8, 9, 10, 12, 13 and 14 do not (1.86:1–4.43:1), and the grid marks each of them with a after its number so the failure is visible, not implied. Two more are marked on the same evidence: slot 15 measures 4.45:1 and slot 0 is the background itself. The extended overlay reassigns the slots to a semantic sixteen that all reach 4.5:1; the site’s profile control shows the grid under it. The background row is legible only with a foreground the program chooses: with the default foreground only slots 0 and 8 pass, which is why the row is shown and not declared as a contract. Two escape families bypass the slots entirely and are outside the theme: bold-as-bright, which substitutes slots 8–15 for 0–7 and must be off for the slots to hold, and 256-colour or 24-bit sequences, which carry their own values. Attributes are attributes: dim uses color.text.muted (5.81:1) rather than a slot, inverse swaps foreground and background (8.65:1), and bold, italic, underline and strikethrough are text styles a screen reader can expose.

    Portability

    Every emulator with a sixteen-slot palette can hold these values byte for byte; the port’s evidence records whether bold-as-bright is off and whether the cursor and selection keys exist. Programs that pick slot 4 or 12 for directories inherit the documented failure; a port may recommend LS_COLORS or a prompt configuration but never changes the slots to compensate. The cursor shape (block, bar, underline) is the user’s setting; the theme only supplies its colour.

    Non-examples

    Normalising the heritage slots so every one reaches 4.5:1 and calling it heritage-ansi. A blinking cursor in the reference. A cursor that is a glowing bar. Bold rendered as bright, which silently swaps the slots. A purple or cyan slot borrowed from another scheme. Wrapping the transcript at narrow widths and breaking the prompt segments. A selection drawn as a ring instead of a fill. Rounded prompt segments or a gradient prompt.

    Keys

    KeyAction
    (host)The emulator and the shell own every key; the theme changes no binding and no cursor behaviour.
    TabReaches the transcript as one focus stop; inside a live emulator Tab belongs to the shell.
    Shift+Arrows / mouseSelection is the emulator's; the theme draws it in selection-bg and selection-text.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: code-editor diagnostics diff-view

    Stress fixtures: FX-STATE-MATRIX FX-320 FX-ZOOM-200 FX-RM FX-HC FX-LONG FX-OVERFLOW

    Composed specimens

    Settings panel, administrative form, filterable table, i3-inspired window frame; file browser, compact dashboard and form builder later.

    Settings panel settings-panel

    • Family: Composed specimens
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Native control: region landmark named by the h2; a nav landmark for the sections with aria-current on the open one; a form landmark holding native controls in one fieldset; aria-busy on the form while applyingAPG pattern
    • specified
    • demonstrated

    A two-column settings screen composed from the sidebar-nav, fieldset, switch, select, radio-group, text-field, checkbox and button components; below 600px the sidebar becomes a tab strip.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    root.bordercolor.border.defaultobserveduse#531310Decorative border (1.39:1; never the only edge of a control).
    nav.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    nav.bordercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
    nav.textcolor.text.defaultobserveduse#e99499Interface and body text.
    nav.current-textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    nav.current-indicatorcolor.border.selected-indicatorobserveduse#e539352px indicator bar on the selected tab or nav item.
    nav.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
    title.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    lead.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    group.bordercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
    group.legendcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    control.bgcolor.surface.inputapproveduse#000000Form-control fill.
    control.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    control.textcolor.text.defaultobserveduse#e99499Interface and body text.
    control.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    control.checked-bgcolor.action.primary.bgapproveduse#7d1310Primary button fill; D-026 darkened it off color12, which stays fixed as heritage ANSI 12.
    control.checked-glyphcolor.action.primary.textobserveduse#f4eeeePrimary button text (9.28:1).
    invalid.bordercolor.status.danger.borderobserveduse#e53935Danger border, 2px on invalid inputs.
    invalid.messagecolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).
    footer.bordercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
    apply.bgcolor.action.primary.bgapproveduse#7d1310Primary button fill; D-026 darkened it off color12, which stays fixed as heritage ANSI 12.
    apply.textcolor.action.primary.textobserveduse#f4eeeePrimary button text (9.28:1).
    apply.busy-glyphcolor.action.primary.textobserveduse#f4eeeePrimary button text (9.28:1).
    reset.textcolor.action.secondary.textobserveduse#ffa2a7Secondary button text.
    reset.bordercolor.action.secondary.borderobserveduse#a3676bSecondary button border (meets 3:1).

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateTwo columnsNarrow (360px)
    default

    Appearance

    Bar, gaps and labels of the workstation. Changes apply to new windows.

    Bar and gaps
    Hide the bar
    Smart gaps

    Shown only where no window is.

    ✕ Choose a wallpaper.

    Bar labels

    ✕ Choose a language.

    Pixels between windows; the outer gap follows.

    ✕ Between 0 and 64.

    Bar modules

    ✕ Choose at least one module.

    Appearance

    Bar, gaps and labels of the workstation. Changes apply to new windows.

    Bar and gaps
    Hide the bar
    Smart gaps

    Shown only where no window is.

    ✕ Choose a wallpaper.

    Bar labels

    ✕ Choose a language.

    Pixels between windows; the outer gap follows.

    ✕ Between 0 and 64.

    Bar modules

    ✕ Choose at least one module.

    focus-visible
    invalid
    busy

    Purpose

    A settings screen that proves the form components compose without new tokens: a section list on the left, one fieldset of preferences on the right, and a footer of actions. It exists to show the pieces together under every state and at every width, not to prescribe a product.

    Anatomy

    The region landmark; the sidebar-nav with the open section marked by aria-current and the 2px color.border.selected-indicator; the form landmark with its h2 in color.text.bright and lead in color.text.muted; one fieldset with a color.border.divider edge holding two switches (Hide the bar, Smart gaps), a wallpaper select, the bar-label radio-group (中文 / English), the inner-gap text-field with a px suffix and the bar-module checkbox group; a footer rule and the Apply (primary) and Reset (secondary) buttons. Every part is the component’s own markup and classes.

    States

    StateVisualNon-colour channel
    defaultrest tokens of every component on color.surface.default; the open section carries the indicator bararia-current
    focus-visiblethe dashed color.interaction.focus.ring on the control holding focus (shown on the first switch); the other controls stay at restthe ring
    invalidthe inner-gap field takes the 2px color.status.danger.border and shows its ✕ message; the other controls stay at restborder width 1 → 2px; glyph; aria-invalid
    busyApply shows the static ⋯ glyph in color.action.primary.text; the form carries aria-busy; nothing shrinks or animatesglyph; aria-busy; cursor: progress

    The composed components keep their own hover, checked, disabled and read-only treatments; this specimen declares only the states the screen adds to them.

    Keyboard

    Landmarks first: a screen reader’s landmark list offers the region, the navigation and the form by name. Tab walks the section links, then every control in reading order, then Apply and Reset. The radio-group and the select move with arrows inside one stop; the numeric field steps with Up and Down; switches and checkboxes toggle with Space. Nothing traps focus and nothing changes on hover alone.

    Accessibility

    The region is named by the h2 through aria-labelledby; the nav has its own label so two navigation landmarks on a page stay distinguishable; the open section is aria-current="page". The form is named by the same h2 and carries aria-busy="true" while Apply is in progress, so the pending state is announced without a live region. Every control has a programmatic label; every message is linked by aria-describedby. Contrast: title 10.10:1 and lead 5.66:1 on the panel surface, control boundaries 4.33:1, the indicator bar 4.57:1, the danger border 4.69:1 on the input surface.

    Portability

    Three landmarks, native controls and a container query; nothing here needs a script. A host without container queries collapses the sidebar at the 600px viewport breakpoint. The 56rem reference width, the sidebar width and the two-column grid belong to this specimen and are not rules; the specimen proves composition, not a product. Toolkits port each contained component through its own mapping and place them with their native layout.

    Non-examples

    A rounded, shadowed settings card. A Material-style app bar above the form. Toggle switches with rounded pills or animated thumbs. Section links drawn as filled tabs instead of the indicator bar. A red form background to show that something is invalid. Applying while the controls are dimmed with opacity. A spinner replacing the Apply label.

    Keys

    KeyAction
    Tab / Shift+TabWalks the section links, then the controls in reading order, then Apply and Reset; nothing inside is a composite widget, so every control is its own stop.
    Enter / SpaceFollows a section link; toggles a switch or checkbox; opens the select.
    Arrow keysMove within the radio-group and the select's options; step the numeric field.
    EscapeNothing; the panel is not a dialog and nothing is dismissed.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: sidebar-nav fieldset switch select radio-group text-field checkbox button tabs

    Stress fixtures: FX-STATE-MATRIX FX-320 FX-360 FX-ZOOM-200 FX-RM FX-HC FX-I18N FX-RTL FX-DENSITY

    Admin form admin-form

    • Family: Composed specimens
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Native control: region landmark named by the h2; a Breadcrumb nav landmark; the wizard step list with aria-current=step; role=status and role=alert notices; a form landmark of native controls; aria-busy on the form while saving; a disabled fieldset around it while inertAPG pattern
    • specified
    • demonstrated

    A create-or-edit record screen composed from breadcrumbs, a wizard step list, alerts, six field components and a button row; the review step is a table with an Edit button per row.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    root.bordercolor.border.defaultobserveduse#531310Decorative border (1.39:1; never the only edge of a control).
    crumbs.linkcolor.text.linkapproveduse#f73f35Strong red link text, distinct from rose body text and headings; retain the underline.
    crumbs.currentcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    title.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    step.textcolor.text.defaultobserveduse#e99499Interface and body text.
    step.current-textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    step.current-indicatorcolor.border.selected-indicatorobserveduse#e539352px indicator bar on the selected tab or nav item.
    step.completecolor.status.success.textapproveduse#86a46fSuccess text (7.13:1).
    step.invalidcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).
    notice.tintcolor.status.info.tintapproveduse#0f141cInfo background tint.
    notice.bordercolor.status.info.borderapproveduse#7e9ebbInfo border.
    notice.textcolor.status.info.textapproveduse#7e9ebbInfo text (7.08:1).
    summary.tintcolor.status.danger.tintobserveduse#2b0e0dDanger background tint.
    summary.bordercolor.status.danger.borderobserveduse#e53935Danger border, 2px on invalid inputs.
    summary.textcolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).
    field.bgcolor.surface.inputapproveduse#000000Form-control fill.
    field.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    field.textcolor.text.defaultobserveduse#e99499Interface and body text.
    field.labelcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    field.helpcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    field.affixcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    invalid.bordercolor.status.danger.borderobserveduse#e53935Danger border, 2px on invalid inputs.
    invalid.messagecolor.status.danger.textobserveduse#f73f35Danger text (5.40:1).
    disabled.bgcolor.interaction.disabled.bgobserveduse#160b0bDisabled control fill.
    disabled.textcolor.text.disabledapproveduse#8a5559Disabled control text.
    disabled.bordercolor.border.disabledobserveduse#7d1310Disabled control border (exempt).
    review.keycolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    review.header-rulecolor.border.strongobserveduse#9e231fEmphasised 2px rule: sticky headers, section ends.
    review.row-rulecolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
    footer.bordercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
    continue.bgcolor.action.primary.bgapproveduse#7d1310Primary button fill; D-026 darkened it off color12, which stays fixed as heritage ANSI 12.
    continue.textcolor.action.primary.textobserveduse#f4eeeePrimary button text (9.28:1).
    continue.busy-glyphcolor.action.primary.textobserveduse#f4eeeePrimary button text (9.28:1).
    back.textcolor.action.secondary.textobserveduse#ffa2a7Secondary button text.
    back.bordercolor.action.secondary.borderobserveduse#a3676bSecondary button border (meets 3:1).
    draft.textcolor.action.tertiary.textobserveduse#e99499Ghost and icon button text.
    draft.bg-hovercolor.action.tertiary.hover-bgobserveduse#1c0a09Ghost and icon button hover.

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateIdentity stepReview step
    default

    New workstation

    Draft

    Nothing is created until Review; Save draft keeps the record locally.

    Shown in the bar and the records list.

    ✕ A workstation named ws-07 already exists.

    Letters, digits and hyphens; the domain is fixed.

    ✕ ws-07.lan is already registered.

    Decides the default workspace layout.

    ✕ Choose a role.

    Today if left unchanged.

    ✕ Not in the future.

    No file chosen

    One .pub file; ed25519 preferred.

    ✕ Only a .pub file.

    31 / 200

    Plain text; shown on the record page.

    ✕ Over the limit.

    ✕ Confirm before continuing.

    New workstation

    Review

    Edit returns to the step that owns the value; Save creates the record.

    Values entered so far
    Field Value Actions
    Namews-07
    Hostnamews-07.lan
    RoleDevelopment
    Commissioned on2026-09-06
    SSH public keyws-07.pub (ed25519)
    Network10.0.7.12 / 24, DNS from DHCP
    EnabledYes, after saving
    invalid
    busy
    disabled

    Purpose

    A record screen that proves the advanced form components compose with the navigation and feedback components: a trail, a heading, a step list, a notice, a grid of fields and a row of actions, then the same screen at its review step. It exists to show validation, saving and inertness across a whole form, not to prescribe a product.

    Anatomy

    The region landmark; the breadcrumbs (Records / Workstations / New); the h2 in color.text.bright; the wizard step list with the current step on the 2px color.border.selected-indicator; an info alert on color.status.info.tint; the form landmark holding the name and hostname text-fields, the role select, the commissioned-on date-picker, the SSH-key file-input, the notes textarea with its count and the enable checkbox; the footer rule and the Back, Save draft and Continue buttons. The review variant replaces the fields with a table whose row headers are the field names in color.text.muted and whose last column is a tertiary Edit button. Every part is the component’s own markup and classes.

    States

    StateVisualNon-colour channel
    defaultrest tokens of every component on color.surface.default; the current step carries the indicator bar, future steps are disabledaria-current="step"
    invalidthe name and hostname fields take the 2px color.status.danger.border and show their ✕ messages; the current step’s marker becomes ✕; a danger alert on color.status.danger.tint summarising the two fields replaces the notice; the other fields stay at restborder width 1 → 2px; glyphs; aria-invalid; role="alert"
    busyContinue shows the static ⋯ glyph in color.action.primary.text; the form carries aria-busy; nothing shrinks or animatesglyph; aria-busy; cursor: progress
    disabledevery control takes its component’s disabled treatment (color.text.disabled, color.border.disabled, color.interaction.disabled.bg); labels and review keys dim; no hover anywheredisabled on the wrapping fieldset; cursor: not-allowed; never opacity

    The composed components keep their own hover, focus-visible, required, placeholder-shown and read-only treatments; this specimen declares only the states the whole form adds to them.

    Keyboard

    Landmarks first: the region, the Breadcrumb navigation and the form are offered by name. Tab walks the trail, the reachable steps, the fields in reading order and the three buttons; the file-input’s hidden native input is the stop and its visible button label is drawn with the ring. The select and the date field move with arrows inside one stop. In the review variant the Edit buttons are ordinary stops inside the table. Nothing traps focus.

    Accessibility

    The region and the form are both named by the h2. Complete steps read ”, complete” through a visually hidden suffix; future steps are disabled, not hidden. The notice is role="status" and the invalid summary is role="alert", so the summary is announced once on submit while each field’s message stays linked by aria-describedby; aria-invalid is set only after submit. While saving the form carries aria-busy and, once inert, sits inside a disabled fieldset so every control reports its state natively. The review table has a caption, column headers and row headers; each Edit button names its field through a visually hidden suffix. Contrast: notice title 6.5:1 or better on its tint, messages 5.26:1 on the panel surface, the invalid boundary 4.69:1 on the input surface, disabled text 3.24:1 (exempt).

    Portability

    Landmarks, native controls, one container query and three root hooks (data-state-invalid, data-state-busy, data-state-disabled); no script is needed to render any state. Hosts without container queries stack the footer at the 600px viewport breakpoint. The 56rem reference width and the two-column field grid are layout of this specimen and not rules; the specimen proves composition, not a product. Toolkits port each contained component through its own mapping.

    Non-examples

    A rounded card with a drop shadow around the form. A Material stepper with circular numbered badges and a connecting line. A red banner across the whole form instead of the summary alert plus field messages. Fields whose borders glow red. A spinner replacing the Continue label. Saving while the fields fade to half opacity. Placing the actions in a sticky footer bar with a shadow.

    Keys

    KeyAction
    Tab / Shift+TabBreadcrumb links, the reachable step buttons, then every field in reading order, then Back, Save draft and Continue; the file-input's native input is the stop and its button label is drawn with the ring.
    EnterFollows a breadcrumb, activates a step or a button; in a text field submits the form in a host.
    SpaceToggles the checkbox; opens the file chooser from the file-input.
    Arrow keysMove within the select and the date field's segments.
    EscapeNothing; the screen is not a dialog.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: breadcrumbs wizard alert text-field select date-picker file-input textarea checkbox button table

    Stress fixtures: FX-STATE-MATRIX FX-LONG FX-320 FX-360 FX-ZOOM-200 FX-RM FX-HC FX-I18N FX-RTL FX-DENSITY

    Filterable table filterable-table

    • Family: Composed specimens
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Native control: region landmark; a toolbar with roving tabindex holding a search landmark, a menu button, a toggle icon button and a button; a group of removable chips; a grid-less native table with aria-sort, aria-selected rows and a checkbox-role select-all; role=status for the count; a pagination navAPG pattern
    • specified
    • demonstrated

    A list screen composed from a toolbar with search and filter, removable chips, a selectable sortable data-table with status badges, a count and pagination; with empty and loading variants.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    root.bordercolor.border.defaultobserveduse#531310Decorative border (1.39:1; never the only edge of a control).
    toolbar.bgcolor.surface.chromeapproveduse#090707Window chrome, title bars, bars.
    toolbar.bordercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
    toolbar.separatorcolor.border.defaultobserveduse#531310Decorative border (1.39:1; never the only edge of a control).
    search.bgcolor.surface.inputapproveduse#000000Form-control fill.
    search.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    search.textcolor.text.defaultobserveduse#e99499Interface and body text.
    search.placeholdercolor.text.placeholderapproveduse#a3676bPlaceholder text, italic; D-027 darkened it to 4.71:1, just clear of the 4.5:1 floor.
    search.iconcolor.icon.defaultobserveduse#e99499Icons take the text colour (currentColor in CSS).
    filter.textcolor.text.defaultobserveduse#e99499Interface and body text.
    filter.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    new.bgcolor.action.primary.bgapproveduse#7d1310Primary button fill; D-026 darkened it off color12, which stays fixed as heritage ANSI 12.
    new.textcolor.action.primary.textobserveduse#f4eeeePrimary button text (9.28:1).
    chip.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    chip.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    chip.textcolor.text.defaultobserveduse#e99499Interface and body text.
    chip.removecolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    header.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    header.rulecolor.border.strongobserveduse#9e231fEmphasised 2px rule: sticky headers, section ends.
    row.textcolor.text.defaultobserveduse#e99499Interface and body text.
    row.rulecolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
    row.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
    row.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    row.selected-bgcolor.interaction.selection.bgapproveduse#531310Selected row, tab, workspace; D-027 recessed the fill, leaving the 2px indicator and the check to carry selection.
    row.selected-textcolor.interaction.selection.textobserveduse#f4eeeeText on the selection.
    row.ring-on-selectioncolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
    check.bgcolor.surface.inputapproveduse#000000Form-control fill.
    check.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    check.checked-bgcolor.action.primary.bgapproveduse#7d1310Primary button fill; D-026 darkened it off color12, which stays fixed as heritage ANSI 12.
    check.glyphcolor.action.primary.textobserveduse#f4eeeePrimary button text (9.28:1).
    badge.tested-fillcolor.status.success.fillapproveduse#86a46fSuccess fill.
    badge.tested-textcolor.status.success.on-fillapproveduse#0c0909Text on the success fill (7.13:1).
    badge.demonstrated-fillcolor.status.info.fillapproveduse#7e9ebbInfo fill.
    badge.demonstrated-textcolor.status.info.on-fillapproveduse#0c0909Text on the info fill (7.08:1).
    empty.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    empty.headingcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    empty.glyphcolor.icon.decorativeobserveduse#a3676bDecorative glyphs (3:1 as graphics, never text).
    count.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    pagination.textcolor.text.defaultobserveduse#e99499Interface and body text.
    pagination.currentcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    pagination.disabledcolor.text.disabledapproveduse#8a5559Disabled control text.

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateEight of 43Nothing matchesLoading
    default
    priority: R1 maturity: stable
    alertfeedbackR13Demonstrated
    badgedisplayR12Demonstrated
    breadcrumbsnavigationR15Demonstrated
    buttonactionsR16Tested
    carddisplayR15Demonstrated
    checkboxforms-basicR110Tested
    chipdisplayR16Demonstrated
    code-editordeveloperR16Demonstrated
    priority: R1 maturity: stable search: marquee
    No components match.

    No components match

    Three filters are active; none of the 43 components passes all of them.

    priority: R1 maturity: stable
    alertfeedbackR13Demonstrated
    badgedisplayR12Demonstrated
    breadcrumbsnavigationR15Demonstrated
    Loading components
    hover
    focus-visible
    selected
    no-results

    Purpose

    A list screen that proves the navigation, display and feedback components compose around one data-table: find, filter, select, page. It exists to show the states of a whole list screen, including nothing matching and still loading, not to prescribe a product.

    Anatomy

    The region landmark; the toolbar on color.surface.chrome with the search-field, the Filter menu button, the Columns toggle, a separator and the primary New button; a row of removable chips (priority: R1, maturity: stable); the scroller around the data-table, whose Name header carries aria-sort, whose rows carry aria-selected and a checkbox, and whose last column is a status badge (✓ Tested on color.status.success.fill, i Demonstrated on color.status.info.fill); the count in color.text.muted and the compact pagination. The empty variant adds the empty-state block; the loading variant marks the table aria-busy. Every part is the component’s own markup and classes.

    States

    StateVisualNon-colour channel
    defaultrest tokens of every component; Name sorted ascending with its ▲ glyph; Prev disabledaria-sort; the glyph
    hoverthe pointed row takes color.interaction.hover.bg; the toolbar controls and chips keep their own hover on their own pointer events onlycursor
    focus-visiblethe dashed color.interaction.focus.ring on the row holding focus (shown on the third row); the toolbar and chips stay at restthe ring
    selectedtwo rows take color.interaction.selection.bg with color.interaction.selection.text and a checked box; the select-all reports mixed with the – glypharia-selected; ✓ and – glyphs; aria-checked="mixed"
    no-resultsthe body is the “No components match” row, the count reads 0 of 43, the search field’s status line announces it; the chips stay so the cause is visibletext; role="status"

    The composed components keep their own pressed, sorted, disabled, loading and open treatments; this specimen declares only the states the whole screen adds to them.

    Keyboard

    Landmarks first: the region, the toolbar’s search landmark and the pagination navigation are offered by name. The toolbar is one stop with arrow movement between the search field, Filter, Columns and New (the toolbar contract); Escape clears the search. Each chip’s Remove button is its own stop. The table follows the data-table contract: the first row is the stop, arrows move between rows, Space on a row’s checkbox toggles it, Enter on a header sorts. Next is the last stop; a disabled Prev is not focusable.

    Accessibility

    The search field’s visible label is replaced by a visually hidden one so the toolbar stays one row; its status line is visually hidden too and announces “No components match” through role="status". The count is a second status region and changes once per filter. Rows are named by their Name cell through aria-labelledby on the row checkbox; the select-all is a checkbox-role button whose mixed state carries the – glyph. Badges carry their glyphs so status survives without colour. Contrast: toolbar text 8.60:1 on the chrome surface, boundaries 4.42:1, headers 10.10:1, badges 7.08:1 and 7.13:1 on their fills, the ring 7.48:1 on the selection fill.

    Portability

    Native table semantics, a toolbar, a menu button and a status region; the roving tabindex and the menu need the host’s script, every state renders without one from the root hooks data-state-selected and data-state-no-results and the table’s own aria-busy. Hosts without container queries wrap the toolbar at the 600px viewport breakpoint. The 56rem width and the 44rem table minimum are layout of this specimen and not rules; the specimen proves composition, not a product.

    Non-examples

    A rounded search pill with a magnifier inside a shadowed toolbar. Filter chips drawn as pills with a coloured fill per category. Zebra-striped rows. A selected row shown by a coloured left bar and no fill. A blue Material checkbox. A skeleton shimmer while loading. An infinite scroll with no count and no pages.

    Keys

    KeyAction
    Tab / Shift+TabInto the toolbar (the search input is its stop), then each chip's Remove button, then the table (the first row is its stop), then Next.
    Arrow keysInside the toolbar move between the search field, Filter, Columns and New; inside the table move between rows; Home and End reach the first and last row.
    Enter / SpaceOpen the Filter menu; toggle Columns; activate New or a chip's Remove; on a header sort by it; on a row's checkbox toggle its selection.
    EscapeClears a non-empty search; closes the Filter menu and returns focus to its button.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: toolbar search-field menu icon-button button chip data-table badge empty-state pagination

    Stress fixtures: FX-STATE-MATRIX FX-320 FX-360 FX-ZOOM-200 FX-RM FX-HC FX-I18N FX-RTL FX-OVERFLOW FX-DENSITY

    i3 window frame i3-window-frame

    • Family: Composed specimens
    • Maturity: stable
    • Priority: R1
    • Since: 0.1.0
    • Native control: region landmark; a group for the bar holding a tablist of workspaces (aria-selected on the visible one) and a labelled status group; each window a focusable named group, or a tablist and tabpanels in the tabbed variant; the clients keep their own roles (log, textbox)APG pattern
    • specified
    • demonstrated

    The workstation frame; an i3 bar with workspaces and Chinese i3status labels above the terminal and code-editor components as tiled, tabbed or floating windows behind i3 title bars.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.desktopobserveduse#000000Behind every window.
    root.bordercolor.border.defaultobserveduse#531310Decorative border (1.39:1; never the only edge of a control).
    bar.bgcolor.surface.chromeapproveduse#090707Window chrome, title bars, bars.
    bar.textcolor.text.defaultobserveduse#e99499Interface and body text.
    bar.rulecolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
    workspace.textcolor.text.defaultobserveduse#e99499Interface and body text.
    workspace.selected-bgcolor.interaction.selection.bgapproveduse#531310Selected row, tab, workspace; D-027 recessed the fill, leaving the 2px indicator and the check to carry selection.
    workspace.selected-textcolor.interaction.selection.textobserveduse#f4eeeeText on the selection.
    workspace.bg-hovercolor.interaction.hover.bgobserveduse#1c0a09Hover on rows, ghost buttons, list items.
    workspace.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    workspace.ring-on-selectioncolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
    workspace.urgent-bgcolor.status.danger.fillobserveduse#dc282eDanger fill.
    workspace.urgent-textcolor.status.danger.on-fillobserveduse#f9faf9Text on the danger fill (4.58:1).
    status.separatorcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    status.glyphcolor.icon.decorativeobserveduse#a3676bDecorative glyphs (3:1 as graphics, never text).
    clock.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    area.bgcolor.surface.desktopobserveduse#000000Behind every window.
    window.bgcolor.surface.canvasapproveduse#000000Page and terminal background.
    window.bordercolor.border.defaultobserveduse#531310Decorative border (1.39:1; never the only edge of a control).
    window.border-focusedcolor.border.activeobserveduse#e53935Active or focused control border.
    window.ringcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
    title.bgcolor.surface.chromeapproveduse#090707Window chrome, title bars, bars.
    title.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    title.bg-focusedcolor.surface.chrome-altobserveduse#1c0a09Alternate chrome.
    title.text-focusedcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    tab.indicatorcolor.border.selected-indicatorobserveduse#e539352px indicator bar on the selected tab or nav item.
    tab.indicator-inactivecolor.border.selected-indicator-inactiveobserveduse#9e231fIndicator bar when the container is not focused.
    floating.bordercolor.border.overlayproposeduse-and-reportD-008#e53935Every floating layer's 1px border.
    floating.shadowshadow.floatingobserveduse0px 6px 22px 0px rgb(0 0 0 / 55%)The only shadow: the i3 floating window.
    terminal.bgcolor.terminal.bgobserveduse#0c0909Terminal background.
    terminal.textcolor.terminal.fgobserveduse#e99499Terminal foreground.
    editor.bgcolor.code.bgobserveduse#0c0909Editor background.

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateTiledTabbedFloating
    default
    处理器 12% 内存储器 3.1G 局域网 up 电池 87%
    ~/theme — zsh
     ~/theme  main  ls -l ports
    total 5
    drwxr-xr-x  2 j3w1 j3w1  4096 Sep  6 09:12 alacritty
    drwx------  2 j3w1 j3w1  4096 Sep  6 09:12 gtk
    -rw-r--r--  1 j3w1 j3w1  1180 Sep  6 09:12 README.md
    -rwxr-xr-x  1 j3w1 j3w1   512 Sep  6 09:12 verify.sh
    lrwxrwxrwx  1 j3w1 j3w1    11 Sep  6 09:12 xresources -> ../tokens/
    -rw-r--r--  1 j3w1 j3w1 20480 Sep  6 09:12 evidence.tar.gz
     ~/theme  main  cat ports/gtk/port.json
    cat: ports/gtk/port.json: No such file or directory
     ~/theme  main  npm run validate
    title.js — editor
    // Compose the window title of the focused container.
    import { Container } from "./tree.js";
    const MAX_LENGTH = 48;
    export function title(container) {
      const name = container.name ?? "untitled";
      let label = `${name} (${container.children.length})`;
      if (label.length > MAX_LENGTH) {
        label = label.slice(0, MAX_LENGTH) + "…";
      }
      return escape(label); /* escape() is deprecated */
    }
    const broken = 0x1G;
    处理器 12% 内存储器 3.1G 局域网 up 电池 87%
     ~/theme  main  ls -l ports
    total 5
    drwxr-xr-x  2 j3w1 j3w1  4096 Sep  6 09:12 alacritty
    drwx------  2 j3w1 j3w1  4096 Sep  6 09:12 gtk
    -rw-r--r--  1 j3w1 j3w1  1180 Sep  6 09:12 README.md
    -rwxr-xr-x  1 j3w1 j3w1   512 Sep  6 09:12 verify.sh
    lrwxrwxrwx  1 j3w1 j3w1    11 Sep  6 09:12 xresources -> ../tokens/
    -rw-r--r--  1 j3w1 j3w1 20480 Sep  6 09:12 evidence.tar.gz
     ~/theme  main  cat ports/gtk/port.json
    cat: ports/gtk/port.json: No such file or directory
     ~/theme  main  npm run validate
    处理器 12% 内存储器 3.1G 局域网 up 电池 87%
    ~/theme — zsh
     ~/theme  main  ls -l ports
    total 5
    drwxr-xr-x  2 j3w1 j3w1  4096 Sep  6 09:12 alacritty
    drwx------  2 j3w1 j3w1  4096 Sep  6 09:12 gtk
    -rw-r--r--  1 j3w1 j3w1  1180 Sep  6 09:12 README.md
    -rwxr-xr-x  1 j3w1 j3w1   512 Sep  6 09:12 verify.sh
    lrwxrwxrwx  1 j3w1 j3w1    11 Sep  6 09:12 xresources -> ../tokens/
    -rw-r--r--  1 j3w1 j3w1 20480 Sep  6 09:12 evidence.tar.gz
     ~/theme  main  cat ports/gtk/port.json
    cat: ports/gtk/port.json: No such file or directory
     ~/theme  main  npm run validate
    title.js — editor
    // Compose the window title of the focused container.
    import { Container } from "./tree.js";
    const MAX_LENGTH = 48;
    export function title(container) {
      const name = container.name ?? "untitled";
      let label = `${name} (${container.children.length})`;
      if (label.length > MAX_LENGTH) {
        label = label.slice(0, MAX_LENGTH) + "…";
      }
      return escape(label); /* escape() is deprecated */
    }
    const broken = 0x1G;
    focus-visible
    selected
    container-inactive
    error

    Purpose

    The frame the palette was tuned in: an i3 bar, tiled windows with 1px pixel borders, 14/−2 gaps, a tabbed container and one floating window. It proves that the terminal and code-editor components sit inside window chrome drawn from the same roles, and it records the workstation’s geometry as reference metrics. It is a specimen of composition, not a desktop.

    Anatomy

    The region on color.surface.desktop; the 28px bar on color.surface.chrome with the workspace tablist (the visible workspace on color.interaction.selection.bg) and the i3status group in Chinese with its clock in color.text.bright; the workspace grid with the reference gaps; each window a focusable group behind a 1px color.border.default frame, color.border.active when focused, with a 23px title bar in color.text.muted on color.surface.chrome that turns color.text.bright on color.surface.chrome-alt when focused; the terminal or code-editor as the client with its own boundary given up to the frame. Tabbed: the titles form a tablist whose visible tab carries the 2px color.border.selected-indicator. Floating: the editor sits above the terminal behind color.border.overlay with shadow.floating, the only shadow in the theme.

    States

    StateVisualNon-colour channel
    defaultthe terminal window focused: color.border.active frame and the bright title; the editor at rest; workspace 1 filledthe title text; aria-selected
    focus-visiblethe 2px color.interaction.focus.ring-container ring at −3px inside the focused window or container; the client draws no second ringthe ring
    selectedworkspace 2 takes the selection fill with color.interaction.selection.text; workspace 1 drops to restaria-selected
    container-inactiveno window has focus: every frame color.border.default, every title color.text.muted on color.surface.chrome, the tab indicator color.border.selected-indicator-inactive, no caretlightness drop; no caret
    errorworkspace 3 is urgent: color.status.danger.fill with color.status.danger.on-fill and a trailing !the ! mark; “urgent” read to assistive technology

    The clients keep their own states (the terminal’s busy cursor, the editor’s selection and read-only gutter); this specimen declares only the states the frame adds around them.

    Keyboard

    The workspace tablist is one stop with arrow movement; Enter or Space shows a workspace. Each window is a focusable group so the frame itself can hold focus, as i3 focuses a container; Tab then enters the client, whose own contract applies (the terminal log, the read-only editor textbox). In the tabbed variant the tab list is one stop and only the visible panel’s client follows. Mod+h j k l and Mod+1..9 belong to the window manager and are documented, not reimplemented. Nothing traps focus.

    Accessibility

    The region names its workspace and layout. The bar is a group holding a named tablist and a status group in lang="zh", whose Nerd Font glyphs are aria-hidden so only the labels are read. Every window is a named group; the focused one says so in its name and the floating one too. Urgency carries the ! mark and a visually hidden “urgent”. Contrast: workspace names 8.60:1 and the clock 10.31:1 on the bar, focused titles 10.01:1, rest titles 5.77:1, the focused frame 4.97:1 and the ring 10.37:1 on the window surface, the urgent fill 4.12:1 against the bar with 4.58:1 text on it.

    Portability

    Groups, a tablist and the clients’ own roles; every state renders from the root hooks without a script. The i3 geometry — bar 28px, titles 23px, gaps 14px inner and −2px outer — is reproduced with private variables on this specimen’s root only. Those numbers are reference metrics of the workstation, recorded so a port of the i3 configuration matches it; they are not tokens and not a rule for any other application, which keeps its own window manager, bar and gaps. The specimen proves composition, not a product; only i3 and sway ports draw this frame.

    Non-examples

    A window with rounded corners or a title bar gradient. A focused window that glows or blurs its neighbours. A shadow under a tiled window; the only shadow is the floating one. Gaps of 14/−2 forced into an unrelated application’s layout. A workspace indicator drawn as a red underline instead of the selection fill. Traffic-light close buttons in the title bar. A translucent bar.

    Keys

    KeyAction
    Tab / Shift+TabThe workspace tablist (its selected tab is the stop), then each window group, then the client inside it; in the tabbed variant the tab list, then the visible panel's client.
    Arrow keysMove between workspaces in the bar and between tabs in a tabbed container; inside a client the client's own contract applies.
    Enter / SpaceShows the workspace or tab under focus.
    Mod+h j k l, Mod+1..9The window manager's own bindings move focus and switch workspaces on the workstation; the specimen documents them and does not reimplement them.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: terminal code-editor tabs

    Stress fixtures: FX-STATE-MATRIX FX-320 FX-360 FX-ZOOM-200 FX-RM FX-HC FX-I18N FX-RTL FX-DENSITY

    File browser file-browser

    • Family: Composed specimens
    • Maturity: stable
    • Priority: R2
    • Since: 1.0.0
    • Native control: Tree composition, native search input and table
    • specified
    • demonstrated

    Location navigation and a filterable native file table with bounded host actions.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    root.textcolor.text.defaultobserveduse#e99499Interface and body text.
    root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    heading.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    secondary.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    control.bgcolor.surface.inputapproveduse#000000Form-control fill.
    control.focuscolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    dependency.role-border-width-defaultborder.width.defaultobserveduse1pxEvery border is 1px.
    dependency.role-border-width-emphasisborder.width.emphasisobserveduse2pxSelected indicator, sticky header rule, invalid border.
    dependency.role-color-border-dividercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
    dependency.role-color-border-selected-indicatorcolor.border.selected-indicatorobserveduse#e539352px indicator bar on the selected tab or nav item.
    dependency.role-density-comfortable-control-heightdensity.comfortable.control-heightobserveduse32px
    dependency.role-density-compact-control-heightdensity.compact.control-heightobserveduse24px
    dependency.role-radius-noneradius.noneobserveduse0pxThe only radius. Nothing is rounded.
    dependency.role-space-12space.12observeduse12px
    dependency.role-space-16space.16observeduse16px
    dependency.role-space-2space.2observeduse2px
    dependency.role-space-8space.8observeduse8px

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateDefault
    default
    • All files
    • Source
    Local file examples
    NameKindSize
    Vue component4 KB
    Documentation2 KB

    2 files

    selected
    empty
    no-results
    focus-visible

    Purpose

    Compose hierarchical location navigation with a filterable file table. Opening an entry emits its stable identity. The caller owns file access, upload, deletion and permissions. The supplied names and sizes are synthetic local examples.

    Anatomy

    • locations: Tree navigation selects a location filter.
    • query: Labelled native search filters visible rows.
    • table: Native rows show names, kinds and sizes with explicit Open actions.

    States

    StatePresentationNon-colour channel
    defaultLocations and native file rows.Explicit names, kinds and sizes.
    selectedSelected location follows the tree contract.aria-selected plus location filter.
    emptyNo file rows.Explicit zero-files text.
    no-resultsFiltered rows are hidden.Matching count and retained search query.
    focus-visibleDashed control outline.Native focus and tree roving focus.

    Keyboard

    • Tab / Shift+Tab: Move among tree navigation, search and row actions.
    • Arrow keys: Use the tree contract inside navigation.
    • Enter / Space: Request opening the chosen file through an event.

    Accessibility

    Keep the complete nested tree behavior and semantic table headers. Filtering does not move focus. Announce counts, and keep the search field available after zero results. File actions must not imply access beyond the host’s actual permissions.

    Portability

    Wrap labels and actions without changing source order. Use logical spacing in RTL. Preserve native target sizes at both densities; only bounded data regions may scroll horizontally. Use equivalent native semantics and approved roles; record any unsupported behavior as a mapping deviation. The host owns application data, persistence, permissions and services.

    Non-examples

    Unlabelled controls, color-only status, drag-only operations, hidden required instructions, stolen focus or an invented service success.

    Keys

    KeyAction
    Tab / Shift+TabMove among tree navigation, search and row actions.
    Arrow keysUse the tree contract inside navigation.
    Enter / SpaceRequest opening the chosen file through an event.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: tree table search-field

    Stress fixtures: FX-320 FX-360 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

    Compact dashboard compact-dashboard

    • Family: Composed specimens
    • Maturity: stable
    • Priority: R2
    • Since: 1.0.0
    • Native control: Native sections, description lists, chart and table composition
    • specified
    • demonstrated

    Named operational metrics, a complete chart and an actionable native records table.

    Report an issue with this component

    Tokens

    PartRoleValueUse
    root.bgcolor.surface.defaultapproveduse#100c0cPanels and cards.
    root.textcolor.text.defaultobserveduse#e99499Interface and body text.
    root.bordercolor.border.controlproposeduse-and-reportD-007#a3676bForm-control boundary (4.45:1, meets the 3:1 non-text minimum).
    heading.textcolor.text.brightobserveduse#ffa2a7Headings and emphasis. Links use color.text.link.
    secondary.textcolor.text.mutedobserveduse#bd787dSecondary text; the darkest colour permitted for chrome text.
    control.bgcolor.surface.inputapproveduse#000000Form-control fill.
    control.focuscolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
    dependency.role-border-width-defaultborder.width.defaultobserveduse1pxEvery border is 1px.
    dependency.role-color-border-dividercolor.border.dividerproposeduse-and-reportD-008#2b0e0dHairline between rows and sections.
    dependency.role-color-surface-chromecolor.surface.chromeapproveduse#090707Window chrome, title bars, bars.
    dependency.role-density-comfortable-control-heightdensity.comfortable.control-heightobserveduse32px
    dependency.role-density-compact-control-heightdensity.compact.control-heightobserveduse24px
    dependency.role-font-size-h2font.size.h2observeduse16px
    dependency.role-radius-noneradius.noneobserveduse0pxThe only radius. Nothing is rounded.
    dependency.role-space-12space.12observeduse12px
    dependency.role-space-2space.2observeduse2px
    dependency.role-space-8space.8observeduse8px

    State matrix

    Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

    StateDefault
    default

    Delivery overview

    Synthetic local fixture

    Active projects
    24
    Ready for review
    7
    Components used
    148
    Completed tasks
    Task data
    WeekTasks
    Week 124
    Week 236
    Projects
    ProjectStatus
    ✓ Ready
    ◌ In progress
    loading
    empty
    focus-visible

    Purpose

    Compose a small operational overview from named metrics, a complete chart and a records table. All figures are caller data. Synthetic fixtures are labelled; the component does not fetch data or infer business health.

    Anatomy

    • metrics: Terms and values pair each metric name with its number.
    • activity: Chart retains its full textual data table.
    • records: Native rows include named actions and explicit status words.

    States

    StatePresentationNon-colour channel
    defaultSquare metric panels and readable tables.Metric names, exact values and status text.
    loadingBusy boundary with existing content retained.aria-busy and host-provided loading status.
    emptyExplicit absence of records.Empty message; metric zero differs from unknown.
    focus-visibleDashed action outline.Native keyboard focus.

    Keyboard

    • Tab / Shift+Tab: Visit record actions and any scrollable data region.
    • Enter / Space: Request the chosen record through an event.

    Accessibility

    Keep metrics as term/value pairs, tables labelled and all chart data visible. Do not use a color-only health score. Busy status does not manufacture a completed refresh. The host decides how unknown metrics are described, rather than silently displaying zero.

    Portability

    Wrap labels and actions without changing source order. Use logical spacing in RTL. Preserve native target sizes at both densities; only bounded data regions may scroll horizontally. Use equivalent native semantics and approved roles; record any unsupported behavior as a mapping deviation. The host owns application data, persistence, permissions and services.

    Non-examples

    Unlabelled controls, color-only status, drag-only operations, hidden required instructions, stolen focus or an invented service success.

    Keys

    KeyAction
    Tab / Shift+TabVisit record actions and any scrollable data region.
    Enter / SpaceRequest the chosen record through an event.

    For agents

    Component JSON ·Implementation brief ·Build a task kit ·

    Related: chart description-list table

    Stress fixtures: FX-320 FX-360 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX

    Stress fixtures and non-examples

    Stress fixtures

    Every fixture id below is referenced from component specifications; a component that lists a fixture must survive it.

    FX-LONG Long text

    A 120-character label, a 40-character unbroken token, three lines of help. Labels wrap; the box never grows past its container; nothing is clipped.

    The value Benachrichtigungseinstellungen_v2_final_final must not widen the box. Help text runs to three lines on a narrow frame and stays readable; it wraps at the container edge rather than clipping.

    FX-320 320 and 360 pixel frames

    The reflow floor (WCAG 1.4.10). No horizontal scrolling inside the frame; the label stacks above; help and message wrap.

    320px

    Shown on your profile.

    360px

    Shown on your profile.

    FX-I18N English, Spanish, Chinese, Arabic

    Not translations of the site: fixtures for width, CJK fallback faces and mirrored affixes. The Arabic block sets dir="rtl".

    Choose how the workstation notifies you.

    Elige cómo te avisa la estación de trabajo.

    选择工作站如何通知您。

    اختر كيف تنبّهك محطة العمل.

    FX-RTL Right-to-left

    Logical properties mirror prefixes, suffixes, indicators and stepper order without a second stylesheet.

    المضيف فقط؛ المسار ثابت.

    FX-RM Reduced motion

    Under prefers-reduced-motion every duration is 0.01ms; toasts and dialogs appear in place, loading glyphs are static. The page's own browser test emulates it.

    FX-HC Forced colours

    Under forced-colors: active the rings use Highlight and borders survive because they are real borders. Emulate it in the browser's rendering settings.

    FX-TOUCH Coarse pointer

    No hover styles; targets at least 24×24 CSS pixels with 4px between them in compact density.

    FX-DENSITY Compact and comfortable

    The same control at both densities, side by side. Both meet the 24×24 target minimum.

    compact

    24px control.

    comfortable

    32px control.

    FX-OVERFLOW Overflow

    Fifty rows and twelve columns scroll inside their own container; the page never scrolls horizontally.

    #col1col2col3col4col5col6col7col8col9col10col11col12
    1123456789101112
    224681012141618202224
    3369121518212427303336
    44812162024283236404448
    551015202530354045505560
    661218243036424854606672
    771421283542495663707784
    881624324048566472808896
    9918273645546372819099108
    10102030405060708090100110120
    11112233445566778899110121132
    121224364860728496108120132144
    1313263952657891104117130143156
    1414284256708498112126140154168
    15153045607590105120135150165180
    16163248648096112128144160176192
    171734516885102119136153170187204
    181836547290108126144162180198216
    191938577695114133152171190209228
    2020406080100120140160180200220240
    2121426384105126147168189210231252
    2222446688110132154176198220242264
    2323466992115138161184207230253276
    2424487296120144168192216240264288
    25255075100125150175200225250275300
    26265278104130156182208234260286312
    27275481108135162189216243270297324
    28285684112140168196224252280308336
    29295887116145174203232261290319348
    30306090120150180210240270300330360
    31316293124155186217248279310341372
    32326496128160192224256288320352384
    33336699132165198231264297330363396
    343468102136170204238272306340374408
    353570105140175210245280315350385420
    363672108144180216252288324360396432
    373774111148185222259296333370407444
    383876114152190228266304342380418456
    393978117156195234273312351390429468
    404080120160200240280320360400440480
    414182123164205246287328369410451492
    424284126168210252294336378420462504
    434386129172215258301344387430473516
    444488132176220264308352396440484528
    454590135180225270315360405450495540
    464692138184230276322368414460506552
    474794141188235282329376423470517564
    484896144192240288336384432480528576
    494998147196245294343392441490539588
    5050100150200250300350400450500550600

    Non-examples

    Sixteen misreadings of the theme, drawn on purpose. The pictures are decorative; the rule under each one is normative.

    Save

    Pills

    Radius is 0 everywhere; buttons, chips, inputs and badges are square.

    content behind

    Glass and blur

    Surfaces are opaque warm blacks; no backdrop-filter, no translucent cards over content.

    Continue

    Gradients

    Fills are flat tokens; no red-to-black buttons, gradient headers or gradient borders.

    focused

    Glow instead of the ring

    Focus is a 1px dashed ring at −2px; never a box-shadow halo, and elevation is a border, not a drop shadow.

    red panelred text

    Red on everything

    Red marks interaction only: focus, selection, active borders, primary actions. Panels, body text and sidebars stay warm black and rose.

    Label floating up+

    Material redesign

    No floating action buttons, ripples, floating labels or tonal elevation stacks. Modern means precise, not Material.

    Settingsdark on white

    Light mode

    There is no light profile. White panels with dark text are a different theme.

    const x = "s";fn(42)

    Rainbow syntax in default

    Syntax stays monochrome rose/red in the default profile; only the proposed extended overlay adds three hues, and never purple, cyan or magenta.

    Colour-only status

    Every status carries a glyph (✕ ! ✓ i ·) and a pattern; a coloured dot alone tells a colour-blind reader nothing.

    DashboardOverview and settings

    Sans-serif chrome

    One monospace family for chrome, reading and code; Inter or system-ui is another identity.

    12 // a comment13 return x;

    #7d1310 as text

    The site's --inactive measures 1.86:1 on the canvas. It is a disabled border and rendered whitespace, never line numbers, comments or any text.

    "focused" rowselected + invisible ring

    Focus drawn as selection

    Focus is a ring and selection is a fill. A focused row painted #531310, or a #e53935 ring on a #531310 row (2.15:1), hides where the keyboard is.

    assets/config/

    Heritage ANSI as UI text

    Slot 4 (#8c1212) is a terminal colour at 2.09:1. Directory names in a file browser use the text roles, not the historical slots.

    JW

    Circular avatars and spinners

    A zero-radius system has square avatars and no circular spinner; loading is a static ⋯ glyph.

    where is the box?

    Hairline as the only edge

    #531310 is decorative (1.39:1). A form control needs color.border.control (#a3676b, 4.45:1) as its boundary.

    Submit

    Disabled by opacity

    opacity: .5 leaks the background and breaks contrast accounting; disabled uses text.disabled, border.disabled and the disabled fill.

    Form composition and recovery

    A local reference workflow preserves values through validation, review and an explicitly simulated save.

    Scope

    The validation and recovery pattern composes admin-form, text-field, textarea, select, checkbox, alert, button and table. It is a reference composition under proposed D-020, not a new approved profile or a production persistence system. Existing component rules remain normative. Its compact JSON contract records the constituent component content digests, fields, fixtures, transitions and limits.

    Interaction

    Enter values and submit to validate. Errors appear together in a focused summary with links to the affected fields. Preserve every entered value, including unrelated notes and choices. Correct fields and submit again to review. Editing does not announce errors on each keystroke or silently remove the last submitted error summary. Review offers an explicit return to editing.

    Confirming the review enters busy, with the form controls disabled and an explicit pending message. The separate Complete simulation action produces success. A submit click alone is never success. Busy, disabled, invalid and success have distinct meaning. Reset clears in-memory values and errors.

    The example reserves ws-07 for Name and Hostname and requires a lowercase hostname made of letters, digits and hyphen-separated segments. These are named local fixtures from admin-form, not server uniqueness checks. No request, account, storage or database is involved. The page retains static normal, invalid, busy and success examples without JavaScript.

    Evidence and limits

    Automated protocols cover keyboard submission, summary navigation, correction, preservation, review, busy and success, along with narrow layout and no-JS content. Test implementation is not an execution pass. Read the published verification report for actual runs; no manual screen-reader pass is claimed. The submit-time feedback follows the GOV.UK validation pattern.

    Figma Variables bridge

    A one-way, pinned Variables API bridge with explicit diffs and external ownership receipts.

    Supported mapping

    This independently authored bridge maps sRGB colors to COLOR variables and scalar px spacing/radius to FLOAT variables. Aliases remain native variable aliases. Token paths are stable identities; slash-separated names live in the j3w1/theme/default/v1 collection. Alias primitives are dependencies with empty property scopes, not newly approved application roles. Semantic scopes are specific to text, fills, strokes, gaps and corner radius. Eligibility and pending decision IDs travel with each definition.

    Only the approved default profile is imported. Heritage and proposed profiles are reported, never converted into extra modes. Typography, shadows, composite borders and other unsupported types are reported without flattening. Figma does not natively import this JSON: the adapter uses the Variables Plugin API. Install the font families named in the pinned typography tokens independently; this bridge neither imports fonts nor distributes binaries.

    Generate a pinned payload

    In a verified checkout, run:

    node scripts/figma-bridge.mjs --ref FULL_COMMIT_OR_RELEASE_TAG > payload.json

    The default sample selects color.surface.default, color.text.default, space.4 and radius.none, plus their two alias dependencies. Use --roles with an explicit comma-separated role selection to change the sample. The command reads Git objects at the resolved full revision and records source and payload digests, mapping version, unsupported items and excluded profiles. It never reads moving branch bytes or substitutes the working tree.

    Reviewed import route

    Use the Figma connector’s use_figma Variables API route in a new design draft or an existing collection for which you retain the current receipt. Read the connector’s current skill/API instructions first. The actual adapter is exports/figma/importer.mjs; pin its download to the same reviewed delivery revision as these instructions.

    Load the module’s function in the connector script (remove only the ES-module export keyword), then return the awaited call:

    return await importFigmaVariables(figma, {
      payload, receipt: null, documentKey, action: "dry-run"
    });

    Supply the locally generated payload and exact target file key as explicit inputs. Inspect the returned diff. Dry-run performs reads only. Invoke again with action: "apply" only for the reviewed change. Preserve the entire returned receipt outside the document and repository. Subsequent dry-runs and applies must supply that receipt and the same document key. An exact re-import is a no-op. Updates show before/after definitions; omitted owned variables are retained and reported, never silently removed. These receipts are trusted local ownership records, not importable third-party configuration.

    This reviewed route is bounded to eight variables including dependencies per namespace, one collection and one default mode, fitting an incremental connector operation. Larger payloads fail before mutation. The connector’s atomic script execution is required for apply/rollback; this module is not a standalone plugin transaction manager. No team publishing permission or paid plan capability is assumed. Permission, mode and API errors remain failures.

    Rollback and conflicts

    Use action: "rollback" with the current receipt to undo its most recent apply. Existing variables regain their exact recorded values and metadata; new variables are removed in reverse dependency order. The result returns the previous receipt. A newly created collection is removed only when it contains no unrelated variables. Preserve the returned previous receipt for another rollback or subsequent import.

    Rollback also refuses to remove a variable referenced by a retained variable in any local collection. Inspect any canvas bindings you added after import before requesting rollback; this adapter does not audit every canvas node.

    Before any mutation the adapter compares all owned IDs, values, descriptions, scopes, collection identity and mode against the receipt. Missing, detached or manually edited variables stop apply and rollback. It never adopts a matching name without a receipt. Resolve the conflict deliberately in Figma or create a separate draft; do not discard ownership records to force an overwrite.

    Actual verification status

    A real six-variable sample was imported through the connector in a new design draft with Starter/Full access and Plugin API 1.0.0. Actual alias IDs matched; spacing and radius matched exactly. Color channels matched the exact float32 representation of the source channels, with no tolerance. Exact re-import changed no IDs. A separately previewed spacing addition was applied and rolled back. A deliberate manual edit was rejected without overwriting the edit, then the test edit was explicitly restored. Private receipts remain outside public artifacts. The issue evidence records the exact candidate and source revision.

    Source protocols also cover detached IDs, value updates, initial rollback, unrelated variables, invalid payloads and extra modes using an explicit API fixture. Those are fixture results, not additional account capability claims. No full component kit, native port, library publication, manual design review, or automatic Figma-to-token synchronization is claimed. D-019 remains proposed.

    Accessibility

    Contrast targets, focus and keyboard contracts, reduced motion, forced colours, and what an automated pass does and does not prove.

    What is claimed

    WCAG 2.2 criteria are used as measurable design targets for the roles this theme defines. A green contrast report and a clean automated scan of the site are evidence that the specified colours and the reference markup meet those targets. They are not a conformance claim for any application that adopts the theme: keyboard operation, focus management, labels, reflow and manual review remain the consumer’s responsibility, and the theme’s own limitations are listed at the end of this document.

    Contrast

    • Ordinary text: at least 4.5:1 against the actual background of the state it is in, measured on resolved sRGB values after compositing translucent colours.
    • Large text (18.66px bold or 24px regular and above): at least 3:1.
    • Control boundaries, focus rings, meaningful icons and chart marks: at least 3:1 (WCAG 1.4.11).
    • Disabled text is exempt under WCAG 1.4.3 but must still reach 3:1 by house policy (text.disabled #8a5559, 3.52:1 on the true-black canvas).
    • Never round a value into a pass. The report keeps the unrounded ratio and displays two decimals; 4.4996 reads 4.50 and fails.
    • Heritage values that fail (#a3676b as text, #7d1310 anywhere as text) are flagged $deprecated in the heritage-ansi profile and are never presented as ordinary passes.

    exports/contrast.md lists every declared pair: the global pairs in spec/contrast.json and every stateTokens and contrast[] entry of every component. Waived pairs carry their reason; a waiver is only valid for decorative graphics that are never the sole boundary of a control.

    Focus

    Focus is never lost and never invisible. Controls and rows show focus.ring (1px dashed #e53935, offset −2px); focusable containers show focus.ring-container (2px solid #ffa2a7, offset −3px). On fills, use the component’s explicit ring role (D-015): primary and checked controls use focus.ring-container where declared; destructive fills use their on-fill text role. Colour mapping does not change ring geometry. :focus without :focus-visible draws nothing, which keeps pointer clicks quiet without hiding keyboard focus. A component that removes a host’s default indicator must draw this one. State matrices on the site render every declared combination including selected+focus-visible and invalid+focus-visible, because those are where rings disappear in practice.

    Keyboard

    Native controls keep native keyboard behaviour. Custom widgets follow the WAI ARIA Authoring Practices pattern cited in their frontmatter (aria.apg): roving tabindex in toolbars, tabs, trees and listboxes; aria-activedescendant in comboboxes; focus trapping and Escape in dialogs and drawers; arrow keys in radio groups and menus. Positive tabindex is banned. Every icon-only control has an accessible name. The site’s own controls (search, filters, inspector, copy) are reachable and operable with the keyboard, and the no-JS build keeps every normative section readable.

    Motion

    Durations are at most 150ms and apply to opacity, transform and background only. Under prefers-reduced-motion: reduce every duration is 0.01ms: toasts, dialogs and drawers appear in place, indeterminate progress shows static stripes, loading glyphs do not spin, skeletons do not shimmer, tab indicators do not slide. No behaviour is sequenced on transitionend.

    The specification page’s generated literal-color previews have the narrow geometry, checkerboard and motion exception recorded in D-014; the component and consumer rules remain as written.

    Forced colours and high contrast

    Under forced-colors: active rings use Highlight, selections use Highlight / HighlightText, borders survive (they are real borders, not box-shadows), and pattern fills keep charts and diffs legible.

    Reflow, zoom and text

    Components reflow at 320 CSS pixels without horizontal page scrolling, at 200% browser zoom and at 200% text-only zoom. Rings and borders stay 1px / 2px CSS. Targets are at least 24×24 CSS pixels with 4px spacing in compact density. Long labels wrap or truncate with a visible affordance; the site’s stress fixtures (English, Spanish, Chinese, Arabic with dir="rtl") exercise this.

    Colour is never the only channel

    Every status has a glyph; every state has a border, pattern or ARIA change; diffs keep + − ~ markers; charts carry pattern fills and a table fallback. The heritage-ansi terminal palette has reduced hue differentiation by design, and the specification documents it as a limitation rather than fixing it silently.

    Limitations (recorded, not hidden)

    • The theme specifies colours, states and reference markup. It cannot make a host application’s own focus management, labels or reading order correct.
    • The automated scan on the site uses axe-core with the WCAG 2.x A and AA rule sets. It does not evaluate every success criterion, and manual checks (keyboard walks, screen-reader reading, zoom) require separate execution evidence. Missing protocols remain not run, not implied by the scan.
    • text.disabled at 3.52:1 on canvas is below the ordinary-text floor by design and relies on the WCAG exemption for inactive controls.
    • Heritage ANSI slots 1, 4, 6, 8, 9, 10, 12, 13, 14 and 15 fail 4.5:1 on the terminal background (slot 0 is the background). Programs that render errors or directories in those slots inherit that failure; the extended overlay proposes a corrected set.
    • Syntax roles inside an editor selection: keyword, type, property and comment drop below 4.5:1 on code.selection-bg. Selection is transient; the limitation is recorded in the code-editor specification.

    Verification evidence and freshness

    The coverage ledger describes source facts: specified, demonstrated and test implemented. exports/coverage.json schemaVersion 1 adds testImplemented and retains tested as a compatibility alias with its original file-existence meaning. Component JSON coverage and family totals use the same definitions. No source coverage Boolean proves execution or blanket WCAG conformance.

    The linked static verification report supplies actual per-test outcomes and per-component summaries. Evidence schemaVersion 1 records automated or manual method, category, component, explicitly covered states/variants, browser/version, OS, viewport, profile, density, JavaScript setting and a run or protocol reference. Empty state/variant lists mean unspecified, never all. The environment’s profile and density describe the initial configuration; tests that switch them say so in their scope. Browser records from one engine never imply another engine. Skipped, failed, not run and not applicable are separate outcomes; every non-pass has a reason. Manual screen-reader and keyboard claims require protocol records. The existing automated suite targets Chromium; other engines remain not run.

    Freshness compares both the tested artifact digest and a conservative source fingerprint covering tracked contract sources, schemas, generators, site code, tests, agent guidance, CI configuration and package lockfile. All such changes invalidate the current claim; unrelated source changes may therefore invalidate more evidence than strictly necessary. A stale record retains its actual outcome and supporting reference but does not establish a current pass.

    A build first publishes a static not-run report and a subject manifest. The browser reporter checks that source and specimen assets still match that subject before publishing execution evidence. Report generation writes only under dist/verification/ and verifies all specimen bytes remain unchanged. Report presentation gets a separate static/browser gate and never certifies itself. Run timestamps and revisions live only in this post-test evidence, outside the committed deterministic exports and their digests, avoiding circular hashes.

    Local workflow: build, run the browser suite, npm run verification:report, npm run verification:check, then npm run test:verification. A local run names its local execution and digests; it is not represented as hosted CI evidence. For a manual protocol, provide a schema-valid evidence document to node scripts/verification-report.mjs <repo-relative-evidence.json> with its actual tested digests, browser/environment and a protocol: reference containing the protocol identifier and recorded observations. Retain the protocol with the evidence; do not copy private artifacts into this public repository.

    Contrast report

    954 declared pairs measured on resolved sRGB values with the WCAG 2.x formula; 17 waived (decorative only), 0 failing. A pass is a design target for the named role, not an application-wide conformance claim.

    PairStateKindForegroundBackgroundRatioMinResult
    default text on canvastextcolor.text.default #e99499color.surface.canvas #0000009.164.5pass
    default text on default surfacetextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    default text on raisedtextcolor.text.default #e99499color.surface.raised #160b0b8.434.5pass
    bright text on canvastextcolor.text.bright #ffa2a7color.surface.canvas #00000010.984.5pass
    prose on canvastextcolor.text.prose #f4eeeecolor.surface.canvas #00000018.314.5pass
    prose on sunkentextcolor.text.prose #f4eeeecolor.surface.sunken #00000018.314.5pass
    muted text on canvastextcolor.text.muted #bd787dcolor.surface.canvas #0000006.154.5pass
    muted text on raisedtextcolor.text.muted #bd787dcolor.surface.raised #160b0b5.664.5pass
    subtle text on canvastextcolor.text.subtle #ad7175color.surface.canvas #0000005.404.5pass
    subtle text on raisedtextcolor.text.subtle #ad7175color.surface.raised #160b0b4.964.5pass
    disabled text on canvas (exempt; house floor 3:1)uicolor.text.disabled #8a5559color.surface.canvas #0000003.523pass
    placeholder on inputtextcolor.text.placeholder #a3676bcolor.surface.input #0000004.714.5pass
    accent text on canvastextcolor.text.accent #e53935color.surface.canvas #0000004.974.5pass
    accent text on default surfacetextcolor.text.accent #e53935color.surface.default #100c0c4.604.5pass
    strong accent on raisedtextcolor.text.accent-strong #f73f35color.surface.raised #160b0b5.264.5pass
    link on canvastextcolor.text.link #f73f35color.surface.canvas #0000005.724.5pass
    link hover text on strong hover filltextcolor.text.link-hover #f4eeeecolor.interaction.hover.bg-strong #630f0d11.414.5pass
    selection text on selectiontextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
    inactive selection text on inactive selectiontextcolor.interaction.selection.inactive-text #e99499color.interaction.selection.inactive-bg #420f0c7.024.5pass
    primary action text on filltextcolor.action.primary.text #f4eeeecolor.action.primary.bg #7d13109.284.5pass
    primary action text on hover filltextcolor.action.primary.text #f4eeeecolor.action.primary.hover-bg #9114107.924.5pass
    secondary action text on canvastextcolor.action.secondary.text #ffa2a7color.surface.canvas #00000010.984.5pass
    destructive text on canvastextcolor.action.destructive.text #f73f35color.surface.canvas #0000005.724.5pass
    destructive hover text on hover filltextcolor.action.destructive.hover-text #f9faf9color.action.destructive.hover-bg #dc282e4.584.5pass
    danger text on canvastextcolor.status.danger.text #f73f35color.surface.canvas #0000005.724.5pass
    danger text on danger tinttextcolor.status.danger.text #f73f35color.status.danger.tint #2b0e0d4.884.5pass
    danger on-fill texttextcolor.status.danger.on-fill #f9faf9color.status.danger.fill #dc282e4.584.5pass
    warning text on canvastextcolor.status.warning.text #c9973fcolor.surface.canvas #0000007.984.5pass
    warning text on warning tinttextcolor.status.warning.text #c9973fcolor.status.warning.tint #1f1a0c6.594.5pass
    warning on-fill texttextcolor.status.warning.on-fill #0c0909color.status.warning.fill #c9973f7.544.5pass
    success text on canvastextcolor.status.success.text #86a46fcolor.surface.canvas #0000007.554.5pass
    success text on success tinttextcolor.status.success.text #86a46fcolor.status.success.tint #0f1a0e6.434.5pass
    success on-fill texttextcolor.status.success.on-fill #0c0909color.status.success.fill #86a46f7.134.5pass
    info text on canvastextcolor.status.info.text #7e9ebbcolor.surface.canvas #0000007.504.5pass
    info text on info tinttextcolor.status.info.text #7e9ebbcolor.status.info.tint #0f141c6.594.5pass
    info on-fill texttextcolor.status.info.on-fill #0c0909color.status.info.fill #7e9ebb7.084.5pass
    neutral on-fill texttextcolor.status.neutral.on-fill #000000color.status.neutral.fill #a3676b4.714.5pass
    focus ring on canvasuicolor.interaction.focus.ring #e53935color.surface.canvas #0000004.973pass
    focus ring on default surfaceuicolor.interaction.focus.ring #e53935color.surface.default #100c0c4.603pass
    container focus ring on selectionuicolor.interaction.focus.ring-container #ffa2a7color.interaction.selection.bg #5313107.483pass
    control border on inputuicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    control border on default surfaceuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    active border on inputuicolor.border.active #e53935color.surface.input #0000004.973pass
    decorative border on canvas (decorative; not a control edge)uicolor.border.default #531310color.surface.canvas #0000001.473waived: decorative hairline; never the only boundary of a control (spec/foundations.md)
    strong rule on canvas (decorative)uicolor.border.strong #9e231fcolor.surface.canvas #0000002.713waived: 2px decorative rule paired with a surface change; never the only boundary of a control
    line numbers on code backgroundtextcolor.code.line-number #ad7175color.code.bg #0c09095.104.5pass
    caret on current lineuicolor.code.caret #e99499color.code.current-line #1c0a098.353pass
    comment on code backgroundtextcolor.code.syntax.comment #ad7175color.code.bg #0c09095.104.5pass
    string on code backgroundtextcolor.code.syntax.string #bd787dcolor.code.bg #0c09095.814.5pass
    keyword on code backgroundtextcolor.code.syntax.keyword #f73f35color.code.bg #0c09095.404.5pass
    type on code backgroundtextcolor.code.syntax.type #b37175color.code.bg #0c09095.234.5pass
    muted text on editor selectiontextcolor.text.muted #bd787dcolor.code.selection-bg #420f0c4.714.5pass
    current search match texttextcolor.code.search-current-text #0c0909color.code.search-current-bg #ffa2a710.374.5pass
    error text on canvastextcolor.diagnostic.error.text #f73f35color.surface.canvas #0000005.724.5pass
    warning diagnostic text on canvastextcolor.diagnostic.warning.text #c9973fcolor.surface.canvas #0000007.984.5pass
    info diagnostic text on canvastextcolor.diagnostic.info.text #7e9ebbcolor.surface.canvas #0000007.504.5pass
    default text on added-line backgroundtextcolor.text.default #e99499color.diff.added.bg #0f1a0e7.804.5pass
    default text on removed-line backgroundtextcolor.text.default #e99499color.diff.removed.bg #2b0e0d7.824.5pass
    default text on modified-line backgroundtextcolor.text.default #e99499color.diff.modified.bg #1f1a0c7.564.5pass
    terminal foregroundtextcolor.terminal.fg #e99499color.terminal.bg #0c09098.654.5pass
    chart label on canvastextcolor.chart.label #bd787dcolor.surface.canvas #0000006.154.5pass
    chart series 4 on canvas (graphic)uicolor.chart.series-4 #a3676bcolor.surface.canvas #0000004.713pass
    decorative icon on canvas (graphic)uicolor.icon.decorative #a3676bcolor.surface.canvas #0000004.713pass
    admin-form default textdefaulttextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    admin-form default borderdefaultuicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    admin-form invalid textinvalidtextcolor.status.danger.text #f73f35color.status.danger.tint #2b0e0d4.884.5pass
    admin-form invalid borderinvaliduicolor.status.danger.border #e53935color.status.danger.tint #2b0e0d4.243pass
    admin-form busy textbusytextcolor.action.primary.text #f4eeeecolor.action.primary.bg #7d13109.284.5pass
    title, labels and the current step on the panel surfacetextcolor.text.bright #ffa2a7color.surface.default #100c0c10.174.5pass
    help, affix and review keys on the panel surfacetextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    breadcrumb links on the panel surfacetextcolor.text.link #f73f35color.surface.default #100c0c5.294.5pass
    complete-step checktextcolor.status.success.text #86a46fcolor.surface.default #100c0c6.994.5pass
    notice title on its tinttextcolor.status.info.text #7e9ebbcolor.status.info.tint #0f141c6.594.5pass
    notice text on its tinttextcolor.text.default #e99499color.status.info.tint #0f141c8.064.5pass
    summary text on the danger tintinvalidtextcolor.text.default #e99499color.status.danger.tint #2b0e0d7.824.5pass
    field messages on the panel surfaceinvalidtextcolor.status.danger.text #f73f35color.surface.default #100c0c5.294.5pass
    invalid field boundaryinvaliduicolor.status.danger.border #e53935color.surface.input #0000004.973pass
    current-step indicator baruicolor.border.selected-indicator #e53935color.surface.default #100c0c4.603pass
    Back button and file-input button boundariesuicolor.action.secondary.border #a3676bcolor.surface.default #100c0c4.363pass
    disabled control text (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.interaction.disabled.bg #160b0b3.243pass
    disabled labels and review keys (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.surface.default #100c0c3.263pass
    disabled boundaries (exempt)disableduicolor.border.disabled #7d1310color.interaction.disabled.bg #160b0b1.821pass
    review header rule (decorative)uicolor.border.strong #9e231fcolor.surface.default #100c0c2.511pass
    panel edge (decorative)uicolor.border.default #531310color.surface.default #100c0c1.361pass
    step, row and footer rules (decorative)uicolor.border.divider #2b0e0dcolor.surface.default #100c0c1.081pass
    alert default textdefaulttextcolor.status.danger.text #f73f35color.status.danger.tint #2b0e0d4.884.5pass
    alert default borderdefaultuicolor.status.danger.border #e53935color.status.danger.tint #2b0e0d4.243pass
    alert hover texthovertextcolor.action.tertiary.text #e99499color.action.tertiary.hover-bg #1c0a098.354.5pass
    alert focus-visible textfocus-visibletextcolor.action.tertiary.text #e99499color.status.info.tint #0f141c8.064.5pass
    alert focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.status.info.tint #0f141c4.373pass
    body text on the danger tinttextcolor.text.default #e99499color.status.danger.tint #2b0e0d7.824.5pass
    warning glyph and title on the warning tinttextcolor.status.warning.text #c9973fcolor.status.warning.tint #1f1a0c6.594.5pass
    warning border on the warning tintuicolor.status.warning.border #c9973fcolor.status.warning.tint #1f1a0c6.593pass
    body text on the warning tinttextcolor.text.default #e99499color.status.warning.tint #1f1a0c7.564.5pass
    success glyph and title on the success tinttextcolor.status.success.text #86a46fcolor.status.success.tint #0f1a0e6.434.5pass
    success border on the success tintuicolor.status.success.border #86a46fcolor.status.success.tint #0f1a0e6.433pass
    body text on the success tinttextcolor.text.default #e99499color.status.success.tint #0f1a0e7.804.5pass
    info glyph and title on the info tinttextcolor.status.info.text #7e9ebbcolor.status.info.tint #0f141c6.594.5pass
    info border on the info tintuicolor.status.info.border #7e9ebbcolor.status.info.tint #0f141c6.593pass
    body text on the info tinttextcolor.text.default #e99499color.status.info.tint #0f141c8.064.5pass
    neutral glyph and title on the neutral tinttextcolor.status.neutral.text #bd787dcolor.status.neutral.tint #2410105.314.5pass
    neutral border on the neutral tintuicolor.status.neutral.border #a3676bcolor.status.neutral.tint #2410104.073pass
    body text on the neutral tinttextcolor.text.default #e99499color.status.neutral.tint #2410107.924.5pass
    close button on the info tinttextcolor.action.tertiary.text #e99499color.status.info.tint #0f141c8.064.5pass
    ring on the info tintfocus-visibleuicolor.interaction.focus.ring #e53935color.status.info.tint #0f141c4.373pass
    avatar default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    avatar default borderdefaultuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    Primary contenttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    Supporting contenttextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    Control boundaryuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    badge default textdefaulttextcolor.status.danger.on-fill #f9faf9color.status.danger.fill #dc282e4.584.5pass
    badge empty textemptytextcolor.status.danger.on-fill #f9faf9color.status.danger.fill #dc282e4.584.5pass
    warning badgetextcolor.status.warning.on-fill #0c0909color.status.warning.fill #c9973f7.544.5pass
    success badgetextcolor.status.success.on-fill #0c0909color.status.success.fill #86a46f7.134.5pass
    info badgetextcolor.status.info.on-fill #0c0909color.status.info.fill #7e9ebb7.084.5pass
    neutral badgetextcolor.status.neutral.on-fill #000000color.status.neutral.fill #a3676b4.714.5pass
    count badgetextcolor.action.primary.text #f4eeeecolor.action.primary.bg #7d13109.284.5pass
    danger outline texttextcolor.status.danger.text #f73f35color.surface.default #100c0c5.294.5pass
    warning outline texttextcolor.status.warning.text #c9973fcolor.surface.default #100c0c7.394.5pass
    success outline texttextcolor.status.success.text #86a46fcolor.surface.default #100c0c6.994.5pass
    info outline texttextcolor.status.info.text #7e9ebbcolor.surface.default #100c0c6.944.5pass
    neutral outline texttextcolor.status.neutral.text #bd787dcolor.surface.default #100c0c5.694.5pass
    danger outline borderuicolor.status.danger.border #e53935color.surface.default #100c0c4.603pass
    warning outline borderuicolor.status.warning.border #c9973fcolor.surface.default #100c0c7.393pass
    success outline borderuicolor.status.success.border #86a46fcolor.surface.default #100c0c6.993pass
    info outline borderuicolor.status.info.border #7e9ebbcolor.surface.default #100c0c6.943pass
    neutral outline borderuicolor.status.neutral.border #a3676bcolor.surface.default #100c0c4.363pass
    danger dot on the panel surfaceemptyuicolor.status.danger.fill #dc282ecolor.surface.default #100c0c4.063pass
    warning dot on the panel surfaceemptyuicolor.status.warning.fill #c9973fcolor.surface.default #100c0c7.393pass
    success dot on the panel surfaceemptyuicolor.status.success.fill #86a46fcolor.surface.default #100c0c6.993pass
    info dot on the panel surfaceemptyuicolor.status.info.fill #7e9ebbcolor.surface.default #100c0c6.943pass
    neutral dot on the panel surfaceemptyuicolor.status.neutral.fill #a3676bcolor.surface.default #100c0c4.363pass
    breadcrumbs default textdefaulttextcolor.text.link #f73f35color.surface.default #100c0c5.294.5pass
    breadcrumbs hover texthovertextcolor.text.link-hover #f4eeeecolor.interaction.hover.bg-strong #630f0d11.414.5pass
    breadcrumbs focus-visible textfocus-visibletextcolor.text.link #f73f35color.surface.default #100c0c5.294.5pass
    breadcrumbs focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.default #100c0c4.603pass
    breadcrumbs current textcurrenttextcolor.text.bright #ffa2a7color.surface.default #100c0c10.174.5pass
    breadcrumbs truncated texttruncatedtextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    separator on the panel surfacetextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    link underlineuicolor.text.link-underline #dc282ecolor.surface.default #100c0c4.063pass
    button-group default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    button-group default borderdefaultuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    Primary contenttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    Supporting contenttextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    Control boundaryuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    button default textdefaulttextcolor.action.primary.text #f4eeeecolor.action.primary.bg #7d13109.284.5pass
    button hover texthovertextcolor.action.primary.text #f4eeeecolor.action.primary.hover-bg #9114107.924.5pass
    button focus-visible textfocus-visibletextcolor.action.primary.text #f4eeeecolor.action.primary.bg #7d13109.284.5pass
    button focus-visible outlinefocus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.action.primary.bg #7d13105.573pass
    button active textactivetextcolor.action.primary.text #f4eeeecolor.action.primary.pressed-bg #630f0d11.414.5pass
    button loading textloadingtextcolor.action.primary.text #f4eeeecolor.action.primary.bg #7d13109.284.5pass
    primary fill against the panel (decorative; the label identifies the button)uicolor.action.primary.bg #7d1310color.surface.default #100c0c1.833waived: the fill is not the boundary of the control; the label text at 9.28:1 identifies it, and hover, active and focus each add a second channel
    secondary text at resttextcolor.action.secondary.text #ffa2a7color.action.secondary.bg #00000010.984.5pass
    secondary border at restuicolor.action.secondary.border #a3676bcolor.action.secondary.bg #0000004.713pass
    secondary text on the hover fillhovertextcolor.action.secondary.text #ffa2a7color.action.secondary.hover-bg #630f0d6.844.5pass
    secondary border against the panel while hovered (the fill inside it measures 2.94:1)hoveruicolor.action.secondary.border #a3676bcolor.surface.default #100c0c4.363pass
    ring on the secondary hover fillhoveruicolor.interaction.focus.ring #e53935color.action.secondary.hover-bg #630f0d3.103pass
    secondary text while pressedactivetextcolor.action.secondary.text #ffa2a7color.action.secondary.pressed-bg #420f0c8.414.5pass
    tertiary text at resttextcolor.action.tertiary.text #e99499color.action.secondary.bg #0000009.164.5pass
    tertiary text on the hover fillhovertextcolor.action.tertiary.text #e99499color.action.tertiary.hover-bg #1c0a098.354.5pass
    tertiary text while pressedactivetextcolor.action.tertiary.text #e99499color.interaction.pressed.bg #420f0c7.024.5pass
    active border on the pressed fillactiveuicolor.border.active #e53935color.interaction.pressed.bg #420f0c3.813pass
    destructive text at resttextcolor.action.destructive.text #f73f35color.action.secondary.bg #0000005.724.5pass
    destructive border at restuicolor.action.destructive.border #e53935color.action.secondary.bg #0000004.973pass
    destructive text on the hover fillhovertextcolor.action.destructive.hover-text #f9faf9color.action.destructive.hover-bg #dc282e4.584.5pass
    ring on the destructive hover fill (the ring takes the on-fill colour)hoveruicolor.action.destructive.hover-text #f9faf9color.action.destructive.hover-bg #dc282e4.583pass
    destructive text while pressedactivetextcolor.action.destructive.hover-text #f9faf9color.action.destructive.pressed-bg #ae19146.814.5pass
    confirm-dialog filled destructivetextcolor.action.destructive.filled-text #f9faf9color.action.destructive.filled-bg #dc282e4.584.5pass
    disabled text (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.interaction.disabled.bg #160b0b3.243pass
    disabled border (exempt)disableduicolor.border.disabled #7d1310color.interaction.disabled.bg #160b0b1.821pass
    card default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    card hover texthovertextcolor.text.default #e99499color.interaction.hover.bg #1c0a098.354.5pass
    card hover borderhoveruicolor.border.control #a3676bcolor.interaction.hover.bg #1c0a094.293pass
    card focus-visible textfocus-visibletextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    card focus-visible outlinefocus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.surface.default #100c0c10.173pass
    card selected textselectedtextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
    card selected+focus-visible textselected+focus-visibletextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
    card selected+focus-visible outlineselected+focus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.interaction.selection.bg #5313107.483pass
    title on the cardtextcolor.text.bright #ffa2a7color.surface.default #100c0c10.174.5pass
    metadata on the cardtextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    title on the hover fillhovertextcolor.text.bright #ffa2a7color.interaction.hover.bg #1c0a0910.014.5pass
    metadata on the hover fillhovertextcolor.text.muted #bd787dcolor.interaction.hover.bg #1c0a095.604.5pass
    card edge (decorative; the card is not a control at rest)uicolor.border.default #531310color.surface.default #100c0c1.361pass
    chart default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    chart default borderdefaultuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    Primary contenttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    Supporting contenttextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    Control boundaryuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    checkbox default borderdefaultuicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    checkbox hover borderhoveruicolor.border.control #a3676bcolor.interaction.hover.bg #1c0a094.293pass
    checkbox focus-visible borderfocus-visibleuicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    checkbox focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.input #0000004.973pass
    checkbox checked textcheckedtextcolor.action.primary.text #f4eeeecolor.action.primary.bg #7d13109.284.5pass
    checkbox mixed textmixedtextcolor.action.primary.text #f4eeeecolor.action.primary.bg #7d13109.284.5pass
    checkbox checked+focus-visible textchecked+focus-visibletextcolor.action.primary.text #f4eeeecolor.action.primary.bg #7d13109.284.5pass
    checkbox checked+focus-visible outlinechecked+focus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.action.primary.bg #7d13105.573pass
    checkbox invalid borderinvaliduicolor.status.danger.border #e53935color.surface.input #0000004.973pass
    checkbox required borderrequireduicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    option text on the panel surfacetextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    legend on the panel surfacetextcolor.text.bright #ffa2a7color.surface.default #100c0c10.174.5pass
    checked box edge against the panel (the border stays border.control)checkeduicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    glyph on the hovered checked fillhovertextcolor.action.primary.text #f4eeeecolor.action.primary.hover-bg #9114107.924.5pass
    validation message on the panel surfacetextcolor.status.danger.text #f73f35color.surface.default #100c0c5.294.5pass
    disabled option text (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.surface.default #100c0c3.263pass
    disabled glyph (exempt; house floor 3:1)checked+disableduicolor.text.disabled #8a5559color.interaction.disabled.bg #160b0b3.243pass
    disabled border (exempt)disableduicolor.border.disabled #7d1310color.interaction.disabled.bg #160b0b1.821pass
    chip default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    chip default borderdefaultuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    chip hover texthovertextcolor.text.default #e99499color.interaction.hover.bg #1c0a098.354.5pass
    chip hover borderhoveruicolor.border.control #a3676bcolor.interaction.hover.bg #1c0a094.293pass
    chip focus-visible textfocus-visibletextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    chip focus-visible borderfocus-visibleuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    chip focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.default #100c0c4.603pass
    chip selected textselectedtextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
    chip selected+focus-visible textselected+focus-visibletextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
    chip selected+focus-visible outlineselected+focus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.interaction.selection.bg #5313107.483pass
    remove glyph at resttextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    disabled chip text (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.interaction.disabled.bg #160b0b3.243pass
    disabled chip border (exempt)disableduicolor.border.disabled #7d1310color.interaction.disabled.bg #160b0b1.821pass
    code-editor default textdefaulttextcolor.code.syntax.variable #e99499color.code.bg #0c09098.654.5pass
    code-editor default borderdefaultuicolor.border.control #a3676bcolor.code.bg #0c09094.453pass
    code-editor focus-visible textfocus-visibletextcolor.code.syntax.variable #e99499color.code.current-line #1c0a098.354.5pass
    code-editor focus-visible outlinefocus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.code.current-line #1c0a0910.013pass
    code-editor selected textselectedtextcolor.code.syntax.variable #e99499color.code.selection-bg #420f0c7.024.5pass
    code-editor selected+container-inactive textselected+container-inactivetextcolor.interaction.selection.inactive-text #e99499color.interaction.selection.inactive-bg #420f0c7.024.5pass
    code-editor current textcurrenttextcolor.code.syntax.variable #e99499color.code.bg #0c09098.654.5pass
    code-editor current bordercurrentuicolor.code.bracket-match #e53935color.code.bg #0c09094.693pass
    code-editor read-only textread-onlytextcolor.code.line-number #ad7175color.surface.sunken #0000005.404.5pass
    caret on the current linefocus-visibleuicolor.code.caret #e99499color.code.current-line #1c0a098.353pass
    bracket-match outline on the editor surfacecurrentuicolor.code.bracket-match #e53935color.code.bg #0c09094.693pass
    bracket-match outline on the current linecurrentuicolor.code.bracket-match #e53935color.code.current-line #1c0a094.533pass
    line numbers in the guttertextcolor.code.line-number #ad7175color.code.gutter-bg #0c09095.104.5pass
    active line numbertextcolor.code.line-number-active #e99499color.code.current-line #1c0a098.354.5pass
    keywordtextcolor.code.syntax.keyword #f73f35color.code.bg #0c09095.404.5pass
    stringtextcolor.code.syntax.string #bd787dcolor.code.bg #0c09095.814.5pass
    commenttextcolor.code.syntax.comment #ad7175color.code.bg #0c09095.104.5pass
    number and constanttextcolor.code.syntax.number #d4868bcolor.code.bg #0c09097.164.5pass
    functiontextcolor.code.syntax.function #ffa2a7color.code.bg #0c090910.374.5pass
    typetextcolor.code.syntax.type #b37175color.code.bg #0c09095.234.5pass
    property, heading and invalid texttextcolor.code.syntax.property #e53935color.code.bg #0c09094.694.5pass
    tagtextcolor.code.syntax.tag #f73f35color.code.bg #0c09095.404.5pass
    attribute and escapetextcolor.code.syntax.attribute #d4868bcolor.code.bg #0c09097.164.5pass
    deprecated texttextcolor.code.syntax.deprecated #ad7175color.code.bg #0c09095.104.5pass
    muted string text inside the selectionselectedtextcolor.code.syntax.string #bd787dcolor.code.selection-bg #420f0c4.714.5pass
    fold marker texttextcolor.text.muted #bd787dcolor.code.bg #0c09095.814.5pass
    indent guide (decorative)uicolor.code.indent-guide #531310color.code.bg #0c09091.391pass
    rendered whitespace (decorative)uicolor.code.whitespace #7d1310color.code.bg #0c09091.861pass
    gutter rule (decorative)uicolor.code.gutter-rule #2b0e0dcolor.code.bg #0c09091.111pass
    combobox default textdefaulttextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    combobox default borderdefaultuicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    combobox hover texthovertextcolor.text.link-hover #f4eeeecolor.interaction.hover.bg-strong #630f0d11.414.5pass
    combobox focus-visible textfocus-visibletextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    combobox focus-visible borderfocus-visibleuicolor.border.active #e53935color.surface.input #0000004.973pass
    combobox focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.input #0000004.973pass
    combobox open textopentextcolor.text.default #e99499color.surface.raised #160b0b8.434.5pass
    combobox open borderopenuicolor.border.overlay #e53935color.surface.raised #160b0b4.573pass
    combobox selected textselectedtextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
    combobox selected outlineselecteduicolor.interaction.focus.ring-container #ffa2a7color.interaction.selection.bg #5313107.483pass
    combobox invalid textinvalidtextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    combobox invalid borderinvaliduicolor.status.danger.border #e53935color.surface.input #0000004.973pass
    combobox invalid+focus-visible textinvalid+focus-visibletextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    combobox invalid+focus-visible borderinvalid+focus-visibleuicolor.status.danger.border #e53935color.surface.input #0000004.973pass
    combobox invalid+focus-visible outlineinvalid+focus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.surface.input #00000010.983pass
    combobox no-results textno-resultstextcolor.text.muted #bd787dcolor.surface.raised #160b0b5.664.5pass
    combobox no-results borderno-resultsuicolor.border.overlay #e53935color.surface.raised #160b0b4.573pass
    group heading on the listboxtextcolor.text.subtle #ad7175color.surface.raised #160b0b4.964.5pass
    validation message on the canvastextcolor.status.danger.text #f73f35color.surface.canvas #0000005.724.5pass
    help text on the canvastextcolor.text.muted #bd787dcolor.surface.canvas #0000006.154.5pass
    disabled text (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.interaction.disabled.bg #160b0b3.243pass
    disabled border (exempt)disableduicolor.border.disabled #7d1310color.interaction.disabled.bg #160b0b1.821pass
    group separator (decorative)uicolor.border.divider #2b0e0dcolor.surface.raised #160b0b1.081pass
    command-palette default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    command-palette default borderdefaultuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    Primary contenttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    Supporting contenttextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    Control boundaryuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    compact-dashboard default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    compact-dashboard default borderdefaultuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    Primary contenttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    Supporting contenttextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    Control boundaryuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    data-table default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    data-table hover texthovertextcolor.text.default #e99499color.interaction.hover.bg #1c0a098.354.5pass
    data-table focus-visible textfocus-visibletextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    data-table focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.default #100c0c4.603pass
    data-table selected textselectedtextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
    data-table selected+focus-visible textselected+focus-visibletextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
    data-table selected+focus-visible outlineselected+focus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.interaction.selection.bg #5313107.483pass
    data-table sorted textsortedtextcolor.text.bright #ffa2a7color.surface.default #100c0c10.174.5pass
    data-table mixed textmixedtextcolor.action.primary.text #f4eeeecolor.action.primary.bg #7d13109.284.5pass
    data-table empty textemptytextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    data-table loading textloadingtextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    header texttextcolor.text.bright #ffa2a7color.surface.default #100c0c10.174.5pass
    checkbox boundaryuicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    checked fill against the row (the glyph and the boundary carry the state)mixeduicolor.action.primary.bg #7d1310color.surface.default #100c0c1.831pass
    header rule (decorative)uicolor.border.strong #9e231fcolor.surface.default #100c0c2.511pass
    row divider (decorative)uicolor.border.divider #2b0e0dcolor.surface.default #100c0c1.081pass
    resize handle at rest (decorative; keyboard resizing is a header action)uicolor.border.default #531310color.surface.default #100c0c1.361pass
    date-picker default textdefaulttextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    date-picker default borderdefaultuicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    date-picker hover texthovertextcolor.text.default #e99499color.interaction.hover.bg #1c0a098.354.5pass
    date-picker hover borderhoveruicolor.border.control #a3676bcolor.interaction.hover.bg #1c0a094.293pass
    date-picker focus-visible textfocus-visibletextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    date-picker focus-visible borderfocus-visibleuicolor.border.active #e53935color.surface.input #0000004.973pass
    date-picker focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.input #0000004.973pass
    date-picker invalid textinvalidtextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    date-picker invalid borderinvaliduicolor.status.danger.border #e53935color.surface.input #0000004.973pass
    date-picker invalid+focus-visible textinvalid+focus-visibletextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    date-picker invalid+focus-visible borderinvalid+focus-visibleuicolor.status.danger.border #e53935color.surface.input #0000004.973pass
    date-picker invalid+focus-visible outlineinvalid+focus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.surface.input #00000010.983pass
    date-picker read-only textread-onlytextcolor.text.default #e99499color.surface.canvas #0000009.164.5pass
    validation message on the canvastextcolor.status.danger.text #f73f35color.surface.canvas #0000005.724.5pass
    help text and the range separator on the canvastextcolor.text.muted #bd787dcolor.surface.canvas #0000006.154.5pass
    disabled text (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.interaction.disabled.bg #160b0b3.243pass
    disabled border (exempt)disableduicolor.border.disabled #7d1310color.interaction.disabled.bg #160b0b1.821pass
    read-only bottom edge (decorative; the field has no box)read-onlyuicolor.border.divider #2b0e0dcolor.surface.canvas #0000001.171pass
    calendar texttextcolor.text.default #e99499color.surface.raised #160b0b8.434.5pass
    selected datetextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
    description-list default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    description-list default borderdefaultuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    Primary contenttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    Supporting contenttextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    Control boundaryuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    diagnostics default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    diagnostics default borderdefaultuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    diagnostics hover texthovertextcolor.text.default #e99499color.interaction.hover.bg #1c0a098.354.5pass
    diagnostics focus-visible textfocus-visibletextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    diagnostics focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.default #100c0c4.603pass
    diagnostics selected textselectedtextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
    diagnostics selected+focus-visible textselected+focus-visibletextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
    diagnostics selected+focus-visible outlineselected+focus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.interaction.selection.bg #5313107.483pass
    diagnostics error texterrortextcolor.status.danger.text #f73f35color.surface.default #100c0c5.294.5pass
    diagnostics empty textemptytextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    code texttextcolor.text.default #e99499color.code.bg #0c09098.654.5pass
    code text on the error linetextcolor.text.default #e99499color.diagnostic.error.bg #2b0e0d7.824.5pass
    error glyph on the error linetextcolor.diagnostic.error.text #f73f35color.diagnostic.error.bg #2b0e0d4.884.5pass
    error underlineuicolor.diagnostic.error.underline #e53935color.code.bg #0c09094.693pass
    error underline on the error lineuicolor.diagnostic.error.underline #e53935color.diagnostic.error.bg #2b0e0d4.243pass
    warning underline inside the selected rangeselecteduicolor.diagnostic.warning.underline #c9973fcolor.code.selection-bg #420f0c6.123pass
    warning underlineuicolor.diagnostic.warning.underline #c9973fcolor.code.bg #0c09097.543pass
    info underlineuicolor.diagnostic.info.underline #7e9ebbcolor.code.bg #0c09097.083pass
    hint underlineuicolor.diagnostic.hint.underline #ad7175color.code.bg #0c09095.103pass
    unused texttextcolor.diagnostic.unused.text #bd787dcolor.code.bg #0c09095.814.5pass
    deprecated texttextcolor.code.syntax.deprecated #ad7175color.code.bg #0c09095.104.5pass
    error stripe markuicolor.diagnostic.error.stripe #e53935color.code.bg #0c09094.693pass
    warning stripe markuicolor.diagnostic.warning.stripe #c9973fcolor.code.bg #0c09097.543pass
    info stripe markuicolor.diagnostic.info.text #7e9ebbcolor.code.bg #0c09097.083pass
    error glyph and count in the paneltextcolor.diagnostic.error.text #f73f35color.surface.default #100c0c5.294.5pass
    warning glyph and count in the paneltextcolor.diagnostic.warning.text #c9973fcolor.surface.default #100c0c7.394.5pass
    info glyph and count in the paneltextcolor.diagnostic.info.text #7e9ebbcolor.surface.default #100c0c6.944.5pass
    hint glyph in the paneltextcolor.text.subtle #ad7175color.surface.default #100c0c5.004.5pass
    location and rule codetextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    row text on hoverhovertextcolor.text.default #e99499color.interaction.hover.bg #1c0a098.354.5pass
    error glyph on hoverhovertextcolor.diagnostic.error.text #f73f35color.interaction.hover.bg #1c0a095.214.5pass
    the ✓ of the empty messageemptytextcolor.status.success.text #86a46fcolor.surface.default #100c0c6.994.5pass
    dialog default textdefaulttextcolor.text.default #e99499color.surface.overlay #2410107.924.5pass
    dialog default borderdefaultuicolor.border.overlay #e53935color.surface.overlay #2410104.303pass
    dialog open textopentextcolor.text.default #e99499color.surface.overlay #2410107.924.5pass
    dialog open borderopenuicolor.border.overlay #e53935color.surface.overlay #2410104.303pass
    dialog focus-trapped textfocus-trappedtextcolor.text.default #e99499color.surface.overlay #2410107.924.5pass
    dialog focus-trapped borderfocus-trappeduicolor.border.overlay #e53935color.surface.overlay #2410104.303pass
    dialog focus-trapped outlinefocus-trappeduicolor.interaction.focus.ring-container #ffa2a7color.surface.overlay #2410109.493pass
    dialog hover texthovertextcolor.action.tertiary.text #e99499color.action.tertiary.hover-bg #1c0a098.354.5pass
    dialog focus-visible textfocus-visibletextcolor.action.tertiary.text #e99499color.surface.overlay #2410107.924.5pass
    dialog focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.overlay #2410104.303pass
    dialog reduced-motion textreduced-motiontextcolor.text.default #e99499color.surface.overlay #2410107.924.5pass
    dialog reduced-motion borderreduced-motionuicolor.border.overlay #e53935color.surface.overlay #2410104.303pass
    title on the overlay surfacetextcolor.text.bright #ffa2a7color.surface.overlay #2410109.494.5pass
    note on the overlay surfacetextcolor.text.muted #bd787dcolor.surface.overlay #2410105.314.5pass
    secondary button text on the overlay surfacetextcolor.action.secondary.text #ffa2a7color.surface.overlay #2410109.494.5pass
    secondary button boundary on the overlay surfaceuicolor.action.secondary.border #a3676bcolor.surface.overlay #2410104.073pass
    primary button texttextcolor.action.primary.text #f4eeeecolor.action.primary.bg #7d13109.284.5pass
    destructive confirm text on its filltextcolor.action.destructive.filled-text #f9faf9color.action.destructive.filled-bg #dc282e4.584.5pass
    destructive fill against the overlay surfaceuicolor.action.destructive.filled-bg #dc282ecolor.surface.overlay #2410103.793pass
    ring on the primary fillfocus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.action.primary.bg #7d13105.573pass
    ring on the destructive fillfocus-visibleuicolor.action.destructive.filled-text #f9faf9color.action.destructive.filled-bg #dc282e4.583pass
    form field texttextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    form field boundary on the overlay surfaceuicolor.border.control #a3676bcolor.surface.overlay #2410104.073pass
    diff-view default textdefaulttextcolor.text.default #e99499color.code.bg #0c09098.654.5pass
    diff-view default borderdefaultuicolor.border.control #a3676bcolor.code.bg #0c09094.453pass
    diff-view hover texthovertextcolor.text.default #e99499color.interaction.hover.bg #1c0a098.354.5pass
    diff-view selected textselectedtextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
    diff-view focus-visible textfocus-visibletextcolor.text.default #e99499color.code.bg #0c09098.654.5pass
    diff-view focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.code.bg #0c09094.693pass
    diff-view expanded textexpandedtextcolor.text.link #f73f35color.diff.header-bg #2410104.944.5pass
    diff-view collapsed textcollapsedtextcolor.text.link #f73f35color.diff.header-bg #2410104.944.5pass
    text on an added rowtextcolor.text.default #e99499color.diff.added.bg #0f1a0e7.804.5pass
    text on a removed rowtextcolor.text.default #e99499color.diff.removed.bg #2b0e0d7.824.5pass
    text on a modified rowtextcolor.text.default #e99499color.diff.modified.bg #1f1a0c7.564.5pass
    hunk context on the headertextcolor.text.default #e99499color.diff.header-bg #2410107.924.5pass
    hunk range on the headertextcolor.text.muted #bd787dcolor.diff.header-bg #2410105.314.5pass
    line numbers on a context rowtextcolor.text.muted #bd787dcolor.code.bg #0c09095.814.5pass
    line numbers on an added rowtextcolor.text.muted #bd787dcolor.diff.added.bg #0f1a0e5.234.5pass
    line numbers on a removed rowtextcolor.text.muted #bd787dcolor.diff.removed.bg #2b0e0d5.254.5pass
    line numbers on a modified rowtextcolor.text.muted #bd787dcolor.diff.modified.bg #1f1a0c5.074.5pass
    the + markertextcolor.diff.added.gutter #86a46fcolor.diff.added.bg #0f1a0e6.434.5pass
    the − marker (bold, 4.24:1; glyph plus fill)uicolor.diff.removed.gutter #e53935color.diff.removed.bg #2b0e0d4.243pass
    the ~ markertextcolor.diff.modified.gutter #c9973fcolor.diff.modified.bg #1f1a0c6.594.5pass
    word-level added underlineuicolor.diff.added.emphasis #86a46fcolor.diff.added.bg #0f1a0e6.433pass
    word-level removed underline and strikeuicolor.diff.removed.emphasis #e53935color.diff.removed.bg #2b0e0d4.243pass
    conflict double borderuicolor.diff.conflict-border #f73f35color.code.bg #0c09095.403pass
    conflict marker linestextcolor.text.bright #ffa2a7color.diff.header-bg #2410109.494.5pass
    ring on an added rowfocus-visibleuicolor.interaction.focus.ring #e53935color.diff.added.bg #0f1a0e4.233pass
    ring on a removed rowfocus-visibleuicolor.interaction.focus.ring #e53935color.diff.removed.bg #2b0e0d4.243pass
    ring on a modified rowfocus-visibleuicolor.interaction.focus.ring #e53935color.diff.modified.bg #1f1a0c4.103pass
    ring on the selected rowfocus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.interaction.selection.bg #5313107.483pass
    fold button texttextcolor.text.link #f73f35color.diff.header-bg #2410104.944.5pass
    disclosure default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    disclosure default borderdefaultuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    Primary contenttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    Supporting contenttextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    Control boundaryuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    drawer default textdefaulttextcolor.text.default #e99499color.surface.overlay #2410107.924.5pass
    drawer default borderdefaultuicolor.border.overlay #e53935color.surface.overlay #2410104.303pass
    drawer open textopentextcolor.text.default #e99499color.surface.overlay #2410107.924.5pass
    drawer open borderopenuicolor.border.overlay #e53935color.surface.overlay #2410104.303pass
    drawer focus-trapped textfocus-trappedtextcolor.text.default #e99499color.surface.overlay #2410107.924.5pass
    drawer focus-trapped borderfocus-trappeduicolor.border.overlay #e53935color.surface.overlay #2410104.303pass
    drawer focus-trapped outlinefocus-trappeduicolor.interaction.focus.ring-container #ffa2a7color.surface.overlay #2410109.493pass
    drawer reduced-motion textreduced-motiontextcolor.text.default #e99499color.surface.overlay #2410107.924.5pass
    drawer reduced-motion borderreduced-motionuicolor.border.overlay #e53935color.surface.overlay #2410104.303pass
    title on the overlay surfacetextcolor.text.bright #ffa2a7color.surface.overlay #2410109.494.5pass
    note on the overlay surfacetextcolor.text.muted #bd787dcolor.surface.overlay #2410105.314.5pass
    close button on the overlay surfacetextcolor.action.tertiary.text #e99499color.surface.overlay #2410107.924.5pass
    ring on the overlay surfaceuicolor.interaction.focus.ring #e53935color.surface.overlay #2410104.303pass
    hovered itemtextcolor.text.link-hover #f4eeeecolor.interaction.hover.bg-strong #630f0d11.414.5pass
    row dividers (decorative)uicolor.border.divider #2b0e0dcolor.surface.overlay #2410101.011pass
    editor-search default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    editor-search default borderdefaultuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    Primary contenttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    Supporting contenttextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    Control boundaryuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    empty-state default textdefaulttextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    heading on the panel surfacetextcolor.text.bright #ffa2a7color.surface.default #100c0c10.174.5pass
    action text on the panel surfacetextcolor.action.secondary.text #ffa2a7color.surface.default #100c0c10.174.5pass
    action boundary on the panel surfaceuicolor.action.secondary.border #a3676bcolor.surface.default #100c0c4.363pass
    glyph (decorative)uicolor.icon.decorative #a3676bcolor.surface.default #100c0c4.361pass
    container edge (decorative)uicolor.border.divider #2b0e0dcolor.surface.canvas #0000001.171pass
    error-state default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    error-state default borderdefaultuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    Primary contenttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    Supporting contenttextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    Control boundaryuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    field default textdefaulttextcolor.text.bright #ffa2a7color.surface.default #100c0c10.174.5pass
    field required textrequiredtextcolor.status.danger.text #f73f35color.surface.default #100c0c5.294.5pass
    field invalid textinvalidtextcolor.status.danger.text #f73f35color.surface.default #100c0c5.294.5pass
    help text on the panel surfacetextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    help text on the canvastextcolor.text.muted #bd787dcolor.surface.canvas #0000006.154.5pass
    disabled label (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.surface.default #100c0c3.263pass
    disabled control text (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.interaction.disabled.bg #160b0b3.243pass
    disabled border (exempt)disableduicolor.border.disabled #7d1310color.interaction.disabled.bg #160b0b1.821pass
    fieldset default textdefaulttextcolor.text.bright #ffa2a7color.surface.default #100c0c10.174.5pass
    group border (decorative; the legend and spacing carry the grouping)uicolor.border.divider #2b0e0dcolor.surface.default #100c0c1.081pass
    field labels inside the grouptextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    help text inside the grouptextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    disabled legend and labels (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.surface.default #100c0c3.263pass
    disabled field text (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.interaction.disabled.bg #160b0b3.243pass
    disabled field border (exempt)disableduicolor.border.disabled #7d1310color.interaction.disabled.bg #160b0b1.821pass
    file-browser default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    file-browser default borderdefaultuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    Primary contenttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    Supporting contenttextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    Control boundaryuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    file-input default textdefaulttextcolor.action.secondary.text #ffa2a7color.surface.canvas #00000010.984.5pass
    file-input default borderdefaultuicolor.action.secondary.border #a3676bcolor.surface.canvas #0000004.713pass
    file-input hover texthovertextcolor.action.secondary.text #ffa2a7color.action.secondary.hover-bg #630f0d6.844.5pass
    file-input focus-visible textfocus-visibletextcolor.action.secondary.text #ffa2a7color.surface.canvas #00000010.984.5pass
    file-input focus-visible borderfocus-visibleuicolor.action.secondary.border #a3676bcolor.surface.canvas #0000004.713pass
    file-input focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.canvas #0000004.973pass
    file-input drop-target textdrop-targettextcolor.text.default #e99499color.interaction.marquee #1102028.844.5pass
    file-input drop-target borderdrop-targetuicolor.interaction.drop-target #e53935color.interaction.marquee #1102024.803pass
    file-input invalid textinvalidtextcolor.action.secondary.text #ffa2a7color.surface.canvas #00000010.984.5pass
    file-input invalid borderinvaliduicolor.status.danger.border #e53935color.surface.canvas #0000004.973pass
    hovered button boundary against the canvas outside ithoveruicolor.action.secondary.border #a3676bcolor.surface.canvas #0000004.713pass
    drop-zone dashed border at restuicolor.interaction.drop-target #e53935color.surface.canvas #0000004.973pass
    status, hint and help text on the canvastextcolor.text.muted #bd787dcolor.surface.canvas #0000006.154.5pass
    file sizes on the canvastextcolor.text.subtle #ad7175color.surface.canvas #0000005.404.5pass
    per-file error and validation message on the canvastextcolor.status.danger.text #f73f35color.surface.canvas #0000005.724.5pass
    disabled button text (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.interaction.disabled.bg #160b0b3.243pass
    disabled border (exempt)disableduicolor.border.disabled #7d1310color.interaction.disabled.bg #160b0b1.821pass
    progress stripes (decorative pattern)loadinguicolor.action.primary.bg #7d1310color.interaction.pressed.bg #420f0c1.511pass
    filterable-table default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    filterable-table hover texthovertextcolor.text.default #e99499color.interaction.hover.bg #1c0a098.354.5pass
    filterable-table focus-visible textfocus-visibletextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    filterable-table focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.default #100c0c4.603pass
    filterable-table selected textselectedtextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
    filterable-table no-results textno-resultstextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    toolbar controls on the chrome surfacetextcolor.text.default #e99499color.surface.chrome #0907078.774.5pass
    search box and filter button boundaries on the chrome surfaceuicolor.border.control #a3676bcolor.surface.chrome #0907074.513pass
    column headers, empty-state heading and current pagetextcolor.text.bright #ffa2a7color.surface.default #100c0c10.174.5pass
    count, chip remove glyph and empty-state texttextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    Tested badgetextcolor.status.success.on-fill #0c0909color.status.success.fill #86a46f7.134.5pass
    Demonstrated badgetextcolor.status.info.on-fill #0c0909color.status.info.fill #7e9ebb7.084.5pass
    New button and checked boxestextcolor.action.primary.text #f4eeeecolor.action.primary.bg #7d13109.284.5pass
    ring on a selected rowselecteduicolor.interaction.focus.ring-container #ffa2a7color.interaction.selection.bg #5313107.483pass
    chip and checkbox boundariesuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    disabled Prev link (exempt; house floor 3:1)uicolor.text.disabled #8a5559color.surface.default #100c0c3.263pass
    header rule (decorative)uicolor.border.strong #9e231fcolor.surface.default #100c0c2.511pass
    panel edge and toolbar separator (decorative)uicolor.border.default #531310color.surface.default #100c0c1.361pass
    row, toolbar and footer rules (decorative)uicolor.border.divider #2b0e0dcolor.surface.default #100c0c1.081pass
    form-builder default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    form-builder default borderdefaultuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    Editor texttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    Definition statustextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    i3-window-frame default textdefaulttextcolor.text.muted #bd787dcolor.surface.chrome #0907075.884.5pass
    i3-window-frame focus-visible textfocus-visibletextcolor.text.bright #ffa2a7color.surface.chrome-alt #1c0a0910.014.5pass
    i3-window-frame focus-visible outlinefocus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.surface.chrome-alt #1c0a0910.013pass
    i3-window-frame selected textselectedtextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
    i3-window-frame container-inactive textcontainer-inactivetextcolor.text.muted #bd787dcolor.surface.chrome #0907075.884.5pass
    i3-window-frame error texterrortextcolor.status.danger.on-fill #f9faf9color.status.danger.fill #dc282e4.584.5pass
    workspace names and status text on the bartextcolor.text.default #e99499color.surface.chrome #0907078.774.5pass
    clock on the bartextcolor.text.bright #ffa2a7color.surface.chrome #09070710.504.5pass
    focused titletextcolor.text.bright #ffa2a7color.surface.chrome-alt #1c0a0910.014.5pass
    focused window frame on the desktopuicolor.border.active #e53935color.surface.desktop #0000004.973pass
    floating window frame on the desktopuicolor.border.overlay #e53935color.surface.desktop #0000004.973pass
    container ring on the window surfacefocus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.surface.canvas #00000010.983pass
    ring on a workspace or tabuicolor.interaction.focus.ring #e53935color.surface.chrome #0907074.753pass
    visible-tab indicator on the title rowuicolor.border.selected-indicator #e53935color.surface.chrome #0907074.753pass
    urgent fill against the barerroruicolor.status.danger.fill #dc282ecolor.surface.chrome #0907074.203pass
    visible-workspace fill against the baruicolor.interaction.selection.bg #531310color.surface.chrome #0907071.411pass
    inactive tab indicatorcontainer-inactiveuicolor.border.selected-indicator-inactive #9e231fcolor.surface.chrome #0907072.601pass
    unfocused window frames (decorative)uicolor.border.default #531310color.surface.desktop #0000001.471pass
    status block separators (decorative)uicolor.text.muted #bd787dcolor.surface.chrome #0907075.881pass
    status glyphs (decorative)uicolor.icon.decorative #a3676bcolor.surface.chrome #0907074.511pass
    icon-button default textdefaulttextcolor.action.tertiary.text #e99499color.action.secondary.bg #0000009.164.5pass
    icon-button hover texthovertextcolor.action.tertiary.text #e99499color.action.tertiary.hover-bg #1c0a098.354.5pass
    icon-button focus-visible textfocus-visibletextcolor.action.tertiary.text #e99499color.action.secondary.bg #0000009.164.5pass
    icon-button focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.action.secondary.bg #0000004.973pass
    icon-button active textactivetextcolor.action.tertiary.text #e99499color.interaction.pressed.bg #420f0c7.024.5pass
    icon-button active borderactiveuicolor.border.active #e53935color.interaction.pressed.bg #420f0c3.813pass
    icon-button toggled texttoggledtextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
    icon-button toggled+focus-visible texttoggled+focus-visibletextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
    icon-button toggled+focus-visible outlinetoggled+focus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.interaction.selection.bg #5313107.483pass
    toggled border against the paneltoggleduicolor.border.selected-indicator #e53935color.surface.default #100c0c4.603pass
    toggled fill against the panel (decorative)toggleduicolor.interaction.selection.bg #531310color.surface.default #100c0c1.363waived: aria-pressed, the filled icon form and the 1px selected-indicator border carry the state; the fill is not the boundary
    disabled icon (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.interaction.disabled.bg #160b0b3.243pass
    disabled border (exempt)disableduicolor.border.disabled #7d1310color.interaction.disabled.bg #160b0b1.821pass
    kbd default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    kbd default borderdefaultuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    Primary contenttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    Supporting contenttextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    Control boundaryuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    link default textdefaulttextcolor.text.link #f73f35color.surface.canvas #0000005.724.5pass
    link hover texthovertextcolor.text.link-hover #f4eeeecolor.interaction.hover.bg-strong #630f0d11.414.5pass
    link focus-visible textfocus-visibletextcolor.text.link #f73f35color.surface.canvas #0000005.724.5pass
    link focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.canvas #0000004.973pass
    link visited textvisitedtextcolor.text.link #f73f35color.surface.canvas #0000005.724.5pass
    link current textcurrenttextcolor.text.bright #ffa2a7color.surface.canvas #00000010.984.5pass
    link current bordercurrentuicolor.border.selected-indicator #e53935color.surface.canvas #0000004.973pass
    underline on the canvasuicolor.text.link-underline #dc282ecolor.surface.canvas #0000004.393pass
    underline on the paneluicolor.text.link-underline #dc282ecolor.surface.default #100c0c4.063pass
    link text on the paneltextcolor.text.link #f73f35color.surface.default #100c0c5.294.5pass
    link text on raised surfacestextcolor.text.link #f73f35color.surface.raised #160b0b5.264.5pass
    ring on the hover fillhoveruicolor.interaction.focus.ring #e53935color.interaction.hover.bg-strong #630f0d3.103pass
    list default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    list default borderdefaultuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    list hover texthovertextcolor.text.default #e99499color.interaction.hover.bg #1c0a098.354.5pass
    list focus-visible textfocus-visibletextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    list focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.default #100c0c4.603pass
    list selected textselectedtextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
    list selected+focus-visible textselected+focus-visibletextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
    list selected+focus-visible outlineselected+focus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.interaction.selection.bg #5313107.483pass
    list selected+container-inactive textselected+container-inactivetextcolor.interaction.selection.inactive-text #e99499color.interaction.selection.inactive-bg #420f0c7.024.5pass
    metadata column on the list surfacetextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    metadata column on the hover fillhovertextcolor.text.muted #bd787dcolor.interaction.hover.bg #1c0a095.604.5pass
    disabled option text (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.surface.default #100c0c3.263pass
    row divider (decorative)uicolor.border.divider #2b0e0dcolor.surface.default #100c0c1.081pass
    loading-indicator default textdefaulttextcolor.text.default #e99499color.surface.canvas #0000009.164.5pass
    loading-indicator reduced-motion textreduced-motiontextcolor.text.default #e99499color.surface.canvas #0000009.164.5pass
    glyph on the canvastextcolor.text.muted #bd787dcolor.surface.canvas #0000006.154.5pass
    block label on the panel surfacetextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    block glyph on the panel surfacetextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    block edge (decorative)uicolor.border.divider #2b0e0dcolor.surface.canvas #0000001.171pass
    menu default textdefaulttextcolor.text.default #e99499color.surface.raised #160b0b8.434.5pass
    menu default borderdefaultuicolor.border.overlay #e53935color.surface.raised #160b0b4.573pass
    menu hover texthovertextcolor.text.link-hover #f4eeeecolor.interaction.hover.bg-strong #630f0d11.414.5pass
    menu focus-visible textfocus-visibletextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    menu focus-visible borderfocus-visibleuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    menu focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.default #100c0c4.603pass
    menu open textopentextcolor.text.default #e99499color.interaction.pressed.bg #420f0c7.024.5pass
    menu open borderopenuicolor.border.active #e53935color.interaction.pressed.bg #420f0c3.813pass
    menu closed textclosedtextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    menu closed bordercloseduicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    menu checked textcheckedtextcolor.text.bright #ffa2a7color.surface.raised #160b0b10.104.5pass
    menu selected textselectedtextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
    menu selected outlineselecteduicolor.interaction.focus.ring-container #ffa2a7color.interaction.selection.bg #5313107.483pass
    shortcut hint on the raised surfacetextcolor.text.muted #bd787dcolor.surface.raised #160b0b5.664.5pass
    disabled item text (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.surface.raised #160b0b3.243pass
    item separator (decorative; role separator carries the grouping)uicolor.border.divider #2b0e0dcolor.surface.raised #160b0b1.081pass
    submenu chevron (decorative; aria-haspopup carries the meaning)uicolor.icon.decorative #a3676bcolor.surface.raised #160b0b4.331pass
    multiselect default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    multiselect default borderdefaultuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    Primary contenttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    Supporting contenttextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    Control boundaryuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    number-field default textdefaulttextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    number-field default borderdefaultuicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    number-field hover texthovertextcolor.text.default #e99499color.interaction.hover.bg #1c0a098.354.5pass
    number-field hover borderhoveruicolor.border.control #a3676bcolor.interaction.hover.bg #1c0a094.293pass
    number-field focus-visible textfocus-visibletextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    number-field focus-visible borderfocus-visibleuicolor.border.active #e53935color.surface.input #0000004.973pass
    number-field focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.input #0000004.973pass
    number-field invalid textinvalidtextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    number-field invalid borderinvaliduicolor.status.danger.border #e53935color.surface.input #0000004.973pass
    number-field invalid+focus-visible textinvalid+focus-visibletextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    number-field invalid+focus-visible borderinvalid+focus-visibleuicolor.status.danger.border #e53935color.surface.input #0000004.973pass
    number-field invalid+focus-visible outlineinvalid+focus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.surface.input #00000010.983pass
    number-field read-only textread-onlytextcolor.text.default #e99499color.surface.canvas #0000009.164.5pass
    unit affix on the input surfacetextcolor.text.muted #bd787dcolor.surface.input #0000006.154.5pass
    stepper glyphs on the input surfacetextcolor.action.tertiary.text #e99499color.surface.input #0000009.164.5pass
    stepper glyphs on their hover fillhovertextcolor.action.tertiary.text #e99499color.action.tertiary.hover-bg #1c0a098.354.5pass
    validation message on the panel surfacetextcolor.status.danger.text #f73f35color.surface.default #100c0c5.294.5pass
    help text on the panel surfacetextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    disabled text (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.interaction.disabled.bg #160b0b3.243pass
    disabled border (exempt)disableduicolor.border.disabled #7d1310color.interaction.disabled.bg #160b0b1.821pass
    affix and stepper dividers (decorative)uicolor.border.divider #2b0e0dcolor.surface.input #0000001.171pass
    read-only bottom edge (decorative; the field has no box)read-onlyuicolor.border.divider #2b0e0dcolor.surface.canvas #0000001.171pass
    pagination default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    pagination hover texthovertextcolor.text.default #e99499color.interaction.hover.bg #1c0a098.354.5pass
    pagination focus-visible textfocus-visibletextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    pagination focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.default #100c0c4.603pass
    pagination current textcurrenttextcolor.text.on-selection #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
    ring on the current page when focusedcurrentuicolor.interaction.focus.ring-container #ffa2a7color.interaction.selection.bg #5313107.483pass
    disabled previous/next (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.surface.default #100c0c3.263pass
    gap ellipsis on the panel surfacetextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    popover default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    popover default borderdefaultuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    Primary contenttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    Supporting contenttextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    Control boundaryuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    progress default textdefaulttextcolor.text.default #e99499color.surface.canvas #0000009.164.5pass
    progress default borderdefaultuicolor.border.control #a3676bcolor.surface.canvas #0000004.713pass
    progress error texterrortextcolor.status.danger.text #f73f35color.surface.canvas #0000005.724.5pass
    progress error bordererroruicolor.status.danger.border #e53935color.surface.canvas #0000004.973pass
    label on the canvastextcolor.text.bright #ffa2a7color.surface.canvas #00000010.984.5pass
    detail line on the canvastextcolor.text.muted #bd787dcolor.surface.canvas #0000006.154.5pass
    value fill against the trackuicolor.action.primary.bg #7d1310color.interaction.pressed.bg #420f0c1.513waived: the fill measures 1.51:1 against the track; the value is carried by the visible percentage text and the native value, and the track boundary (border.control, 4.45:1) marks the full extent
    stripes (decorative pattern)busyuicolor.action.primary.bg #7d1310color.interaction.pressed.bg #420f0c1.511pass
    error fill against the trackerroruicolor.status.danger.fill #dc282ecolor.interaction.pressed.bg #420f0c3.363pass
    radio-group default borderdefaultuicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    radio-group hover borderhoveruicolor.border.control #a3676bcolor.interaction.hover.bg #1c0a094.293pass
    radio-group focus-visible borderfocus-visibleuicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    radio-group focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.input #0000004.973pass
    radio-group checked textcheckedtextcolor.action.primary.text #f4eeeecolor.action.primary.bg #7d13109.284.5pass
    radio-group checked+focus-visible textchecked+focus-visibletextcolor.action.primary.text #f4eeeecolor.action.primary.bg #7d13109.284.5pass
    radio-group checked+focus-visible outlinechecked+focus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.action.primary.bg #7d13105.573pass
    radio-group invalid borderinvaliduicolor.status.danger.border #e53935color.surface.input #0000004.973pass
    radio-group required borderrequireduicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    option text on the panel surfacetextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    legend on the panel surfacetextcolor.text.bright #ffa2a7color.surface.default #100c0c10.174.5pass
    checked radio edge against the panel (the border stays border.control)checkeduicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    inner square on the hovered checked fillhoveruicolor.action.primary.text #f4eeeecolor.action.primary.hover-bg #9114107.923pass
    validation message on the panel surfacetextcolor.status.danger.text #f73f35color.surface.default #100c0c5.294.5pass
    disabled option text (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.surface.default #100c0c3.263pass
    disabled inner square (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.interaction.disabled.bg #160b0b3.243pass
    disabled border (exempt)disableduicolor.border.disabled #7d1310color.interaction.disabled.bg #160b0b1.821pass
    range default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    range default borderdefaultuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    Primary contenttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    Supporting contenttextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    Control boundaryuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    repeater default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    repeater default borderdefaultuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    Primary contenttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    Supporting contenttextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    Control boundaryuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    search-field default textdefaulttextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    search-field default borderdefaultuicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    search-field hover texthovertextcolor.text.default #e99499color.interaction.hover.bg #1c0a098.354.5pass
    search-field hover borderhoveruicolor.border.control #a3676bcolor.interaction.hover.bg #1c0a094.293pass
    search-field focus-visible textfocus-visibletextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    search-field focus-visible borderfocus-visibleuicolor.border.active #e53935color.surface.input #0000004.973pass
    search-field focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.input #0000004.973pass
    search-field placeholder-shown textplaceholder-showntextcolor.text.placeholder #a3676bcolor.surface.input #0000004.714.5pass
    search-field placeholder-shown borderplaceholder-shownuicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    search-field loading textloadingtextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    search-field loading borderloadinguicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    search-field no-results textno-resultstextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    search-field no-results borderno-resultsuicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    magnifier on the input surfaceuicolor.icon.default #e99499color.surface.input #0000009.163pass
    loading glyph and kbd hint on the input surfacetextcolor.text.muted #bd787dcolor.surface.input #0000006.154.5pass
    clear glyph on the input surfacetextcolor.action.tertiary.text #e99499color.surface.input #0000009.164.5pass
    clear glyph on its hover fillhovertextcolor.action.tertiary.text #e99499color.action.tertiary.hover-bg #1c0a098.354.5pass
    help and no-results status on the panel surfacetextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    kbd hint edge (decorative)uicolor.border.default #531310color.surface.input #0000001.471pass
    disabled text (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.interaction.disabled.bg #160b0b3.243pass
    disabled border (exempt)disableduicolor.border.disabled #7d1310color.interaction.disabled.bg #160b0b1.821pass
    segmented-control default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    segmented-control default borderdefaultuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    Primary contenttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    Supporting contenttextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    Control boundaryuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    select default textdefaulttextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    select default borderdefaultuicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    select hover texthovertextcolor.text.default #e99499color.interaction.hover.bg #1c0a098.354.5pass
    select hover borderhoveruicolor.border.control #a3676bcolor.interaction.hover.bg #1c0a094.293pass
    select focus-visible textfocus-visibletextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    select focus-visible borderfocus-visibleuicolor.border.active #e53935color.surface.input #0000004.973pass
    select focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.input #0000004.973pass
    select required textrequiredtextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    select required borderrequireduicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    select invalid textinvalidtextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    select invalid borderinvaliduicolor.status.danger.border #e53935color.surface.input #0000004.973pass
    select invalid+focus-visible textinvalid+focus-visibletextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    select invalid+focus-visible borderinvalid+focus-visibleuicolor.status.danger.border #e53935color.surface.input #0000004.973pass
    select invalid+focus-visible outlineinvalid+focus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.surface.input #00000010.983pass
    chevron on the input surfaceuicolor.icon.default #e99499color.surface.input #0000009.163pass
    option text in the themed listtextcolor.text.default #e99499color.surface.raised #160b0b8.434.5pass
    group label in the themed listtextcolor.text.muted #bd787dcolor.surface.raised #160b0b5.664.5pass
    selected optiontextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
    validation message on the panel surfacetextcolor.status.danger.text #f73f35color.surface.default #100c0c5.294.5pass
    help text on the panel surfacetextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    disabled text (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.interaction.disabled.bg #160b0b3.243pass
    disabled border (exempt)disableduicolor.border.disabled #7d1310color.interaction.disabled.bg #160b0b1.821pass
    settings-panel default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    settings-panel focus-visible textfocus-visibletextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    settings-panel focus-visible borderfocus-visibleuicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    settings-panel focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.input #0000004.973pass
    settings-panel invalid textinvalidtextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    settings-panel invalid borderinvaliduicolor.status.danger.border #e53935color.surface.input #0000004.973pass
    settings-panel busy textbusytextcolor.action.primary.text #f4eeeecolor.action.primary.bg #7d13109.284.5pass
    title, legend and the current section on the panel surfacetextcolor.text.bright #ffa2a7color.surface.default #100c0c10.174.5pass
    lead and help text on the panel surfacetextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    validation message on the panel surfaceinvalidtextcolor.status.danger.text #f73f35color.surface.default #100c0c5.294.5pass
    current-section indicator baruicolor.border.selected-indicator #e53935color.surface.default #100c0c4.603pass
    control boundaries on the panel surfaceuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    Reset button boundaryuicolor.action.secondary.border #a3676bcolor.surface.default #100c0c4.363pass
    panel edge (decorative)uicolor.border.default #531310color.surface.default #100c0c1.361pass
    sidebar, group and footer rules (decorative)uicolor.border.divider #2b0e0dcolor.surface.default #100c0c1.081pass
    sidebar-nav default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    sidebar-nav hover texthovertextcolor.text.default #e99499color.interaction.hover.bg #1c0a098.354.5pass
    sidebar-nav focus-visible textfocus-visibletextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    sidebar-nav focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.default #100c0c4.603pass
    sidebar-nav current textcurrenttextcolor.text.bright #ffa2a7color.surface.default #100c0c10.174.5pass
    sidebar-nav current bordercurrentuicolor.border.selected-indicator #e53935color.surface.default #100c0c4.603pass
    sidebar-nav selected textselectedtextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
    sidebar-nav selected+container-inactive textselected+container-inactivetextcolor.interaction.selection.inactive-text #e99499color.interaction.selection.inactive-bg #420f0c7.024.5pass
    sidebar-nav expanded textexpandedtextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    sidebar-nav collapsed textcollapsedtextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    ring on a selected item when focusedselecteduicolor.interaction.focus.ring-container #ffa2a7color.interaction.selection.bg #5313107.483pass
    group chevron (decorative; aria-expanded carries the state)uicolor.icon.decorative #a3676bcolor.surface.default #100c0c4.361pass
    rail edge (decorative)uicolor.border.divider #2b0e0dcolor.surface.default #100c0c1.081pass
    skeleton default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    skeleton default borderdefaultuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    Primary contenttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    Supporting contenttextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    Control boundaryuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    skip-link default textdefaulttextcolor.text.bright #ffa2a7color.surface.raised #160b0b10.104.5pass
    skip-link default borderdefaultuicolor.border.overlay #e53935color.surface.raised #160b0b4.573pass
    skip-link focus-visible textfocus-visibletextcolor.text.bright #ffa2a7color.surface.raised #160b0b10.104.5pass
    skip-link focus-visible borderfocus-visibleuicolor.border.overlay #e53935color.surface.raised #160b0b4.573pass
    skip-link focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.raised #160b0b4.573pass
    ring on the raised surfacefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.raised #160b0b4.573pass
    switch default borderdefaultuicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    switch hover borderhoveruicolor.border.control #a3676bcolor.interaction.hover.bg #1c0a094.293pass
    switch focus-visible borderfocus-visibleuicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    switch focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.input #0000004.973pass
    switch checked textcheckedtextcolor.action.primary.text #f4eeeecolor.action.primary.bg #7d13109.284.5pass
    switch checked+focus-visible textchecked+focus-visibletextcolor.action.primary.text #f4eeeecolor.action.primary.bg #7d13109.284.5pass
    switch checked+focus-visible outlinechecked+focus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.action.primary.bg #7d13105.573pass
    thumb on the off trackuicolor.text.default #e99499color.surface.input #0000009.163pass
    thumb on the hovered off trackhoveruicolor.text.default #e99499color.interaction.hover.bg #1c0a098.353pass
    thumb on the hovered on trackhoveruicolor.action.primary.text #f4eeeecolor.action.primary.hover-bg #9114107.923pass
    on track edge against the panel (the border stays border.control)checkeduicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    visible name on the panel surfacetextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    Off / On word on the panel surfacetextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    disabled thumb (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.interaction.disabled.bg #160b0b3.243pass
    disabled name (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.surface.default #100c0c3.263pass
    disabled border (exempt)disableduicolor.border.disabled #7d1310color.interaction.disabled.bg #160b0b1.821pass
    table default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    table hover texthovertextcolor.text.default #e99499color.interaction.hover.bg #1c0a098.354.5pass
    table selected textselectedtextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
    table selected+focus-visible textselected+focus-visibletextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
    table selected+focus-visible outlineselected+focus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.interaction.selection.bg #5313107.483pass
    table selected+container-inactive textselected+container-inactivetextcolor.interaction.selection.inactive-text #e99499color.interaction.selection.inactive-bg #420f0c7.024.5pass
    table sorted textsortedtextcolor.text.bright #ffa2a7color.surface.default #100c0c10.174.5pass
    table empty textemptytextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    table loading textloadingtextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    header texttextcolor.text.bright #ffa2a7color.surface.default #100c0c10.174.5pass
    sticky header text on the raised surfacetextcolor.text.bright #ffa2a7color.surface.raised #160b0b10.104.5pass
    captiontextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    ring on a sort buttonuicolor.interaction.focus.ring #e53935color.surface.default #100c0c4.603pass
    header rule (decorative; thead carries the structure)uicolor.border.strong #9e231fcolor.surface.default #100c0c2.511pass
    row divider (decorative)uicolor.border.divider #2b0e0dcolor.surface.default #100c0c1.081pass
    tabs default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    tabs hover texthovertextcolor.text.default #e99499color.interaction.hover.bg #1c0a098.354.5pass
    tabs focus-visible textfocus-visibletextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    tabs focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.default #100c0c4.603pass
    tabs selected textselectedtextcolor.text.bright #ffa2a7color.surface.default #100c0c10.174.5pass
    tabs selected borderselecteduicolor.border.selected-indicator #e53935color.surface.default #100c0c4.603pass
    tabs selected+focus-visible textselected+focus-visibletextcolor.text.bright #ffa2a7color.surface.default #100c0c10.174.5pass
    tabs selected+focus-visible borderselected+focus-visibleuicolor.border.selected-indicator #e53935color.surface.default #100c0c4.603pass
    tabs selected+focus-visible outlineselected+focus-visibleuicolor.interaction.focus.ring #e53935color.surface.default #100c0c4.603pass
    tabs selected+container-inactive textselected+container-inactivetextcolor.text.bright #ffa2a7color.surface.default #100c0c10.174.5pass
    inactive indicator (decorative; the selected tab keeps aria-selected and bright text)selected+container-inactiveuicolor.border.selected-indicator-inactive #9e231fcolor.surface.default #100c0c2.511pass
    disabled tab text (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.surface.default #100c0c3.263pass
    tablist bottom rule (decorative)uicolor.border.divider #2b0e0dcolor.surface.default #100c0c1.081pass
    terminal default textdefaulttextcolor.terminal.fg #e99499color.terminal.bg #0c09098.654.5pass
    terminal default borderdefaultuicolor.border.control #a3676bcolor.terminal.bg #0c09094.453pass
    terminal focus-visible textfocus-visibletextcolor.terminal.fg #e99499color.terminal.bg #0c09098.654.5pass
    terminal focus-visible outlinefocus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.terminal.bg #0c090910.373pass
    terminal selected textselectedtextcolor.terminal.selection-text #f4eeeecolor.terminal.selection-bg #9114107.924.5pass
    terminal busy textbusytextcolor.terminal.bg #0c0909color.terminal.cursor #e994998.654.5pass
    terminal current textcurrenttextcolor.terminal.fg #e99499color.code.current-line #1c0a098.354.5pass
    hollow cursor outline at restuicolor.terminal.cursor #e99499color.terminal.bg #0c09098.653pass
    cursor on the cursor linecurrentuicolor.terminal.cursor #e99499color.code.current-line #1c0a098.353pass
    prompt segment text on slot 4textcolor.terminal.selection-text #f4eeeecolor.terminal.ansi.4 #8c12128.284.5pass
    branch segment text on slot 3textcolor.terminal.bg #0c0909color.terminal.ansi.3 #d4868b7.164.5pass
    prompt arrow (the segment's own colour, decorative)uicolor.terminal.ansi.4 #8c1212color.terminal.bg #0c09092.091pass
    dim text and grid labelstextcolor.text.muted #bd787dcolor.terminal.bg #0c09095.814.5pass
    inverse texttextcolor.terminal.bg #0c0909color.terminal.fg #e994998.654.5pass
    slot 2textcolor.terminal.ansi.2 #bd787dcolor.terminal.bg #0c09095.814.5pass
    slot 3textcolor.terminal.ansi.3 #d4868bcolor.terminal.bg #0c09097.164.5pass
    slot 5textcolor.terminal.ansi.5 #f73f35color.terminal.bg #0c09095.404.5pass
    slot 7textcolor.terminal.ansi.7 #ffa2a7color.terminal.bg #0c090910.374.5pass
    slot 11textcolor.terminal.ansi.11 #b37175color.terminal.bg #0c09095.234.5pass
    slot 1 (3.42:1)textcolor.terminal.ansi.1 #c81a1acolor.terminal.bg #0c09093.424.5waived: heritage slot; documented as failing, programs choose slot semantics
    slot 4 (2.09:1)textcolor.terminal.ansi.4 #8c1212color.terminal.bg #0c09092.094.5waived: heritage slot; documented as failing, programs choose slot semantics
    slot 6 (3.26:1)textcolor.terminal.ansi.6 #9e474acolor.terminal.bg #0c09093.264.5waived: heritage slot; documented as failing, programs choose slot semantics
    slot 8 (1.86:1)textcolor.terminal.ansi.8 #7d1310color.terminal.bg #0c09091.864.5waived: heritage slot; documented as failing, programs choose slot semantics
    slot 9 (2.70:1)textcolor.terminal.ansi.9 #ab1612color.terminal.bg #0c09092.704.5waived: heritage slot; documented as failing, programs choose slot semantics
    slot 10 (2.92:1)textcolor.terminal.ansi.10 #ad2721color.terminal.bg #0c09092.924.5waived: heritage slot; documented as failing, programs choose slot semantics
    slot 12 (2.12:1)textcolor.terminal.ansi.12 #871f19color.terminal.bg #0c09092.124.5waived: heritage slot; documented as failing, programs choose slot semantics
    slot 13 (4.43:1)textcolor.terminal.ansi.13 #e82132color.terminal.bg #0c09094.434.5waived: heritage slot; documented as failing, programs choose slot semantics
    slot 14 (4.28:1)textcolor.terminal.ansi.14 #e0292fcolor.terminal.bg #0c09094.284.5waived: heritage slot; documented as failing, programs choose slot semantics
    slot 15 (4.45:1; not in the foundations list)textcolor.terminal.ansi.15 #a3676bcolor.terminal.bg #0c09094.454.5waived: heritage slot; documented as failing, programs choose slot semantics
    slot 0 (1.00:1; it is the background)textcolor.terminal.ansi.0 #0c0909color.terminal.bg #0c09091.004.5waived: heritage slot; slot 0 is the terminal background and is never a foreground on it
    text-field default textdefaulttextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    text-field default borderdefaultuicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    text-field hover texthovertextcolor.text.default #e99499color.interaction.hover.bg #1c0a098.354.5pass
    text-field hover borderhoveruicolor.border.control #a3676bcolor.interaction.hover.bg #1c0a094.293pass
    text-field focus-visible textfocus-visibletextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    text-field focus-visible borderfocus-visibleuicolor.border.active #e53935color.surface.input #0000004.973pass
    text-field focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.input #0000004.973pass
    text-field placeholder-shown textplaceholder-showntextcolor.text.placeholder #a3676bcolor.surface.input #0000004.714.5pass
    text-field placeholder-shown borderplaceholder-shownuicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    text-field invalid textinvalidtextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    text-field invalid borderinvaliduicolor.status.danger.border #e53935color.surface.input #0000004.973pass
    text-field invalid+focus-visible textinvalid+focus-visibletextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    text-field invalid+focus-visible borderinvalid+focus-visibleuicolor.status.danger.border #e53935color.surface.input #0000004.973pass
    text-field invalid+focus-visible outlineinvalid+focus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.surface.input #00000010.983pass
    text-field read-only textread-onlytextcolor.text.default #e99499color.surface.canvas #0000009.164.5pass
    validation message on the panel surfacetextcolor.status.danger.text #f73f35color.surface.default #100c0c5.294.5pass
    help text on the panel surfacetextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    disabled text (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.interaction.disabled.bg #160b0b3.243pass
    disabled border (exempt)disableduicolor.border.disabled #7d1310color.interaction.disabled.bg #160b0b1.821pass
    read-only bottom edge (decorative; the field has no box)read-onlyuicolor.border.divider #2b0e0dcolor.surface.canvas #0000001.171pass
    textarea default textdefaulttextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    textarea default borderdefaultuicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    textarea hover texthovertextcolor.text.default #e99499color.interaction.hover.bg #1c0a098.354.5pass
    textarea hover borderhoveruicolor.border.control #a3676bcolor.interaction.hover.bg #1c0a094.293pass
    textarea focus-visible textfocus-visibletextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    textarea focus-visible borderfocus-visibleuicolor.border.active #e53935color.surface.input #0000004.973pass
    textarea focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.input #0000004.973pass
    textarea placeholder-shown textplaceholder-showntextcolor.text.placeholder #a3676bcolor.surface.input #0000004.714.5pass
    textarea placeholder-shown borderplaceholder-shownuicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    textarea invalid textinvalidtextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    textarea invalid borderinvaliduicolor.status.danger.border #e53935color.surface.input #0000004.973pass
    textarea invalid+focus-visible textinvalid+focus-visibletextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    textarea invalid+focus-visible borderinvalid+focus-visibleuicolor.status.danger.border #e53935color.surface.input #0000004.973pass
    textarea invalid+focus-visible outlineinvalid+focus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.surface.input #00000010.983pass
    textarea read-only textread-onlytextcolor.text.default #e99499color.surface.canvas #0000009.164.5pass
    validation message on the panel surfacetextcolor.status.danger.text #f73f35color.surface.default #100c0c5.294.5pass
    help and count on the panel surfacetextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    disabled text (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.interaction.disabled.bg #160b0b3.243pass
    disabled border (exempt)disableduicolor.border.disabled #7d1310color.interaction.disabled.bg #160b0b1.821pass
    read-only bottom edge (decorative; the field has no box)read-onlyuicolor.border.divider #2b0e0dcolor.surface.canvas #0000001.171pass
    time-picker default textdefaulttextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    time-picker default borderdefaultuicolor.border.control #a3676bcolor.surface.input #0000004.713pass
    time-picker hover texthovertextcolor.text.default #e99499color.interaction.hover.bg #1c0a098.354.5pass
    time-picker hover borderhoveruicolor.border.control #a3676bcolor.interaction.hover.bg #1c0a094.293pass
    time-picker focus-visible textfocus-visibletextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    time-picker focus-visible borderfocus-visibleuicolor.border.active #e53935color.surface.input #0000004.973pass
    time-picker focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.input #0000004.973pass
    time-picker invalid textinvalidtextcolor.text.default #e99499color.surface.input #0000009.164.5pass
    time-picker invalid borderinvaliduicolor.status.danger.border #e53935color.surface.input #0000004.973pass
    validation message on the canvastextcolor.status.danger.text #f73f35color.surface.canvas #0000005.724.5pass
    help text on the canvastextcolor.text.muted #bd787dcolor.surface.canvas #0000006.154.5pass
    disabled text (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.interaction.disabled.bg #160b0b3.243pass
    disabled border (exempt)disableduicolor.border.disabled #7d1310color.interaction.disabled.bg #160b0b1.821pass
    timeline default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    timeline default borderdefaultuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    Primary contenttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    Supporting contenttextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    Control boundaryuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    toast default textdefaulttextcolor.text.default #e99499color.surface.canvas #0000009.164.5pass
    toast default borderdefaultuicolor.border.overlay #e53935color.surface.canvas #0000004.973pass
    toast hover texthovertextcolor.text.link-hover #f4eeeecolor.interaction.hover.bg-strong #630f0d11.414.5pass
    toast focus-visible textfocus-visibletextcolor.action.tertiary.text #e99499color.surface.canvas #0000009.164.5pass
    toast focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.canvas #0000004.973pass
    toast stacked textstackedtextcolor.text.muted #bd787dcolor.surface.canvas #0000006.154.5pass
    toast stacked borderstackeduicolor.border.overlay #e53935color.surface.canvas #0000004.973pass
    toast reduced-motion textreduced-motiontextcolor.text.default #e99499color.surface.canvas #0000009.164.5pass
    toast reduced-motion borderreduced-motionuicolor.border.overlay #e53935color.surface.canvas #0000004.973pass
    glyph on the plain toasttextcolor.status.info.text #7e9ebbcolor.surface.canvas #0000007.504.5pass
    action text on the plain toasttextcolor.text.link #f73f35color.surface.canvas #0000005.724.5pass
    warning glyph on its tinttextcolor.status.warning.text #c9973fcolor.status.warning.tint #1f1a0c6.594.5pass
    warning border on its tintuicolor.status.warning.border #c9973fcolor.status.warning.tint #1f1a0c6.593pass
    text on the warning tinttextcolor.text.default #e99499color.status.warning.tint #1f1a0c7.564.5pass
    success glyph on its tinttextcolor.status.success.text #86a46fcolor.status.success.tint #0f1a0e6.434.5pass
    success border on its tintuicolor.status.success.border #86a46fcolor.status.success.tint #0f1a0e6.433pass
    text on the success tinttextcolor.text.default #e99499color.status.success.tint #0f1a0e7.804.5pass
    info glyph on its tinttextcolor.status.info.text #7e9ebbcolor.status.info.tint #0f141c6.594.5pass
    info border on its tintuicolor.status.info.border #7e9ebbcolor.status.info.tint #0f141c6.593pass
    text on the info tinttextcolor.text.default #e99499color.status.info.tint #0f141c8.064.5pass
    neutral glyph on its tinttextcolor.status.neutral.text #bd787dcolor.status.neutral.tint #2410105.314.5pass
    neutral border on its tintuicolor.status.neutral.border #a3676bcolor.status.neutral.tint #2410104.073pass
    text on the neutral tinttextcolor.text.default #e99499color.status.neutral.tint #2410107.924.5pass
    text, glyph and buttons on the danger filltextcolor.status.danger.on-fill #f9faf9color.status.danger.fill #dc282e4.584.5pass
    the danger fill is its own boundary against the canvasuicolor.status.danger.fill #dc282ecolor.surface.canvas #0000004.393pass
    danger border on the danger fill (decorative)uicolor.status.danger.border #e53935color.status.danger.fill #dc282e1.131pass
    toolbar default textdefaulttextcolor.text.default #e99499color.surface.chrome #0907078.774.5pass
    toolbar hover texthovertextcolor.text.default #e99499color.interaction.hover.bg #1c0a098.354.5pass
    toolbar focus-visible textfocus-visibletextcolor.text.default #e99499color.surface.chrome #0907078.774.5pass
    toolbar focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.chrome #0907074.753pass
    toolbar toggled texttoggledtextcolor.text.bright #ffa2a7color.interaction.pressed.bg #420f0c8.414.5pass
    toolbar toggled bordertoggleduicolor.border.active #e53935color.interaction.pressed.bg #420f0c3.813pass
    disabled button text (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.surface.chrome #0907073.373pass
    separator (decorative; role separator carries the grouping)uicolor.border.default #531310color.surface.chrome #0907071.411pass
    toolbar bottom edge (decorative)uicolor.border.divider #2b0e0dcolor.surface.chrome #0907071.121pass
    tooltip default textdefaulttextcolor.text.default #e99499color.surface.raised #160b0b8.434.5pass
    tooltip default borderdefaultuicolor.border.overlay #e53935color.surface.raised #160b0b4.573pass
    tooltip hover texthovertextcolor.action.tertiary.text #e99499color.action.tertiary.hover-bg #1c0a098.354.5pass
    tooltip focus-visible textfocus-visibletextcolor.action.tertiary.text #e99499color.surface.canvas #0000009.164.5pass
    tooltip focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.canvas #0000004.973pass
    tooltip open textopentextcolor.text.default #e99499color.surface.raised #160b0b8.434.5pass
    tooltip open borderopenuicolor.border.overlay #e53935color.surface.raised #160b0b4.573pass
    shortcut on the tooltiptextcolor.text.bright #ffa2a7color.surface.raised #160b0b10.104.5pass
    shortcut key border on the tooltipuicolor.border.control #a3676bcolor.surface.raised #160b0b4.333pass
    trigger text on the canvastextcolor.action.tertiary.text #e99499color.surface.canvas #0000009.164.5pass
    tree default textdefaulttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    tree default borderdefaultuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    Primary contenttextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    Supporting contenttextcolor.text.muted #bd787dcolor.surface.default #100c0c5.694.5pass
    Control boundaryuicolor.border.control #a3676bcolor.surface.default #100c0c4.363pass
    wizard default textdefaulttextcolor.text.default #e99499color.surface.canvas #0000009.164.5pass
    wizard hover texthovertextcolor.text.default #e99499color.interaction.hover.bg #1c0a098.354.5pass
    wizard focus-visible textfocus-visibletextcolor.text.bright #ffa2a7color.surface.canvas #00000010.984.5pass
    wizard focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.canvas #0000004.973pass
    wizard current textcurrenttextcolor.text.bright #ffa2a7color.surface.canvas #00000010.984.5pass
    wizard current bordercurrentuicolor.border.selected-indicator #e53935color.surface.canvas #0000004.973pass
    wizard invalid textinvalidtextcolor.status.danger.text #f73f35color.surface.canvas #0000005.724.5pass
    wizard invalid borderinvaliduicolor.status.danger.border #e53935color.surface.canvas #0000004.973pass
    wizard busy textbusytextcolor.action.primary.text #f4eeeecolor.action.primary.bg #7d13109.284.5pass
    complete marker on the canvastextcolor.status.success.text #86a46fcolor.surface.canvas #0000007.554.5pass
    panel title on the panel surfacetextcolor.text.bright #ffa2a7color.surface.default #100c0c10.174.5pass
    panel text on the panel surfacetextcolor.text.default #e99499color.surface.default #100c0c8.484.5pass
    step message on the panel surfacetextcolor.status.danger.text #f73f35color.surface.default #100c0c5.294.5pass
    panel edge (decorative)uicolor.border.default #531310color.surface.canvas #0000001.471pass
    back button texttextcolor.action.secondary.text #ffa2a7color.surface.canvas #00000010.984.5pass
    back button boundaryuicolor.action.secondary.border #a3676bcolor.surface.canvas #0000004.713pass
    next button boundaryuicolor.action.primary.border #9e231fcolor.surface.canvas #0000002.713waived: the primary button is identified by its text at 9.28:1 on its fill and by its position; the fill measures 1.86:1 and its border 2.56:1 against the canvas, a documented property of the actions family, not of the wizard
    ring on the next button's fillfocus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.action.primary.bg #7d13105.573pass
    future step text (exempt; house floor 3:1)disableduicolor.text.disabled #8a5559color.surface.canvas #0000003.523pass

    Portability

    How the theme travels to other applications and frameworks, what a port must reproduce, what it may declare unsupported, and how support is catalogued truthfully.

    Scope of a port

    A port themes only what the host documents as customisable. Editor colouring, application chrome, terminal colours and plugin surfaces are separate scopes; a file that changes one does not claim the others. A port never patches binaries, injects unsupported hacks, overwrites a user’s whole settings file or replaces keybindings, credentials or unrelated preferences. It installs under a unique name beside the host’s defaults and documents how to roll back.

    What every port must reproduce

    1. The surface ladder: canvas, default, raised, overlay, input.
    2. The text ladder: default, bright, prose, muted, subtle, disabled.
    3. Focus as a ring distinct from selection as a fill, with the ring recoloured on fills.
    4. Selection, inactive selection and hover as three distinguishable fills.
    5. The status hues with their glyphs where the host renders glyphs.
    6. Zero radii and 1px borders where the host allows geometry; otherwise a recorded deviation.
    7. The monospace family by name, honouring the user’s size.

    Every required role is mapped, explicitly inherited from the host, marked unsupported with an explanation, or intentionally out of scope. A percentage of coverage is meaningful only with its denominator.

    Fallbacks by host capability

    Host capabilityFallback
    No dashed outlines (many native toolkits)solid 1px ring in focus.ring; record the deviation
    No separate inactive selectionselection fill everywhere; record it
    No read-only styling hooktreat as default text with a dotted bottom edge if borders are available, else as default
    No pattern fills (charts)keep the glyph or label channel; never colour alone
    Sixteen-colour terminalheritage-ansi for fidelity or the extended slots when approved; document bold-as-bright and whether 256/24-bit colours bypass the slots
    Fixed radii in the hostdocument; do not fight the toolkit
    Host forbids removing its focus indicatorkeep the host’s indicator; never draw two

    Web consumers

    The site’s exports/tokens.css exposes every role as a custom property. Consume roles (--color-text-default), never primitives. A framework integration maps roles onto the framework’s theme keys and lists what it cannot express; agents/consume.md gives the reading order and the deviation report format, and theme.lock.json pins the revision.

    Native ports (future)

    A port lives at ports/<slug>/ with port.json, mapping.json, src/, dist/ and evidence/, created from templates/port/ only when work begins. Statuses are experimental, verified and deprecated; reference implementations and roadmap candidates are not statuses. verified requires a real import into the recorded application version with matching evidence and a token digest equal to the current default profile. A successful XML or JSON parse is a structural pass, not verification. Never hand-edit a generated hex; fix the mapping or the approved token and regenerate.

    For JetBrains, an editor scheme (.icls) and a UI theme plugin are separate capabilities; the scheme alone does not recolour toolbars or dialogs. For Notepad++, a style-theme XML, the dark-mode chrome setting and User Defined Languages are three mechanisms. Consult the vendor documentation for the tested version before mapping.

    The reference implementation

    j3w1/j3w1.github.io is the flagship web implementation and the source of the observed values. It is not an upstream that this repository scrapes at build time, and there is no automatic synchronisation in either direction. A later integration pins a release of this theme in that site through a separate reviewed change and records its own site-specific values (window-manager geometry, wallpaper gradients) as such.

    Application ports

    Explore capabilities and semantic mappings

    No native ports are published yet. Historical implementations are catalogued under References and are not supported downloads.

    Coverage ledger

    Specified: spec/components/<id>.md validates. Demonstrated: <id>.demo.html exists with a fragment for every declared variant and renders on the site. Test implemented: tests/browser/components/<id>.spec.js exists; does not establish a pass. Computed from the sources, never declared.

    Execution results are separate: verification summaries and full matrix. Missing browser or manual evidence is not run.

    FamilyTotalSpecifiedDemonstratedTest implemented
    composed6660
    feedback1111111
    display1111111
    navigation1010102
    actions5552
    forms-basic1111114
    developer5550
    forms-advanced8881
    ComponentFamilyPrioritySpecifiedDemonstratedTest implemented
    admin-form · evidencecomposedR1yesyes
    alert · evidencefeedbackR1yesyes
    avatar · evidencedisplayR2yesyes
    badge · evidencedisplayR1yesyes
    breadcrumbs · evidencenavigationR1yesyes
    button-group · evidenceactionsR2yesyes
    button · evidenceactionsR1yesyesyes
    card · evidencedisplayR1yesyes
    chart · evidencedisplayR2yesyes
    checkbox · evidenceforms-basicR1yesyesyes
    chip · evidencedisplayR1yesyes
    code-editor · evidencedeveloperR1yesyes
    combobox · evidenceforms-advancedR1yesyes
    command-palette · evidencenavigationR2yesyes
    compact-dashboard · evidencecomposedR2yesyes
    data-table · evidencedisplayR1yesyes
    date-picker · evidenceforms-advancedR1yesyes
    description-list · evidencedisplayR2yesyes
    diagnostics · evidencedeveloperR1yesyes
    dialog · evidencefeedbackR1yesyesyes
    diff-view · evidencedeveloperR1yesyes
    disclosure · evidencenavigationR2yesyes
    drawer · evidencefeedbackR1yesyes
    editor-search · evidencedeveloperR2yesyes
    empty-state · evidencefeedbackR1yesyes
    error-state · evidencefeedbackR2yesyes
    field · evidenceforms-basicR1yesyes
    fieldset · evidenceforms-basicR1yesyes
    file-browser · evidencecomposedR2yesyes
    file-input · evidenceforms-advancedR1yesyes
    filterable-table · evidencecomposedR1yesyes
    form-builder · evidenceforms-advancedLyesyesyes
    i3-window-frame · evidencecomposedR1yesyes
    icon-button · evidenceactionsR1yesyes
    kbd · evidencedisplayR2yesyes
    link · evidenceactionsR1yesyesyes
    list · evidencedisplayR1yesyes
    loading-indicator · evidencefeedbackR1yesyes
    menu · evidencenavigationR1yesyesyes
    multiselect · evidenceforms-advancedR2yesyes
    number-field · evidenceforms-basicR1yesyes
    pagination · evidencenavigationR1yesyes
    popover · evidencefeedbackR2yesyes
    progress · evidencefeedbackR1yesyes
    radio-group · evidenceforms-basicR1yesyesyes
    range · evidenceforms-basicR2yesyes
    repeater · evidenceforms-advancedR2yesyes
    search-field · evidenceforms-basicR1yesyes
    segmented-control · evidenceactionsR2yesyes
    select · evidenceforms-basicR1yesyesyes
    settings-panel · evidencecomposedR1yesyes
    sidebar-nav · evidencenavigationR1yesyes
    skeleton · evidencefeedbackR2yesyes
    skip-link · evidencenavigationR1yesyes
    switch · evidenceforms-basicR1yesyes
    table · evidencedisplayR1yesyesyes
    tabs · evidencenavigationR1yesyesyes
    terminal · evidencedeveloperR1yesyes
    text-field · evidenceforms-basicR1yesyesyes
    textarea · evidenceforms-basicR1yesyes
    time-picker · evidenceforms-advancedR1yesyes
    timeline · evidencedisplayR2yesyes
    toast · evidencefeedbackR1yesyes
    toolbar · evidencenavigationR1yesyes
    tooltip · evidencefeedbackR1yesyes
    tree · evidencenavigationR2yesyes
    wizard · evidenceforms-advancedR1yesyes

    References

    Where the values came from and what each reference does not prove. Nothing here is a supported download.

    ReferenceKindWhereWhat it does not prove
    j3w1.github.io site.css — the flagship web implementationreference-implementationj3w1/j3w1.github.io@ffa8122 assets/css/site.cssThe :root block (lines 78–136) is the observed source of every role value. It will become a pinned consumer of this theme through a separate reviewed change; there is no live import.
    j3w1.github.io accessibility contract (contrast floor, reduced motion, focus)reference-implementationj3w1/j3w1.github.io@ffa8122 docs/wm-accessibility.mdSection 9 measured the palette and restricted --quiet and --inactive; this specification extends those rules (D-003).
    Xresources — the canonical sixteen-slot palette with the author's slot annotationshistoricalj3w1/1w3j@9841315 config/XresourcesExact values are preserved as color.primitive.ansi.*; the annotations seed the syntax roles. A 2020–21 X11 configuration proves nothing about current desktop installations.
    i3-gaps configuration — borders, gaps, bar and client colourshistoricalj3w1/1w3j@9841315 config/i3/configSource of the 1px borders, 14/−2 gaps and the focused/urgent colour classes. Window-manager geometry is reference metrics, not a cross-application rule.
    i3status colours — good, bad and degraded inside the same huehistoricalj3w1/1w3j@9841315 config/i3/i3status.confA historical status semantic (#FFA2A7 / #A3676B / #C81A1A). Superseded for new work by D-001.
    dunst notification colourshistoricalj3w1/1w3j@9841315 config/config/dunst/dunstrcOrigin of the toast roles and the critical pair #DC282E / #F9FAF9 (4.58:1).
    dmenu colourshistoricalj3w1/1w3j@9841315 config/dmenurcOrigin of the dark selection #630F0D.
    gedit GtkSourceView scheme '1w3j' — a Solarized structure filled with redshistoricalj3w1/1w3j@9841315 config/config/gedit/styles/1w3j.xmlAn early editor port by the owner. Not a supported download; values predate the token set.
    IntelliJ colour scheme '1w3j theme' (2020–21, Material Darker base, red chrome and console)historicalj3w1/1w3j@9841315 config/intellij/config/colors/1w3j-theme.iclsOnly chrome, console, gutter and selection were recoloured; syntax stayed stock. Evidence that a JetBrains port has precedent, not a port.
    tmux status colours (pywal-cache variant)historicalj3w1/1w3j@9841315 config/tmux.conf.localUses the non-canonical #0C0A09 / #D09899 variant; catalogued to explain why those values are not tokens.
    pywal-generated ramp (scripts/colors.sh)historicalj3w1/1w3j@9841315 scripts/colors.shThe machine-generated predecessor of the hand-tuned Xresources palette. Not normative.

    For agents

    Do not read this page. Pin a tag or commit and fetch the exports at that revision; the site is confirmation only.

    Consuming j3w1/theme (for agents and integrators)

    This document is for people and agents applying the theme to another project. The contributor workflow for this repository is in AGENTS.md and is not repeated here.

    You are consuming design data and optional official implementations. The consumer project’s own instructions (its AGENTS.md, CLAUDE.md, security, architecture and operational rules) always take precedence over anything in this repository.

    Official web implementations

    For compatible web apps, prefer the exact @j3w1/ui package. Complete copy bundles are also supported. Read packages/ui/dist/index.json at your immutable revision, then selected contracts/<id>.json and examples/<id>.json files. The installed CLI prepares a bounded task:

    j3w1-ui kit --components text-field,button,dialog --framework vue --mode package --out ./j3w1-task

    Choose copy for complete source ownership or mapping for an incompatible host. Native hosts require mapping mode. Kits include canonical contracts, dependency closure and shared accessibility/identity rules; they do not declare your application verified. Follow docs/ui-consumption.md for exact installation, framework binding and runtime checks. npm publication is an owner release action; use the release tarball and its published integrity metadata before publication. Keep the existing lock and deviation workflow below for canonical mappings.

    0. Pin a revision first

    <rev> is a release tag (v0.1.0) or a full 40-character commit SHA. Never main, never a branch name, never “latest”. Resolve a tag to its commit before reading anything, and use the same <rev> in every URL below. Mixing revisions is a contract violation.

    GET https://api.github.com/repos/j3w1/theme/git/ref/tags/<tag>   → object.sha
    git ls-remote https://github.com/j3w1/theme refs/tags/<tag>

    1. Read the manifest

    https://raw.githubusercontent.com/j3w1/theme/<rev>/theme.json

    Take version, profiles, exports.canonicalForAgents and exports.digests.

    2. Read this document at the same revision

    https://raw.githubusercontent.com/j3w1/theme/<rev>/agents/consume.md

    If the copy you are reading came from a different revision, fetch it again.

    3. Pick a profile

    Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens.

    The policy block is generated. Pending decision IDs are available in each resolved token’s eligibility.decisionIds, including alias dependencies. Report those IDs alongside any actual deviations; using an authorized pending value is a disclosure, not an invented substitution. No replacement is implied by a blocked action. A profile preview does not authorize delivered work.

    4. Read only what you need, in this order

    https://raw.githubusercontent.com/j3w1/theme/<rev>/exports/theme.compact.md
    https://raw.githubusercontent.com/j3w1/theme/<rev>/exports/components/<id>.json      one per component you implement
    https://raw.githubusercontent.com/j3w1/theme/<rev>/exports/tokens.resolved.json      only for aliases the component JSON does not inline
    https://raw.githubusercontent.com/j3w1/theme/<rev>/exports/digests.json              to record what you used

    Optional: exports/theme.full.md for the whole specification; exports/tokens.css for a ready-made custom-property sheet. The website https://j3w1.github.io/theme/ is for visual confirmation only. It is not a source of values, and screenshots never override tokens.

    5. Inspect the target before changing anything

    Name the integration kind: css-vars, vuetify, tailwind, jetbrains-icls, gtk-css, terminal-16 or other. List which specified surfaces the target can express natively and which it cannot (for example a framework with no read-only field style, or a sixteen-colour terminal that cannot carry hover). Anything the target cannot express becomes a documented deviation in step 7, never an invented approximation.

    6. Implement the mapping

    • Map roles to the target’s native keys using only resolved token values.
    • Do not restyle anything the requester did not name.
    • Do not change behaviour, markup semantics, focus order or keyboard handling except where a component’s keyboard or aria section requires it and the host allows it.
    • Keep host accessibility at least as strong as before: never remove a focus indicator, never lower a contrast ratio the host already met, never set outline: none without drawing the specified ring.
    • Radii are 0, borders 1px, the family is monospace. A host that forbids one of these produces a deviation, not a redesign.
    • Selection is a fill; focus is a ring; on fills the ring takes the on-fill text colour. Status roles keep their glyphs.

    7. Validate and report

    Check computed values against the component JSON for every declared state. Write the deviation report (below) into the pull request or commit body and write theme.lock.json (below) at the consumer’s chosen path.

    What you may not do

    • Invent, blend, lighten, darken or “harmonise” colours. Only resolved values.
    • Use a blocked value, deliver a proposed profile, or omit the required pending-decision disclosures. Historical-only values are not approved UI roles.
    • Derive values from the site’s HTML, from screenshots or from memory.
    • Touch unrelated components, layouts, copy, dependencies or build configuration.
    • Weaken the host’s accessibility, security or architecture rules.
    • Treat this file as authority over the consumer repository’s own agent instructions.
    • Claim “verified”. Consumers report “implemented” plus deviations; only this repository’s evidence records use the word verified.

    Deviation report format

    ## j3w1/theme deviation report
    theme: j3w1-theme <version> @ <commit> (<tag or "commit">) profile=<profile>
    integration: <kind> (<host framework and version>)
    implemented: <component-id> (<n>/<m> states); ...
    unsupported surfaces:
    - <spec surface or host surface> — <why the target cannot express it>
    deviations:
    | component | state / property | spec value | applied | reason | kind |
    | --- | --- | --- | --- | --- | --- |
    host rules that took precedence: <list or "none">
    lock: <path to theme.lock.json>

    kind is one of unsupported (the target cannot express it), substituted (the nearest native equivalent, with a value taken from the token set, never invented), omitted (the requester excluded it) or host-rule (a consumer instruction won).

    theme.lock.json

    Minimal, committed next to the integration code, validated by schemas/json/theme.lock.schema.json. Not a package manager: no graph, no install, no auto-update. Updating the theme means changing ref, revision, version and exports, re-running the consumer’s own checks and re-emitting the deviations.

    {
      "schemaVersion": 1,
      "theme": "j3w1-theme",
      "version": "0.1.0",
      "ref": "v0.1.0",
      "revision": "0123456789abcdef0123456789abcdef01234567",
      "profile": "default",
      "integration": { "id": "my-app-css-vars", "version": "1", "kind": "css-vars" },
      "resolvedAt": "2026-10-01T12:00:00Z",
      "exports": {
        "exports/theme.compact.md": "sha256-…",
        "exports/tokens.resolved.json": "sha256-…",
        "exports/components/text-field.json": "sha256-…"
      },
      "components": ["text-field"],
      "deviations": [
        {
          "component": "text-field",
          "target": "read-only",
          "kind": "unsupported",
          "specValue": "color.border.divider dotted bottom edge",
          "applied": null,
          "reason": "The host renders read-only as disabled; no separate style hook."
        }
      ]
    }

    revision is always the full commit even when ref is a tag; exports keys are the repository-relative paths listed in exports/digests.json for exactly the files you read; deviations may be empty but must be present.

    The short prompt

    Once a consumer project points its own agent instructions at this document and records a pinned revision, the everyday request can be:

    Implement this interface using j3w1/theme’s approved default profile.

    Without that setup, say it in full:

    Implement this interface using j3w1/theme. Resolve and record a theme revision, follow agents/consume.md, use the approved default profile, and read the relevant component specifications. Preserve this project’s behaviour and framework; report unsupported mappings and deviations.

    Decision log

    Numbered design and governance decisions. A token or rule is approved only through an accepted entry here.

    Statuses: proposed (awaiting the owner), accepted, rejected, superseded. A token moves from proposed to approved only by an accepted decision referenced in its $extensions["io.github.j3w1.theme"].approval.decision. Agents may open proposed entries; only the owner changes a status.

    #TitleStatusDateDecided by
    D-000Responsibility split: tokens, spec, ports, evidenceaccepted2026-09-05owner (design package)
    D-001Controlled three-hue extension for status, diagnostics and diffsaccepted2026-09-06owner
    D-002v0.1.0 ships the full R1 component inventoryaccepted2026-09-06owner
    D-003Text-role corrections with new in-hue valuesaccepted2026-09-06owner
    D-004Public repository; MIT code, CC BY 4.0 proseaccepted2026-09-06owner
    D-005Default profile id is defaultproposed2026-09-06
    D-006Focus-ring rule, including invalid + focusproposed2026-09-06
    D-007border.control uses #A3676Bproposed2026-09-06
    D-008Fold site hairlines into border.divider; surface.sunken; unified overlay borderproposed2026-09-06
    D-009Density modes compact and comfortable as tokensproposed2026-09-06
    D-010The site deploys from mainproposed2026-09-06
    D-011Reference screenshots are cropped before publicationproposed2026-09-06
    D-012Exports are committed and drift-checkedproposed2026-09-06
    D-015Clarify component mappings exposed by consumption acceptanceproposed2026-09-07
    D-016Pinned release comparison report and historical renderingproposed2026-09-08

    | D-017 | Private framework parity evidence | proposed | 2026-09-08 | — | | D-018 | Declared port capabilities and fresh import evidence | proposed | 2026-09-08 | — | | D-019 | One-way namespaced Figma Variables bridge | proposed | 2026-09-08 | — | | D-020 | Bounded local validation and recovery workflow | proposed | 2026-09-08 | — | | D-021 | Local form composition with versioned data | proposed | 2026-09-08 | — | | D-022 | Local visual selection before agent implementation distribution | proposed | 2026-09-08 | — | | D-023 | True Black / Rose canonical foundation | accepted | 2026-09-08 | owner (explicit selection of candidate I) | | D-024 | Distinguish links from body text and headings | accepted | 2026-09-08 | owner (explicit preview correction) | | D-025 | Theme interactive controls throughout the portal and demo | accepted | 2026-09-09 | owner (explicit native-control replacement request) | | D-026 | Primary action fill darkens off heritage ANSI 12 | accepted | 2026-09-11 | owner (explicit acceptance after visual review) | | D-027 | Recede the interactive chrome | accepted | 2026-09-11 | owner (explicit acceptance after visual review) | | D-028 | Merge gates and the deployment gate are different suites | accepted | 2026-09-11 | owner (explicit verification-split instruction) |

    D-000 Responsibility split

    Status: accepted · 2026-09-05 (adopted from the design package ARCHITECTURE.md).

    Decision. Token files own literal values and aliases. The specification owns meaning, permitted uses and constraints. Port mappings own native keys. Evidence records own what was actually tested. README, the site, and pictures summarise these authorities and never replace them. A disagreement between spec and tokens is a defect to resolve, not permission to choose the convenient answer. Images never override token values. Historical source is evidence of origin, not an override of the adopted accessible design.

    D-001 Controlled three-hue extension

    Status: accepted · 2026-09-06.

    Context. The observed identity is monochrome red/rose. Diagnostics, diffs and status information need differentiation that lightness alone cannot give (a 200-line diff cannot be scanned by glyph). The owner’s own PhpStorm scheme already uses conventional hues for these surfaces.

    Decision. The default profile adds exactly three hues, desaturated and warm-shifted: amber #C9973F (warning, modified), green #86A46F (success, added), blue #7E9EBB (info), with dark tints #1F1A0C, #0F1A0E, #0F141C. They are permitted only in the status, diagnostic, diff and (in the extended overlay) code, terminal and chart groups. They are forbidden in surface, text, border, interaction and action. Purple, cyan and magenta are not added. Every status role also carries a mandatory non-colour channel (glyph, underline pattern or border style). Syntax highlighting in default stays monochrome; the extended overlay profile remains proposed.

    Consequences. Measured contrast on canvas / surface / raised: amber 7.54 / 7.34 / 6.90, green 7.13 / 6.95 / 6.53, blue 7.08 / 6.90 / 6.48.

    D-002 v0.1.0 inventory

    Status: accepted · 2026-09-06.

    Decision. The first public release contains every component marked R1 in the coverage inventory (about 47 across all nine families) plus four composed specimens (settings panel, administrative form, filterable table, i3 window frame), each specified and demonstrated; ten core components are also tested (button, link, text-field, select, checkbox, radio-group, tabs, dialog, menu, table). R2 items and the form-builder specimen are deferred to v0.2.

    D-003 Text-role corrections

    Status: accepted · 2026-09-06.

    Context. #A3676B (the site’s --quiet) measures 4.45:1 on #0C0909 and #7D1310 (--inactive) 1.86:1; the site already restricts them but still uses #7D1310 for line numbers. The site’s suggested replacement #A8403A measures only 3.27:1.

    Decision. text.subtle = #AD7175 (5.10 / 4.96 / 4.67) for metadata, comments and line numbers. text.disabled = #8A5559 (3.33 / 3.24 / 3.05; exempt under WCAG 1.4.3, at least 3:1 by house policy). #A3676B remains in service as border.control, icon.decorative, status.neutral.fill and chart.series.4 (non-text, at least 3:1). #7D1310 remains only as border.disabled, code.whitespace and minor grid lines, never as text. The heritage-ansi profile keeps the original assignments flagged $deprecated.

    D-004 Visibility and licensing

    Status: accepted · 2026-09-06.

    Decision. The repository is public. Code, tokens, schemas, scripts, tests, site source and generated JSON/CSS exports are MIT. Specification prose, specimens and generated Markdown exports are CC BY 4.0. Screenshots under references/ are all rights reserved, reference only. No fonts, no vendor template material, no private business data are ever committed; CI scans for them. See LICENSE.md.

    D-005 Default profile id

    Status: proposed.

    Decision. The approved everyday composition is the profile default. A later rename would be a MAJOR version change.

    D-006 Focus-ring rule

    Status: proposed.

    Decision. Controls and rows: outline: 1px dashed {color.interaction.focus.ring} (#E53935) with outline-offset: -2px. Focusable containers (panes, windows, dialogs, cards): outline: 2px solid {color.interaction.focus.ring-container} (#FFA2A7) with outline-offset: -3px. On any filled surface (selection, action fills, status fills) the ring takes that surface’s on-fill text colour, because #E53935 on #911410 measures 2.15:1. For invalid + focus, where the 2px danger border is already red, the ring switches to the container colour #FFA2A7 at outline-offset: -4px. :focus:not(:focus-visible) draws nothing. In forced-colors mode the ring uses Highlight. Selection is always a fill and focus is always a ring; neither borrows the other’s form.

    Current clarification (D-015). The owner-directed component mappings below clarify the generic on-fill wording above. Primary buttons and checked controls retain their explicitly declared container-colour ring; destructive fills retain their declared on-fill text ring. Geometry and contrast floors are unchanged.

    D-007 Control boundary colour

    Status: proposed.

    Decision. Form-control boundaries must reach 3:1 against their surface (WCAG 1.4.11). #531310 (1.39) and #9E231F (2.56) both fail, so border.control = #A3676B (4.45 / 4.33 / 4.07). The alternative #C81A1A (3.42) is rejected as too loud for every input at rest.

    D-008 Hairlines, sunken surface, overlay border

    Status: proposed.

    Decision. The site’s six near-identical hairline hexes (#290D0C, #24100F, #321110, #38100F, #190B0B, #2B0E0D) fold into one border.divider = #2B0E0D. #0A0707 becomes surface.sunken. Every floating layer (dialog, drawer, menu, popover, toast) uses a 1px border.overlay = #E53935; the historical dunst frame #AE1914 survives only in heritage-ansi.

    D-009 Density modes

    Status: proposed.

    Decision. Two density modes are tokens, applied with data-density on any subtree. compact matches the site: control height 24px, row height 28px, UI type 12/16, icon 16, list gap 2. comfortable: control 32px, row 36px, UI type 13/18, icon 16, list gap 4. Both meet the 24×24 CSS-pixel target minimum; compact requires 4px between adjacent targets.

    D-010 Deployment source

    Status: proposed.

    Decision. The site deploys from main through GitHub Actions after the full pipeline passes. The page header prints the version and build commit and links to the latest tag; consumers pin tags or commits regardless.

    D-011 Reference screenshots

    Status: proposed.

    Context. The four PhpStorm screenshots show a private project name in the window title bar.

    Decision. Before any screenshot is committed under references/, the title bar is cropped (or the name redacted) and the redaction is disclosed in the provenance record. If the owner prefers, the screenshots stay out of the public repository and are described in references/catalogue.json only.

    D-012 Committed exports

    Status: proposed.

    Decision. exports/, site/src/styles/tokens.generated.css, the JSON schemas under schemas/json/ and the README marker blocks are generated and committed; npm run check fails CI on drift or orphan files. Outputs contain no timestamps and no commit hashes so two runs are byte-identical. dist/ is never committed.

    D-013 Consumption eligibility is separate from approval

    Status: proposed (formal log status remains owner-controlled).

    Context. Issue #4 found conflicting instructions to use and to prohibit pending roles in the approved default profile. Alternatives were to block pending roles until individually approved, or to use pinned values with disclosure.

    Owner direction, 2026-09-07. During Phase 1 planning the owner selected “Use and report” and “Block new use” for deprecated roles, then authorized implementation. That explicit direction governs consumption without approving pending token values or changing D-005 through D-012.

    Policy. An approved default profile’s pending roles may be used at a pinned revision with disclosure of their pending decision IDs, including dependencies. Proposed profiles remain preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles cannot be newly mapped in an approved profile; no substitute is implied. Ordinary observed/approved roles remain usable within their documented scope; primitives remain inspection-only. Release version, profile status, role status, deprecation and eligibility are separate facts. The generator emits the policy and eligibility metadata.

    D-014 Automatic inline literal color previews

    Status: proposed (formal log status remains owner-controlled).

    Context. Issue #1 requests circular previews and a transparency checkerboard, which conflict with the general square geometry and no-gradient rules. Keeping square previews would remove the requested circle-to-square interaction.

    Owner direction, 2026-09-07. The owner explicitly approved a narrow preview exception and authorized implementation. It is presentation of literal data, not a new palette, semantic role or component geometry rule.

    Exception. Every visible CSS hex literal on the spec page receives one automatically generated preview. Preserve the literal exactly. The preview is 16px including its theme-derived 1px boundary, circular at rest, and scales to 17.4px with radius zero when CSS :hover matches. The fast duration token and ease-out govern transform and border-radius; reduced motion removes animation. Alpha is composited over a checkerboard made from existing theme tokens. Only this preview permits rounded geometry, patterned gradient backgrounds and border-radius animation. Text, copying, keyboard order and no-JS access remain intact. The parsed literal is data and never inferred from a token or screenshot.

    Syntax specimens (literal data, not additional theme roles): #f00, #f008, #ff0000, #ff000080, #000000, #ffffff. These examples also exercise copy fidelity and transparent, dark and light previews in the browser suite.

    Follow the pointer hovering effect

    The j3w1 specification’s inline color circles provide a pointer-following exact-value preview for actual mouse and pen pointer events. The popup follows the pointer’s position inside the circle with an 8px gap, flips when necessary and stays inside an 8px viewport gutter. It disappears immediately when the pointer leaves that circle, on an outside press, Escape, or loss of window focus. After page or nested-container scrolling, recheck the element under the last pointer position: keep the popup only if the same circle remains there. The popup cannot capture pointer input or keep itself open when hovered. It is a supplementary, non-interactive visual preview; token tables and the keyboard-accessible token inspector retain the persistent information and links. Long previews are bounded by the viewport. No new keyboard stop is introduced. Pointer tracking has no animation or easing, including under reduced motion. This owner-directed behavior extends the D-014 preview exception only; it does not change the general tooltip or focus contract.

    Compatibility clarification. CSS :hover controls the circle-to-square morph directly. Mouse and pen pointer events control the popup; touch and unknown pointer types do not open it. Neither behavior is gated by hover or any-hover media features: browsers can report no hover capability while still delivering mouse input. Reduced motion continues to remove animation, and circles and their literal text remain visible without JavaScript.

    D-015 Clarify component mappings exposed by consumption acceptance

    Status: proposed. The owner directed application of this resolution on 2026-09-07; its implementation preserves existing component appearance. The formal decision status remains owner-managed.

    Context. Phase 2’s independently reviewed composed acceptance preserved three contradictions: ordinary confirmation versus destructive alert-dialog tone, the primary button’s pressed-border metadata versus its prose/CSS, and the global on-fill focus wording versus explicit component ring mappings. Phase 3 controls must not present an arbitrary interpretation as canonical.

    Owner-directed resolution. Preserve current component appearance and all token values. Ordinary confirmation uses the primary action tone; destructive tone belongs to destructive actions, independent of the confirmation’s semantic role. The primary button retains color.action.primary.border when pressed; secondary and tertiary use color.border.active, and destructive retains its declared destructive border. Correct the generic/default metadata accordingly. Focusable controls retain their documented component ring mappings: primary and checked/selected fills use color.interaction.focus.ring-container where declared; destructive fills use their on-fill text role. Clarify the global wording to refer to these explicit mappings, retaining ring geometry, forced-colors behavior and every contrast floor. No profile or pending-token approval is implied.

    Alternatives. Enforce the generic prose everywhere, changing currently rendered pressed borders and focus colors; or retain the contradictions and explicitly mark affected workbench configurations unresolved. Neither is silently selected. Historical acceptance reports remain historical evidence.

    D-016 Pinned release comparison report and historical rendering

    Status: proposed. Issue #2 authorizes derived release diagnostics; formal decision status and all theme approvals remain owner-managed.

    Context. Release comparison needs a versioned report without putting run metadata into deterministic canonical exports or interpreting missing historical fields using today’s rules.

    Implementation scope. Schema version 1 records both immutable revisions, profile and input digests, separate semantic change categories, explicit dependency evidence, and unsupported historical inputs. Reports and historical specimen renderings are build artifacts under dist/releases/; the canonical exports retain their existing contract. Historical data is read from Git, never executed as a build or imported as a module. The current shared specimen renderer presents each side’s maintained markup and styles with a documented renderer version and matched conditions. This is a reconstructed visual reference, not evidence that an old site’s JavaScript or an external port ran. Actual browser captures remain run evidence with recorded environment and artifact hashes. Missing evidence stays not run. Renames require an explicit mapping naming the two revisions; equal values do not establish a rename.

    Alternatives. A raw file diff loses semantic categories and dependency evidence; executing historical applications expands the trust boundary and confounds renderer changes with theme changes. Neither is required for this bounded comparison. No design values, eligibility rules or verification statuses are changed by the report format.

    D-017 Private framework parity evidence

    Status: proposed. Issue #3 authorizes an independently authored private harness; formal approval statuses and the existing license boundaries are unchanged.

    The harness consumes an operator-supplied licensed target and an explicit license review. It copies only declared template inputs into a new private fixture directory, uses synthetic examples and records the exact theme, template, framework, dependency and fixture identities. The original target and its application behavior remain outside this experiment’s write scope. Browser captures, copied vendor inputs and detailed results remain private. Missing prerequisites produce not-run output. A successful diagnostic run is not a verified port or a claim of complete visual parity.

    Alternatives are a public vendor copy (incompatible with the current license boundary) or a generic framework mock presented as real template evidence (insufficient provenance). Neither is used.

    D-018 Declared port capabilities and fresh import evidence

    Status: proposed. Issue #14 authorizes a derived mapping explorer; it does not create a port, change host capabilities or approve a profile.

    Optional capabilities.json metadata refines each existing mapped/unmapped role into mapped, inherited, unsupported, out-of-scope or not-implemented, with an explicit surface and reason. Legacy unmapped reasons remain unclassified; the generator never guesses a more specific state. Import verification is separate from mapping state and declared manifest status. Verified output requires a recorded real-import protocol bound to current target metadata, canonical tokens, mappings, capabilities and artifact bytes. Relevant changes make evidence stale; failed or missing checks cannot pass. The same generated catalogue supplies summaries, drill-downs and task kits. Private parity records are never automatically imported into the catalogue.

    Alternatives are a hand-maintained support matrix or treating a successful parse as an application import. Both lose the evidence boundary.

    D-019 One-way namespaced Figma Variables bridge

    Status: proposed. Issue #15 authorizes this bounded adapter; approval and eligibility statuses remain those of the canonical source.

    An explicit pinned revision supplies colors and scalar spacing/radius values. Aliases retain their dependency structure; dependency-only primitives are hidden from property pickers. Unsupported types and non-approved profiles are reported. One collection and one mode avoid assuming paid mode capabilities. Dry-run is read-only, apply is explicit, and external import receipts identify owned IDs and their last observed values. Conflicts and manual edits stop an update or rollback. The bridge does not store ownership in unsupported plugin data, overwrite unrelated variables, or write values back to the repository.

    Alternatives are manual duplicate maintenance, a paid-only REST workflow, or silently flattening aliases/composites. None meets the one-way evidence scope.

    D-020 Bounded local validation and recovery workflow

    Status: proposed. Issue #16 authorizes one executable pattern using existing admin-form, field, alert and button rules, without adding palette roles.

    The workflow has editing, invalid, review, busy and success stages. Validation runs on explicit submission, preserves values, and presents linked errors. Typing does not rewrite live announcements. Review can return to a field; confirm enters busy, and a separate local simulation-completion event enters success. No request is made. The existing workstation example’s reserved name and hostname are explicitly local fixture conflicts, not business policy. The pattern contract pins constituent component content digests and reports automated evidence separately from manual screen-reader acceptance.

    Alternatives are a color-only invalid snapshot, validation on every keystroke, or treating a submit click as a successful save. They do not teach recovery.

    D-021 Local form composition with versioned data

    Status: proposed. Issue #19 authorizes the deferred form-builder demonstration.

    Five canonical field kinds can be added, edited, removed and reordered with buttons. Definitions, preview values and validation state are separate. JSON imports have closed fields, bounded size/counts and unique stable IDs; failed imports leave the current form unchanged. Content identity pins the supplying theme and component contracts. Downloads contain definitions, never entered values. The builder reuses D-020’s field rendering and validation behavior. It remains a draft reference component, not a backend platform or native port.

    Alternatives are arbitrary HTML/schema execution, a conditional workflow engine, and a second visual field implementation. They exceed this task.

    D-022 Local visual selection before agent implementation distribution

    Status: proposed. Issue #37 and the owner’s implementation instruction authorize three local candidate systems before canonicalization. Formal design approval remains owner-managed.

    The primary outcome is agent consumption of installable or copyable components and compositions with complete dependencies and pinned machine contracts. The future package, documentation portal and Vue application are consumers of the same canonical design language. A local review harness first compares exactly three explicit token overlays with Current, using shared specimen rendering and an original Vue composition. Overlays, generated reports and review builds stay ignored and are never public profiles or delivery artifacts. The existing alias resolver and unrounded contrast engine evaluate candidates without changing canonical values, historical ANSI slots or waivers. No approval is inferred from numerical or browser evidence. The owner must select a concrete candidate before foundation freeze, mass productization or deployment. See docs/phase6-visual-review.md for commands, boundaries and continuation.

    Alternatives are productizing the old palette before visual selection, publishing unapproved preview profiles, or offering incomplete appearance-only snippets as consumable components. None satisfies the authorized sequence and consumption goal.

    D-023 True Black / Rose canonical foundation

    Status: accepted. The owner explicitly selected the reviewed candidate I: “use the True Black / Rose theme and make it permanent for j3w1/theme”, and authorized continuing the remaining Phase 6 implementation.

    The approved change is confined to seven surface assignments: canvas, sunken, input, code and terminal use the existing pure black primitive; chrome uses #090707; default panels use #100c0c. Add the two selected values as color.primitive.ink.14 and color.primitive.ink.28, preserving the luminance ordering and all historical primitives. Keep every other color assignment, including rose/white foreground, red actions, focus, borders, selections, status and chart roles, exactly as reviewed. Raised/overlay surfaces remain #241010; alternate chrome remains #1c0a09. Preserve the complete historical profile by explicitly retaining its previous surface assignments.

    The rejected A/B/C, revised D/E/F and final G/H/I reviews are historical local evidence. Their temporary inputs are not public profiles. Selection approves these specific surface values and assignments, not unrelated pending decisions, new colors or accessibility waivers. This is the foundation for the Phase 6 package, copy distributions, static portal and Vue showcase. Existing consumers retain their immutable pins; the new surface contract ships in version 1.0.0, following the repository’s major-version rule for approved value changes.

    Superseded in part, and only in part. Three later accepted decisions each replace one or more of the role assignments above, and leave everything else here standing: D-024 replaces text.link; D-026 replaces action.primary.bg; D-027 replaces surface.raised, interaction.selection.bg and text.placeholder. Every other value and rule recorded in this decision — the seven surface assignments, the two new primitives, the luminance ordering, the remaining foreground, red action, focus, border, selection, status and chart roles, overlay #241010, alternate chrome #1c0a09, and the retained historical profile — stands as accepted. This decision keeps its accepted status; it is not superseded as a whole.

    D-024 Distinguish links from body text and headings

    Status: accepted. During the implementation preview the owner requested links that are more distinguishable from normal text, using different colors. This is an explicit correction to the foreground-role retention in D-023, limited to links. Map color.text.link to the existing strong red primitive #f73f35, retain the persistent red underline, and retain near-white hover text on the strong dark-red hover fill. Visited links keep the link color and underline; current-page indicators and selected navigation retain their explicit on-fill roles. Body text and heading colors remain the True Black / Rose hierarchy.

    The alternative of bright-rose links still shares the heading color and gives too little separation in the reviewed dashboard. Blue/purple links would introduce an unrelated hue. No new primitive, status hue, contrast exception or focus rule is introduced. Preserve the old link assignment in the historical profile. This refinement ships with the same unreleased 1.0.0 major change.

    D-025 Theme interactive controls throughout the portal and demo

    Status: accepted. After reviewing native blue selections in the work board and agent-kit picker, the owner explicitly instructed: “replace mostly all native components like <select> we must use all j3w1 themed”. The owner also requested a properly proportioned command-search field. This records that authorization.

    The maintained select implementation now renders its single-choice popup and multiple-choice list in theme-owned DOM using the existing selection, surface, text, border and focus roles. The native select remains the form-value and constraint source and the no-JavaScript fallback. This supersedes the select specification’s prohibition on replacing the host popup for web implementations. Native ports retain their host-specific mappings. The custom interface follows the select-only combobox and multiple listbox keyboard patterns, preserves labels, disabled options/fieldsets, native input/change events, defaults and form reset, and documents its actual tested scope.

    Provide the same supported enhancement for existing application controls, use it throughout the portal and Vue demo, and include it in consumption documentation and copy closures. Theme ordinary input, button, checkbox, radio, range and file control chrome as well. Browser-owned system dialogs and explicit no-JavaScript fallbacks remain native; they are not styled by unsupported platform hacks.

    Date inputs use a theme-owned text editor and calendar; time inputs use explicit text entry and theme-owned step buttons. Their original native inputs retain constraints and form values. This supersedes the earlier date/time component specifications’ host-popup descriptions for enhanced web implementations.

    The alternative of advisory option CSS leaves the demonstrated blue host selection unchanged. One-off Vue/portal dropdowns duplicate behavior and leave agents with inconsistent components. New hues, focus rules, accessibility waivers and license changes are not authorized by this correction. The additive enhancement and corrected component behavior ship in 1.1.0; existing 1.0.0 pins remain immutable. The command field fills its dialog width below its label.

    D-026 Primary action fill darkens off heritage ANSI 12

    Status: accepted. The owner asked for a slightly darker fill on primary actions such as the portal’s Explore components button, and accepted this entry as implemented after reviewing it.

    color.action.primary.bg aliased color.primitive.red.300, which is also color.primitive.ansi.12 and color.terminal.ansi.12. schemas/roles.mjs fixes every color.primitive.ansi.<i> to its heritage value byte for byte in every profile, so darkening that primitive is not available: it would fail validation and silently repaint the terminal’s bright red.

    The role therefore aliases color.primitive.red.200 (#7d1310), a value already in the palette, rather than minting a new colour. Label contrast rises from 8.17:1 to 9.28:1 and the focus ring over the fill from 4.90:1 to 5.57:1; both were already passing. The state ladder stays ordered — pressed #630f0d below the fill, hover #911410 above it.

    The declared pair primary fill against the panel is a recorded decorative waiver. It measured 2.07:1 before this change and measures 1.83:1 after it, further from 3:1. It is listed as decorative because the label identifies the button; this decision does not change that reasoning, and no waiver is added or widened.

    This supersedes part of D-023, and only this part. action.primary.bg (#871f19) was one of the assignments that decision kept “exactly as reviewed” under its red actions clause; this entry replaces that single role and nothing else in D-023. The primitive is untouched, so color.primitive.red.300, color.primitive.ansi.12 and color.terminal.ansi.12 all still carry the heritage value.

    Alternatives: mint a new primitive at the exact requested value, which adds a colour to the palette for a difference of about one step and no measurable gain; or leave the fill and darken only the portal button, which would put a value in a stylesheet that is not in tokens/, against the confirmation-only rule in theme.json.

    D-027 Recede the interactive chrome

    Status: accepted. The owner found the open list, its selected row, the placeholder text and the link hover fill all louder than the content they sit against, and asked for a darker treatment across the set, then accepted this entry as implemented after reviewing it.

    Four roles move, all onto values already in the palette; no colour is minted.

    • surface.raised takes ink.30 (#160b0b) instead of ink.52. An open list now reads as depth rather than as a lighter panel, and stays distinct from surface.default (#100c0c).
    • interaction.selection.bg takes red.100 (#531310) instead of red.350. Text on the fill improves from 7.92:1 to 12.47:1.
    • text.placeholder takes rose.350 (#a3676b) instead of rose.600, measuring 4.71:1 on surface.input — darker, and still clear of the 4.5:1 floor without a waiver.
    • Links hover on interaction.hover.bg rather than interaction.hover.bg-strong. Menu items keep the strong fill, so the two remain distinguishable.

    The selection fill was never what carried selection: at #911410 it measured 2.00:1 against the raised surface, below the 3:1 non-text minimum, and the recessed value measures less again. Selection is carried by the 2px border.selected-indicator and the check glyph, which is what spec/foundations.md requires when a state would otherwise be colour-only. Both are unchanged. The full report still shows 954 pairs, 17 waived and none failing; no waiver is added or widened.

    This supersedes part of D-023, and only this part. surface.raised (#241010) and interaction.selection.bg (#911410) were among the values the owner selected in that accepted decision, and text.placeholder (#bd787d) fell under the same decision’s instruction to keep the foreground roles exactly as reviewed. This entry replaces those three role assignments and nothing else in D-023: every other surface, foreground, focus, border, selection, status and chart role it approved stands as accepted, as does its historical-profile retention. tests/foundation-selection.test.js guards the set by name and now records the recessed values; every other surface in it is still the D-023 selection, untouched.

    The darker fill also settles the ring on a selected row. D-006 recolours the ring on filled surfaces because #e53935 measured 2.15:1 on the old #911410; on #531310 it measures 3.38:1, past the 3:1 minimum, so a selected row now takes the ordinary 1px dashed control ring instead of the 2px solid container ring. That is the only fill this reaches: the ring still measures 2.52:1 on action.primary.bg and 1.13:1 on status.danger.fill, and both keep their recoloured ring. spec/foundations.md carried the stale 2.15:1 figure as its stated reason and has been corrected; D-006’s own record is left as written, since it describes what was true when it was opened.

    Alternatives: keep the fills and darken only the components the owner pointed at, which would put presentation in a stylesheet rather than in the roles and leave selection meaning two different things; or introduce new primitives at intermediate values, which adds colours to the palette for differences the existing steps already cover.

    D-028 Merge gates and the deployment gate are different suites

    Status: accepted. The owner instructed that the exhaustive verification move off the pull-request critical path: merges gate on a few minutes of checks, the full matrix gates deployment, and a local full run stays recommended rather than mandatory.

    Context. Accepting D-026 and D-027 changed prose, token metadata and generated exports. It cost twenty-nine and a half minutes of continuous integration before it could merge. Measured on that run: sources zero point six minutes, build zero point seven, packed consumers three point three, and the browser matrix twenty-four point nine. The browser job was eighty-four per cent of the wait, and the repository is public, so the runners are free and the whole cost is latency for whoever is waiting.

    Decision. A pull request merges on validate, build and a new smoke job. The packed-consumer and browser suites run on main before deployment and on demand through the workflow dispatch. The full local loop is npm run test:all; it is available and recommended before pushing, and it is not mandatory. Nothing verifies that it was run.

    The full matrix is a deployment gate. It always was: a browser failure has never prevented a merge from being correct, it prevents the site from being published, and deploy still depends on it. Requiring it before merge treated a publication gate as a correctness gate and charged every change for the difference. What the merge gate keeps is what a source test cannot see: that the built site loads under its base path, renders from the tokens, and takes a keyboard.

    smoke is a named subset and reports as one. It runs the desktop project only, over the page, portal, button and text-field specs, and it reports with the plain list reporter rather than the evidence reporter. That last point is the rule, not an optimisation: the evidence reporter records unselected tests as not run, so a filtered run that reached it would publish an evidence matrix that looked complete and was not. A passing smoke is a signal that the build is sound. It is never a coverage claim, and the published matrix continues to come only from the full suite.

    The packed-consumer suite moves with the browser suite and cannot be split from it. The browser job downloads the consumer evidence artifact and republishes it against the deployed package, and scripts/ui-verification-report.mjs requires the complete protocol on all three engines because a filtered run must not pass as a full one. Both are on the deployment path together.

    No mandatory local gate. A receipt produced by the machine that ran the tests proves only that something wrote a receipt. It cannot distinguish a real run from a forgotten one that was filled in afterwards, so it would have caught carelessness and nothing else, at the price of machinery that looked like proof. Local verification is a practice here, recorded in AGENTS.md, not a gate.

    Alternatives: shard the full suite across runners, which keeps complete coverage before merge at about six minutes and costs nothing on a public repository, but is bounded below by the largest single spec file and gives each shard its own partial evidence file to merge; or keep the packed consumers on the merge path for three more minutes, which buys cross-engine coverage of the distributed package rather than of this site. Sharding is the one worth revisiting if complete pre-merge coverage ever matters more than the minutes.