# Story: Mobile hamburger nav **Phase:** `46_mobile_hamburger_nav` · **Source:** `TODO.md` L9 · **E2E:** `tests/e2e/test_mobile_hamburger_nav.py` ## Bug report (verbatim, `TODO.md` L9) > "The navbar on mobile is way too squished. Make it a hamburger > dropdown menu with a nice animation" ## Narrative As **a mobile user**, the 58px header currently crams up to four text nav pills (Chat / Sources / Git sources / Tuning) next to the brand and four icon action pills — the phase-34/35 squeeze at 360–375px leaves 0.72rem-font pills that are hard to hit and hard to read. The nav links move into a **hamburger dropdown menu** on small screens: one `#nav-toggle` button in the bar, and the links open as an animated panel below the header with comfortable touch targets. - **Given** a viewport ≤640px - **When** I tap the hamburger - **Then** the nav menu drops down with a short slide+fade animation and full-size links; tapping a link navigates and closes the menu. - **Given** a viewport >640px - **When** the page loads - **Then** nothing changes — the inline nav pills render exactly as today. ## Acceptance criteria 1. **Mobile (≤640px):** the inline nav pills are hidden from the bar; a hamburger button (`#nav-toggle`, `aria-label="Menu"`, `aria-controls="app-nav"`, `aria-expanded`) appears — 44px touch target, icon-only. 2. **Menu:** `.app-nav` (now `id="app-nav"`) becomes a dropdown panel below the header — vertical full-width rows, ≥44px targets, readable font size; the **auth visibility contract is preserved inside the menu** (anonymous: only "Chat"; admin: Chat / Sources / Git sources / Tuning — the same ship-hidden `hidden` attributes the whoami gate already drives). 3. **Animation:** opening/closing animates (slide-down + fade, ≈180ms); `prefers-reduced-motion: reduce` stills it (no transition). 4. **Behavior:** toggle flips `aria-expanded`; `Esc` closes while open; a link click navigates **and** closes the menu; resizing back to >640px closes it (the inline nav reappears, no stale state). 5. **Bar layout:** the action pills (Tuning toggle, Sync, New chat, Sign in/out) stay in the bar icon-only — the phase-35 tightest squeeze rules on `.nav-link` / `.app-nav` gaps are replaced by the roomier menu; the bar fits 360px with the brand intact or clipped as today. 6. **All six pages** get the identical toggle + menu (the phase-34 "same bar on every page" contract). ## Owner-confirmed (2026-08-27, roadmap A5) 1. **The hamburger contains the nav links only** (Chat / Sources / Git sources / Tuning). The action pills stay in the bar. 2. **Animation:** slide-down + fade, 180ms; `prefers-reduced-motion` stills it. 3. **Breakpoint:** the existing ≤640px mobile block (no new breakpoint). ## UI Visualization & Structure - **Markup (all six pages — `index.html`, `sources.html`, `document.html`, `git-sources.html`, `login.html`, `tuning.html`):** a `#nav-toggle` button inserted before `