# S04: Accessibility & SEO Fixes — UAT

**Milestone:** M011
**Written:** 2026-03-31T08:57:55.558Z

## UAT: S04 — Accessibility & SEO Fixes

### Preconditions
- Frontend built and served (dev server or production build)
- Browser with DevTools available
- Keyboard accessible (physical keyboard, not virtual)

---

### Test 1: Single H1 Per Page
**Steps:**
1. Navigate to Home (`/`)
2. Open DevTools → Console → run `document.querySelectorAll('h1').length`
3. Confirm result is `1`
4. Repeat for each route: `/topics`, `/topics/Sound%20Design/Bass`, `/creators`, `/creators/some-creator`, `/techniques/some-technique`, `/search?q=test`, `/about`, `/admin/reports`, `/admin/pipeline`

**Expected:** Every page returns exactly `1` for h1 count.

### Test 2: Sequential Heading Levels (Home Page)
**Steps:**
1. Navigate to Home (`/`)
2. Run in console: `[...document.querySelectorAll('h1,h2,h3,h4,h5,h6')].map(h => h.tagName)`
3. Verify the sequence goes H1 → H2 (no H1→H3 jumps)

**Expected:** Heading tags are sequential — no level skips.

### Test 3: Skip-to-Content Link
**Steps:**
1. Navigate to any page
2. Press Tab once from page load
3. Observe a "Skip to content" link appears at the top of the viewport
4. Press Enter on the link
5. Verify focus moves to the main content area

**Expected:** Skip link is visually hidden by default, appears on first Tab, and navigates to `#main-content`.

### Test 4: Skip Link Not Visible Without Keyboard
**Steps:**
1. Navigate to any page
2. Do NOT press Tab
3. Inspect the page visually

**Expected:** No skip link visible — it's off-screen until focused.

### Test 5: Muted Text Contrast
**Steps:**
1. Open DevTools → Elements
2. Find any element using `var(--color-text-muted)`
3. Inspect computed color — should be `#828291` (rgb(130, 130, 145))
4. Check contrast against page background `#1a1a2e`: ratio should be ≥ 4.5:1

**Expected:** Muted text color is `#828291` with ≥ 4.5:1 contrast ratio.

### Test 6: Document Title — Static Pages
**Steps:**
1. Navigate to Home → check browser tab title
2. Navigate to `/topics` → check tab title
3. Navigate to `/creators` → check tab title
4. Navigate to `/about` → check tab title
5. Navigate to `/admin/reports` → check tab title
6. Navigate to `/admin/pipeline` → check tab title

**Expected:**
- Home: "Chrysopedia — Production Knowledge, Distilled"
- Topics: "Topics — Chrysopedia"
- Creators: "Creators — Chrysopedia"
- About: "About — Chrysopedia"
- Reports: "Content Reports — Chrysopedia"
- Pipeline: "Pipeline Management — Chrysopedia"

### Test 7: Document Title — Dynamic Pages
**Steps:**
1. Navigate to a technique page (e.g., `/techniques/some-slug`)
2. Wait for content to load
3. Check browser tab title — should show technique name + "— Chrysopedia"
4. Navigate to a creator detail page
5. Check tab title — should show creator name + "— Chrysopedia"
6. Navigate to `/search?q=reverb`
7. Check tab title — should show "Search: reverb — Chrysopedia"

**Expected:** Dynamic pages update the tab title when data finishes loading. While loading, title shows "Chrysopedia".

### Test 8: Title Cleanup on Navigation
**Steps:**
1. Navigate to a technique page (title updates to technique name)
2. Click browser back button or navigate to Home
3. Check tab title updates to the new page's title (not stuck on previous)

**Expected:** Title updates correctly on SPA navigation — no stale titles.

### Edge Cases

### Test 9: SearchResults H1 Screen Reader
**Steps:**
1. Navigate to `/search?q=test`
2. In DevTools, find the h1 element
3. Verify it exists but has `sr-only` or equivalent visually-hidden class
4. Verify it's not visible on screen but present in accessibility tree

**Expected:** h1 exists for screen readers but is not visually rendered.

### Test 10: Nav Brand Is Not H1
**Steps:**
1. Navigate to any page
2. Inspect the "Chrysopedia" text in the nav header
3. Verify it's a `<span>`, not an `<h1>`

**Expected:** Nav brand is `<span>Chrysopedia</span>`, not heading element.
