# Themes in Depth

The complete theming feature set. For the concept and the render-time model, see **[Theming](../concepts/theming.md)**;
this page catalogs the full surface.

## The token dimensions

A ChainRender theme is a set of **design tokens** (W3C Design Tokens aligned). The full surface:

| Dimension | Tokens |
|---|---|
| **Color** | 23 semantic colors (bg, surface, fg, muted, border, primary, accent, success, warning, danger, info + their foreground pairs, hover/active/focus/disabled/selected) |
| **Series palette** | a 6-color ramp for multi-series charts |
| **Typography** | fontFamily, monoFamily, a size scale (title/heading/body/label/legend), four weights, lineHeight, letterSpacing, textTransform |
| **Spacing** | xs / sm / md / lg / xl |
| **Sizing** | control height, icon size, chart min-width, content max-width |
| **Border** | width, radius, stroke style |
| **Elevation** | none / sm / md / lg shadows |
| **Motion** | fast / base / slow durations, easing |
| **Layering** | z-index scale |
| **Breakpoints** | responsive breakpoints |

Components reference tokens (`var(--cr-space-md)`), never hardcoded values — which is why changing one token
re-flows the whole page.

## Presets

Three presets ship, all fully on-chain and drift-locked between the SDK and the on-chain generator:

- **Light** — the default.
- **Dark** — a genuine dark preset (dark surfaces, light text, brightened series).
- **High-contrast** — WCAG AAA (near-black on white, thicker borders/focus).

## Built-in invariants (an inaccessible theme can't ship)

- **Legibility floor** — no font size below 12px, enforced.
- **Contrast invariant** — every key foreground/background pair meets WCAG AA (AAA for high-contrast), enforced as
  a build-failing check. A low-contrast theme is rejected at build time.

## Render-time application (zero gas)

Themes apply via the presentation context at render time — the same app renders with any theme, no redeploy:

```ts
// Render with a presentation context (theme/palette/dims) via the on-chain
// renderHashWithContext entrypoint. The context is encoded and passed to the router;
// the app hash is unchanged. (See the runtime reference for the exact call.)
const html = await renderComponent({ rpc, router }, hash); // + presentation context
```

And for **whole-page** iteration, override the tokens directly — the token-driven CSS re-flows the entire page in
the browser at zero gas, zero chain calls. See **[Build, Grade & Style Before Deploy](../guides/test-before-deploy.md)**.

## ThemeSets (the theme registry)

Themes are discoverable + shareable via **ThemeSets** — an ownerless, staking-aware theme registry. Author a theme,
preview it locally, then submit it to a ThemeSet so others can find and use it. Themes are content-addressed, so a
theme has a permanent identity like an app.

## Generating theme CSS in code

```ts
import { lightThemeCss, darkThemeCss, fullThemeCss } from "@chainrender/client/runtime";
const css = fullThemeCss(myTokens);   // your token set → the complete component CSS
```

## Related
- **[Presentation & Theming](../concepts/theming.md)** · **[Authoring & Committing a Theme](../guides/authoring-themes.md)**
- **[Theme Without Redeploying](../guides/theme-without-redeploy.md)**
