# Step 4 handoff — table-of-contents sidebar Branch `v2-toc`, worktree `/home/thallada/workspace/the-daily-epub-v2d`, one commit. Builds on step 2's design system (`handoff-step2.md`) and step 1's legacy fallback (`handoff-step1.md`). Also folds in one reader-side fix from the step-2 review: the phone "ears" row. ## Landed ### Data (`src/web/issue.rs`) - `issue_toc(&IssueView, TocPosition) -> Toc`, one helper feeding all four signed-in handlers (`render_full`, `article`, `world`, `behind`) as the template field `toc`. - `TocPosition` (`FrontPage`, `Article(ArticleId)`, `World`, `Behind`) and `TocKind` (`Brief`, `Section`, `Chapter`, `World`, `Behind`, `Colophon`) as the brief specifies. - Chapters are the picks in `chapters::section_names` × `Lineup::section_picks` order — the same order the issue index and the EPUB use — numbered `1..n` across sections with the section names interleaved as non-links. World Briefing and Behind the paper follow when available (`world_briefing.is_some() || world_html.is_some()`, and `has_behind`, both as computed after step 1), then a `#colophon` anchor on the issue page. - `position` / `total` count navigable chapters only (articles + world + behind), so an article page says "Chapter 4 of 11"; the issue page has `position == 0` and reads "Front page". - New small helpers: `issue_href(date)` (replaces four inline `format!`s) and `crate::pipeline::short_display_date(date)` → `"Wed, Sep 2"`. ### Markup (`src/web/templates/_toc.html`, included by the four reader templates) - One `