# DesignOS foundations

Generated from the Figma variable export by `build-tokens.mjs` and `build-docs.mjs`.
**Do not edit by hand** — re-run the generators instead.

| | |
|---|---|
| Source file | `Design - OS` (`aNwqZofj4RJFKLUNhzPePs`) |
| Inspected | 2026-08-17 |
| Colour mode | Light Mode only |
| Radius mode | `6. Themes: Auto (Full)` |
| Typography mode | `5. Typography: Auto (Inter)` |
| Variables | **623** across 7 collections |

## Naming

Figma variable names map to CSS custom properties by the DesignOS §14.1 rule:
lowercase, slashes and spaces collapse to single hyphens, suffix identical to
the Figma name. Category prefixes that would duplicate the suffix are dropped
(`Background/bg-primary` → `--bg-primary`).

Two conventions from the export are easy to get wrong:

- **State suffixes use an underscore** — `--bg-secondary_hover`, not `-hover`.
- **Component theme tokens are bare** — `--button`, `--input`, not `--radius-button`.

## The primitive gate

`7. _Primitive` holds **385** tokens and is excluded from
`tokens.css` entirely. Never reference a primitive directly; if a semantic role
is missing, define one (see *Added roles* below) rather than reaching past the
semantic layer.

## Corrections applied to the export

**None.** Every value is the raw export, verbatim.

| Figma variable | Export | Used | Why |
|---|---|---|---|

## Roles added on top of the export

The export leaves these undefined, and each covers a need that would otherwise
fall back to a raw value.

| Token | Value | Why |
|---|---|---|
| `--text-on-error-solid` | `#ffffff` | on-solid content; text-alt flips per mode, bg-error-solid does not |
| `--text-on-warning-solid` | `#0a0a0a` | white on bg-warning-solid measures 2.15:1 |
| `--text-on-success-solid` | `#0a0a0a` | on-solid content for bg-success-solid |
| `--text-on-info-solid` | `#ffffff` | on-solid content for bg-info-solid |
| `--bg-error-solid_hover` | `#b91c1c` | error/700 — the export defines no error hover; the solid fill deepens on hover |
| `--bg-error-solid_press` | `#991b1b` | error/800 — deepens again on press, two steps below the resting error/600 |
| `--bg-error_press` | `#fecaca` | error/200 — press step for the soft error surface, above bg-error-secondary |
| `--focus-ring-width` | `3px` | shadcn-style ring: one soft band hugging the border, no offset gap |
| `--focus-ring` | `var(--alpha-neutral-accent-20)` | focus band — the export's own neutral accent at 20% |
| `--focus-ring-error` | `var(--alpha-error-accent-20)` | focus band for an invalid control |
| `--border-control` | `#8d8d8d` | interactive control boundary; WCAG 1.4.11 needs 3:1 |
| `--border-focus-ring` | `#171717` | focus treatment named in components §10.3 but untokenised |
| `--shadow-card` | `0 4px 24px rgba(10,10,10,.05)` | elevation must arrive through a named token |
| `--shadow-evidence` | `0 24px 60px rgba(10,10,10,.14)` | elevation must arrive through a named token |
| `--ring-offset` | `var(--bg-primary)` | inner 2px of Ring/*; must match the canvas, not literal white |
| `--ring-brand` | `rgba(10,10,10,0.12)` | outer 4px of the exported Ring/brand effect |
| `--ring-error` | `rgba(255,0,0,0.12)` | outer 4px of the exported Ring/error effect |
| `--motion-state` | `160ms` | no motion tokens in the export; §12 baseline |
| `--motion-ease` | `cubic-bezier(.2,0,0,1)` | no motion tokens in the export; §12 baseline |
| `--line-height-paragraph-md` | `1.5` | line heights live in the text styles, not the variables |
| `--line-height-paragraph-sm` | `1.4286` | line heights live in the text styles, not the variables |
| `--line-height-caption-md` | `1.5` | line heights live in the text styles, not the variables |

## Status families

Badges, alerts and banners read one shared block. Each status sets five custom
properties, so adding a status is one block rather than three.

| Property | Role |
|---|---|
| `--st-soft` | soft fill for large message regions |
| `--st-solid` | strong fill for compact high-emphasis surfaces |
| `--st-border` | boundary |
| `--st-content` | text and icon on the soft fill |
| `--st-on-solid` | text and icon on the strong fill |

Statuses: `default`, `brand`, `success`, `warning`, `error`, `neutral`, `info`.

> **Info** ships in Figma only on Badges. It was added to Alert and Banner using
> the export's existing information family.

> **On-solid content**, by request: white for every status **except warning**,
> which uses `--text-primary`.
>
> | Status | On-solid | Contrast on its fill |
> |---|---|---|
> | Warning | `--text-primary` | **9.22:1** — passes AA |
> | Error | `--text-on-error-solid` | 4.83:1 — passes AA |
> | Info | `--text-on-info-solid` | 5.17:1 — passes AA |
> | Brand / Neutral | `--text-alt` / `--text-white` | high — passes AA |
> | Success | `--text-white` | **2.07:1 — fails AA** |
>
> Success is the one remaining failure. `--text-on-success-solid` (near-black,
> 7.80:1) is already in the token set if you want to close it.

## Radius themes

Components bind to the component theme token, never to a raw radius. Switching
`data-radius` swaps the whole set at once.

| Component theme | Full | Normal | Sharp | Slightly Rounded |
|---|---|---|---|---|
| `--button` | 100000px | 8px | 0px | 12px |
| `--modal` | 32px | 16px | 0px | 20px |
| `--modal-inner-container` | 20px | 12px | 0px | 16px |
| `--input` | 8px | 8px | 0px | 12px |
| `--calendar-header` | 100000px | 12px | 0px | 16px |
| `--pagination` | 100000px | 10px | 0px | 14px |
| `--card` | 12px | 8px | 0px | 12px |
| `--nav-item` | 12px | 8px | 0px | 8px |

## Product surfaces

Selecting a surface means selecting all three values as one contract.

| Surface | Canvas | Page padding | Default gap |
|---|---|---|---|
| `dashboard` | 1440px | 24px | 24px |
| `website` | 1440px | 128px | 24px |
| `tablet` | 768px | 24px | 16px |
| `mobile` | 375px | 16px | 16px |

## Colour

### Text — 20 tokens

| Token | Value | Figma variable |
|---|---|---|
| `--text-primary` | `#0a0a0a` | `Text/text-primary` |
| `--text-secondary` | `#404040` | `Text/text-secondary` |
| `--text-tertiary` | `#525252` | `Text/text-tertiary` |
| `--text-quarternary` | `#737373` | `Text/text-quarternary` |
| `--text-disabled` | `#a3a3a3` | `Text/text-disabled` |
| `--text-error` | `#dc2626` | `Text/text-error` |
| `--text-error-secondary` | `#f87171` | `Text/text-error-secondary` |
| `--text-warning` | `#d97706` | `Text/text-warning` |
| `--text-warning-secondary` | `#fbbf24` | `Text/text-warning-secondary` |
| `--text-success` | `#059669` | `Text/text-success` |
| `--text-brand` | `#171717` | `Text/text-brand` |
| `--text-brand-secondary` | `#a3a3a3` | `Text/text-brand-secondary` |
| `--text-alt` | `#ffffff` | `Text/text-alt` |
| `--text-placeholder` | `#a3a3a3` | `Text/text-placeholder` |
| `--text-placeholder-alt` | `#d4d4d4` | `Text/text-placeholder-alt` |
| `--text-success-secondary` | `#34d399` | `Text/text-success-secondary` |
| `--text-white` | `#ffffff` | `Text/text-white` |
| `--text-dark` | `#000000` | `Text/text-dark` |
| `--text-info` | `#2563eb` | `Text/text-info` |
| `--text-info-secondary` | `#60a5fa` | `Text/text-info-secondary` |

### Background — 33 tokens

| Token | Value | Figma variable |
|---|---|---|
| `--bg-primary` | `#ffffff` | `Background/bg-primary` |
| `--bg-primary_hover` | `#f7f7f7` | `Background/bg-primary_hover` |
| `--bg-secondary` | `#f7f7f7` | `Background/bg-secondary` |
| `--bg-tertiary` | `#f0f0f0` | `Background/bg-tertiary` |
| `--bg-quarternary` | `#e5e5e5` | `Background/bg-quarternary` |
| `--bg-disabled` | `#f7f7f7` | `Background/bg-disabled` |
| `--bg-error` | `#fef2f2` | `Background/bg-error` |
| `--bg-error-secondary` | `#fee2e2` | `Background/bg-error-secondary` |
| `--bg-warning` | `#fffbeb` | `Background/bg-warning` |
| `--bg-warning-secondary` | `#fef3c7` | `Background/bg-warning-secondary` |
| `--bg-success` | `#ecfdf5` | `Background/bg-success` |
| `--bg-brand-primary` | `#f7f7f7` | `Background/bg-brand-primary` |
| `--bg-brand-secondary` | `#f0f0f0` | `Background/bg-brand-secondary` |
| `--bg-alt` | `#171717` | `Background/bg-alt` |
| `--bg-error-solid` | `#dc2626` | `Background/bg-error-solid` |
| `--bg-success-secondary` | `#d1fae5` | `Background/bg-success-secondary` |
| `--bg-success-solid` | `#10b981` | `Background/bg-success-solid` |
| `--bg-warning-solid` | `#f59e0b` | `Background/bg-warning-solid` |
| `--bg-brand-primary_hover` | `#f0f0f0` | `Background/bg-brand-primary_hover` |
| `--bg-brand-solid` | `#0a0a0a` | `Background/bg-brand-solid` |
| `--bg-primary_press` | `#f0f0f0` | `Background/bg-primary_press` |
| `--bg-dark` | `#171717` | `Background/bg-dark` |
| `--bg-white` | `#ffffff` | `Background/bg-white` |
| `--bg-info` | `#eff6ff` | `Background/bg-info` |
| `--bg-info-secondary` | `#dbeafe` | `Background/bg-info-secondary` |
| `--bg-info-solid` | `#2563eb` | `Background/bg-info-solid` |
| `--bg-secondary_hover` | `#f0f0f0` | `Background/bg-secondary_hover` |
| `--bg-secondary_press` | `#e5e5e5` | `Background/bg-secondary_press` |
| `--bg-brand-hover` | `#262626` | `Background/bg-brand-hover` |
| `--bg-brand-press` | `#404040` | `Background/bg-brand-press` |
| `--black` | `#000000` | `Background/black` |
| `--white` | `#ffffff` | `Background/white` |
| `--bg-brand-primary_press` | `#e5e5e5` | `Background/bg-brand-primary_press` |

### Border — 17 tokens

| Token | Value | Figma variable |
|---|---|---|
| `--border-primary` | `#f0f0f0` | `Border/border-primary` |
| `--border-secondary` | `#e5e5e5` | `Border/border-secondary` |
| `--border-tertiary` | `#d4d4d4` | `Border/border-tertiary` |
| `--border-disabled` | `#f0f0f0` | `Border/border-disabled` |
| `--border-error` | `#dc2626` | `Border/border-error` |
| `--border-error-secondary` | `#fecaca` | `Border/border-error-secondary` |
| `--border-warning` | `#d97706` | `Border/border-warning` |
| `--border-warning-secondary` | `#fde68a` | `Border/border-warning-secondary` |
| `--border-success` | `#059669` | `Border/border-success` |
| `--border-brand` | `#171717` | `Border/border-brand` |
| `--border-brand-secondary` | `#e5e5e5` | `Border/border-brand-secondary` |
| `--border-success-secondary` | `#a7f3d0` | `Border/border-success-secondary` |
| `--border-white` | `#ffffff` | `Border/border-white` |
| `--border-info` | `#2563eb` | `Border/border-info` |
| `--border-info-secondary` | `#bfdbfe` | `Border/border-info-secondary` |
| `--border-alt` | `#ffffff` | `Border/border-alt` |
| `--border-alt-2` | `#000000` | `Border/border-alt-2` |

### Icon — 19 tokens

| Token | Value | Figma variable |
|---|---|---|
| `--icon-primary` | `#171717` | `Icon/icon-primary` |
| `--icon-secondary` | `#525252` | `Icon/icon-secondary` |
| `--icon-tertiary` | `#737373` | `Icon/icon-tertiary` |
| `--icon-disabled` | `#a3a3a3` | `Icon/icon-disabled` |
| `--icon-error` | `#dc2626` | `Icon/icon-error` |
| `--icon-error-secondary` | `#f87171` | `Icon/icon-error-secondary` |
| `--icon-warning` | `#d97706` | `Icon/icon-warning` |
| `--icon-warning-secondary` | `#fbbf24` | `Icon/icon-warning-secondary` |
| `--icon-success` | `#059669` | `Icon/icon-success` |
| `--icon-brand` | `#171717` | `Icon/icon-brand` |
| `--icon-brand-secondary` | `#a3a3a3` | `Icon/icon-brand-secondary` |
| `--icon-success-secondary` | `#34d399` | `Icon/icon-success-secondary` |
| `--icon-dark` | `#0a0a0a` | `Icon/icon-dark` |
| `--icon-white` | `#ffffff` | `Icon/icon-white` |
| `--icon-alt` | `#ffffff` | `Icon/icon-alt` |
| `--icon-info` | `#2563eb` | `Icon/icon-info` |
| `--icon-info-secondary` | `#60a5fa` | `Icon/icon-info-secondary` |
| `--icon-quarternary` | `#a3a3a3` | `Icon/icon-quarternary` |
| `--icon-quinary` | `#d4d4d4` | `Icon/icon-quinary` |

### Charts — 12 tokens

| Token | Value | Figma variable |
|---|---|---|
| `--chart-blue` | `#3b82f6` | `Charts/Blue` |
| `--chart-orange` | `#fb923c` | `Charts/Orange` |
| `--chart-green` | `#16a34a` | `Charts/Green` |
| `--chart-red` | `#dc2626` | `Charts/Red` |
| `--chart-purple` | `#a855f7` | `Charts/Purple` |
| `--chart-yellow` | `#facc15` | `Charts/Yellow` |
| `--chart-pink` | `#ec4899` | `Charts/Pink` |
| `--chart-dark` | `#525252` | `Charts/Dark` |
| `--chart-lime` | `#65a30d` | `Charts/Lime` |
| `--chart-cyan` | `#06b6d4` | `Charts/Cyan` |
| `--chart-success` | `#10b981` | `Charts/Success` |
| `--chart-success-light` | `#6ee7b7` | `Charts/Success Light` |

### Opacity — 18 tokens

| Token | Value | Figma variable |
|---|---|---|
| `--opacity-light-10` | `#ffffff1a` | `Opacity/opacity-light-10` |
| `--opacity-light-20` | `#ffffff33` | `Opacity/opacity-light-20` |
| `--opacity-light-30` | `#ffffff4d` | `Opacity/opacity-light-30` |
| `--opacity-light-40` | `#ffffff66` | `Opacity/opacity-light-40` |
| `--opacity-light-50` | `#ffffff80` | `Opacity/opacity-light-50` |
| `--opacity-light-60` | `#ffffff99` | `Opacity/opacity-light-60` |
| `--opacity-light-70` | `#ffffffb2` | `Opacity/opacity-light-70` |
| `--opacity-light-80` | `#ffffffcc` | `Opacity/opacity-light-80` |
| `--opacity-light-90` | `#ffffffe5` | `Opacity/opacity-light-90` |
| `--opacity-dark-10` | `#0000001a` | `Opacity/opacity-dark-10` |
| `--opacity-dark-20` | `#00000033` | `Opacity/opacity-dark-20` |
| `--opacity-dark-30` | `#0000004d` | `Opacity/opacity-dark-30` |
| `--opacity-dark-40` | `#00000066` | `Opacity/opacity-dark-40` |
| `--opacity-dark-50` | `#00000080` | `Opacity/opacity-dark-50` |
| `--opacity-dark-60` | `#00000099` | `Opacity/opacity-dark-60` |
| `--opacity-dark-70` | `#000000b2` | `Opacity/opacity-dark-70` |
| `--opacity-dark-80` | `#000000cc` | `Opacity/opacity-dark-80` |
| `--opacity-dark-90` | `#000000e5` | `Opacity/opacity-dark-90` |

### Alpha — 30 tokens

| Token | Value | Figma variable |
|---|---|---|
| `--alpha-brand-accent-85` | `#0a0a0ad9` | `Alpha/brand/accent 85` |
| `--alpha-brand-accent-10` | `#0a0a0a1a` | `Alpha/brand/accent 10` |
| `--alpha-brand-accent-40` | `#0a0a0a66` | `Alpha/brand/accent 40` |
| `--alpha-brand-accent-60` | `#0a0a0a99` | `Alpha/brand/accent 60` |
| `--alpha-brand-accent-20` | `#0a0a0a33` | `Alpha/brand/accent 20` |
| `--alpha-neutral-accent-10` | `#0a0a0a1a` | `Alpha/neutral/accent 10` |
| `--alpha-neutral-accent-20` | `#0a0a0a33` | `Alpha/neutral/accent 20` |
| `--alpha-neutral-accent-40` | `#0a0a0a66` | `Alpha/neutral/accent 40` |
| `--alpha-neutral-accent-60` | `#0a0a0a99` | `Alpha/neutral/accent 60` |
| `--alpha-neutral-accent-85` | `#0a0a0ad9` | `Alpha/neutral/accent 85` |
| `--alpha-success-accent-10` | `#0596691a` | `Alpha/success/accent 10` |
| `--alpha-success-accent-20` | `#05966933` | `Alpha/success/accent 20` |
| `--alpha-success-accent-40` | `#05966966` | `Alpha/success/accent 40` |
| `--alpha-success-accent-60` | `#05966999` | `Alpha/success/accent 60` |
| `--alpha-success-accent-85` | `#059669d9` | `Alpha/success/accent 85` |
| `--alpha-warning-accent-10` | `#f59e0b1a` | `Alpha/warning/accent 10` |
| `--alpha-warning-accent-20` | `#f59e0b33` | `Alpha/warning/accent 20` |
| `--alpha-warning-accent-40` | `#f59e0b66` | `Alpha/warning/accent 40` |
| `--alpha-warning-accent-60` | `#f59e0b99` | `Alpha/warning/accent 60` |
| `--alpha-warning-accent-85` | `#f59e0bd9` | `Alpha/warning/accent 85` |
| `--alpha-blue-accent-10` | `#2563eb1a` | `Alpha/blue/accent 10` |
| `--alpha-blue-accent-20` | `#2563eb33` | `Alpha/blue/accent 20` |
| `--alpha-blue-accent-40` | `#2563eb66` | `Alpha/blue/accent 40` |
| `--alpha-blue-accent-60` | `#2563eb99` | `Alpha/blue/accent 60` |
| `--alpha-blue-accent-85` | `#2563ebd9` | `Alpha/blue/accent 85` |
| `--alpha-error-accent-10` | `#dc26261a` | `Alpha/error/accent 10` |
| `--alpha-error-accent-20` | `#dc262633` | `Alpha/error/accent 20` |
| `--alpha-error-accent-40` | `#dc262666` | `Alpha/error/accent 40` |
| `--alpha-error-accent-60` | `#dc262699` | `Alpha/error/accent 60` |
| `--alpha-error-accent-85` | `#dc2626d9` | `Alpha/error/accent 85` |



## Scales

### 2. Spacing & Size — 50 tokens

| Token | Value | Figma variable |
|---|---|---|
| `--spacing-0` | `0px` | `UI Spacing/spacing-0` |
| `--spacing-2` | `2px` | `UI Spacing/spacing-2` |
| `--spacing-4` | `4px` | `UI Spacing/spacing-4` |
| `--spacing-6` | `6px` | `UI Spacing/spacing-6` |
| `--spacing-8` | `8px` | `UI Spacing/spacing-8` |
| `--spacing-12` | `12px` | `UI Spacing/spacing-12` |
| `--spacing-16` | `16px` | `UI Spacing/spacing-16` |
| `--spacing-20` | `20px` | `UI Spacing/spacing-20` |
| `--spacing-24` | `24px` | `UI Spacing/spacing-24` |
| `--spacing-32` | `32px` | `UI Spacing/spacing-32` |
| `--spacing-40` | `40px` | `UI Spacing/spacing-40` |
| `--spacing-48` | `48px` | `UI Spacing/spacing-48` |
| `--spacing-56` | `56px` | `UI Spacing/spacing-56` |
| `--spacing-64` | `64px` | `UI Spacing/spacing-64` |
| `--spacing-96` | `96px` | `UI Spacing/spacing-96` |
| `--spacing-128` | `128px` | `UI Spacing/spacing-128` |
| `--spacing-160` | `160px` | `UI Spacing/spacing-160` |
| `--spacing-192` | `192px` | `UI Spacing/spacing-192` |
| `--spacing-224` | `224px` | `UI Spacing/spacing-224` |
| `--spacing-256` | `256px` | `UI Spacing/spacing-256` |
| `--spacing-320` | `320px` | `UI Spacing/spacing-320` |
| `--spacing-384` | `384px` | `UI Spacing/spacing-384` |
| `--spacing-480` | `480px` | `UI Spacing/spacing-480` |
| `--spacing-560` | `560px` | `UI Spacing/spacing-560` |
| `--spacing-640` | `640px` | `UI Spacing/spacing-640` |
| `--spacing-720` | `720px` | `UI Spacing/spacing-720` |
| `--spacing-768` | `768px` | `UI Spacing/spacing-768` |
| `--spacing-960` | `960px` | `UI Spacing/spacing-960` |
| `--spacing-1280` | `1280px` | `UI Spacing/spacing-1280` |
| `--spacing-1440` | `1440px` | `UI Spacing/spacing-1440` |
| `--spacing-1920` | `1920px` | `UI Spacing/spacing-1920` |
| `--screen-size` | `1440px` | `Screen Size/Size` |
| `--padding-padding` | `24px` | `Padding/padding` |
| `--spacing-1024` | `1024px` | `UI Spacing/spacing-1024` |
| `--spacing-80` | `80px` | `UI Spacing/spacing-80` |
| `--spacing-1080` | `1080px` | `UI Spacing/spacing-1080` |
| `--gap-gap` | `24px` | `Gap/gap` |
| `--spacing-72` | `72px` | `UI Spacing/spacing-72` |
| `--font-size-display` | `72px` | `Font Size/display` |
| `--font-size-header-h1` | `60px` | `Font Size/header-h1` |
| `--font-size-header-h2` | `48px` | `Font Size/header-h2` |
| `--font-size-header-h3` | `36px` | `Font Size/header-h3` |
| `--font-size-header-h4` | `30px` | `Font Size/header-h4` |
| `--font-size-header-h5` | `24px` | `Font Size/header-h5` |
| `--font-size-header-h6` | `20px` | `Font Size/header-h6` |
| `--font-size-paragraph-lg` | `18px` | `Font Size/paragraph-lg` |
| `--font-size-paragraph-md` | `16px` | `Font Size/paragraph-md` |
| `--font-size-paragraph-sm` | `14px` | `Font Size/paragraph-sm` |
| `--font-size-caption-md` | `12px` | `Font Size/caption-md` |
| `--font-size-caption-sm` | `10px` | `Font Size/caption-sm` |

### 3. Radius — 11 tokens

| Token | Value | Figma variable |
|---|---|---|
| `--radius-none` | `0px` | `radius-none` |
| `--radius-xxs` | `2px` | `radius-xxs` |
| `--radius-xs` | `4px` | `radius-xs` |
| `--radius-sm` | `6px` | `radius-sm` |
| `--radius-md` | `8px` | `radius-md` |
| `--radius-lg` | `12px` | `radius-lg` |
| `--radius-xl` | `16px` | `radius-xl` |
| `--radius-2xl` | `20px` | `radius-2xl` |
| `--radius-3xl` | `24px` | `radius-3xl` |
| `--radius-4xl` | `32px` | `radius-4xl` |
| `--radius-full` | `100000px` | `radius-full` |

### 4. Widths — 12 tokens

| Token | Value | Figma variable |
|---|---|---|
| `--width-xxs` | `320px` | `width-xxs` |
| `--width-xs` | `384px` | `width-xs` |
| `--width-sm` | `480px` | `width-sm` |
| `--width-md` | `560px` | `width-md` |
| `--width-lg` | `640px` | `width-lg` |
| `--width-xl` | `768px` | `width-xl` |
| `--width-2xl` | `1024px` | `width-2xl` |
| `--width-3xl` | `1080px` | `width-3xl` |
| `--width-4xl` | `1280px` | `width-4xl` |
| `--width-5xl` | `1440px` | `width-5xl` |
| `--width-6xl` | `1920px` | `width-6xl` |
| `--width-xxxs` | `256px` | `width-xxxs` |

### 5. Typography — 8 tokens

| Token | Value | Figma variable |
|---|---|---|
| `--family-display` | `Inter` | `Family/display` |
| `--weight-regular` | `regular` | `Weight/regular` |
| `--family-heading` | `Inter` | `Family/heading` |
| `--family-text` | `Inter` | `Family/text` |
| `--family-caption` | `Inter` | `Family/caption` |
| `--weight-bold` | `bold` | `Weight/bold` |
| `--weight-medium` | `medium` | `Weight/medium` |
| `--weight-semibold` | `semibold` | `Weight/semibold` |

## Known issues

- The input resting border `--border-primary` measures ~1.1:1 on `--bg-primary`,
  below the 3:1 WCAG 1.4.11 minimum for control boundaries. Reproduced faithfully
  from the source; use `--border-control` before shipping.
- Button `sm` (32px) and `md` (40px) fall below the 44px touch-target minimum.
- The export stores font weights as words and carries no line heights; both are
  mapped in `tokens.css` and listed as added roles.
- Light Mode collapses `bg-secondary`, `bg-primary_hover`, `bg-brand-primary`
  and `bg-disabled` onto `#f7f7f7`. A selected row only reads as selected on
  `bg-primary`; express selection with a border or weight change as well.
