.ew-map-stage { display: grid; grid-template-columns: 9rem minmax(0, 1fr); gap: var(--space-3); margin-top: var(--space-3); }
.ew-map-canvas { min-width: 0; }
.ew-map-canvas .leaflet-control-zoom a { width: 44px; height: 44px; line-height: 44px; }
.ew-office-tabs { display: grid; align-content: start; gap: var(--space-1); margin: 0; }
.ew-office-tabs a { display: flex; align-items: center; min-height: 44px; padding: var(--space-2) var(--space-3); border: 1px solid var(--colour-border); border-radius: var(--radius-sm); font-size: var(--text-sm); text-decoration: none; }
.ew-office-tabs a[aria-current] { background: var(--colour-primary); color: var(--colour-bg); }
.ew-place h3 { margin-top: var(--space-3); }
.ew-place summary, .ep-population summary { min-height: 44px; padding-block: var(--space-3); cursor: pointer; }
.ew-place-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr)); gap: var(--space-2); }
.ew-place-list a { display: flex; justify-content: space-between; gap: var(--space-2); align-items: center; min-height: 44px; padding: var(--space-2); background: var(--colour-bg-subtle); font-size: var(--text-sm); }
.ew-result-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); gap: var(--space-2); max-height: 25rem; overflow-y: auto; }
.ew-winner { display: flex; flex-direction: column; margin: 0; padding: var(--space-3); border-left: 3px solid var(--colour-primary); background: var(--colour-bg-subtle); font-size: var(--text-sm); }
.ew-winner a { min-height: 44px; display: flex; align-items: center; }
.ew-map-tooltip { font-size: var(--text-sm); padding: var(--space-3); max-width: min(48rem, calc(100vw - 2rem)); white-space: normal; }
.ew-map-tooltip__office { display: grid; grid-template-columns: 11rem auto; gap: var(--space-2); margin-top: var(--space-2); white-space: nowrap; }
.ep-population { min-width: 0; }
.ep-population h3 { margin-bottom: var(--space-3); }
.ep-comparison { margin: 0; }
.ep-measure { display: grid; grid-template-columns: 1fr auto; gap: var(--space-1) var(--space-3); margin-bottom: var(--space-4); font-size: var(--text-sm); }
.ep-measure strong { font-variant-numeric: tabular-nums; }
.ep-measure__track { grid-column: 1 / -1; height: .8rem; background: var(--colour-bg-subtle); border-radius: var(--radius-sm); }
.ep-measure__track i { display: block; height: 100%; width: var(--w); background: var(--colour-text-muted); border-radius: inherit; }
.ep-measure--adults i { background: var(--colour-secondary); }
.ep-measure--voters i { background: var(--colour-primary); }
.ep-comparison figcaption { font-size: var(--text-xs); color: var(--colour-text-muted); }
.ep-pairs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); margin-block: var(--space-3); }
.ep-pairs div { display: flex; flex-direction: column; padding: var(--space-3); background: var(--colour-bg-subtle); }
.ep-pairs strong { font-size: var(--text-xl); }
.ep-pairs span { font-size: var(--text-xs); }
.ep-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4); align-items: start; }
.ep-grid > * { min-width: 0; }
.page-elections-hub.has-brand-hero .page-band .elections-hero__lead a { color: inherit; text-decoration: underline; }
.ep-result-coverage > summary { min-height: 44px; padding-block: var(--space-3); cursor: pointer; font-weight: 650; }
.ep-contrast-heading { font-size: var(--text-xs); font-weight: 750; margin-block: var(--space-3) var(--space-1); }
@media (max-width: 52rem) {
  .ep-grid { grid-template-columns: 1fr; }
  .ew-map-stage { grid-template-columns: 1fr; }
  .ew-office-tabs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ew-map-tooltip__office { grid-template-columns: 1fr; white-space: normal; gap: 0; }
}
/* Register growth panel — shown on a county and on a constituency page. Both
   halves the owner asked for sit side by side: the number of voters added and
   what percentage that is of the earlier register.

   It is a CARD, because on both pages it lands among cards and an unframed
   strip read as an orphan. The columns are `auto-fit`, not a fixed two, because
   on a constituency page it sits in a ~450px column where two fixed columns
   wrapped "87th of 290 constituencies by number" onto three cramped lines. */
/* `max-width` because this panel is now placed full-width under a two-column
   grid: across 1,392px its three bars stretch into rulers and the two figure
   cards drift apart. It still fills a narrower column unchanged. */
.rg-growth { min-width: 0; max-width: 56rem; margin-block: var(--space-4); padding: var(--space-4); border: 1px solid var(--colour-border); border-radius: var(--radius-md); background: var(--colour-bg); }
/* Quieter than the h3 above it on a constituency page, which is the register
   count itself — the panel explains that number, it does not compete with it. */
.rg-growth > h3 { margin: 0 0 var(--space-3); font-size: var(--text-xs); font-weight: var(--fw-bold); letter-spacing: .06em; text-transform: uppercase; color: var(--colour-text-muted); }
/* The three-register chart. CSS bars, no chart library and no JS: three rows
   do not justify a dependency, and a bar that is just a div always prints.
   Grid, not flex, so the year column, the tracks and the counts line up
   across rows — ragged tracks were the whole point of drawing this. */
.rg-bars { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: var(--space-2) var(--space-3); margin: 0 0 var(--space-3); padding: 0; list-style: none; }
.rg-bar { display: contents; }
.rg-bar__year { font-size: var(--text-xs); font-weight: var(--fw-semibold); color: var(--colour-text-muted); font-variant-numeric: tabular-nums; }
.rg-bar__track { position: relative; height: 1.15rem; border-radius: var(--radius-sm); background: var(--colour-bg-subtle); }
.rg-bar__track > i { display: block; width: var(--w); height: 100%; border-radius: var(--radius-sm); background: var(--colour-primary); }
.rg-bar__value { font-size: var(--text-sm); font-weight: var(--fw-bold); font-variant-numeric: tabular-nums; }
/* A year with no register held: an outlined, EMPTY track. Filling it to zero
   would read as "nobody is registered here", which is not what we know. */
.rg-bar--pending .rg-bar__track { background: transparent; border: 1px dashed var(--colour-border); }
.rg-bar--pending .rg-bar__year,
.rg-bar--pending .rg-bar__value { color: var(--colour-text-muted); font-weight: var(--fw-semibold); font-size: var(--text-xs); }
/* `max-width` in CH, not rem: these are small-print sentences, and in a 56rem
   panel a 12px line ran 128 characters (measured 2026-09-15 on the Changamwe
   constituency page). A reading measure is counted in characters. */
.rg-bars__pending { margin: calc(var(--space-2) * -1) 0 var(--space-3); max-width: 78ch; font-size: var(--text-xs); color: var(--colour-text-muted); }
/* Places compared as bars (wards in a constituency, constituencies in a
   county). It REUSES .rg-bars above rather than copying it: this is the same
   object — a register year drawn as a bar — and a second copy of those rules
   would drift from the one the growth panel right below it draws. */
.pb-chart { margin: 0; }
.pb-places { display: grid; gap: var(--space-3); margin: 0; padding: 0; list-style: none; }
.pb-place { display: grid; gap: var(--space-1); min-width: 0; }
.pb-place__name { display: flex; align-items: center; min-height: 44px; font-size: var(--text-sm); font-weight: var(--fw-semibold); }
.pb-place__bars { margin: 0; }
.pb-chart figcaption { margin-top: var(--space-3); max-width: 78ch; font-size: var(--text-xs); color: var(--colour-text-muted); }
.rg-growth__sub { margin: 0 0 var(--space-2); font-size: var(--text-xs); font-weight: var(--fw-bold); letter-spacing: .06em; text-transform: uppercase; color: var(--colour-text-muted); }
.rg-growth__figures { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr)); gap: var(--space-3); }
.rg-figure { display: flex; flex-direction: column; gap: var(--space-1); padding: var(--space-3); background: var(--colour-bg-subtle); border-left: 3px solid var(--colour-text-muted); border-radius: var(--radius-sm); }
.rg-figure--count { border-left-color: var(--colour-primary); }
.rg-figure--percent { border-left-color: var(--colour-info); }
/* The register the new registrations are added to. A third colour because it
   is a different KIND of number from the two beside it — a standing total, not
   a change — and the owner's point on 2026-09-15 was that the page was letting
   the two read as one. */
.rg-figure--register { border-left-color: var(--colour-text-muted); }
.rg-figure strong { font-size: var(--text-xl); line-height: 1.15; font-variant-numeric: tabular-nums; }
.rg-figure span { font-size: var(--text-xs); }
.rg-figure__rank { margin-top: auto; padding-top: var(--space-1); color: var(--colour-text-muted); }
.rg-growth > details { margin-top: var(--space-2); border-top: 1px solid var(--colour-border); }
.rg-growth > details > summary { min-height: 44px; padding-block: var(--space-2); cursor: pointer; font-size: var(--text-xs); color: var(--colour-text-muted); }
.rg-growth > details p { margin: 0 0 var(--space-2); font-size: var(--text-xs); color: var(--colour-text-muted); }

/* Registration towards 2027. The same box as `.rg-growth`, sitting directly
   above it, because the two answer one question between them: where the
   register stands, and how much has been added towards the next election. The
   top rule is what marks it as the LEADING figure — owner, 2026-09-15: "the two
   relevant sets of data are 2022 and 2027. 2017 is no longer relevant." */
.rg-progress { min-width: 0; max-width: 56rem; margin-block: var(--space-4); padding: var(--space-4); border: 1px solid var(--colour-border); border-top: 3px solid var(--colour-primary); border-radius: var(--radius-md); background: var(--colour-bg); }
.rg-progress > h3 { margin: 0 0 var(--space-3); font-size: var(--text-xs); font-weight: var(--fw-bold); letter-spacing: .06em; text-transform: uppercase; color: var(--colour-text-muted); }
/* Load-bearing sentence, not fine print: without it a reader adds the new
   registrations to the 2022 register and invents a 2027 total. */
.rg-progress__wider { margin: var(--space-3) 0 0; max-width: 78ch; font-size: var(--text-sm); color: var(--colour-text); }
.rg-progress__wider strong { font-variant-numeric: tabular-nums; }
/* The top counties, drawn. This was `.rg-progress__top`, a bordered list of
   name-and-number rows: the ranking lived in the ORDER and nowhere in the
   shape, so 276,886 and 84,198 read as two big numbers. It is now the shared
   `.ew-rank-chart` below, tinted to match the drive bar above it, with the
   44px touch target the list rows had. */
/* Two classes in the selector on purpose. `.ew-rank-chart` sets the shorthand
   `margin: 0 0 var(--space-5)` and is defined LATER in this file, so a
   single-class rule here lost the cascade and the band heading sat flush
   against the paragraph above it. */
.rg-progress__ranked.ew-rank-chart { --rank-ink: var(--colour-info); margin: var(--space-4) 0 0; }
.rg-progress__ranked .ew-rank-chart__bars a { min-height: 44px; }
/* The share chart on the hub. Same ink as the by-number chart it sits beside,
   and as `.ew-ranking-group--percentage` on the watch hub: one drive, two
   views of it, so a second hue would suggest a second measurement. Identity is
   never carried by the colour here — each bar is named and its value printed. */
.elections-registration-share .ew-rank-chart { --rank-ink: var(--colour-info); margin: 0; }
.elections-registration-share .ew-rank-chart__bars a { min-height: 44px; }
.rg-progress__note { margin: var(--space-3) 0 0; max-width: 78ch; font-size: var(--text-xs); color: var(--colour-text-muted); }
.rg-progress > details { margin-top: var(--space-2); border-top: 1px solid var(--colour-border); }
.rg-progress > details > summary { min-height: 44px; padding-block: var(--space-2); cursor: pointer; font-size: var(--text-xs); color: var(--colour-text-muted); }
.rg-progress > details p { margin: 0 0 var(--space-2); font-size: var(--text-xs); color: var(--colour-text-muted); }

/* The registration panel's leading picture, replacing three number tiles on
   2026-09-15. The tiles printed 22,102,532 next to +2,345,476 in equal type
   and left the reader to work out that one is nine times the other; one
   zero-based track says it before a word is read.

   CSS geometry from an inline custom property — no chart library and no JS,
   the same idiom as `.rg-bars` and `.ep-measure` above it on this page. Every
   figure is printed in text beside its own bar, so the picture is never the
   only copy of a number and the tracks are `aria-hidden`.

   Three inks, one per KIND of number, because that was the owner's point the
   same day: the standing register is muted, IEBC's national count of new
   registrations carries the brand, and this drive — a part of that count —
   carries the secondary. Identity is never colour alone: every row is
   labelled. */
.rg-scale { margin: 0 0 var(--space-3); }
.rg-scale__row { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: baseline; gap: var(--space-1) var(--space-3); margin-bottom: var(--space-3); }
.rg-scale__value { font-size: var(--text-xl); line-height: 1.15; font-variant-numeric: tabular-nums; color: var(--rg-ink, var(--colour-text)); }
.rg-scale__label { font-size: var(--text-xs); color: var(--colour-text-muted); }
.rg-scale__track { grid-column: 1 / -1; display: block; height: 1.15rem; background: var(--colour-bg-subtle); border: 1px solid var(--colour-border); border-radius: var(--radius-sm); overflow: hidden; }
.rg-scale__track > i { display: block; width: var(--w); min-width: 2px; height: 100%; background: var(--rg-ink, var(--colour-text-muted)); }
.rg-scale__foot { grid-column: 1 / -1; font-size: var(--text-xs); color: var(--colour-text-muted); }
.rg-scale__row--register { --rg-ink: var(--colour-text-muted); }
.rg-scale__row--national { --rg-ink: var(--colour-primary); }
.rg-scale__row--drive { --rg-ink: var(--colour-info); }
/* "of which": this drive is PART of the national count directly above, never a
   second group to be added to it. An indent behind a rule is the table idiom
   for a sub-total and needs no extra words. Only applied when the national bar
   is actually drawn — on a county page there is nothing above to be part of. */
.rg-scale__row--inset { margin-left: var(--space-4); padding-left: var(--space-3); border-left: 2px solid var(--colour-border); }
.rg-scale figcaption { max-width: 78ch; font-size: var(--text-xs); color: var(--colour-text-muted); }

/* Ranked bar chart. MOVED here from `reforms/css/watch-hub.css` on 2026-09-15:
   its markup partials live in `apps/elections/templates/elections/`, and the
   registration panel above now draws one on a page that does not load
   watch-hub.css. Every page that loads watch-hub.css also loads this file,
   after it. The name column is a variable so the bars line up across both
   bands of the same figure. There is no drawn axis: a bar's exact value is
   printed beside it and the figcaption names the shared scale, which avoids
   aligning an axis to a three-column grid. */
.ew-rank-chart { --rank-name-col: clamp(6rem, 24%, 11rem); --rank-value-col: 5.5rem; margin: 0 0 var(--space-5); }
.ew-rank-chart__band { margin: var(--space-3) 0 var(--space-1); font-size: var(--text-xs); font-weight: var(--fw-bold); text-transform: uppercase; letter-spacing: .04em; color: var(--colour-text-muted); }
.ew-rank-chart__band:first-child { margin-top: 0; }
.ew-rank-chart__bars { list-style: none; margin: 0; padding: 0; }
.ew-rank-chart__bars a { display: grid; grid-template-columns: var(--rank-name-col) minmax(0, 1fr) var(--rank-value-col); align-items: center; gap: var(--space-2); padding: .25rem; border-radius: var(--radius-sm); color: inherit; text-decoration: none; }
.ew-rank-chart__bars a:hover { background: var(--colour-primary-alpha-10); }
.ew-rank-chart__bars a:hover .ew-rank-chart__name { text-decoration: underline; }
.ew-rank-chart__bars a:focus-visible { outline: 2px solid var(--rank-ink, var(--colour-primary)); outline-offset: 2px; }
.ew-rank-chart__name { min-width: 0; font-size: var(--text-sm); overflow-wrap: anywhere; }
.ew-rank-chart__track { display: block; height: 1.15rem; background: var(--colour-bg-subtle); border: 1px solid var(--colour-border); border-radius: var(--radius-sm); overflow: hidden; }
/* A near-zero increase is still a real row: draw it as a hairline rather than
   nothing, and let the printed value carry the magnitude. */
/* The fallback is not decoration. Every caller so far set `--rank-ink` on an
   ancestor, so the base class never needed one — and a caller that forgot drew
   INVISIBLE BARS: an undefined custom property makes the whole declaration
   invalid, which leaves `background` transparent and `color` inheriting the
   link red from the row's own <a>. Measured on the share chart added
   2026-09-15, which rendered five empty tracks and five red numbers. */
.ew-rank-chart__fill { display: block; width: var(--w); min-width: 2px; height: 100%; background: var(--rank-ink, var(--colour-primary)); }
.ew-rank-chart__value { text-align: right; font-size: var(--text-sm); font-weight: var(--fw-semibold); color: var(--rank-ink, var(--colour-primary)); font-variant-numeric: tabular-nums; white-space: nowrap; }
.ew-rank-chart__bars--muted .ew-rank-chart__fill { background: var(--colour-border-strong); }
.ew-rank-chart__bars--muted .ew-rank-chart__value { color: var(--colour-text-muted); font-weight: 400; }
.ew-rank-chart__empty { font-size: var(--text-sm); color: var(--colour-text-muted); }
.ew-rank-chart figcaption { margin-top: var(--space-2); font-size: var(--text-xs); color: var(--colour-text-muted); }
@media (max-width: 760px) {
  .ew-rank-chart { --rank-name-col: clamp(5rem, 30%, 8rem); --rank-value-col: 4.6rem; }
}
