Canonical · Web primary
Foundations
A semantic contract derived from the production Quiet Sky layer—not a copy of the frontend’s mixed global stylesheet.
Color
Semantics before pigments
Dark is the default. Light is an explicit data-theme="light" override. Components consume semantic names; primitive colors never appear inside component rules.
Every swatch below is rendered from the token, so nothing on this page can drift from tokens.css. Each label carries the runtime name and the Tailwind utility. Toggle the theme in the header to see both resolutions.
Surfaces
--bg · bg-canvas--surface-1 · bg-surface-1--surface-2 · bg-surface-2--surface-3 · bg-surface-3Alpha surfaces
--fill · bg-wash--track · bg-track--glass · bg-glass--bubble-agentThese four are alpha values and read as invisible on an opaque card, so they sit on a checkerboard. --fill is a hover and press wash. --track is the unfilled part of a meter and is deliberately a step stronger than --fill; all three current prototypes make that distinction.
Content
Primary content sits on --text-1, the Tailwind utility text-content-1.
Secondary content sits on --text-2, the utility text-content-2.
Tertiary content sits on --text-3, the utility text-content-3.
Content tokens are shown as type rather than as blocks, because legibility at real size is the only thing that matters about them. Tailwind reserves the --text-* namespace for font sizes, which is why the colours surface as content-1/2/3.
Line
--qs-border-soft · border-line--qs-border-strong · border-line-strongBrand
--qs-accent · bg-brand--accent-tint--accent-border--accent-textFocus ring
The ring is drawn statically here so it is visible in a screenshot. In use it appears on :focus-visible only, at 2px with a 3px offset, from --focus-ring.
bg-brand, text-brand, border-line, and border-line-strong. The generic bg-accent and border-border names are currently owned or overwritten by legacy/shadcn layers.Danger
--danger--danger-text--danger-tint--danger-borderSuccess
--ok--ok-text--ok-tint--ok-borderBoth state families follow the same four-token shape: a fill, an on-surface text value with enough contrast to read at 12px, a wash, and a hairline. --ok and --ok-text differ, because the mint that reads as a filled dot is not legible as text.
Chart ramp
One sequence, not five independent colours. The anchor flips between themes so that --chart-5 always reads as “most”: the ramp runs dark to light on night and light to dark on the light canvas.
Buttons and bubbles
Primary button
--btn-primary-bg and --btn-primary-fg. The primary fill is ink, not brand: cyan is reserved for state, not for the loudest button on the page.
Message bubbles
--bubble-agent, --bubble-user-bg, and --bubble-user-fg. The flat corner points at the speaker's own side.
Elevation
Two structurally identical panels. The well behind them is the page canvas, because on a recessed surface neither shadow is visible at all. There are exactly two elevations, and depth is never used to signal state.
Typography
Onest, seven functional rungs
Sentence case is the default. Weight creates hierarchy before color. Quiet Sky Web surfaces must use collision-safe names for body, caption, and micro.
Title 1
28 / 34 · page titles
text-title-1Title 2
19 / 25 · card and modal titles
text-title-2Title 3
15 / 21 · row titles
text-title-3Body
14 / 21 · product default
text-qs-bodySmall
13 / 19 · navigation and secondary rows
text-smallCaption
12 / 17 · timestamps and metadata
text-qs-captionMicro
11 / 15 · chips and compact labels
text-qs-microEvery rung above is rendered from its token, so a size printed here cannot disagree with tokens.css. Sizes are the only thing the scale fixes; weight and colour stay free.
Why three rungs carry a qs- prefix
A legacy AIC @theme block later in globals.css redefines three of the seven Tailwind size utilities. The collision-safe names exist so a Quiet Sky surface can opt out. Each pair below renders the intended value beside what the generic utility actually produces in the shipping build.
Intended · text-qs-body
Thursday review moved
Two guests declined, so the agent proposed Thursday and is waiting on a reply.
Row title 15 / 21, body 14 / 21. The title reads as a title.
Collided · text-body
Thursday review moved
Two guests declined, so the agent proposed Thursday and is waiting on a reply.
Body renders 15 / 20, identical in size to the row title above it. Hierarchy collapses to weight alone.
Body
text-body renders 15 / 20 instead of 14 / 21, matching text-title-3. Use text-qs-body.
globals.css:269-300Caption
text-caption is repointed to 11px instead of 12 / 17, colliding with micro. Use text-qs-caption.
globals.css:269-300Micro
text-micro renders 10 / 14 instead of 11 / 15. Use text-qs-micro.
globals.css:269-300Shape & space
Nested geometry stays legible
Use the radius scale by role, not by preference. A Quiet Sky card is 16px; the 28px card style still found in legacy product code is a deviation.
Radius
tight 8 · control 12 · inner 14 · card 16 · frame 20 · pill 99. The runtime names are --radius-tight … --radius-pill, matching production.
rounded-tight … rounded-pill · globals.css:214-219Spacing
A 4px rhythm. The rhythm is the rule; the six variables are a convenience for this reference package only.
--qs-space-1 … --qs-space-6Regular density
44px rows · 24px section gap · 16px card padding · 11/18px cells
:rootCompact density
36px rows · 16px section gap · 12px card padding · 7/14px cells
[data-density="compact"]Radius ramp
--radius-tight--radius-ctrl--radius-inner--radius-card--radius-frame--radius-pillPick by role, not by preference. An inner element takes the rung below its container, which is why a 14px group nests inside a 16px card without the corners fighting. The 28px card treatment still present in legacy product code is a deviation, not a seventh rung.
Spacing rhythm
The grid behind the bars is 4px. Production ships no canonical Quiet Sky spacing scale: it has a legacy AIC family at 4/8/16/24/32/48 (globals.css:1069-1074) and a second at 2/4/8/12/16/20 (globals.css:900-905). The qs- prefix on these six keeps them clear of both. For rows, cards, and sections use the density tokens below instead, which is where the real contract lives.
Density
Regular · :root
Compact · [data-density="compact"]
--row-h
44px regular, 36px compact. The minimum height of a list row.
globals.css:57-68--cell-y / --cell-x
11/18px regular, 7/14px compact. Row and cell padding.
globals.css:57-68--pad-card
16px regular, 12px compact.
globals.css:57-68--gap-section
24px regular, 16px compact.
globals.css:57-68Density changes space only. Type sizes, radii, stroke weights, and colours are identical in both panels above, and the two panels use the same markup. That constraint is what keeps compact mode from becoming a second design.
Motion & layers
Quiet, brief, and interruptible
The tokens exist in production; broad enforcement remains incomplete and is tracked in conformance.
Timing
Fast 200ms · base 250ms · slow 300ms · reveal 500ms. Use the brand ease for spatial transitions.
cubic-bezier(.22,1,.36,1)Reduced motion
Respect prefers-reduced-motion; remove nonessential movement and preserve state changes.
Layer scale
base 0 · raised 100 · rail 200 · popover 300 · drawer 400 · scrim 500 · modal 600 · toast 700 · tooltip 800
Partially adoptedThe brand ease at each duration
200ms · --t-fast · hover, press, colour
250ms · --t-base · most spatial transitions
300ms · --t-slow · panels and drawers
500ms · --t-reveal · first appearance only
All four run cubic-bezier(.22, 1, .36, 1): fast departure, long settle, no overshoot. Nothing in Quiet Sky bounces. The track behind each dot is --track.
Motion is suppressed because this browser reports prefers-reduced-motion: reduce. The four durations are 200ms, 250ms, 300ms, and 500ms, all on cubic-bezier(.22, 1, .36, 1). State changes still happen; only the movement is removed.
Layer scale
A closed scale with 100 between rungs, so a new surface never needs an arbitrary number. A toast outranks a modal deliberately: a confirmation must remain readable above the thing that triggered it. Adoption in production is partial and tracked on the conformance page.
Implementation files
Use the portable contract
tokens.css
The portable contract. Framework-neutral runtime values: colour, radius, the seven type rungs, density, motion, and layers, with a dark default and a light override. This page and the patterns page both link it, so everything you see above resolves from it.
View CSS →
demo.css
The specimen stylesheet. Every rendered example on this page and the patterns page is drawn by its ds- classes, ported from the archived 2026 catalog. Nothing in the page chrome depends on it, so it can be deleted without breaking the documents.
View CSS →
site.css
Document chrome only: the shell, nav, spec tables, badges, swatches, and the frames the specimens sit in. It styles the documentation, never the thing being documented.
View CSS →
tokens.tailwind.css
A Tailwind v4 source fragment mapping the tokens into utility namespaces. No page links it and none can: @theme needs a Tailwind build, and a browser silently drops it. Copy it into a Tailwind entry stylesheet after tokens.css.
View Tailwind bridge →
What the bridge maps
Reproduced here so the mapping is readable without opening the file. Nothing below is exercised by this page. Note the renames: Tailwind reserves --text-* for font sizes, so the three content colours become content-1/2/3, and the three names legacy layers overwrite get collision-safe utilities.
/* colour, abridged */
--color-canvas: var(--bg); /* bg-canvas */
--color-surface-1/2/3: var(--surface-1/2/3);
--color-content-1/2/3: var(--text-1/2/3); /* NOT text-1: --text-* is a size namespace */
--color-wash: var(--fill); /* bg-wash */
--color-track: var(--track); /* bg-track */
--color-brand: var(--qs-accent); /* bg-brand, not bg-accent: shadcn owns --accent */
--color-line: var(--qs-border-soft); /* border-line, not border-border */
--color-line-strong: var(--qs-border-strong);
--color-danger/-text/-tint/-border, --color-ok/-text/-tint/-border
--color-chart-1 … --color-chart-5
/* radius, literal values */
--radius-tight: 8px; --radius-ctrl: 12px; --radius-inner: 14px;
--radius-card: 16px; --radius-frame: 20px; --radius-pill: 99px;
/* the three collision-safe type rungs */
--text-qs-body: 14px; --text-qs-body--line-height: 21px;
--text-qs-caption: 12px; --text-qs-caption--line-height: 17px;
--text-qs-micro: 11px; --text-qs-micro--line-height: 15px;
@custom-variant light ([data-theme="light"] &);