Files
brain-of-reese/.agent/phases/todo/08_story_dark_tech_theme.md
T

6.7 KiB
Raw Blame History

Phase 08 — Story: Dark Tech Theme

Story: .agent/user_stories/dark-tech-theme.md Context: .agent/PLAN.md §7 (UI/UX strategy), §10 (testing)

Goal

Re-skin the whole UI to a dark, techy, emoji-free look with a subtly animated pure-CSS background — zero behavior or layout changes, WCAG 2.1 AA re-proven on the new palette.

Dependencies

Phases 01–07 (all complete). Independent of 09/10; phase 10's viewer page inherits this theme, so 08 must land first.

Locked decisions

No anchors changed. Replaces the §7.2 light contrast pairs with the dark palette below (PLAN §7.2 already updated 2026-08-21 with owner permission). No new technology — pure CSS/HTML/inline SVG (A11).

Implementation steps

  1. Palette swap — frontend/assets/styles.css :root tokens (all pairs computed, ≥4.5:1):

    token dark value computed pair
    --bg #0a0e17 ink on bg 16.2:1
    --surface #121a2e ink on surface 14.5:1
    --ink #e8ebf4 —
    --ink-soft #9aa4bd ink-soft on surface 6.9:1
    --line #26304a decorative
    --brand #6d78f2 dark ink --bg on brand 5.2:1
    --brand-soft #232b52 brand-ink on brand-soft 6.9:1
    --brand-ink #a5b4fc brand-ink on surface 8.7:1
    --accent-bg #2b2110 accent-ink on accent-bg 9.5:1
    --accent-ink #fbbf24 —
    --accent-line #f59e0b unchanged (8.9:1 on bg)
    --err-bg / --err-ink #2d1318 / #fca5a5 9.1:1
    --err-line #ef4444 4.6:1 on err-bg (UI boundary)
    --ok-bg / --ok-ink #10241b / #6ee7a8 10.6:1

    Button text is --bg (dark) on --brand — never white on brand (3.7:1, fails). Busy button: keep the #a5b4fc background (the tests/unit/test_frontend_feedback.py assertion greps this token) with a dark arc (--bg, 9.7:1). Update derived light-mode values: shadows (black-based, lower alpha), selection, typing dots, chip hover.

  2. Emoji purge — replace every emoji in chrome with inline SVG (aria-hidden kept, ~16–20px, currentColor where sensible):

    • frontend/assets/app.js (~L116, ~L132): avatars 🧠/🧑 → SVG circuit-node glyph (brain) / minimal silhouette (user) as JS string constants.
    • frontend/index.html: favicon 🧠 data-URI → SVG tech mark (hex + node, brand color on dark, <1 KB), still a data: URI; .brand-mark 🧠 → same mark; ⚠️ banner icon → SVG triangle; 👋 empty state → SVG glyph.
    • frontend/sources.html: favicon, .brand-mark, 📂 empty state → SVG marks.
  3. Tech details — mono wordmark with letter-spacing; stat values mono; radii 10px/6px; 1px --line borders on cards/bubbles/table; 2px gradient hairline (brand→cyan, low alpha) under the sticky header.

  4. Animated background (pure CSS, zero JS) — working recipe: html { background: var(--bg) }, body { background: transparent; position: relative } (body must not create a stacking context):

    • body::before — fine grid: two linear-gradients (1px lines, --line at ~35% alpha), background-size: 44px 44px, masked with a radial fade (visible center-top, fading to the edges), animated background-position 0 0 → 44px 44px, 60s linear infinite (seamless loop — the delta equals one cell).
    • body::after — two large soft radial glows: indigo rgba(109,120,242,0.14) top-left, cyan rgba(34,211,238,0.10) bottom-right; 14s ease-in-out infinite alternate breathing (opacity/scale). No filter: blur (perf).
    • Both: position: fixed; inset: 0; pointer-events: none; z-index: -1. Keep glow alpha low — subtle, never competing with text.
  5. Reduced motion — @media (prefers-reduced-motion: reduce): body::before, body::after { animation: none } (static grid + glows remain). Existing typing/spinner reduced-motion handling stays.

  6. Test updates (behavior unchanged):

    • tests/e2e/test_honest_deflection.py (~L104): deflection bubble backgroundColor assertion rgb(255, 247, 232) → rgb(43, 33, 16); the border assertion rgb(245, 158, 11) is unchanged.
    • New integration test tests/integration/test_api.py::test_ui_chrome_has_no_emoji: GET /, /sources.html, /assets/app.js, /assets/styles.css — assert no characters in the emoji code-point set (U+1F300–U+1FAFF, U+2600–U+27BF, U+2B00–U+2BFF, U+FE0F, U+200D, plus the specific glyphs previously used: 🧠 🧑 👋 📂 ⚠️).
  7. PLAN.md §7.2 — dark contrast table already applied (2026-08-21, owner permission); no further plan edits in this phase.

UI Verification

Manual screenshot pass (1280px + 375px, both pages): grid is faint (barely-there), glows soft, no banding; brand button legible (dark text); deflection bubble distinct from normal answers; avatars crisp at 16px; reduced-motion preview (DevTools emulation) shows the static background.

Testing & Quality

  • Integration: no-CDN check still green on both pages (it covers /sources.html since Phase 07); new emoji-guard test above.
  • Existing E2E regression check: after the reskin, run the existing story suites in isolation and confirm they stay green — at minimum test_chat_rag.py, test_honest_deflection.py, test_responsive_ polish.py (the contrast helper computes from live styles and must pass on the new palette).
  • Coverage: uv run pytest --cov=app --cov-report=term-missing — >90% on app/.
  • uv run ruff check . && uv run pyright green.

Playwright Execution Phase

Run ONLY this story's suite:

uv run pytest tests/e2e/test_dark_tech_theme.py -v --no-cov

Implements the story mapping: dark bg + computed contrast pairs ≥4.5:1; no emoji in innerText/outerHTML on both pages; body::before/::after animate; reduced-motion context → animation-name: none; on-topic smoke (stream + chip + button recovery) unchanged; all assets local.

Success criteria

  • both pages dark; every text pair ≥4.5:1 (computed in E2E)
  • zero emoji in chrome (E2E + new integration guard)
  • animated background subtle, pure CSS, reduced-motion honored
  • layout metrics + chat behavior unchanged (smoke E2E)
  • existing story E2E suites still green in isolation
  • unit + integration green, coverage >90%, ruff + pyright green
  • committed (force-add .agent/PLAN.md + this phase record — rule 8)

Commit

git add -A
git add -f .agent/PLAN.md .agent/phases/todo/08_story_dark_tech_theme.md
git commit --no-gpg-sign -m "feat(ui): dark tech theme — emoji-free chrome, subtle animated CSS background, WCAG AA dark palette"