/* Map tab — Leaflet container, toolbar, side panel and popups.

   Hierarchy:
   - .map-* — toolbar, map body split (canvas + side panel), pills,
     uninspected-toggle, region geojson stroke.
   - .leaflet-* overrides — popup chrome adjusted to read like our
     school-card surface.
   - .map-side-panel-* — the slide-in side panel content (LA + per-
     school detail).
   - .map-popup-* — inline popup variant with grade chips, bullets,
     trend mini-charts (.map-popup-perf-*).
   - .map-band-marker-img — pre-rasterised banded school marker
     (one coloured stripe per inspection area), served as an
     L.icon data-URL since PR 499. The legacy DOM-based class
     family (.map-band-marker / .m-band-bar / .m-band / .m-band-
     empty) was retired in the same map-polish bundle — no live
     JS or HTML referenced them by the time they came out. */

/* Map tab — fills the available width via the full-bleed rule on
   .main-inner, and uses the remaining viewport height so the canvas
   is as generous as the screen allows. Toolbar lives in its own
   padded strip above the map proper. */
/* Scoped to :not([hidden]) — the #tab-map id selector is more
   specific than [hidden]'s display:none, so without the scope this
   rule would keep the (full-bleed, 100vh) map section visible in
   the DOM beneath every other tab, dumping a phantom block of
   blank space under Big picture and pushing Trends / Latest /
   About down a screenful. */
#tab-map:not([hidden]) {
  display: flex;
  flex-direction: column;
  /* Fixed-height so the side panel can scroll independently of the
     map (overflow-y: auto on .map-side-panel only works when its
     parent's height is constrained — with min-height the panel
     would grow to fit content and the whole page would scroll). */
  height: calc(100vh - 60px);
  padding: 0;
  overflow: hidden;
}
.map-toolbar {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 14px 22px;
  padding: 12px 24px;
  border-bottom: 1px solid var(--rule);
  background: var(--paper-2);
  flex-shrink: 0;
}
@media (max-width: 760px) {
  .map-toolbar { padding: 10px 12px; gap: 8px 12px; }
  .map-legend  { font-size: 11px; gap: var(--space-2); }
  .map-legend .dot { width: 8px; height: 8px; }
  .map-pill { padding: 4px 8px; font-size: 11px; }
  .map-status { font-size: 11px; margin-left: 0; }
}
/* The toolbar h2 was dropped (the tab indicator already names this
   surface) — rule kept as a no-op so any historical reference still
   resolves to a defined selector. Safe to delete in a follow-up. */
.map-toolbar h2 {
  font-size: 19px; /* @approved: retained no-op rule for historical selector compatibility; element no longer rendered */
  margin: 0;
  flex-shrink: 0;
}
/* Legend lives inside a Leaflet control at the bottom-right of the
   map (positioned by Leaflet's overlay system, not the toolbar
   flow). The base .map-legend rules style the swatch row regardless
   of where it ends up; .map-legend-ctrl adds the bottom-right panel
   chrome — translucent-white background, subtle border + shadow so
   it reads as a standard map widget rather than a toolbar spillover. */
.map-legend {
  display: flex; flex-wrap: wrap; gap: var(--space-3);
  font-size: 12px; color: var(--ink-2);
  align-items: center;
}
.map-legend-ctrl {
  display: flex !important;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-1);
  padding: 8px 10px;
  background: color-mix(in srgb, var(--card) 92%, transparent);
  border: 1px solid var(--rule);
  border-radius: var(--r-sm);
  box-shadow: 0 1px 4px rgba(0,0,0,0.08);
  font-size: 11px;
  line-height: 1.3;
  max-width: 180px;
}
.map-legend-ctrl > span {
  display: flex;
  align-items: center;
  white-space: nowrap;
}
.map-legend .dot {
  width: 10px; height: 10px; border-radius: 50%;
  display: inline-block;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.08);
  margin-right: var(--space-1);
  vertical-align: -1px;
}
/* Grade-coloured legend dots — driven by data-grade so the swatches
   match the canonical GRADE_ORDER tokens that drive every other graded
   surface (charts.ga-seg, reports.seg, ag-cell-head). Dot keeps the
   --dot-bg pass-through fallback declared on the generic .legend .dot
   rule for sequential-band legends. */
.map-legend .dot[data-grade="Exceptional"]        { background: var(--g-exceptional); }
.map-legend .dot[data-grade="Strong standard"]    { background: var(--g-strong); }
.map-legend .dot[data-grade="Expected standard"]  { background: var(--g-expected); }
.map-legend .dot[data-grade="Needs attention"]    { background: var(--g-attention); }
.map-legend .dot[data-grade="Urgent improvement"] { background: var(--g-urgent); }
/* "Not yet inspected" swatch — muted grey at low opacity so it
   reads as visually softer than the graded dots above. Replaces
   an inline `style="background:var(--ink-3);opacity:0.4"` on the
   final legend item. */
.map-legend .dot--uninspected {
  background: var(--ink-3);
  opacity: 0.4;
}
/* LA-fill swatches — square rather than round to signal "polygon
   fill" vs the round dots that represent point markers. Same
   palette tokens as the school grades so the colour-to-meaning
   mapping stays consistent across the legend. */
.map-legend .dot--square {
  border-radius: 2px;
}
.map-legend .dot[data-send="positive"]          { background: var(--g-expected); }
.map-legend .dot[data-send="inconsistent"]      { background: var(--g-attention); }
.map-legend .dot[data-send="systemic_failings"] { background: var(--g-urgent); }
.map-legend .dot[data-ilacs="Outstanding"]                     { background: var(--g-strong); }
.map-legend .dot[data-ilacs="Good"]                            { background: var(--g-expected); }
.map-legend .dot[data-ilacs="Requires improvement to be good"] { background: var(--g-attention); }
.map-legend .dot[data-ilacs="Inadequate"]                      { background: var(--g-urgent); }
/* Small section heading inside the legend control — separates the
   marker-grade swatches above from the LA-fill swatches below. */
.map-legend-section-head {
  font-size: var(--text-nano);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-top: var(--space-1);
  display: block;
}
.map-legend-ctrl .dot {
  margin-right: 6px;
  flex-shrink: 0;
}
/* Leaflet bar controls (+/- zoom, Reset view) — token-driven so they
   follow the site theme like the legend control does (vendored
   leaflet.css ships literal #fff / #f4f4f4 chrome, and loadLeaflet
   injects it after the site stylesheets, hence the .leaflet-container
   scope for the specificity to win). Applies to every map instance —
   main tab + panel mini-maps — so the buttons read as one system. */
.leaflet-container .leaflet-bar a,
.leaflet-container .leaflet-bar button {
  background-color: var(--card);
  color: var(--ink);
  border-bottom-color: var(--rule);
}
.leaflet-container .leaflet-bar a:hover,
.leaflet-container .leaflet-bar a:focus,
.leaflet-container .leaflet-bar button:hover,
.leaflet-container .leaflet-bar button:focus {
  background-color: var(--paper-2);
}
.leaflet-container .leaflet-bar a.leaflet-disabled {
  background-color: var(--paper-2);
  color: var(--ink-3);
}
/* Reset-view button (main Map tab, under the +/- bar at top-left).
   A <button> — natively keyboard-activatable, unlike Leaflet's <a>
   controls — so it needs the box metrics vendor CSS scopes to
   `.leaflet-bar a` (26px, 30px on touch). Colours come from the
   shared bar rules above; the bar div supplies border + shadow. */
.map-reset-btn {
  display: block;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  line-height: 26px;
  text-align: center;
  font: inherit;
  cursor: pointer;
  border-radius: inherit;
}
.map-reset-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.leaflet-touch .map-reset-btn {
  width: 30px;
  height: 30px;
  line-height: 30px;
}
.map-reset-btn svg {
  vertical-align: middle;
}
.map-color-by {
  display: flex; align-items: center; gap: var(--space-2);
  font-size: 12px; color: var(--ink-3);
}
/* "Show not yet inspected" toggle in the map toolbar. Plain
   checkbox + label — sits between the colour-by select and the
   map-status text. */
/* @applies-to label */
.map-uninspected-toggle {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; color: var(--ink-3);
  cursor: pointer; user-select: none;
}
.map-uninspected-toggle input { cursor: pointer; }
.map-uninspected-toggle:hover { color: var(--ink); }

/* Display popover — three controls (Colour by / Show not yet
   inspected / Show local authorities) used to sit inline in the
   toolbar, occupying ~80 px of vertical wrap-row on a 375 px
   mobile viewport. PR 505 folds them into a single "Display ▾"
   trigger that opens a small panel; the toolbar collapses to one
   row on mobile. <details> handles the open/close state without
   JS so the popover works under prefers-reduced-motion + slow
   network conditions. */
.map-display-popover {
  position: relative;
  flex-shrink: 0;
}
.map-display-trigger {
  display: inline-flex; align-items: center; gap: var(--space-1);
  padding: 4px 10px;
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-2);
  background: var(--card);
  border: 1px solid var(--rule-2);
  border-radius: var(--r-sm);
  cursor: pointer;
  user-select: none;
  /* Suppress the default <summary> disclosure triangle. Three lines
     because the rendering path differs by browser:
       list-style: none           — modern Chrome / Firefox.
       ::-webkit-details-marker   — Safari < 17.
       ::marker { content: "" }   — spec-compliant marker pseudo.
     The caret arrow we want is the rotating ▾ span inside the
     trigger. */
  list-style: none;
}
.map-display-trigger::-webkit-details-marker { display: none; }
.map-display-trigger::marker { content: ""; }
.map-display-trigger:hover { color: var(--ink); border-color: var(--rule); }
.map-display-popover[open] > .map-display-trigger {
  border-color: var(--ink-3);
  background: var(--paper-2);
}
.map-display-caret {
  display: inline-block;
  font-size: var(--text-9);
  transition: transform var(--t-fast);
  color: var(--ink-3);
}
.map-display-popover[open] > .map-display-trigger > .map-display-caret {
  transform: rotate(180deg);
}
.map-display-panel {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: 401; /* above Leaflet panes (default 400) */
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
  padding: 12px 14px;
  min-width: 220px;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  box-shadow: 0 4px 12px rgba(0,0,0,0.08);
}
/* Section group inside the popover — visually pairs related toggles
   (Schools: show/hide + colour-by) and (Background: LA outlines +
   legend) so the panel reads as two short stacks rather than five
   loose controls. The first section has no border-top; subsequent
   ones get a faint rule above the head. */
.map-display-section {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
  width: 100%;
}
.map-display-section + .map-display-section {
  border-top: 1px solid var(--rule);
  padding-top: var(--space-3);
}
.map-display-section-head {
  font-size: var(--text-nano);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-3);
}
/* Inside the popover the inline labels read tighter and stack
   vertically rather than competing for horizontal toolbar space. */
.map-display-panel .map-color-by { width: 100%; }
.map-display-panel .map-color-by .area-select { flex: 1 1 auto; }
/* Search input in the "Find" section. Same shape as the sidebar's
   `.filter-search-input` but scoped to this popover so the rest of
   the chrome (border-radius, padding) reads consistently with the
   adjacent `.area-select` controls. Writes through to `state.search`
   on a 220 ms debounce — shared with the sidebar search on other
   tabs so a query set here persists across tab switches. */
.map-search-input {
  width: 100%;
  padding: 6px 10px;
  font-family: inherit;
  font-size: var(--text-sm);
  color: var(--ink);
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r-sm);
}
.map-search-input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
/* Search results listbox — populated by `renderMapSearchResults`
   underneath `.map-search-input` while the query is non-empty.
   Each row is a school the user can click → flyTo + open the
   school panel. Mirrors the visual shape of Compare's trust-find
   `.compare-explore-results` row (compare/dashboard.css) so the
   pattern reads as familiar across the site, but keys class names
   off `.map-search-*` to keep the namespaces independent. */
.map-search-results {
  width: 100%;
  max-height: 240px;
  overflow-y: auto;
  border: 1px solid var(--rule);
  border-radius: var(--r-sm);
  background: var(--card);
}
.map-search-result {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 6px 10px;
  cursor: pointer;
  border-bottom: 1px solid var(--rule);
}
.map-search-result:last-child { border-bottom: 0; }
.map-search-result:hover,
.map-search-result:focus-visible {
  background: var(--paper-2);
  outline: none;
}
.map-search-result-name {
  font-size: var(--text-sm);
  color: var(--ink);
  font-weight: 500;
}
.map-search-result-meta {
  font-size: var(--text-xs);
  color: var(--ink-3);
}
/* Trust rows in the dropdown — accent-tinted left border so the
   eye separates "filter to this whole MAT" from "navigate to this
   one school" without a heavier visual treatment. */
.map-search-result--trust { border-left: 3px solid var(--accent); }
.map-search-empty {
  padding: 8px 10px;
  font-size: var(--text-sm);
  color: var(--ink-3);
  font-style: italic;
}
.map-display-panel .map-uninspected-toggle { width: 100%; }
@media (max-width: 760px) {
  .map-display-trigger { padding: 4px 8px; font-size: 11px; }
  .map-display-panel { min-width: 200px; padding: 10px 12px; }
}
/* Inline filter pills in the map toolbar. They write through to
   state.phases / state.lowestGrades so the right-hand sidebar
   panel stays in sync if the user opens it. */
.map-pills {
  display: flex; align-items: center; gap: 6px;
  flex-wrap: wrap;
  font-size: 12px; color: var(--ink-3);
}
/* Recipe inherited from .chip + .chip--pill (components.css). The
   legacy `.map-pill` selector stays for the segmented-row chrome
   below (collapsed border-right between siblings; only first/last
   carry rounded corners). The `.on` modifier on the legacy markup
   is mirrored by `.chip--on` so the primitive's active-state chrome
   wins. */
/* @applies-to button */
.map-pill {
  /* Segmented-row override — adjacent pills sit shoulder-to-shoulder,
     so the shared border between them is dropped on every pill except
     the last. The Open-LA-profile button outside any group is both
     :first-child and :last-child so the :last-child rule below
     restores its right border. */
  border-right-width: 0;
}
.map-pill:first-child { border-radius: 4px 0 0 4px; }
.map-pill:last-child  { border-radius: 0 4px 4px 0; border-right-width: 1px; }
.map-status {
  margin-left: auto;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
  font-size: 12px;
}
/* Pointer affordance on the SVG path itself. Suppress the default
   browser focus outline (a rectangle around the polygon's bounding
   box) which is visually noisy on irregular shapes — hover/click
   style changes already provide the affordance. Keep focus visible
   for keyboard users via :focus-visible if the SVG ever gains
   tabindex. */
.leaflet-overlay-pane svg path { cursor: pointer; outline: none; }
.leaflet-overlay-pane svg path:focus { outline: none; }

/* LA side panel header — the LA name + region subline above the
   SEND / ILACS info blocks. The 2px gap under the name lets the
   region line sit immediately below as a tight pair; the 10px
   gap under the region line pushes the first info block clear.
   `.map-popup-name` / `.map-popup-meta` base rules live further
   down this file. */
.map-popup-name--la { margin-bottom: 2px; }
.map-popup-meta--la {
  color: var(--ink-3);
  font-size: 13px;
  margin-bottom: 10px;
}
/* "Open full LA profile ↗" CTA at the foot of the LA side
   panel — wraps a single .chip--pill. The 14px top margin
   pulls it clear of whatever block precedes it (schools list
   when present, sample-caveat otherwise). */
.la-panel-profile-cta { margin-top: 14px; }
/* Small-sample caveat under the grade-mix + characteristics
   bars on the LA panel. Sits in the muted ink-3 with a tight
   leading so it reads as fine-print disclaimer rather than
   body copy. */
.la-panel-sample-caveat {
  font-size: 11px;
  color: var(--ink-3);
  margin-top: 6px;
  line-height: 1.45;
}

/* Schools-in-this-LA list inside the map LA side panel. Compact
   row layout, grade chip on the right for inspected schools, soft
   "Not yet inspected" tag for uninspected. Whole row is clickable
   (opens the school's side panel). */
.la-schools-disclosure { margin-top: 14px; }
/* Inline override on the section-head sitting inside the summary —
   the eyebrow's default block-margin would break the baseline
   alignment with the counts span next to it. */
.la-schools-summary .la-schools-summary__head { margin: 0; display: inline; }
/* Disclosure chrome (summary list-style suppression, caret ▸,
   [open] rotate, caret hover-darken) is provided by the
   `.disclosure` primitive in components.css — JS composes
   `class="disclosure la-schools-disclosure"`. The summary keeps
   the baseline-aligned inline layout with a tight 2px gap (the
   section-head + counts read as a single inline header here,
   tighter than the primitive's default 6px). */
/* @applies-to summary */
.la-schools-disclosure > .la-schools-summary {
  align-items: baseline;
  gap: 2px;
  padding: 4px 0;
}
.la-schools-counts {
  color: var(--ink-3);
  font-size: 12px;
  font-weight: 400;
}
.la-schools-list {
  list-style: none;
  margin: 6px 0 0;
  padding: 0;
  max-height: 360px;
  overflow-y: auto;
}
/* "Schools at a glance" block on the LA side panel (only rendered
   when an LA has 0 inspected schools — phase mix + governance
   split sourced from GIAS). Surfaces a two-row swatch legend
   below the bars; each item is an inline-flex pair of swatch +
   label, with a 10px right-margin separating items horizontally.
   Item swatches use `--dot-bg` for the colour pass-through
   (matches the `.legend .dot` recipe in components.css). The
   italic `.panel-glance-legend__note` reads as fine-print
   beneath. */
.panel-characteristics--mt-sm { margin-top: var(--space-2); }
.panel-glance-legend {
  font-size: var(--text-nano);
  color: var(--ink-3);
  margin-top: 6px;
  line-height: 1.6;
}
.panel-glance-legend__item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  margin-right: 10px;
}
.panel-glance-legend__chip {
  display: inline-block;
  width: 10px; height: 8px;
  background: var(--dot-bg, var(--rule));
  border-radius: 1px;
}
.panel-glance-legend__note { font-style: italic; }
.la-school-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: 5px 6px;
  border-radius: var(--r-sm);
  cursor: pointer;
  font-size: 13px;
  line-height: 1.3;
}
.la-school-row:hover, .la-school-row:focus-visible {
  background: var(--rule-2);
  outline: none;
}
.la-school-name {
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.la-school-row--inspected .la-school-grade {
  flex: 0 0 auto;
  font-size: 11px;
  padding: 2px 6px;
  border-radius: 3px;
  background: color-mix(in srgb, var(--g) 18%, transparent);
  border-left: 2px solid var(--g);
}
.la-school-row--uninspected .la-school-name { color: var(--ink-3); }
.la-school-row--uninspected .la-school-status {
  flex: 0 0 auto;
  font-size: 11px;
  color: var(--ink-3);
  font-style: italic;
}
#map-container {
  flex: 1 1 auto;
  min-height: 520px;
  background: var(--paper-2);
}
/* Map body splits horizontally between the map canvas and an
   optional side-panel that opens when a marker is clicked. The
   panel uses the [hidden] attribute (which sets display:none) so
   the map occupies the full width until the user asks for detail.
   Once visible it claims a fixed 380px column. */
.map-body {
  display: flex; flex-direction: row;
  flex: 1 1 auto;
  min-height: 520px;
  overflow: hidden;
}
/* Side panel is a global aside (#map-side-panel in index.html / the
   SPA shell) used from the Map, Trust profile, LA profile, school-
   timeline rows, and global search. Position:fixed keeps it
   accessible across all those surfaces.

   On the Map specifically, the panel used to cover ~42% of the
   map canvas (540 px on a 1280 px desktop). Two fixes:

   1. Narrowed to 440 px (still comfortable for the chip-and-
      mini-chart layout) so it covers less of the map.
   2. When the panel is open AND the Map tab is active, the
      `body.map-side-panel-open` class adds padding-right to the
      map body so the map shrinks left instead of being covered.
      Leaflet's invalidateSize() is already called on panel open/
      close, so the basemap repaints to the new container width. */
.map-side-panel {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: 440px;
  max-width: 95vw;
  border-left: 1px solid var(--rule);
  background: var(--card);
  overflow-y: auto;
  z-index: 1000;
  box-shadow: -6px 0 18px rgba(0, 0, 0, 0.08);
}
.map-side-panel[hidden] { display: none; }
body.map-side-panel-open #tab-map #map-container {
  margin-right: 440px;
  transition: margin-right var(--t-fast);
}
.map-side-panel-inner {
  position: relative;
  padding: 16px 36px 24px 18px;
  line-height: 1.5;
}
.map-side-panel-inner > .close-btn--lg {
  position: absolute;
  top: var(--space-2);
  right: var(--space-3);
  margin-left: 0;
}
/* Bullets list inside the side panel — same look as the inline
   popup version, just allowed to grow to full length. */
.map-side-panel .map-popup-bullets { font-size: 13px; }
.map-side-panel .map-popup-name { font-size: var(--text-lg); }
.map-side-panel-mini-map {
  float: right;
  margin: 0 0 6px 12px;
}
/* Narrative + next-steps disclosure blocks inside the side panel
   get the same .sv-narrative-block treatment used on the Reports
   tab cards; tighten the body padding so the panel fits more on
   screen at the 380px width. */
.map-side-panel .sv-narrative-block { margin-top: var(--space-2); }
.map-side-panel .sv-narrative-body { padding: 4px 12px 12px; }
.map-side-panel .sv-narrative-body p { font-size: var(--text-sm); }
.map-side-panel .map-popup-bullets {
  list-style: disc;
  padding-left: 18px;
  margin: 0;
}
.map-side-panel .sv-narrative-body .map-popup-bullets li { margin: 0 0 4px; }
.map-side-panel .sv-links { margin: 6px 0; }
.map-side-panel .sv-timeline-row { grid-template-columns: 96px 1fr auto; }
/* Local-authority context chips row — sits between meta line and
   external links on the map side panel. Two chips: LA SEND outcome
   and ILACS children's-services grade for the school's LA. Coloured
   to match the SEND/ILACS palettes elsewhere on the site so a red
   chip on the panel means the same thing as a red row on the LA
   SEND chart. Click → opens the LA in the Groups tab via the
   standard data-nav-la handler. */
.map-popup-local-context {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin: 6px 0 10px;
}
.ctx-chip {
  display: inline-flex; flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  padding: 4px 8px 4px 6px;
  border: 1px solid color-mix(in oklch, var(--g, var(--rule)) 45%, var(--card));
  border-left: 4px solid var(--g, var(--rule));
  border-radius: 3px;
  background: color-mix(in oklch, var(--g, var(--rule)) 22%, var(--card));
  color: var(--ink-2);
  cursor: pointer;
  font: inherit;
  text-align: left;
  transition: background var(--t-fast), border-color var(--t-fast);
}
.ctx-chip:hover,
.ctx-chip:focus-visible {
  background: color-mix(in oklch, var(--g, var(--rule)) 35%, var(--card));
  color: var(--ink);
}
.ctx-chip:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
.ctx-chip-label {
  font-size: var(--text-nano);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.ctx-chip-value {
  font-size: 12px;
  font-weight: 500;
  color: var(--ink);
}
/* DfE pupil-characteristics disclosure on uninspected schools.
   A two-column <dl> inside the disclosure body — Governance /
   Establishment / Postcode etc. used to share these styles via a
   `.gias-facts` selector at the foot of every panel, but that
   block was retired; this rule now stands alone. */
.uninspected-facts {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 4px 12px;
  margin: 0;
  font-size: 13px;
}
.uninspected-facts dt { color: var(--ink-3); font-size: 12px; }
.uninspected-facts dd { margin: 0; color: var(--ink); }
/* Compact 2-col key-value table used by the Financial profile
   mini-block on the Map side panel. The LA-panel version (PR2)
   adds the same rule in compare/panel.css — kept here too so PR3
   stands on its own when reviewed pre-PR2-merge; the duplicate is
   collapsed by a later cleanup once both have landed. */
.finance-mini-table {
  width: 100%;
  margin: 8px 0 6px;
  border-collapse: collapse;
  font-size: var(--text-sm);
}
.finance-mini-table th,
.finance-mini-table td {
  padding: 4px 0;
  border-bottom: 1px solid var(--rule);
  text-align: left;
  font-weight: 400;
}
.finance-mini-table th { color: var(--ink-3); }
.finance-mini-table td {
  color: var(--ink);
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.finance-mini-table tr:last-child th,
.finance-mini-table tr:last-child td { border-bottom: 0; }

/* Trust-style headline cards on the school side panel — two stacked
   cards (In-year balance + Reserves) above the supporting figures
   table. The container carries both `.school-finance-cards` and
   `.aar-headlines-grid` so the card styling (border, padding, the
   .aar-headline-trend divider line, the .aar-fill-bar percentile
   bar) is inherited verbatim from compare/blocks.css. Compound
   selector (specificity 2,0 vs the trust's 1,0) flips the trust's
   3-column grid to a single stacked column — the side panel is
   narrow and 2 cards side-by-side would crush the historical-trend
   axis. */
.school-finance-cards.aar-headlines-grid {
  grid-template-columns: 1fr;
  margin: 6px 0 12px;
}
/* Tighter staff-cost / per-pupil table beneath the cards — only
   3 rows so we let it size to its content rather than carrying the
   default top margin. */
.school-finance-context-table { margin-top: var(--space-2); }
@media (max-width: 760px) {
  .map-body { flex-direction: column; min-height: 0; }
  /* On mobile the map and the side panel stack vertically and
     share the calc(100vh - 60px) container height. Without the
     overrides below, #map-container's 520px floor (sensible on
     desktop) forces it to fill the whole column, pushing the
     side panel below the viewport — combined with .map-body's
     overflow:hidden the panel ends up clipped and invisible.
     Loosening the floor lets the flex layout cede ~50vh to the
     panel when a marker is tapped. */
  #map-container { min-height: 0; }
  .map-side-panel {
    width: 100%; max-width: none;
    max-height: 50vh;
    min-height: 200px;
    border-left: 0;
    border-top: 1px solid var(--rule);
  }
  /* Mobile reverts the desktop "shift map left" behaviour — the
     panel stacks vertically under the map (see .map-body
     flex-direction above) and the desktop margin would leave a
     column of empty space to the right of the map. */
  body.map-side-panel-open #tab-map #map-container { margin-right: 0; }
}
/* Leaflet popup styling — match the school-card look so the popup
   reads like a smaller version of what users see on Latest reports. */
.leaflet-popup-content-wrapper {
  border-radius: var(--r-md);
  box-shadow: var(--shadow);
}
.leaflet-popup-content { margin: 12px 14px; line-height: 1.5; }
.map-popup-name { font-weight: 600; font-size: 14px; color: var(--ink); }
.map-popup-meta { color: var(--ink-3); font-size: 12px; margin: 2px 0 8px; }
/* Identity badge beside the school name — e.g. the "Grammar school"
   flag for selective-admissions schools (GIAS admissions_policy). A
   subtle inline tag, not interactive; sits on the name line so it
   reads as part of the school's identity rather than an outcome. */
.map-popup-badge {
  display: inline-block;
  vertical-align: middle;
  margin-left: var(--space-1);
  padding: 1px 6px;
  border-radius: 999px;
  font-size: var(--text-10);
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  color: var(--accent);
  border: 1px solid var(--accent);
}
/* Click-to-filter chip inside a map popup — used for region and
   trust names. Visually a subtle link, but it's a real <button>
   for keyboard / a11y; the delegated handler on #tab-map applies
   the filter and refits the map. */
/* @applies-to button */
.map-popup-filter {
  background: none; border: 0; padding: 0;
  color: var(--accent); font: inherit; font-size: 12px;
  cursor: pointer; text-decoration: underline; text-decoration-style: dotted;
  text-underline-offset: 2px;
}
.map-popup-filter:hover { text-decoration-style: solid; }
.map-popup-grades { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-bottom: var(--space-2); }
/* Chrome inherited from .chip--graded (components.css). The
   popup variant tightens padding (2×6×2×4 vs 3×8×3×4 default)
   and narrows the stripe (3px vs 4px) so several chips can sit
   side-by-side inside the constrained popup body without
   overflowing. Gap also narrows (5px vs 7px default). */
.map-popup-grade {
  --chip-py: 2px;
  --chip-px: 6px;
  --chip-stripe: 3px;
  --chip-gap: 5px;
}
.map-popup-grade-name { color: var(--ink-3); }
.map-popup-grade-val { font-weight: 500; color: var(--ink); }
.map-popup-bullets {
  margin: 0 0 8px; padding-left: 18px;
  font-size: 12px; color: var(--ink-2); line-height: 1.45;
}
.map-popup-bullets li { margin: 0 0 3px; }
/* Multi-year DfE attainment + attendance trend charts in the
   map popup. Each chart is a small line plot with explicit Y-range
   labels (min / max) on the left and first / last academic year on
   the bottom — proper mini-charts, not sparklines. */
.map-popup-perf-label {
  font-size: 11px; color: var(--ink-3); text-transform: uppercase;
  letter-spacing: 0.06em; margin: 8px 0 2px;
  display: flex; justify-content: space-between; align-items: baseline;
  gap: var(--space-2);
}
.map-popup-perf-label .pm-latest {
  text-transform: none; letter-spacing: 0;
  color: var(--ink); font-weight: 500; font-size: 12px;
}
.map-popup-perf-chart {
  display: block;
  width: 100%;
  height: auto;
  max-height: 70px;
  margin: 0 0 4px;
}
.map-popup-perf-chart .pm-axis { stroke: var(--rule); stroke-width: 1; }
.map-popup-perf-chart .pm-axis-label {
  font-family: -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  font-size: var(--text-9); fill: var(--ink-3);
}
.map-popup-perf-chart .pm-line { fill: none; stroke: var(--accent); stroke-width: 1.6; }
.map-popup-perf-chart .pm-pt   { fill: var(--accent); }
.map-popup-perf-chart .pm-pt-last { fill: var(--ink); }
/* Faded dashed national-average line, drawn behind the school
   line so the school's trajectory pops while still being legible
   against the national baseline. */
.map-popup-perf-chart .pm-nat-line {
  fill: none;
  stroke: var(--ink-3);
  stroke-width: 1.2;
  stroke-dasharray: 3 2;
  opacity: 0.7;
}
/* Vertical marker at the inspection year — anchors the
   "data at time of inspection" callout to a specific point on the
   line. Subtle so it doesn't compete with the school line itself. */
.map-popup-perf-chart .pm-inspect {
  stroke: var(--accent);
  stroke-width: 1;
  stroke-dasharray: 2 2;
  opacity: 0.55;
}
/* Series-break marker — faint dashed vertical at the midpoint of a
   year-gap > 1 (e.g. the COVID hole). Muted so it reads as a
   structural annotation, not data. */
.map-popup-perf-chart .pm-series-break {
  stroke: var(--ink-3);
  stroke-width: 1;
  stroke-dasharray: 3 3;
  opacity: 0.4;
}
/* Zero baseline — solid but muted horizontal rule for signed
   measures (disadvantage gap, Progress 8) where 0 means parity /
   national average. Solid (not dashed) so it reads as an axis, not
   a projection. */
.map-popup-perf-chart .pm-zero {
  stroke: var(--ink-2);
  stroke-width: 1;
  opacity: 0.5;
}
.map-popup-perf-sub {
  font-size: 11px; color: var(--ink-3); margin: 0 0 4px;
  display: flex; justify-content: space-between; gap: var(--space-2); align-items: baseline;
}
/* Per-phase per-year percentile chip — same recipe as the school-
   finance + trust-finance cards, reused via .trust-finance-rank +
   .aar-fill-bar. Sits between the headline value and the
   "Data at time of inspection" callout so readers see "school A
   scored 72% — 65th percentile against 13k Primaries in 2024/25"
   in one glance. */
.map-popup-perf-rank {
  margin: 0 0 6px;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
/* (Retired) The "Data at time of inspection" callout
   (.map-popup-perf-snapshot + .pm-snap-* children) lived between
   the headline and the chart. It was removed when the per-phase
   percentile chip + the trend chart's inspection-year marker
   together made the standalone block redundant. The
   `opts.snapshot.year` field still feeds the chart's vertical
   marker; see performanceTrendBlock in tabs/map.js. */
.map-popup-perf-sub .pm-leg {
  display: inline-flex; align-items: center; gap: 6px;
}
.map-popup-perf-sub .pm-leg::before {
  content: ""; display: inline-block; width: 16px; height: 0;
  border-top: 1.5px dashed var(--ink-3);
  vertical-align: middle;
}

/* ── KS4 Results: "By pupil group" table ────────────────────────────
   Compact table of the six DfE subgroups × headline measures, with a
   leading All-pupils anchor row and the group cohort "(N)" beside each
   row. Reuses the muted-caption / source-hint register of the perf
   trend blocks. */
.results-sg-table,
.results-subj-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-base);
}
.results-sg-caption,
.results-subj-caption {
  caption-side: top;
  text-align: left;
  font-size: var(--text-nano);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-3);
  margin: 0 0 var(--space-2);
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-2);
}
.results-sg-table th,
.results-sg-table td {
  padding: var(--space-1) var(--space-2);
  border-bottom: 1px solid var(--rule-2);
  text-align: right;
  white-space: nowrap;
}
.results-sg-grp {
  text-align: left;
  font-weight: 500;
  color: var(--ink-2);
}
.results-sg-table thead th {
  font-size: var(--text-nano);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-3);
  font-weight: 500;
}
.results-sg-val { font-variant-numeric: tabular-nums; }
.results-sg-n {
  font-variant-numeric: tabular-nums;
  color: var(--ink-3);
}
.results-sg-row--all .results-sg-grp,
.results-sg-row--all .results-sg-val { font-weight: 600; color: var(--ink); }
.results-sg-row--all th,
.results-sg-row--all td { border-bottom: 1.5px solid var(--rule); }
/* non_mobile is a technical DfE category, visually subordinated. */
.results-sg-row--tech .results-sg-grp,
.results-sg-row--tech .results-sg-val,
.results-sg-row--tech .results-sg-n {
  color: var(--ink-3);
  font-style: italic;
}
.results-sg-note,
.results-subj-note {
  font-size: var(--text-nano);
  color: var(--ink-3);
  margin: var(--space-2) 0 0;
  line-height: 1.4;
}

/* ── KS4 Results: "Att8 by element" composition bar ─────────────────
   Latest-year breakdown of Attainment 8 into its four subject slots
   (English / maths / EBacc / open). Per-segment width + colour via
   custom-property pass-through (--att8-elem-w / --att8-elem-bg set
   inline on each segment, consumed here) — no inline style literals. */
.att8-elem-block { margin: var(--space-2) 0 0; }
.att8-elem-label {
  font-size: 11px; color: var(--ink-3); text-transform: uppercase;
  letter-spacing: 0.06em; margin: 0 0 var(--space-1);
  display: flex; justify-content: space-between; align-items: baseline;
}
.att8-elem-bar {
  display: flex; width: 100%; height: 14px;
  border-radius: var(--r-sm); overflow: hidden;
  background: var(--rule-2);
}
.att8-elem-seg {
  width: var(--att8-elem-w);
  background: var(--att8-elem-bg);
  min-width: 1px;
}
.att8-elem-legend {
  display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-3);
  margin: var(--space-1) 0 0;
  font-size: var(--text-nano); color: var(--ink-2);
}
.att8-elem-legend-item { display: inline-flex; align-items: center; gap: var(--space-1); }
.att8-elem-legend-dot {
  width: 8px; height: 8px; border-radius: 2px;
  background: var(--att8-elem-bg); display: inline-block;
}
.att8-elem-note {
  font-size: var(--text-nano); color: var(--ink-3);
  margin: var(--space-2) 0 0; line-height: 1.4;
}

/* ── KS4 Results: "Subjects" table ──────────────────────────────────
   One row per subject group: entries, % of cohort entered, and a
   compact entries-denominated grade-distribution bar (custom-property
   pass-through for the per-segment width + band colour). */
.results-subj-table th,
.results-subj-table td {
  padding: var(--space-1) var(--space-2);
  border-bottom: 1px solid var(--rule-2);
  text-align: right;
  vertical-align: middle;
}
.results-subj-table thead th {
  font-size: var(--text-nano);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-3);
  font-weight: 500;
}
.results-subj-name {
  text-align: left;
  font-weight: 500;
  color: var(--ink-2);
}
.results-subj-qual {
  display: block;
  font-size: var(--text-nano);
  font-weight: 400;
  color: var(--ink-3);
  text-transform: none;
  letter-spacing: normal;
}
.results-subj-entries,
.results-subj-pct {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.results-subj-dist { width: 40%; min-width: 90px; }
.results-subj-bar {
  display: flex;
  width: 100%;
  height: 10px;
  border-radius: var(--r-sm);
  overflow: hidden;
  background: var(--rule-2);
}
.results-subj-bar--empty { background: var(--rule-2); }
.results-subj-seg {
  display: block;
  width: var(--seg-w);
  background: var(--seg-bg);
  height: 100%;
}
.results-subj-fold > summary { font-size: var(--text-base); }
.results-subj-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-3);
  margin: var(--space-2) 0 0;
}
.results-subj-legend-item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-nano);
  color: var(--ink-3);
}
.results-subj-legend-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 2px;
  background: var(--seg-bg);
}

/* Banded marker styling moved to the pre-rasterised SVG data-URL
   path inside main.js (PR 499). The legacy DOM-based rules
   (.map-band-marker / .m-band-bar / .m-band / .m-band-empty) lived
   here for backwards-compat with older markers; they're now dead
   and were retired in the same map-polish bundle as the Display
   popover. The new .map-band-marker-img class is just a Leaflet
   hook — no styles needed, the icon is fully self-contained as an
   <img> with its own SVG bitmap. */

