/* public/browse.css — standalone; browse pages never load the SPA bundle.
   Editorial system: one display serif, monospace for every label, a sans for
   body copy, and exactly ONE saturated accent used like a marker pen. */

:root {
  --bg:#faf9f5;
  --panel:#ffffff;
  --ink:#111214;
  --body:#4a4842;
  --muted:#8a8780;
  --line:#e3e1da;
  --line-strong:#111214;
  /* CJP's own burnt orange (cjpparty.com). Dark type sits on it at
     5.4:1; white does not, at 3.5:1, so solid uses set the ink
     explicitly. The soft tint carries hovers, where a whole row of the
     solid colour would shout. */
  --accent:#e0651e;
  --accent-soft:#fbe4d5;
  --rule:#d8d5cd;

  --serif:'Playfair Display', Georgia, 'Times New Roman', serif;
  --mono:'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --sans:'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
}


/* Light is the default, whatever the device is set to.
 *
 * This deliberately ignores prefers-color-scheme. The page is a printed
 * public record — paper stock, a serif headline, ruled tables — and a
 * visitor arriving from a phone in night mode was getting a different
 * document from the one everyone else sees, with no way to say otherwise.
 * Dark is still here, and now it is a choice: the toggle in the masthead
 * writes it to localStorage, and the inline script in <head> applies it
 * before first paint so there is no flash of the wrong theme. */
:root[data-theme="dark"] {
  --bg:#0e0f10; --panel:#161719; --ink:#f4f2ec; --body:#b5b2a9;
  --muted:#807d76; --line:#26282b; --line-strong:#f4f2ec; --rule:#2c2e31;
  --accent:#e0651e; --accent-soft:#3a2417;
  --map-panel:#1a1b1d; --b-nodata:#232426;
}

* { box-sizing:border-box; }

body.browse {
  margin:0; padding:0 0 80px;
  background:var(--bg); color:var(--ink);
  font:16px/1.6 var(--sans);
  -webkit-font-smoothing:antialiased;
}
/* ---------- masthead ---------- */
.masthead { display:flex; align-items:baseline; justify-content:space-between;
  gap:16px; padding-bottom:14px; border-bottom:1.5px solid var(--line-strong);
  margin-bottom:26px; flex-wrap:wrap; }
.masthead .wordmark { font:600 17px/1 var(--mono); letter-spacing:-0.02em;
  color:var(--ink); text-decoration:none; }
.masthead .wordmark span { color:var(--muted); }

/* ---------- shared label ---------- */
.label { display:inline-block; font:500 11px/1 var(--mono); letter-spacing:.16em;
  text-transform:uppercase; color:var(--muted); }

/* ---------- stat strip ---------- */
/* The three boxes are one row: equal height, and each one's note sits on
   the bottom rule rather than floating wherever its text happened to end. */
.stat-grid > div { display:flex; flex-direction:column; }
.stat-grid > div > .note:last-child,
.stat-grid > div > .note { margin-top:auto; padding-top:14px; }
.stat-grid { display:grid; grid-template-columns:repeat(3, 1fr);
  border:1px solid var(--line-strong); margin-bottom:16px; }
.stat-grid > div { padding:26px 28px 28px;
  border-right:1px solid var(--line-strong); }
.stat-grid > div:last-child { border-right:0; }
.stat-grid .label { padding-bottom:12px; margin-bottom:16px;
  border-bottom:1px solid var(--rule); display:block; }
/* Serif is the editorial voice; mono is always the data. Keeping figures in
   the display serif blurred that line — every number on the site is mono. */
.stat-grid .figure { font:600 46px/1 var(--sans); letter-spacing:-0.03em;
  font-variant-numeric:tabular-nums slashed-zero;
  font-feature-settings:'zero' 1, 'tnum' 1; }
.stat-grid .figure mark { background:var(--accent); color:#111214; padding:0 .06em; }
/* This figure is a school's name, not a number — at 46px a long one ran
   to four lines and pushed the card past its neighbours. */
.stat-grid #latest-figure { font-size:21px; line-height:1.25; letter-spacing:-0.01em; }
.stat-grid .note { margin:10px 0 0; font-size:14px; color:var(--body); }
.stat-grid .note b { color:var(--ink); font-weight:600; }

/* ---------- page head (state / district / block) ---------- */
.crumb { font:500 11px/1.6 var(--mono); letter-spacing:.12em; text-transform:uppercase;
  color:var(--muted); margin-bottom:20px; }
.crumb a { color:var(--body); text-decoration:none; }
.crumb a:hover { color:var(--ink); }

.head { padding-bottom:40px; margin-bottom:44px; border-bottom:1.5px solid var(--line-strong); }
.head h1 { margin:0 0 18px; font:900 clamp(32px, 5.5vw, 54px)/1.05 var(--serif);
  letter-spacing:-0.02em; }
.head .hero-rate { margin:0; display:flex; align-items:baseline; gap:12px; flex-wrap:wrap; }
.head .hero-rate strong { font:700 clamp(40px, 7vw, 60px)/1 var(--mono);
  letter-spacing:-0.04em; }
.head .hero-rate > span { font:500 12px/1 var(--mono); letter-spacing:.14em;
  text-transform:uppercase; color:var(--muted); }
.head .sub { margin:14px 0 0; font-size:15px; color:var(--body); }
/* Above the baseline gets the accent; at or below it stays quiet. Colour is
   never the only carrier — the sentence itself says which it is. */
.head .cmp { display:inline-block; margin:16px 0 0; padding:6px 12px;
  font:500 12px/1 var(--mono); letter-spacing:.08em; text-transform:uppercase;
  background:var(--accent); color:#111214; }
.head .cmp.is-low { background:transparent; color:var(--muted);
  border:1px solid var(--rule); }

/* ---------- hero (index only) ----------
   Declared after .head deliberately: the index page's hero renders inside
   .head, and .head h1 / .hero h1 have identical specificity, so source order
   is what decides. Moving this above .head silently shrinks the hero. */
.hero { padding:26px 0 56px; }
.hero .kicker { display:flex; align-items:center; gap:9px; margin-bottom:30px; }
.hero .kicker .dot { width:6px; height:6px; border-radius:50%; background:var(--ink); }
.hero h1 { margin:0; font:700 clamp(30px, 4.6vw, 52px)/1.12 var(--serif);
  letter-spacing:-0.02em; }
.hero h1 em { font-style:italic; }
/* The three key words carry italic emphasis only. The accent block that
   used to sit behind them read as highlighter pen drawn over the headline,
   and at hero size three of them dominated the page. */
.hero h1 mark { background:none; color:inherit; font-style:italic; }
.hero /* One line under the headline, not the paragraph it used to be: tighter
   measure, and it sits close enough to read as part of the same block. */
.standfirst { margin:20px 0 0; max-width:46ch; font-size:16px; line-height:1.55;
  color:var(--muted); }
.hero .standfirst strong { color:var(--ink); font-weight:600; }
.hero .actions { display:flex; gap:14px; margin-top:40px; flex-wrap:wrap; }
/* Small type in a generous box. Uppercase mono with wide letterspacing
   made a short label occupy as much width as a sentence, so the buttons
   read as large and the words inside them as shouted. */
.btn { display:inline-block; padding:18px 34px; min-width:200px; text-align:center;
  font:500 15px/1.2 var(--sans); letter-spacing:0; text-transform:none;
  text-decoration:none; border:1.5px solid var(--line-strong); }
/* White with black type, inside the border .btn already carries. Written
   as tokens rather than #fff/#000 so the dark theme inverts with the rest
   of the page instead of punching a white block through it. */
.btn-primary { background:var(--panel); color:var(--ink); }
.btn-ghost { background:transparent; color:var(--ink); }
/* The one action the site is for, in the one saturated colour it owns.
   Ink on the accent, never paper: white on #e0651e measures 3.47:1 and
   fails AA at this size, while #111214 on it measures 5.40:1. */
/* Two classes, not one: .foot a paints every link in the footer and at
   (0,1,1) outranks a lone .btn-accent, which repainted the label in
   --body over the orange — 2.63:1, worse than the white this rule exists
   to avoid. .btn.btn-accent (0,2,0) wins wherever the button lands. */
/* White on the brand accent #e0651e measures 3.47:1 and fails AA at this
   size. The orange is darkened just far enough that white clears it —
   #c2540f is 4.60:1 — rather than dropping the white the button wants. */
.btn.btn-accent { background:#c2540f; color:#fff; }
.btn.btn-accent:hover { background:#a34308; color:#fff; }

/* ---------- filter ---------- */
#filter { width:100%; padding:13px 15px; margin-bottom:0; font:14px/1 var(--mono);
  color:var(--ink); background:var(--panel); border:1px solid var(--line);
  border-bottom:0; }
#filter::placeholder { color:var(--muted); letter-spacing:.06em; }
#filter:focus { outline:none; border-color:var(--line-strong); }

/* ---------- table ---------- */
table.stats { width:100%; border-collapse:collapse; border:1px solid var(--line); }
table.stats thead th { padding:13px 14px; text-align:left; background:var(--panel);
  border-bottom:1px solid var(--line-strong);
  font:500 10px/1 var(--mono); letter-spacing:.16em; text-transform:uppercase;
  color:var(--muted); font-weight:600; }
table.stats td { padding:15px 14px; border-bottom:1px solid var(--line);
  vertical-align:middle; }
table.stats tbody tr:last-child td { border-bottom:0; }
/* Whole-row accent on hover, the way the reference marks a ledger row —
   a highlighter drawn across the line, not a subtle tint. */
table.stats tbody tr:hover { background:var(--accent-soft); }
table.stats tbody tr:hover td, table.stats tbody tr:hover td.num,
table.stats tbody tr:hover td .rate-val, table.stats tbody tr:hover td.udise,
table.stats tbody tr:hover td.name a { color:#111214; }
table.stats tbody tr:hover td.rate .bar { background:#111214; }

table.stats td.num { text-align:right;
  font:500 14px/1 var(--mono); color:var(--body); }
/* A numeric header is still a header. It takes the alignment and nothing
   else, so it matches the first column instead of rendering larger and
   darker than it — the font and colour come from `thead th` above. */
table.stats th.num { text-align:right; }
/* Region names are monospace too: in a ledger the name is data, not prose,
   and the fixed advance keeps the column reading as a record. */
table.stats td.name a { color:var(--ink); text-decoration:none;
  font:500 14px/1.4 var(--mono); letter-spacing:-0.01em; }
table.stats td.name a:hover { text-decoration:underline; }
table.stats td.udise { font:12px/1 var(--mono); color:var(--muted); }

/* Rate cell. LENGTH is relative to the largest rate in this same table (see
   barWidth) so a page can be scanned — a 0-100% scale would render nearly
   every bar invisible, the national median being 4.7% against a 29.7% max.
   WEIGHT is absolute, against the national rate (see severityOf), so the
   same bar length never means two different things on two pages: Kerala's
   worst district (0.8%) fills its bar exactly as Meghalaya's (46.5%) fills
   its own. A monochrome intensity scale, like a choropleth legend. */
/* The grid lives on an inner span, never on the <td> itself: display:grid on
   a table cell drops it out of table layout, which visibly breaks the row
   borders around this column under border-collapse. */
table.stats td.rate { width:190px; }
table.stats td.rate .rate-wrap { display:grid; grid-template-columns:1fr auto;
  align-items:center; gap:14px; }
table.stats td.rate .bar { height:7px; width:var(--w); justify-self:start; }
table.stats td.rate .bar.is-high { background:var(--line-strong); }
table.stats td.rate .bar.is-mid  { background:var(--muted); }
table.stats td.rate .bar.is-low  { background:var(--rule); }
table.stats td.rate .rate-val { font:600 15px/1 var(--mono);
  font-variant-numeric:tabular-nums; color:var(--ink); }
table.stats td.rate .rate-val.is-low { color:var(--muted); }

/* Issue tag on block pages. */
.tag { display:inline-block; font:500 10px/1 var(--mono); letter-spacing:.1em;
  text-transform:uppercase; padding:5px 9px; white-space:nowrap;
  border:1px solid var(--rule); color:var(--body); }


/* ---------- footer ---------- */
.foot { margin-top:44px; padding-top:20px; border-top:1px solid var(--line-strong);
  font-size:13px; color:var(--muted); max-width:46em; }
.foot a { color:var(--body); }

/* ---------- atlas: the state map and the state table, as one unit ---------- */
/* The map answers "where" and the table answers "how many"; they are laid
   out together because either alone invites a wrong reading. Below 900px
   they stack, map first. */
/* The one section allowed out of the 1060px text column. Prose gets no
   better past a comfortable measure, but a map does — boxed into half a
   text column India was the smallest thing on a page that is mostly about
   India. No transform is used to centre it: a transformed ancestor would
   change the containing block for the sticky header inside the table. */
/* No rule of its own: .head already draws one directly above, at the
   page's width rather than this section's wider one. Two rules of two
   different lengths, stacked, is what that looked like. */
/* Page width, like everything else. It used to break out to 1320px, which
   made the map bigger and made every left edge and every rule on the page
   disagree with its neighbours. The map keeps most of that size by taking
   it from the table column beside it instead. */
/* The index breaks out past the page measure, so the rules that fence it
   break out with it: a section wider than its own delimiters reads as a
   mistake rather than as a feature. The neighbours give up their rule so
   there is exactly one line above and one below, each the index's width. */
.head:has(+ .atlas) { border-bottom:0; margin-bottom:0; padding-bottom:26px; }
.atlas { margin-top:0; padding:34px 0 38px;
  border-top:1.5px solid var(--line-strong);
  border-bottom:1.5px solid var(--line-strong); }
.atlas + .findmine { border-top:0; padding-top:0; margin-top:52px; }
.atlas-head { display:flex; justify-content:space-between; align-items:flex-end;
  gap:28px; margin-bottom:24px; }
/* Bodoni Moda, not Playfair: this is the one display-caps setting on
   the site, and Playfair's italic capitals are swashy — "BY STATE" grew
   curls. A didone keeps the reference's clean high-contrast caps. */
.atlas-title { margin:0; font:900 clamp(24px, 2.9vw, 36px)/1 'Bodoni Moda', var(--serif);
  letter-spacing:.005em; text-transform:uppercase; font-optical-sizing:auto; }
.atlas-title em { font-style:italic; font-weight:800; }
.atlas-lede { margin:0; max-width:36ch; font-size:14px; line-height:1.55;
  color:var(--muted); }
.atlas-grid { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,470px);
  gap:26px; align-items:start; }
/* No breakout. The index and the stat band sit on the same measure as the
   hero above them: one section wider than the rest read as stretched, and
   the map gains its size from height (see svg.india) rather than from
   width taken off the page's own edge. The card sizes to its ten states
   rather than to the map's height — see .atlas-grid align-items. */
.atlas-table { min-width:0; display:flex; }
.atlas-table .ledger { display:flex; flex-direction:column; flex:1; min-width:0; }

/* The reference card's anatomy: content inset from the card edge, the
   hairline under the head only, roomy rows whose rank sits at the same
   size as the name, and each figure wearing its own small label — no
   header row to look back at. */
.atlas-table .ledger { padding:0 20px; }
.atlas-table .ledger-head { padding:17px 0 12px; }
.atlas-table .ledger-head h2 { font-size:16px; }
.atlas-table .ledger-controls { padding:12px 0 8px; border-bottom:0; }
.atlas-table .sortby { gap:10px; }
.atlas-table .sortby button { height:27px; padding:0 11px; font-size:10px; }
.atlas-table .sort-label { font-size:9px; }
.atlas-table table.stats.inline td { padding:9px 0; }
.atlas-table table.stats.inline td.rank { width:34px; padding-right:0;
  text-align:left; font:500 10.5px/1.4 var(--mono); color:var(--muted); }
.atlas-table table.stats.inline td.name { padding-left:8px; }
.atlas-table table.stats.inline td.name a { font:600 11px/1.4 var(--mono); }
.atlas-table table.stats.inline td.stat { text-align:right; white-space:nowrap;
  padding-left:13px; }
.atlas-table table.stats.inline td.stat b { font:600 11px/1 var(--mono);
  font-variant-numeric:tabular-nums slashed-zero;
  font-feature-settings:'zero' 1,'tnum' 1; }
.atlas-table table.stats.inline td.stat .lab { margin-left:6px;
  font:500 8.5px/1 var(--mono); letter-spacing:.08em; text-transform:uppercase;
  color:var(--muted); }
.atlas-table table.stats.inline tbody tr:last-child td { border-bottom:0; }
.atlas-table table.stats td { padding:11px 12px; }
.atlas-table table.stats thead th { padding:11px 12px; }
.atlas-table table.stats td.name a { font-size:13px; }
.atlas-table table.stats td.num { font-size:13px; }
.atlas-table table.stats td.rate { width:132px; }
.atlas-table table.stats td.rate .rate-wrap { gap:10px; }
.atlas-table table.stats td.rate .rate-val { font-size:13px; }
.atlas-table #filter { height:34px; padding:0 12px; font:13px/1 var(--mono); }
.atlas-map { margin:0; min-width:0; background:var(--map-panel);
  padding:28px 28px 20px; display:flex; flex-direction:column; }
.atlas-map svg.india { flex:1; min-height:0; }
.map-foot { display:flex; align-items:center; gap:16px; margin-top:16px; }
.legend .lo, .legend .hi { white-space:nowrap; }
/* Sized by HEIGHT, not width. The outline is a 10:11 portrait, so filling
   the widened column would make it ~950px tall and tower over the list
   beside it. Driving from height keeps the two columns roughly level and
   still leaves the map far larger than the half-text-column it was.
   width:auto lets the intrinsic aspect ratio from the viewBox pick the
   width, so it is never stretched. */
.atlas-map svg.india { height:min(78vh, 900px); width:auto; max-width:100%;
  display:block; margin-inline:auto; }

/* Five shades, cut at multiples of the national rate (see BIN_MULTIPLES in
   scripts/lib/choropleth.mjs). Absolute, not ranked: b3 means the same
   thing here as it would on any other map we draw. */
:root {
  /* Measured against the map panel (#f2f1ec): b0 sits at 1.36:1 and
     every adjacent step holds 1.37:1 or better, so five bins survive a
     phone screen in daylight. Neutral greys, not warm ones — the shade
     axis carries data, and hue would only editorialise it. */
  --b0:#d2d2d0; --b1:#b7b7b5; --b2:#8e8e8c; --b3:#605f5d; --b4:#3a3937;
  --b-nodata:#ffffff;
  --map-panel:#f0f0ee;
}
svg.india .st { stroke:var(--bg); stroke-width:1.1; vector-effect:non-scaling-stroke; }
svg.india .b0 { fill:var(--b0); }
svg.india .b1 { fill:var(--b1); }
svg.india .b2 { fill:var(--b2); }
svg.india .b3 { fill:var(--b3); }
svg.india .b4 { fill:var(--b4); }
/* A state we have no figures for must never read as a state with nothing
   wrong, so no-data gets its own near-blank fill, outside the ramp. */
svg.india .nodata { fill:var(--b-nodata); }
svg.india a { cursor:pointer; }
svg.india a:hover .st, svg.india a:focus-visible .st { fill:var(--accent); }
svg.india a:focus-visible { outline:none; }

.legend { display:flex; align-items:center; gap:7px;
  font:500 10.5px/1 var(--mono); letter-spacing:0.12em; text-transform:uppercase;
  color:var(--muted); }
.legend .sw { width:28px; height:11px; display:block; }
.legend .sw.b0 { background:var(--b0); }
.legend .sw.b1 { background:var(--b1); }
.legend .sw.b2 { background:var(--b2); }
.legend .sw.b3 { background:var(--b3); }
.legend .sw.b4 { background:var(--b4); }
.atlas-map figcaption { margin-top:12px; max-width:58ch;
  font:400 12px/1.6 var(--sans); color:var(--muted); }

/* ---------- report call-out (index only) ---------- */
.findmine { margin-top:52px; padding-top:26px; border-top:1.5px solid var(--line-strong); }
.findmine h2 { margin:0 0 12px; font:900 30px/1.1 var(--serif); letter-spacing:-0.02em; }
.findmine p { margin:0 0 20px; max-width:56ch; color:var(--body); }
.findmine .actions { margin:0; }

/* The state list scrolls inside its own panel so the map stays beside it.
   32 rows are taller than the map, and a reader comparing a state's shading
   to its figures should not have to scroll the map off screen to do it.
   Every row stays in the DOM, so this costs nothing for crawlers. */
@media (min-width:901px) {
  .atlas-table { max-height:78vh; overflow-y:auto; overscroll-behavior:contain;
    border:1px solid var(--line); }
  .atlas-table table.stats { border:0; }
  /* An explicit height, not an inherited one: the sticky header below is
     offset by exactly this, and a guessed offset shows a sliver of moving
     rows above a header that is supposed to be pinned. */
  .atlas-table #filter { position:sticky; top:0; z-index:3; height:44px;
    padding-block:0; border:0; border-bottom:1px solid var(--line); }
  .atlas-table table.stats thead th { position:sticky; top:0; z-index:2;
    /* A sticky cell silently drops its border under border-collapse in
       Chrome; an inset shadow paints the same rule and survives. */
    border-bottom:0; box-shadow:inset 0 -1px 0 var(--line-strong); }
  /* The filter ships hidden and is unhidden by script. With JavaScript off
     it never takes up space, so the header must pin to the very top
     instead of leaving a 44px gap where the input would have been. */
  .atlas-table:has(#filter:not([hidden])) table.stats thead th { top:44px; }
}

@media (max-width:900px) {
  .atlas-grid { grid-template-columns:minmax(0,1fr); gap:34px; }
  /* The card's desktop density is a mouse target; a thumb needs more.
     Only the controls grow — the rows stay a ledger. */
  .atlas-table .sortby button { height:40px; padding:0 16px; font-size:12px; }
  .atlas-head { flex-direction:column; align-items:flex-start; gap:10px;
    margin-bottom:18px; }
  .atlas-map { padding:18px 16px 14px; }
  /* Stacked, width is the scarce dimension again, so hand it back. */
  .atlas-map svg.india { height:auto; width:100%; max-height:66vh; flex:none; }
}

@media (max-width:640px) {
  body.browse { padding:20px 16px 48px; }
  .stat-grid { grid-template-columns:1fr; }
  .stat-grid > div { border-right:0; border-bottom:1px solid var(--line-strong); }
  .stat-grid > div:last-child { border-bottom:0; }
  table.stats thead th, table.stats td { padding:12px 10px; }
  /* Total-schools is the least load-bearing column; the rate cell has to stay
     wide enough for the bar to still say something. */
  table.stats:not(.schools) th:nth-child(3),
  table.stats:not(.schools) td:nth-child(3) { display:none; }
  table.stats td.rate { width:128px; gap:10px; }
  /* The register stops being a table on a phone. Four columns in 360px
     gives the record line about twelve characters of measure, which is a
     column of single words falling down the screen. Each school becomes a
     block instead: who it is on one line, what its record shows under it.
     Headcounts are the one thing dropped — they are context, and they are
     on the school's own page.

     The rows are laid out with grid, so the pager must clear display
     rather than set 'table-row'; see FILTER_SCRIPT in render.mjs. */
  table.stats.schools thead { display:none; }
  table.stats.schools, table.stats.schools tbody { display:block; }
  table.stats.schools tbody tr { display:grid; grid-template-columns:1fr auto;
    align-items:baseline; gap:2px 12px; padding:12px 14px;
    border-bottom:1px solid var(--line); }
  table.stats.schools tbody tr:last-child { border-bottom:0; }
  table.stats.schools tbody td { display:block; padding:0; border:0; }
  table.stats.schools td.name { grid-column:1; }
  table.stats.schools td.also { grid-column:1 / -1; margin-top:6px;
    font-size:12.5px; max-width:none; }
  table.stats.schools td.num { display:none; }
  table.stats.schools td.name .sub { font-size:11px; }
}

/* Every figure on the site is monospace with a SLASHED zero and tabular
   widths. The slash is what stops 0 reading as O at label sizes, and it is
   the detail that makes a data table look like a record rather than prose.
   Applied to one class so it can never drift between the hero, the stat
   panels and the table. */
.tnum, .stat-grid .figure, .head .hero-rate strong,
table.stats td.num, table.stats th.num, table.stats td.rate .rate-val,
table.stats td.udise, .crumb, .label {
  font-variant-numeric:tabular-nums slashed-zero;
  font-feature-settings:'zero' 1, 'tnum' 1;
}

/* ---------- headline figures ---------- */
/* Each figure gets a heading in ordinary words. An earlier pass removed
   these because they read as jargon ("COUNTED HONESTLY"), but a bare
   number with a trailing sentence is harder to read, not easier: the
   reader meets the number before learning what it counts. The fix was
   never fewer words, it was words that say something. */
.stat-grid .stat-head {
  margin:0 0 10px; padding-bottom:10px; border-bottom:1px solid var(--line);
  font:600 13px/1.35 var(--sans); letter-spacing:0; text-transform:none;
  color:var(--body); }

/* A broader column heading has to say what it actually counted, next to
   the numbers rather than only in prose further up the page. */
.table-note { margin:12px 0 0; max-width:70ch;
  font:400 12px/1.6 var(--sans); color:var(--muted); }
/* Beside the map the table sits in a 420px column, where a 70ch measure
   overflows the page. The note wraps to its column instead. */
.atlas-table .table-note { max-width:100%; }

/* ---------- theme toggle ---------- */
.theme-toggle { display:inline-flex; align-items:center; gap:6px;
  padding:6px 10px; cursor:pointer; color:var(--muted);
  background:transparent; border:1px solid var(--line);
  font:600 10px/1 var(--mono); letter-spacing:.14em; text-transform:uppercase; }
.theme-toggle:hover { color:var(--ink); border-color:var(--accent); background:var(--accent-soft); }
.theme-toggle svg { width:13px; height:13px; }
/* One button, two labels: the stylesheet shows whichever matches the theme
   in force, so the script only has to flip an attribute on <html>. */
.theme-toggle .t-dark { display:inline-flex; align-items:center; gap:6px; }
.theme-toggle .t-light { display:none; align-items:center; gap:6px; }
:root[data-theme="dark"] .theme-toggle .t-dark { display:none; }
:root[data-theme="dark"] .theme-toggle .t-light { display:inline-flex; }
.masthead .mast-right { display:flex; align-items:center; gap:12px; flex-wrap:wrap; }

/* ---------- what else these schools report ---------- */
.issues, .accountable { margin-top:48px; padding-top:26px;
  border-top:1.5px solid var(--line-strong); }
.issues h2, .accountable h2 { margin:0 0 10px; font:900 28px/1.15 var(--serif);
  letter-spacing:-0.02em; }
.issues > .note, .accountable > .note { margin:0 0 20px; max-width:64ch;
  font:400 13px/1.6 var(--sans); color:var(--muted); }
.issue-list { list-style:none; margin:0; padding:0;
  display:grid; grid-template-columns:repeat(auto-fill, minmax(280px, 1fr)); gap:0; }
.issue-list li { display:flex; align-items:baseline; gap:12px;
  padding:12px 14px; border:1px solid var(--line); margin:-1px 0 0 -1px; }
.issue-list .n { font:700 17px/1 var(--mono); min-width:4.5em; text-align:right;
  font-variant-numeric:tabular-nums slashed-zero; font-feature-settings:'zero' 1,'tnum' 1; }
.issue-list .l { font:400 13px/1.35 var(--sans); color:var(--body); }

/* ---------- who answers ---------- */
.who-list { list-style:none; margin:0; padding:0; }
.who-list li { display:grid; grid-template-columns:auto 1fr auto; gap:2px 14px;
  align-items:baseline; padding:14px 16px; border:1px solid var(--line); margin-top:-1px; }

/* A face-shaped slot, filled with initials.
   MyNeta holds an affidavit photo for most members, but a card that stays
   blank until 4,181 of them are fetched and hosted is a card that looks
   broken today. This holds the exact space a portrait will take, so the
   photo can drop in later without the row being redesigned around it. */
.who-list .face { grid-column:1; grid-row:1 / span 2; align-self:center;
  width:42px; height:42px; border-radius:50%; display:grid; place-items:center;
  background:var(--accent-soft); color:var(--accent);
  font:700 14px/1 var(--mono); letter-spacing:.04em; }
:root[data-theme="dark"] .who-list .face { color:#e8823f; }
.who-list li:hover .face { background:var(--accent); color:#111214; }

.who-list .who { grid-column:2; font:600 16px/1.3 var(--sans); }
/* The party is a fact about the seat's holder, not a heading — a quiet
   chip reads as an attribution where uppercase mono read as a shout. */
.who-list .party { font:600 10px/1 var(--mono); letter-spacing:.1em;
  color:var(--body); background:var(--bg); border:1px solid var(--rule);
  padding:4px 6px; margin-left:8px; vertical-align:1px; white-space:nowrap; }
.who-list .seat { grid-column:2; font:400 12.5px/1.5 var(--mono); color:var(--muted); }
.who-list .acts { grid-column:3; grid-row:1 / span 2; align-self:center;
  display:flex; gap:8px; align-items:center; }

/* The two questions are the point of the panel; the record is the receipt.
   So the questions get the logo — recognised at a glance, where a word has
   to be read — and the receipt keeps its label. */
.who-list .ico { display:grid; place-items:center; width:38px; height:38px;
  color:var(--ink); border:1px solid var(--line-strong); text-decoration:none; }
.who-list .ico svg { width:16px; height:16px; display:block; }
.who-list .src { font:600 10px/1 var(--mono); letter-spacing:.14em;
  text-transform:uppercase; text-decoration:none; padding:7px 10px;
  white-space:nowrap; color:var(--muted); border:1px solid var(--line); }
.who-list .ico:hover, .who-list .src:hover { background:var(--accent-soft);
  border-color:var(--accent); color:var(--ink); }
@media (max-width:700px) {
  /* Two columns, not one: .face is pinned to column 1 / rows 1-2, so a
     single-column grid had nowhere to auto-place the name and the seat
     and pushed them into an implicit second column, 21px off the right
     of a 390px screen. The face keeps its slot; everything else stacks
     beside it. */
  .who-list li { grid-template-columns:auto minmax(0,1fr); }
  .who-list .who, .who-list .seat { grid-column:2; }
  .who-list .acts { grid-column:1 / -1; grid-row:auto; margin-top:10px; flex-wrap:wrap; }
}

/* ---------- the school register ---------- */
/* Four columns, because the row carries four different KINDS of fact and
   they were all being said the same way: up to twelve uppercase mono pills
   in a single cell, wrapping three lines deep, the same four pills
   repeating down every row. Uppercase mono at .1em tracking is the site's
   LABEL voice — used twelve times a row it stops labelling anything and
   just shouts. Exactly one pill survives per row now, on the one fact the
   page exists for; everything else drops to its ordinary register. */

/* Name and code are one identity, so they are one cell. As a separate
   column the code took a fifth of the table's width to say something
   nobody reads across — only down, when checking one school. */
table.stats.schools td.name { line-height:1.35; }
table.stats.schools td.name a { display:block; }
/* The row used to caption itself with the UDISE code alone — a database
   key, in a column a parent is scanning for their child's school. Classes
   and the village are what a person recognises a school by; the code stays
   because the report form, the QR codes on school walls and any check
   against UDISE+ are keyed on it, but labelled and last. */
table.stats.schools td.name .sub { display:block; margin-top:4px;
  font:400 12px/1.4 var(--sans); color:var(--muted); }
table.stats.schools tbody tr:hover td.name .sub { color:#111214; }

/* Everything else the record says, as one line of ordinary sentence type.
   Same words as the pills carried — this is a change of voice, not of
   content: secondary findings should read like a footnote to the row, and
   a footnote is not set in caps. */
table.stats.schools td.also { font:400 13px/1.5 var(--sans); color:var(--body);
  max-width:38em; }
table.stats.schools tbody tr:hover td.also { color:#111214; }
.nil { color:var(--muted); font-style:italic; }
table.stats.schools tbody tr:hover .nil { color:#111214; }

/* Size is a number, so it sits in number columns — tabular, right-aligned,
   scannable down. As a dashed pill mid-sentence it was neither. */
table.stats.schools td.num { white-space:nowrap; }

/* ---------- pagination ---------- */
/* Ten rows at a time. Every row stays in the DOM — the script only hides
   them — so a crawler still sees the whole list and a reader without
   JavaScript gets it too. */
.pager { display:flex; align-items:center; justify-content:space-between; gap:12px;
  margin-top:-1px; padding:12px 14px; border:1px solid var(--line); }
.pager button { font:600 11px/1 var(--mono); letter-spacing:.12em; text-transform:uppercase;
  color:var(--ink); background:transparent; border:1px solid var(--line);
  padding:9px 13px; cursor:pointer; }
.pager button:hover:not(:disabled) { background:var(--accent-soft); border-color:var(--accent); }
.pager button:disabled { color:var(--muted); cursor:default; opacity:.5; }
.pager .pager-status { font:500 12px/1 var(--mono); color:var(--muted);
  font-variant-numeric:tabular-nums slashed-zero; font-feature-settings:'zero' 1,'tnum' 1; }

/* ---------- the ledger panel ---------- */
.ledger { border:1px solid var(--line); background:var(--panel); }
.ledger-head { display:flex; align-items:baseline; justify-content:space-between;
  gap:16px; padding:16px 18px; border-bottom:1px solid var(--line); }
.ledger-head h2 { margin:0; font:700 17px/1 var(--serif); letter-spacing:.01em;
  text-transform:uppercase; }
.ledger-note { margin:0; padding:10px 16px 0; max-width:70ch;
  font:400 12.5px/1.55 var(--sans); color:var(--muted); }
.ledger-controls { display:flex; align-items:center; gap:12px; flex-wrap:wrap;
  padding:12px 18px; border-bottom:1px solid var(--line); }
.sortby { display:flex; align-items:center; gap:8px; }
.sort-label { font:500 10px/1 var(--mono); letter-spacing:.14em;
  text-transform:uppercase; color:var(--muted); }
.sortby button { padding:0 12px; height:34px; cursor:pointer; background:transparent;
  border:1px solid var(--line); color:var(--body);
  font:600 11px/1 var(--mono); letter-spacing:.06em; }
.sortby button.is-on { background:var(--ink); border-color:var(--ink); color:var(--bg); }
.sortby button:hover:not(.is-on) { border-color:var(--accent); color:var(--accent); }
.ledger #filter { flex:1 1 180px; width:auto; border:1px solid var(--line);
  height:34px; padding:0 12px; font:12px/1 var(--mono); }
.ledger table.stats { border:0; }
.ledger .pager { border:0; border-top:1px solid var(--line); }
.ledger .table-note { padding:0 18px 16px; }

/* Rank sits with the row it numbers, quiet enough not to compete with it.
   Width and alignment are shared; the 12px type is the BODY cell's only —
   th.rank out-specifies `thead th`, so naming it in the font rule made the
   RANK heading render two points larger than the headings beside it. */
table.stats td.rank, table.stats th.rank { width:46px; padding-right:0;
  text-align:right; }
table.stats td.rank { font:500 12px/1 var(--mono); color:var(--muted);
  font-variant-numeric:tabular-nums slashed-zero; font-feature-settings:'zero' 1,'tnum' 1; }
table.stats tbody tr:hover td.rank { color:#111214; }
/* The whole row is a target once the script is running. */
table.stats tbody tr[data-name] { cursor:pointer; }

/* ---------- questions ---------- */
.faq { margin-top:52px; padding-top:26px; border-top:1.5px solid var(--line-strong); }
.faq h2 { margin:0 0 22px; font:900 34px/1.05 var(--serif); letter-spacing:-0.02em; }
.faq-item { border-bottom:1px solid var(--line); }
.faq-item summary { display:flex; align-items:center; justify-content:space-between;
  gap:16px; padding:17px 2px; cursor:pointer; list-style:none;
  font:600 15.5px/1.4 var(--sans); }
.faq-item summary::-webkit-details-marker { display:none; }
.faq-item summary::after { content:'+'; font:400 20px/1 var(--mono); color:var(--muted); }
.faq-item[open] summary::after { content:'−'; }
.faq-item summary:hover { color:var(--body); }
.faq-body { padding:0 2px 18px; max-width:68ch; }
.faq-body p { margin:0; font-size:14.5px; line-height:1.65; color:var(--body); }

/* ---------- closing band ---------- */
.closer { margin-top:52px; padding:44px 40px; background:var(--ink); color:var(--bg); }
.closer h2 { margin:0 0 14px; font:900 36px/1.1 var(--serif); letter-spacing:-0.02em; }
.closer p { margin:0 0 22px; max-width:52ch; color:rgba(250,249,245,0.72); }
.closer .btn-accent { display:inline-block; padding:15px 22px;
  background:var(--accent); color:#111214; border:1px solid var(--accent);
  font:600 12px/1 var(--mono); letter-spacing:.12em; text-transform:uppercase;
  text-decoration:none; }
.closer .btn-accent:hover { background:transparent; color:var(--accent); }
@media (max-width:640px) {
  .closer { padding:32px 22px; }
  .closer h2 { font-size:28px; }
}

/* Long column headings stacked three words deep on a phone. Both labels
   ship; the stylesheet picks one, so no script is involved and a crawler
   still reads the full wording. */
table.stats th .sm { display:none; }
@media (max-width:640px) {
  table.stats th .lg { display:none; }
  table.stats th .sm { display:inline; }

  /* Everything a notch tighter: ten rows should be scannable in one
     screen, not four. */
  .ledger-head { padding:13px 14px; }
  .ledger-head h2 { font-size:15px; }
  .ledger-controls { padding:10px 14px; gap:8px; }
  .sortby button { padding:7px 10px; font-size:10.5px; }
  .ledger #filter { flex-basis:100%; padding:10px 12px; font-size:13px; }

  table.stats thead th { padding:9px 10px; font-size:9.5px; letter-spacing:.1em; }
  table.stats td { padding:10px; }
  table.stats td.rank, table.stats th.rank { width:30px; font-size:11px; }
  table.stats td.name a { font-size:13px; }
  table.stats td.num { font-size:12.5px; }
  table.stats td.rate { width:74px; }
  table.stats td.rate .rate-val { font-size:12.5px; }
  /* The bar and the figure say the same thing; on a narrow screen the
     figure is the one that survives. */
  table.stats td.rate .bar { display:none; }
  table.stats td.rate .rate-wrap { grid-template-columns:auto; }
  .table-note { padding:0 14px 14px; font-size:11.5px; }
  .pager { padding:10px 12px; }
  .pager button { padding:8px 10px; font-size:10px; }
}

/* No data is a hatch, not a paler tone. As a tone it measured 1.09:1
   against the lightest bin — invisible — so an unmeasured state looked
   exactly like a state doing well. */
svg.india .nodata { fill:var(--b-nodata); }

/* Only the worst few are named; the rest are a tap away. */
svg.india .india-label { font:600 15px/1 var(--sans); fill:var(--bg);
  paint-order:stroke; stroke:rgba(17,18,20,0.55); stroke-width:3px;
  pointer-events:none; letter-spacing:-0.01em; }

/* Hovering either view marks the other. */
@media (hover:hover) {
  svg.india .st.is-linked { fill:var(--accent); }
}
table.stats tbody tr.is-linked { background:var(--accent-soft); }
table.stats tbody tr.is-linked td, table.stats tbody tr.is-linked td.name a,
table.stats tbody tr.is-linked td .rate-val { color:#111214; }
@media (max-width:640px) { svg.india .india-label { font-size:19px; } }

/* ---------- live reports ---------- */
/* Hidden until something has actually been approved: an empty "no reports
   yet" panel on the front page advertises that nobody has used this. */
.live { margin-top:52px; padding-top:26px; border-top:1.5px solid var(--line-strong); }
.live-head { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,44ch);
  gap:24px; align-items:start; margin-bottom:20px; }
.live-head h2 { margin:0; font:900 38px/1.05 var(--serif); letter-spacing:-0.02em; }
.live-head h2 em { font-style:italic; }
.live-head p { margin:0; font-size:14px; line-height:1.6; color:var(--muted); }
@media (max-width:760px) {
  .live-head { grid-template-columns:minmax(0,1fr); gap:10px; }
  .live-head h2 { font-size:30px; }
}

/* Map header, matching the ledger's beside it. */
.legend .sw-nodata { background:var(--b-nodata); border:1px solid var(--rule);
  background-image:repeating-linear-gradient(45deg, var(--rule) 0 1.5px, transparent 1.5px 5px); }
.legend .sw-nodata { margin-left:14px; }

/* ---------- headline figures ---------- */
/* Label, rule, figure, detail — the order a reader needs them in. The
   label was removed once and put back: a bare number makes the reader
   meet the figure before learning what it counts. */
.stat-grid .stat-label { display:block; margin:0 0 10px; padding-bottom:10px;
  border-bottom:1px solid var(--line);
  font:500 10.5px/1 var(--mono); letter-spacing:.14em; text-transform:uppercase;
  color:var(--muted); }
.stat-grid .figure { letter-spacing:-0.03em; }
.stat-mini { display:flex; gap:26px; margin:16px 0 0; }
.stat-mini > div { margin:0; }
.stat-mini dt { margin:0; font:600 22px/1 var(--sans);
  font-variant-numeric:tabular-nums slashed-zero; font-feature-settings:'zero' 1,'tnum' 1; }
.stat-mini dd { margin:4px 0 0; font-size:11.5px; line-height:1.3; color:var(--muted); }
/* The live figures start as placeholders and are filled if reports exist;
   an em dash is not a number, so it should not be sized like one. */
#latest-figure { font-size:26px; line-height:1.2; letter-spacing:0; }

/* Space between the major sections, set once. They were each carrying
   their own margin against a tight baseline, so the page read as one
   block rather than as parts a reader can rest between. */
.findmine, .live, .faq { margin-top:72px; }
/* The index draws its own rules now (see .atlas above), so it sets its own
   spacing there and must not be given the 72px the other sections take —
   that margin plus .head's padding left 128px of blank paper between the
   stat boxes and the rule. */
.closer { margin-top:72px; padding:56px 48px; }
.foot { margin-top:64px; padding-top:26px; }
@media (max-width:760px) {
  .findmine, .live, .faq, .closer { margin-top:44px; }
  .atlas { padding:22px 0 26px; }
  .stat-grid > div { min-height:0; padding:22px 20px 26px; }
  .hero { padding:16px 0 34px; }
  .head { padding-bottom:26px; margin-bottom:28px; }
}

/* The bar spans the window; the wordmark inside it stays on the page's
   own measure, so it lines up with everything below. */
.mast-bar { border-bottom:1.5px solid var(--line-strong); background:var(--bg); }
.mast-bar .masthead { max-width:1200px; margin:0 auto;
  padding:18px 24px; border-bottom:0; }
/* Everything below the bar keeps the page's measure. */
.page { max-width:1200px; margin:0 auto; padding:34px 24px 0; }

/* ---------- school finder ---------- */
/* The headline says "Find a school", so the page should let you. Browsing
   state to district to block is four clicks to a name you already knew. */
.finder { position:relative; margin-top:34px; max-width:560px; }
.finder input { width:100%; padding:17px 18px; background:var(--panel);
  border:1.5px solid var(--line-strong); color:var(--ink);
  font:400 16px/1.2 var(--sans); }
.finder input::placeholder { color:var(--muted); }
.finder input:focus { outline:none; box-shadow:inset 0 0 0 1px var(--line-strong); }
.finder-hits { position:absolute; z-index:5; left:0; right:0; top:calc(100% - 1px);
  background:var(--panel); border:1.5px solid var(--line-strong);
  max-height:60vh; overflow-y:auto; }
.finder-hit { display:block; padding:12px 16px; text-decoration:none; color:inherit;
  border-bottom:1px solid var(--line); }
.finder-hit:last-child { border-bottom:0; }
.finder-hit:hover { background:var(--accent-soft); }
.finder-hit .h-name { display:block; font-weight:600; font-size:14.5px; }
.finder-hit .h-where { display:block; margin-top:3px;
  font:500 11.5px/1.3 var(--mono); color:var(--muted); text-transform:capitalize; }
.finder-none { margin:0; padding:14px 16px; font-size:13.5px; line-height:1.55;
  color:var(--muted); }
.finder-none a { color:var(--ink); }

/* The search had a placeholder and nothing else, so it read as a stray
   box. The name belongs here — not on the map, which shows states. */
.finder-label { display:flex; align-items:baseline; justify-content:space-between;
  gap:14px; flex-wrap:wrap; margin-bottom:10px; cursor:pointer;
  font:500 10.5px/1 var(--mono); letter-spacing:.14em; text-transform:uppercase;
  color:var(--muted); }
.finder-label span { text-transform:none; letter-spacing:0;
  font:400 12.5px/1.3 var(--sans); }

/* Beside the map the ledger sits in a 340px column, so "Schools with
   issues" stacked three words deep whatever the window width — the phone
   breakpoint was the wrong test. The short label belongs to the narrow
   COLUMN, not to a narrow screen. */
.atlas-table table.stats th .lg { display:none; }
.atlas-table table.stats th .sm { display:inline; }

/* Reports as a card grid, three up — the bribes.fyi proportions: at the
   1200px page measure each card lands near 390px wide, small enough to
   take in whole, big enough for the photo to read. */
.live-list { display:grid; grid-template-columns:repeat(3, minmax(0,1fr));
  gap:18px; list-style:none; margin:0; padding:0; border:0;
  /* Rows sized alike, so a report covering five things does not stand
     half a card taller than one covering one. */
  grid-auto-rows:1fr; }
.live-list li { margin:0; padding:0; border:0; }
.live-list a, .live-list .norow { display:block; height:100%; padding:16px;
  border:1px solid var(--line); background:var(--panel);
  color:inherit; text-decoration:none; }
.live-list a:hover { border-color:var(--line-strong); }

.r-head { display:grid; grid-template-columns:auto 1fr; gap:10px;
  align-items:start; }
.r-badge { display:flex; align-items:center; justify-content:center;
  width:30px; height:30px; background:var(--panel-2, #f2f0ea);
  font:600 13px/1 var(--mono); color:var(--body); }
.r-who { display:flex; flex-direction:column; gap:3px; min-width:0; }
.r-who b { font:600 15px/1.25 var(--sans); }
.r-who span { font:500 12px/1.35 var(--mono); color:var(--muted);
  overflow:hidden; text-overflow:ellipsis; }
/* Every issue the report covers, each beside what was found there. A
   lone "LOCKED" chip in the header had nothing to attach to once a
   report could carry three different things. */
.r-issues { display:flex; flex-direction:column; gap:5px; margin-top:11px; }
.r-issue { display:flex; align-items:baseline; gap:8px; }
.r-issue b { font:600 13px/1.3 var(--sans); }
.r-issue > span { font:500 10px/1 var(--mono); letter-spacing:.09em;
  text-transform:uppercase; color:var(--ink); background:var(--accent-soft);
  padding:5px 7px; white-space:nowrap; }

.r-shot { display:block; width:100%; aspect-ratio:16/10; object-fit:cover;
  margin:12px 0 0; background:var(--panel-2, #f2f0ea);
  border:1px solid var(--line); }
.r-note { margin:12px 0 0; padding-top:12px; border-top:1px dashed var(--line);
  font:italic 400 13.5px/1.5 var(--sans); color:var(--body); }
.r-foot { margin-top:12px; padding-top:10px; border-top:1px solid var(--line);
  font:500 10.5px/1 var(--mono); letter-spacing:.08em; text-transform:uppercase;
  color:var(--muted); }
.r-ok { color:var(--ink); }

@media (max-width:1020px) {
  .live-list { grid-template-columns:repeat(2, minmax(0,1fr)); }
}
@media (max-width:700px) {
  .live-list { grid-template-columns:minmax(0,1fr); gap:12px; }
  .r-shot { aspect-ratio:4/3; }
}

.live-note { margin:14px 0 0; max-width:62ch; font:400 12px/1.6 var(--sans);
  color:var(--muted); }

/* ---------- map hover card ---------- */
.atlas-map { position:relative; }
.map-tip { position:absolute; z-index:6; width:240px; padding:14px 16px;
  background:var(--ink); color:var(--bg); pointer-events:none; }
.map-tip .t-name { font:600 15px/1.2 var(--mono); padding-bottom:10px;
  margin-bottom:10px; border-bottom:1px solid rgba(250,249,245,0.22); }
.map-tip .t-row { display:flex; align-items:baseline; justify-content:space-between;
  gap:14px; padding:3px 0; }
.map-tip .t-row span { font:500 10px/1.3 var(--mono); letter-spacing:.1em;
  text-transform:uppercase; color:rgba(250,249,245,0.6); }
.map-tip .t-row b { font:600 13px/1 var(--mono);
  font-variant-numeric:tabular-nums slashed-zero; font-feature-settings:'zero' 1,'tnum' 1; }
.map-tip .t-row b.t-big { font-size:17px; color:var(--accent); }
.map-tip .t-also { margin-top:10px; padding-top:10px;
  border-top:1px solid rgba(250,249,245,0.22); }
.map-tip .t-also span { display:block; font:500 10px/1.3 var(--mono);
  letter-spacing:.1em; text-transform:uppercase; color:rgba(250,249,245,0.6); }
.map-tip .t-also b { display:block; margin-top:4px; font:400 12.5px/1.4 var(--sans); }
@media (hover:none) { .map-tip { display:none; } }

/* The language toggle sits in the masthead, styled as quietly as the tag
   beside it: a reader who needs it finds it; one who does not never
   notices it. */
.masthead .lang { font:600 11px/1 var(--mono); letter-spacing:.1em;
  color:var(--ink); text-decoration:none; border:1px solid var(--line);
  padding:7px 10px; margin-right:10px; }
.masthead .lang:hover { border-color:var(--accent); background:var(--accent-soft); }

/* ---------- the national register ---------- */
/* Every other table on the site is a slice the server already chose. This
   one is the whole record, 78,744 rows, and the reader chooses the slice —
   so the controls are the page, and they get room to say what they do. */
.register .reg-controls { flex-direction:column; align-items:stretch; gap:12px; }
.reg-line { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.reg-line .sort-label { flex:0 0 auto; }

/* A chip is pressed or it is not; there is no third state, so it carries
   the marker-pen accent when it is on and nothing at all when it is off. */
.chips { display:flex; flex-wrap:wrap; gap:6px; }
.chips button { padding:7px 10px; cursor:pointer; background:transparent;
  border:1px solid var(--line); color:var(--body);
  font:500 10.5px/1 var(--mono); letter-spacing:.1em; text-transform:uppercase; }
.chips button:hover { border-color:var(--accent); color:var(--ink); }
.chips button.is-on { background:var(--accent); color:#111214; border-color:transparent; }

#reg-state { flex:0 0 auto; max-width:230px; padding:9px 11px; cursor:pointer;
  font:500 12px/1 var(--mono); color:var(--ink);
  background:var(--panel); border:1px solid var(--line); }
#reg-state:focus { outline:none; border-color:var(--line-strong); }
.register #filter { flex:1 1 200px; }
.reg-clear { flex:0 0 auto; padding:9px 12px; cursor:pointer; background:transparent;
  border:1px solid var(--line); color:var(--muted);
  font:600 10px/1 var(--mono); letter-spacing:.14em; text-transform:uppercase; }
.reg-clear:hover { border-color:var(--accent); color:var(--ink); }

/* The count is the answer to whatever the reader just asked, so it sits
   between the controls and the rows rather than under them. */
.reg-count { margin:0; padding:12px 18px; border-bottom:1px solid var(--line);
  font:500 12px/1 var(--mono); letter-spacing:.06em; color:var(--muted);
  font-variant-numeric:tabular-nums slashed-zero; }

/* Where a school is, which every other table could leave implicit because
   the page itself was the place. */
table.stats.register td.where { font:500 13px/1.35 var(--mono); }
table.stats.register td.where a { color:var(--ink); text-decoration:none;
  text-transform:capitalize; }
table.stats.register td.where a:hover { text-decoration:underline; }
table.stats.register td.where .sub { display:block; margin-top:3px;
  font:400 11px/1.35 var(--sans); color:var(--muted); text-transform:capitalize; }
table.stats.register tbody tr:hover td.where a,
table.stats.register tbody tr:hover td.where .sub { color:#111214; }

.reg-fallback { padding:18px; font-size:13px; color:var(--muted); }
.reg-fallback p { margin:0 0 12px; }
.reg-states { display:flex; flex-wrap:wrap; gap:6px; }
.reg-states a { padding:6px 9px; border:1px solid var(--line); color:var(--body);
  text-decoration:none; font:500 11px/1 var(--mono); }
.reg-states a:hover { border-color:var(--accent); color:var(--ink); }

@media (max-width:640px) {
  .chips button { padding:6px 8px; font-size:9.5px; letter-spacing:.06em; }
  .reg-count { padding:10px 14px; font-size:11px; }
  #reg-state { max-width:none; flex:1 1 100%; }
  /* The stacked school block on a phone gains one line: where it is. */
  table.stats.register tbody td.where { grid-column:1 / -1; margin-top:6px;
    font-size:11.5px; }
  table.stats.register tbody td.where .sub { display:inline; margin-left:6px; }
}

/* A filtered-on issue is true of every row on screen, so it is a given,
   not news. Dimming it lets the part that differs between two rows be the
   part the eye lands on — the same reason the register stopped shouting
   every finding as a pill. */
table.stats.register td.also .given { color:var(--muted); }
table.stats.register tbody tr:hover td.also .given { color:#3d3a34; }
/* How many findings this row carries — the sort key for "most issues",
   which was otherwise doing something invisible. */
table.stats.register td.also .n { display:inline-block; min-width:1.6em;
  margin-right:9px; text-align:right; color:var(--muted);
  font:700 12px/1 var(--mono); font-variant-numeric:tabular-nums; }
table.stats.register tbody tr:hover td.also .n { color:#111214; }

/* The affidavit photo fills the slot the initials were holding. Same box,
   same round mask, so a member with a photo and one without sit on the
   same baseline and the list keeps its rhythm. */
/* The slot centres its initials with place-items, which stops a child
   stretching — so height:100% never resolved and a 42px box held a 53px
   portrait, oval and overflowing. With a photograph the slot is a plain
   block the image fills exactly. */
.who-list .face:has(img), .d-face:has(img) { display:block; overflow:hidden; }
.who-list .face img { width:42px; height:42px; aspect-ratio:1/1; border-radius:50%;
  object-fit:cover; object-position:50% 20%; display:block; }
.who-list .face:has(img) { background:var(--line); }
.who-list li:hover .face:has(img) { background:var(--accent); }
/* Where the photos came from, said once under the list that uses them. */
.accountable .credit { margin:14px 0 0; font:400 11.5px/1.5 var(--sans); color:var(--muted); }
.accountable .credit a { color:var(--body); }

/* What someone standing at the school sent back.
   The register states the government's record in neutral ink; a citizen's
   photo is a different kind of claim, so it sits under that record in the
   accent colour and never inside the record line itself. */
.seen { display:flex; align-items:center; gap:11px; margin-top:11px;
  padding-top:11px; border-top:1px dashed var(--accent); }
.seen-shot { flex:none; display:block; width:46px; height:46px; }
.seen-shot img { display:block; width:100%; height:100%; object-fit:cover;
  border:1px solid var(--accent); background:var(--accent-soft); }
.seen-txt { font:500 10.5px/1.45 var(--mono); letter-spacing:.06em;
  text-transform:uppercase; color:var(--accent); }
.seen-txt b { color:var(--ink); }

/* ---------- the register, as cards ---------- */
/* Four columns squeezed the record into a narrow measure and stranded the
   counts at the far right, disconnected from the school they describe.
   Each row is a card now. The <table> stays: sort, filter and paging are
   all wired to it, and a school register is a table whatever it looks
   like — so the header row is kept for screen readers and hidden from
   sight, with each count carrying its own label instead. */
.sr-only { position:absolute; width:1px; height:1px; margin:-1px;
  padding:0; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0; }

table.stats.schools, table.stats.schools tbody { display:block; }
table.stats.schools tbody tr {
  display:grid; grid-template-columns:minmax(190px,270px) minmax(0,1fr) 88px;
  gap:6px 28px; align-items:start;
  padding:20px 18px; border-bottom:1px solid var(--line); }
table.stats.schools tbody tr:last-child { border-bottom:0; }
table.stats.schools tbody td { display:block; padding:0; border:0; }
table.stats.schools td.name { grid-column:1; grid-row:1 / span 2; }
table.stats.schools td.also { grid-column:2; grid-row:1 / span 2; max-width:none; }
table.stats.schools td.num { grid-column:3; text-align:right;
  font:600 15px/1.15 var(--mono);
  font-variant-numeric:tabular-nums slashed-zero; }
table.stats.schools td.num[data-label]::after { display:block; content:attr(data-label);
  margin-top:3px; font:500 9px/1 var(--mono); letter-spacing:.1em;
  text-transform:uppercase; color:var(--muted); }
table.stats.schools td.num .nil { color:var(--muted); }

/* A photograph is the only thing on this page that is not the
   government's paperwork. At 46px it was a stamp; at 132 it is evidence. */
.seen { align-items:flex-start; }
.seen-shot { width:132px; height:99px; }
.seen-txt { padding-top:2px; }

@media (max-width:820px) {
  table.stats.schools tbody tr { grid-template-columns:minmax(0,1fr) auto; gap:4px 14px;
    padding:14px; }
  table.stats.schools td.name { grid-column:1; grid-row:1; }
  table.stats.schools td.also { grid-column:1 / -1; grid-row:2; margin-top:8px; }
  table.stats.schools td.num { grid-column:2; text-align:right; font-size:13px; }
  table.stats.schools td:nth-of-type(3) { grid-row:1; }
  table.stats.schools td:nth-of-type(4) { grid-row:2; }
  table.stats.schools td.num[data-label]::after { display:inline; margin-left:4px; }
  .seen-shot { width:96px; height:72px; }
}

/* The source toggle governs the ledger and the map beside it, so it sits
   above the sort controls rather than among them. */
.atlas-table .sourceby { width:100%; margin-bottom:2px; }
.atlas-table .sourceby button { font-size:10px; }

/* Ten states and a way to the rest. */
.ledger-more { display:block; padding:14px 0 18px; text-align:center;
  font:600 11px/1 var(--mono); letter-spacing:.12em; text-transform:uppercase;
  color:var(--ink); text-decoration:none; border-top:1px solid var(--line); }
.ledger-more:hover { background:var(--accent-soft); }
.head-simple h1 { margin:0 0 12px; font:900 clamp(30px,5vw,48px)/1.05 var(--serif);
  letter-spacing:-0.02em; }
.head-simple .sub { margin:0; max-width:60ch; color:var(--body); }

@media (max-width:520px) {
  /* nowrap keeps FEWER…MORE on one line, which is right until the line
     is wider than the phone. Below that the key wraps rather than
     pushing the whole document 25px sideways. */
  .map-foot { flex-wrap:wrap; row-gap:8px; }
  .legend { flex-wrap:wrap; row-gap:8px; }
  .legend .lo, .legend .hi { white-space:normal; }
  .legend .sw-nodata { margin-left:6px; }
}


/* The two logos in their own colours: a WhatsApp mark that is not green
   is a shape nobody recognises, and recognition is the whole point of
   putting a logo on a button rather than a word. */
.who-list .ico { border:1px solid var(--line); }
.who-list .ico[data-brand="x"] { color:#111214; }
.who-list .ico[data-brand="x"]:hover { background:#111214; color:#fff; border-color:#111214; }
.who-list .ico[data-brand="wa"] { color:#25D366; }
.who-list .ico[data-brand="wa"]:hover { background:#25D366; color:#fff; border-color:#25D366; }
:root[data-theme="dark"] .who-list .ico[data-brand="x"] { color:#f4f2ec; }

/* Share one school. The card it opens is the school's own page, which
   already unfurls with its record on it. */
/* Under the school's name, where the row is wide enough for it to sit
   without crowding anything. On a phone it moves to the corner — see the
   820px block — because there the row stacks and the name needs the width. */
.share-school { display:inline-flex; align-items:center; gap:6px; margin-top:9px;
  padding:7px 10px; border:1px solid var(--line); border-radius:9px;
  background:var(--soft); font:600 9.5px/1 var(--mono); letter-spacing:.12em;
  text-transform:uppercase; color:var(--muted); cursor:pointer; }
.share-school:hover { border-color:var(--accent); color:var(--accent); }
.share-school svg { width:12px; height:12px; }

/* The party a member sits for, in the colour it is recognised by. Not a
   logo: an election symbol is a registered mark, and redrawing a lotus
   or a hand would put an approximation of someone's trademark on a page
   about their record. Parties we hold no colour for keep the neutral
   chip rather than being given one that means nothing. */
.who-list .party[data-colour], .d-rep .party[data-colour] {
  background:var(--party); color:#fff; border-color:transparent; padding:3px 7px; }
.d-rep .party { display:inline-block; align-self:flex-start;
  font:500 10px/1 var(--mono); letter-spacing:.08em; border-radius:99px;
  border:1px solid var(--line); color:var(--muted); padding:3px 7px; }

/* ---------- a school, opened ---------- */
/* The row opens the school rather than following its link into a blank
   report form: the reader came to see what this school is like. */
table.stats.schools tbody tr[data-udise] { cursor:pointer; }
.detail-inner { padding:22px 18px 24px; border-left:3px solid var(--accent); }
.detail-inner h3 { margin:0 0 4px; font:700 17px/1.25 var(--sans); }
.d-lede { margin:0 0 16px; font-size:13.5px; color:var(--muted); max-width:64ch; }
.d-lede b { color:var(--ink); }
/* Numbered, so five photographs of one school read as a sequence rather
   than as five separate things that happen to be stacked. */
.d-report { counter-increment:shot; position:relative; }
.detail-inner { counter-reset:shot; }
.d-figure::before { content:counter(shot); position:absolute; z-index:1;
  left:10px; top:10px; min-width:26px; height:26px; padding:0 7px;
  display:grid; place-items:center; background:var(--ink); color:var(--bg);
  font:600 11px/1 var(--mono); }

.d-issues { display:flex; flex-direction:column; gap:7px; margin-top:16px; }
.d-issue { display:flex; align-items:baseline; gap:8px; }
.d-issue b { font:600 14px/1.3 var(--sans); }
.d-issue > span { font:500 10px/1 var(--mono); letter-spacing:.09em;
  text-transform:uppercase; background:var(--accent-soft); color:var(--ink);
  padding:5px 7px; white-space:nowrap; }
.d-note { margin:14px 0 0; font:italic 400 14px/1.55 var(--sans); color:var(--body); }
.d-meta { margin:14px 0 0; font:500 10px/1 var(--mono); letter-spacing:.1em;
  text-transform:uppercase; color:var(--muted); }
.d-vote { margin-top:12px; padding:9px 13px; cursor:pointer;
  border:1px solid var(--line-strong); background:transparent; color:var(--ink);
  font:600 10.5px/1 var(--mono); letter-spacing:.1em; text-transform:uppercase; }
.d-vote:hover:not(:disabled) { background:var(--ink); color:var(--bg); }
.d-vote.is-done { border-color:var(--accent); color:var(--accent); background:var(--accent-soft); }
.d-vote:disabled { cursor:default; }
.d-count { margin-left:8px; font-variant-numeric:tabular-nums; }
.d-acts { margin:20px 0 0; }
.d-acts .btn { min-width:0; padding:14px 22px; font-size:14px; }

@media (max-width:700px) {
  .d-report { grid-template-columns:minmax(0,1fr); gap:12px; }
  .detail-inner { padding:18px 14px 20px; }
}

/* ---------- the opened school, in detail ---------- */
.d-where { margin:0; font:500 11px/1.4 var(--mono); letter-spacing:.06em;
  text-transform:uppercase; color:var(--muted); }
.d-dir { display:inline-block; margin-top:8px; font:600 10.5px/1 var(--mono);
  letter-spacing:.1em; text-transform:uppercase; color:var(--accent);
  text-decoration:none; border-bottom:1px solid var(--accent); padding-bottom:3px; }

/* Side by side and swiped, rather than a column the reader must scroll
   past to learn how many photographs there were. One report per slide,
   so a photograph never drifts away from the words that explain it. */
.d-gallery { display:flex; gap:22px; overflow-x:auto; scroll-snap-type:x mandatory;
  scroll-padding:0; margin:0 0 6px; padding-bottom:20px;
  scrollbar-width:thin; scrollbar-color:var(--rule) transparent; }
.d-gallery::-webkit-scrollbar { height:8px; }
.d-gallery::-webkit-scrollbar-thumb { background:var(--rule); border-radius:99px; }
.d-gallery[data-many] { padding-right:34px; }
.d-report { flex:0 0 100%; min-width:0; scroll-snap-align:start;
  display:block; padding:0; }
/* One report needs no rail. */
.d-gallery:not([data-many]) { overflow:visible; }
.d-figure { position:relative; }
.d-figure img { display:block; width:100%; height:260px; object-fit:cover;
  border:1px solid var(--line); background:var(--panel-2, #f2f0ea); }

.d-tiles { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)) 1.4fr;
  gap:8px; margin:12px 0 14px; }
.d-tile { display:flex; flex-direction:column; gap:4px; padding:11px 13px;
  border:1px solid var(--line); background:var(--panel); }
.d-tile b { font:700 19px/1 var(--sans); font-variant-numeric:tabular-nums; }
.d-tile small { font:500 9.5px/1.2 var(--mono); letter-spacing:.1em;
  text-transform:uppercase; color:var(--muted); }
.d-tile-wide b { font-size:14px; line-height:1.2; }

.d-bar { display:grid; grid-template-columns:1fr 1fr; gap:10px; margin-top:14px; }
.d-act { padding:14px 12px; cursor:pointer; border:1px solid var(--line-strong);
  background:transparent; font:600 11px/1 var(--mono); letter-spacing:.1em;
  text-transform:uppercase; }
.d-yes { color:var(--ink); }
.d-yes:hover:not(:disabled), .d-yes.is-done { background:#1e7d72; border-color:#1e7d72; color:#fff; }
.d-no { color:var(--muted); }
.d-no:hover:not(:disabled), .d-no.is-done { background:#c0392b; border-color:#c0392b; color:#fff; }
.d-act:disabled { opacity:.5; cursor:wait; }

.d-acc { margin-top:24px; padding-top:20px; border-top:1px solid var(--line); }
.d-acc h4 { margin:0 0 12px; font:500 10px/1 var(--mono); letter-spacing:.14em;
  text-transform:uppercase; color:var(--muted); }
.d-rep { display:flex; align-items:center; gap:12px; padding:12px;
  border:1px solid var(--line); background:var(--panel); }
.d-face { flex:none; width:52px; height:52px; border-radius:50%; overflow:hidden;
  display:grid; place-items:center; background:var(--accent-soft);
  color:var(--accent); font:700 17px/1 var(--mono); }
.d-face img { width:52px; height:52px; aspect-ratio:1/1; border-radius:50%;
  object-fit:cover; object-position:50% 20%; display:block; }
.d-rep-who { display:flex; flex-direction:column; gap:3px; min-width:0; }
.d-rep-who b { font:600 15px/1.2 var(--sans); }
.d-seat { font:500 11px/1.3 var(--mono); color:var(--muted); }
.d-acc-note { margin:10px 0 0; font-size:12px; color:var(--muted); max-width:60ch; }

@media (max-width:700px) {
  .d-figure img { height:200px; }
  .d-gallery { gap:16px; padding-bottom:18px; }
  .d-issues { margin-top:14px; }
  .d-tiles { grid-template-columns:1fr 1fr; }
  .d-tile-wide { grid-column:1 / -1; }
  .d-bar { grid-template-columns:1fr; }
}


/* ---------- the school, as a sheet ---------- */
/* A dialog rather than an inline panel: expanding in place shoves every
   row below it down the page, so the reader loses the list they were
   reading the moment they look at one thing in it. */
.sheet-wrap { position:fixed; inset:0; height:100vh; height:100dvh;
  z-index:60; display:flex;
  align-items:center; justify-content:center; padding:24px;
  background:rgba(17,18,20,.55); overscroll-behavior:contain; }
.sheet { position:relative; width:min(680px,100%);
  max-height:calc(100vh - 48px); max-height:calc(100dvh - 48px);
  display:flex; flex-direction:column;
  background:var(--bg); border:1px solid var(--line-strong);
  box-shadow:0 24px 60px rgba(17,18,20,.28); }
/* The header and the answers stay put; only the case file between them
   scrolls, so the two things a reader is most likely to want — the way
   out and the way to answer — are never scrolled past. */
/* The school's name stays with the way out: both hold their place while
   the case file scrolls under them, so a reader ten photographs deep
   still knows which school they are looking at. */
.sheet-top { flex:none; display:flex; align-items:flex-start; gap:12px;
  padding:14px 16px 12px; border-bottom:1px solid var(--soft-line); background:var(--soft); }
.sheet-title { flex:1 1 auto; min-width:0; }
.sheet-title h3 { margin:0 0 3px; font:700 17px/1.25 var(--sans); }
.sheet-tools { flex:none; display:flex; gap:8px; }
.sheet .detail-inner { flex:1 1 auto; min-height:0; overflow-y:auto; }
.sheet-share { width:40px; height:40px; display:grid; place-items:center; cursor:pointer;
  border:1px solid var(--line); background:var(--panel); color:var(--ink); }
.sheet-share:hover { background:var(--ink); color:var(--bg); border-color:var(--ink); }
.sheet-share.is-done { border-color:var(--accent); color:var(--accent); }
.sheet-bar { flex:none; display:grid; grid-template-columns:1fr 1fr; gap:10px;
  padding:16px 16px 20px; border-top:1px solid var(--line-strong); background:var(--bg); }
.d-count-now { display:inline-block; margin-left:8px; padding:2px 7px;
  background:var(--ink); color:var(--bg);
  font:600 10px/1.5 var(--mono); letter-spacing:.06em; }
/* Top left, where the reference puts it and where a thumb reaching from
   the left of a phone lands. */
.sheet-x { width:40px; height:40px; display:grid; place-items:center; cursor:pointer;
  border:1px solid var(--line); background:var(--panel); color:var(--ink);
  font:400 22px/1 var(--sans); }
.sheet-x:hover { background:var(--ink); color:var(--bg); border-color:var(--ink); }
.sheet .detail-inner { padding:16px 22px 22px; border-left:0; }

@media (max-width:700px) {
  /* Bottom sheet on a phone: it opens under the thumb rather than in the
     middle of the screen, and the close sits where the hand already is. */
  .sheet-wrap { padding:0; align-items:flex-end; }
  .sheet { width:100%; max-height:92vh; max-height:92dvh;
    border-left:0; border-right:0; border-bottom:0; }
  .sheet .detail-inner { padding:14px 16px 18px; }
  .sheet-bar { padding:14px 12px calc(18px + env(safe-area-inset-bottom)); }
}

/* ==========================================================================
   The soft layer
   --------------------------------------------------------------------------
   The register keeps its broadsheet manner — that is what makes it read as a
   record. Everything a reader touches gets the softer, colour-coded surface
   of an app: rounded cards, a lifted sheet, filled answers in green and red,
   a blue for links, tinted pills for how bad a thing is.

   Every colour here was measured against the surface it sits on. The green
   most palettes reach for (#16A34A) carries white at 3.3:1 and fails; the
   one used is #15803D at 5.02:1.
   ========================================================================== */
:root {
  --soft:        #ffffff;      /* card face                                */
  --soft-page:   #f4f5f7;      /* ground behind the cards                  */
  --soft-line:   #e6e8ec;
  --link:        #1D4ED8;      /* 6.7:1 on white                           */
  --go:          #15803D;      /* white on it: 5.02:1                      */
  --stop:        #B91C1C;      /* white on it: 6.47:1                      */
  --pill-warn-bg:#FEF3C7; --pill-warn-ink:#B45309;   /* 4.51:1 */
  --pill-bad-bg: #FEE2E2; --pill-bad-ink:#991B1B;    /* 6.80:1 */
  --pill-ok-bg:  #DCFCE7; --pill-ok-ink:#166534;     /* 6.49:1 */
  --radius:14px;
}
:root[data-theme="dark"] {
  --soft:#17171a; --soft-page:#0e0f10; --soft-line:#26282b; --link:#7aa5ff;
}

/* ---- the sheet ---- */
.sheet-wrap { background:rgba(15,17,21,.5); backdrop-filter:blur(2px); }
.sheet { border-radius:var(--radius); border-color:var(--soft-line);
  background:var(--soft); overflow:hidden;
  box-shadow:0 20px 50px rgba(15,17,21,.24); }
.sheet-top { border-bottom-color:var(--soft-line); }
.sheet-x, .sheet-share { border-radius:11px; border-color:var(--soft-line);
  background:var(--soft-page); }
.sheet .detail-inner { background:var(--soft); }
.d-dir { color:var(--link); border-bottom-color:var(--link); }
.d-figure img { border-radius:11px; border-color:var(--soft-line); }
.d-figure::before { border-radius:8px; left:12px; top:12px; }
.d-tile { border-radius:11px; border-color:var(--soft-line); background:var(--soft-page); }
.d-issue > span { border-radius:99px; padding:5px 10px; }
.d-rep { border-radius:11px; border-color:var(--soft-line); background:var(--soft-page); }
.d-acts .btn { border-radius:11px; }

/* ---- the two answers ---- */
.sheet-bar { border-top-color:var(--soft-line); background:var(--soft); gap:12px; }
.d-act { border-radius:11px; font-size:11.5px; border-width:1.5px; }
.d-yes { border-color:var(--go); color:var(--go); }
.d-yes:hover:not(:disabled), .d-yes.is-done { background:var(--go); border-color:var(--go); color:#fff; }
.d-no { border-color:var(--stop); color:var(--stop); }
.d-no:hover:not(:disabled), .d-no.is-done { background:var(--stop); border-color:var(--stop); color:#fff; }

/* ---- what people sent, on the homepage ---- */
.live-list a, .live-list .norow { border-radius:var(--radius); border-color:var(--soft-line);
  background:var(--soft); box-shadow:0 1px 2px rgba(15,17,21,.05); }
.live-list a:hover { border-color:var(--link); box-shadow:0 8px 22px rgba(15,17,21,.10); }
.r-shot { border-radius:11px; border-color:var(--soft-line); }
.r-badge { border-radius:11px; }
.r-issue > span { border-radius:99px; padding:5px 10px; }

/* ---- the strip on a register row ---- */
.seen-shot img { border-radius:10px; }

/* ---- an even card grid ----
   Rows sized alike and the footer pushed down, so a report covering five
   things no longer stands half a card taller than one covering one. */
.live-list a, .live-list .norow { display:flex; flex-direction:column; }
.r-issues { min-height:0; }
.r-more { align-self:flex-start; font:500 9.5px/1 var(--mono); letter-spacing:.1em;
  text-transform:uppercase; color:var(--muted); padding:5px 0 0; }
.r-note { flex:0 0 auto; }
.r-foot { margin-top:auto; }

/* One summary for the school, above the answers, rather than the same
   three facts repeated under every photograph. */
.sheet-sum { flex:none; margin:0; padding:14px 16px 16px; background:var(--soft);
  grid-template-columns:repeat(3, minmax(0,1fr)); }
.sheet-sum .d-tile { padding:9px 11px; }
.sheet-sum .d-tile b { font-size:17px; }
@media (max-width:700px) {
  .sheet-title h3 { font-size:15.5px; }
  .sheet-sum { padding:12px 12px 14px; gap:6px; }
  .sheet-sum .d-tile { padding:7px 9px; }
  .sheet-sum .d-tile b { font-size:15px; }
  .sheet-sum .d-tile small { font-size:8.5px; }
}

/* Where the school is, under its name: a name alone tells a stranger
   nothing about which part of the country they are looking at. */
.r-where { display:block; margin-top:3px; font:500 10px/1.4 var(--mono);
  letter-spacing:.06em; text-transform:uppercase; color:var(--muted);
  overflow:hidden; text-overflow:ellipsis; }

/* ---- the register, given room ---- */
table.stats.schools tbody tr { position:relative; }
/* The name and the line under it belong together; the record is a
   separate statement and gets the space to read as one. */
table.stats.schools td.name .sub { margin-top:5px; }
table.stats.schools td.also .also-l { display:block; line-height:1.62; }

@media (max-width:820px) {
  table.stats.schools tbody tr { padding:18px 16px 20px; gap:0; }
  table.stats.schools td.name { padding-right:96px; }
  table.stats.schools td.also { margin-top:12px; }
  /* Counts read as one quiet line under the record rather than as two
     figures wedged beside the name. */
  table.stats.schools td.num { grid-column:1; grid-row:auto; text-align:left;
    display:inline-block; margin:10px 14px 0 0; font-size:12.5px; }
  /* A row each. Both in row 3 put them in the same cell, which printed
     TEACHERS and CHILDREN on top of one another — the same collision as
     before, reintroduced from the other direction. */
  table.stats.schools td:nth-of-type(3) { grid-row:3; }
  table.stats.schools td:nth-of-type(4) { grid-row:4; }
  .share-school { position:absolute; top:16px; right:16px; z-index:1;
    margin-top:0; }
  .share-school span { position:absolute; width:1px; height:1px; overflow:hidden;
    clip:rect(0 0 0 0); white-space:nowrap; }
  .share-school { padding:9px; }
}

/* A state nobody has reported from says so, rather than showing a blank
   card or the record's figures under a heading about reports. */
.map-tip .t-none { font:400 12.5px/1.5 var(--sans); color:rgba(250,249,245,.72); }

/* The kicker carries both halves of the site: what people have sent, and
   what the government recorded. The live half appears only once there is
   something to count, and the dot beats while it is showing. */
.kicker .k-live b { color:var(--ink); }
.hero .kicker:has(.k-live:not([hidden])) .dot { background:var(--accent);
  animation:k-beat 2.4s ease-in-out infinite; }
@keyframes k-beat { 0%,100% { opacity:1; } 50% { opacity:.35; } }
@media (prefers-reduced-motion:reduce) {
  .hero .kicker:has(.k-live:not([hidden])) .dot { animation:none; }
}

/* ---------- the ask, at the foot of every page ----------
   The report form used to be reachable only from the homepage hero and
   one band halfway down it. A reader who arrived on a block page from a
   search — which is most of them, there being 6,164 of those and one
   homepage — reached the end and had nowhere to go. */
.foot-cta { display:flex; flex-wrap:wrap; align-items:center; gap:18px;
  margin:0 0 26px; padding:0 0 26px; border-bottom:1px solid var(--line); }
.foot-cta p { margin:0; flex:1 1 260px; max-width:42ch;
  font:500 15px/1.5 var(--sans); color:var(--ink); }
.foot-cta .btn { flex:0 0 auto; }
@media (max-width:560px) {
  .foot-cta { gap:14px; }
  .foot-cta .btn { width:100%; }
}
