Skip to content
Guide

Foundations

Every foundation of the design system, rendered live in the active skin: color, type, surfaces, elevation, radius, sizing, motion, and focus.

Color

Every skin carries twelve-step ramps for neutral, primary, and seven hues. Each step has one job, and the same job in light and dark: 1–2 backgrounds, 3–5 component fills, 6–8 borders, 9–10 solid fills, 11–12 text. A ramp derives from its --scale-{name}-seed, so one declaration retints the whole family.

Components paint roles, never a ramp step: surfaces, text, lines, and the badge families each alias a step. A skin re-values a seed or a role and every component follows. Contrast between each pairing is audited on Theme accessibility.

Ramps

Backgrounds
Component fills
Borders
Solid fills
Text
123456789101112
neutral
primary
red
orange
yellow
green
blue
purple
pink
--scale-neutral-seed
—
--scale-primary-seed
—
--scale-red-seed
—
--scale-orange-seed
—
--scale-yellow-seed
—
--scale-green-seed
—
--scale-blue-seed
—
--scale-purple-seed
—
--scale-pink-seed
—

Surfaces

Aa
--canvasThe page paper the scene/panels float on; same ramp step as --background by default, skins may drop it below.
Aa
--backgroundBase surface color (panels, bubbles read it via bg-background).
Aa
--card--card-foregroundCard surface; sits on --background in light, one ramp step above it in dark.
Aa
--popover--popover-foregroundFloating surface base (popover / menu / select / dialog).
Aa
--muted--muted-foregroundSubdued fill for quiet surfaces.
Aa
--secondary--secondary-foregroundSecondary action fill (assistant bubble in chat skins).
Aa
--accent--accent-foregroundHover / selection highlight fill.
Aa
--primary--primary-foregroundTHE brand color; primary action surfaces route through it.
Aa
--destructive--destructive-foregroundDestructive action color.

Status

The quick brown fox

--success--success-textSuccess status color; defaults to --scale-green-9.

The quick brown fox

--warning--warning-textWarning status color; defaults to --scale-yellow-9.

The quick brown fox

--info--info-textInfo status color; defaults to --scale-blue-9.

Text

The quick brown fox

--foregroundDefault text color on --background.

The quick brown fox

--muted-foregroundSecondary / meta text color.

The quick brown fox

--primary-textReadable brand text color on base and card surfaces; --primary at ramp step 11.

The quick brown fox

--destructive-textReadable destructive text color on base and card surfaces; --destructive at ramp step 11.

Lines

--borderHairline border color (carries --ring-opacity).
--inputForm field border color; defaults to --control-rim.
--control-rimBoundary color of a control's own edge; defaults to --border.
--control-boundaryEdge of a control that has no other outline (unchecked checkbox, radio, switch track); defaults to --foreground at 60% and must clear 3:1 on --background and --card (WCAG 1.4.11).
--image-outlineHairline inside images and media that separates them from any surface; 10% black in light, 10% white in dark.
--ringRing palette color; --focus-ring derives from it at 70% alpha, so a skin whose ring loses 3:1 there (a saturated accent or a softened halo) must set --focus-ring.
--focus-ringColor of the keyboard focus indicator; defaults to --ring at 70% alpha. Must clear 3:1 against every surface it lands on (WCAG 1.4.11).
--canvas-grid-dotDot color of canvas and flow grid backgrounds.

Control fills

Aa
--control-fillResting fill shared by fields and surface controls; defaults to --card at 72% alpha.
Aa
--hover-fillWash a row or control takes on hover; defaults to a 6% tint of --foreground.
Aa
--active-fillWash a selected or pressed row keeps; defaults to an 8% tint of --foreground.

Sidebar

Aa
--sidebar--sidebar-foregroundSidebar surface; defaults to --canvas.
Aa
--sidebar-accent--sidebar-accent-foregroundHover and active wash of sidebar items; defaults to --hover-fill.
--sidebar-primaryAccent of the active sidebar item; defaults to --primary.
--sidebar-borderEdge between the sidebar and the page; defaults to --border.

Badge colors

neutralneutral
--badge-neutral--badge-neutral-foreground--badge-neutral-border--badge-neutral-hover
redred
--badge-red--badge-red-foreground--badge-red-border--badge-red-hover
orangeorange
--badge-orange--badge-orange-foreground--badge-orange-border--badge-orange-hover
yellowyellow
--badge-yellow--badge-yellow-foreground--badge-yellow-border--badge-yellow-hover
greengreen
--badge-green--badge-green-foreground--badge-green-border--badge-green-hover
blueblue
--badge-blue--badge-blue-foreground--badge-blue-border--badge-blue-hover
purplepurple
--badge-purple--badge-purple-foreground--badge-purple-border--badge-purple-hover
pinkpink
--badge-pink--badge-pink-foreground--badge-pink-border--badge-pink-hover
--badge-fill-alpha
—
--badge-border-alpha
—
--badge-hover-alpha
—

Chart colors

--chart-blue
--chart-purple
--chart-pink
--chart-orange
--chart-green
--chart-yellow
--chart-red
--chart-neutral

Typography

Two font roles, body and display, default to one sans stack. The type scale is a fixed ladder of rungs; headings carry their own line-height, weight, and tracking so a skin can re-voice them without touching components.

Font roles

Aa Bb Gg 0123

--font-sansTypeface for the whole UI.

Aa Bb Gg 0123

--font-monoMonospace face (code, kbd).

Aa Bb Gg 0123

--font-bodyFont ROLE for body/UI text; defaults to --font-sans.

Aa Bb Gg 0123

--font-displayFont ROLE for headings; defaults to --font-sans.

Type scale

Ship the interface your agent deserves

--text-micro--text-micro--line-height

Ship the interface your agent deserves

--text-caption--text-caption--line-height

Ship the interface your agent deserves

--text-label--text-label--line-height

Ship the interface your agent deserves

--text-body--text-body--line-height

Ship the interface your agent deserves

--text-body-lg--text-body-lg--line-height

Ship the interface your agent deserves

--text-heading-4--text-heading-4--line-height--text-heading-4--font-weight

Ship the interface your agent deserves

--text-heading-3--text-heading-3--line-height--text-heading-3--font-weight

Ship the interface your agent deserves

--text-heading-2--text-heading-2--line-height--text-heading-2--font-weight

Ship the interface your agent deserves

--text-heading-1--text-heading-1--line-height--text-heading-1--font-weight--text-heading-1--letter-spacing

Ship the interface your agent deserves

--text-display--text-display--line-height--text-display--font-weight--text-display--letter-spacing

Surfaces and layers

Canvas is the paper, background and card sit on it, and popovers float above everything. Floating surfaces and the modal overlay take their translucency and blur from the surface knobs.

Stacking follows one ladder of tiers, so layers from different components never compete: --z-raised (10), --z-sticky (20), --z-nav (30), --z-overlay (70), --z-modal (one above the overlay), --z-popup (80), --z-toast (90), and --z-tooltip (95). A part that only needs to sit above or below a sibling inside its own component uses a local z-1 or -z-1 instead of a tier.

Stacking order

--canvas
--background
--card
--popoverMenus, selects and dialogs float here.

Overlays and translucency

Popover surface
--popover-opacity
—
--backdrop-blur-popover
—
--overlay-opacity
—
--backdrop-blur-overlay
—
--scroll-fade-size
—
--disabled-opacity
—

Elevation

Every shadow is one recipe scaled by a tier multiplier, then by the global size, opacity, and vertical bias knobs. Flatten a skin with --shadow-size: 0; deepen one tier by raising its multiplier.

Tiers

Control
--shadow-control-multiplier
Panel
--shadow-panel-multiplier
Popover
--shadow-popover-multiplier
Modal
--shadow-modal-multiplier
Ambient
--shadow-ambient-multiplier
Overlay
--shadow-opacity
Inset
--shadow-control-multiplier

Global shadow knobs

--shadow-color
—
--shadow-highlight
—
--shadow-size
—
--shadow-opacity
—
--shadow-y
—

Radius and corners

One --radius knob drives the whole scale: each role is a multiple of it. Nested corners stay concentric through the additive tokens — --radius-popover, --radius-composer, and --nest-radius add the inset to the inner corner — and --corner-shape reshapes every corner where the browser supports it.

Scale

--radius-sm
--radius-md
--radius-lg
--radius-xl
--radius-2xl

Roles

--radius-popup-itemSelect/menu row corner; derived from --radius-control.
--radius-popup-item-fitRow corner capped at half the smallest control height; --radius-popover nests around it.
--radius-controlShared control corner (button, trigger, field, chip); ×2 from --radius.
--radius-fieldUser bubble corner; --radius × 2.2.
--radius-composerComposer shell corner, concentric with the fitted control corner plus composer padding and rim.
--radius-popoverPopup container corner, concentric with the fitted row corner.
--radius-panelCode / markdown panel corner; --radius × 2.6.
--radius-sceneScene frame / large media corner; --radius × 2.8.

Knobs

--radius
—
--corner-shape
—

Sizing and density

--control-h is the medium control height, 2.25rem by default. The extra-small, small, and large sizes are 0.78, 0.89, and 1.11 times that height, snapped to 2px, so one declaration rescales every control and the heights follow the user's font size. --spacing is the density unit: gaps and padding are multiples of it, including --popover-padding and --composer-padding. Padding knobs set the density of rounded surfaces such as bubbles and the composer.

Control heights

--control-h-xs
--control-h-sm
--control-h-md
--control-h-lg

Density knobs

--composer-padding
—
--spacing
—
--popover-padding
—
--padding-x
—
--padding-y
—
--control-h
—
--control-h-xs
—
--control-h-sm
—
--control-h-md
—
--control-h-lg
—
--sidebar-width
—
--sidebar-width-icon
—
--z-raised
—
--z-sticky
—
--z-nav
—
--z-overlay
—
--z-modal
—
--z-popup
—
--z-toast
—
--z-tooltip
—
--control-rim-width
—
--touch-target
—
--target-min
—
--text-input-min
—

Motion

Three tempos and two curves cover every transition. Reduced-motion settings collapse them to zero globally, so components never check the preference themselves.

Tempo × curve

--duration-fast · --ease-standard
--duration-base · --ease-standard
--duration-slow · --ease-standard
--duration-loop · --ease-standard
--duration-fast · --ease-emphasized
--duration-base · --ease-emphasized
--duration-slow · --ease-emphasized
--duration-loop · --ease-emphasized

Values

--ease-standard
—
--ease-emphasized
—
--duration-fast
—
--duration-base
—
--duration-slow
—
--duration-loop
—

Focus

The focus indicator is its own role: color, width, style, and offset. It appears on :focus-visible only, so a pointer press on a button, tab, or checkbox draws nothing, while a text field shows it on click because typing goes there next. Each control draws one indicator: fields, the composer, the message being edited, and highlighted menu items paint it on their own edge, and everything else gets a ring at --focus-ring-offset. A container that owns the ring for its parts declares data-focus-ring="within"; a field whose surface already shows where focus is, like the command palette search, declares data-focus-ring="none" and relies on the caret. It must clear 3:1 against every surface it lands on.

Indicator

Focused

Values

--focus-ring
—
--focus-ring-width
—
--focus-ring-style
—
--focus-ring-offset
—