Standardize on the .agents/ directory (shared with project skills): phases/, user_stories/, reports/, screenshots/, validate.sh, and phase-sessions/ + pipeline.log all move to .agents/ (git mv preserves history; runtime artifacts move alongside). Updates every reference in AGENTS.md, README.md, .gitignore, app docstrings, and test story headers. Historical KB content in data/ and the runtime pipeline.log transcript are left untouched.
82 lines
4.2 KiB
Markdown
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).
|