diff --git a/data/repo-awareness-snapshot.json b/data/repo-awareness-snapshot.json
index 0a4eb0bf2c..d4f5825035 100644
--- a/data/repo-awareness-snapshot.json
+++ b/data/repo-awareness-snapshot.json
@@ -1,8 +1,8 @@
{
"version": "repo-awareness-snapshot-v1",
"captured_revision": {
- "sha": "9b26a3d69b447c5fa3d45b4e011b26ba46c32b69",
- "committed_at": "2026-08-27T12:01:45+00:00"
+ "sha": "6b2d6f421ee2b2e33f4ccf4fa1d31581b452d4b4",
+ "committed_at": "2026-08-27T12:18:53+00:00"
},
"routes": {
"modes": [
@@ -2389,7 +2389,7 @@
{
"path": "docs/design-system/FIX-GUIDE.md",
"section": "design-system",
- "catalogued": false
+ "catalogued": true
},
{
"path": "docs/design-system/GATES.md",
@@ -3873,8 +3873,8 @@
],
"counts": {
"documents": 481,
- "catalogued": 106,
- "uncatalogued": 375,
+ "catalogued": 107,
+ "uncatalogued": 374,
"sections": 19
}
},
diff --git a/docs/README.md b/docs/README.md
index 6098437cc7..9491881913 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -36,6 +36,7 @@ npm run docs:check-links
- [design-system/COMPONENTS.md](design-system/COMPONENTS.md) — the eight safety-component specifications plus the maturity matrix
- [design-system/DECISIONS.md](design-system/DECISIONS.md) — conflicts C1–C5 resolved, clinical Q&A record, assumptions, blocked items
- [design-system/GATES.md](design-system/GATES.md) — every design-system rule paired with its enforcement status
+- [design-system/FIX-GUIDE.md](design-system/FIX-GUIDE.md) — Hazard 1–2 sweep dispositions (Fixed / Documented / Deferred / Out-of-scope)
- [design-system/ADOPTION.md](design-system/ADOPTION.md) — PR 13 registration record: adoption order, per-surface file allowlists, exclusions, pins, proof shots
- [comparison-behaviour.md](comparison-behaviour.md) — shared selection, state, responsive, and accessibility contract for comparison surfaces
- [clinical-chat-ui-component-map.md](clinical-chat-ui-component-map.md) — chat UI component inventory
diff --git a/docs/design-system/COMPONENTS.md b/docs/design-system/COMPONENTS.md
index b64d1c5a90..4efef5d55d 100644
--- a/docs/design-system/COMPONENTS.md
+++ b/docs/design-system/COMPONENTS.md
@@ -39,14 +39,21 @@ _Remaining from the original eight in this document:_ `DocumentFrame` is built l
(`src/components/ui/document-frame.tsx`, shell-only in `DocumentViewer`) but is not yet among
the 55 design-sync registered visual exports — registration and full controls remain follow-up.
+`AppliedFilters` (`src/components/ui/applied-filters.tsx`) and `CopyButton`
+(`src/components/ui/copy-button.tsx`) are built, proof-migrated (CatalogueToolbar chip row
+and answer-status copy control), and covered by DOM tests. They are **not** design-sync
+registered — do not count them toward the 55 visual exports, and do not treat them as
+specified-not-built. Registration remains follow-up (the Chip/Button add path is a 55-row
+cascade).
+
`OverlayRoot`, `SegmentedControl`, and the PR 6–8 components are built and represented by the
local publication contract. The generated snapshot records their current product-import counts;
registration still proves only a source/API/preview/test reference and does not prove remote
design-project publication or browser acceptance.
_P1 reusable (specified in outline only):_ `Menu`/`Popover` · `KeyValue` ·
-`AppliedFilters`/`FilterSheet` · `ResponsiveActionGroup` · `ScrollableStrip`/
-`ScrollAffordance` · `SourceLink` · `Banner` · `CopyButton`/`CopyField` ·
+`FilterSheet` · `ResponsiveActionGroup` · `ScrollableStrip`/
+`ScrollAffordance` · `SourceLink` · `Banner` · `CopyField` ·
state family (`ErrorState`, `OfflineState`, `PermissionDeniedState`, `NotFoundState`,
`UnavailableState`).
@@ -976,9 +983,9 @@ This generated snapshot is a local source-derived inventory. It does not assert
| `AnswerFooter` | answer | yes | yes | inherited-global-root | yes | no | 1 |
| `AsyncButton` | controls | yes | yes | inherited-global-root | yes | no | 4 |
| `Breadcrumb` | layout | yes | yes | inherited-global-root | yes | no | 1 |
-| `Button` | controls | yes | yes | inherited-global-root | yes | no | 19 |
+| `Button` | controls | yes | yes | inherited-global-root | yes | no | 21 |
| `Checkbox` | controls | yes | yes | no | yes | no | 0 |
-| `Chip` | controls | yes | yes | inherited-global-root | yes | no | 5 |
+| `Chip` | controls | yes | yes | inherited-global-root | yes | no | 6 |
| `ChoiceChip` | controls | yes | yes | inherited-global-root | yes | no | 4 |
| `Citation` | source | yes | yes | no | yes | no | 0 |
| `CitationList` | source | yes | yes | no | yes | no | 0 |
diff --git a/docs/design-system/FIX-GUIDE.md b/docs/design-system/FIX-GUIDE.md
index ea94c24453..9b194b5e5f 100644
--- a/docs/design-system/FIX-GUIDE.md
+++ b/docs/design-system/FIX-GUIDE.md
@@ -37,27 +37,27 @@ measurement of `globals.css` / `ckb-v2-tokens.css`.
## Batch B — docs dispositions
-| ID | Status | Rationale |
-| -------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| DS-P2-04 | Documented | Intentional Geist variable interpolation. Already explained in [`docs/design-system.md`](../design-system.md) (intermediate weights; do **not** snap to 600/700). |
-| DS-P2-22 | Documented | `SectionHeading` exists (`src/components/ui/section-heading.tsx`); 14 production call sites. No opportunistic migration this sweep. |
-| DS-P2-23 | Documented | `AnswerCard` `frame?: "raised" \| "bare"` — both valid. Production answer surface uses **bare**. Future visual baselines must include both. Do not commit screenshots. |
-| DS-P2-27 | Documented | 15-mode load: recommend first-run / Tools prominence later. No IA redesign this sweep. |
-| DS-P2-28 | Documented | Settings **Motion** already has a per-control description. **Recent searches on home** does not — docs recommendation only; no extra intro copy in product this sweep. |
-| DS-P2-29 | Deferred | Phone document-viewer density waits on the tap-floor (Hazard ≥3). |
-| DS-P2-30 | Documented | Toast primitive exists; there is no **universal network-error** toast. Do not build toast infra here. `OverlayRoot` remains the overlay owner. |
-| DS-P2-31 | Documented | Already in TOKENS §4 / SPEC §3: add `--kind-*` **with the first call site**. No values in this sweep. |
-| DS-P2-32 | Documented | `--text-placeholder` is **live** (globals + v2 + `placeholder:` consumers), not planned. TOKENS §5 corrected. No further role migration. |
-| DS-P2-33 | Documented | Contract `textSoftConsumers=0` in production. Keep the `--text-soft` alias until zero `var(--text-soft)` remain **including mockups**. Do not rename; do not delete this sweep. |
-| DS-P3-01 | Deferred | PR-9 plan. `--shadow-focus` and dead springs are already gone. `--shadow-lift` still has live `mode-nav` and `document-search-results` consumers — do **not** delete it. |
-| DS-P3-02 | Documented | TOKENS already: `--tone-*` frozen, not deleted. |
-| DS-P3-03 | Documented | TOKENS already: design-side `--quantity-unit-scale` never lands. |
-| DS-P3-04 | Documented | TOKENS already: ConfidenceMeter deferred; no token without a call site. |
-| DS-P3-05 | Documented | Registry has **55** registered visual exports. `DocumentFrame` is built shell-only and still unregistered. Register when print primitives ship (PR 11). Docs elsewhere may still say 53/54. |
-| DS-P3-07 | Documented | Full visual state matrix grows incrementally with new adoptions. |
-| DS-P3-08 | Documented | QA checklist: inspect the filter band at 414–430px. No code this sweep. |
-| DS-P3-09 | Documented | `#TYZK23` PWA install CLS already fixed (PR #2253). Regression-check note only; no speculative CSS. |
-| DS-P3-10 | Documented | Mockup `min-h-11` and `--text-soft` body must not leak into production. |
+| ID | Status | Rationale |
+| -------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| DS-P2-04 | Documented | Intentional Geist variable interpolation. Already explained in [`docs/design-system.md`](../design-system.md) (intermediate weights; do **not** snap to 600/700). |
+| DS-P2-22 | Documented | `SectionHeading` exists (`src/components/ui/section-heading.tsx`); 14 production call sites. No opportunistic migration this sweep. |
+| DS-P2-23 | Residual / Documented | Both frames valid. Production `answer-result-surface` uses `frame="bare"`; default/preview is `frame="raised"`. Harness note on `targets` in `tests/ui-visual-baseline.spec.ts`: a future AnswerCard baseline must capture **both** frames. Do not add targets, PNGs, or `AWAITING_BASELINE` entries until a real approval path exists. |
+| DS-P2-27 | Documented | 15-mode load: recommend first-run / Tools prominence later. No IA redesign this sweep. |
+| DS-P2-28 | Documented | Settings **Motion** already has a per-control description. **Recent searches on home** does not — docs recommendation only; no extra intro copy in product this sweep. |
+| DS-P2-29 | Deferred | Phone document-viewer density waits on the tap-floor (Hazard ≥3). |
+| DS-P2-30 | Documented | Toast primitive exists; there is no **universal network-error** toast. Do not build toast infra here. `OverlayRoot` remains the overlay owner. |
+| DS-P2-31 | Documented | Already in TOKENS §4 / SPEC §3: add `--kind-*` **with the first call site**. No values in this sweep. |
+| DS-P2-32 | Documented | `--text-placeholder` is **live** (globals + v2 + `placeholder:` consumers), not planned. TOKENS §5 corrected. No further role migration. |
+| DS-P2-33 | Documented | Contract `textSoftConsumers=0` in production. Keep the `--text-soft` alias until zero `var(--text-soft)` remain **including mockups**. Do not rename; do not delete this sweep. |
+| DS-P3-01 | Deferred | PR-9 plan. `--shadow-focus` and dead springs are already gone. `--shadow-lift` still has live `mode-nav` and `document-search-results` consumers — do **not** delete it. |
+| DS-P3-02 | Documented | TOKENS already: `--tone-*` frozen, not deleted. |
+| DS-P3-03 | Documented | TOKENS already: design-side `--quantity-unit-scale` never lands. |
+| DS-P3-04 | Documented | TOKENS already: ConfidenceMeter deferred; no token without a call site. |
+| DS-P3-05 | Documented | Registry has **55** registered visual exports. `DocumentFrame` is built shell-only and still unregistered. Register when print primitives ship (PR 11). Docs elsewhere may still say 53/54. |
+| DS-P3-07 | Documented | Full visual state matrix grows incrementally with new adoptions. |
+| DS-P3-08 | Documented | QA checklist: inspect the filter band at 414–430px. No code this sweep. |
+| DS-P3-09 | Documented | `#TYZK23` PWA install CLS already fixed (PR #2253). Regression-check note only; no speculative CSS. |
+| DS-P3-10 | Documented | Mockup `min-h-11` and `--text-soft` body must not leak into production. |
---
@@ -92,3 +92,4 @@ capture · `npm run ensure` unless a visual defect is proven.
- `--shadow-lift` still live (`mode-nav`, `document-search-results`).
- Mockup `--text-soft` still blocks alias deletion.
- Mockup `min-h-11` must stay mockup-only.
+- AnswerCard visual baselines: future captures must include `frame="bare"` (live `answer-result-surface`) and `frame="raised"` (default/preview). No committed screenshots this sweep.
diff --git a/docs/design-system/GATES.md b/docs/design-system/GATES.md
index c2d75730a8..46ce6f0b43 100644
--- a/docs/design-system/GATES.md
+++ b/docs/design-system/GATES.md
@@ -52,11 +52,26 @@ gated from both sides, so the build fails if an exempted step stops being declar
consumer (class utility or direct `var(--text-*)` across walked production sources), and the
list cannot rot.
-**Still not enforced:** which of the _existing_ steps a component picks. Nothing stops a
-surface choosing `text-sm-minus` over `text-sm`, and nothing mechanical can — that is a
-judgement about the rendered design, not a property of the source. Do not describe the scale
-as ungated, and do not write an ESLint rule duplicating the arbitrary-value check that
-already ships.
+**Still not enforced:** which of the _existing_ steps a component picks, except
+the same-file mix below. Nothing stops a surface choosing `text-sm-minus` over
+`text-sm` in isolation, and nothing mechanical should — that is a judgement
+about the rendered design, not a property of the source. Do not describe the
+scale as ungated, and do not write an ESLint rule duplicating the
+arbitrary-value check that already ships.
+
+**Same-file density mix (DS-P2-02, warn/ratchet, not a hard zero).** Canonical
+metadata is `--text-sm` / live `text-sm`. Compact `text-sm-minus` is a named
+density notch, not a second metadata role. `check:design-system-contract`
+records `sameFileTextSmMinusMix` per path and **warns** when both utilities
+appear in one production file without implying the 705 legacy steps are illegal.
+A new mixed file fails the per-path ratchet; existing mixed files stay until a
+named density reason is recorded or the mix is removed. Do **not** delete the
+705 legacy steps.
+
+Canonical role → live utility (TOKENS §6): `--text-xs` → `text-xs`; `--text-sm`
+→ `text-sm` (compact `text-sm-minus` only with a named density reason);
+`--text-body` → `text-base-minus`; `--text-md` → `text-[length:var(--text-md)]`;
+`--text-lg` → `text-xl`; `--text-xl` → `text-2xl`; `--text-hero` → `text-hero`.
⚠️ **The "1 318 call sites" figure this section used to quote was a repo-wide grep including
`src/app/mockups/**`, which every one of these gates excludes** — 1 360 at `7aaf9349c`.
@@ -85,10 +100,15 @@ because it contributed nothing.
| 11 | Published-type conformance — every `dtsPropsFor` entry exactly matches source props | **implemented-blocking** | `generate-design-sync-contract.mjs` uses the TypeScript checker to derive every public property from the exported source `*Props` type; `--check` and `check-design-sync-contract.mjs` reject drift, missing named types, or machine-specific declarations. Zero-prop visual roots are explicit. |
| 12 | Publication coverage — every registered visual component has source, export, preview, prop contract and direct publication test | **implemented-blocking** | Registry/map/props parity and all 55 direct component rows are pinned by the design-sync contract and `design-sync-visual-exports.test.ts`. Behavioural, full visual-state, print, and browser acceptance remain separate gates; `DocumentFrame` is built shell-only in product but not yet among the 55 registered visual exports (print primitives remain specified-not-built). |
-**Computed-style suites (planned, PR 1–2):** Tailwind conflict order · v2 cascade, ancestor
-**and** same-node forms · HCM remapping under all three v2 selectors · z-index · target
-geometry · contrast · print token reset. Class-string assertions are not accepted for any of
-these — computed values only.
+**Computed-style suites.** HCM remapping under all three v2 selectors is
+**already implemented** (`ckb-v2 forced-colours computed tokens` in
+`tests/ui-style-contract.spec.ts`) — do not re-litigate. Overlay z-index vs
+named `--z-*` tokens is **implemented-blocking** in the same spec (`overlay
+z-index computed tokens`); class-string assertions are forbidden; the
+`rawCssZIndices` exception baseline stays at 8 in `globals.css`. Still planned
+(PR 1–2): Tailwind conflict order · v2 cascade, ancestor **and** same-node
+forms · target geometry · contrast · print token reset. Class-string assertions
+are not accepted for any of these — computed values only.
**Reference preview coverage is implemented-blocking for all 55 registered visual exports.**
The full runtime visual state matrix remains planned: default · hover · active · focus-visible ·
@@ -103,34 +123,34 @@ theme-list parity, and remote design-project publication remain separate concern
## 3 · The prohibition table
-| Never do this | Gate | Status |
-| -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Reintroduce `.ckb-v2:not(.dark)` | Cascade computed-style test (PR 1) + contract-test selector filter update | implemented-blocking — landed #1538; contract parser + dark-ink regression guard |
-| Add `prefers-color-scheme` rules to the v2 layer | — (users pin a theme against OS preference) | **manual** |
-| Paint a numeral with a status colour; use amber/red decoratively | `check:design-system-contract` — `statusColouredNumerals` + `colourOnlyStatusIndicators` | **implemented-blocking** — both metrics and their per-path baselines are pinned at **0**; see §5 |
-| Put `--decoration-soft`/`--text-soft` on a text node | Tier pinned both sides in the token contract; recipe AST (`decoration-on-text.contract.test.ts`) | implemented-blocking (recipes); broader AST follow-on |
-| Uppercase a dose unit | `Quantity` pins `normal-case` + unit test | implemented-blocking (branch) |
-| Invert a PDF, diagram or clinical image in any theme | `check:design-system-contract` — `imageInversions`, pinned at **zero**, not ratcheted | **implemented-blocking** (9 Aug 2026) — CSS `filter`/`backdrop-filter` plus the Tailwind `invert`/`hue-rotate` utilities; see §5 |
-| Border **and** ring on one surface, or a 1px spread in a drop shadow | `check:design-system-contract` — `edgeOwnershipConflicts` (18) + `onePixelShadowSpreads` (0) | **implemented-blocking for new use** — AST/CSS ratchets with per-path pins; the recorded debt itself is Gate 8's remaining half |
-| A child shadow heavier than its parent's | Gate 7 | implemented-partial |
-| Use `--shadow-tight`/any alias in new code | `check:design-system-contract` — `legacyShadowAliases`, ratcheted at 89 with per-path pins | **implemented-blocking for new use** — a new alias in any file fails. `--shadow-tight` itself is retired onto `--e1` and additionally pinned by a tracked-tree sweep in `tests/design-token-contract.test.ts` (it was silently reverted once by the `acf78bf` merge); the remaining 89 are the other six aliases, still `#262` |
-| Raw pixel size, padding, radius, gap or line-height in markup | `check:design-system-contract` — `rawPaddingLiterals` (52), `rawRadiusLiterals` (20), `rawGapLiterals` (25), `rawMarginLiterals` (74), `rawLineHeightLiterals` (0) | **implemented-blocking for new use** (9 Aug 2026) — per-path ratchets over both the utility and the CSS-declaration spelling, so a literal cannot move into `globals.css` to escape. Values containing a CSS function (`env(`, `clamp(`, `max(`, `calc(`) are sanctioned computed forms and exempt. Raw _size_ is still covered only for tap/shadow/colour |
-| Animate `width`, `height`, `grid-template-*`, `top`, `left`, `gap` | `check:design-system-contract` — `layoutTransitionExceptions`, ratcheted at 11 with per-path pins | **implemented-blocking for new use** — `SAFE_TRANSITION_PROPERTIES` carries the compositor-only allowlist; phone chrome's deliberate `grid-template-rows` is in the recorded 11 |
-| Hardcode a transition duration | `check:design-system-contract` — `hardcodedMotionClasses` (**zero**) + `hardcodedCssMotionDurations` (41) | **implemented-blocking** for the Tailwind `duration-*`/`delay-*`/`transition-all` form; the CSS form is a ratchet, so its 41 are debt |
-| A `z-[N]` literal outside the named rungs, in JS/TS only | `require-z-index-ladder` (ESLint) | implemented-blocking. Scope: `z-[N]` literals in JS/TS AST nodes. Plain `z-30` utilities and every `.css` / `.module.css` declaration are invisible to an ESLint rule - `sidebar-live-shell.module.css` carries an off-ladder `z-index: var(--z-sidebar-flyout, 50)` this cannot see. |
-| Ship a registered component without a direct publication test | Gate 12 | implemented-blocking |
-| Lower a production tap target below 48px | `check:design-system-contract` — `interactiveTapFloorDeclarations` (33) + Gate 2's phone-viewport `ui-style-contract` audit + `ui-smoke` flake history | **implemented-blocking for new use** (15 Aug 2026) — a new interactive control declaring a sub-floor `min-h-*`, including comparable arbitrary values and any reachable conditional branch, fails on both the total and its own path; the 33 recorded sites remain debt. Component-wrapper tags such as `` are a known blind spot |
-| Construct an enabled control with no action, destination or name | PR 4 discriminated unions + DOM contracts; `require-button-wiring` covers raw `