b793640507d669872bd3af02e0964e404e1cf33f
6
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
3236efa846 |
fix(map): the hero map's fade to the header was hardcoded white
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m7s
PR Checks / Backend Smoke (pull_request) Successful in 8s
PR Checks / Build Backend (no push) (pull_request) Successful in 10s
PR Checks / Build Frontend (no push) (pull_request) Successful in 44s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 11s
PR Checks / AI Code Review (Claude) (pull_request) Successful in 49s
The fade between the map band and the school header ramped through rgba(255,255,255,...) and landed on var(--bg-card). In the light theme that is white into white and invisible, as designed. In the dark theme it climbed to 95% WHITE and then met a near-black card, putting a bright band across the full width exactly where the map should dissolve into the title. Fading to the colour the gradient lands on is the whole trick, and it only works if that colour is a token — so --bg-card-rgb now exists in both theme blocks, matching the --hero-ground-rgb precedent. Two more defects in the same file, same cause, found while in there: The controls floating over the map paired a hardcoded white background with color: var(--text-primary), which resolves to #E9EEF0 in dark — near-white text on a near-white button. These deliberately do NOT follow the theme, because the map tiles are light in both, so the ink is now literal too and says why. A themed token is the wrong tool for a surface that never changes. The loading skeleton swept 50% white across var(--bg-secondary), which is a bright flash every 1.4s on a dark page. It now sweeps toward the card colour, a shade lighter than the ground in both themes. The guard is a stylesheet test rather than a render test, because the bug is invisible in the theme it was written for. Verified by reverting each fix in turn: it names .fade and .openHint exactly. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015mWQnpye9F299NVRCCSRvj |
||
|
|
8ab0ac0a04 |
feat(design): adopt the Cohort identity — new palette, type, mark and dark theme
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m6s
PR Checks / Backend Smoke (pull_request) Successful in 7s
PR Checks / Build Backend (no push) (pull_request) Successful in 12s
PR Checks / Build Frontend (no push) (pull_request) Successful in 49s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 10s
PR Checks / AI Code Review (Claude) (pull_request) Failing after 3m13s
Implements the direction agreed from the identity board: Route C ("Cohort")
with the paper ground from C1, the Schibsted Grotesk / Literata pairing from
C2, and the iris accent from C3. Dark theme is in scope from the start rather
than retrofitted.
The audit found three things wrong beyond taste:
* No brand asset set. og:image was absent entirely, so every link shared into
a class WhatsApp group rendered as a bare grey card. apple-touch-icon pointed
at an SVG, which iOS ignores, and the manifest shipped no PNGs, so Android
installs had no icon. The header mark and the favicon had also drifted into
two different logos.
* No colour discipline. --primary and --trend-down were the same coral, so the
main CTA and "below average" shared a hue. 58 distinct hex values were spread
across component CSS, and the chart palette was still Chart.js's stock demo
colours.
* A dark theme that was declared but never built — themeColor announced a dark
variant with no dark styling behind it.
What changed:
Colour now has exactly three jobs that never borrow each other's hues: brand
(iris) for interactive and identity, status (teal/amber) for above/below a
comparison point, and phase for categories. Teal/amber rather than green/red
keeps the above/below signal readable for every form of colour blindness.
Every chromatic literal in component CSS is now a token, and the JS-painted
surfaces (Chart.js, Leaflet) read the tokens through lib/theme so they follow
the theme instead of ignoring it.
The mark is the five-bar cohort spread — the same object as the distribution
strip inside a school row, built from opacity steps so it inverts cleanly.
components/Logo.tsx is the single source; the favicon, apple-icon and share
card all derive from its geometry.
globals.css drops 123 dead global classes left over from the vanilla-JS app
(only the btn family, .skip-link and .main were still referenced), along with
the noise overlay. It also gains prefers-reduced-motion support, which was
missing entirely, and a type scale so the 54 ad-hoc font sizes have somewhere
to converge.
Verified: tsc clean, 159 unit tests pass, production build succeeds and
prerenders /icon.svg, /apple-icon and /opengraph-image. Three e2e journeys
added for the asset set, the themeColor/background match, and the dark theme
actually repainting — all silent failures that nothing on the page reveals.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
d52d384cf2 |
fix(school): make hero map fullscreen work on iOS Safari
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 9m39s
PR Checks / Backend Smoke (pull_request) Successful in 5s
PR Checks / Build Backend (no push) (pull_request) Successful in 10s
PR Checks / Build Frontend (no push) (pull_request) Successful in 47s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 9s
PR Checks / AI Code Review (Claude) (pull_request) Successful in 4m15s
iOS Safari has no Element.requestFullscreen (fullscreen is video-only), so tapping the map band or 'View on map' silently did nothing on iPhones. Fall back to a fixed-position CSS overlay driven by state when the Fullscreen API is missing or its promise rejects, locking body scroll while open. The Leaflet map already re-measures via the shared isFullscreen flag. New e2e journey simulates the iOS condition by deleting the API and asserts the overlay opens and closes; it fails against the current production build. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
192173e515 |
feat(school-detail): icon-only Compare on phone heroes; unclutter map bottom edge
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 12s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 50s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 12s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 0s
On ≤640px the floating Compare button becomes a 40px round glyph (+ / ✓, aria-labelled) like the section-nav compare icon, instead of a full-width text pill over the map. The OSM attribution moves to the map band's top-left in preview so it no longer collides with the school name sliding up under the fade; fullscreen keeps Leaflet's default bottom-right since the zoom control occupies the top-left there. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
eae62a4b42 |
fix(school-detail): make the hero map fade visible
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 13s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 53s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 12s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
The blend gradient sat at z-index 2 — below Leaflet's tile pane (200) — so it was painted behind the map and the band ended in a hard edge with no diffusion. Raise the fade above the tile/overlay panes (450, still below the marker pane so the pin stays crisp) and the whole-band open button above the marker pane (800), and isolate the wrapper's stacking context so those raised z-indexes don't leak out and outrank the header's Compare button. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
d4d9ae5252 |
feat(school-detail): map-blended hero, remove at-a-glance stats
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 14s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 52s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 13s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 0s
Replace the header's at-a-glance stats row with a location map that sits atop the hero and blends into the school title. The map is a static, non-interactive preview (never traps page scroll) with a coral pin; the whole band — or the inline "View on map ↗" link by the address — opens a fullscreen, interactive map. Compare floats glassy over the band. The separate "Location" section (and its nav item) is removed; the map now lives only in the hero. Schools without lat/long render the header with no map band, as before. New: SchoolHeroMap (fullscreen wrapper, forwardRef open handle) + LeafletHeroMapInner (minimal single-school map with interaction toggle). Applied to both primary and secondary detail views; dead heroStats/tone/ mapContainer CSS removed (shared .heroStat* card classes kept). Also drops the orphaned "Latest data" note and does not reintroduce an Ofsted strip in the hero (it would duplicate the Ofsted section directly below). Mockup kept at mockups/header-map-hero.html. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |