feat(04-06): Wave 1 GREEN — dark-logo currentColor strategy + inline-SVG injection

UI-SPEC Option A landed end-to-end at the source layer:

- src/shared/brand/mokosh-mark.svg: single-attribute change on the root
  <svg> — stroke="#181b2a" → stroke="currentColor". The 12 <line> + 1
  <rect> children inherit stroke from the root and are UNCHANGED. This
  switches the mark from a hardcoded near-black ink to inheriting the
  parent CSS `color` cascade (W3C SVG2 §13.3).
- src/welcome/welcome.ts: `import markUrl from '..mokosh-mark.svg?url'`
  → `import markSvg from '..mokosh-mark.svg?raw'`. populateMark()
  rewritten to inline-inject the SVG via DOMParser + replaceChildren
  (NOT <img>, NEVER innerHTML — MV3 CSP discipline / T-04-06-01).
  The inline <svg> inherits `color: var(--mks-fg-inverse)` from the
  `.welcome-hero__mark` wrapper (welcome.css:67); on the dark surface
  the `.dark` token override (tokens.css 234-251) flips the resolved
  colour automatically — contrast-correct on both surfaces, no JS
  branching. The bare class selector `.welcome-hero__mark-img`
  (welcome.css:91-95) is tag-agnostic so width/height/display rules
  apply identically to the injected <svg>. role='img' + aria-label
  preserve the prior accessibility shape.
- globals.d.ts: append the `declare module '*.svg?raw'` ambient block
  alongside the existing `*.svg?url` + `*.webm?url` blocks so tsc
  accepts the new import.

Gates run:
- npx tsc --noEmit exit 0.
- npm test against tests/welcome/inline-svg.test.ts + tests/build/
  cursor-visibility.test.ts: 4/4 GREEN (the 3 Wave-0 RED inline-svg
  tests flipped to GREEN; cursor-visibility stays GREEN).
- Full vitest: 187 passed / 1 failed (188 total). The single RED is
  tests/background/webm-remux.test.ts > ffprobe -count_frames timeout
  — the documented 04-CONTEXT #9/#10 parallel-vitest / ffprobe flake
  family. Re-run in isolation: 5/5 GREEN. TOLERATED per the Task 2
  VITEST GATE LOGIC (isolation-passing flake is NOT a regression).
- npm run build exit 0; the welcome chunk JS bundles the raw SVG
  source (currentColor + viewBox="0 0 32 32" both present in
  dist/assets/welcome-Bkrf1_bZ.js).

References:
- 04-UI-SPEC.md §"Implementation amendment" (the 2-part technique).
- Vite ?raw query: https://vite.dev/guide/assets.html#importing-asset-as-string
- W3C SVG2 §13.3 (currentColor inheritance).
- DOMParser is CSP-safe per MDN (no script execution).
This commit is contained in:
2026-05-26 07:58:06 +02:00
parent f0b88d4d17
commit c4161431e7
3 changed files with 96 additions and 37 deletions

21
globals.d.ts vendored
View File

@@ -36,6 +36,27 @@ declare module '*.svg?url' {
export default url;
}
// Plan 04-06 — Vite `?raw` import for SVG-as-string. The `?raw` query
// suffix instructs Vite to bundle the resolved module's CONTENTS verbatim
// as a UTF-8 string at build time (not a hashed asset URL). Used by
// src/welcome/welcome.ts populateMark to inline-inject the canonical
// mokosh-mark.svg via DOMParser + replaceChildren — required by the
// UI-SPEC dark-logo `currentColor` strategy (Option A), because
// `currentColor` only inherits the parent CSS `color` cascade when the
// <svg> lives in the host document's DOM (an <img>-rendered SVG runs in
// an isolated SVG document context where the parent cascade does not
// reach it; W3C SVG2 §13.3). Mirrors the existing `*.svg?url` ambient
// decl above; both forms can coexist for different consumers.
//
// References:
// - https://vite.dev/guide/assets.html#importing-asset-as-string
// - .planning/phases/04-harden-clean-up-optional/04-UI-SPEC.md
// §"Implementation amendment"
declare module '*.svg?raw' {
const raw: string;
export default raw;
}
// Plan 04-08 — Vite `?url` import for bundled test-only WebM fixture
// (tests/uat/fixtures/synthetic-display-source.webm). Mirrors the
// Plan 01-10 mokosh-mark.svg precedent; only gated test builds resolve