# Theme Contract Tokens The tier tokens in `@elements/ui/style/ui-tokens.css`. Every template reads only these and the base tokens, and every theme sets all of them, so a theme can make controls square and dialogs round, or surfaces flat and overlays lifted. Set one in your app CSS to retune every template that reads it. Continued on [ui-parts](ui-parts). **Default** is the value ui-tokens.css declares. **Themes** names the shipped themes (`@elements/ui/themes/`) whose light-mode value differs from it; "all but" counts all 12 themes. ## Type: families | Token | Default | Note | Themes | | --- | --- | --- | --- | | `--font-body` | `var(--font-sans)` | running text | all but default, marketing | | `--font-heading` | `var(--font-sans)` | h1-h4, titles, display | all but default | | `--font-ui` | `var(--font-sans)` | controls, menus, labels, tables | all but default, marketing | ## Type: weights and tracking | Token | Default | Note | Themes | | --- | --- | --- | --- | | `--weight-body` | `var(--weight-regular)` | running text | none | | `--weight-heading` | `var(--weight-semibold)` | h1-h6 | all but dashboard, default | | `--weight-ui` | `var(--weight-medium)` | control labels | all but coder, commerce, default, elements, luxury | | `--weight-strong` | `var(--weight-semibold)` | titles inside surfaces | all but commerce, dashboard, default | | `--tracking-heading` | `var(--tracking-tight)` | letter-spacing for headings | all but default, elements | | `--tracking-ui` | `var(--tracking-normal)` | letter-spacing for control labels | all but civic, default, editorial, playful | | `--leading-heading` | `var(--leading-tight)` | line-height for headings | all but default, elements, luxury | | `--case-ui` | `none` | text-transform for control labels | brutalist, coder, luxury | ## Type: role sizes | Token | Default | Note | Themes | | --- | --- | --- | --- | | `--text-display` | `var(--text-5xl)` | display and hero type | all but calm, commerce, default, editorial, playful | | `--text-h1` | `var(--text-4xl)` | h1 | calm, civic, coder, dashboard, marketing | | `--text-h2` | `var(--text-3xl)` | h2 | calm, civic, coder, dashboard, editorial, marketing | | `--text-h3` | `var(--text-2xl)` | h3 | brutalist, calm, civic, coder, dashboard, editorial | | `--text-h4` | `var(--text-xl)` | h4 | all but commerce, default, luxury, marketing, playful | | `--text-title` | `var(--text-lg)` | dialog, card, sheet title | all but calm, civic, default, elements, playful | | `--text-body` | `var(--text-base)` | running text | calm, civic, coder, dashboard, editorial, marketing | | `--text-ui` | `var(--text-sm)` | control and menu text | all but brutalist, dashboard, default | | `--text-ui-sm` | `var(--text-xs)` | small control text | all but brutalist, default | | `--text-ui-lg` | `var(--text-base)` | large control text | all but brutalist, dashboard, default, elements | | `--text-caption` | `var(--text-xs)` | descriptions under labels, meta | all but coder, dashboard, default | | `--text-label` | `var(--text-sm)` | form labels | all but brutalist, commerce, default, elements, marketing | ## Control tier | Token | Default | Note | Themes | | --- | --- | --- | --- | | `--control-height` | `2.5rem` | default control height | all but default, elements | | `--control-height-sm` | `2rem` | small control height | all but dashboard, default, elements | | `--control-height-lg` | `3rem` | large control height | all but default, elements | | `--control-padding-x` | `1rem` | inline padding inside a control | all but civic, default, elements | | `--control-padding-x-sm` | `0.75rem` | inline padding, small control | all but brutalist, civic, dashboard, default, elements | | `--control-padding-x-lg` | `1.25rem` | inline padding, large control | all but default | | `--control-gap` | `var(--space-2)` | icon to label | calm, coder, commerce, luxury | | `--control-border-width` | `1px` | control edge width | brutalist, civic, playful | | `--control-border` | `var(--rule)` | control edge color | all | | `--control-border-bottom` | `var(--control-border)` | A field's bottom edge. A theme with a light field edge makes this one the 3:1 boundary, so the field stays identifiable without a heavy box. | none | | `--control-border-hover` | `color-mix(in oklab, var(--control-border), var(--ink) 30%)` | Hover always darkens the edge it starts from. | none | | `--control-border-bottom-hover` | `color-mix(in oklab, var(--control-border-bottom), var(--ink) 30%)` | the bottom edge on hover | none | | `--control-bg` | `var(--bg)` | control fill | calm, editorial, luxury, playful | | `--control-shadow` | `none` | control box-shadow | brutalist, calm, dashboard, marketing, playful | ## Item tier | Token | Default | Note | Themes | | --- | --- | --- | --- | | `--item-height` | `2rem` | row height | all but dashboard, default | | `--item-padding-x` | `var(--space-2)` | inline padding inside a row | all but coder, default | | `--item-gap` | `var(--space-2)` | icon to label in a row | calm, coder, commerce, luxury, marketing, playful | | `--radius-item` | `var(--radius-sm)` | row corner radius | all but default | | `--item-highlight` | `var(--bg-muted)` | hovered / keyboard-highlighted row | brutalist, civic, coder, dashboard | | `--item-highlight-ink` | `var(--ink)` | text on a highlighted row | brutalist, civic, coder | | `--item-selected` | `var(--accent-soft)` | selected row fill | brutalist, commerce, editorial | | `--item-selected-ink` | `var(--ink)` | text on a selected row | brutalist, elements, marketing | ## Surface tier | Token | Default | Note | Themes | | --- | --- | --- | --- | | `--surface-bg` | `var(--bg)` | card and panel fill | calm, editorial, luxury, marketing, playful | | `--surface-border-width` | `1px` | surface edge width | brutalist | | `--surface-border` | `var(--rule)` | surface edge color | brutalist, dashboard | | `--surface-shadow` | `var(--shadow-xs)` | surface box-shadow | all but default | | `--surface-padding` | `var(--space-6)` | inner padding | all but brutalist, civic, default, elements | | `--surface-padding-sm` | `var(--space-4)` | compact inner padding | all but brutalist, civic, default, editorial, elements | | `--surface-gap` | `var(--space-4)` | space between a surface's parts | all but brutalist, civic, default, elements | ## Overlay tier | Token | Default | Note | Themes | | --- | --- | --- | --- | | `--overlay-bg` | `var(--bg-elevated)` | overlay fill | none | | `--overlay-ink` | `var(--ink)` | text in an overlay | none | | `--overlay-border-width` | `1px` | overlay edge width | brutalist, civic | | `--overlay-border` | `var(--rule)` | overlay edge color | brutalist, civic, coder | | `--overlay-shadow` | `var(--shadow-lg)` | overlay box-shadow | all but default | | `--overlay-padding` | `var(--space-1)` | menus, listboxes | all but civic, default | | `--overlay-padding-lg` | `var(--space-4)` | popover, hover card | all but brutalist, dashboard, default | | `--tooltip-bg` | `var(--bg-inverse)` | tooltip fill | none | | `--tooltip-ink` | `var(--ink-inverse)` | tooltip text | none | ## Dialog tier | Token | Default | Note | Themes | | --- | --- | --- | --- | | `--dialog-bg` | `var(--bg-elevated)` | dialog, sheet and drawer fill | none | | `--dialog-border-width` | `1px` | dialog edge width | brutalist, civic, commerce, playful | | `--dialog-border` | `var(--rule)` | dialog edge color | brutalist, civic, coder, dashboard | | `--dialog-shadow` | `var(--shadow-2xl)` | dialog box-shadow | all but default | | `--dialog-padding` | `var(--space-6)` | inner padding | all but brutalist, civic, default | | `--dialog-gap` | `var(--space-4)` | space between header, body and footer | all but brutalist, dashboard, default | | `--dialog-width` | `32rem` | dialog max-width | all but brutalist, default, playful | | `--backdrop` | `rgb(8 12 20 / 0.5)` | the scrim behind a modal | all but default | | `--backdrop-blur` | `0px` | blur behind the scrim | calm, editorial, elements, luxury, marketing, playful | ## Tag tier | Token | Default | Note | Themes | | --- | --- | --- | --- | | `--tag-height` | `1.375rem` | tag height | all but default, elements | | `--tag-padding-x` | `var(--space-2)` | inline padding inside a tag | calm, coder, commerce, luxury, marketing, playful | | `--tag-font-size` | `var(--text-xs)` | tag text size | civic, coder, editorial, luxury | | `--tag-weight` | `var(--weight-medium)` | tag text weight | all but calm, coder, default, luxury | ## Extra radius roles (the rest are style/base's) | Token | Default | Note | Themes | | --- | --- | --- | --- | | `--radius-check` | `var(--radius-xs)` | checkbox box | all but dashboard, default | ## Icons | Token | Default | Note | Themes | | --- | --- | --- | --- | | `--icon-size` | `1rem` | default icon size | civic, coder, commerce, marketing, playful | | `--icon-size-sm` | `0.875rem` | small icon size | civic, coder, commerce, marketing, playful | | `--icon-size-lg` | `1.25rem` | large icon size | calm, civic, coder, commerce, marketing, playful | | `--icon-stroke` | `2` | line icon stroke width, in 24-unit viewBox units | all but civic, coder, default, marketing | ## Color roles the semantic set does not name | Token | Default | Note | Themes | | --- | --- | --- | --- | | `--secondary` | `var(--bg-muted)` | secondary button fill | dashboard, marketing, playful | | `--secondary-ink` | `var(--ink)` | secondary button text | dashboard, marketing | | `--secondary-hover` | `var(--rule)` | secondary button fill on hover | brutalist, civic, coder, dashboard, marketing, playful | | `--link` | `var(--ink)` | link-variant text | all but commerce, default | ## Focus | Token | Default | Note | Themes | | --- | --- | --- | --- | | `--focus-ring-width` | `3px` | ring thickness | none | | `--focus-ring-offset` | `0px` | gap between control and ring | civic | | `--focus-ring-inner` | `var(--bg)` | the gap layer between control and ring, when offset > 0 | civic | | `--focus-ring-color` | `color-mix(in oklab, var(--focus) 45%, transparent)` | ring color | civic | ## Motion | Token | Default | Note | Themes | | --- | --- | --- | --- | | `--duration-enter` | `var(--duration-normal)` | overlays and disclosures opening | all but commerce, default | | `--duration-exit` | `var(--duration-fast)` | overlays and disclosures closing | all but commerce, default, elements, marketing, playful | | `--ease-enter` | `var(--ease-out)` | easing for opening | all but commerce, default, elements, marketing | | `--ease-exit` | `var(--ease-in)` | easing for closing | brutalist, calm, civic, coder, dashboard, luxury | | `--enter-scale` | `0.96` | overlays and dialogs grow from this | all but default | | `--enter-distance` | `0.5rem` | popovers slide this far from their side | all but default | | `--duration-loop` | `var(--duration-slower)` | looping animations multiply it; never 0 | calm, dashboard | | `--caret-blink` | `1120ms` | one blink of a drawn text caret | brutalist, calm, dashboard, elements, luxury, playful |