The UI read flat and boring. Reskin to one charm/TUI-inspired layout in two palettes (CSS custom properties): a warm "reader" light theme (sketch B) and a "cozy terminal" dark theme (sketch C). - Palette chosen in cascade order: :root light default; an OS-preference dark block scoped to :root:not([data-theme]) so it applies only absent an explicit choice; and :root[data-theme="dark"|"light"] set by a header toggle that outranks the media query by specificity and persists in localStorage (guarded, degrades to OS default). A <head> init script applies the stored choice before paint, so no flash of the wrong palette. - Charm touches via existing classes (no templ structure churn): monospace meta lines, accent uppercase section dividers with a trailing rule, pill buttons, a lifted/accent-edged expanded card. - Error/danger shades become --err-* tokens so they follow the theme, replacing three per-block prefers-color-scheme dark overrides. - Theme toggle wired into Layout and PublicLayout headers. BDD: docs/use-cases/visual_theme.feature un-pended, mapped in scenarioCoverage. TDD: internal/web/visual_theme_test.go (palettes, OS default, persisted toggle, expanded-card embed). Verified light+dark on list/reader/welcome via web-shot. Sketches kept as the design record. ui-spec.md as-built row added. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
30 lines
1.4 KiB
Gherkin
30 lines
1.4 KiB
Gherkin
Feature: Visual refresh — one charm-reader layout, light + dark themes (ADR-032, #17)
|
|
As a reader who likes a TUI/charm aesthetic
|
|
I want a fresh look with a light and a dark theme
|
|
So that the app feels distinctive and reads well in either mode
|
|
|
|
# Direction B (light) + C (dark) are one layout in two palettes (CSS variables),
|
|
# plus a persisted toggle and an OS-preference default. Colours are reviewed via
|
|
# the mockups in docs/sketches/, not unit-tested; these scenarios cover the
|
|
# testable structure. Each maps to a Go test in scenario_coverage_test.go.
|
|
|
|
Scenario: Light and dark themes share one layout via CSS variables
|
|
Given the app stylesheet
|
|
When it is rendered
|
|
Then it defines a light palette on the root and a dark palette under data-theme="dark", with no duplicate markup
|
|
|
|
Scenario: Without a stored choice the theme follows the OS preference
|
|
Given a visitor with no saved theme
|
|
When the page loads
|
|
Then a prefers-color-scheme dark block applies the dark palette automatically
|
|
|
|
Scenario: A persisted toggle switches light and dark
|
|
Given any page
|
|
When it is rendered
|
|
Then it includes a theme-toggle control and a small script that flips data-theme and persists the choice
|
|
|
|
Scenario: The expanded card embeds the video player
|
|
Given a summarized video with a valid provider id
|
|
When its card is expanded
|
|
Then the expanded card includes the embedded video player
|