# M016: UX Polish, Brand & Reading Experience

> **Stream:** Frontend — intended for a dedicated GSD milestone instance
> **Conflict zone:** `frontend/src/` only — no backend Python changes
> **Deploy cadence:** commit-build-redeploy after each slice completion

---

## Goal

Modernize the public site's visual identity and reading experience, fix pipeline admin UI bugs, and establish a brand baseline (logo, favicon, OG tags). Every change in this milestone lives entirely in the frontend — CSS, React components, and static assets.

---

## Slice Breakdown

### S01: Landing Page Visual Fixes (Quick Wins)
**Risk:** Low | **Effort:** Small | **Files:** `App.css`, `Home.tsx`

Research found 5 concrete bugs/inconsistencies on the homepage:

| # | Issue | Fix |
|---|-------|-----|
| 1 | Duplicate `.btn` rule at App.css:3185 overrides CTA sizing (renders 131x38 instead of ~195x48) | Remove or merge the duplicate `.btn` block |
| 2 | `.home-featured` uses `border-image` which kills `border-radius` — card renders square | Replace with pseudo-element gradient border technique |
| 3 | Three different `max-width` tracks (36rem, 42rem, none) create jagged center column | Unify to 42rem for all content sections |
| 4 | Vertical spacing irregular — Random→Featured gap is only 8px vs 24px elsewhere | Normalize section margins to 1.5rem |
| 5 | Two `border-radius` values (0.5rem vs 0.625rem) on home cards | Unify to 0.625rem |

**Verification:** Visual screenshot comparison before/after on desktop (1280px) and mobile (375px).

---

### S02: Pipeline Admin UI Fixes
**Risk:** Low | **Effort:** Small-Medium | **Files:** `AdminPipeline.tsx`, `App.css`

Four issues identified with root causes already diagnosed:

| # | Issue | Root Cause | Fix |
|---|-------|-----------|-----|
| 1 | Most-recent run won't collapse / flickers | `expandedRunId` in `load()` useCallback dependency array (line 729) causes race condition — collapsing sets null, which triggers load recreation, which re-expands | Remove `expandedRunId` from dependency array + use `useRef` for initial-load tracking |
| 2 | Mobile job cards show vertical text ("C h e e") | `.pipeline-video__creator` missing overflow rules (App.css:4477) | Add `overflow: hidden; text-overflow: ellipsis; white-space: nowrap` (matches `.pipeline-video__filename` pattern) |
| 3 | No stage direction chevrons | Pipeline stages listed without visual flow indicator | Add CSS chevron/arrow between stage indicators using `::after` pseudo-elements or inline SVG |
| 4 | Filter text box should be replaced with button group | Current text input for status filter; should be "ALL \| Not Started \| In Progress \| Complete" buttons, end-aligned | Replace `<input>` with `<div className="filter-buttons">` flexbox, `justify-content: flex-end`, verify vertical alignment against adjacent elements |
| 5 | Creators dropdown never populates (422 error) | Frontend requests `fetchCreators({ limit: 200 })` but backend validates `le=100` (line 1126) | Change to `limit: 100` |

**Verification:** Test collapse toggle on most-recent run, resize to 375px and check creator name truncation, confirm chevrons render between stages, confirm filter buttons align right and sit level with row, confirm creator filter dropdown populates.

---

### S03: Brand Minimum (Favicon, OG Tags, Logo)
**Risk:** Low | **Effort:** Small | **Files:** `index.html`, `App.tsx`, `App.css`, new static assets

The site currently has:
- No favicon (browser default icon)
- No OG meta tags (no preview image when sharing URL via text/Discord)
- No logo next to "Chrysopedia" in the header

Tasks:
1. **Design a simple logo** — something that fits the dark theme + cyan accent aesthetic. Could be a stylized book/page icon, a knowledge/crystal motif matching the "chryso-" (gold) prefix, or an abstract mark. Generate an SVG.
2. **Add favicon** — export logo as favicon.ico + apple-touch-icon + 192/512 PNG for PWA manifest
3. **Add OG meta tags** — `og:title`, `og:description`, `og:image`, `og:url`, `twitter:card` in index.html. Create a 1200x630 OG image using the logo + brand colors.
4. **Place logo in header** — render the SVG inline next to "Chrysopedia" text with appropriate sizing

**Verification:** Share URL in Discord/iMessage and confirm preview card renders. Check favicon in browser tab. Visual check logo in header.

---

### S04: ToC Modernization
**Risk:** Medium | **Effort:** Medium | **Files:** `TableOfContents.tsx`, `App.css`, `TechniquePage.tsx`

Research identified these dated elements:
- CSS counter numbering ("1.", "1.2") — biggest offender
- Boxed card container with solid border
- Uppercase "CONTENTS" label
- No active-section highlighting
- Underline-only hover states

Modernization plan:
1. **Remove numbered counters** — switch to unordered list with clean indentation
2. **Replace box border** with left accent bar (`border-left: 2px solid var(--color-accent)`)
3. **Change heading** from "CONTENTS" to "On this page" in sentence case
4. **Add hover background** (`rgba(34, 211, 238, 0.08)`) instead of underline
5. **Add IntersectionObserver** — track which section heading is in the viewport, highlight the corresponding ToC entry with accent left-border + brighter text color
6. **Make ToC sticky** — position it at the top of the existing sidebar (above Key Moments), `position: sticky; top: 1.5rem`

**Verification:** Navigate to a technique page with 4+ sections. Scroll through — ToC should highlight current section. ToC stays visible in sidebar while scrolling. Hover states work. No numbering visible.

---

### S05: Sticky Reading Header
**Risk:** Medium | **Effort:** Medium | **Files:** new `ReadingHeader.tsx`, `App.css`, `TechniquePage.tsx`

New component that slides in when user scrolls past the article title:
- Shows: article title (truncated) + current section name
- `position: sticky; top: 0; z-index: 50`
- Thin bar (~40px height), `var(--color-bg-header)` background, subtle bottom border
- Hidden by default, slides in via `transform: translateY(-100%)` → `translateY(0)` transition
- Uses IntersectionObserver on the technique header element as show/hide trigger
- Shares the section-tracking observer from S04's ToC work
- On mobile: compact single-line with optional dropdown for section jump
- Update `scroll-margin-top` values on section anchors to account for new header height

**Verification:** Open long technique page. Scroll past title — reading header appears. Correct section name updates as you scroll. Works on mobile (375px). Doesn't break existing header.

---

### S06: Landing Page Personality Pass
**Risk:** Low | **Effort:** Small | **Files:** `Home.tsx`, `App.css`

After S01 fixes the bugs, this slice adds polish:
1. **Hero tightening** — reduce hero bottom padding and how-it-works top margin to get content above the fold faster (~40-50px reclaim)
2. **Stats scorecard enhancement** — animated count-up on first view (simple `requestAnimationFrame` counter), subtle glow on numbers
3. **Random button treatment** — wrap in a small card with "Feeling adventurous?" tagline, or embed as secondary action inside Trending Searches
4. **Section heading standardization** — pick one treatment (title-case with left accent bar) and apply consistently to "Recently Added", "Trending Searches", "Popular Topics"
5. **Header brand accent** — apply `color: var(--color-accent)` or subtle gradient to "Chrysopedia" text (pairs with S03 logo)

**Verification:** Visual check desktop + mobile. Stats animate on page load. Section headings consistent. Content peeks above fold on standard viewport.

---

## Dependency Graph

```
S01 (landing fixes) ──→ S06 (personality pass)
S02 (pipeline fixes)     [independent]
S03 (brand minimum)  ──→ S06 (header accent uses logo)
S04 (ToC modern)     ──→ S05 (reading header shares IntersectionObserver pattern)
```

S01, S02, S03, S04 can all start in parallel. S05 depends on S04. S06 depends on S01 + S03.

Recommended execution order: **S01 → S02 → S03 → S04 → S05 → S06**

---

## Out of Scope (for this milestone)

- Creator landing page redesign (depends on backend social links API — see backend session workplan)
- Auto-avatar images (backend-gated — see backend session workplan)
- Embed tab (needs backend investigation first — see backend session workplan)
- Any backend Python changes
- M015 S04/S05 leftovers (trending searches block, admin dropdown hover) — should be completed by M015's own GSD session first
