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>
This commit is contained in:
Tudor
2026-07-01 18:12:12 +01:00
co-authored by Claude Opus 4.8
parent fba79b391a
commit d4d9ae5252
8 changed files with 617 additions and 369 deletions
+54 -101
View File
@@ -29,12 +29,15 @@
/* Header Section */
.header {
position: relative;
background: var(--bg-card, white);
border: 1px solid var(--border-color, #e5dfd5);
border-radius: 10px;
padding: 1.25rem 1.5rem;
/* Padding lives on .headerContent so the map band can bleed to the edges. */
padding: 0;
margin-bottom: 0;
box-shadow: var(--shadow-soft);
overflow: hidden;
}
.headerContent {
@@ -42,6 +45,55 @@
justify-content: space-between;
align-items: flex-start;
gap: 1.5rem;
padding: 1.25rem 1.5rem;
}
/* With a map band above, slide the title up under the fade so map and title
read as one object; the Compare button floats glassy over the map. */
.headerHasMap .headerContent {
padding-top: 0;
margin-top: -0.5rem;
position: relative;
z-index: 3;
}
.headerHasMap .actions {
position: absolute;
top: 14px;
right: 14px;
z-index: 6;
margin: 0;
}
.headerHasMap .actions .btnAdd {
background: rgba(255, 255, 255, 0.9);
color: var(--accent-coral, #e07256);
border-color: transparent;
-webkit-backdrop-filter: blur(6px);
backdrop-filter: blur(6px);
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.16);
}
.headerHasMap .actions .btnAdd:hover {
background: #fff;
}
/* Inline "View on map ↗" trigger next to the address. */
.mapLink {
border: none;
background: none;
padding: 0;
font: inherit;
font-weight: 600;
color: var(--accent-coral, #e07256);
cursor: pointer;
white-space: nowrap;
}
.mapLink:hover {
color: var(--accent-coral-dark, #c45a3f);
text-decoration: underline;
text-underline-offset: 2px;
}
.titleSection {
@@ -841,18 +893,6 @@
color: var(--accent-teal, #2d7d7d);
}
/* Map */
.mapContainer {
width: 100%;
height: 250px;
border-radius: 8px;
overflow: hidden;
border: 1px solid var(--border-color, #e5dfd5);
isolation: isolate;
z-index: 0;
position: relative;
}
/* History Table */
.tableWrapper {
overflow-x: auto;
@@ -1179,10 +1219,6 @@
height: auto;
}
.mapContainer {
height: 200px;
}
.dataTable {
font-size: 0.75rem;
}
@@ -1218,75 +1254,7 @@
}
}
/* Hero tone scheme — colour tokens applied to the scorecard's serif Ofsted
number (colour only) without bleeding into the .ofstedGrade{N} badges. */
.tone-teal {
--hero-tone: var(--accent-teal, #2d7d7d);
}
.tone-green {
--hero-tone: #3c8c3c;
}
.tone-gold {
--hero-tone: var(--accent-gold, #c9a227);
}
.tone-coral {
--hero-tone: var(--accent-coral, #e07256);
}
.tone-neutral {
--hero-tone: var(--text-muted, #8a847a);
}
/* ── Hero at-a-glance stats (A3) ─────────────────────────────────────── */
.heroStats {
display: flex;
flex-wrap: wrap;
gap: 1.25rem 3rem;
margin-top: 1.5rem;
padding-top: 1.5rem;
border-top: 1px solid var(--border-color, #e5dfd5);
}
.heroStat {
display: flex;
flex-direction: column;
gap: 0.35rem;
min-width: 0;
flex: 0 0 auto;
}
.heroStatNumber,
.heroStatNumberSerif {
font-family: var(--font-playfair), "Playfair Display", serif;
font-weight: 700;
line-height: 1;
color: var(--text-primary, #1a1612);
/* Fixed height so every stat's label row sits at the same Y, regardless
of whether the content is a short numeral or a longer word. Each
stat's content is bottom-aligned within this box. */
min-height: clamp(2rem, 4vw, 2.75rem);
display: flex;
align-items: flex-end;
}
.heroStatNumber {
font-size: clamp(2rem, 4vw, 2.75rem);
font-variant-numeric: tabular-nums;
}
.heroStatNumberSerif {
/* Slightly smaller so long words like "Requires Improvement" still fit,
but aligned on the same bottom baseline as the numeric stats. */
font-size: clamp(1.75rem, 3.5vw, 2.25rem);
}
.heroStatNumberSerif.tone-teal,
.heroStatNumberSerif.tone-green,
.heroStatNumberSerif.tone-gold,
.heroStatNumberSerif.tone-coral,
.heroStatNumberSerif.tone-neutral {
color: var(--hero-tone);
}
/* .heroStatLabel is shared by the SATs / Pupils stat cards below. */
.heroStatLabel {
font-size: 0.6875rem;
font-weight: 600;
@@ -1295,22 +1263,7 @@
color: var(--text-secondary, #5c564d);
}
.heroStatFoot {
font-size: 0.75rem;
color: var(--text-muted, #8a847a);
}
.heroDataNote {
margin: 0.5rem 0 0;
font-size: 0.75rem;
color: var(--text-muted, #8a847a);
}
@media (max-width: 640px) {
.heroStats {
gap: 1rem 1.5rem;
}
.heroSummary {
font-size: 1rem;
margin-top: 1rem;