zudo-doc ships its layout and content components from the `@takazudo/zudo-doc` package. Those components hardcode their zudo-wind utility classes — the doc-page title is literally `<h1 class="text-heading font-bold">`. That is the right call for a shipped component (see [Component First Strategy](https://zudo-doc.takazudomodular.com/docs/reference/component-first)), but it leaves consumers a question: how do you re-style a component you do not own?

The `--zdc-*` **component tokens** are the answer. They are a small, curated set of CSS custom properties that the package exposes as supported override seams — redefine one in your own `:root` and the matching component restyles across every route, with no `!important` and no eject.

## The component-library ownership inversion

The usual component-first guidance is: _the component is the abstraction, so if you want a different look, change the component._ That works when the component is yours. Here it is not — it lives in `node_modules/@takazudo/zudo-doc`. Editing it means forking or ejecting the whole component, and trying to override it from the outside means fighting unlayered zudo-wind utility specificity with `!important`. Both are bad doors.

So the conclusion inverts. When you cannot edit the component file, **the component token becomes your scope.** Instead of reaching into the component, you redefine a value the component already reads. The component-first rule still holds inside the package; the `--zdc-*` surface is simply the seam it exposes outward.

[Dynamic content unavailable in text export]

This is the opposite of "component-first, so skip component tokens." That shortcut assumes you own the component. For a packaged component you do not own, the component token is the _only_ clean override point — so it is exactly where your customization belongs.



## The one-line override

Every `--zdc-*` token is redefined the same way: declare it on `:root`. There is no API to import, no component to wrap, and no build step to run.

```css title="src/styles/global.css"
:root {
  --zdc-doc-title-font: "Georgia", serif;
  --zdc-doc-title-weight: 800;
}
```

That single block rebrands the page-title `<h1>` on every page — doc pages, the home page, tag pages, the versions page — because `:root` is global and the backing rule is unlayered with enough specificity to beat the component's own utility class. No `!important` is needed, and you never touch the package source.

The defaults are deliberately invisible. Each token falls back to an existing design token or `inherit` (for example `--zdc-doc-title-weight` defaults to `var(--font-weight-bold)`, matching the original `font-bold` utility), so a project that overrides nothing renders byte-for-byte as before. You only opt in to the tokens you actually want to change.

## How it fits the three-tier token story

zudo-doc's tokens are organized into three tiers, each referencing only the tier above it: raw **palette** values (Tier 1) flow into **semantic** tokens (Tier 2), which feed **component** tokens (Tier 3). See [Design System](https://zudo-doc.takazudomodular.com/docs/reference/design-system) and [Color](https://zudo-doc.takazudomodular.com/docs/reference/color) for the full model.

`--zdc-*` tokens are Tier 3 — component-scoped. But unlike the internal Tier-3 color variables inside `.zd-content` (which are private implementation details you should not reference), `--zdc-*` tokens are **published as a public API**: stable, documented names you are meant to redefine. They extend the same proven pattern the color system already uses, where redefining a `--zd-*` palette token in `:root` re-themes the whole site. `--zdc-*` brings that one-line `:root` override model to component typography.

## Token reference

The tables below list every `--zdc-*` token. They are sourced directly from the registry, so they always match what the package ships.

Tokens are split by **rendering surface**. Content tokens target the `.zd-content` prose area (shipped in `@takazudo/zudo-doc/content.css`). Chrome tokens target the app shell — the document body, the header, sidebar navigation, the TOC, and card grids (shipped in `@takazudo/zudo-doc/features.css`).

### Content tokens

| Token | Component | Default | What it controls |
| --- | --- | --- | --- |
| `--zdc-doc-title-font` | `doc-title` | `inherit` | Font family of the page-title `<h1>` (doc-page titles plus the home, tag, and versions page titles that share `text-heading`). |
| `--zdc-doc-title-weight` | `doc-title` | `var(--font-weight-bold)` | Font weight of the page-title `<h1>`. |
| `--zdc-doc-title-tracking` | `doc-title` | `var(--tracking-normal)` | Letter spacing of the page-title `<h1>`. Defaults to `var(--tracking-normal)` (resolves to `normal` — byte-identical to the browser default). |
| `--zdc-doc-h2-font` | `heading-h2` | `inherit` | Font family of content `<h2>` headings. |
| `--zdc-doc-h2-weight` | `heading-h2` | `var(--font-weight-bold)` | Font weight of content `<h2>` headings. |
| `--zdc-doc-h2-tracking` | `heading-h2` | `var(--tracking-normal)` | Letter spacing of content `<h2>` headings. |
| `--zdc-doc-h3-weight` | `heading-h3` | `var(--font-weight-bold)` | Font weight of content `<h3>` headings. |
| `--zdc-doc-h4-weight` | `heading-h4` | `var(--font-weight-semibold)` | Font weight of content `<h4>` headings. |
| `--zdc-doc-prose-font` | `doc-prose` | `var(--font-sans)` | Font family of the `.zd-content` prose area. Redefine to use a distinct body font for doc content; headings with `--zdc-doc-*-font: inherit` inherit this value. |
| `--zdc-doc-link-decoration` | `content-link` | `underline` | Text decoration of prose links only — the `text-accent underline` path in ContentLink (`a.text-accent.underline`); excludes block and hash-link variants and never matches chrome links, including the underlined home hero and footer copyright rows (those are `text-fg`). Set to `none` to remove underlines from prose links. |
| `--zdc-admonition-radius` | `admonition` | `0 var(--radius-DEFAULT) var(--radius-DEFAULT) 0` | Border radius of admonition/callout blocks. Defaults to the current value (0 on the left edges, `--radius-DEFAULT` on the right — the flush-left accent look). |
| `--zdc-admonition-border-width` | `admonition` | `4px` | Width of the admonition left accent border. |

### Chrome tokens

| Token | Component | Default | What it controls |
| --- | --- | --- | --- |
| `--zdc-card-radius` | `card-grid` | `var(--zdc-surface-radius, var(--radius-DEFAULT))` | Border radius of nav/doc card anchors (doc-card-grid, nav-card-grid, category-nav). Chains through `--zdc-surface-radius` — see below. |
| `--zdc-content-max-width` | `doc-content-band` | `clamp(50rem,75vw,90rem)` | Max width of the doc reading column (sidebar-present case). The no-sidebar 80 rem variant is handled separately by `[data-zd-nosidebar]` in features.css. |
| `--zdc-toc-width` | `toc` | `280px` | Width of the desktop Table of Contents right rail. |
| `--zdc-nav-active-indicator-color` | `nav-active` | `var(--color-fg)` | Background color of the active sidebar nav link (the inversion fill that marks the current page). |
| `--zdc-nav-active-weight` | `nav-active` | `var(--font-weight-medium)` | Font weight of the active sidebar nav link. |
| `--zdc-chrome-font` | `chrome` | `var(--font-sans)` | Base font family of the document `body` — the seam that lets a theme pack's `--font-sans` reach the whole app shell (header, sidebar, TOC, breadcrumb, footer), not just `.zd-content` prose. Redefine `--font-sans` to restyle chrome and content together, or `--zdc-chrome-font` directly to move the shell independently of prose. |
| `--zdc-header-font` | `header` | `var(--zdc-chrome-font, var(--font-sans))` | Font family of the site header (`header[data-header]`). A no-op until redefined; set it to give the header its own face (for example a display font for the wordmark and nav) without touching the rest of the chrome. |
| `--zdc-header-logo-font` | `header-logo` | `inherit` | Font family of the site-name anchor (`a[data-header-logo]`) only. Theme packs with explicit logo fonts preserve their existing family as fallback. |
| `--zdc-header-logo-weight` | `header-logo` | `var(--font-weight-bold)` | Font weight of the site-name anchor only. Theme packs with explicit logo weights preserve their existing weight as fallback. |
| `--zdc-sidebar-font` | `sidebar` | `var(--zdc-chrome-font, var(--font-sans))` | Font family of the navigation sidebar. The selector names both the desktop rail (`#desktop-sidebar`) and the mobile drawer (`aside[data-zd-mobile-sidebar]`) — both match in the production build (see the note below the table). |
| `--zdc-toc-font` | `toc` | `var(--zdc-chrome-font, var(--font-sans))` | Font family of the table of contents. The selector names both the desktop rail (`nav[data-zd-toc]`) and the mobile TOC (`div[data-zd-mobile-toc]`) — both match in the production build (see the note below the table). |

[Dynamic content unavailable in text export]

`--zdc-sidebar-font` and `--zdc-toc-font` are optional per-surface art-direction hooks, not tokens every pack is expected to set — the chrome font seam (`--zdc-chrome-font`, defaulting to `--font-sans`) already delivers a single cohesive typeface across the whole shell, which is what every bundled theme pack wants. Reach for one of these only when a pack deliberately wants the sidebar or TOC to diverge from the rest of the chrome.

The component selectors cover desktop and mobile chrome. Check their computed values on built pages, including repeated client navigation; retained islands preserve unchanged effective identity and props, while changed identity or props recreate their render scope.



### Wordmark typography

Use the logo tokens to change only the site name while navigation, search and language controls retain their typography. The default theme inherits the header family and uses `--font-weight-bold`; bundled packs retain their own logo family and weight until overridden. Each token works independently. Remove its declaration to restore the theme's fallback.

```css title="src/styles/global.css"
:root {
  --zdc-header-logo-font: "Georgia", serif;
  --zdc-header-logo-weight: 400;
}
```

### The `--zdc-surface-radius` meta-knob

`--zdc-surface-radius` is **not a registry entry** — it has no backing CSS rule of its own. It exists as a link in the default chain of `--zdc-card-radius`:

```
var(--zdc-card-radius, var(--zdc-surface-radius, var(--radius-DEFAULT)))
```

Set `--zdc-surface-radius` in `:root` and every surface that opts into the chain rounds together — without overriding each token individually:

```css title="src/styles/global.css"
:root {
  --zdc-surface-radius: 0.75rem; /* rounds all surfaces at once */
}
```

This is the "round everything at once" knob. Individual surfaces can still break out by setting their own `--zdc-card-radius` (or future surface tokens) directly; the meta-knob only wins when the per-surface token is unset.

[Dynamic content unavailable in text export]

Font family (`-font`), font weight (`-weight`), and letter spacing (`-tracking`) are kept as separate, granular tokens rather than a single `font` shorthand. The CSS `font` shorthand resets every sub-property it does not name (size, line-height, style), which would both break the byte-identical default and reduce control — you could not change the weight without restating the family and size. Independent knobs stay independent tokens.



## Not editable in the Design Token Panel

These are **source-level override seams**, not live-tweakable values.

[Dynamic content unavailable in text export]

The [Design Token Panel](https://zudo-doc.takazudomodular.com/docs/reference/design-token-panel) edits the semantic spacing, font, size, and color tokens live in the browser. The `--zdc-*` component tokens are deliberately outside its scope: they are component-owned rebrand seams you set once in `:root` (in `src/styles/global.css`), not knobs you drag at runtime. If you are looking for a token in the panel and cannot find it, it is a component token — set it in your stylesheet instead.



## Discovering the full set

The registry that backs the table above is the typed source of truth. It is exported from the package as `@takazudo/zudo-doc/component-tokens` (the `COMPONENT_TOKENS` array), so the complete, current list — token name, component, default, and description — is discoverable and type-checked in code, not just in this page. When the package adds a new component token, it appears in that export, and this reference is regenerated from it.