# Stats Dashboard Feedback Pass — Design Date: 2026-04-09 Scope: Stats dashboard UX follow-ups from user feedback (items 1–7). Delivery: **Single PR**, broken into logically scoped commits. ## Goals Address seven concrete pieces of feedback against the Statistics menu: 1. Library — collapse episodes behind a per-series dropdown. 2. Sessions — roll up multiple sessions of the same episode within a day. 3. Trends — add a 365d range option. 4. Library — delete an episode (video) from its detail view. 5. Vocabulary — tighten spacing between word and reading in the Top 50 table. 6. Episode detail — hide cards whose Anki notes have been deleted. 7. Trend/watch charts — add gridlines, fix tick legibility, unify theming. Out of scope for this pass: English-token ingestion cleanup and Overview stat-card drill-downs (feedback items 8 and 9). Those require a larger design decision and a migration respectively. ## Files touched (inventory) Dashboard (`stats/src/`): - `components/library/LibraryTab.tsx` — collapsible groups (item 1). - `components/library/MediaDetailView.tsx`, `components/library/MediaHeader.tsx` — delete-episode action (item 4). - `components/sessions/SessionsTab.tsx`, `components/library/MediaSessionList.tsx` — episode rollup (item 2). - `components/trends/DateRangeSelector.tsx`, `hooks/useTrends.ts`, `lib/api-client.ts`, `lib/api-client.test.ts` — 365d (item 3). - `components/vocabulary/FrequencyRankTable.tsx` — word/reading column collapse (item 5). - `components/anime/EpisodeDetail.tsx` — filter deleted Anki cards (item 6). - `components/trends/TrendChart.tsx`, `components/trends/StackedTrendChart.tsx`, `components/overview/WatchTimeChart.tsx`, `lib/chart-theme.ts` — chart clarity (item 7). - New file: `stats/src/lib/session-grouping.ts` + `session-grouping.test.ts`. Backend (`src/core/services/`): - `immersion-tracker/query-trends.ts` — extend `TrendRange` and `TREND_DAY_LIMITS` (item 3). - `immersion-tracker/__tests__/query.test.ts` — 365d coverage (item 3). - `stats-server.ts` — passthrough if range validation lives here (check before editing). - `__tests__/stats-server.test.ts` — 365d coverage (item 3). ## Commit plan One PR, one feature per commit. Order picks low-risk mechanical changes first so failures in later commits don't block merging of earlier ones. 1. `feat(stats): add 365d range to trends dashboard` (item 3) 2. `fix(stats): tighten word/reading column in Top 50 table` (item 5) 3. `fix(stats): hide cards deleted from Anki in episode detail` (item 6) 4. `feat(stats): delete episode from library detail view` (item 4) 5. `feat(stats): collapsible series groups in library` (item 1) 6. `feat(stats): roll up same-episode sessions within a day` (item 2) 7. `feat(stats): gridlines and unified theme for trend charts` (item 7) Each commit must pass `bun run typecheck`, `bun run test:fast`, and any change-specific checks listed below. --- ## Item 1 — Library collapsible series groups ### Current behavior `LibraryTab.tsx` groups media via `groupMediaLibraryItems` and always renders the full grid of `MediaCard`s beneath each group header. ### Target behavior Each group header becomes clickable. Groups with `items.length > 1` default to **collapsed**; single-video groups stay expanded (collapsing them would be visual noise). ### Implementation - State: `const [collapsedGroups, setCollapsedGroups] = useState>(...)`. Initialize from `grouped` where `items.length > 1`. - Toggle helper: `toggleGroup(key: string)` adds/removes from the set. - Group header: wrap in a `