Files
brain-of-reese/.agent/user_stories/dark-tech-theme.md
T
ducoterra 4971e2859d
Build and Push Containers / build-and-push-app (push) Successful in 12s
Build and Push Containers / build-and-push-db (push) Successful in 10s
chore(agent): track .agent/ planning tree in git
Remove the blanket .agent/ gitignore so the phase roadmap, user
stories, reports, and PLAN.md are versioned with the code. Only
runtime artifacts (.agent/phase-sessions/, .agent/pipeline.log)
remain ignored. Update AGENTS.md git protocol rule to match.
2026-09-01 10:18:22 -04:00

82 lines
4.2 KiB
Markdown

# Story: Dark Tech Theme
**Phase:** `08_story_dark_tech_theme.md` · **E2E:** `tests/e2e/test_dark_tech_theme.py`
## Narrative
As **a user**, I want Brain of Reese to look like a serious piece of my
infrastructure — dark, technical, free of emojis, with a subtly animated
background — so the app feels at home next to my dashboards and is
comfortable to use at night, instead of a generic light-mode chat widget.
- **Given** the v1 UI (light palette, emoji avatars/brand/favicon, static background)
- **When** the theme phase is complete
- **Then** every page is dark with a tech aesthetic, no emoji appear anywhere
in the UI chrome, a subtle pure-CSS animated background (drifting grid +
breathing glows) is visible but never distracting, all layout metrics and
behavior are unchanged, and WCAG 2.1 AA still holds on the new palette.
## Acceptance criteria
1. Dark palette (tokens in the phase file) applied to **both** pages
(`/`, `/sources.html`); every text/background pair ≥4.5:1 — computed,
not eyeballed.
2. **Zero emoji in UI chrome** — HTML templates, JS-rendered chrome,
favicon, CSS — replaced by inline SVG glyphs. An integration test
enforces this as a permanent regression guard.
3. Subtly animated background: a fine drifting grid + two slow breathing
radial glows, **pure CSS, zero JS**, `pointer-events: none`, never
blocking or dimming content.
4. `prefers-reduced-motion: reduce` → background animations disabled
(static grid + glows remain).
5. No-CDN invariant holds on both pages (all script/link refs local or
`data:`).
6. Layout metrics unchanged (PLAN §7.1): 72rem frame, 46rem centered chat
column, full-width Sources table, mobile rules; behavior unchanged
(chat state machine, chips, banners).
7. WCAG 2.1 AA: landmarks, labels, skip link, `:focus-visible`, live
regions intact on the new palette.
8. LLM answer content is out of scope (the model may output anything; the
rule binds UI chrome only).
9. Whole pytest suite green, `app/` coverage >90%, story E2E green in
isolation.
## UI Visualization & Structure
- **Palette (all pairs computed, ≥4.5:1):** page `#0a0e17`, surface
`#121a2e`, ink `#e8ebf4` (14.5:1 on surface), ink-soft `#9aa4bd`
(6.9:1), line `#26304a`, brand `#6d78f2` with **dark** text `#0a0e17`
(5.2:1 — white on brand is 3.7:1, forbidden for text), brand-soft
`#232b52` + brand-ink `#a5b4fc` (6.9:1), deflection `#2b2110`/`#fbbf24`
(9.5:1) + border `#f59e0b`, error `#2d1318`/`#fca5a5` (9.1:1), ok
`#10241b`/`#6ee7a8` (10.6:1).
- **Busy button** keeps its `#a5b4fc` background (the existing unit test
asserts the token) with a **dark** arc (`#0a0e17`, 9.7:1).
- **Avatars:** brain → inline SVG circuit-node glyph; user → minimal
silhouette SVG; `aria-hidden` retained.
- **Favicon / brand mark:** tech SVG mark (hex + node), still an inline
`data:` URI (no CDN).
- **Tech details:** mono wordmark + stat values, 1px `--line` borders,
radii 10px/6px, a 2px brand→cyan gradient hairline under the sticky
header.
- **Background:** `body::before` grid (44px cells, ~35% alpha 1px lines,
radial mask fade, 60s seamless diagonal drift); `body::after` two radial
glows (indigo ~14% top-left, cyan ~10% bottom-right, 14s breathing).
Both `position: fixed; inset: 0; pointer-events: none`.
## Playwright Mapping Rule
**Test Scenario → `tests/e2e/test_dark_tech_theme.py`** (mock LLM, seeded KB):
1. `test_dark_palette_and_contrast` — body background is
`rgb(10, 14, 23)`; computed ink-on-surface and brand-button
text/background pairs ≥4.5:1 (same contrast helper as Phase 07).
2. `test_no_emoji_in_chrome` — neither page's `document.body.innerText`
nor raw `outerHTML` contains any emoji code point.
3. `test_animated_background` — computed style of `body::before` has a
non-none `background-image` and `animation-name`; `body::after`
animates too.
4. `test_reduced_motion_honored` — a browser context created with
`reduced_motion="reduce"` → `animation-name: none` on both layers.
5. `test_behavior_unchanged_smoke` — on-topic question streams an answer +
a source chip + the send button recovers (state machine intact under
the new skin).
6. `test_all_assets_local` — every `script[src]` / `link[href]` on both
pages is relative or `data:` (no CDN).