Token contract
Guide index · Color · Terminal
One decision, three renderings
A token names a stable visual decision at the role or recipe layer, not an ad hoc platform alias. Desktop and mobile share the same reference values and semantic roles. The terminal maps those same roles to flat cell backgrounds, foreground glyphs, and one-cell frame geometry; it does not own separate face tokens such as terminal.controlFace.
Hex values stay on Color, gradient stops on Surfaces, cuts on Shape, type metrics on Typography, spacing on Layout, and durations on Motion. This page indexes those authorities and shows how roles compose into controls. It does not publish a second copy of the numbers.
Typography and iconography split between the graphical system and the terminal: desktop and mobile share Exo 2 and Oxanium families, type roles, sizes and weights, and outlined icons at the same sizes and strokes. Both use icons; layout, padding, and component target dimensions adapt to the platform. The terminal uses one monospaced cell and the glyph guide. Color, shape, and status keep the same meaning with a thinner translation.
Role and authority
The tables below index the authoritative topic pages. They are independent of any implementation format.
Use three layers:
- Reference values: exact colors, lengths, durations and font families.
- Semantic roles: surface, foreground, boundary, action, focus, selection and status.
- Component recipes: button, tab, card, and field combinations of semantic roles and geometry.
A component should depend on semantic and component roles, not pick an arbitrary hex value. Never overload one value to mean blue edge, blue face, violet navigation, cyan focus and semantic success.
action.edge opaque sRGB · gradient.control angle and ordered stops · type.control weight 600
Blue action edge · control face gradient · primary label on the control face
action.edge · gradient.control · type.control at the touch control height
Same blue edge and control gradient; 48px minimum target
Naming and value types
Use dot-separated semantic names in this design specification. An implementation can translate them to CSS custom properties, native values or typed theme fields. Keep meaning unchanged when renaming.
| Family | Example names | Value type | Authority |
|---|---|---|---|
| Surface | surface.canvas, surface.content, surface.chrome, surface.input |
Opaque sRGB color | Color |
| Foreground | text.primary, text.secondary |
Opaque sRGB color | Color |
| Boundary | line.quiet, line.essential, focus |
Opaque sRGB color | Color |
| Action | action.edge |
Opaque sRGB color | Color |
| Navigation and selection | navigation.accent, row.selectionMarker |
Navigation color plus persistent primary-text selection glyph | Color |
| Semantic | running.foreground/surface, positive.foreground/surface, warning.foreground/surface, danger.foreground/surface |
Paired colors | Color |
| Gradient | gradient.content, gradient.chrome, gradient.control, gradient.controlHover, gradient.controlPressed, gradient.selection |
Angle plus ordered color stops and positions | Surfaces |
| Shape | cut.panel, cut.action, cut.tab, cut.chip, radius.field, radius.join |
Nonnegative logical length | Shape |
| Frame detail | frame.detail.width, frame.detail.depth, frame.detail.rightInset |
Logical lengths; use the authoritative top-right frame embellishment dimensions | Shape: top-right frame embellishment |
| Stroke | stroke.frame, stroke.focus, focus.offset |
Logical length | Shape |
| Space | space.1 through named steps |
Logical length | Layout |
| Size | control.height.standard/dense/compact/touch, shell.header, drawer.width |
Logical minimum/preferred length | Layout |
| Type | type.display, type.pageTitle, type.section, type.panelHeading, type.body, type.control, type.metadata, type.badge, type.code |
Family, weight, size and line height | Typography |
| Motion | motion.hover, motion.press, motion.menuEnter, motion.menuExit, motion.drawer, motion.pageDetail, motion.scroll, motion.stateChange, motion.collapse, motion.listEnter, motion.listExit, motion.progressStep, motion.progressMax, motion.spinnerCycle, motion.marquee, motion.flowCycle, motion.containmentCurve, motion.standardCurve, motion.enterCurve, motion.exitCurve |
Duration or easing curve | Motion |
| Terminal mapping | surface.* backgrounds, line.*, focus, action.edge glyph colors, one-cell frame geometry |
Same semantic roles as Color and Shape; flat cells and foreground glyphs | Terminal |
A gradient's named stops are part of its value, not permission to substitute unrelated colors. Colors use opaque sRGB by default; scrim alpha is explicit and confined to the scrim role.
Semantic specimens
Each example shows the complete set of roles in that family using shared classes so a change in guide.css updates the specimen. Desktop and mobile share values; the terminal maps the same roles.
Surfaces
Canvas ████████ Content ████████ Chrome ████████ Input ████████
Foregrounds
text.primary · enabled labels and reading copy
text.primary · enabled labels and reading copy
text.primary Reading and enabled labels
Boundaries, action, and focus
line.quiet
line.essential
focus
action.edge
line.quiet
line.essential
focus
action.edge
line.quiet ┌──────┐ line.essential ┌──────┐ focus action.edge
Selection markers
▸ Preferences ▸ Record 042
Semantic status pairs
Ready Needs review Failed
Gradients
content ████████ chrome ████████ control ████████ + bold label selection ████████ + persistent primary-text ▸ glyph
Shape cuts
Panel 🮣──🮢 Action Tab | Overview \ Chip Tag Field Text
Spacing
space.1–space.12 · blank cells between content, not px ÷ char width
Control heights
One cell row height in every density mode
Type roles
Oracle
Validation
Evidence
On this page
Body copy.
Run validation
revision: 8
Oracle
Validation
Evidence
On this page
Body copy.
Run validation
revision: 8
ORACLE
Validation
Evidence
On this page
Body copy.
Run validation
Job 042
Ready
revision: 8Motion
| Token | Value |
|---|---|
motion.hover | 120ms |
motion.press | 80ms |
motion.menuEnter / motion.menuExit | 120ms |
motion.drawer / motion.collapse | 180ms |
motion.pageDetail | 160ms |
motion.scroll | 200ms |
motion.stateChange | 160ms |
motion.listEnter / motion.listExit | 160ms |
motion.progressStep | 60ms per whole segment |
motion.progressMax | 1500ms maximum catch-up; shorten segment intervals for large jumps |
motion.spinnerCycle | 1000ms |
motion.marquee | 3500ms |
motion.flowCycle | 1200ms |
motion.standardCurve | cubic-bezier(0.2, 0, 0, 1) |
motion.enterCurve | cubic-bezier(0, 0, 0.2, 1) |
motion.exitCurve | cubic-bezier(0.4, 0, 1, 1) |
motion.containmentCurve | cubic-bezier(0.4, 0, 0.2, 1) |
| Token | Value |
|---|---|
motion.hover | 120ms (no hover face on mobile) |
motion.press | 80ms |
motion.menuEnter / motion.menuExit | 120ms |
motion.drawer / motion.collapse | 180ms |
motion.pageDetail | 160ms |
motion.scroll | 200ms |
motion.stateChange | 160ms |
motion.listEnter / motion.listExit | 160ms |
motion.progressStep | 60ms per whole segment |
motion.progressMax | 1500ms maximum catch-up; shorten segment intervals for large jumps |
motion.spinnerCycle | 1000ms |
motion.marquee | 3500ms |
motion.flowCycle | 1200ms |
motion.standardCurve | cubic-bezier(0.2, 0, 0, 1) |
motion.enterCurve | cubic-bezier(0, 0, 0.2, 1) |
motion.exitCurve | cubic-bezier(0.4, 0, 1, 1) |
motion.containmentCurve | cubic-bezier(0.4, 0, 0.2, 1) |
Spinner · motion.spinnerCycle at ≤8 fps
Observed progress · motion.progressStep, capped by motion.progressMax
Marquee · motion.marquee (3500ms traversal) on segmented bar
Flow · motion.flowCycle on active connector
No hover · no press · instant state when reduced motionComponent aliases
| Component decision | Shared meaning | Desktop and mobile | Terminal |
|---|---|---|---|
| Primary button | Dominant local action | Control gradient + action edge + primary text + control weight 600 | Containing background + bold pale primary label in brackets |
| Secondary button | Alternate action beside primary | Same control gradient + essential neutral edge + primary text + weight 500 | Same containing background and brackets; essential edge color |
| Selected content tab | Active panel in a tab strip | Control gradient + action top marker + primary text | Bold pale label with square-profile endcap; containing background |
| Inactive tab | Available but not active panel | Content gradient + quiet edge + secondary text | Secondary text label; containing background |
| Keyboard focus | Where input goes next | Existing 1px contour recolored cyan, 0 offset; semantic-edge exceptions use surface.focus | Cyan control label; unchanged value and persistent selection glyph; cyan pane frame |
| Selected navigation | Current destination in a nav list | Neutral selection gradient + violet leading edge + bold navigation label | Primary-text ▸ marker on content surface |
| Selected data row | Current record in a collection | Neutral selection gradient + persistent ▸ glyph + bold primary text | Primary-text ▸ marker on content surface |
| Neutral editable field | Valid text entry | Input surface + essential edge + primary text | Input surface cell + essential edge glyphs |
| Invalid field | Rejected value with explanation | Input surface + danger edge + associated error; focus uses the lighter surface.focus fill | Danger edge cue + message; focus stays cyan |
| Status badge | Short semantic state word | Matching semantic foreground/surface pair | Bracketed status word in semantic foreground |
| Disabled action | Action that cannot run yet | Content surface + quiet edge + full-opacity secondary label | Readable label + nearby reason sentence; terminal (disabled) only when the sentence will not fit |
Selection and focus are separate aliases even if a host platform combines them in one native widget. Terminal aliases flatten gradients as specified by the terminal chapter; they do not reuse GUI gradient objects as strings.
Primary
Secondary
Selected tab
Inactive tab
DetailsFocus
Nav selection
PreferencesData row
Field
Invalid field
Enter a single token.
Status badge
ReadyDisabled
Primary
Secondary
Selected tab
Inactive tab
DetailsFocus
Nav selection
PreferencesData row
Field
Invalid field
Enter a single token.
Status badge
ReadyDisabled
| Overview \ Details ▸ Preferences ▸ Record 042 revision: 8 Ready Change the draft before saving.
Portability
CSS logical dimensions become density-independent native layout lengths, with separately scaled type. A 12px panel cut means a 12-unit logical cut in native composition; it does not mean 12 physical pixels on every display. A terminal corner is one cell and has no fixed pixel equivalent.
Role separation is a contract: action.edge, gradient.control, navigation.accent and focus stay distinct roles. A blue face never recolors violet workflow categories or cyan diagnostics.
Keep theme values at explicit composition boundaries. Do not create ad hoc per-component theme objects that drift from the role tables. Theme overrides must replace coherent role pairs/recipes and preserve contrast, geometry and state separation.
Governance
When a value changes, update its authority page and every affected recipe and example before the guide counts as consistent.
A renderer is not accepted merely because its token names match. Review complete states, typography, contour joins, adjacent contrast, text scaling and terminal fallbacks. The accessibility checklist and component recipes define the review envelope.