From f52de0bdbbb12ab085e328b42a5f29f923a92aa7 Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 9 May 2026 12:10:18 -0400 Subject: [PATCH] =?UTF-8?q?fix(02-06,G1):=20add=20src/index.css=20and=20im?= =?UTF-8?q?port=20from=20main.tsx=20=E2=80=94=20close=20white-halo=20gap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds src/index.css with body bg #1a1a1a + serif color #e8e0d0 + zero margin + 100vh min-height + #game-container flex centering, imported once from src/main.tsx so Vite bundles it into the entry chunk. Closes G1 first-impression UX gap from 2026-05-09 live UAT — the dark canvas no longer floats in a sea of white. Phase 3 (Watercolor & Cello) layers a painted treatment over this base without changing the structural intent. No new npm dependencies, no painted assets. Vitest smoke: 6/6 cases green via file-read assertion (jsdom does not bundle CSS imports; the Playwright e2e in Task 5 proves end-to-end that the bundled CSS actually applies in a real browser). Co-Authored-By: Claude Opus 4.7 (1M context) --- src/index.css | 26 ++++++++++++++++++++++++++ src/index.css.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ src/main.tsx | 1 + 3 files changed, 67 insertions(+) create mode 100644 src/index.css create mode 100644 src/index.css.test.ts diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..cf391e9 --- /dev/null +++ b/src/index.css @@ -0,0 +1,26 @@ +/* Global page styles. Phase-2 minimum-viable tonal coherence — body bg + * matches the Phaser canvas backgroundColor (#1a1a1a) and the BeginScreen + * overlay so there is no white halo around the dark canvas at any moment. + * + * Phase 3 (Watercolor & Cello) layers a painted treatment on top of this + * base; this file establishes the foundation that the painted treatment + * layers over. + * + * Per CLAUDE.md tone constraint and anti-FOMO doctrine — calm, contemplative, + * no animation, no urgency. + */ + +html, body { + margin: 0; + padding: 0; + min-height: 100vh; + background: #1a1a1a; + color: #e8e0d0; + font-family: serif; +} + +#game-container { + display: flex; + justify-content: center; + align-items: center; +} diff --git a/src/index.css.test.ts b/src/index.css.test.ts new file mode 100644 index 0000000..405160c --- /dev/null +++ b/src/index.css.test.ts @@ -0,0 +1,40 @@ +import { describe, it, expect } from 'vitest'; +import { readFileSync } from 'node:fs'; +import { join } from 'node:path'; + +/** + * G1 (gap closure 02-06) — assert src/index.css contains the load-bearing + * tonal-coherence rules. We test by file-read because Vitest jsdom does + * not bundle CSS imports; the e2e (tests/e2e/season1-loop.spec.ts) is the + * end-to-end proof that the bundled CSS actually applies in a real browser. + */ +describe('src/index.css (Plan 02-06 G1 closure)', () => { + const cssPath = join(__dirname, 'index.css'); + const css = readFileSync(cssPath, 'utf8'); + + it('sets body background to #1a1a1a (matches Phaser canvas)', () => { + expect(css).toMatch(/background:\s*#1a1a1a/); + }); + + it('sets body color to #e8e0d0 (matches BeginScreen palette)', () => { + expect(css).toMatch(/color:\s*#e8e0d0/); + }); + + it('zeroes body margin (kills browser default white halo)', () => { + expect(css).toMatch(/margin:\s*0/); + }); + + it('sets body min-height to 100vh (dark bg fills viewport)', () => { + expect(css).toMatch(/min-height:\s*100vh/); + }); + + it('uses serif font-family (matches BeginScreen)', () => { + expect(css).toMatch(/font-family:\s*serif/); + }); + + it('main.tsx imports the CSS', () => { + const mainPath = join(__dirname, 'main.tsx'); + const main = readFileSync(mainPath, 'utf8'); + expect(main).toMatch(/import\s+['"]\.\/index\.css['"]/); + }); +}); diff --git a/src/main.tsx b/src/main.tsx index b04c04e..db7ea87 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,6 +1,7 @@ import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import App from './App.tsx'; +import './index.css'; // Plan 02-06 G1 — global page styles (body bg, font, margin) const rootEl = document.getElementById('root'); if (!rootEl) {