feat(web): sleek Stage-0 reader — design system, card list, reader detail

Implements the Top 5 fixes from the Stage-0 UX review (docs/ux-review/UX-REVIEW.md):

1. Dark mode: full light+dark custom-property palette (bg/fg/muted/line/accent/
   card) under :root + @media (prefers-color-scheme: dark), applied to body.
   color-scheme: light dark is now actually honoured — summary text was invisible
   on a dark canvas before.
2. Table -> responsive card list: one card per summary (title link, channel·date
   meta, provider chip, fallback badge, action state). Single-column reflow at
   375px, no horizontal crush.
3. Minimal design system: 4/8px spacing scale, one accent, styled accent links
   (underline-on-hover), real buttons with active/pressed state, consistent
   radius and dividers — applied across list + detail.
4. Detail page as a reader: prose capped at 38rem, title->meta->summary->
   highlights->takeaways hierarchy with section rules, 1.7 line-height. Meta is
   built from non-empty parts (detailMeta) so the no-video edge case no longer
   renders a stray "· — ·".
5. Contrast + a11y: muted bumped to #595959 (~7:1, clears WCAG AA), fallback
   badge gets vertical padding + aria-label/title, friendly first-run empty
   state, hx-indicator on the filter form.

Tests updated for the card markup (table -> cards); missing date is now omitted
rather than em-dashed. task check green; HTMX action toggles verified working.
This commit is contained in:
2026-06-03 00:20:22 +02:00
parent fa9f101abe
commit d9b7107ccb
5 changed files with 339 additions and 286 deletions
+3 -3
View File
@@ -149,7 +149,7 @@ func TestListRendersRowsAndActionState(t *testing.T) {
require.Contains(t, html, "youtube")
require.Contains(t, html, "watched", "current action state shown in the list")
require.Contains(t, html, "2026-01-01")
require.Contains(t, html, "—", "missing published date renders an em dash")
require.Contains(t, html, `class="card"`, "rows render as cards, not a table")
}
func TestListHTMXReturnsFragment(t *testing.T) {
@@ -164,8 +164,8 @@ func TestListHTMXReturnsFragment(t *testing.T) {
require.Equal(t, http.StatusOK, rec.Code)
html := body(t, rec)
require.Contains(t, html, "<table")
require.NotContains(t, html, "<html", "HTMX request gets only the table fragment")
require.Contains(t, html, `class="cards"`)
require.NotContains(t, html, "<html", "HTMX request gets only the list fragment")
}
func TestListChannelFilter(t *testing.T) {