# Journey 4: Rankings → shortlist — audit notes

**Pages visited:** `/rankings`, `/rankings?local_authority=Solihull`, `/rankings?local_authority=Solihull&metric=rwm_expected_pct`, `/school/{urn}` (drill-in + back)
**Viewports:** 390×844, 1440×900

## Task attempt log

Parent scenario: "show me the good schools around here" — filter to a local authority, scan, jump to a school (and ideally shortlist a few to compare).

**Mobile (390×844):**
1. Loaded `/rankings`. The filter controls (Metric / Area / Year) are visible directly above the list — no accordion or hidden panel, so filtering is immediately discoverable (good). Default subtitle: "Top-performing schools by reading, writing & maths combined higher % — showing top 100".
2. Filtered to Solihull: one interaction on the **Area** native select → picked "Solihull". List updated to 54 schools; URL became `?local_authority=Solihull`. Seconds-to-goal: fast, ~1 select interaction.
3. Changed **Metric** to "Reading, Writing & Maths Combined %". Subtitle updated dynamically to "% meeting expected standard in reading, writing and maths"; URL gained `&metric=rwm_expected_pct`. Both filter and metric are encoded in the URL.
4. Drilled into a school by tapping the school-name link; navigated back (browser back). **Filter (Solihull), metric, and vertical scroll position (2500px) were all restored.** This is the strongest result of the journey.
5. Observed that on mobile the **Type** and **Action** columns are `display:none`, and the metric % column sits past the initial fold requiring horizontal scroll of a nested table wrapper.

**Desktop (1440×900):** Full 6-column table (RANK, SCHOOL, AREA, TYPE, metric %, ACTION with View / +Compare). Table is a real `<table>` with `<thead>`/`<th>`. Ran axe, keyboard/focus checks, and a 200%-zoom reflow proxy (720px width).

## Friction points

- **F1. The ranking numbers themselves are low-contrast teal (fails AA)**
  - Evidence: `j4-rankings-desktop.png`; axe `color-contrast` (serious) reported **100 nodes** on desktop, sampleTargets include `.valueCell strong` (the teal "63.0%", "60.0%"… values in every row) and the teal "+ Compare" links. Value colour ≈ teal `rgb(45,125,125)` on cream.
  - Criterion violated: WCAG 2.2 AA 1.4.3 Contrast (Minimum).
  - Argument: The percentage is the entire reason a parent is on this page — it is the score they are comparing schools by. Rendering the primary data in a colour that fails contrast makes the key number hard to read for low-vision parents (and outdoors on a phone). (Low-contrast text also seen on earlier journeys, but here it degrades the core content, not chrome.)
  - Severity guess: P1

- **F2. Cannot add a school to the compare shortlist from the ranked list on mobile**
  - Evidence: computed style — the `td` in the "Action" column (containing "View" and "+ Compare") is `display:none` at 390px; visible only at desktop width. The bottom nav shows a "Compare (3)" feature, so shortlisting is a first-class task.
  - Criterion violated: Task-flow obstruction; Nielsen "User control & freedom" / "Flexibility & efficiency". The journey is literally rankings → shortlist, and the shortlist action is removed on the primary (mobile) viewport.
  - Argument: A parent on a phone scanning the good local schools cannot build a comparison set from the rankings — they must open each school page individually and find another route in, adding steps to the core task on the highest-traffic device class.
  - Severity guess: P2

- **F3. The ranking value is off-screen on mobile — the list shows names but not scores without horizontal scroll**
  - Evidence: `j4-rankings-mobile.png`, `j4-rankings-filtered-mobile.png`. RANK + SCHOOL + AREA fill the 324px table wrapper; the metric % column (e.g. "86.0%") is present but requires horizontally scrolling the nested `.tableWrapper` (scrollWidth 551 > clientWidth 324) to reveal.
  - Criterion violated: Mobile usability (primary content not visible in the initial viewport). (Data tables are a recognised 1.4.10 Reflow exception, so noted as usability friction rather than a hard SC failure.)
  - Argument: A parent sees a ranked list of names but not the numbers that justify the ranking, unless they discover a sideways swipe inside the table. The comparison value — the point of the page — is hidden by default.
  - Severity guess: P2

- **F4. Horizontally-scrollable table wrapper is keyboard-inaccessible and unlabelled**
  - Evidence: `.RankingsView…tableWrapper` has `overflow-x:auto` with `scrollWidth > clientWidth`, but no `tabindex="0"`, no `role`, no `aria-label`.
  - Criterion violated: WCAG 2.2 A 2.1.1 Keyboard (scrollable region not operable by keyboard); also 1.3.1 (unnamed region for screen readers).
  - Argument: Keyboard-only and switch users cannot scroll the table sideways to reach the off-screen metric/Action columns; screen-reader users get no region name. (Keyboard-inaccessible scrollable regions also seen on earlier journeys.)
  - Severity guess: P2

- **F5. Default ranking uses unexplained "higher standard" jargon**
  - Evidence: default metric is "Reading, Writing & Maths Combined **Higher** %"; top school scores 63.0%. Subtitle says "% achieving higher standard in reading, writing & maths combined" — but "higher standard" (greater depth) itself is not explained, and it is not the more familiar "expected standard".
  - Criterion violated: Nielsen "Match between system and the real world" / "Help & documentation".
  - Argument: A parent who doesn't know that "higher standard" means the top ~1 in 6 pupils may misread 63% as mediocre, when 63% at the higher standard is exceptional. The default frames every school's headline number in terms the audience is least likely to understand. (The chosen **year** — 2024/25 — is shown in the Year select but not repeated in the results subtitle.)
  - Severity guess: P2

- **F6. 33-option metric dropdown is a flat list of dataset jargon**
  - Evidence: metric select has 33 options including "GPS Expected %", "Maths Progress", "Reading Average Score", "Disadvantaged Gap", "% EAL Pupils", "% SEN Support", "% Pupil Stability", "GPS Test Absence %" — one ungrouped list, no plain-language expansion of abbreviations.
  - Criterion violated: Nielsen "Recognition rather than recall" / "Match with the real world".
  - Argument: A parent looking for "the good schools" must wade past acronyms (GPS, EAL, SEN) and technical measures (scaled "Average Score", "Progress") with no grouping or help text to find the metric they actually understand.
  - Severity guess: P3

- **F7. No column-sort affordance; `<th>`s lack `scope`**
  - Evidence: `<thead>` cells have `cursor:auto`, no `aria-sort`, no button, and are not clickable; no `scope` attribute and no `<caption>`. Ordering is controllable only via the Metric dropdown.
  - Criterion violated: Nielsen "Consistency & standards" (users expect a ranked data table to sort by clicking a column header); WCAG 1.3.1 best-practice (missing `scope` on header cells).
  - Argument: Parents who click "READING, WRITING & MATHS…" expecting to re-sort get no response; the only re-order path (a separate dropdown) is less discoverable than the convention they expect.
  - Severity guess: P3

- **F8. Filter selects remove the focus outline for a subtle border-colour change**
  - Evidence: CSS `.filter-select:focus { border-color: var(--accent-teal); outline: none; }`. Links and buttons, by contrast, get a strong 2px orange focus ring (`rgb(224,114,86)`).
  - Criterion violated: WCAG 2.2 AA 2.4.11 Focus Appearance (indicator area/contrast); inconsistent focus treatment.
  - Argument: A keyboard user tabbing through Metric/Area/Year gets only a faint 1.5px border hue shift — much weaker than the focus ring everywhere else — making it easy to lose track of focus while operating the filters.
  - Severity guess: P3

## Works well — keep

- **Back-navigation preserves full state.** After drilling into a school and pressing back, the LA filter, the chosen metric, AND the vertical scroll position were all restored (verified scroll 2500px + `area=Solihull` + `metric=rwm_expected_pct`). State lives in the URL, so results are also shareable/bookmarkable. This is the classic mobile task-killer check and the page passes cleanly.
- **The selected metric is explained in plain language and updates live.** Switching the dropdown changed the subtitle from "% achieving higher standard…" to "% meeting expected standard in reading, writing and maths" — good real-time sensemaking.
- **Filter selects are properly labelled.** Each select has an associated visible `<label>` (Metric / Area / Year). The unlabelled-select (WCAG 4.1.2 select-name) issue seen on the home results state does NOT recur here.
- **Semantic table.** Real `<table>` with `<thead>` and `<th>` header cells — screen readers announce it as a table with columns, not a pile of divs.
- **Skip link + logical tab order.** A "Skip to main content" link is first in the tab order, followed by nav → phase tabs → the three filter selects → table rows, in reading order.
- **Reflow at 200% / narrow width.** At 720px (200% zoom proxy) the filters stack vertically and there is no page-level horizontal scroll.

## Axe results

- `/rankings` @ 390×844 (default): **1** violation — `color-contrast` (serious, 2 nodes: active nav tab + active "Primary (KS2)" phase tab, white on orange).
- `/rankings?local_authority=Solihull` @ 390×844 (filtered): **1** violation — `color-contrast` (serious, 2 nodes: same active tabs).
- `/rankings` @ 1440×900 (default): **1** violation — `color-contrast` (serious, **100 nodes**: active tabs + `.valueCell strong` teal metric numbers across every row, plus teal "+ Compare" links). Node count jumps on desktop because the full 100-row table with visible metric values is rendered.

## Manual WCAG spot checks

- Touch targets ≥24px on interactive elements: **Pass (for visible targets).** School-name link 123×86px, Metric select 324×41px, phase tab 148×40px — all comfortably above 24px. Note: View / +Compare buttons are hidden on mobile (see F2), so no mobile shortlist target exists.
- Keyboard: tab order, focus visibility (desktop): **Mostly pass, one weakness.** Tab order logical (skip-link → nav → tabs → filters → rows); links and buttons show a strong 2px orange focus ring; filter selects suppress the outline for a faint teal border change (see F8).
- Zoom 200% text reflow (desktop): **Pass.** Filters reflow to a single column; no horizontal page scroll at 720px effective width.

## Screenshots

- `j4-rankings-mobile.png`: default `/rankings` at 390×844 — filters visible above list; table shows RANK/SCHOOL/AREA with metric % cut off to the right.
- `j4-rankings-filtered-mobile.png`: `/rankings?local_authority=Solihull` at 390×844 — 54 Solihull schools.
- `j4-rankings-desktop.png`: `/rankings` at 1440×900 — full 6-column table; teal metric values and teal "+ Compare" links visible (low-contrast, F1).
