# Trait Detail Pages, the required template

Every trait detail page under `site/pages/traits/<name>/` follows one binding section template. The 41-page Phase B sweep proved what a loose contract produces: bimodal quality (portfolio-grade pages next to abstract-box demos) and zero pages teaching restraint. Navigate-by-template is the contract. Source: ADR-0019.

Trait pages are this skill's charter (traits live in `packages/web-components/traits/`); `site-docs-authoring` owns `site/pages/{architecture,getting-started,guides,patterns,reference}`, not `traits/`.

## Required sections, in order

| # | Section (`data-property=`) | Required? | Purpose |
|---|---|---|---|
| 1 | `<header>` | always | `<h1>` trait name + `<tag-ui>trait</tag-ui>` + category tag matching `_catalog.json` SoT |
| 2 | `hero` | always | "In context" demo with real product chrome, no abstract boxes |
| 3 | `minimal` | always | Single-tag declarative usage; `<h2>` reads "Bare minimum" |
| 4 | `declarative` | always | `<X traits="trait-name">` code-ui block |
| 5 | `config` | conditional | Only when the trait declares `config` attrs in `defineTrait()`; live sliders + readouts |
| 6 | `reduced-motion` | motion-only | Toggleable `prefers-reduced-motion: reduce` degradation demo. Required for any trait touching transform / opacity / animation |
| 7 | `accessibility` | always | 1–3 bullets on pointer-only, touch-confused, AT-silent reality |
| 8 | `performance` | always | 1 sentence on rAF cost, observer count, listener cost |
| 9 | `when-not-to-use` | always | 2–4 opinionated bullets on overuse, audience-mismatch, perf cost |
| 10 | `api` | always | Auto-stamped from `_api-table.js` |
| 11 | `composes` | always | ≥ 1 trait demonstrated in a WORKING composition; ≥ 4 traits listed |

Trait-specific extras (`state`, `lifecycle`, scenario `usage` recipes) slot between `config` (5) and `accessibility` (7).

## Naming and sourcing rules

- `data-property` values are lowercase hyphen-separated tokens; canonical set as in the table. **`minimal`, not `bare`.**
- `data-artifact-label` values are lowercase descriptive prose ("settle log") OR code-shaped strings describing the demo axis (`speed=120 (slow, dramatic)`). HTML-entity escapes inside attribute values are correct.
- Header category tag MUST match the trait's `category` in `packages/web-components/traits/_catalog.json`, catalog SoT, never page-author judgment.
- Imports in code-ui blocks use the full package name `@adia-ai/web-components/traits`, never internal aliases like `@traits/index.js`.
- Inline-style tokens use canonical names: `--a-border` (dashed borders), `--a-radius-md` / `--a-radius-lg`, `--a-accent` / `--a-accent-fg`.

## The two teeth

- **`when-not-to-use` is the highest-impact section.** A page shipping without it defaults to "this trait is good, please use it", wrong for every trait once overuse, density, or a11y tradeoffs enter. The restraint mandate is the pedagogy differentiator (Motion / GSAP / React Spring all whiff on it). Fewer than 2 bullets requires an articulated why.
- **Composes must SHOW.** Listing trait names with prose-only descriptions does not satisfy the contract, at least one composition runs as a working demo.

No mechanical gate enforces this template yet (ADR-0019's verify-trait-pages.mjs was deferred and does not exist): the 11-section contract is enforced at PR review. Source: ADR-0019.
