# Story: Responsive, Polished, Accessible UI **Phase:** `07_story_responsive_polish.md` · **E2E:** `tests/e2e/test_responsive_polish.py` ## Narrative As **a user on any device** — phone at the coffee shop, laptop at the desk — I want the chat to be comfortable to read and drive: no pinched layout, no tiny tap targets, no contrast failures, no wasted whitespace — so asking Brain feels effortless everywhere. - **Given** any viewport from 360px to 1600px+ - **When** I use the chat and the Sources page - **Then** the layout follows the PLAN §7 standards (containers, chat column, full-width table), all interactive elements are reachable by keyboard, and every color pair meets WCAG 2.1 AA. ## Acceptance criteria 1. **Layout:** container 72rem centered with side padding; chat column capped at 46rem centered; Sources table uses full container width with horizontal scroll below 640px (never a squeezed single hairline column). 2. **Mobile (375px):** header condenses, composer reachable above the home indicator (`safe-area-inset-bottom`), chips scroll horizontally, bubbles ≤92% width, no horizontal page overflow (document `scrollWidth == clientWidth`). 3. **A11y sweep:** landmarks present on both pages (`header/nav/main/ footer`); skip link works (focus `#main`); all inputs have labels (visible or programmatically associated); all icon-only buttons have `aria-label`; `:focus-visible` outline on every control (Tab through). 4. **Contrast:** automated check of the key pairs (ink/surface, ink-soft/surface, white/brand, chip-ink/chip-bg, deflection pairs) ≥4.5:1 (test computes from computed styles; PLAN §7.2 table is the baseline). 5. **No-CDN re-verification** on both pages (no `http(s)://` src/href except same-origin `/…`). 6. **Reduced motion:** with `prefers-reduced-motion`, typing dots and spinner do not animate (computed `animation: none` or duration ≥2s). 7. Long words/paths (e.g. a 60-char file path) wrap or ellipsize without breaking the bubble (overflow-wrap anywhere). ## UI Visualization & Structure - This phase is the **visual audit + fix pass**: it does not add features, it enforces PLAN §7 end-to-end on chat + sources. - Desktop 1440px screenshot pass: header 64px, chat centered with balanced margins, sources table edge-to-edge within the container. - Tablet 768px: chat column uses most of the width (≤46rem cap), no mid-column dead zones; stat cards 3-across. - Phone 375px: one-column flow, 44px+ targets, thumb-zone composer. - Any deviation found → fix in `frontend/assets/styles.css` (tokens first), re-verify with the E2E below. ## Playwright Mapping Rule **Test Scenario → `tests/e2e/test_responsive_polish.py`**: 1. `test_no_horizontal_overflow_at_viewports` — for 360/375/768/1280/1600: `document.documentElement.scrollWidth <= clientWidth` on both pages. 2. `test_chat_column_capped_and_centered` — at 1600px, `.chat-shell` width ≤ 46rem (736px) + 2% and horizontally centered (±2%). 3. `test_sources_table_full_width` — at 1280px, `.table-wrap` width ≥ 80% of `.container` width. 4. `test_a11y_landmarks_and_labels` — both pages: landmarks present, skip link target `#main` focusable, `#message-input` has an associated label, no ``/icon buttons without accessible name. 5. `test_contrast_pairs_pass_aa` — computed-color contrast assertions for the PLAN §7.2 pairs (helper computes WCAG relative luminance). 6. `test_reduced_motion_respected` — emulate `reducedMotion: 'reduce'`; typing dots have no running animation (or ≥2s duration).