fix(debug 04-06): decouple welcome-hero mark stroke via --mks-mark-stroke

Operator-empirical Task 4 checkpoint flagged the dark-mode mark stroke
as muddy ink-on-madder. Root cause: .welcome-hero__mark used
`color: var(--mks-fg-inverse)`, which is a SEMANTIC text-foreground-on-
inverse-surface token that flips to ink-900 in the dark theme
(tokens.css line 244). The mark sits on a theme-independent madder-600
circle, so the stroke must be theme-independent too.

Fix: introduce a dedicated BRAND-COMPONENT token --mks-mark-stroke =
var(--mks-linen-50) in the universal :root block. CRUCIALLY NOT
overridden in the .dark/[data-theme="dark"] block — stays linen-50 on
every surface. Rewire .welcome-hero__mark to point at the new token.

SVG (mokosh-mark.svg) unchanged — `stroke="currentColor"` cascade
plumbing identical; only the wrapper's color source changed.

A35 strengthened: extracted live-DOM probe into a helper, now probes
BOTH light + dark themes (data-theme="dark" toggle on documentElement),
and added A35.5 — the decouple proof that light.computedStroke ===
dark.computedStroke === "rgb(250, 247, 241)" (linen-50). No new
__MOKOSH_UAT__ symbol; FORBIDDEN_HOOK_STRINGS stays at 12.

Scope expansion note: src/welcome/welcome.css was not in Plan 04-06
re-plan iter-2 files_modified. The edit is authorized by the operator's
TWEAK verdict on Task 4 checkpoint.

Verification:
- /tmp/04-06-welcome-hero-{light,dark}.png re-shot — both show identical
  crisp linen-on-madder grid icon.
- A35.5 LIVE-DOM probe (UAT): light="rgb(250, 247, 241)", dark=same.
- UAT 36/36 GREEN; vitest 187 + 1 tolerated webm-remux flake.
- 6/6 pre-checkpoint bundle gates PASS; FORBIDDEN_HOOK_STRINGS = 12.

Debug session: .planning/debug/04-06-dark-mode-mark-decouple.md

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-26 12:54:54 +02:00
parent d66cbf6900
commit a8bcc17822
7 changed files with 310 additions and 82 deletions

View File

@@ -13,14 +13,17 @@
// It does NOT instantiate any document, does NOT call populateMark, does
// NOT invoke DOMParser at runtime. The runtime behavior (live <svg>
// injection into the welcome page DOM and the currentColor CSS cascade
// through `.welcome-hero__mark { color: var(--mks-fg-inverse); }`) is
// verified by the host-side UAT harness assertion A35 (driveA35 in
// tests/uat/lib/harness-page-driver.ts) — A35 opens welcome.html as a real
// Puppeteer tab so populateMark() actually runs, then reads
// `getComputedStyle().stroke` on the injected <svg> to prove the cascade
// resolves. This split mirrors the project's two-layer test approach
// (source contract under vitest + live-DOM behavior under the Puppeteer
// harness) — verified at re-plan iter-2 (BLOCKER 1 resolution).
// through `.welcome-hero__mark { color: var(--mks-mark-stroke); }` — the
// theme-INDEPENDENT brand-component token introduced by Plan 04-06 Task 4
// operator-empirical debug-decouple) is verified by the host-side UAT
// harness assertion A35 (driveA35 in tests/uat/lib/harness-page-driver.ts)
// — A35 opens welcome.html as a real Puppeteer tab so populateMark()
// actually runs, then reads `getComputedStyle().stroke` on the injected
// <svg> in BOTH light and dark themes to prove (a) the cascade resolves
// and (b) the resolved stroke is identical across themes (linen-50). This
// split mirrors the project's two-layer test approach (source contract
// under vitest + live-DOM behavior under the Puppeteer harness) — verified
// at re-plan iter-2 (BLOCKER 1 resolution) + Plan 04-06 Task 4 decouple.
//
// References:
// - .planning/phases/04-harden-clean-up-optional/04-UI-SPEC.md