# Changelog — CyberSkill Design System

Full version history. Current release: **v5.0.0** (see `VERSION`). Newest first.

**Post-release batch 4 (v5.0.0, no version bump):** doc-redundancy sweep across the whole project (owner ask). Checked every doc for true duplication vs. deliberate audience-layering (README full guide / SKILL.md condensed agent skill / CONTRIBUTING.md one-page onboarding / docs/conventions.md deep authoring reference all restate the Expansion Rule, but for genuinely different audiences and lengths — kept as-is, not redundant). Found one real, mergeable duplication: `docs/agents.md` (AI-agent quick path) and `docs/consuming.md` (human adopt/upgrade guide) carried near-identical adoption-path prose and the same namespace-resolution code snippet, cross-referencing each other rather than sharing one source. Merged into a single `docs/consuming.md` — a "Quick path for AI agents" section up top, the fuller adopt/axes/upgrade/extend guide below, one canonical namespace-resolution snippet. Deleted `docs/agents.md`; fixed its 3 live references (README doc-map, `docs/viewer.html` Reference registry, `docs/deploy.md` pointer, `llms.txt` docs listing) — left frozen CHANGELOG bodies untouched, per doctrine. **Re-verified whole-set after:** `check_design_system` clean, full 18-gate fast board 18/18, all four whole-set audits green.

**Post-release batch 3 (v5.0.0, no version bump — owner: pin at 5.0.0 until no bug left):** owner reported a live health-report screenshot showing `docs-consistency` FAIL with README/package.json "NOT FOUND" and a package.json `SyntaxError` on "The page c...". **Root cause, found by reproducing the identical gate here:** the source is clean — running `docs-consistency.html` in this project passes 14/14 with README/package.json resolving and matching. The failure was the *deployed* copy: a static host (Vercel) had auto-detected a JS framework from the presence of `package.json` and was serving its own 404/error page for root-level file requests instead of the raw files — a hosting misconfig already half-documented in `docs/deploy.md`, not a source drift. This is a real gap, though: nothing in this repo could have caught a *deploy-environment* failure, and the gate's own error ("Unexpected token 'T'...") gave no hint that the cause was hosting, not content. Fixed at the root, not just described: (1) shipped `vercel.json` pinning `framework: null` + no build/install command + `outputDirectory: "."`, so Vercel can't auto-detect a framework regardless of dashboard state; (2) `docs-consistency.html` now detects an HTML/error body where a raw file was expected and reports it as an explicit, actionable diagnostic ("hosting is intercepting this path, not a source bug") instead of a bare parse error — the next time this class of failure happens (here or in any consumer's deploy), it will name itself. **On "how do I know there isn't a hidden bug":** the honest boundary is that deterministic gates here verify the *source tree*; they cannot verify third-party hosting behavior (framework auto-detection, CDN caching, MIME types) because nothing in this sandbox deploys to Vercel. `docs/deploy.md`'s post-deploy checklist already told users to re-run the gate board against the *live* URL after every deploy for exactly this reason — now reinforced with a self-diagnosing message instead of a cryptic one. **Docs hygiene (owner: remove stale docs, move unimplemented plans to a backlog):** `docs/audit-v3.md` and `docs/v3-roadmap.md` were fully historical — every item in both had already shipped (verified against `_ds_manifest.json`: all ~20 new components from the v3 roadmap's dedup/survey exist; all v4 roadmap goals — density, APCA dark, form unification, ESM — are in `CHANGELOG.md` as shipped). Removed both; their content is preserved as history in this file's per-version entries, which is what a changelog is for. One genuinely-still-open item was found while checking (density has no per-product default-flip/presets) and moved to a new **`docs/BACKLOG.md`** — a living forward-only list (ships → deleted from here + changelogged, never frozen like a "roadmap" doc). Fixed the two live references to the deleted docs (README doc-map table, `docs/viewer.html`'s Reference group, `llms.txt`); left every CHANGELOG/README-changelog-body mention of the old paths untouched (frozen historical prose, per doctrine). **Re-verified whole-set:** full 18-gate fast board 18/18, `responsive-overflow` 87/87, `language-overflow` 84/84, `density-overflow` 84/84, `theme-overflow` hard-gate pass with 0 open advisory — all re-run after these changes, not assumed from the prior pass.

**Post-release batch 2 (v5.0.0, no version bump):** three improvements applied on top of the post-release triage below. (1) **Component behavior gate 21→27 assertions** — added Tree (twist-expand + label-click select), Splitter (arrow-key resize), DatePicker (calendar day pick closes popover), ColorPicker (swatch pick commits + closes), TreeSelect (leaf pick closes), Sortable (real HTML5 `dragstart`/`dragover`/`drop` reorder) — all six read from actual component source (DOM classes, ARIA, state shape), not guessed; two genuine test bugs caught and fixed while building them (a stale post-expand DOM index picked the wrong tree row; the drag/drop synthetic events fired faster than React's state commit, so `onDrop` ran against a stale closure — fixed by yielding a tick between dispatches). 27/27 green. (2) **theme-overflow advisory hardened, not just allowlisted** — investigating the 7 confirmed false positives surfaced an 8th (`Marketing page`, 15 flags, screenshotted fully legible — same DOM-walk-can't-see-the-real-paint class as the others) *and*, more importantly, revealed the advisory list is not a fixed defect set: re-running repeatedly surfaced a different single new template each time (`Dashboard` → `Tech · Incident report` → `Tech · RFC / design doc`), each with exactly one flagged node. Two hardening passes applied — longer settle budget (1.5s→2.4s) and a double-measurement stability filter (a fail only counts if it reproduces 350ms apart, catching mid-transition/mid-paint reads) — did **not** eliminate the residual single-flag churn, pointing to iframe-pool scheduling contention (a straggler in the concurrent batch) rather than a real per-template defect. Documented honestly rather than papered over: the 8 structurally-caused false positives are allowlisted (blue "reviewed" rows); the lede and advisory-line copy now explicitly warn that any *other* single new flag is more likely measurement noise than a bug — re-run once, and only chase it if the same template reflags twice in a row. (3) Considered true pixel-diff visual regression (vs. today's baseline-freshness-only advisory) — not applied: the pixel capture this would need is a main-agent-side tool (`screenshot`/`save_screenshot`), unreachable from inside an in-browser gate page, so it can't become a self-running deterministic gate in this architecture without a build step this project doesn't have. Left as documented scope, not silently attempted. **Re-verified whole-set, not spot-checked, after all of the above:** full 18-gate fast board (`_audit/run.html`) — 18/18 (0 hard fail, 0 advisory fail); `responsive-overflow` 87/87; `language-overflow` 84/84; `density-overflow` 84/84; `theme-overflow` hard gate PASS (16 themed, 0 dark overflow) with 0 open advisory this run (residual single-flake risk documented above, not hidden).

**Post-release fixes (v5.0.0, no version bump — owner pinned at 5.0.0):** triaged all 12 advisory contrast flags from `theme-overflow`. Two real bugs found and fixed: (1) `--cs-component-button-primary-bg` was wired to `--cs-accent-bright` — itself light in dark mode — paired with `--cs-accent-on` (also flipped light by the v4.0.0 APCA pack), giving light-on-light primary buttons (ratio 1.34, e.g. App shell "New project", Settings "Save changes"); repointed to `--cs-accent-strong`, the pairing the APCA pack actually solved for ("button ink ≥ 75 on strong"). (2) `.cs-badge--success/danger/warning/info` hardcoded `color:#fff`, but `--cs-color-semantic-*` are foreground-role tokens that flip light in dark theme (by design, for text-on-dark-page) — so a badge fill in dark mode paired white text on a now-pale pastel bg (ratio 2.77, e.g. Dashboard "BLOCKED", Tech incident report "SEV-2"); switched to `--cs-color-text-inverse`, which already flips the correct direction (white in light theme, dark ink in dark theme) and matches `docs/contrast-report.md`'s own documented "fill w/ ink" ratios. Also found: `--cs-accent-ink` flips light in dark theme by design (an APCA-solved "ink-on-tint" text pairing with zero actual foreground consumers), which broke its one real usage everywhere — `background:var(--cs-accent-ink);color:#fff` banner/CTA strips across 32 templates + 2 non-template pages. Rather than touch the gate-checked pack, repointed every one of those banner consumers to `--cs-accent-strong` (already APCA-solved as a dark, white-text-safe fill in both themes) — verified legible via a forced-dark screenshot before and after. The remaining 7 flags (3 canvas-rendered decks + 4 templates whose header text sits behind a DOM-walk-inherited outer wrapper colour) are confirmed false positives — screenshotted in dark mode and legible; matches the pre-existing "DOM-walk contrast is unreliable here" caveat already on the report.

**Also (no version bump):** swept template content-schema v2 from 3 exemplars to **all 21 hole-driven templates** (every template whose copy is bound via `{{ hole }}` tokens in `renderVals()`, as opposed to hardcoded per-language `sc-if` branches — an architectural split discovered while doing the sweep). Added a component-tier visual-diff counterpart, `_audit/component-visual-diff.html` (12 curated components rendered directly, sidestepping the nested-iframe rasterizer limitation), with baseline crops in `baselines/components/`, wired into the fast board as a 17th advisory row.

**Also (no version bump):** closed the remaining two roadmap items. **Scheduled CI for whole-set audits** — new `whole-set-audits` job (nightly cron + manual dispatch, kept off push/PR) runs all four whole-set state audits via `run-single-gate.mjs` with a 6-min timeout each. **Style-Dictionary regeneration automated** — new `_audit/ci/generate-native-tokens.mjs` (browser-free Node script, the exact same transform algorithm as `token-pipeline-test.html`'s `expected()`, verified byte-identical against the committed native files: 134 base + 17 dark-color + 13 density-compact + 75 dark-pack constants, zero missing) regenerates `tokens/native/*` + `provenance.json` from `tokens.dtcg.json`; a new `regenerate-tokens` CI job runs it on every push/PR and auto-commits the diff — a token change no longer needs a human to hand-run a generator.

- **5.0.0** (Jul 2026) — **THE v5 CUT — a11y-proven, schema-typed, CI-automated, searchable.** The major that closes the post-v4.0.0 batch queue (owner-approved, "implement all, aim for 5.0.0"). Rolls up five shipped minors: **4.1.0** A11y-harness promoted to a real gate (found + fixed 2 real gaps: Switch/Slider had no coarse-pointer treatment, Splitter's resize handle had zero focus indicator) · **4.2.0** template content-schema v2, typed content slots via opt-in `content-schema.json` sidecars (3 exemplars: product/document/deck) · **4.3.0** visual regression depth, baselines 9→12 incl. `dashboard-dark` anchoring the v4.0.0 APCA repaint · **4.4.0** CI/CD automation, a GitHub Actions workflow (headless Playwright gate run + browser-free token-provenance check + docs/bilingual merge blockers) · **4.5.0** docs-site niceties, full-text search across every doc. Fast gate board grew **13 → 16** across the batch (A11y CSSOM, Template schema v2, plus the pre-existing 14). This cut's own verification: the 16-gate fast board proven green, **plus all four whole-set state audits re-run in full** (responsive/language/theme/density-overflow — all 84 templates × fresh iframes each) rather than relying on the fast board alone, per the project's deep-verification doctrine. See the cut's audit note below for each whole-set result.

**Whole-set re-verification results (this cut):** `responsive-overflow` — 84/84 pass, 0 fails. `language-overflow` — 84/84 pass, VN applies everywhere, 0 fails. `theme-overflow` — hard gate PASS (16 themed templates, 0 dark overflow, 68 correctly light-only); contrast stays advisory per doctrine (12 templates flagged for human eyeball, unchanged from pre-cut). `density-overflow` — 84/84 pass, 0 fails under forced compact @1280.

- **4.5.0** (Jul 2026) — **Docs-site niceties (roadmap item, closes the v4.x batch queue before the cut).** `docs/viewer.html` gains **full-text search across every doc**: fetches + caches all `.md`/`.txt` files once, filters the nav to matches with a highlighted snippet as you type (150ms debounce), and jumps to + highlights the first hit inside the rendered doc on click; clearing the box restores the normal grouped nav. `docs/deploy.md` gains concrete **OG social-preview-image** steps (deferred at v3.1.0 for lack of a production domain — now a documented 3-step recipe for once one exists).
- **4.4.0** (Jul 2026) — **CI/CD automation (roadmap item).** New `.github/workflows/design-system-gates.yml`: three jobs on push/PR/dispatch — (1) **`fast-gates`**, a headless Playwright run of `_audit/run.html` (`_audit/ci/run-gates.mjs`) that fails the build on any hard-gate red and uploads the import-report text as an artifact; (2) **`token-provenance`**, a browser-free Node re-hash of the DTCG source + native targets against `tokens/provenance.json` (`_audit/ci/check-token-provenance.mjs`) — same drift authority as the in-browser gate, cheaper as a fail-fast; (3) **`docs-consistency-blocker`**, running `docs-consistency` and `bilingual-parity` individually so they act as the merge blockers `CLAUDE.md` already calls for, not just board members. New `docs/ci-cd.md` (setup, local-run commands, badge markdown). The token-provenance script's sha-256 logic was hand-verified against the real repo files (matched: source + all 3 native targets in lockstep) — the workflow YAML itself has not been executed inside an actual GitHub Actions runner from this environment, documented as an honest caveat in `docs/ci-cd.md` rather than claimed proven.

- **4.3.0** (Jul 2026) — **Visual regression depth (roadmap item).** Baselines grown 9→12: added `auth` (sign-in archetype), `tech-incident-report` (a document layout distinct from `bod-report` — timeline + root-cause), and **`dashboard-dark`** — the dashboard forced dark, specifically anchoring the v4.0.0 APCA-derived dark elemental packs so any future token change that shifts dark rendering has a real before/after to diff against. Tried `guidelines/atomic-view.html` as a full-catalog sentinel; its nested-iframe composition breaks the capture tool, so `kitchen-sink` remains the composite anchor — documented as a known limitation rather than silently skipped.
- **4.2.0** (Jul 2026) — **Template data-props schema v2 — typed content slots (roadmap item, #16 in the fast runner).** Purely additive: a `templates/<slug>/content-schema.json` sidecar declares the **type** (`text`/`richtext`/`image`/`link`/`list`/`table`/`date`), label, and optional maxLength/required/i18n for each `{{ hole }}` a template already exposes — zero markup changes, so an agent or content pipeline can populate/validate real client copy without parsing HTML. Spec: `docs/template-schema-v2.md`; machine-checkable shape: `templates/schema/content-schema.schema.json` (JSON Schema draft-07). Shipped **intentionally incomplete**, same doctrine as the visual-diff baselines: 3 exemplars, one per major archetype — `marketing-page` (product, 18 slots), `bod-report` (document, 22 slots), `slide-deck` (deck, 16 slots) — all cross-checked against the templates' real holes. New gate validates shape + bidirectional hole-matching for every sidecar that exists and reports coverage (3/84) informationally, never failing on templates that don't have one yet. Also fixed two stale doc-pointer gaps found while wiring this in: `llms.txt` was missing `docs/deploy.md` from the earlier v4.0.2 cut.
- **4.1.0** (Jul 2026) — **A11y-harness promoted to a real gate (roadmap item, in the fast runner as #15).** `_audit/a11y-harness.html` was a manual-inspection page (render controls, eyeball them) — now it asserts. Found and fixed two real gaps while building it: **`.cs-switch`** and **`.cs-slider`** had no coarse-pointer touch-target treatment at all (unlike Check/Radio); `.cs-splitter__bar:focus-visible` silently set `outline: none` with **zero replacement** — a keyboard-focusable resize handle with no focus indicator. All three fixed. The gate itself: coarse-pointer floors are read from **source, not a live DOM re-render** (a DOM-reparse of an extracted media block proved unreliable for logical sizing on native/replaced elements — same class of flakiness the project already downgrades to static analysis elsewhere, e.g. contrast-guard); each control gets its own **documented** floor (44px default; icon affordances/segmented/native-range deliberately tiered lower, matching the CSS's own comments) rather than one blanket number. Focus-visible is proven by a static scan for a global ring plus zero unguarded `outline:none` overrides — the scan recognizes the established ancestor-`:focus-within`-ring pattern (InputGroup/TagInput/TimePicker) instead of false-flagging it. Caught its own bug mid-build: the test-runner helper wasn't awaiting async checks, so two checks were silently rubber-stamped passing — fixed before shipping. Proven green twice.
- **4.0.2** (Jul 2026) — **Root-caused a real re-import failure + docs hygiene.** A faithful port of this repo into a fresh project reported `_esm/` as "absent from the repo (gitignored)" and skipped it — breaking the ESM smoke gate on arrival. Root cause: **`docs/sync.md`'s round-trip file list never named `_esm/`**, so a session following it verbatim inferred the underscore prefix meant build-artifact/gitignored (true for `_ds_bundle.js`, false for `_esm/cs.mjs`, which is source). Fixed: `_esm/cs.mjs` added explicitly to the round-trip list with a called-out warning against inferring gitignore status from a leading underscore; `.gitignore` was already correct (only `uploads/`, `scraps/`, `_audit/exports/`) — the gap was documentation, not configuration. Also: new **`docs/deploy.md`** (Vercel zero-config steps + common misconfig, generic VPS/nginx, post-deploy checklist) — the audit's inline "Vercel showcase" notes are now a proper standalone guide; fixed a dangling `docs-src/` reference in README (that folder was never part of this project); corrected a stale `esm/cs.js` sub-label on the runner's ESM gate card; removed stray uploaded screenshots.
- **4.0.1** (Jul 2026) — **Behavior + a11y gates de-flaked for slow environments (verifier caught under-load timing flakes, not regressions).** (1) `until()` polling (default 2.5s) replaces single-shot fixed waits on every DOM-appearance assertion in `component-behavior-test.html` (InlineEdit edit-mode — the observed flake — plus Menu/Popover/Dialog/Drawer/Popconfirm/CommandPalette open·close·filter and the Form asserts). (2) Watchdogs scale for load instead of false-failing: per-test 8s→30s, suite 60s→240s in both interaction gates; `fxSure` retries 0.6s→4s; the runner's hard cap rises to ~8min while a gate keeps reporting progress (idle cap ~60s — true hangs still fail fast). Healthy runs stay just as fast — polls return on first success.
- **4.0.0** (Jul 2026) — **THE v4 CUT — APCA-true dark, denser, module-native.** The major that closes the v4 roadmap approved in `docs/audit-v3.md`. **Breaking (visual): dark elemental packs are now APCA-derived** — the owner-approved proposal from `_audit/apca-dark-preview.html` is applied to `tokens/elements.css` (15 packs; previously 0/15 held the targets, worst: button ink on mid-tone strongs at Lc 11–38; now 15/15 hold bright ≥ 75 · accent ≥ 60 · button ink ≥ 75 · ink-on-tint ≥ 75 with dark-native tints, hues kept via oklch lightness-solve). Ripple per the Expansion Rule: `tokens.dtcg.json` gains `$extensions.overrides.elementsDark` (stamp v4.0.0), natives regenerated (+75 `<Scope>Dark` constants, provenance re-pinned), `docs/contrast-report.md` gains the generated dark-pack Lc table, and the preview page is **promoted to fast gate #14** (current packs must pass; it keeps deriving proposals for future packs). Rolled up from the v4 batches: **3.5.0** Density axis · **3.6.0** ESM entry · **3.7.0** Form controller · **3.8.0** APCA preview. Deferred to v4.x: template data-props schema v2.
- **3.8.0** (Jul 2026) — **v4 batch 4 — APCA dark-pack preview (decision artifact; tokens untouched).** New `_audit/apca-dark-preview.html`: parses the 15 element×variant packs live from `tokens/elements.css`, scores the **current dark** rendering with a real APCA-W3 implementation (SAPC-4g) and derives a **proposal** in oklch — hue/character kept, lightness solved — to targets: `accent-bright` text ≥ Lc 75 on the dark panel, `accent` ≥ 60, button ink ≥ 75 on `accent-strong` (mid-tone strongs get their lightness re-solved in whichever direction is nearest — the doctrine's “text never sits on the mid-tone accent” problem, now measured), `ink`-on-`tint` ≥ 75 with dark-native tints. Verdict: **current dark packs fail 15/15; proposals pass 15/15.** Side-by-side swatches with Lc chips + copyable proposed CSS; nothing ships until the owner approves, after which the token cut + `contrast-report.md` regeneration follows the Expansion Rule.
- **3.7.0** (Jul 2026) — **v4 batch 3 — Form controller unification (backward-compatible).** `Form` becomes the single form controller while plain usage stays byte-compatible: new `rules` (name → `"required"` | `fn(value, values) → msg|null` | arrays; validated on submit, blocking until clean), `initialValues`, and a context registry — `FormField` with `name` auto-wires its single element child (`value`/`onChange` clone; `valueProp="checked"` for Checkbox/Switch/Toggle shapes) and auto-shows its context error (explicit `error` prop still wins; typing clears that field's rule error). New bilingual registry key `Form.requiredField` (EN/VI — parity gate stays green). Coverage per doctrine: behavior gate grows 20→21 (“rules block → field flagged → typed → values collected → summary clears”), new Atomic View **Form** organism story with a live controller demo (EL/EX/lang aware), `.d.ts` + `.prompt.md` rewritten.
- **3.6.0** (Jul 2026) — **v4 batch 2 — ESM entry point (additive; UMD contract untouched).** New generated **`_esm/cs.mjs`**: `import { Button } from "_esm/cs.mjs"` with no build step — top-level-await module that self-ensures pinned React 18.3.1 (skipped when `window.React` exists), side-loads `_ds_bundle.js` exactly once, resolves the namespace **by prefix**, and re-exports all 113 components + `CS`/default + `VERSION`. Styles stay a separate `styles.css` link (unchanged contract). New **ESM smoke gate** in the fast runner: module imports, **export/manifest parity in both directions** (a new component without regenerating `_esm/cs.mjs` turns the board red — same drift doctrine as story-coverage), Button mounts with the umber brand token, and no hardcoded namespace suffix in the module source. `package.json` gains `"module"`/`"exports"`; consuming/agents/llms document the path. Gate-semantics fix surfaced by this cut: the token-pipeline gate asserted `provenance.release === VERSION`, which reddened the board on every version bump even when tokens were untouched — the drift authority is now the **source sha-256** alone (release stamp informational), matching the doctrine that natives regenerate on *token* change, not on release. Placement lesson (compiler-scope): a first cut at `esm/cs.js` was swept into `_ds_bundle.js` by the compiler (113 export collisions + an `import.meta` parse failure); underscore-prefixed root trees are outside the scan, so the module lives at **`_esm/cs.mjs`** — the ESM smoke gate would catch any regression here.
- **3.5.0** (Jul 2026) — **v4 batch 1 — the Density axis (opt-in, non-breaking).** New 4th styling axis `data-cs-density="comfortable|compact"` (`tokens/density.css`, imported by `styles.css`): compact tightens **control metrics only** — button md 44→36 / sm 36→30 / lg 52→44 + paddings + gap, textfield 44→38 — by overriding the existing component tokens; layout spacing and type untouched; **comfortable = byte-identical defaults** (no attribute needed). Scope discipline: the compact block is wrapped in `@media (pointer: fine)` so coarse-pointer (touch) surfaces keep the `base/a11y.css` 44px floor — density can never undercut touch a11y. Wired everywhere per the Expansion Rule: Atomic View toolbar + `applyAxis` (Templates/Pages tiers reskin too), `templates/playground.html` axis rail, new specimen card `guidelines/spacing-density.html`, conventions/consuming/SKILL/llms/agents/dashboard axis prose (now “the four axes”), DTCG `$extensions.overrides.densities` + regenerated natives/provenance. Gates: new fast **density gate** (compact applies 36/30/38 · defaults untouched · pointer-fine gating asserted in source) and a new whole-set **density overflow audit** (all templates forced compact @1280, zero horizontal overflow) joining the per-axis audit family. Count-proof prose: token counts now say “500+” (density scope adds registered overrides); fixed a stale “8-gate runner” line in llms.txt.
- **3.4.0** (Jul 2026) — **v3.4 cut — token pipeline (roadmap batch 4, closes the approved v3.x series).** **Native token builds** generated from the DTCG source into `tokens/native/`: `CSTokens.swift` (SwiftUI, hex+alpha helper), `CSTokens.kt` (Compose, `Color(0xAARRGGBB)` + `.dp`), `cs_tokens.dart` (Flutter) — 134 base constants (colors, dimensions rem→px@16 / em→`…Em`, numbers, durations, cubic-beziers, font stacks, shadow strings) + 17 dark-theme color overrides, zero skipped. **`tokens/provenance.json`**: release, generated-at, source sha-256, conversion rules, per-target sha-256, counts (incl. the DTCG file's own generation stamp). New **token-pipeline parity gate** in the fast runner: re-derives every expected constant from the DTCG source and asserts verbatim presence in all 3 targets + provenance integrity (release = VERSION, hashes, counts) — any token change without regeneration turns the board red. Docs: consuming/agents point at the native path.
- **3.3.1** (Jul 2026) — **A11y gate made environment-deterministic (verifier found cross-context flake).** In pooled/background iframes the browser can silently ignore `focus()` on fresh nodes, so assertions that depended on real focus transfer flaked. The gate now (1) retries the *action* — `fxSure()` loops focus+`focusin` until `document.activeElement` takes, failing loud with `env: element refuses focus`; (2) asserts component *intent* deterministically via focus **spies** (prototype-level for focus-into-overlay, instance-level for restore-to-trigger/top-item and roving moves) OR'd with real containment; (3) the two Dialog tests are now self-contained (no shared state). Proven green in both contexts: directly-loaded page 16/16 and the full runner board twice (`ALL 10 FAST GATES PASS`), which also refreshes the dashboard gate badge.
- **3.3.0** (Jul 2026) — **v3.3 cut — visual regression (roadmap batch 3).** Baselines grown **3→9, per-tier**: template archetypes now also cover VN legal (`vn-labor-contract`), email (`email`), marketing (`marketing-page`); plus `kitchen-sink` (the Atoms→Organisms composite sheet) and the two UI-kit **Pages** (`status-hub`, `website`) — all 909×540, declared in `visual-diff.html`'s `BASE` map (which now supports explicit `src` for non-manifest pages). **`visual-diff` is wired into the gate runner as an advisory row**: the runner gained advisory-row support (amber, excluded from the aggregate and the gate badge; report lines tagged `ADVS`), and visual-diff publishes `window.__visualdiff` = baseline freshness (every declared baseline exists + its live source resolves). Pixel drift itself stays judged by eye — documented limitation (nested-iframe raster unavailable). `baselines/README.md` rewritten with the per-tier set.
- **3.2.0** (Jul 2026) — **v3.2 cut — accessibility depth (roadmap batch 2).** Component fixes: **Dialog + Drawer gain full focus management** (initial focus to first focusable, Tab/Shift-Tab trap, focus restore to the opener on close; Dialog now also closes on Escape like Drawer); **Tabs, SegmentedControl, Menubar get roving tabindex** (ArrowLeft/Right + Home/End move selection/focus; Menubar ArrowDown opens the focused menu and Escape returns focus to its top item); **Combobox** sets `aria-activedescendant` with per-option ids (full APG combobox pattern). New **a11y interaction gate** (`_audit/a11y-gate.html`, in the fast runner — the a11y-harness promotion the roadmap called for): 16 keyboard/ARIA assertions with the hardened skeleton (preflight, per-test 8s + suite 60s watchdogs, `__gateProgress`). New **QR reader-scan sanity check** (`_audit/qr-scan-test.html`, advisory — CDN decoder): renders `QRCode`, rasterizes with a quiet zone, decodes with jsQR, asserts exact byte round-trip incl. Vietnamese UTF-8 (encoder already `TextEncoder`-based). Housekeeping: removed a duplicate Bilingual-parity card in the suite index; count-proof phrasing (“every fast gate”) across docs so gate-count growth can't go stale.
- **3.1.0** (Jul 2026) — **v3.1 cut — live-site polish (roadmap batch 1, owner-approved).** (1) **Docs tab**: new `docs/viewer.html` — the whole `.md` set rendered in-page (hash-routed, grouped Start/Guides/Reference, relative `.md` links re-route inside the viewer) — embedded as a dashboard tab; on static hosts the docs are now readable, not plain text. (2) **Gate-status badge** in the dashboard header: the runner persists its last verdict to `localStorage` (`cs:last-gate-run`: version, timestamp, pass/failed); the badge shows ✓/✗ + version + age and jumps to Health. (3) **Atomic View permalinks**: per-story `#` copy-link (honest ✓ only on successful clipboard write) + incoming-hash scroll that waits for the async render. (4) **OG/description/theme-color meta** on the dashboard (`og:image` deferred until the production domain exists). (5) **`package.json`** (minimal, `private`, version mirrors `VERSION` — now asserted by the `docs-consistency` gate) + **`docs/agents.md`** (AI-agent import one-pager: Claude Code, no-build React, static HTML, DTCG token pipelines, post-import gate proof).
- **3.0.4** (Jul 2026) — **Final deep audit + deploy readiness.** Whole-set structural audit on top of the green gate board (see `docs/audit-v3.md` for method, findings, Vercel showcase map, agent-import contract, and the v3.x→v4 roadmap). Scans: unit completeness across all component dirs (every `.jsx` ships `.d.ts` + `.prompt.md`; zero orphans), debt-marker sweep (clean), portability sweep (no localhost/absolute refs; all assets referenced). Fixes: **root `index.html` → `dashboard.html`** (static hosts — Vercel/Pages — previously 404'd at `/`); dashboard version fallback no longer hardcodes a stale number. Recommended-not-applied (needs approval): minimal `package.json`, `docs/agents.md` import one-pager, dashboard Docs tab.
- **3.0.3** (Jul 2026) — **Gate-runner hardening (first real import surfaced two runner bugs).** (1) *Copy import report* silently failed in embedded previews: the async clipboard call rejects outside a permissioned context and `try/catch` never catches a promise rejection — the button claimed “Copied ✓” with an empty clipboard. Now selection + `execCommand('copy')` first, async clipboard as fallback, and an honest “copy blocked — press Ctrl/Cmd+C” state (report text stays selected). (2) `component-behavior-test` could die or hang without publishing a verdict (e.g. React CDN failure killed the script at the top-level `React.createElement` ref), so the runner reported a bare `{"timeout":true}`. Now: React/bundle preflight, 8s per-test watchdog, 60s suite watchdog, and a `window.__behaviorProgress` global — the gate always publishes, naming the stalled test. (3) The runner extends its deadline while a gate reports progress (hard cap ~2 min) and timeout verdicts carry `stalledAt` + `done` counts. Runner card subtitle corrected 11→20 assertions.
- **3.0.2** (Jul 2026) — **Gate-coverage audit (owner: "don't miss anything").** Deterministic sweep of gates vs the v3 surface: (1) i18n registry scan — every `makeT()` name across all 99 component files resolves (TreeTable→DataGrid and FormField→Form share entries by design); (2) **behavior test extended 11→20** — Toggle · Rating · InputOTP · Combobox (filter+pick) · TagInput (add/remove) · InlineEdit (commit) · Popconfirm (confirm) · Carousel (advance) · DataGrid (sort+select) now asserted, ALL GREEN on the live bundle; (3) **responsive whole-set audit now probes the 3 UI kits** (84→87 pages — run it once pre-push to baseline the kit rows). Remaining documented non-gate items: QR reader-scan check, a11y-harness extension to the new set, theme-audit contrast stays advisory by design.
- **3.0.1** (Jul 2026) — **Import health report.** The gate runner (`_audit/run.html`) now emits a **Copy import report** after each sweep — version + per-gate PASS/FAIL + failure detail JSON in one paste-ready block — so a re-imported copy of this system (fresh Claude Design project bound to the git repo) can hand its diagnosis straight back for fixing. Runner counts corrected to 9 gates in the suite docs. All three whole-set audits re-run green before this cut (responsive 84/84 · language 84/84 · theme 0 dark overflow); `scraps/`+`uploads/` leftovers removed from the repo tree.
- **3.0.0** (Jul 2026) — **THE v3 CUT — bilingual-by-rule, 5-tier, 113-export design system.** The major that closes the owner's expansion mandate (roadmap: `docs/v3-roadmap.md`). **Breaking:** components now resolve language themselves (`lang` prop → nearest `[lang]` ancestor → `<html lang>` → vi) and built-in strings come from the central EN·VI registry — the behavior shift that earns the major. **What v3 added since 2.22:** the bilingual engine + registry + parity gate; 16 existing components retrofitted; all templates/kits/Atomic-View bilingual (incl. mock data, owner decision A); Element reach (surfaces, not just accent) + Expression type treatment; the 5-tier Atomic View with a Language axis; and **46 new components** across Batches 2–7 (inputs · date/time with VN formats · overlays · nav/display · Form + enterprise set · heavy/advanced incl. DataGrid, TreeTable, Sortable, Chart, Editor, Terminal, hand-rolled QRCode) — 67→113 exports, every one a full unit (source + `.d.ts` + `.prompt.md` + token styles + registry strings + Atomic View story). **Cut verification:** 86 stories/0 missing on the final bundle; gate sweep green — contrast-guard · namespace-portability · token-contract · story-coverage · consumer-smoke · component-children · component-behavior · bilingual-parity (docs-consistency caught two stale README counts during the sweep; fixed — its remaining count line reconciles with the end-of-turn manifest rewrite). The three ~5-min whole-set audits (responsive · language · theme) should be re-run once before the next push. Known scope notes: behavior tests cover the pre-v3 interactive set (new-component assertions are the first post-3.0 task); QR verified rendering, reader-scan pending.
- **2.38.0** (Jul 2026) — **v3 Batch 7c: Chart · Editor · Terminal — Batch 7 complete.** Chart (token-colored SVG bar/line/spark/pie, values in aria), Editor (light contentEditable rich-text, bilingual toolbar), Terminal (warm-dark console with onCommand). **All planned v3 components are built** (110→113 exports). Next: Batch 8 — the v3.0.0 cut (full gate sweep + roadmap close-out).
- **2.37.0** (Jul 2026) — **v3 Batch 7b: DataGrid · TreeTable · Sortable.** DataGrid (sortable aria-sort columns · checkbox selection with bilingual labels · sticky header scroll), TreeTable (expandable nested rows), Sortable (HTML5 drag-to-reorder; compose columns for kanban). Counts 107→110.
- **2.36.0** (Jul 2026) — **v3 Batch 7a: Masonry · Splitter · HotKeys · Dock.** Masonry (CSS-columns gallery), Splitter (pointer + arrow-key resizable panes, bilingual aria), HotKeys (mod+key bindings, "?" bilingual cheat-sheet, input-safe), Dock (magnifying icon dock, reduced-motion safe). Counts 103→107.
- **2.35.0** (Jul 2026) — **v3 Batch 6c: ColorPicker · Tour · QRCode — Batch 6 complete.** ColorPicker (curated Ngũ Hành swatches + hex, never a raw free-picker), Tour (spotlight cutout + bilingual Skip/Back/Next/Done), QRCode (SVG, hand-rolled encoder in `components/data/qr-encode.js` — byte mode, EC-L, versions 1–4/≤78 bytes, mask 0; lowercase module so it stays off the namespace). Counts 100→103. QR scan-verification against a real reader rides the next gate pass.
- **2.34.0** (Jul 2026) — **v3 Batch 6b: TreeSelect · Cascader · Transfer · Mentions.** TreeSelect (field + popover Tree, leaf commits), Cascader (column-per-level, VN demo TP.HCM/Quận 1), Transfer (checked ‹/› mover, bilingual Có sẵn/Đã chọn), Mentions (@user typeahead). Counts 96→100 — the library crosses 100 exports.
- **2.33.0** (Jul 2026) — **v3 Batch 6a: Form (+FormField) · Tree · BackTop · Watermark.** Form collects named-field values + bilingual error summary ("Vui lòng sửa các mục sau:"); FormField pairs label/hint/error; Tree = expandable role=tree hierarchy with accent selection; BackTop (bilingual aria, smooth scroll); Watermark repeats rotated SVG text (BẢN NHÁP/DRAFT). Counts 91→96.
- **2.32.0** (Jul 2026) — **v3 Batch 5 (part 2): Menubar · NavigationMenu · Carousel · Comment.** App menu bar (hover-switch, separators), site nav with rich panels, slide carousel (arrows + dots, bilingual aria, reduced-motion safe), and discussion Comment with nested replies + bilingual default Reply action. Batch 5 complete; counts 87→91.
- **2.31.0** (Jul 2026) — **v3 Batch 5 (part 1): Navigation/Display — Link · Anchor · Image · Toolbar.** Link (brand anchor: default/muted/standalone/external), Anchor (in-page TOC with IntersectionObserver scrollspy, ochre rail), Image (shimmer · warm error fallback · optional lightbox with bilingual aria), Toolbar (action bar with ⋯ overflow menu, bilingual aria). Full units + stories; counts 83→87. Part 2 next: Menubar · NavigationMenu · Carousel · Comment.
- **2.30.0** (Jul 2026) — **v3 Batch 4: Overlays/Feedback — HoverCard · Popconfirm · ContextMenu · FloatingActionButton · Result · InlineEdit.** Six full bilingual-by-rule units: HoverCard (delayed hover/focus preview), Popconfirm (inline alertdialog, registry OK/Đồng ý + Cancel/Hủy), ContextMenu (right-click zone reusing Menu styling, "-" separators, danger items), FloatingActionButton (Ochre accent-aware round action + speed-dial, `position="static"` for embeds), Result (page-level outcome with bilingual default titles per status), InlineEdit (click-to-edit, Enter/blur commit · Escape cancel). Token styles in `base/controls.css`; stories with VN demo data; counts 77→83.
- **2.29.0** (Jul 2026) — **v3 Batch 3: Date/Time — Calendar · DatePicker · TimePicker.** VN-first by construction: **Monday week-start**, bilingual weekday row (**T2–CN** / Mo–Su) and month names (Tháng 7), **DD/MM/YYYY** display via the shared i18n `formatDate`, 24-hour TimePicker. DatePicker composes Calendar in a popover (outside-click + Escape close); hand-rolled date math is confined to the one `grid()` helper (lead offset + month length — leap-safe via `Date`). Full units: `.jsx` + `.d.ts` + `.prompt.md` + registry strings (prev/next month · placeholder · label) + token styles + Atomic View stories (fixed demo date 18/07/2026). Counts 74→77. Behavior tests for the trio ride with the next gate-extension pass.
- **2.28.0** (Jul 2026) — **v3 Batch 2 (part 2): Combobox · InputGroup · TagInput.** The ARIA-heavier input trio, each a full bilingual-by-rule unit: **Combobox** (typeahead + listbox, arrows/Enter/Escape, registry placeholder + empty state), **InputGroup** (prefix/suffix addons · clearable × · password reveal with EN·VI labels), **TagInput** (Enter/comma adds · Backspace removes · blur commits · dedupe · max). Token-based styles in `base/controls.css` (accent-aware, dark-safe, Ochre focus), Atomic View stories (VN demo data included), README/atomic-map + counts 71→74. **Batch 2 component set complete** — remaining Batch 2 tail: variant expansions (Tag/Alert/Avatar/Badge/Progress-circular) ride with Batch 3+.
- **2.27.0** (Jul 2026) — **v3 Batch 2 (part 1): four new input components — Toggle · Rating · InputOTP · ButtonGroup.** Each ships as a full unit per the Expansion rule: `.jsx` + `.d.ts` + `.prompt.md`, token-based styles in `base/controls.css` (accent-aware, dark-safe, 3px Ochre focus), **bilingual by rule** (Rating/InputOTP register EN·VI aria strings; Toggle/ButtonGroup take all text as props), Atomic View stories + playgrounds (Toggle · Rating), and README/atomic-map entries (67→71 exports). Deduped by design: Toggle ≠ Switch (no form semantics) ≠ SegmentedControl (choice set); ButtonGroup composes existing Buttons. Remaining Batch 2: Combobox · InputGroup · TagInput + variant expansions.
- **2.26.1** (Jul 2026) — **v3 Batch 1b: all three UI kits fully bilingual (owner decision A — overrides the Thổ-faithful EN-only recreation boundary).** Website kit: `work`/`careers` language links are now a working EN⇄VN toggle (`data-vi` swap + shared `cs_site_lang` persistence; home already used `copy.js`). Brand deck: floating EN⇄VN toggle, every slide's copy localized (brand slogan pair stays bilingual by design). **Status Hub**: full bilingual rewrite — header EN/VN button, all UI chrome from a `T` dictionary, and **mock data** (blurbs · risks · owners · squads · relative times · release titles/items) from new `window.SH_VI` in `data.js`; verified live (“Danh mục”, VN lenses, VN blurbs, VN drawer). Remaining: the kit's static specimen pages (`settings.html`, `sign-in`) get the `data-vi` pass with the next kit touch. CLAUDE.md scope-boundary line is superseded by this decision.
- **2.26.0** (Jul 2026) — **v3 Batch 1 cut — bilingual retrofit complete (components · templates · Atomic View).** Components: 16 wired to the registry (2.25.0), parity 16/16, behavior 11/11. Templates (1a): verified by construction — every template mounting DS components binds `lang` on its root to its Language tweak, so component chrome switches automatically; visible strings were already bilingual `{{ }}` props. Atomic View display copy fully EN·VI (2.25.1). **Kits (1b) audit:** the website kit's home is already fully bilingual (`copy.js` EN⇄VN toggle); its `work`/`careers` pages carry a **static** language link (not wired); status-hub + deck are EN-only under the documented Thổ-faithful recreation boundary — making them fully bilingual would override that boundary and awaits the owner's call. Next: Batch 2 (Inputs: Combobox · InputOTP · Rating · Toggle · InputGroup · ButtonGroup · TagInput).
- **2.25.1** (Jul 2026) — **Atomic View fixes (user-reported).** (1) The CommandPalette story rendered a dark scrim band and overflowed its frame — the `.framed` override now renders cmdk inline (no fixed/absolute scrim). (2) Sidebar widened 230→264px with group separators + **collapsible tier groups** (▾/▸) for the growing artifact list (filter retained). (3) Demo **mock data** now switches EN·VI with the Language axis (threaded `lang` into story renders) — CommandPalette, Sidebar, Menu, Breadcrumb, DataTable localized; remaining stories to follow. (4) Popover story escaped its frame / overlapped the sticky toolbar \u2014 the `.framed` box now establishes a stacking context (`z-index:0`) capped below the toolbar (`z-index:20`), so anchored overlays stay contained; Popover demo localized too. (5) Sidebar restructured to the full **5 Atomic tiers** — Templates + Pages are proper tier groups (per-artifact jump links, collapsed by default), not an "Artifacts" umbrella; Drawer · Steps · Tabs · Timeline · List · EmptyState demo data localized EN·VI, then the remaining display copy (Conversation · Card · Alert · Toast · Stat · Accordion · DescriptionList · StatusIndicator · Search/Segmented/Prompt helpers) — whole-canvas scan confirms VN mode shows no English **display** copy; the only EN left is playground *seed values* (user-editable inputs, intentionally kept).
- **2.25.0** (Jul 2026) — **v3 Batch 1 (components): 16 components retrofitted to the bilingual registry.** New `useLang` hook resolves language (explicit `lang` prop → nearest `[lang]` ancestor → `<html lang>` → vi); wired Pagination · Breadcrumb · CommandPalette · SearchField · NumberField · FileUpload · Dialog · Drawer · DataTable · Spinner · Tag · Toast/ToastStack · TypingIndicator · PromptInput · HumanReviewGate · ConfidenceMeter to pull built-in strings (aria-labels, placeholders, prev/next, close/dismiss, hints, confidence words) from `components/_i18n/strings.js` instead of hardcoded English. **bilingual-parity 16/16 green, behavior 11/11, compiler clean.** Verified end-to-end: a component renders Vietnamese under a `[lang]` ancestor (dual-block templates remount their VN block on toggle, so component chrome switches automatically). The other ~39 exports take all text as props — nothing to retrofit. Also fixed the Atomic View Language axis to remount stories on toggle. Next: 1a templates · 1b kits.
- **2.24.0** (Jul 2026) — **v3 Batch 0: bilingual foundation + Expression type treatment + 5-tier Atomic View.** (1) **i18n mechanism** — `components/_i18n/i18n.js` (lang resolve, vi-default · `makeT`/`tr` · `formatDate` DD/MM/YYYY · `formatNumber` · `formatCurrency` ₫) + central EN·VI registry `components/_i18n/strings.js`; new gate `_audit/bilingual-parity.html` enforces en/vi key parity + non-empty (green; 8 components seeded). Batch 1 wires each existing component to it. (2) **Expression type treatment** — expressions now retune heading weight/tracking (Swiss / editorial / luxe / brutalist voices) via overridable `--cs-heading-*` tokens wired into `.cs-display/h1–h4`; the expression half of the “not different enough” fix (element half shipped in 2.23.0). (3) **Atomic View → 5 tiers** — added **Templates** (84, live lazy iframes) + **Pages** (3 UI kits) tiers and a **Language axis**; the toolbar forces Theme·Element·Expression·Language on every artifact via attribute-scoping, so all axes are browsable on all artifacts (owner concern). Bilingual-parity registered in the gate runner + suite. check_design_system clean (67 components; the i18n data export is lowercase so it stays off the namespace).
- **2.23.0** (Jul 2026) — **Element reach (surfaces, not just accent) + v3 planning.** Owner concern: switching Element barely changed a page because elements only remapped the 9 accent tokens (a small % of pixels). Elements now also **wash page + panel + raised surfaces + borders** with their accent — per-theme literal bases keep each elevation tier + contrast intact (tints capped low; text stays ≥AA; **contrast-guard green**). Verified visibly distinct across Thổ/Thủy/Mộc/Hỏa in the Atomic View; pages with no element attribute are unchanged. Planning docs: new `docs/design-styles.md` (adaptation catalog mapping the “50 design styles” vocabulary onto our axes + a 7-step process to adopt more) and `docs/v3-roadmap.md` updated — heavy/advanced components (DataGrid, Charts, rich-text Editor, TreeTable, Masonry, drag-and-drop…) moved INTO scope per owner; retrofit-first order confirmed. Expression **type/material treatment** and element-driven CTAs are queued for v3 Batch 0.
- **2.22.0** (Jul 2026) — **Single-page dashboard.** New root `dashboard.html` — one hub that ties the whole system together via tabs, each embedding the real tool (no duplication): **Overview** (live version + counts from the compiler; quick links to the suite, README, DTCG tokens, changelog), **Components & Playgrounds** (the Atomic View — 42 stories, 21 live playgrounds, Theme×Element×Expression), **Health** (the 8-gate runner), and **Identity Lab**. Header version + counts load live from `VERSION` + `_ds_manifest.json`. Verified: tabs switch, panels load, stats resolve (84 templates · 57 cards · 476 tokens). Also extended the CLAUDE.md **Expansion rule** to enforce updating the Atomic View (story/playground), `dashboard.html`, and the matching deterministic gate on any change — with `_audit/run.html` + `docs-consistency` added to the gate bar.
- **2.21.2** (Jul 2026) — **Gate runner.** New `_audit/run.html` (a dev tool in `_audit/`, linked from the suite index) — a one-click health board that runs all 8 fast deterministic gates in sequence (contrast-guard · docs-consistency · namespace-portability · token-contract · story-coverage · consumer-smoke · component-children · component-behavior), reads each verdict global, and reports pass/fail + an aggregate `window.__run.pass`. The 4 whole-set state audits (~5 min each) stay on the suite index. **All 8 green.** Also polished the Atomic View controls panel to **21 live playgrounds** — every component with meaningful tweakable props (added Icon · ProgressBar · LumiAvatar · Switch · Toast · Card · Tooltip · CodeBlock · Steps · AIDisclosureBadge · EmptyState · HumanReviewGate · Accordion on top of the first eight, with select/toggle/text/range controls). Already-interactive controlled components (Tabs · Pagination · Slider · SegmentedControl) and prop-less display atoms (Kbd · Divider · Logo · TypingIndicator) intentionally stay static; story coverage remains 100%.
- **2.21.1** (Jul 2026) — **Improve-loop fixes.** (1) `dashboard` project-code labels (CDS/SITE/OS) used inline `var(--cs-color-brand-umber)` on themeable cards → near-invisible in dark; remapped to `--cs-color-text-accent` (flips to ochre in dark). (2) `_audit/contrast-guard.html` now scans **full screen-template bodies** (not just headers) for inline umber, and adds a **15-scope Ngũ Hành element-pack accent-contrast** section — WCAG advisory (the system metric is APCA), hard-flagging only <3.0. It surfaced that `accent-strong`-as-text-on-light is WCAG-borderline for a few packs (tho · tho/sand · thuy/mist · moc/bamboo, ~3.18–4.26) — expected: that role is APCA-validated for accent text (note added to `docs/conventions.md`). All six screen templates now theme-safe (guard review = 0). Contrast-guard PASS.
- **2.21.0** (Jul 2026) — **Contrast guard + coverage/behavior gates + Atomic View controls (improve-loop batch).** (1) New `_audit/contrast-guard.html` — the *reliable* dark-contrast gate the theme-advisory couldn't be: a **static lint** fails any base rule setting `color: var(--cs-color-brand-umber)` on a themeable surface without a `[data-theme="dark"]` override, plus a **token-pair WCAG matrix** over every semantic text×surface pairing in light + dark from `tokens.json` (no DOM → no false reads). It earned its keep on first run — caught a real dark defect (`.cs-empty__icon` umber-on-tint, now overridden to ochre) and a lint-precision bug (a `border-*-color` substring). PASS. (2) New `_audit/story-coverage.html` — asserts every primary component export (55) has an Atomic View story; **0 missing**. (3) Extended `component-behavior-test.html` 5→**11** — added Menu/Popover/Dialog/Drawer open+close (trigger · Escape · overlay/close-button) and Pagination/SegmentedControl selection; all pass. (4) `guidelines/atomic-view.html` gained a **live controls panel** (Storybook-style) on Button/Badge/Alert — select/toggle/text editors driving live props on a reusable mechanism. Both gates registered in `_audit/index.html` + `_audit/README.md`. Compiler clean; contrast-guard + story-coverage + behavior + docs-consistency all green.
- **2.20.0** (Jul 2026) — **Atomic View — a Storybook for the system (user-requested).** New `guidelines/atomic-view.html`: a browsable gallery of **every component (42 stories)** grouped by Atomic-Design tier (Atoms · Molecules · Organisms), each rendered live and reskinned in real time across all three system axes — **Theme (light/dark) × Element (15 Ngũ Hành packs) × Expression (7 treatments)** — from one toolbar, so any component can be checked in any variant in one place. Filterable tiered sidebar with jump links; portal components (Dialog, Drawer, CommandPalette, Popover, Toast) are frame-scoped to render inline; any missing export self-reports. Registered as a `@dsCard` (new **Atomic View** group) so it's one click from the Design System tab, and it also opens standalone. This is the “isn't it like Storybook?” answer — yes, tuned to this system's three axes (a plain Storybook has no Element/Expression axis). Verified: 42 stories, 0 missing, all three axes reskin live (dark canvas, `--cs-accent` remaps per element, expression treatments apply). The README component map now also carries an **Atomic tiers** view (Atoms/Molecules/Organisms) matching this browser, so the written docs and the live view agree. Compiler clean (57 cards); docs-consistency re-verified.
- **2.19.1** (Jul 2026) — **Dark-mode contrast + table/wordmark fixes (user-reported).** Fixed real dark-surface contrast defects the theme advisory had flagged among its false positives (the advisory earning its keep): (1) base `.cs-nav-item.is-active` and `.cs-button--secondary/--tertiary/--ghost` set umber text/border with **no dark override** → near-invisible on dark surfaces; added `[data-theme="dark"]` overrides (nav-active + secondary → ochre; tertiary/ghost → light body colour). One base fix repairs every template + card (verified: secondary button ~9.8:1, nav-active ochre). (2) The two dark-capable **screen** templates hardcoded the brand wordmark as `--cs-color-brand-umber` (`marketing-page`, `app-shell`) → swapped to `--cs-color-text-primary` so it flips to cream in dark (identical in light; print-doc headers stay umber by design). (3) `bod-minutes` resolution **NO.** column word-broke `R-26-07`→`R-26-/07` → `white-space:nowrap` on the mono ID cells (EN + VN). (4) `shell.card` command-palette clipped left (a 560px dialog in a ~430px demo frame) → constrained to the frame width. Root cause codified in `docs/conventions.md` (umber-on-themeable-surface needs a dark override). Compiler clean; docs-consistency re-verified.
- **2.19.0** (Jul 2026) — **Audit symmetry + DTCG tokens + behavior/visual gates.** Brought the *language* and *theme* passes up to the race-free, manifest-driven, all-84 standard the responsive gate reached in 2.18.0 (owner doctrine: language · theme · responsive each get their own whole-set pass; one clean state is not evidence for another). New **`_audit/language-overflow.html`** — forces Tiếng Việt on all 84 templates in fresh single-navigation iframes and fails on any VN-induced document overflow or text clipping; **verified 84/84 green — VN applied on every template, 0 overflow/clip @390.** New **`_audit/theme-overflow.html`** — forces dark on all 84; **hard gate = dark-applies + 0 document overflow in dark (verified green: 16 themed templates, 0 dark overflow; 68 light-only by design).** Its contrast check is deliberately **advisory, not gating**: a DOM ancestor-walk cannot reliably attribute the painted fg/bg pixel in this layered/branded/deck system — proven by three false-positive classes (transparent-chain fallback; email header bands read as light; and a deck reporting “black-on-dark” that visually renders as **legible cream** because the walk measured a container’s inherited UA colour, not the styled child). The advisory scans only leaf text over a resolvable solid, image/gradient-free background and lists suspects to eyeball; authoritative dark-contrast proof stays the manual token audit (`docs/contrast-report.md`, v2.9.0) + the new visual-diff review. New **`_audit/component-behavior-test.html`** — drives real interactions on the compiled components (Switch/Checkbox toggle, Accordion single-open switch, Tabs controlled selection, CommandPalette live filter) and asserts state, beyond the mount-only `component-children-test`. New **`_audit/visual-diff.html`** — a visual-regression *review* assist (side-by-side + mix-blend-difference overlay of live render vs. stored baseline; honestly not a numeric gate — nested-iframe raster is unavailable and the baselines are downscaled references). New **`tokens/tokens.dtcg.json`** — the full token set in **W3C DTCG** format (`$value`/`$type`, CSS-var keys for lossless round-trip, scope overrides under `$extensions`), importable by Tokens Studio for Figma / Style Dictionary; generated from `tokens/tokens.json` (regenerate after any token change). Registered all four harnesses in `_audit/index.html` + `_audit/README.md`; docs (llms · SKILL · `docs/conventions.md`) teach the DTCG export and the audit-symmetry + DOM-contrast-limitation policy. Compiler clean; docs-consistency + namespace-portability + responsive-overflow re-verified green.
- **2.18.0** (Jul 2026) — **Responsive: no horizontal scroll on phone/tablet + all-template preview.** A whole-set audit (`_audit/responsive-overflow.html`, all 84 templates in fresh race-free iframes) found real horizontal overflow at mobile 390 in the print-doc write-on lines (agenda/PIP/review `______` runs), the app-shell (shell grid didn't collapse; DataTable didn't scroll), the 16:9 decks (a slide's min-content exceeded even a 1280 laptop), and the marketing-page header. Fixes in `base/responsive.css`: §9 `overflow-wrap:anywhere` on `.cs-desk/.cs-sheet` (unbreakable tokens break instead of propping a column open — and `anywhere` shrinks min-content, so tracks size down); §10 app-shell shell grid collapses to one column (attribute selector — see gotcha) with `main{min-width:0}` + `.cs-table-wrap` scroll; §5 `.cs-canvas-desk` now `overflow-x:auto` at **all** widths so an oversized slide scrolls inside the desk instead of pushing the page wide. Two templates fixed in source (robust — CSS can't reliably override an inline-set prop): app-shell search `min-width:0`, marketing-page header `flex-wrap:wrap`. Verified **84/84 = 0 document overflow at 390**; desktop unchanged. **Gotcha documented:** a class selector can't override an inline style — inline-set props need an *attribute* selector or an in-source fix; and reusing one iframe across many templates races the `@import`ed CSS (false positives) — always probe with a fresh iframe. **Responsive preview** (`_audit/responsive-harness.html`) upgraded from 8 hardcoded templates to **manifest-driven, all 84** (grouped + filterable, fresh iframes) — "all variants available." Compiler clean; docs-consistency + namespace-portability re-verified green.
- **2.17.0** (Jul 2026) — **Namespace portability — zero-touch re-import.** The compiler names the bundle global `window.CyberSkillDesignSystem_<projectId>`; the 6-hex suffix is derived from the project id, so it changes whenever the system is imported into another project — and every file that hardcoded `…_847b3c` broke on re-import until global-replaced (observed live in a Claude Code re-import — 23 files needed the sweep). Made the whole system resolve the namespace dynamically. **`ds-base.js`** (all 84 template copies) now publishes a stable, id-independent **`window.CyberSkillDS`** alias in the bundle's `onload`; **all 84 templates** mount via `component-from-global-scope="CyberSkillDS.…"`; **all 19 component cards, the UI-kit chat page, the raw standalone email, and the audit harnesses** resolve by prefix (`window[Object.keys(window).find(k=>/^CyberSkillDesignSystem_[0-9a-f]{6}$/.test(k))]`). Docs (README · llms.txt · `docs/consuming.md`) now teach the portable pattern instead of a literal suffix; `docs/conventions.md` codifies the rule. New guard **`_audit/namespace-portability.html`** fetches every manifest-indexed source (84 template entries + 56 cards + the kit pages) and **fails if any hardcodes a project-id suffix** — verified green (it also asserts the alias + mount pattern are present, not just the bad pattern absent). Net effect: re-import into any project needs **no namespace sweep**. (`_ds_bundle.js` / `_ds_manifest.json` still carry the real suffix — they *define* it — as does the frozen `_audit/exports/` snapshot.) Compiler clean; `docs-consistency` + `consumer-smoke-test` re-verified green.
- **2.16.1** (Jul 2026) — **Maintenance: count reconciliation + consumer-path health re-proof.** Corrected a stale Templates count in the README Quick-start (`85`→`84`, the compiler's true count — the other README/SKILL references already read 84; doctrine: counts follow the compiler). Re-ran `_audit/consumer-smoke-test.html` against the *freshly-compiled* bundle — **PASS** (68 namespace exports · tokens resolve `umber #45210E` · 11 key components mount without error · umber `Button` inherits the brand token · 21 real DOM nodes). Reconciled the 67-vs-68 denominator: the namespace correctly exposes 3 internal data constants (`CS_ICONS`, `CS_LOGO_MARK_INNER`, `CS_LOGO_VIEWBOX`) beside the 67 `.d.ts`-paired components — not a registration gap (`check_design_system`: *no issues*). Added **`_audit/docs-consistency.html`** — an automated guardrail that reads `_ds_manifest.json` + `VERSION` (the compiler's truth) and asserts every count/version claim in the **live** docs matches: template count, export count, component-file count, token count, and all five version pointers (README-above-changelog · SKILL · llms + the two CHANGELOG pointers; changelog *bodies* excluded so historical counts stay frozen). It's the machine form of *"counts follow the compiler"* — and it immediately paid for itself, catching a stale `llms.txt` component-file count (corrected to **54 modules / 67 exports** — the 55th manifest sourcePath is the `logo-data.js` data helper, not a component). Registered in `_audit/index.html` + `_audit/README.md`; suite is green.
- **2.16.0** (Jul 2026) — **Optional-set completion (O1–O3).** (O1) Built the remaining send-path email-safe copy-swaps — `email-launch`, `email-status`, `email-announcement`, `email-investor` (all bilingual, table-based, from the transactional exemplar; leak-scanned clean). (O2) Playground element picker now covers all 15 Ngũ Hành variants. (O3) Added `docs/consuming.md` — how an external project adopts (static stylesheet vs. compiled bundle vs. templates) and upgrades the system safely.
- **2.15.0** (Jul 2026) — **Consumer proof, playground & imagery finish (S1–S3).** (S1) Added `_audit/consumer-smoke-test.html` — imports `styles.css` + `_ds_bundle.js` exactly as an external project would, mounts real components off the namespace, and asserts tokens resolve + the brand token reaches a Button. **PASS** (68 exports, umber button). This is the first check of the *packaged* consumer path, not just the in-repo sources. (S2) Finished the social-kit image-slots (link + story canvases join square); the remaining email copy-swaps add no structural coverage beyond the three `email-safe` exemplars. (S3) Added `templates/playground.html` — a live Theme × Element × Expression switcher over a component gallery, proving the same markup re-skins across all three axes with zero code changes.
- **2.14.0** (Jul 2026) — **Image-slot retrofits (R1–R4).** Applied the real-imagery pattern to the image-hungry template heroes — `marketing-page`, `marketing-social-kit` (square canvas), and `culture-event-invite` — each with a source-ordered `<image-slot>` behind the `.cs-aurora-wash` + a warm umber scrim so the empty drop-tile stays subtle and copy is legible over any dropped photo (verified render on all three). `article` intentionally skipped — it's a text-first reading layout where a full-bleed hero image doesn't fit (an inline lead figure is a per-article copy choice). Story/link social canvases follow the identical pattern on request.
- **2.13.0** (Jul 2026) — **Consumer polish & completeness (K1–K6).** (K1) Finished the email-safe set — added `email-newsletter.html` (multi-card) + `email-dunning.html` (amount-box) so `templates/email-safe/` now covers all three send-ready structures. (K2) Retrofitted the `<image-slot>` real-imagery pattern into `marketing-case-study` (verified web-component-in-DC integration) and documented the 4-line pattern. (K3) Split the changelog into this `CHANGELOG.md`; README keeps recent + a pointer. (K4) Added `CONTRIBUTING.md` consolidating the Expansion Rule + verification doctrine + add-a-thing recipes. (K5) Extended the icon set 19→27 (chevron-down/up/left/right, edit, copy, info, alert-triangle) synced across `Icon.jsx`/`.d.ts`/prompt/card/iconography/README. (K6) Confirmed RTL-readiness (logical properties throughout; verified at `dir="rtl"`) and fixed the last 2 physical props in `responsive.css`.
- **2.12.0** (Jul 2026) — **Dev-consumer & imagery polish (M1–M5).** (M1) Generated machine-readable token exports — `tokens/tokens.json` + `tokens/tokens.js` (ESM), root grouped by 16 categories plus theme/element/expression override maps (134 root · dark/system 22 · 15 elements · 6 expressions); regenerate from `tokens/*.css`. (M2) Added `templates/email-safe/` — a send-ready, table-based, fully-inlined bilingual email (bulletproof CTA, Outlook conditionals, preheader, email-safe fonts, dark-mode-safe brand colors) as the canonical pattern for the DC emails, which use client-stripped modern CSS. (M3) Rebuilt the Motion specimen card with **live** animating easing tracks + duration chips (was a static value table). (M4) Added the `<image-slot>` mechanism + `templates/image-slots-demo.html` showing the layout-safe real-imagery pattern (full-bleed hero with warm scrim, avatars, card images). (M5) Added `templates/kitchen-sink.html` — the whole component library in one scroll for fast cross-component review.
- **2.11.0** (Jul 2026) — **Follow-up polish (N1–N6).** (N1) Closed the last bilingual-`lang` gap: wrapped every `sc-if isVN` block in the 24 dual-block templates with a layout-neutral `<div lang="vi" style="display:contents">`, so VN is pronounced correctly even in *Both* mode. (N2) Added a token-contract test — static (element role-token completeness + no undefined `var()` in tokens/base) and runtime (`_audit/token-contract.html`); both pass. (N3) Verified print-CSS is identical across all 61 docs and triggered a real A4 PDF export for visual pagination confirmation. (N5) Added `[data-theme="dark"]` shadow overrides (near-black) so elevation reads on dark surfaces — the umber-tinted light shadows vanished there. (N6) Added `_audit/index.html`, a launcher for the whole verification suite. (N4) Seeded `_audit/baselines/` with product/document/deck reference captures for visual regression.
- **2.10.3** (Jul 2026) — **Dual-block *Both*-mode language marking (N1).** Wrapped every `sc-if isVN` block in the 24 dual-block templates with a layout-neutral `<div lang="vi" style="display:contents">`, so VN text is pronounced correctly even in **Both** mode (where the root carries the primary `en`). Verified: email in Both mode renders both languages with the VN block under `lang="vi"` and no layout shift. Closes the last documented bilingual-`lang` gap — pronunciation is now correct in every language mode.
- **2.10.2** (Jul 2026) — **Bilingual `lang` rollout completed + P6 fix confirmed.** Extended screen-reader language marking from the 37 `vn-*` instruments to **all 44 tweakable bilingual templates** — each root now binds `lang="{{ langAttr }}"` to the Language tweak (injected into `renderVals`; 23 swap + 21 dual-block), so switching to Tiếng Việt marks the document `lang="vi"` (verified: email resolves `vi` in VN mode). Every bilingual template now carries a root `lang`. Also re-ran `_audit/component-children-test.html` against the freshly-compiled bundle: all 8 hardened void-element components mount cleanly with stray children (`anyThrew: false`) — the P6 fix is confirmed at runtime. Remaining nuance: dual-block **Both** mode marks the root primary (`en`) with VN blocks unmarked (per-block `lang="vi"` is the documented refinement).
- **2.10.1** (Jul 2026) — **Docs & tooling (Phase 7).** Verified every one of the 55 components ships a `.prompt.md` (complete AI-consumer coverage). Formalized `_audit/` as a named regression suite in `_audit/README.md` (responsive · vn-overflow · a11y · component-children harnesses + exports), and cleaned stray captures. Synced `SKILL.md` — added an **Exporting** section (PPTX/PDF/standalone paths), refreshed the a11y hard-rule (coarse-pointer 44px, reduced-motion, prefers-contrast, dark AA) and the guidelines groups. Contribution/expansion process is the Expansion rule + the `docs/conventions.md` decision log (no separate file needed).
- **2.10.0** (Jul 2026) — **Component gaps & API consistency (Phase 6).** Audited the 55-component / 67-export set — coverage is complete (all common primitives present: Tooltip, Popover, Alert, Badge, Tag, EmptyState, ProgressBar, Skeleton, Spinner, Card, Avatar, Accordion, CommandPalette, Sidebar, Steps, …); DatePicker/Combobox are deliberately out of scope for a base DS. Hardened the whole void-element family against the React #137 footgun that hit `settings`: TextField, Checkbox, Radio, Switch, SearchField, NumberField, Slider, and Divider now destructure `children` out of `...props` so a stray child can never spread onto an `<input>`/`<hr>`. State coverage is supported across the set (Button loading/disabled, fields error/disabled/readOnly, plus EmptyState/Skeleton/Spinner/ProgressBar). Retained `_audit/component-children-test.html` to re-confirm against each fresh bundle.
- **2.9.2** (Jul 2026) — **Responsive completeness verification (Phase 5).** Deep-checked print + ultrawide, no changes needed. Print is clean by construction: a whole-project scan found the only bare `@media (max-width)` queries are `.cs-dialog` (640px, below A4/Letter print width so never fires on paper; dialogs aren't printed) and exempt UI-kit/vendor pages — every responsive collapse rule in `responsive.css`/`a11y.css` is `@media screen`, so no screen reflow reaches print. Confirmed every content template caps its width (emails 600–640px · docs 760–820px · article 720px · decks/social/dashboard 1280px), so nothing stretches at ultrawide; app-shell is intentionally full-width. Inline-grid collapse is handled globally by `responsive.css §7`.
- **2.9.1** (Jul 2026) — **Typography & locale verification (Phase 4).** Deep-checked the Vietnamese type foundations — no code changes needed, all sound: both self-hosted fonts ship a full `vietnamese` subset for every weight; line-heights are VN-safe (`:where(h*)`=1.35 + balanced wrap, `.cs-display`=1.15); and a scan confirmed English-format dates appear only in English branches while VN branches use VN formats (`DD/MM/YYYY`, `₫` suffix, dot-thousands). Codified the VN typography + locale conventions in `docs/conventions.md`.
- **2.9.0** (Jul 2026) — **Contrast & theming (Phase 3).** Audited every dark-theme text/surface pairing (all pass WCAG AA body, 9–15:1) and confirmed the 15 elemental packs still pass APCA Lc ≥ 60 (unchanged). Verified dark completeness: core dark already remaps the primary button to Ochre and warms the field border, so no dark control is low-contrast. Added a high-contrast accommodation — `@media (prefers-contrast: more)` strengthens the soft hairline border + muted text on request. Documented the new dark-semantic pairings in `docs/contrast-report.md`.
- **2.8.0** (Jul 2026) — **Accessibility hardening (Phase 2).** Added `base/a11y.css`: 44px touch targets on `@media (pointer: coarse)` for every interactive control (tabs, pagination, menu items, stepper, checkbox/radio, segmented) while keeping desktop mouse density, plus a global `prefers-reduced-motion` safety net. Fixed a real focus-ring regression — `.cs-menu__item` set `outline:none` on `:focus-visible` (keyboard users got no ring); now a 3px inset ochre ring. Marked the 37 Vietnamese instruments `lang="vi"` for correct screen-reader pronunciation (bilingual `lang` convention documented). Fixed a real **dark-theme contrast defect** found by a full pairing audit: the semantic colours had no dark overrides and failed on dark surfaces (~2.5:1); added dark-safe `success/danger/warning/info` (now 6–10:1). Verified component ARIA is already complete across all interactive components. Audit harness: `_audit/a11y-harness.html`.
- **2.7.0** (Jul 2026) — **Export & handoff fidelity (Phase 1).** Proved and hardened every export path, all preserving Vietnamese. (1) **All 61 document templates are now one-click PDF-exportable** — added `<meta name="omelette-owns-print">` to each doc's raw `<head>` so the browser print engine paginates them at A4/Letter (the export dialog now accepts them directly; no rebuild). (2) **All 4 decks export to editable PPTX in VN** — verified by unzipping the slide XML: VN diacritics survive as native text runs (26–69 runs/deck, zero empty, only the Logo is an image). (3) **Standalone offline-HTML path proven** for DCs — the dynamic `ds-base.js` loader is invisible to the bundler, so the pattern is a same-folder `*-standalone.html` copy with static `<link>`/`<script>` resource tags; shipped a VN email bundle (fonts inlined, faithful offline). (4) Documented the **export-path matrix + font-embedding policy** in `docs/conventions.md`. Artifacts in `_audit/exports/`.
- **2.6.2** (Jul 2026) — **Deep-verification pass (found real bugs).** A complete VN render audit forced every one of the 44 toggle-able templates into Tiếng Việt (via `__dcSetProps`) and measured clipping/overflow — **0 offenders**, diacritics clean at display and body sizes. It caught a genuine crash: `settings` passed a `TextField` value as **children**, which the component spreads onto its `<input>` (a void element) → **React #137 on every prop re-render** (any tweak toggle, not just language); fixed by using `default-value`, and documented the rule (never children on `TextField`). Also: **print regression fixed** — responsive media rules are now `@media screen` so a <900px print page keeps the native A4/Letter layout instead of collapsing; **mobile touch targets** (§8) grow sidebar nav rows (39→44) and the search input (26→44) to the 44px floor on ≤760px; dark-theme reflow confirmed (layout and theme are orthogonal at 390px). New dev harnesses in `_audit/` (responsive + VN overflow). Verification-depth rule codified in `CLAUDE.md`.
- **2.6.1** (Jul 2026) — **Responsive & bilingual hardening.** Fixed the responsive layer, which was inert: its `[style*=…]` selectors used no-space syntax while the DC runtime serializes React styles *spaced* (`grid-template-columns: repeat(4, 1fr)`), so nothing matched. Rewrote every substring selector, added inline fixed-column grid collapse (3+→2 tablet, →1 phone) and deck/social `cs-canvas-desk` scroll (keeps export geometry), and **verified at 390/768/1280 px** via a new harness (`_audit/responsive-harness.html`) — reaching into the same-origin frames confirmed the 4-col agenda bar collapses 4→2→1 and decks scroll with 3-col slides intact. Header eyebrow labels (Agenda, Runbook, Master agreement, …) now swap with the Language tweak. Ran a **complete bilingual audit across all 84 templates** (mechanism, en/vi key parity, hole coverage, hardcoded-leak scan): parity clean everywhere, and fixed 6 residual leaks — `delivery-change-note` English-month dates + party name, `article` team label, `marketing-page` footer slogan + "golden genie", and the board runway unit (`19 mo`→`19 tháng`).
- **2.6.0** (Jul 2026) — **Full bilingual coverage + responsive layer.** The last 8 English-only templates gained the *English · Tiếng Việt* Language tweak — board & comms (`bod-report`, `bod-deck`, `bod-investor-update`, `bod-resolution`) and client decks/docs (`sales-proposal-deck`, `tech-rfc`, `delivery-kickoff`, `delivery-qbr-deck`). **All 84 templates are now bilingual** (37 `vn-*` + 3 `doc-*` stacked Vietnamese-first; every other template swaps via the Language tweak, several emails add *Both*). Also shipped a global responsive layer (`base/responsive.css`) — fluid media, print-doc padding reflow, table + fixed-canvas scroll (decks/social carry `cs-canvas-desk` and scroll to keep export geometry), sidebar collapse, and inline fixed-column grids that collapse (3+→2 on tablet, →1 on phone) across every archetype; its `[style*=…]` selectors match the DC runtime's spaced style serialization (`grid-template-columns: repeat(4, 1fr)`). Enforced full **language separation**: swept the header brand line to the canonical bilingual lockup (`Hiện Thực Hoá Ý Chí · Turn Your Will Into Real`) across 17 doc headers, and made every header eyebrow label (Agenda, Runbook, Master agreement, …) swap with the tweak — a selected language now renders with no stray English/Vietnamese (rule codified in `docs/conventions.md`).
- **2.5.0** (Jul 2026) — Consolidated the 4 reference docs into **3 suite-wide documents** that now govern EVERY template (not just the HR suite): `doc-style-guide` (Style Guide — Articles 1–10 verbatim + new Article 11 archetype map), `doc-suite-index` (merged Suite Index + Usage Guide — full catalogue of all categories + lifecycle/discipline/house-rules/how-to-add), `doc-templates` (blank A4 shell + archetype map). Removed `suite-style-guide` / `suite-index` / `suite-usage-guide` / `suite-word-template`; no stale HR/Employment-Suite-scoped naming remains on the reference docs. HR Suite is now 37 `vn-*` instruments; the 3 reference docs stand suite-wide.
- **2.4.1** (Jul 2026) — Removed four fictional templates now superseded verbatim by validated Employment Suite instruments: `legal-nda`→`vn-mutual-nda`, `hr-offer-letter`→`vn-offer-letter`, `hr-onboarding`→`vn-onboarding-checklist`, `hr-job-description`→`vn-job-description`. Remaining fictional templates are EN-first comms and client-facing sales/finance paperwork (distinct purpose). Docs/counts synced.
- **2.4.0** (Jul 2026) — **HR & Employment Suite** (+41 templates, ~90 total): 41 client-supplied, lawyer-validated bilingual documents converted one-by-one into templates with content preserved verbatim and re-skinned to the latest system, following the suite's own Style Guide (A4, VN-first Ink/Slate pairs, state-motto header, umber table bars, yellow fill-ins, PDPL blank Party B). New **HR Suite** group under `templates/vn-*` + `templates/suite-*`; every doc carries the Element + Expression tweaks. `vn-labor-contract` supersedes (and removes) the earlier fictional `legal-employment-contract`. `.docx` provenance retained under `docs-src/`.
- **2.3.0** (Jul 2026) — **Operations coverage build-out** (+18 templates, 49 total): Delivery pack (status email EN·VN·Both, kickoff, change note, runbook/handover, QBR deck); People pack (interview kit, performance review, offboarding, retro — all EN·VN); Comms pack (social kit 1080²/1200×630/1080×1920, Culture event invite, board minutes EN·VN, investor update, expense report EN·VN, dunning email EN·VN·Both); counsel-gated trio banner-marked (PIP EN·VN, board resolution, VN-primary employment contract). New team groups: Delivery, Culture. Expansion rule extended to related documents/guidelines.
- **2.2.0** (Jul 2026) — **Expansion rule codified** (CLAUDE.md · conventions · SKILL): when any set grows, every deliverable updates in the same change, gated by compiler + grep. Gaps it caught, fixed: component icon card was stuck at 9 icons (→19); one-pager hero glow hardcoded ochre (→ `--cs-accent-glow`); EN·VN added to `team-meeting-agenda` + `hr-job-description`.
- **2.1.1** (Jul 2026) — Housekeeping: removed the finished audit and the shipped proposal docs (operative rules live in `docs/conventions.md`, token-file headers, and the cards; decisions preserved in the conventions decision log), the consumer-test scaffold (validation recorded), and the stale pre-Ngũ-Hành brand-deck PPTX (export on demand).
- **2.1.0** (Jul 2026) — Element tweak expanded to all 15 variants everywhere; **Expression tweak on all 31 templates** (7 treatments); README entrance ("Start here" + document map); Tương-sinh gradient wash referenced live on the marketing CTA band; Identity Lab shows all 15 variant pills.
- **2.0.0** (Jul 2026) — Consumer rebind validated end-to-end (`templates/_consumer-test/`); APCA contrast sweep, 0 failures after 13 token nudges (`docs/contrast-report.md`; new rule: text never sits on the mid-tone accent); icon set 9→19; components-under-elements card; 4 new templates (case study, press release, job description, meeting agenda — 31 total); EN·VN on memo, offer (banner-marked), onboarding, incident; Ngũ Hành slide in the brand deck; elemental thumbnail strip; onboarding emoji removed per doctrine.
- **1.10.0** (Jul 2026) — `luxe` expression (cap extended 6→7 by owner decision); **Element tweak on all 27 templates** (docs, emails, decks, product surfaces — accents swept to `--cs-accent-*` roles); Identity Lab gains luxe.
- **1.9.0** (Jul 2026) — Provisional product→element registry (5 products, per "decide for me"); `dense` expression (6th and final slot); Identity Lab (`ui_kits/status-hub/identity-lab.html`) — live Theme × Element × Expression switching; unreviewed-draft Tiếng Việt versions of NDA, MSA, SOW, invoice, quote (language tweak; English governs).
- **1.8.0** (Jul 2026) — Expressions treatment axis (`tokens/expressions.css`: solid · paper · soft · bold; glass default); expression tweaks on dashboard, marketing-page, app-shell, settings, auth, article; Expressions specimen card; elemental aurora washes (`.cs-aurora-wash`, consumed by the marketing hero); element tweak on sales-proposal-deck; bilingual toggles completed across all five email templates; Elements variants card.
- **1.7.0** (Jul 2026) — Ngũ Hành elemental identity layer (`tokens/elements.css`, `--cs-accent-*`, element tweaks on marketing-page + slide-deck); business templates (legal · finance · sales); bilingual email tweaks; audit cleanup (single-entry ds-base, ai2→ai, refinements→interaction, component-tokens rename, deck-stage out of bundle, print docs light-only); conventions + registry docs; iconography + interaction cards.
