diff --git a/docs/design-system-contract.md b/docs/design-system-contract.md index 850ab04813..d69ff72c34 100644 --- a/docs/design-system-contract.md +++ b/docs/design-system-contract.md @@ -34,7 +34,7 @@ npm run check:icon-scale ### 2.2 Typography Scale - **Named Steps Only**: Font sizes must use the registered type steps in `@theme`: - - `text-3xs` (10px - absolute floor), `text-2xs` (11px), `text-xs` (12px), `text-sm-minus` (13px), `text-sm` (14px), `text-base-minus` (15px), `text-base` (16px), `text-lg-minus` (17px), `text-lg` (18px), `text-xl` (20px), `text-2xl-minus` (22px), `text-2xl` (24px). + - `text-3xs` (10px - absolute floor), `text-2xs` (11px), `text-xs` (12px), `text-sm` / `text-sm-minus` (13px; v2 `--text-sm` equals `@theme --text-sm-minus` at `0.8125rem`), `text-base-minus` (15px), `text-base` (16px), `text-lg-minus` (17px), `text-lg` (18px), `text-xl` (20px), `text-2xl-minus` (22px), `text-2xl` (24px). - **Arbitrary Size Prohibited**: `text-[12px]`, `text-[13px]`, etc. are blocked by `npm run check:type-scale --strict`. - **Declared Steps Usage**: Any type step declared in `@theme` must have production consumers (no dead or unselected type tokens). diff --git a/docs/design-system.md b/docs/design-system.md index 73e9116a2a..e12da5922a 100644 --- a/docs/design-system.md +++ b/docs/design-system.md @@ -77,9 +77,12 @@ When you meet a pre-token hardcode (mockups being promoted, old branches), map i Named steps live in the `@theme` block of `globals.css` and are **size-only** (no baked line-height/tracking — set `leading-*`/`tracking-*` at the call site): -`text-3xs` 10px (floor) · `text-2xs` 11px · (`text-xs` 12 / `text-sm` 14 / `text-base` -16 from Tailwind) · `text-sm-minus` 13px · `text-base-minus` 15px · (`text-lg` 18 / `text-xl` -20 / `text-2xl` 24 from Tailwind) · `text-lg-minus` 17px · `text-2xl-minus` 22px. +`text-3xs` 10px (floor) · `text-2xs` 11px · (`text-xs` 12 / `text-base` 16 from Tailwind) · +`text-sm` / `text-sm-minus` 13px (v2 `--text-sm` equals `@theme --text-sm-minus` at +`0.8125rem`; Tailwind's default `text-sm` 14px is overridden app-wide because `ckb-v2` is +mounted on ``. Pinned in `tests/ckb-v2-token-contract.test.ts`; do not restore 14px +and do not alias the two files at each other) · `text-base-minus` 15px · (`text-lg` 18 / +`text-xl` 20 / `text-2xl` 24 from Tailwind) · `text-lg-minus` 17px · `text-2xl-minus` 22px. - **10px is the floor.** An 8px `text-4xs` step existed and is retired — indefensible at any density in a clinical product. Do not reintroduce a sub-10px step. diff --git a/docs/design-system/GATES.md b/docs/design-system/GATES.md index fc885beddb..ddbafefef8 100644 --- a/docs/design-system/GATES.md +++ b/docs/design-system/GATES.md @@ -19,7 +19,7 @@ than CI, two of them by the second reader; review does not scale past two carefu | Check | What it enforces | Label | | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------ | | `npm run check:design-system-contract` (token baseline + adoption + design-sync contracts) | Raw colour literals (ratchet against `design-system-contract-baseline.json`), literal `shadow-[…]` classes, the legacy tap class, interactive tap-size literals, therapy-compass `tc-btn` base-class use; border+ring edge conflicts, 1px shadow spreads, layout-property transitions and legacy shadow aliases (all ratcheted **per path**, so new use fails anywhere); status-coloured numerals and colour-only status indicators; raw padding, radius, gap and line-height literals in both classes and CSS declarations (ratcheted **per path**; named utilities and Tailwind arbitrary-property forms such as `[padding:22px]` both count; values computed with `var()`/`env()`/`calc()`/`clamp()`/`max()`, zero with any CSS unit identifier, and the CSS-wide keywords are exempt); declared-but-unselected type steps (**hard rule** with a gated exemption list); `dark:` colour overrides, legacy palette utilities and image-inversion filters (all pinned at **zero**, not ratcheted); deterministic adoption truth; local source/export/preview/design-sync parity. Mockups exempt. | implemented-blocking | -| `tests/ckb-v2-token-contract.test.ts` | v2 layer stays class-scoped (no `:root` leak) · `--border-lux` solid and no lighter than `--border`, both themes · dark surface ramp monotonic and separated · `--surface-subtle` aliases up · text/muted/heading ≥4.5:1 on the light shell, muted ≥4.5:1 dark · `--text-soft` pinned **below** 4.5:1 and ≥3:1 (both sides, so the tier cannot be "fixed" away) · command pair ≥4.5:1 both themes · `--shadow-inset` true inset · elevation ladder carries no baked 1px hairline · tap floor ≠ chip height ≠ compact row · reduced-motion zeroes durations · type-scale pins `--leading-prose` plus `--text-hero--line-height` / `--text-hero-tr` (no per-step `-lh`/`-tr` orphans) | implemented-blocking | +| `tests/ckb-v2-token-contract.test.ts` | v2 layer stays class-scoped (no `:root` leak) · `--border-lux` solid and no lighter than `--border`, both themes · dark surface ramp monotonic and separated · `--surface-subtle` aliases up · text/muted/heading ≥4.5:1 on the light shell, muted ≥4.5:1 dark · `--text-soft` pinned **below** 4.5:1 and ≥3:1 (both sides, so the tier cannot be "fixed" away) · command pair ≥4.5:1 both themes · `--shadow-inset` true inset · elevation ladder carries no baked 1px hairline · tap floor ≠ chip height ≠ compact row · reduced-motion zeroes durations · type-scale pins `--leading-prose` plus `--text-hero--line-height` / `--text-hero-tr` (no per-step `-lh`/`-tr` orphans) · v2 `--text-sm` === `@theme --text-sm-minus` === `0.8125rem` (literals; not aliased at each other) | implemented-blocking | | `tests/design-token-contract.test.ts` | Live-layer token relationships (companion to the v2 contract) | implemented-blocking | | `tests/source-badges-off-vocab.dom.test.tsx` | Enum resilience: off-vocabulary `clinical_validation_status` degrades to the neutral triad, logs once, never throws | implemented-blocking | | `tests/source-metadata-browser-safety.test.ts` | The `process is not defined` client-bundle crash stays fixed (server logger never ships to the browser) | implemented-blocking | diff --git a/tests/ckb-v2-token-contract.test.ts b/tests/ckb-v2-token-contract.test.ts index b2ad7873c2..7eb12e6c70 100644 --- a/tests/ckb-v2-token-contract.test.ts +++ b/tests/ckb-v2-token-contract.test.ts @@ -2,7 +2,7 @@ import { readFileSync } from "node:fs"; import { describe, expect, it } from "vitest"; -import { sourceFrom } from "./helpers/source-contract"; +import { sourceFrom, sourceSegment } from "./helpers/source-contract"; /** * Invariants of the scoped `.ckb-v2` token layer (`src/app/ckb-v2-tokens.css`). @@ -324,6 +324,23 @@ describe("ckb-v2 structure", () => { expect(structural.get("--text-hero--line-height")).toMatch(/^\d+(\.\d+)?$/); expect(structural.get("--text-hero-tr")).toMatch(/^-/); }); + + it("pins v2 --text-sm to @theme --text-sm-minus at 0.8125rem (PR 3c)", () => { + // Production `text-sm` is 13px because `.ckb-v2` is mounted on . + // The overlap with `--text-sm-minus` is the catalog. Do not "fix" it by + // restoring Tailwind's 14px, and do not alias the two files at each other: + // both layers keep the same literal so the documented source-of-truth + // order (v2 above the compat `@theme` block) stays intact. + const theme = declarations( + sourceSegment(globalsStylesheet, "\n@theme {", "\n}", { label: "globals.css `@theme`" }), + ); + const v2Sm = structural.get("--text-sm"); + const themeSmMinus = theme.get("--text-sm-minus"); + + expect(v2Sm).toBe("0.8125rem"); + expect(themeSmMinus).toBe("0.8125rem"); + expect(v2Sm).toBe(themeSmMinus); + }); }); describe("ckb-v2 category chip tones", () => {