Foundations

Colour

Achromatic neutrals, so that the accents are the only colour in the interface.

The three tiers

Colour is defined in three layers, and product code consumes only the third. primitives.css holds raw values, semantic.css gives them meaning, and the --color-*tier is the public surface — the one and only answer to “where do I edit to change the look”.

The boundary is enforced. A var(--semantic-…) or var(--primitive-…) outside src/styles/ is a hard audit failure, and the check scans TS and TSX as well as CSS — an inline var(--primitive-…) in a style object is the same violation.

There used to be a fourth tier of short aliases (--text-primary, --panel-bg, --accent-solid). It has been deleted. If you reach for one it will not resolve — and because an undefined custom property drops the whole declaration silently, nothing will tell you. See Working with tokens.

Surfaces

Neutrals are achromatic — red, green and blue channels are equal, deliberately. Depth is carried by lightness alone: cards are borderless and shadowless, separated from the page by being a step lighter than it.

--color-surface-appPage background, sidebars
--color-surface-panelCards, panels
--color-surface-inputInputs and controls
--color-surface-elevatedHover, popovers
--color-surface-canvasThe builder canvas behind user content
--color-surface-popoverFloating surfaces

Text

Three tiers, and the third is not body text. --color-text-tertiary sits below WCAG AA against every surface in the app; it is for placeholders, disabled labels and decorative fills only. Using it for a sentence a reader has to read is a contrast failure the audit will catch.

Ag--color-text-primaryHeadings, values, anything load-bearing
Ag--color-text-secondaryBody copy, labels, descriptions
Ag--color-text-tertiaryPlaceholders, disabled, decoration — never body text
Ag--color-text-on-accentLabels sitting on a solid accent fill

Borders

Borders are hairlines. Rather than compose 1px solid var(--color-border-default) at each site, use the pre-composed rules — Radius & borders covers them.

--color-border-defaultHairlines between surfaces
--color-border-strongHover and emphasis
--color-border-focusThe focused control's edge

Status colours

Four status accents. Red is unshared on purpose — it is used for destructive actions and nothing else, so its meaning never becomes ambiguous.

--color-accent-successPublished, complete, verified
--color-accent-warningNeeds attention; also responsive-inherited fields
--color-accent-dangerDestructive actions only
--color-accent-infoNeutral information
--color-accent-scheduledQueued or scheduled work