# Theme Contract (the "theme API") — v1

A theme is one file: `themes/<name>.css`. It declares **only** custom properties
inside `@layer theme { [data-theme="<name>"] { … } }`, with an optional
`@media (prefers-color-scheme: dark)` override of the same selector. Select it via
the build's `site.config.json` `theme` field (the build sets `<html data-theme="…">`).

You MUST define every token below (and `--contract-version: 1`). You MUST NOT edit
`reset.css`, `structure.css`, any class name, or any template — re-skinning is pure data.

## Required tokens (v1 baseline — permanent)
- **Meta:** `--contract-version`
- **Color roles:** `--bg --surface --surface-2 --text --text-muted --border --accent --accent-base --on-accent --link --focus-ring`
- **Fonts:** `--font-sans --font-display --font-mono`
- **Type scale:** `--step--1 --step-0 --step-1 --step-2 --step-3 --step-4`
- **Spacing/layout:** `--space-3xs --space-2xs --space-xs --space-s --space-m --space-l --space-xl --space-2xl --space-3xl --gutter --measure`
- **Form:** `--radius-sm --radius --radius-lg --border-width --shadow-1 --shadow-2`
- **Motion:** `--ease --dur-fast --dur --dur-slow`

## Versioning & graceful degradation
`--contract-version` is an integer; the list above is the permanent **v1 baseline**
(never removed/renamed). When a future structural feature needs a new token,
`structure.css` references it as `var(--newer, var(--baseline))` — a fallback to a
v1 baseline token, never a raw value — so a v1 theme that omits it degrades instead
of breaking. A build test fails if `structure.css` uses a non-baseline token without
a fallback. Mirrors the data `schemaVersion` discipline.

## Per-type accents
`structure.css`'s `@layer type-accents` derives each content type's `--accent` from
your `--accent-base` via relative `oklch()`. A theme that does nothing special still
works — types just shift hue from your base accent.
