:root {
  --bg: #0b0e13;
  --bg-2: #11151d;
  --panel: #0e1219;
  --sea: #0b0e13;
  --line: #1d2733;
  --line-2: #2a3645;
  --ink: #e7edf4;
  --ink-dim: #93a1b3;
  --ink-faint: #5d6b7d;
  --accent: #4dd6c1;
  --accent-2: #ffd166;
  --land: #1b2530;
  --land-hi: #2b3a49;
  --stroke: #05070c;   /* near-black seat borders — high contrast against the coloured seats */
  --select: #ffd166;
  --radius: 12px;
  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --sans: "Space Grotesk", system-ui, -apple-system, sans-serif;
}

* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; }
/* Safari paints the pinch-zoom / overscroll canvas from the ROOT element's
   background — without this, zooming out exposes WHITE beyond the fixed layers. */
html { background: var(--bg); }
body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
}
a { color: var(--link, var(--accent)); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ---- keyboard focus ring (visible only for keyboard users) ---- */
:focus-visible { outline: 2px solid var(--focus, var(--accent)); outline-offset: 2px; border-radius: 4px; }
/* .seg clips overflow, so inset the ring on its buttons to keep it visible */
.seg button:focus-visible { outline-offset: -2px; }
/* the search input zeroes its outline by default — re-assert it on keyboard focus */
.search input:focus-visible { outline: 2px solid var(--focus, var(--accent)); outline-offset: 2px; border-color: var(--focus, var(--accent)); }

#app {
  display: grid;
  grid-template-columns: 1fr 340px;
  grid-template-rows: auto 1fr;
  grid-template-areas: "top top" "stage panel";
  height: 100vh;
  height: 100dvh;
}

/* ---- top bar ---- */
#topbar {
  grid-area: top;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  padding: 12px 18px;
  background: linear-gradient(180deg, var(--bg-2), var(--bg));
  border-bottom: 1px solid var(--line);
  flex-wrap: wrap;
}
.brand { display: flex; flex-direction: column; line-height: 1.05; }
.brand .mark { font-family: var(--font-display); font-size: 20px; font-weight: 700; letter-spacing: .01em; }
.brand .brand-symbol { font-family: var(--sans); }
.brand .brand-word { font-family: var(--font-display); }
.brand .mark b { color: var(--accent); font-weight: 700; }
.brand .tag { font-size: 11px; color: var(--ink-faint); letter-spacing: .02em; margin-top: 2px; }

.controls { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.seg { display: inline-flex; background: var(--bg); border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
.seg button {
  font-family: var(--sans); font-size: 12px; font-weight: 500;
  color: var(--ink-dim); background: transparent; border: 0; padding: 7px 13px;
  cursor: pointer; transition: background .15s, color .15s;
}
.seg button:hover:not(:disabled) { color: var(--ink); background: var(--bg-2); }
.seg button.on { color: var(--accent-fg, var(--bg)); background: var(--accent); font-weight: 600; }
.seg button:disabled { color: var(--ink-faint); cursor: not-allowed; opacity: .55; }
/* "Soon/Segera" badge on the gated Skor tab — communicates "coming" instead of a dead button.
   Rendered as a ::after pill from data-after (set by applyStatic); guarded on [data-after]
   so an unset attribute never paints an empty dot. The tab stays disabled — gating is unchanged. */
.seg button[data-after]::after {
  content: attr(data-after);
  margin-left: 6px; vertical-align: middle;
  font-size: 10px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  padding: 1px 5px; border-radius: 999px;
  background: var(--accent-2); color: var(--badge-fg, var(--bg));
}

.search { position: relative; }
.search input {
  font-family: var(--sans); font-size: 13px; color: var(--ink);
  background: var(--bg); border: 1px solid var(--line); border-radius: 8px;
  padding: 8px 12px; width: 190px; outline: none;
}
.search input:focus { border-color: var(--focus); }
.results {
  position: absolute; top: calc(100% + 6px); right: 0; width: 260px; z-index: 30;
  background: var(--panel); border: 1px solid var(--line-2); border-radius: 8px;
  overflow: hidden; box-shadow: var(--shadow-pop, 0 14px 40px rgba(0,0,0,.5));
}
.results button {
  display: flex; justify-content: space-between; gap: 10px; width: 100%;
  text-align: left; background: transparent; border: 0; color: var(--ink);
  padding: 9px 12px; cursor: pointer; font-family: var(--sans); font-size: 13px;
  border-bottom: 1px solid var(--line);
}
.results button:last-child { border-bottom: 0; }
.results button:hover,
.results button.active { background: var(--bg-2); }
.results .code { font-family: var(--mono); font-size: 11px; color: var(--ink-faint); }
/* search-match highlight: dim the result text so the typed letters (bright white,
   bold) stand out — same in the main list and the bento results. */
.results button > span, .bento-result { color: var(--ink-dim); }
.q-hl { color: #fff; font-weight: 700; }
/* a state row jumps to the whole dashboard — tag it with the accent so it reads as a
   distinct action from the seat rows */
.results .result-state .code {
  color: var(--accent); font-family: inherit; font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .08em;
}

/* ---- stage / map ---- */
#stage { grid-area: stage; position: relative; background:
  radial-gradient(120% 90% at 50% 0%, var(--stage-top, #0d141d) 0%, var(--sea) 70%); overflow: hidden;
  isolation: isolate; }
#map { width: 100%; height: 100%; display: block; cursor: grab; }
#map:active { cursor: grabbing; }

.seat {
  fill: var(--land);
  stroke: var(--stroke);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;   /* borders stay a constant ~1px wide at EVERY zoom */
  stroke-linejoin: round;
  transition: fill .12s ease;
  cursor: pointer;
}
.seat:hover { filter: brightness(1.3) saturate(1.1); stroke: var(--accent); stroke-width: 1.8; }
.seat.dim { opacity: .28; }
.seat.match { stroke: var(--accent); stroke-width: 1.8; }
.seat.sel {
  stroke: var(--select);
  stroke-width: 2.4;
  paint-order: stroke;
}
#seats.has-data .seat { stroke-width: 1; }
/* federal territories (KL/Putrajaya/Labuan) have no state assembly → shown as a muted,
   inert underlay in DUN mode so they read as "no DUN here", not as missing black holes. */
.seat.no-dun { fill: var(--land-muted, #31353e); stroke: none; pointer-events: none; }

#tooltip {
  position: absolute; z-index: 20; pointer-events: none;
  background: var(--tooltip-bg, rgba(8,11,16,.94)); border: 1px solid var(--line-2);
  border-radius: 8px; padding: 6px 10px; font-size: 12px; color: var(--ink);
  transform: translate(-50%, -130%); white-space: nowrap;
  box-shadow: var(--shadow-soft, 0 6px 22px rgba(0,0,0,.5));
}
#tooltip .t-statename { font-family: var(--font-display); font-weight: 700; font-size: 13px; color: var(--ink); margin-bottom: 1px; }
#tooltip .t-code { font-family: var(--mono); color: var(--accent); font-size: 10px; }
#tooltip .t-state { color: var(--ink-faint); font-size: 11px; }
#tooltip .t-win { margin-top: 4px; padding-top: 4px; border-top: 1px solid var(--line);
  font-size: 11px; color: var(--ink-dim); display: flex; align-items: center; gap: 6px; }
#tooltip .pill { font-size: 10px; padding: 1px 6px; }

/* Big state name centred at the top of the map: hover in overview, persistent once isolated. */
#state-label {
  position: absolute; top: calc(var(--map-top, 70px) + 8px); left: 50%;
  transform: translateX(-50%) translateY(7px);
  z-index: 16; pointer-events: none;
  display: flex; flex-direction: column; align-items: center;
  max-width: calc(100vw - 32px);
  color: var(--ink); text-align: center;
  opacity: 0; transition: opacity 160ms var(--ease-out), transform 160ms var(--ease-out);
}
#state-label .label-main {
  font-family: var(--font-display); font-weight: 700; line-height: 1;
  font-size: clamp(28px, 4vw, 60px); letter-spacing: .01em; white-space: nowrap;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis;
  text-shadow: var(--label-shadow);
  display: inline-flex; align-items: center; justify-content: center; gap: .24em;
}
#state-label .label-flag {
  width: 1.05em; height: .68em; flex: 0 0 auto;
  object-fit: cover; border-radius: 4px;
  border: 1px solid color-mix(in srgb, var(--ink) 24%, transparent);
  box-shadow: none;
  background: var(--surface-soft);
}
#state-label .label-sub {
  margin-top: 6px; line-height: 1; white-space: nowrap;
  font-family: var(--font-display); font-weight: 600; letter-spacing: .01em;
  font-size: clamp(13px, 1.5vw, 22px); color: var(--ink-dim);
  text-shadow: var(--label-shadow);
  opacity: 0; transition: opacity 140ms var(--ease-out);
}
#state-label .label-sub.show { opacity: 1; }
/* reserve the sub-line's height only when a state is open, so the state name never
   jumps as the hovered-district name fades in and out. */
body.state-open #state-label .label-sub { min-height: 1em; }
body.state-open #state-label {
  top: var(--state-label-top, calc(var(--map-top, 70px) + 4px));
}
#state-label.show { opacity: 1; transform: translateX(-50%) translateY(0); }
@media (prefers-reduced-motion: reduce) {
  #state-label { transition: opacity 120ms linear; transform: translateX(-50%); }
}

/* coalition seat-share bar (overview) */
.sharebar {
  display: flex;
  height: 12px;
  min-height: 12px;
  border-radius: 4px;
  overflow: hidden;
  margin: 16px 0 8px;
  width: 100%;
  flex-shrink: 0;
  background: color-mix(in oklab, var(--ink) 8%, transparent);
}
.sharebar span { display: block; height: 100%; min-height: 12px; flex: 0 0 auto; }
.sharebar-key { display: flex; flex-wrap: wrap; gap: 4px 12px; font-size: 11px; color: var(--ink-dim); }
.sharebar-key b { color: var(--ink); font-family: var(--mono); font-weight: 500; }

#reset {
  position: absolute; left: 16px; bottom: 16px; z-index: 15;
  font-family: var(--mono); font-size: 12px; color: var(--ink);
  background: var(--glass-strong); border: 1px solid var(--line-2);
  border-radius: 8px; padding: 8px 12px; cursor: pointer; backdrop-filter: blur(6px);
}
#reset:hover { border-color: var(--accent); }
/* draw the eye when "Show all" first appears, so the way back is discoverable */
#reset:not([hidden]) { animation: reset-in .4s ease both; }
@keyframes reset-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) { #reset:not([hidden]) { animation: none; } }

/* ---- first-load tap hint ---- */
.tap-hint {
  position: absolute; z-index: 16; top: 14px; left: 50%; transform: translateX(-50%);
  display: flex; align-items: center; gap: 8px; max-width: min(90%, 380px);
  font-size: 13px; line-height: 1.4; color: var(--ink);
  background: var(--glass-strong); border: 1px solid var(--line-2);
  border-radius: 999px; padding: 8px 8px 8px 15px; backdrop-filter: blur(6px);
  box-shadow: var(--shadow-soft, 0 6px 22px rgba(0,0,0,.45));
  animation: hint-in .45s ease both;
}
.tap-hint[hidden] { display: none; }
.tap-hint-x {
  flex: 0 0 auto; width: 26px; height: 26px; border-radius: 999px;
  display: grid; place-items: center; cursor: pointer; font-size: 11px; line-height: 1;
  background: var(--bg-2); border: 1px solid var(--line); color: var(--ink-dim);
}
.tap-hint-x:hover { color: var(--ink); border-color: var(--accent); }
@keyframes hint-in { from { opacity: 0; transform: translate(-50%, -8px); } to { opacity: 1; transform: translate(-50%, 0); } }
@media (prefers-reduced-motion: reduce) { .tap-hint { animation: none; } }

#loading {
  position: absolute; inset: 0; display: grid; place-items: center;
  font-family: var(--mono); font-size: 13px; color: var(--ink-faint);
  pointer-events: none;
}
#loading[hidden] { display: none; }
/* subtle "still working" affordance while boundaries load; no layout impact */
#loading:not(.error) { animation: loading-pulse 1.5s ease-in-out infinite; }
@keyframes loading-pulse { 0%, 100% { opacity: .5; } 50% { opacity: 1; } }
/* friendly, non-alarming message when a data layer can't be fetched */
#loading.error span {
  display: block; max-width: 260px; text-align: center; line-height: 1.5;
  color: var(--ink-dim); padding: 0 24px;
}
@media (prefers-reduced-motion: reduce) { #loading { animation: none; } }

/* ---- panel ---- */
#panel {
  grid-area: panel; background: var(--panel); border-left: 1px solid var(--line);
  padding: 20px 18px; overflow-y: auto;
}
/* the bottom-sheet grab-handle only exists on mobile (see the ≤820px block) */
.sheet-handle { display: none; }
#panel h2 { font-size: 16px; margin: 0 0 6px; letter-spacing: .01em; }
.muted { color: var(--ink-dim); }
.src { font-size: 11px; margin-top: 22px; }

/* ---- "Find your YB" front door (empty panel hero) ---- */
.find { padding: 4px 0 2px; }
.find-kicker { font-family: var(--mono); font-size: 11px; color: var(--accent);
  letter-spacing: .12em; margin: 0 0 6px; }
.find h2 { font-size: 22px; line-height: 1.2; margin: 0 0 8px; }
.find-sub { font-size: 13px; line-height: 1.5; margin: 0 0 16px; }
.find-loc {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; min-height: 44px; padding: 12px 16px; cursor: pointer;
  font-family: var(--sans); font-size: 14px; font-weight: 600;
  color: var(--bg); background: var(--accent); border: 0; border-radius: var(--radius);
}
.find-loc:hover { filter: brightness(1.06); }
.find-loc:disabled { cursor: progress; opacity: .7; }
.find-or { font-size: 12px; text-align: center; margin: 12px 0 2px; }
.find-eg { font-size: 12px; line-height: 1.5; margin: 0; color: var(--ink-faint); }
.find-status { font-size: 12px; line-height: 1.5; margin: 10px 0 0; padding: 8px 10px;
  border-radius: var(--radius); background: var(--surface-soft-2); border: 1px solid var(--line); color: var(--ink); }

/* legend + summary demoted into a collapsible "explore" disclosure */
.empty-more { margin-top: 20px; border-top: 1px solid var(--line); padding-top: 14px; }
.empty-more > summary {
  cursor: pointer; font-size: 12px; color: var(--ink-dim);
  list-style: none; user-select: none; padding: 2px 0;
}
.empty-more > summary::-webkit-details-marker { display: none; }
.empty-more > summary::before { content: "▸ "; color: var(--ink-faint); }
.empty-more[open] > summary::before { content: "▾ "; }
.empty-more > summary:hover { color: var(--ink); }

.legend { margin: 20px 0 10px; display: flex; flex-direction: column; gap: 5px; }
.legend .row { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--ink-dim); }
/* 1px ring keeps low-contrast swatches distinguishable from the panel and each
   other — colour is never the only cue (every row is paired with a text label). */
.legend .sw { width: 12px; height: 12px; border-radius: 4px; flex: 0 0 auto; border: 1px solid rgba(231,237,244,.22); }
.sharebar-key .sw { border: 1px solid rgba(231,237,244,.22); }

.summary { margin: 6px 0 0; display: grid; grid-template-columns: 1fr auto; gap: 4px 10px; }
.summary dt { color: var(--ink-faint); font-size: 12px; }
.summary dd { margin: 0; font-family: var(--mono); font-size: 13px; text-align: right; }

/* seat panel */
.seat-head { position: relative; border-bottom: 1px solid var(--line); padding-bottom: 14px; margin-bottom: 14px; }
.seat-head-share { display: none; }
.seat-head .kicker { font-family: var(--mono); font-size: 11px; color: var(--accent); letter-spacing: .08em; }
.seat-head h2 { font-size: 22px; margin: 4px 0 2px; }
.seat-head .where { font-size: 13px; color: var(--ink-dim); }
.seat-head .where b { color: var(--ink); font-weight: 500; }

/* detail as a CLOSED bordered table: an outer box with row + column hairlines, so every
   metric is a boxed cell — easy to scan on mobile. min-width:0 lets the value cell shrink
   and WRAP rather than overflow; overflow-wrap breaks even an unbroken long string. */
.rows {
  display: grid; grid-template-columns: auto 1fr;
  border: 1px solid var(--line); border-radius: 12px; overflow: hidden;
}
.rows dt, .rows dd { padding: 10px 12px; border-bottom: 1px solid var(--line); min-width: 0; }
.rows dt { color: var(--ink-dim); font-size: 13px; white-space: nowrap; border-right: 1px solid var(--line); }
.rows dd { margin: 0; text-align: right; font-size: 14px; overflow-wrap: anywhere; }
.rows dd.mono { font-family: var(--mono); }
.rows .bloc-unit { white-space: nowrap; }   /* "· <pill>" stays as one unit when the party name wraps */
.rows dt:last-of-type, .rows dd:last-of-type { border-bottom: 0; }   /* last row closed by the outer border */

.pill { display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: 12px; font-weight: 600;
  font-family: var(--mono); color: #0b0e13; }
.placeholder { color: var(--ink-faint); font-style: italic; font-size: 13px; }

.note { margin-top: 18px; padding: 11px 12px; background: var(--bg); border: 1px solid var(--line);
  border-radius: 8px; font-size: 12px; color: var(--ink-dim); line-height: 1.5; }
.note b { color: var(--ink); }

/* per-card data provenance (transparency: every number shows its source) */
.src-line { margin-top: 12px; font-size: 11px; line-height: 1.4; }

/* share / copy-link */
.seat-actions { margin-top: 18px; display: flex; gap: 8px; flex-wrap: wrap; }
.share-btn { flex: 1 1 140px; width: 100%; min-height: 44px; padding: 11px 14px; font-size: 14px; font-weight: 600;
  cursor: pointer; color: var(--ink); background: var(--bg); border: 1px solid var(--line);
  border-radius: var(--radius); transition: border-color .15s, color .15s; }
.share-btn:hover { border-color: var(--accent); color: var(--accent); }
.seat-detail-actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  margin: 0 0 14px;
}
.seat-detail-action {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  text-align: center;
}
@media (max-width: 760px) {
  .seat-detail-actions { display: none; }
  .seat-head { padding-right: 48px; }
  .seat-head-share {
    display: grid;
    position: absolute;
    top: -2px;
    right: 0;
    width: 36px;
    height: 36px;
    border-radius: 12px;
  }
  .seat-head-share svg { width: 17px; height: 17px; }
}

/* transient confirmation toast */
.toast { position: fixed; left: 50%; bottom: 24px; transform: translate(-50%, 12px);
  max-width: min(92vw, 420px); padding: 11px 16px; font-size: 13px; text-align: center;
  color: var(--bg); background: var(--accent); border-radius: 999px; z-index: 80;
  box-shadow: 0 6px 24px rgba(0,0,0,.35); opacity: 0; pointer-events: none;
  transition: opacity .2s, transform .2s; }
.toast.show { opacity: 1; transform: translate(-50%, 0); }
/* Live flashes above the bottom PRN sheet */
body.map-inspect.prn-mode .toast {
  bottom: calc(min(52dvh, 520px) + 12px);
  top: auto;
}
@media (prefers-reduced-motion: reduce) { .toast { transition: opacity .2s; } }

/* ============================================================
   KD Labs font pairing — Space Grotesk (body) + Redaction (serif display)
   self-hosted woff2 (same files as kd-labs), zero external requests
   ============================================================ */
@font-face { font-family: "Space Grotesk"; font-style: normal; font-weight: 300 700; font-display: swap;
  src: url(/fonts/space-grotesk-latin.woff2) format("woff2"); }
@font-face { font-family: "Space Grotesk"; font-style: normal; font-weight: 300 700; font-display: swap;
  src: url(/fonts/space-grotesk-latinext.woff2) format("woff2");
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF; }
@font-face { font-family: "Redaction 20"; font-style: normal; font-weight: 400; font-display: swap;
  src: url(/fonts/redaction-20-latin.woff2) format("woff2"); }
@font-face { font-family: "Redaction 20"; font-style: normal; font-weight: 700; font-display: swap;
  src: url(/fonts/redaction-20-bold-latin.woff2) format("woff2"); }
@font-face { font-family: "Redaction"; font-style: normal; font-weight: 400; font-display: swap;
  src: url(/fonts/redaction-latin.woff2) format("woff2"); }

:root {
  --sans: "Space Grotesk", ui-sans-serif, system-ui, -apple-system, sans-serif;
  --font-display: "Redaction 20", Georgia, "Times New Roman", serif;
  --font-display-fine: "Redaction", Georgia, "Times New Roman", serif;
}

/* the pairing move: headlines in the Redaction serif, body stays Space Grotesk */
h1, h2, .seat-head h2 { font-family: var(--font-display); font-weight: 700; letter-spacing: 0; }

/* =================================================================
   XIO-STYLE DARK FLOATING LAYOUT  (consolidated — replaces all prior
   light/mono/mobile-vN overrides). Full-bleed map; logo + icons float
   top; a bordered (no-shadow) card floats bottom and expands into the
   seat detail. Body font Space Grotesk, headlines Redaction.
   ================================================================= */

/* ---- near-black palette (XIO) + light monochrome chrome ---- */
:root {
  --bg: #0e0f12; --bg-2: #181a1f; --panel: #16181c; --sea: #0e0f12;
  --line: #2a2d33; --line-2: #383c45;
  --ink: #e9eaed; --ink-dim: #9a9da4; --ink-faint: #6b6f77;
  --accent: #eceef1; --accent-2: #eceef1;
  --land: #1c2026; --land-hi: #2a2f37; --stroke: var(--bg); --select: #ffffff;
  color-scheme: dark;
  --accent-fg: #0e0f12;
  --badge-fg: #0e0f12;
  --link: var(--accent);
  --focus: var(--accent);
  --surface-hover: #20242b;
  --surface-hover-2: #171c24;
  --surface-soft: rgba(255,255,255,.025);
  --surface-soft-2: rgba(255,255,255,.04);
  --glass: rgba(20,22,26,.72);
  --glass-strong: rgba(20,22,26,.92);
  --topbar-strip: rgba(9, 11, 15, .94);
  --tooltip-bg: rgba(8,11,16,.94);
  --dialog-backdrop: rgba(4,7,11,.72);
  --shadow-pop: 0 14px 40px rgba(0,0,0,.5);
  --shadow-soft: 0 6px 22px rgba(0,0,0,.45);
  --stage-top: #15171c;
  --bento-page-top: #1a1c21;
  --label-shadow: 0 2px 30px rgba(0,0,0,.72), 0 1px 3px rgba(0,0,0,.55);
  --state-emblem-bg: rgba(255,255,255,.055);
  --land-muted: #31353e;
  --danger: #b8323a;
  --danger-hi: #cc3a43;
  --danger-fg: #ffffff;
  --control-radius: 12px;
  --grid-line: transparent;
  --grid-size: 24px;
  /* ---- motion vocabulary (one source of truth; compositor-only props only) ---- */
  --dur-1: 90ms; --dur-2: 140ms; --dur-3: 200ms; --dur-4: 260ms;
  --ease-out: cubic-bezier(0, 0, 0.2, 1);      /* entrances / user-triggered */
  --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1); /* reflow */
}

html[data-theme="light"] {
  color-scheme: light;
  --bg: #f5f7fa;
  --bg-2: #ffffff;
  --panel: #ffffff;
  --sea: #f1f4f8;
  --line: #d8dee8;
  --line-2: #b7c1cd;
  --ink: #151a21;
  --ink-dim: #55606d;
  --ink-faint: #64707d;
  --accent: #151a21;
  --accent-fg: #ffffff;
  --accent-2: #925f00;
  --badge-fg: #ffffff;
  --link: #1d4ed8;
  --focus: #2563eb;
  --land: #dbe3ec;
  --land-hi: #cbd5df;
  --stroke: #ffffff;
  --select: #111827;
  --surface-hover: #eef2f7;
  --surface-hover-2: #e7edf4;
  --surface-soft: #f8fafc;
  --surface-soft-2: #eef2f7;
  --glass: rgba(255,255,255,.78);
  --glass-strong: rgba(255,255,255,.94);
  --topbar-strip: rgba(255,255,255,.94);
  --tooltip-bg: rgba(255,255,255,.96);
  --dialog-backdrop: rgba(15,23,42,.32);
  --shadow-pop: none;
  --shadow-soft: none;
  --stage-top: #ffffff;
  --bento-page-top: #ffffff;
  --label-shadow: none;
  --state-emblem-bg: rgba(15,23,42,.055);
  --land-muted: #c6ced8;
  --danger: #b8323a;
  --danger-hi: #9f2932;
  --danger-fg: #ffffff;
  --grid-line: transparent;
}

/* #bento-content is display:contents — its children join #state-bento's flex. */
#bento-content { display: contents; }
body.bento-on #bento-content > * { position: relative; z-index: 1; }

body { font-family: var(--sans); }
#app { display: block; position: relative; height: 100vh; height: 100dvh; }

/* ---- full-bleed map canvas ---- */
#stage {
  position: fixed; inset: 0; z-index: 1; border: 0;
  /* the grid is part of the stage background, so it stays behind the map. */
  background:
    linear-gradient(to right,  var(--grid-line) 1px, transparent 1px) 0 0 / var(--grid-size) var(--grid-size),
    linear-gradient(to bottom, var(--grid-line) 1px, transparent 1px) 0 0 / var(--grid-size) var(--grid-size),
    radial-gradient(120% 90% at 50% 0%, var(--stage-top) 0%, var(--sea) 72%);
}
#loading, #tooltip, #tap-hint, #seats { position: relative; z-index: 2; }
/* The map owns the visible band between the floating top chrome and the bottom card.
   JS keeps --map-top/--map-h in sync with the real chrome/card heights on resize.
   Head script seeds --map-h/--map-top so the first paint is already near-final size. */
#map {
  margin-top: var(--map-top, 70px);
  height: var(--map-h, calc(100% - var(--map-top, 70px) - 200px));
}
/* Sidebar collapsed preference applied in <head> before paint (desktop only). */
@media (min-width: 640px) {
  html.sb-pref-collapsed #app { margin-left: 60px; }
}
/* Brief hide while PRN switches Parliament → DUN, so the whole-country DUN
   recolour never flashes before Johor is isolated. */
body.tier-switching #map,
body.tier-switching #seats,
body.tier-switching #state-outlines {
  opacity: 0;
  pointer-events: none;
}
/* While a state is isolated, let the map paint OUTSIDE its band box: during the detail
   pop the band is already small while the state holds at full size — the default SVG
   clip read as a hard line slicing the state's bottom. Only the isolated state is
   visible (outstate seats are opacity 0) and the card (z-30) covers it as it rises. */
body.state-open #map { overflow: visible; }

/* ---- floating top bar: logo left, actions + theme right ---- */
#topbar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 50;   /* stays above the lifted map when a state is open */
  display: flex; align-items: center; gap: 8px;
  background: none; border: 0; flex-wrap: nowrap;
  padding: max(12px, env(safe-area-inset-top)) 14px 10px;
  pointer-events: none;
  /* room for absolute-centred MyPolitik title */
  min-height: calc(max(12px, env(safe-area-inset-top)) + 44px + 10px);
}
#topbar > * { pointer-events: auto; }
/* Theme toggle hidden while product is dark-only (light mode unreadable on PRN). */
.theme-toggle,
[data-theme-toggle] {
  display: none !important;
}
/* right cluster: bento close/toggle · theme (always) · hamburger — theme is last-but-menu so it stays top-right */
.topbar-end {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
  min-width: 0;
}
.brand { flex-direction: row; align-items: center; }
.brand .mark { font-size: 18px; }
.brand .tag { display: none; }
.brand-home {
  min-height: 44px;
  display: flex;
  align-items: center;
  padding: 0 12px;
  font: inherit;
  line-height: 1.05;
  background: var(--glass);
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--ink);
  cursor: pointer;
  backdrop-filter: blur(8px);
}
.brand-home:hover { border-color: var(--line-2); }
.mobile-menu {
  display: contents;
}
/* the map-controls menu slot is only populated on mobile (JS relocates tier/mode there);
   empty on desktop, where the controls live in the search card */
.menu-map-controls:empty { display: none; }
.mobile-menu-btn {
  display: none;
}
.topicons { display: flex; align-items: center; gap: 8px; margin-left: auto; }
/* theme + language live in .topbar-end — always visible (map, bento, politicians) */
.topbar-theme { margin-left: 0; flex: 0 0 auto; order: 3; }
.topbar-end .topbar-lang { order: 2; flex: 0 0 auto; }
.topbar-end .mobile-menu-btn { order: 4; }
.topbar-end .topbar-actions { order: 1; }
.topbar-lang {
  background: var(--glass);
  border: 1px solid var(--line);
  border-radius: var(--control-radius);
  backdrop-filter: blur(8px);
  overflow: hidden;
}
.topbar-lang button {
  min-width: 40px;
  min-height: 44px;
  padding: 0 10px;
  font-size: 11px;
  font-weight: 600;
}
/* when menu is open as display:contents, don't let topicons steal right-side space */
@media (min-width: 640px) {
  #topbar > .mobile-menu,
  #topbar .topicons { display: none; }
}
.iconbtn {
  width: 44px; height: 44px; display: grid; place-items: center; padding: 0;
  background: var(--glass); border: 1px solid var(--line); border-radius: var(--control-radius);
  color: var(--ink-dim); cursor: pointer; backdrop-filter: blur(8px);
  transition: color .15s, border-color .15s;
}
.iconbtn svg { width: 18px; height: 18px; }
.nav-icon {
  width: 18px; height: 18px; display: block;
  stroke: currentColor; stroke-width: 1.85; stroke-linecap: round; stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.iconbtn:hover { color: var(--ink); border-color: var(--line-2); }
.iconbtn:active { transform: scale(.92); }
.iconbtn[hidden] { display: none; }   /* the base display:grid would otherwise defeat the hidden attr */
.iconbtn.top-live .live-dot { width: 9px; height: 9px; }   /* the election shortcut = a red pulse */
#mobile-menu-btn {
  display: none;
}
.top-controls {
  position: fixed;
  top: max(12px, env(safe-area-inset-top));
  left: 50%;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  transform: translateX(-50%);
  pointer-events: auto;
}
.top-controls .seg.chip {
  background: var(--glass);
  border-color: var(--line);
  backdrop-filter: blur(8px);
}
.top-controls .seg.chip button {
  min-height: 44px;
  padding: 8px 14px;
}
.lang-seg {
  background: var(--glass); border: 1px solid var(--line); border-radius: var(--control-radius);
  backdrop-filter: blur(8px); overflow: hidden;
}
.lang-seg button { min-width: 44px; min-height: 44px; padding: 9px 9px; font-size: 11px; }

@media (max-width: 860px) {
  /* topbar stays visible in map-inspect too — Danial: logo top-left + menu top-right
     AT ALL TIMES (the band and state label start below it; see syncMapToCard). */
  #tooltip {
    display: none !important;
  }
  body.state-open #state-label {
    top: var(--state-label-top, max(12px, calc(var(--map-top, 8px) + 4px)));
    font-size: clamp(28px, 8vw, 38px);
  }
  #seats .seat.state-hover,
  #seats.overview .seat.state-hover:hover {
    filter: none;
  }
}
/* Hamburger + dropdown menu — ONLY below the sidebar breakpoint. From 640px up
   the fixed rail owns navigation, so the layout stays consistent across sizes. */
@media (max-width: 639px) {
  #mobile-menu-btn {
    display: grid;
  }
  /* the left brand button IS the logo/home at phone widths — the absolutely-
     centered title slot would duplicate it and paint over the badge/lang cluster.
     Hide the whole slot (not just the pill) so nothing centered can collide. */
  #topbar-context, .topbar-title { display: none !important; }
  .mobile-menu {
    position: fixed;
    top: calc(max(12px, env(safe-area-inset-top)) + 54px);
    /* right-anchored dropdown, same as the 861-1239 band — full-bleed left/right
       made the tier/mode pills comically wide on wide-but-short viewports */
    right: 10px;
    left: auto;
    width: min(360px, calc(100vw - 20px));
    z-index: 60;
    display: none;
    gap: 10px;
    padding: 10px;
    background: var(--glass-strong);
    border: 1px solid var(--line);
    border-radius: 16px;
    backdrop-filter: blur(12px);
    pointer-events: auto;
  }
  body.mobile-menu-open .mobile-menu {
    display: grid;
  }
  .mobile-menu .top-controls,
  .mobile-menu .menu-map-controls {
    position: static;
    left: auto;
    top: auto;
    width: 100%;
    display: grid;
    grid-template-columns: 1fr;
    gap: 8px;
    transform: none;
  }
  .mobile-menu .top-controls .seg.chip,
  .mobile-menu .menu-map-controls .seg.chip {
    width: 100%;
  }
  .mobile-menu .top-controls .seg.chip button,
  .mobile-menu .menu-map-controls .seg.chip button {
    flex: 1 1 0;
    min-width: 0;
  }
  .mobile-menu .topicons {
    display: flex;
    align-items: center;
    flex-wrap: wrap;          /* the fuller nav (Map · Politicians · PRN · News · Pledges · Info · Share · lang) wraps instead of overflowing */
    gap: 8px;
    width: 100%;
    margin-left: 0;
    padding-top: 10px;
    border-top: 1px solid var(--line);
  }
  .mobile-menu .top-map-btn {
    display: grid;
  }
  .mobile-menu .lang-seg {
    margin-left: auto;
  }
}

/* (medium-width hamburger band removed — the sidebar rail now covers ≥640px,
   so the hamburger exists only in the ≤639px block above) */

@media (max-width: 430px) {
  #topbar { padding-left: 12px; padding-right: 12px; gap: 8px; }   /* one alignment line: buttons = card = info box */
  .brand-home { padding-inline: 10px; }
  #topbar .brand .mark { font-size: 16px; }
  .mobile-menu .topicons { gap: 6px; }
  .mobile-menu .top-controls,
  .mobile-menu .menu-map-controls {
    width: 100%;
    gap: 6px;
  }
  .mobile-menu .top-controls .seg.chip button,
  .mobile-menu .menu-map-controls .seg.chip button {
    padding: 8px 10px;
    font-size: 11px;
  }
}

/* ---- info card: pops up under the top nav, same card style ---- */
#info-card {
  position: fixed; top: 62px; right: 14px; z-index: 55;
  width: min(360px, calc(100vw - 28px));
  background: var(--panel); border: 1px solid var(--line); border-radius: 16px;
  box-shadow: none; padding: 16px;
}
#info-card[hidden] { display: none; }
.info-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.info-head h2 { font-size: 18px; margin: 0; }
.info-head .card-back { width: 44px; height: 44px; font-size: 14px; }
#info-card p { font-size: 13px; line-height: 1.55; margin: 10px 0 0; }
#info-card .src { margin-top: 12px; }

/* ---- floating bottom card (search/controls ⇄ seat detail) ---- */
#panel {
  position: fixed; left: 0; right: 0; bottom: 0; top: auto; z-index: 30;
  display: flex; justify-content: center; align-items: flex-end;
  background: none; border: 0; overflow: visible;
  padding: 0 12px calc(12px + env(safe-area-inset-bottom));
}
/* empty home search card: bottom air matches topbar air above the MyPolitik logo
   (topbar uses max(12px, safe-area-inset-top) above the brand border) */
#panel.empty {
  padding-bottom: max(12px, env(safe-area-inset-bottom));
}
#panel-empty {
  transform-origin: bottom center;   /* the minimize collapse grows/shrinks from the bottom */
  max-height: var(--panel-card-max-h, none);
  overflow-y: auto;
  overscroll-behavior: contain;
}
#panel-empty, #panel-seat, #panel-state {
  width: 100%; max-width: 560px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 20px;
  box-shadow: none; padding: 12px;
}
@media (prefers-reduced-motion: reduce) {
  #panel, #panel-empty, #panel-seat, #panel-state { transition: none; }
}
#panel-seat, #panel-state {
  padding: 16px;
  overflow-y: auto;
  overscroll-behavior: contain;
}
#panel-state {
  display: flex;
  flex-direction: column;
}
#panel.state-summary #panel-state {
  height: auto;
  max-height: var(--panel-card-max-h, calc(100dvh - 86px));
}
#panel.seat-detail #panel-state {
  height: auto;
  max-height: var(--panel-card-max-h, calc(100dvh - 70px));
}
#panel.seat-detail #panel-state > .state-head {
  display: none;
}
#panel.seat-detail #state-info {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}
/* the card shows exactly one view at a time (toggled by the [hidden] attrs in JS) */
#panel.empty #panel-seat, #panel.empty #panel-state { display: none; }
#panel:not(.empty) #panel-empty { display: none; }
#panel-empty[hidden], #panel-seat[hidden], #panel-state[hidden] { display: none; }
/* belt-and-braces: the overview search/controls card must NEVER be stranded invisible
   by a leftover minimize animation. minimizeCard() fades #panel-empty with fill:forwards
   (opacity→0) when a state opens, and a backgrounded tab can freeze that fill so the JS
   cancel() misses it — the search bar then "disappears". When #panel-empty IS the shown
   overview card (class empty, not hidden), force it fully visible; !important beats the
   stray WAAPI fill. Safe: no OTHER animation ever targets this card (minimize runs while
   the class is NOT .empty). */
#panel.empty #panel-empty:not([hidden]) { opacity: 1 !important; transform: none !important; }

/* ---- state card: header + a mini-map of that state's districts ---- */
.state-head { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.state-h { min-width: 0; }
.state-h h2 { font-size: 18px; margin: 0; line-height: 1.1; }
.state-h .muted { font-size: 12px; }
.state-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
}
.state-actions[hidden] { display: none; }
.share-icon {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 12px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--ink);
  cursor: pointer;
  font-size: 18px;
  line-height: 1;
  padding: 0;
}
.share-icon svg { width: 20px; height: 20px; }
.share-icon:hover { border-color: var(--line-2); background: var(--surface-hover); }
.share-icon:disabled,
.share-icon[aria-busy="true"] {
  opacity: .62;
  cursor: progress;
}
.map-inspect-toggle {
  display: none;
}
.map-inspect-toggle[hidden] {
  display: none !important;
}
.card-back {
  flex: 0 0 auto; width: 44px; height: 44px; display: grid; place-items: center;
  border-radius: 12px; background: var(--bg-2); border: 1px solid var(--line);
  color: var(--ink-dim); cursor: pointer; font-size: 18px; line-height: 1; padding: 0;
}
.card-back:hover { color: var(--ink); border-color: var(--line-2); }
#panel-seat .card-back { width: auto; min-width: 44px; height: 44px; padding: 0 12px; gap: 6px; font-size: 13px; margin-bottom: 12px; }
.state-map-wrap { width: 100%; height: 300px; }
#state-map { width: 100%; height: 100%; display: block; }
/* same non-scaling rule as .bento-seat / .seat — mini map viewBoxes also differ per state */
.mini-seat {
  stroke: var(--line-2);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
  stroke-linejoin: round;
  cursor: pointer;
  transition: filter .12s;
}
.mini-seat:hover { filter: brightness(1.3) saturate(1.1); stroke: var(--accent); stroke-width: 1.5; }
.mini-seat.sel { stroke: var(--select); stroke-width: 1.8; paint-order: stroke; }

/* info under the state map: coalition make-up by default, the tapped district's detail when chosen */
#state-info { margin-top: 14px; border-top: 1px solid var(--line); padding-top: 14px; }
.state-info-h { font-size: 12px; margin: 0 0 8px; }
.state-section {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}
.state-section:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.state-brief {
  display: grid;
  gap: 12px;
  padding: 13px 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: linear-gradient(180deg, rgba(255,255,255,.035), rgba(255,255,255,.012));
}
.state-brief.is-election {
  border-color: rgba(255,120,120,.38);
  background: linear-gradient(180deg, rgba(255,90,90,.11), rgba(255,90,90,.025));
}
.state-brief-kicker {
  display: flex;
  align-items: center;
  gap: 7px;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.state-brief h3 {
  margin: 4px 0 0;
  font-size: 20px;
  line-height: 1.08;
}
.state-brief p {
  margin: 6px 0 0;
  color: var(--ink-dim);
  font-size: 13px;
  line-height: 1.45;
}
.state-brief-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.state-brief-chip {
  min-height: 28px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 100%;
  padding: 5px 8px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface-soft);
  color: var(--ink-dim);
  font-size: 12px;
  line-height: 1.25;
  overflow-wrap: anywhere;
}
.state-brief-chip b { color: var(--ink); font-weight: 700; }
.state-brief-chip .sw {
  width: 8px;
  height: 8px;
  border-radius: 4px;
  flex: 0 0 auto;
  border: 1px solid rgba(231,237,244,.22);
}
.state-brief .prn-open-btn { margin-top: 0; }
.state-tap-hint { font-size: 12px; margin: 12px 0 0; text-align: center; }
.state-turnout { font-size: 12px; margin-top: 8px; }
.state-stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  margin-top: 12px;
}
.state-stat {
  min-width: 0;
  min-height: 72px;
  display: grid;
  align-content: start;
  gap: 5px;
  padding: 10px 11px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface-soft);
}
.state-stat-label {
  color: var(--ink-dim);
  font-size: 11px;
  line-height: 1.2;
}
.state-stat-value {
  min-width: 0;
  color: var(--ink);
  font-size: 16px;
  font-weight: 600;
  line-height: 1.15;
  overflow-wrap: anywhere;
}
.state-stat-note {
  min-width: 0;
  color: var(--ink-faint);
  font-size: 11px;
  line-height: 1.25;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.state-bloc {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.state-bloc .sw {
  width: 9px;
  height: 9px;
  border-radius: 4px;
  border: 1px solid rgba(231,237,244,.22);
  flex: 0 0 auto;
}
#state-info .seat-head { border-bottom: 0; padding-bottom: 0; margin-bottom: 12px; }
#state-info .seat-actions { margin-top: 14px; }
.map-inspect-tray {
  display: none;
}
.map-inspect-tray[hidden] {
  display: none;
}
.map-inspect-choice {
  min-width: 0;
  display: grid;
  gap: 10px;
}
.map-inspect-row {
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 10px;
}
.map-inspect-select {
  flex: 1 1 auto;
  min-width: 0;
  position: relative;
}
.map-inspect-select-button {
  width: 100%;
  min-height: 46px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 12px;
  align-items: center;
  gap: 10px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--bg-2);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 750;
  line-height: 1.2;
  text-align: left;
  padding: 0 12px;
  cursor: pointer;
}
.map-inspect-select-button span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.map-inspect-select-caret {
  width: 8px;
  height: 8px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  opacity: .78;
  transform: rotate(45deg) translateY(-2px);
  transform-origin: center;
  transition: transform var(--dur-2) var(--ease-out);
}
.map-inspect-select.open .map-inspect-select-caret {
  transform: rotate(225deg) translate(-1px, -1px);
}
.map-inspect-select-list {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(100% + 6px);
  z-index: 80;
  display: flex;
  flex-direction: column;
  padding: 4px;
  border: 1px solid var(--line-2);
  border-radius: 12px;
  background: var(--glass-strong);
  box-shadow: var(--shadow-pop);
  backdrop-filter: blur(10px);
}
.map-inspect-select-list[hidden] {
  display: none;
}
/* search box pinned above the scrollable option list */
.map-inspect-search-wrap { padding: 2px 2px 6px; }
.map-inspect-search {
  width: 100%; font: inherit; font-size: 12px; padding: 7px 11px;
  border-radius: 8px; border: 1px solid var(--line); background: var(--bg-2); color: var(--ink);
}
.map-inspect-search:focus { outline: none; border-color: var(--focus); }
.map-inspect-search::placeholder { color: var(--ink-faint); }
.map-inspect-options {
  display: grid; gap: 2px;
  max-height: min(168px, 30dvh); overflow-y: auto; overscroll-behavior: contain;
}
.map-inspect-option[hidden] { display: none; }
.map-inspect-option-yb { font-weight: 500; font-size: 11px; }
.map-inspect-noresult { padding: 12px 10px; font-size: 12px; text-align: center; }
.map-inspect-option {
  width: 100%;
  min-height: 36px;
  display: block;
  padding: 8px 10px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--ink-dim);
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 700;
  line-height: 1.2;
  text-align: left;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.map-inspect-option:hover,
.map-inspect-option:focus-visible {
  color: var(--ink);
  background: rgba(236, 241, 247, .10);
}
.map-inspect-option:focus-visible {
  outline: 1px solid rgba(236, 241, 247, .46);
  outline-offset: -1px;
}
.map-inspect-option[aria-selected="true"] {
  color: var(--ink);
  background: rgba(236, 241, 247, .16);
}
.map-inspect-select-button:focus-visible {
  outline: 2px solid rgba(236, 241, 247, .84);
  outline-offset: 2px;
}
.map-inspect-locate {
  flex: 0 0 auto;
}
.map-inspect-more {
  flex: 0 0 auto;
  min-height: 46px;
  padding: 0 15px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--accent);
  color: var(--bg);
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 800;
  cursor: pointer;
}
.map-inspect-more:focus-visible {
  outline: 2px solid rgba(236, 241, 247, .84);
  outline-offset: 2px;
}
.map-inspect-overview {
  min-width: 0;
  display: grid;
  gap: 4px;
  padding: 2px 2px 0;
}
.map-inspect-overview span {
  color: var(--ink-faint);
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.map-inspect-overview strong {
  min-width: 0;
  color: var(--ink);
  font-size: 16px;
  line-height: 1.2;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.map-inspect-overview p {
  min-width: 0;
  margin: 0;
  color: var(--ink-dim);
  font-size: 12px;
  line-height: 1.35;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.seat-district-switcher {
  display: grid;
  gap: 8px;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}
.seat-district-switcher .map-inspect-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 46px;
  align-items: center;
}
.seat-district-switcher .map-inspect-more {
  display: none;
}
.seat-district-switcher .map-inspect-select-list {
  top: auto;
  bottom: calc(100% + 6px);
  max-height: min(156px, 28dvh);
}
.map-inspect-details {
  min-height: 44px;
  padding: 0 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--accent);
  color: var(--bg);
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 800;
  cursor: pointer;
}
.seat-tabs {
  display: flex;
  gap: 6px;
  margin: 0 0 12px;
  padding-bottom: 2px;
  overflow-x: auto;
  scrollbar-width: none;
}
.seat-tabs::-webkit-scrollbar { display: none; }
.seat-detail-main { min-width: 0; }
.seat-tab {
  flex: 0 0 auto;
  min-height: 48px;
  padding: 8px 12px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--bg-2);
  color: var(--ink-dim);
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
}
.seat-tab:hover { color: var(--ink); border-color: var(--line-2); background: var(--surface-hover); }
.seat-tab.on { color: var(--accent-fg); background: var(--accent); border-color: var(--accent); }
.seat-tab:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.seat-tabpanel { min-width: 0; }

/* ---- "In the Dewan" tab: Hansard activity ---- */
.dewan-activity .dewan-none { margin: 4px 0 0; }
.dewan-excerpt {
  margin: 10px 0 0; padding: 10px 12px;
  background: var(--bg); border: 1px solid var(--line); border-radius: 12px;
}
.dewan-excerpt p { margin: 6px 0 0; font-size: 13px; line-height: 1.55; color: var(--ink); }
.dewan-excerpt-head { display: flex; justify-content: space-between; gap: 10px; font-size: 11px; }
.dewan-excerpt-head a { color: var(--accent-2); text-decoration: none; white-space: nowrap; }
.dewan-excerpt-head a:hover { text-decoration: underline; }
.dewan-excerpt-sec {
  margin-top: 4px; font-size: 10px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-faint);
}
.dewan-activity .state-info-h { margin-top: 16px; }
.dewan-coverage { margin-top: 14px; }
.dewan-coverage + .note { margin-top: 8px; }
/* ---- Dewan activity page: the Hansard league table ---- */
.dewan-page { max-width: 900px; margin: 0 auto; }
.dewan-tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin: 14px 0 4px; }
.dewan-tile {
  display: flex; flex-direction: column; gap: 2px;
  padding: 12px 14px; background: var(--bg-2); border: 1px solid var(--line); border-radius: 12px;
}
.dewan-tile .muted { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }
.dewan-tile b { font-size: 16px; line-height: 1.25; }
.dewan-controls { flex-wrap: wrap; }
.dewan-sorts { flex: 0 0 auto; }
.dewan-table { margin-top: 8px; border: 1px solid var(--line); border-radius: 12px; overflow: hidden; }
.dewan-tr {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr) 64px 70px 70px 64px 96px;
  gap: 8px; align-items: center;
  width: 100%; padding: 9px 12px; margin: 0; border: 0; text-align: left;
  background: transparent; color: var(--ink); font: inherit; cursor: pointer;
  border-bottom: 1px solid color-mix(in oklab, var(--line) 60%, transparent);
}
.dewan-tr:last-child { border-bottom: 0; }
button.dewan-tr:hover { background: var(--surface-hover, var(--bg-2)); }
.dewan-th {
  cursor: default; font-size: 10px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--ink-faint); background: var(--bg-2);
}
.dewan-rank { color: var(--ink-faint); font-size: 11px; }
.dewan-mp { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.dewan-mp b { font-size: 13px; line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dewan-mp .muted { font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dewan-coal { display: flex; justify-content: flex-start; }
.dewan-num { text-align: right; font-size: 12px; }
.dewan-th .dewan-num { font-size: 10px; }
.dewan-page-note { margin-top: 14px; }
@media (max-width: 680px) {
  .dewan-tr { grid-template-columns: 26px minmax(0, 1fr) 52px 58px 52px; padding: 9px 10px; }
  .dewan-col-qa, .dewan-col-last { display: none; }
  .dewan-tiles { grid-template-columns: 1fr 1fr; }
  .dewan-tile:first-child { display: none; }
}

/* compact Hansard strip in the bento seat spotlight */
.bento-spot-dewan { margin-top: 10px; }
.dewan-spot-link { color: var(--accent-2); font-size: 11px; text-decoration: none; white-space: nowrap; }
.dewan-spot-link:hover { text-decoration: underline; }
.seat-overview {
  display: grid;
  gap: 10px;
}
.seat-yb-card {
  display: grid;
  gap: 5px;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface-soft);
}
.seat-yb-card span,
.seat-metric span,
.module-empty-kicker,
.module-empty-needed span {
  color: var(--ink-faint);
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.seat-yb-card strong {
  color: var(--ink);
  font-size: 18px;
  line-height: 1.15;
}
.seat-yb-card p {
  margin: 0;
  color: var(--ink-dim);
  font-size: 13px;
  line-height: 1.4;
}
.seat-metrics {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}
.seat-metric {
  min-width: 0;
  display: grid;
  gap: 5px;
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface-soft);
}
.seat-metric b {
  min-width: 0;
  color: var(--ink);
  font-family: var(--mono);
  font-size: 16px;
  line-height: 1.1;
  overflow-wrap: anywhere;
}
.seat-metric small {
  color: var(--ink-faint);
  font-size: 11px;
}
.rows.seat-score-row { margin-top: 10px; }
.module-empty {
  display: grid;
  gap: 8px;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface-soft);
}
.module-empty h3 {
  margin: 0;
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.25;
}
.module-empty p {
  margin: 0;
  color: var(--ink-dim);
  font-size: 13px;
  line-height: 1.45;
}
.module-empty-needed {
  display: grid;
  gap: 5px;
  margin-top: 2px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
}
.candidate-module,
.voting-guide {
  display: grid;
  gap: 10px;
}
.module-source {
  display: grid;
  gap: 4px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface-soft);
}
.module-source span {
  color: var(--ink-faint);
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.module-source p {
  margin: 0;
  color: var(--ink-dim);
  font-size: 12px;
  line-height: 1.4;
}
.candidate-vote-share {
  display: grid;
  gap: 9px;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background:
    linear-gradient(180deg, rgba(255,255,255,.035), rgba(255,255,255,.018)),
    rgba(255,255,255,.018);
}
.candidate-vote-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.candidate-vote-head h3 {
  margin: 0;
  color: var(--ink);
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 700;
  line-height: 1.2;
}
.candidate-vote-head span {
  color: var(--ink-faint);
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.2;
  white-space: nowrap;
}
.candidate-vote-sides {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 16px;
  align-items: end;
}
.candidate-vote-sides.single {
  grid-template-columns: minmax(0, 1fr);
}
.candidate-vote-side {
  min-width: 0;
  display: grid;
  gap: 3px;
}
.candidate-vote-side.right {
  justify-items: end;
  text-align: right;
}
.candidate-vote-side-name {
  min-width: 0;
  max-width: 100%;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--ink);
  font-size: 13px;
  font-weight: 800;
  line-height: 1.2;
}
.candidate-vote-side-name .candidate-vote-dot {
  flex: 0 0 auto;
}
.candidate-vote-side.right .candidate-vote-side-name {
  flex-direction: row-reverse;
}
.candidate-vote-side-text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.candidate-vote-side-meta {
  color: var(--ink-faint);
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  line-height: 1.2;
  text-transform: uppercase;
}
.candidate-vote-bar {
  display: flex;
  width: 100%;
  height: 34px;
  overflow: hidden;
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 12px;
  background: rgba(255,255,255,.04);
}
.candidate-vote-seg {
  flex-basis: 0;
  flex-shrink: 1;
  min-width: 3px;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  padding: 0 8px;
  color: #fff;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 800;
  line-height: 1;
  text-shadow: 0 1px 2px rgba(0,0,0,.45);
  box-shadow: inset -1px 0 rgba(9,13,18,.7);
}
.candidate-vote-seg:last-child {
  box-shadow: none;
}
.candidate-vote-seg span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.candidate-vote-seg.middle {
  justify-content: center;
}
.candidate-vote-seg.right-edge {
  justify-content: flex-end;
}
.candidate-vote-key {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 6px 10px;
}
.candidate-vote-key-item {
  min-width: 0;
  display: grid;
  grid-template-columns: 8px minmax(0, 1fr) auto;
  align-items: center;
  gap: 7px;
  color: var(--ink-dim);
  font-size: 11px;
  line-height: 1.3;
}
.candidate-vote-dot {
  width: 8px;
  height: 8px;
  border-radius: 999px;
  box-shadow: 0 0 0 1px rgba(255,255,255,.18);
}
.candidate-vote-key-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.candidate-vote-key-item b {
  color: var(--ink);
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 800;
}
.candidate-list {
  display: grid;
  gap: 8px;
}
.candidate-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 8px 12px;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface-soft);
}
.candidate-card.won {
  border-color: color-mix(in srgb, var(--accent) 40%, var(--line));
  background: var(--surface-soft-2);
}
.candidate-main {
  min-width: 0;
  display: flex;
  gap: 9px;
  align-items: flex-start;
}
.candidate-rank {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  min-width: 30px;
  height: 30px;
  padding: 0 6px;
  border: 1px solid var(--line);
  border-radius: 8px;
  color: var(--ink-dim);
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
}
.candidate-card h3 {
  margin: 0;
  color: var(--ink);
  font-family: var(--sans);
  font-size: 14px;
  line-height: 1.25;
}
.candidate-card p {
  margin: 3px 0 0;
  color: var(--ink-faint);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.candidate-side {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 6px;
  flex-wrap: wrap;
}
.candidate-status {
  color: var(--ink-dim);
  font-size: 12px;
  white-space: nowrap;
}
.candidate-meta {
  grid-column: 1 / -1;
  color: var(--ink-dim);
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.35;
}
@media (max-width: 430px) {
  .candidate-vote-head {
    align-items: flex-start;
    flex-direction: column;
    gap: 3px;
  }
  .candidate-vote-bar {
    height: 32px;
  }
  .candidate-vote-seg {
    padding: 0 5px;
    font-size: 10px;
  }
  .candidate-vote-sides {
    gap: 10px;
  }
  .candidate-vote-side-name {
    font-size: 12px;
  }
  .candidate-vote-key {
    grid-template-columns: 1fr;
  }
}
.voting-privacy {
  margin: 0;
  padding: 11px 12px;
  border: 1px solid var(--line);
  border-radius: 12px;
  color: var(--ink-dim);
  background: var(--surface-soft);
  font-size: 13px;
  line-height: 1.45;
}
.voting-actions {
  display: grid;
  gap: 8px;
}
.voting-action {
  min-height: 44px;
  display: grid;
  gap: 5px;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface-soft);
  color: var(--ink);
  text-decoration: none;
}
.voting-action:hover {
  border-color: var(--line-2);
  background: var(--surface-hover);
  text-decoration: none;
}
.voting-action strong {
  font-size: 14px;
  line-height: 1.25;
}
.voting-action span {
  color: var(--ink-dim);
  font-size: 13px;
  line-height: 1.4;
}
.voting-action em {
  color: var(--accent);
  font-style: normal;
  font-size: 12px;
  font-weight: 700;
}

/* idle card: search + locate on one row; tier/mode may wrap under on narrow */
.search-row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  flex-wrap: wrap;
}
/* Search field + location fab always share a single row */
.search-main {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1 1 260px;
  min-width: 0;
}
.search {
  flex: 1 1 auto;
  min-width: 0;
  position: relative;
}
.search-main .loc-fab {
  flex: 0 0 auto;
  width: 46px;
  height: 46px;
  min-width: 46px;
}
@media (max-width: 560px) {
  .search-row {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
  }
  .search-main {
    flex: 1 1 auto;
    width: 100%;
  }
  .find-actions {
    width: 100%;
    justify-content: flex-start;
    flex-wrap: wrap;
  }
}
.search input {
  width: 100%; background: var(--bg-2); border: 1px solid var(--line); border-radius: 12px;
  padding: 13px 14px; font-size: 16px; font-family: var(--sans); color: var(--ink);
  /* 16px minimum: anything smaller makes iOS Safari auto-zoom the page on focus */
}
.search input::placeholder { color: var(--ink-faint); }
.search input:focus { border-color: var(--line-2); outline: none; }
.search input:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-color: var(--focus); }
.results { top: auto; bottom: calc(100% + 8px); left: 0; right: 0; width: auto;
  background: var(--panel); border-color: var(--line-2); box-shadow: 0 -16px 40px rgba(0,0,0,.5); }

/* ---- state landing makeup: coalition share of current YBs (mobile tray) ----
   Mirrors home #nat-glance — coloured line + PH 12 · BN 8 · … counts. */
.state-makeup-glance {
  margin: 0 0 12px;
  padding: 0;
  outline: none;
}
.state-makeup-glance-h {
  font-size: 11px;
  letter-spacing: .02em;
  margin: 0 0 8px;
}
.state-makeup-glance .state-makeup-bar,
.state-makeup-glance .sharebar {
  margin: 0;
  height: 10px;
  border-radius: 999px;
}
.state-makeup-glance .sharebar-key {
  display: flex;
  flex-wrap: wrap;
  gap: 5px 12px;
  margin-top: 8px;
  font-size: 11px;
}
.state-makeup-glance .sharebar-key .sk {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  white-space: nowrap;
}
.state-makeup-glance .sharebar-key .sw {
  width: 9px;
  height: 9px;
  border-radius: 4px;
  flex: 0 0 auto;
}
/* PRN mobile sheet: sit the makeup bar in the padded summary band */
body.map-inspect.prn-mode .state-makeup-glance {
  margin: 0;
  padding: 4px 16px 12px;
  border-bottom: 1px solid var(--line);
}
body.map-inspect:not(.prn-mode) .state-makeup-glance {
  padding: 0 2px 4px;
}

/* ---- national at-a-glance: GE15 bloc bar under the home search ----
   Default: colour bar only. Hover / focus-within reveals PH 82 · PN 74 · …
   Touch (no hover): counts stay open so they remain discoverable. */
.nat-glance {
  /* equal air: gap under search = card bottom padding (12px) so the bar sits mid-band */
  margin: 12px 0 0;
  padding: 0;
  border: 0;
  outline: none;
  cursor: default;
  /* Reserve bar height even before results load so the card (and map band) don't jump */
  min-height: 10px;
}
/* Keep layout slot while hidden — avoids "something appears under search" flash */
.nat-glance[hidden] {
  display: block !important;
  visibility: hidden;
  pointer-events: none;
  min-height: 10px;
}
.nat-glance-h,
.nat-glance-maj { display: none; } /* title + majority live in aria-label */
.nat-glance .sharebar {
  margin: 0;
  height: 10px;
  border-radius: 999px;
}
.nat-glance .sharebar-key {
  display: flex;
  flex-wrap: wrap;
  gap: 5px 13px;
  margin: 0;
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  pointer-events: none;
  transition: max-height .22s ease, opacity .18s ease, margin .18s ease;
}
.nat-glance .sharebar-key .sk {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  white-space: nowrap;
}
/* reveal counts while open — JS adds .is-open on enter and keeps it ~3s after leave */
.nat-glance.is-open .sharebar-key {
  max-height: 6em;
  opacity: 1;
  margin-top: 8px;
  pointer-events: auto;
}
@media (hover: none) {
  .nat-glance .sharebar-key {
    max-height: 6em;
    opacity: 1;
    margin-top: 8px;
    pointer-events: auto;
  }
}
@media (prefers-reduced-motion: reduce) {
  .nat-glance .sharebar-key { transition: none; }
}

@media (min-aspect-ratio: 1/1) {
  .nat-glance .sharebar {
    height: 12px;
  }
  .nat-glance .sharebar-key {
    gap: 6px 16px;
    font-size: 13px;
    line-height: 1.35;
  }
}

.card-row { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
.find-actions { flex: 0 0 auto; display: flex; align-items: center; justify-content: flex-end; gap: 8px; flex-wrap: wrap; }
/* the map controls (Parliament/DUN · State/Party) now live beside the search, bigger to
   match the search bar rather than the small top-bar chips they used to be */
.find-actions .seg.chip { border-radius: 12px; }
.find-actions .seg.chip button { min-height: 48px; padding: 10px 17px; font-size: 13px; }
.seg.chip { background: var(--bg-2); border: 1px solid var(--line); border-radius: var(--control-radius); }
.seg.chip button { min-height: 44px; padding: 8px 13px; font-size: 12px; }
.seg.chip button.on { background: var(--accent); color: var(--bg); font-weight: 600; }
.seg.chip button:hover:not(:disabled):not(.on) { background: var(--surface-hover); color: var(--ink); }

/* circular locate button — the XIO "send" position */
.loc-fab {
  position: relative;
  flex: 0 0 auto; width: 46px; height: 46px; padding: 0;
  display: grid; place-items: center; border-radius: 999px;
  background: var(--accent); color: var(--bg); border: 0; cursor: pointer;
  transition: filter .15s;
}
.loc-fab svg { width: 22px; height: 22px; }
.loc-fab:hover { filter: brightness(.9); }
.loc-fab[aria-busy="true"] {
  cursor: progress;
  filter: brightness(.95);
}
.loc-fab[aria-busy="true"] svg {
  opacity: 0;
}
.loc-fab[aria-busy="true"]::after {
  content: "";
  position: absolute;
  inset: 0;
  width: 18px;
  height: 18px;
  margin: auto;
  border: 2px solid rgba(14,15,18,.28);
  border-top-color: var(--bg);
  border-radius: 999px;
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.find-status { margin: 10px 2px 0; }

/* ---- things we no longer show in the card ---- */
#reset { display: none !important; }
.empty-more[hidden] { display: none; }
.sheet-handle { display: none !important; }

/* ---- seat detail card (reuses .seat-head/.rows/.seat-actions, dark) ---- */
.seat-actions { margin-top: 16px; }
.share-btn { background: var(--bg-2); }

/* ---- share-card preview dialog ---- */
.card-preview {
  width: min(420px, calc(100vw - 28px));
  max-height: min(92dvh, 760px);
  padding: 0;
  color: var(--ink);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: 0 24px 70px rgba(0,0,0,.62);
  overflow: hidden;
}
.card-preview::backdrop { background: rgba(0,0,0,.62); }
.card-preview-shell {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  max-height: min(92dvh, 760px);
}
.card-preview-head,
.card-preview-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px;
}
.card-preview-head {
  justify-content: space-between;
  border-bottom: 1px solid var(--line);
}
.card-preview-head h2 {
  margin: 0;
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 600;
}
.card-preview-close {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--bg-2);
  color: var(--ink-dim);
  cursor: pointer;
}
.card-preview-close svg { width: 18px; height: 18px; }
.card-preview-close:hover { color: var(--ink); border-color: var(--line-2); }
.card-preview-frame {
  min-height: 0;
  display: grid;
  place-items: center;
  overflow: hidden;
  padding: 14px;
  background: #101217;
}
.card-preview-frame img {
  display: block;
  width: auto;
  max-width: 100%;
  max-height: min(62dvh, 560px);
  height: auto;
  border-radius: 0;
  border: 0;
  background: #0f141b;
}
.card-preview-actions {
  border-top: 1px solid var(--line);
}
.preview-download {
  min-height: 44px;
  width: 100%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 0;
  border-radius: 12px;
  background: var(--accent);
  color: var(--bg);
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
}
.preview-download svg { width: 18px; height: 18px; }
.preview-download:hover { filter: brightness(.92); }
.preview-download:disabled { opacity: .6; cursor: progress; }

/* ---- state-first overview: hide internal seat borders so states read as blobs ---- */
#seats.overview .seat { stroke: var(--stroke); stroke-width: 1; }
#seats.overview .seat:hover { stroke: var(--stroke); filter: brightness(1.12); }
.state-outline { display: none; fill: #fff; filter: url(#state-outline-filter); pointer-events: none; opacity: .88; }
/* hover (mouse only): light up every seat of the state under the cursor, uniformly */
#seats .seat.state-hover, #seats.overview .seat.state-hover:hover { filter: brightness(1.32); }

/* ---- spotlight: with a state card open, the open state stays lit, the rest dim back ---- */
#seats .seat { transition: opacity .1s ease, filter .1s ease; }
#seats.overview .seat.outstate { opacity: .24; }
#seats.overview .seat.instate { opacity: 1; }

/* ---- isolate & zoom: tap a state → the others fade out, its districts get borders,
   and the map zooms in (the big map becomes the district map; card rises behind) ---- */
#seats.isolated .seat.outstate { opacity: 0; pointer-events: none; }
#seats.isolated .seat.instate {
  opacity: 1;
  stroke: rgba(255,255,255,.58);
  stroke-width: 1.2;
  paint-order: stroke;
}
#seats.isolated .seat.instate:hover {
  stroke: rgba(255,255,255,.9);
  stroke-width: 1.8;
  filter: brightness(1.08);
}
#seats.isolated .seat.sel {
  stroke: #fff;
  stroke-width: 1.8;
  paint-order: stroke;
}
#seats.returning .seat {
  transition-duration: 220ms;
  transition-timing-function: var(--ease-in-out);
}
#seats.isolated.returning .seat.outstate {
  opacity: 1;
  pointer-events: none;
}
.selected-texture {
  pointer-events: none;
  fill: url(#selected-district-lines);
  stroke: rgba(255,255,255,.95);
  stroke-width: 1.1;
  vector-effect: non-scaling-stroke;
  paint-order: stroke;
}
@media (max-width: 860px) {
  /* Mobile overview uses one white perimeter per state, not white lines around
     every district. The outline layer is built from merged state silhouettes. */
  #state-outlines { display: block; }
  .state-outline { display: block; }
  body.state-open #state-outlines { display: none; }
  #seats.overview:not(.isolated) .seat,
  #seats.overview:not(.isolated) .seat:hover {
    filter: none;
    stroke: none;
  }
  #seats.isolated .seat.instate,
  #seats.isolated .seat.instate:hover {
    filter: none;
    stroke: rgba(255,255,255,.68);
    stroke-width: 1.3;
  }
  #seats.isolated .seat.sel {
    stroke: #fff;
    stroke-width: 1.8;
  }
  .selected-texture {
    stroke-width: 1.1;
  }
}
.state-map-wrap { display: none; }   /* the isolated state IS the map now — drop the card mini-map */

/* ---- state open: keep the same bottom card, expanding it upward by view state. ---- */
body.state-open #stage { z-index: 1; pointer-events: auto; }
body.state-open #seats .seat.instate { pointer-events: auto; }   /* districts stay tappable */
body.state-open #tap-hint { display: none; }                     /* overview hint off while drilled in */
body.state-open #panel-state {
  max-width: 620px;
  justify-content: flex-start;
  transform-origin: bottom center;
}

@media (max-width: 860px) {
  body.state-open .map-inspect-toggle {
    display: grid;
  }
  body.map-inspect #panel {
    padding: 0 10px calc(8px + env(safe-area-inset-bottom));
  }
  body.map-inspect #panel-state {
    max-height: none;
    overflow: visible;
    padding: 14px;
    border-radius: 16px;
  }
  body.map-inspect #panel-state .state-head {
    display: none;
  }
  body.map-inspect #panel-state .card-back,
  body.map-inspect #panel-state .share-icon {
    width: 44px;
    height: 44px;
    border-radius: 12px;
  }
  body.map-inspect #panel-state .state-h h2 {
    font-size: 16px;
    line-height: 1.05;
  }
  body.map-inspect #panel-state .state-h .muted {
    font-size: 11px;
  }
  body.map-inspect #panel-state #state-info,
  body.map-inspect #panel-state .state-actions {
    display: none;
  }
  body.map-inspect #panel-state #map-inspect-tray {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
    gap: 10px;
    padding-top: 0;
    border-top: 0;
    max-height: min(58dvh, 560px);
    overflow-x: hidden;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }
  body.map-inspect #panel-state #map-inspect-tray.has-select {
    grid-template-columns: minmax(0, 1fr);
  }
  /* Non-PRN: district dropdown opens upward — don't clip it inside the tray */
  body.map-inspect:not(.prn-mode) #panel-state {
    overflow: visible;
  }
  body.map-inspect:not(.prn-mode) #panel-state #map-inspect-tray {
    overflow: visible;
    max-height: none;
  }
  body.map-inspect:not(.prn-mode) #map-inspect-tray:has(.map-inspect-select.open),
  body.map-inspect.district-picker-open #map-inspect-tray {
    overflow: visible;
    z-index: 60;
  }
  body.map-inspect.district-picker-open #panel-state {
    overflow: visible;
    z-index: 60;
  }
  /*
   * PRN night mobile:
   * - Map stays visible above the sheet, painted by live leaders (enterPrnMode).
   * - Sheet is a bottom panel (not full-screen) so the choropleth is readable.
   * - Block flow inside the sheet (no nested flex:1) for iOS Safari stability.
   */
  body.map-inspect.prn-mode #stage,
  body.map-inspect.prn-mode #map {
    visibility: visible;
    pointer-events: auto;
  }
  body.map-inspect.prn-mode #state-label {
    visibility: visible;
  }
  body.map-inspect.prn-mode #panel {
    padding: 0;
    top: auto;
    bottom: 0;
    align-items: flex-end;
  }
  body.map-inspect.prn-mode #panel-state {
    max-width: none;
    width: 100%;
    height: auto;
    max-height: none;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
    overflow: visible;
  }
  body.map-inspect.prn-mode #panel-state #map-inspect-tray {
    display: block;
    height: auto;
    max-height: min(52dvh, 520px);   /* leave ~half the screen for the coloured map */
    min-height: 0;
    overflow-x: hidden;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    border-radius: 16px 16px 0 0;
    border: 0;
    border-top: 1px solid var(--line);   /* neutral edge — no red accent */
    background: #0e0f12;
    background-image: none;
    box-shadow: 0 -8px 28px rgba(0, 0, 0, .35);
    padding-top: 10px;
    padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
  }
  body.map-inspect.prn-mode #topbar {
    z-index: 40;
  }
  body.map-inspect.prn-mode #map-inspect-tray,
  body.map-inspect.prn-mode .map-inspect-choice {
    gap: 0;
    border-radius: 16px 16px 0 0;
  }
  body.map-inspect.prn-mode .map-inspect-choice {
    display: block;
    overflow: visible;
    background: transparent;
    box-shadow: none;
    padding: 0;
    min-height: 0;
  }
  body.map-inspect.prn-mode .prn-mobile-summary,
  body.map-inspect.prn-mode .prn-mobile-summary.is-live,
  body.map-inspect.prn-mode .prn-mobile-summary.is-compact {
    display: block;
    border: 0;
    border-radius: 0;
    background: transparent;
    padding: 8px 16px 12px;
    overflow: visible;
    min-height: 0;
    flex: none;
  }
  /* Header stack: title → meta → metrics → bar — give each block air */
  body.map-inspect.prn-mode .prn-mobile-title {
    font-size: 16px;
    line-height: 1.3;
    margin: 0 0 6px;
    gap: 10px;
  }
  body.map-inspect.prn-mode .prn-mobile-title .prn-live-chip {
    padding: 4px 9px;
    font-size: 11px;
  }
  body.map-inspect.prn-mode .prn-mobile-meta {
    font-size: 13px;
    line-height: 1.4;
    margin: 0 0 14px;
  }
  body.map-inspect.prn-mode .prn-mobile-metrics {
    gap: 8px;
    margin: 0 0 16px;
  }
  body.map-inspect.prn-mode .prn-mobile-metric {
    padding: 12px 10px 11px;
    border-radius: 12px;
  }
  body.map-inspect.prn-mode .prn-mobile-metric span {
    font-size: 11px;
    margin-bottom: 4px;
    letter-spacing: .04em;
  }
  body.map-inspect.prn-mode .prn-mobile-metric b {
    font-size: 20px;
    line-height: 1.15;
  }
  body.map-inspect.prn-mode .prn-live-tally-h {
    font-size: 12px;
    margin: 0 0 8px;
    line-height: 1.35;
  }
  body.map-inspect.prn-mode .sharebar.prn-live-bar {
    margin: 0 0 10px;
    height: 14px;
    min-height: 14px;
    border-radius: 8px;
  }
  body.map-inspect.prn-mode .sharebar-key {
    gap: 6px 14px;
    font-size: 13px;
    margin: 0 0 6px;
    line-height: 1.4;
  }
  body.map-inspect.prn-mode .prn-majority {
    font-size: 12px;
    line-height: 1.45;
    margin: 4px 0 14px;
  }
  body.map-inspect.prn-mode .prn-mobile-cands {
    margin: 4px 0 16px;
    min-height: 48px;
  }
  body.map-inspect.prn-mode .mobile-live-board .bento-kicker,
  body.map-inspect.prn-mode .prn-mobile-board .bento-kicker {
    margin: 0 0 8px;
    font-size: 12px;
    letter-spacing: .06em;
  }
  body.map-inspect.prn-mode .mobile-live-board .bento-live-filters,
  body.map-inspect.prn-mode .prn-mobile-board .bento-live-filters {
    gap: 6px;
    margin: 0 0 12px;
  }
  body.map-inspect.prn-mode .mobile-live-board .bento-livetable-head,
  body.map-inspect.prn-mode .prn-mobile-board .bento-livetable-head {
    gap: 10px;
    margin-bottom: 4px;
  }
  body.map-inspect.prn-mode .mobile-live-board,
  body.map-inspect.prn-mode .prn-mobile-board,
  body.map-inspect.prn-mode .mobile-live-board .bento-livetable,
  body.map-inspect.prn-mode .prn-mobile-board .bento-livetable {
    display: block;
    overflow: visible;
    min-height: 0;
    flex: none;
    height: auto;
  }
  body.map-inspect.prn-mode .mobile-live-board .bento-livetable-head,
  body.map-inspect.prn-mode .prn-mobile-board .bento-livetable-head {
    position: relative;
    z-index: 2;
  }
  /* Table has its own scroll so header/filters stay in the sheet flow */
  body.map-inspect.prn-mode .mobile-live-board .bento-livetable-scroll,
  body.map-inspect.prn-mode .prn-mobile-board .bento-livetable-scroll {
    display: block;
    max-height: min(28dvh, 280px);
    min-height: 140px;
    overflow-x: auto;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    position: relative;
    z-index: 1;
    border: 1px solid color-mix(in oklab, var(--line) 80%, transparent);
    border-radius: 12px;
    background: color-mix(in oklab, var(--bg-2) 55%, transparent);
  }
  body.map-inspect.prn-mode .prn-mobile-cands {
    display: flex;
    position: relative;
    z-index: 2;
  }
  body.map-inspect.prn-mode .prn-mobile-hint {
    display: none; /* redundant under live table; was painting over rows on iOS */
  }
  body.map-inspect.prn-mode .map-inspect-overview,
  body.map-inspect.prn-mode .seat-district-switcher {
    display: block;
    margin: 0;
    padding: 8px 12px 10px;
    position: relative;
    z-index: 3;
    background: #0e0f12;
  }
  /* Keep pick-seat + locate on ONE row (display:block was stacking the loc fab under the select) */
  body.map-inspect.prn-mode .map-inspect-row {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 8px;
    margin: 0;
    padding: 8px 12px 10px;
    position: sticky;
    bottom: 0;
    z-index: 4;
    background: #0e0f12;
    border-top: 1px solid color-mix(in oklab, var(--line) 70%, transparent);
    padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px));
  }
  body.map-inspect.prn-mode .map-inspect-row .map-inspect-select {
    flex: 1 1 auto;
    min-width: 0;
  }
  body.map-inspect.prn-mode .map-inspect-row .map-inspect-locate,
  body.map-inspect.prn-mode .map-inspect-row .map-inspect-more {
    flex: 0 0 auto;
    width: 46px;
    height: 46px;
    min-width: 46px;
  }
  body.map-inspect.prn-mode .seat-district-switcher {
    border-top: 1px solid color-mix(in oklab, var(--line) 70%, transparent);
    position: sticky;
    bottom: 0;
    z-index: 4;
    padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px));
  }
  body.map-inspect.prn-mode .seat-district-switcher .map-inspect-row {
    border-top: 0;
    padding: 0;
    position: static;
  }
  body.map-inspect.prn-mode .sharebar.prn-live-bar {
    min-height: 12px;
    height: 12px;
    flex-shrink: 0;
    width: 100%;
  }
  body.map-inspect.prn-mode .sharebar.prn-live-bar span {
    min-width: 2px;
    flex: 0 0 auto;
  }
  body.map-inspect .map-inspect-select-list {
    top: auto;
    bottom: calc(100% + 6px);
    max-height: min(42dvh, 320px);
    z-index: 120;
    overflow: hidden; /* chrome only; options scroll inside */
  }
  body.map-inspect .map-inspect-options {
    max-height: min(36dvh, 280px);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }
  body.map-inspect .map-inspect-select {
    position: relative;
    z-index: 5;
  }
  body.map-inspect .map-inspect-select.open {
    z-index: 120;
  }
  body.map-inspect #panel.state-summary #panel-state,
  body.map-inspect #panel.seat-detail #panel-state {
    max-height: none;
  }
  #panel.seat-detail #panel-state {
    overflow: hidden;
  }
  #panel.seat-detail #state-info {
    min-height: 0;
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    overflow: visible;
  }
  #panel.seat-detail .seat-detail-main {
    min-height: 0;
    flex: 1 1 auto;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-bottom: 12px;
    scrollbar-width: none;
  }
  #panel.seat-detail .seat-detail-main::-webkit-scrollbar {
    display: none;
  }
  #panel.seat-detail .seat-district-switcher {
    position: relative;
    z-index: 5;
    flex: 0 0 auto;
    margin-top: 10px;
    background: var(--panel);
  }
}

/* ---- wider than a phone (landscape / desktop): the bottom sheet becomes a FLOATING card
   over a full-bleed map. An open state zooms into the map full-bleed with its detail in the
   floating card — NOT the tall mobile backdrop (which left a lot of empty space here). ---- */
@media (min-aspect-ratio: 1/1) {
  #panel { padding-bottom: calc(24px + env(safe-area-inset-bottom)); }
  /* desktop: sit the search card higher — roomy bottom margin balances the map gap above */
  #panel.empty {
    padding-bottom: max(80px, calc(11vh + env(safe-area-inset-bottom)));
  }
  /* cap the map width on wide screens and CENTRE it (grid stays full-bleed behind). The map
     is aspect-locked, so a width cap also bounds its height. */
  #map {
    max-width: 1280px; margin-left: auto; margin-right: auto;
    height: var(--map-h, calc(100% - var(--map-top, 70px) - 200px));
  }
  /* the card widens with the viewport on wider screens (not a lost 560px under a huge map),
     capped so the content stays readable */
  #panel-empty, #panel-seat, #panel-state {
    max-width: clamp(560px, 62vw, 820px);
    box-shadow: 0 22px 60px rgba(0,0,0,.55);
  }
  body.state-open #stage { z-index: 1; pointer-events: auto; }
  body.state-open #map { height: var(--map-h, calc(100% - var(--map-top, 70px) - 200px)); }
  body.state-open #panel { top: auto; bottom: 0; align-items: flex-end; padding-top: 0; }
  body.state-open #panel-state {
    max-width: clamp(560px, 62vw, 820px);
    justify-content: flex-start;
    transform-origin: bottom center;
  }
  #panel.state-summary #panel-state { height: auto; }
  #panel.seat-detail #panel-state { height: auto; max-height: var(--panel-card-max-h, calc(100dvh - 70px)); }
}

@media (prefers-reduced-motion: reduce) { #seats .seat { transition: none; } }

/* ---- tactile press feedback: a small compositor-only scale on :active ---- */
.seg button, .lang-seg button, .brand-home, .iconbtn, .share-btn, .share-icon, .card-back, .seat-tab, .map-inspect-details, .map-inspect-more, .map-inspect-select-button, .map-inspect-option,
.card-preview-close, .preview-download, .find-loc {
  transition-property: background, color, border-color, transform;
  transition-duration: var(--dur-1);
  transition-timing-function: var(--ease-out);
}
.seg button:focus-visible, .lang-seg button:focus-visible, .brand-home:focus-visible, .iconbtn:focus-visible,
.card-back:focus-visible, .share-btn:focus-visible, .share-icon:focus-visible, .seat-tab:focus-visible, .map-inspect-details:focus-visible, .map-inspect-more:focus-visible, .map-inspect-select-button:focus-visible,
.card-preview-close:focus-visible, .preview-download:focus-visible, .loc-fab:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}
.seg button:active:not(:disabled), .lang-seg button:active, .brand-home:active, .card-back:active, .seat-tab:active,
.share-icon:active, .map-inspect-details:active, .map-inspect-more:active, .map-inspect-select-button:active, .map-inspect-option:active, .card-preview-close:active { transform: scale(.94); }
.iconbtn:active { transform: scale(.9); }
.share-btn:active, .preview-download:active, .find-loc:active:not(:disabled) { transform: scale(.985); }
@media (prefers-reduced-motion: reduce) {
  .seg button:active, .lang-seg button:active, .brand-home:active, .iconbtn:active,
  .share-btn:active, .card-back:active, .share-icon:active, .seat-tab:active, .map-inspect-details:active, .map-inspect-more:active, .map-inspect-select-button:active, .map-inspect-option:active,
  .card-preview-close:active, .preview-download:active, .find-loc:active { transform: none; }
}

/* ---- surface entrances: menus, dropdowns and popovers pop from their anchor instead of
   appearing binarily. Compositor-only (opacity+transform); reduced-motion gets a plain fade. ---- */
@keyframes pop-down { from { opacity: 0; transform: translateY(-6px) scale(.985); } to { opacity: 1; transform: none; } }
@keyframes pop-up   { from { opacity: 0; transform: translateY(6px)  scale(.985); } to { opacity: 1; transform: none; } }
@keyframes fade-in-only { from { opacity: 0; } to { opacity: 1; } }
body.mobile-menu-open .mobile-menu { transform-origin: top center;  animation: pop-down var(--dur-2) var(--ease-out); }
#info-card:not([hidden])           { transform-origin: top right;   animation: pop-down var(--dur-2) var(--ease-out); }
.results:not([hidden])             { transform-origin: bottom center; animation: pop-up var(--dur-2) var(--ease-out); }
.map-inspect-select-list:not([hidden]) { transform-origin: bottom center; animation: pop-up var(--dur-2) var(--ease-out); }
/* the just-selected district's line texture draws in rather than snapping on */
.selected-texture { animation: fade-in-only 120ms var(--ease-out); }
/* dialogs and the state dashboard rise in the same way — once per open: both only
   animate on the hidden→shown switch, so live re-renders inside them never replay it */
@keyframes rise-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.pol-modal[open], .card-preview[open] { animation: pop-up var(--dur-3) var(--ease-out); }
.pol-modal[open]::backdrop, .card-preview[open]::backdrop { animation: fade-in-only var(--dur-3) var(--ease-out); }
body.bento-on #state-bento { animation: rise-in var(--dur-4) var(--ease-out); }
@media (prefers-reduced-motion: reduce) {
  body.mobile-menu-open .mobile-menu,
  #info-card:not([hidden]),
  .results:not([hidden]),
  .map-inspect-select-list:not([hidden]),
  .pol-modal[open], .card-preview[open],
  body.bento-on #state-bento { animation: fade-in-only 120ms linear; }
  .selected-texture { animation: none; }
}

/* ---- tray YB overview is a button now: same look at rest, honest feedback under the hand ---- */
button.map-inspect-overview {
  border: 0;
  background: transparent;
  font: inherit;
  text-align: left;
  cursor: pointer;
  border-radius: 12px;
  padding: 8px 10px 6px;
  margin: -6px -8px -4px;
  width: calc(100% + 16px);
  transition: background var(--dur-1) var(--ease-out), transform var(--dur-1) var(--ease-out);
}
button.map-inspect-overview:hover { background: rgba(236, 241, 247, .05); }
button.map-inspect-overview:active { transform: scale(.985); }
button.map-inspect-overview:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { button.map-inspect-overview:active { transform: none; } }

/* ---- narrow phones: let the controls row breathe ---- */
@media (max-width: 380px) {
  .seg.chip button { padding: 8px 10px; font-size: 11px; }
  .loc-fab { width: 44px; height: 44px; }
  /* keep the district row's controls one height (the select/More were 46 next to a 44 fab) */
  .map-inspect-select-button, .map-inspect-more { min-height: 44px; }
}

/* ---- fluid card type + spacing: scales UP with viewport width on wide screens, giving the
   card bigger text and more height/room. Each clamp's MINIMUM is the existing phone size, and
   vw is tiny on phones/tablets, so those are unchanged — it only grows on wide desktops.
   Continuous (no breakpoint jump), so no transition needed. ---- */
#panel-seat, #panel-state { padding: clamp(16px, 1.55vw, 28px); }
#panel .seat-head h2 { font-size: clamp(16px, 1.9vw, 30px); }   /* min 16 = the real phone size (beats `#panel h2`) */
.seat-head .where { font-size: clamp(13px, 1.05vw, 16px); }
.seat-head .kicker { font-size: clamp(11px, 0.82vw, 13px); }
#panel .state-h h2 { font-size: clamp(16px, 1.6vw, 25px); }
.state-h .muted { font-size: clamp(12px, 0.95vw, 15px); }
.rows dt { font-size: clamp(12.5px, 1.02vw, 15.5px); }
.rows dd { font-size: clamp(14px, 1.18vw, 18px); }
.rows dt, .rows dd { padding-block: clamp(10px, 0.95vw, 16px); }
.sharebar { height: clamp(12px, 1.05vw, 18px); }
.sharebar-key { font-size: clamp(11px, 0.92vw, 14px); }
.state-stat-label, .state-stat-note { font-size: clamp(11px, 0.86vw, 13px); }
.state-stat-value { font-size: clamp(15px, 1.12vw, 18px); }

@media (min-width: 720px) {
  .state-stats { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 360px) {
  .state-stats { grid-template-columns: 1fr; }
  .seat-metrics { grid-template-columns: 1fr; }
}

@media (min-aspect-ratio: 1/1) and (max-height: 700px) {
  #panel.seat-detail #panel-state {
    max-height: var(--panel-card-max-h, calc(100dvh - 160px));
    padding: 14px 18px;
  }
  #panel.seat-detail #state-info {
    margin-top: 0;
    padding-top: 0;
  }
  #panel.seat-detail #state-info .seat-head {
    margin-bottom: 6px;
  }
  #panel.seat-detail #state-info .seat-head h2 {
    margin-block: 2px;
    font-size: 24px;
  }
  #panel.seat-detail .rows dt,
  #panel.seat-detail .rows dd {
    padding-block: 5px;
  }
  #panel.seat-detail .src-line {
    margin-top: 8px;
  }
}

/* PRN bottom tile: running candidates (replaces key numbers + economy).
   Do NOT use flex:1 + min-height:0 here — the stats grid row is height:auto, so
   a flex-grow child collapses to 0 and you only see the kicker bar. */
.bento-runners {
  flex: 0 0 auto;
  min-height: auto;
  gap: 12px;
}
.bento-runners-body {
  flex: 0 0 auto;
  min-height: auto;
  overflow: visible;
}
.bento-runners-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 10px;
  align-content: start;
}
.bento-runners-grid .prn-cc {
  min-height: 88px;
  background: var(--bg-2, rgba(255,255,255,.06));
  border: 1px solid var(--line, rgba(255,255,255,.1));
}
.bento-runners-grid .prn-cc.is-compact {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  padding: 12px 14px;
  text-align: left;
}
.bento-runners-grid .prn-cc.is-compact .prn-cc-head {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 10px;
  width: 100%;
}
.bento-runners-grid .prn-cc.is-compact .prn-cc-id {
  flex: 1;
  min-width: 0;
  align-items: flex-start;
  text-align: left;
}
.bento-runners-grid .prn-cc.is-compact .prn-cc-name {
  font-size: 14px;
  justify-content: flex-start;
}
.bento-runners-grid .prn-cc.is-compact .prn-cc-head .pill {
  align-self: center;
  flex: 0 0 auto;
}
.bento-runners-grid .prn-cc.is-compact .pol-photo.prn-profile-photo,
.bento-runners-grid .prn-cc.is-compact .pol-photo {
  width: 40px;
  height: 40px;
  flex: 0 0 auto;
}
/* always show a monogram if no photo — compact cards still need a face */
.bento-runners-grid .prn-cc.is-compact .prn-cc-open { display: none; }

/* EXCO / seat-context chips in PRN spotlight */
.bento-exco-chip {
  margin-top: 6px;
  padding: 6px 10px;
  border-radius: 12px;
  background: color-mix(in srgb, var(--accent, #8ab4f8) 14%, transparent);
  font-size: 12px;
  line-height: 1.35;
}
.bento-exco-kicker {
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-size: 10px;
  opacity: 0.85;
  margin-right: 6px;
}
.bento-spot-bye { margin: 4px 0 0; font-size: 12px; }
.cand-socials { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.cand-socials a {
  font-size: 11px;
  padding: 4px 8px;
  border-radius: 999px;
  border: 1px solid var(--line, rgba(255,255,255,.12));
  color: inherit;
  text-decoration: none;
}
.cand-socials a:hover { border-color: var(--accent, #8ab4f8); }

/* ===== live election (PRN16 Johor) — banner, campaign view ===== */
/* (the topbar "PRN Johor 2026" pill was retired 2026-08-02 — resurrect .live-badge
   from git history for the next live election) */
.live-dot {
  width: 7px; height: 7px; border-radius: 50%; background: #ff5a5a; flex: 0 0 auto;
  animation: live-pulse 1.6s ease-in-out infinite;
}
@keyframes live-pulse { 0%,100% { opacity: 1; transform: scale(1); } 50% { opacity: .45; transform: scale(.72); } }
@keyframes live-badge-sweep {
  0%   { transform: translateX(-120%); opacity: 0; }
  12%  { opacity: 1; }
  55%  { opacity: 1; }
  88%  { opacity: 0.35; }
  100% { transform: translateX(220%); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .live-dot { animation: none; }
}
@media (max-width: 560px) {
  #topbar { gap: 8px; padding-left: 10px; padding-right: 10px; }
}

.prn-banner {
  border: 1px solid rgba(255,120,120,.35);
  background: linear-gradient(180deg, rgba(255,90,90,.10), rgba(255,90,90,.03));
  border-radius: 12px; padding: 12px 14px; margin-bottom: 14px;
}
.prn-banner-h { display: flex; align-items: center; gap: 8px; font-family: var(--font-display); font-weight: 700; font-size: 18px; color: var(--ink); }
.prn-banner-sub { font-size: 12px; margin-top: 3px; }
.prn-open-btn {
  margin-top: 10px; width: 100%; min-height: 44px; padding: 10px 14px; border-radius: 12px;
  border: 1px solid color-mix(in oklab, var(--danger) 65%, var(--line)); background: var(--danger); color: var(--danger-fg);
  font-family: var(--sans); font-weight: 700; font-size: 14px; cursor: pointer;
}
.prn-open-btn:hover { background: var(--danger-hi); }
.prn-open-btn:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.prn-open-compact { margin: 0 0 8px; }
.prn-summary { display: grid; gap: 14px; }
.prn-brief { margin-bottom: 0; }
.prn-countdown { font-family: var(--mono); font-size: 13px; color: var(--danger); margin-top: 6px; }
.prn-dates { margin-top: 10px; }
.prn-majority { font-size: 12px; margin: 8px 0 0; }
.prn-panel-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}
.prn-panel-card {
  min-width: 0;
  padding: 11px 12px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface-soft);
}
.prn-panel-card .sharebar { margin-top: 10px; }
.prn-check { display: inline-block; margin-top: 12px; font-size: 13px; color: var(--accent); text-decoration: none; }
.prn-check:hover { text-decoration: underline; }
.prn-mobile-summary {
  display: grid;
  gap: 8px;
  padding: 12px;
  border: 1px solid rgba(255,120,120,.34);
  border-radius: 12px;
  background: linear-gradient(180deg, rgba(255,90,90,.12), rgba(255,90,90,.03));
}
.prn-mobile-summary.is-live {
  border-color: rgba(255,90,90,.45);
  background: linear-gradient(180deg, rgba(255,70,70,.16), rgba(20,22,28,.55));
}
.prn-mobile-summary.is-compact {
  gap: 6px;
  padding: 10px 12px;
}
.prn-mobile-title {
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--ink);
  font-weight: 800;
  font-size: 14px;
  line-height: 1.25;
}
.prn-mobile-title > span:nth-child(2) {
  min-width: 0;
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.prn-mobile-title .prn-live-chip {
  flex: 0 0 auto;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .04em;
  padding: 3px 7px;
  border-radius: 999px;
  color: #fff;
  background: #e23;
}
.prn-mobile-meta,
.prn-mobile-foot,
.prn-mobile-board-h,
.prn-mobile-hint {
  color: var(--ink-dim);
  font-size: 12px;
  line-height: 1.35;
}
.prn-mobile-hint { margin: 0; }
.prn-mobile-metrics {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
}
.prn-mobile-metric {
  min-width: 0;
  padding: 8px 8px 7px;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: color-mix(in oklab, var(--surface-soft) 88%, transparent);
  text-align: center;
}
.prn-mobile-metric span {
  display: block;
  font-size: 10px;
  line-height: 1.2;
  margin-bottom: 2px;
}
.prn-mobile-metric b {
  display: block;
  font-size: 16px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  line-height: 1.1;
}
.prn-mobile-metric b small {
  font-size: 11px;
  font-weight: 600;
  color: var(--ink-dim);
  margin-left: 1px;
}
.prn-mobile-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.prn-mobile-chip {
  display: inline-flex;
  align-items: center;
  min-height: 28px;
  padding: 4px 9px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--surface-soft);
  font-size: 12px;
  color: var(--ink-dim);
}
.prn-mobile-chip b { color: var(--ink); font-weight: 700; }
.prn-mobile-board-h {
  margin-top: 2px;
  font-weight: 600;
  letter-spacing: .02em;
  text-transform: uppercase;
  font-size: 11px;
}
.prn-mobile-board {
  margin-top: 0;
}
/* Nested bento-tile chrome is for desktop dashboard only — on phone it steals
   height/width from the 56-seat table. Flatten it so filters + rows own the tray. */
.mobile-live-board .bento-livetable,
.prn-mobile-board .bento-livetable {
  background: transparent;
  border: 0;
  border-radius: 0;
  padding: 0;
  gap: 8px;
  box-shadow: none;
  backdrop-filter: none;
  background-image: none;
}
.mobile-live-board .bento-livetable-head,
.prn-mobile-board .bento-livetable-head {
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
}
.mobile-live-board .bento-kicker,
.prn-mobile-board .bento-kicker {
  font-size: 11px;
}
.mobile-live-board .bento-live-filters,
.prn-mobile-board .bento-live-filters {
  gap: 4px;
}
.mobile-live-board .bento-live-chip,
.prn-mobile-board .bento-live-chip {
  min-height: 28px;
  padding: 0 9px;
  font-size: 11px;
  position: relative;
  z-index: 2;
  pointer-events: auto;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.mobile-live-board .bento-live-filters,
.prn-mobile-board .bento-live-filters,
.mobile-live-board .bento-livetable-head,
.prn-mobile-board .bento-livetable-head {
  position: relative;
  z-index: 2;
  flex: 0 0 auto;
  pointer-events: auto;
}
.mobile-live-board .bento-livetable-scroll,
.prn-mobile-board .bento-livetable-scroll {
  max-height: min(52dvh, 420px);
  border: 0;
  border-radius: 0;
  background: transparent;
}
/* Phone: only Seat · Leader · Party (leading party) */
@media (max-width: 860px) {
  .mobile-live-board .bento-live-table .col-code,
  .mobile-live-board .bento-live-table .col-status,
  .mobile-live-board .bento-live-table .col-bloc,
  .mobile-live-board .bento-live-table .col-maj,
  .prn-mobile-board .bento-live-table .col-code,
  .prn-mobile-board .bento-live-table .col-status,
  .prn-mobile-board .bento-live-table .col-bloc,
  .prn-mobile-board .bento-live-table .col-maj {
    display: none;
  }
  .mobile-live-board .bento-live-table col.col-seat,
  .prn-mobile-board .bento-live-table col.col-seat { width: 30%; }
  .mobile-live-board .bento-live-table col.col-leader,
  .prn-mobile-board .bento-live-table col.col-leader { width: 44%; }
  .mobile-live-board .bento-live-table col.col-party,
  .prn-mobile-board .bento-live-table col.col-party { width: 26%; }
  .mobile-live-board .bento-live-table,
  .prn-mobile-board .bento-live-table {
    font-size: 13px;
  }
  .mobile-live-board .bento-live-table th,
  .mobile-live-board .bento-live-table td,
  .prn-mobile-board .bento-live-table th,
  .prn-mobile-board .bento-live-table td {
    padding: 10px 8px;
  }
  .mobile-live-board .col-party,
  .prn-mobile-board .col-party {
    font-weight: 700;
    color: var(--ink);
  }
  .mobile-live-board .col-party .sw,
  .prn-mobile-board .col-party .sw {
    width: 9px;
    height: 9px;
    border-radius: 4px;
    flex: 0 0 auto;
  }
}
.prn-mobile-cands {
  margin-top: 4px;
  min-height: 42px;
  font-size: 13px;
}
.prn-live-tally-h {
  font-size: 11px;
  font-weight: 600;
  margin: 2px 0 0;
}
.map-inspect-overview.is-live-lead {
  border-color: color-mix(in oklab, var(--accent) 35%, var(--line));
  background: color-mix(in oklab, var(--accent) 8%, var(--surface-soft));
}
.map-inspect-overview.is-live-await strong {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-dim);
}
.prn-close-btn {
  margin-top: 14px; width: 100%; min-height: 44px; padding: 8px 12px; border-radius: 12px;
  border: 1px solid var(--line-2); background: transparent; color: var(--ink-dim);
  font-family: var(--sans); font-size: 13px; cursor: pointer;
}
.prn-close-btn:hover { color: var(--ink); border-color: var(--ink-faint); }
.prn-cands { display: grid; gap: 6px; }
.prn-cand {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  border: 1px solid var(--line); border-radius: 12px; padding: 9px 11px;
  background: var(--surface-soft);
}
.prn-cand-name { font-size: 14px; color: var(--ink); min-width: 0; overflow-wrap: anywhere; }
.prn-cand .pill { flex: 0 0 auto; }
.prn-cands-compare {
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 8px;
  margin-top: 8px;
}
.prn-cands-compare:has(.prn-cc.has-profile) {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 310px), 1fr));
}
.prn-cands-compare .prn-cc { min-height: 112px; }
.prn-race-facts {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  margin: 8px 0 10px;
}
.prn-race-fact {
  min-width: 0;
  padding: 10px 11px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface-soft);
}
.prn-race-fact span {
  display: block;
  color: var(--ink-dim);
  font-size: 11px;
  line-height: 1.25;
}
.prn-race-fact b {
  display: block;
  margin-top: 3px;
  color: var(--ink);
  font-size: 14px;
  line-height: 1.2;
  overflow-wrap: anywhere;
}
.prn-note { margin-top: 12px; }
.prn-seat-head { border-bottom: 1px solid var(--line); padding-bottom: 12px; margin-bottom: 12px; }

@media (max-width: 560px) {
  .prn-panel-grid,
  .prn-race-facts {
    grid-template-columns: 1fr;
  }
  .state-brief h3 {
    font-size: 18px;
  }
}


/* ===== app-feel on touch: no page zoom, keyboard-aware bottom panel ===== */
/* pan gestures only — no double-tap-to-zoom, no page pinch-zoom (map gestures unaffected) */
html, body, #stage, #map { touch-action: pan-x pan-y; }   /* touch-action does not inherit */
/* the page itself never scrolls — a swipe that escapes a card scroller (e.g. at its top
   edge) must not rubber-band the document: that pan fires visualViewport events and eats
   the gesture (iOS: the seat card "can't scroll back up" report) */
html, body { overscroll-behavior: none; }
/* the on-screen keyboard lift is applied as a translateY TRANSFORM from JS
   (syncKeyboardInset) — iOS freezes position:fixed anchoring while the keyboard is
   open, so a bottom offset is ignored there; compositor transforms are not. */



/* typing in search (mobile): the card is keyboard-shrunk — give it entirely to the
   search box by hiding the stats blocks that sat above it. */
body.searching #stage { pointer-events: none; }
body.searching #panel { z-index: 70; }
body.searching #panel-empty { overflow: visible; }
body.searching .results {
  z-index: 90;
  pointer-events: auto;
}
@media (max-width: 860px) {
  body.searching #nat-glance,
  body.searching #empty-more { display: none; }
}


/* small tier chip riding the big state label — says which layer (DUN / Parliament)
   and toggles that layer on tap while the state stays open */
#state-label .label-tier {
  display: inline-flex; align-items: center; justify-content: center;
  vertical-align: middle; margin-left: 12px;
  font-family: var(--mono); font-weight: 700; font-size: 11px; letter-spacing: .12em;
  line-height: 1; text-transform: uppercase; color: var(--ink-dim);
  border: 1px solid var(--line-2); border-radius: 999px; padding: 5px 10px;
  text-shadow: none;
  background: color-mix(in oklab, var(--panel) 72%, transparent);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  pointer-events: auto; /* parent #state-label is pointer-events: none */
  cursor: pointer;
  appearance: none; -webkit-appearance: none;
  min-height: 28px;
  transition: color .15s, border-color .15s, background .15s, transform .12s;
}
#state-label .label-tier:hover:not(:disabled) {
  color: var(--ink);
  border-color: var(--line-2);
  background: color-mix(in oklab, var(--panel) 88%, transparent);
}
#state-label .label-tier:active:not(:disabled) {
  transform: scale(.96);
}
#state-label .label-tier:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}
#state-label .label-tier:disabled {
  opacity: .45;
  cursor: default;
}


/* polling-night chip + tally bar accents */
.prn-live-chip {
  display: inline-block; margin-left: 8px; padding: 3px 9px; border-radius: 999px;
  font-family: var(--mono); font-size: 10px; font-weight: 700; letter-spacing: .12em;
  background: #b8323a; color: #fff; vertical-align: middle;
}
.prn-live-bar { position: relative; }
.prn-live-bar::after {
  /* the majority line at 29/56 */
  content: ""; position: absolute; top: -3px; bottom: -3px; left: 51.786%;
  width: 2px; background: var(--ink); opacity: .7;
}


/* economy arrows + candidate news links */
.econ-up { color: #4caf78; font-size: 11px; }
.econ-down { color: #e05555; font-size: 11px; }
.state-ctx { margin-top: 14px; }
.prn-news { display: grid; gap: 8px; }
.prn-news-cand { display: grid; gap: 4px; }
.prn-news-name { font-size: 11px; font-family: var(--mono); letter-spacing: .04em; }
.prn-news-item {
  display: grid; gap: 2px; padding: 8px 10px; border: 1px solid var(--line);
  border-radius: 8px; background: var(--surface-soft); text-decoration: none;
}
.prn-news-item:hover { border-color: var(--line-2); background: var(--surface-hover); }
.prn-news-t { font-size: 13px; line-height: 1.35; color: var(--ink); }
.prn-news-s { font-size: 11px; }


/* ===== info-card footer: maker credit + KD logo; box aligned to the app's 12px line ===== */
.info-footer { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); display: grid; gap: 10px; }
.info-credit { font-size: 12px; margin: 0; }
.kd-logo-link { display: inline-block; width: fit-content; }
.kd-logo { height: 40px; width: auto; image-rendering: pixelated; display: block; }

@media (max-width: 860px) {
  #info-card { left: 12px; right: 12px; width: auto; }
}


/* desktop/landscape: the state card's own district finder (dropdown + locate) */
.state-district-find { margin-top: 8px; }
.state-district-find .map-inspect-row { display: flex; gap: 8px; }
.state-district-find .map-inspect-select { flex: 1 1 auto; min-width: 0; }


/* the district finder sits near the top of the desktop state card — a subtle divider
   under it separates the primary action from the summary content below */
.state-district-find-top { margin-bottom: 16px; padding-bottom: 16px; border-bottom: 1px solid var(--line); }
.state-find-section .state-district-find-top { margin-bottom: 0; padding-bottom: 0; border-bottom: 0; }

/* ===== MP profile (photo + bio) on the Current YB block & directory ===== */
.pol-photo {
  width: 72px; height: 72px; aspect-ratio: 1 / 1; box-sizing: border-box; overflow: hidden;
  border-radius: 12px; object-fit: cover; flex: 0 0 auto;
  background: var(--line); display: grid; place-items: center;
}
/* a portrait still downloading shows a soft shimmer instead of an empty box; the load
   listener in app.js marks it .is-loaded, which stops the sweep */
@keyframes photo-wait { from { background-position: 100% 0; } to { background-position: 0 0; } }
img.pol-photo:not(.is-loaded) {
  background: linear-gradient(100deg, var(--line) 35%, var(--line-2) 50%, var(--line) 65%) 0 0 / 300% 100%;
  animation: photo-wait 1.4s linear infinite;
}
@media (prefers-reduced-motion: reduce) { img.pol-photo:not(.is-loaded) { animation: none; } }
.pol-monogram { font-family: var(--font-display); font-weight: 700; font-size: 24px; line-height: 1; color: #fff; letter-spacing: .02em; }
.seat-yb-card.has-profile { gap: 10px; }
/* bento compact strip: fixed-height identity row — no bio, so the map never grows */
.seat-yb-card.is-compact { gap: 0; }
.seat-yb-card.is-compact .yb-head { align-items: center; }
.seat-yb-card.is-openable {
  cursor: pointer;
  border-radius: 12px;
  transition: background .12s ease, border-color .12s ease;
}
.seat-yb-card.is-openable:hover { background: color-mix(in oklab, var(--bg-2) 70%, transparent); }
.seat-yb-card.is-openable:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.yb-head { display: flex; gap: 12px; align-items: flex-start; }
.yb-id { min-width: 0; display: grid; gap: 3px; }
.yb-kicker { color: var(--ink-faint); font-family: var(--mono); font-size: 10px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; }
.yb-id strong { color: var(--ink); font-size: 18px; line-height: 1.15; }
.yb-ballot { font-size: 12px; }
.yb-meta { font-size: 12px; margin: 2px 0 0; }
.yb-bio { display: grid; gap: 4px; }
.yb-bio-text {
  font-size: 13px; line-height: 1.5; color: var(--ink-dim); margin: 0;
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden;
}
.yb-bio-more { font-size: 12px; white-space: nowrap; }
.pol-socials { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.pol-soc-icon {
  display: inline-grid; place-items: center; width: 34px; height: 34px; border-radius: 8px;
  border: 1px solid var(--line); background: var(--bg-2); color: var(--ink-dim);
  transition: color .12s, border-color .12s;
}
.pol-soc-icon:hover { color: var(--ink); border-color: var(--line-2); }
.pol-soc-icon:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.pol-soc-icon svg { width: 17px; height: 17px; display: block; }
.pol-socials-compact { gap: 5px; margin-top: 8px; }
.pol-socials-compact .pol-soc-icon { width: 26px; height: 26px; border-radius: 8px; }
.pol-socials-compact .pol-soc-icon svg { width: 14px; height: 14px; }
.pol-socials-unverified .pol-soc-icon { border-style: dashed; }
.yb-credit { font-size: 11px; margin: 0; }

/* ===== Politicians directory ===== */
#politicians-view, #news-view, #dewan-view { display: none; }
body.politicians-open #politicians-view, body.news-open #news-view, body.dewan-open #dewan-view { display: block; }
body.politicians-open #stage, body.politicians-open #panel,
body.news-open #stage, body.news-open #panel,
body.dewan-open #stage, body.dewan-open #panel { display: none; }
/* directory pages hide map chrome; keep centre MyPolitik title + theme/lang cluster */
body.politicians-open #brand-home,
body.politicians-open #mobile-menu-btn,
body.politicians-open #mobile-menu,
body.politicians-open #topbar-actions,
body.news-open #brand-home,
body.news-open #mobile-menu-btn,
body.news-open #mobile-menu,
body.news-open #topbar-actions,
body.dewan-open #brand-home,
body.dewan-open #mobile-menu-btn,
body.dewan-open #mobile-menu,
body.dewan-open #topbar-actions { display: none !important; }
body.politicians-open #topbar,
body.news-open #topbar,
body.dewan-open #topbar {
  display: flex;
  align-items: center;
  background: transparent;
  border: 0;
  pointer-events: none;
}
body.politicians-open #topbar .topbar-end,
body.politicians-open #topbar .topbar-context,
body.news-open #topbar .topbar-end,
body.news-open #topbar .topbar-context,
body.dewan-open #topbar .topbar-end,
body.dewan-open #topbar .topbar-context { pointer-events: auto; }
/* news full page: a readable single column of headlines (reuses the .pol-dir shell) */
.news-page { max-width: 760px; margin: 0 auto; }
.news-list { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 2px; }
.news-list .news-link { padding: 12px 12px; margin: 0 -12px; border-radius: 12px; }
.news-list .news-t { font-size: 16px; line-height: 1.4; }
.news-list li + li { border-top: 1px solid var(--line); }
.news-page .news-empty { padding: 28px 4px; font-size: 16px; }
.news-page .src-line { max-width: 760px; margin: 18px auto 0; }
.pol-dir {
  position: fixed; inset: 0; z-index: 6;
  overflow-y: auto; overscroll-behavior: contain;
  padding: clamp(22px, 5vw, 72px) clamp(14px, 4vw, 40px) 60px;
}
.pol-dir-head { max-width: 1100px; margin: 0 auto 16px; }
.pol-dir-head h1 { font-family: var(--font-display); font-size: clamp(24px, 4vw, 40px); margin: 0; }
.pol-dir-head .pol-dir-sub { color: var(--ink-dim); font-size: 13px; margin: 4px 0 0; }
.pol-back {
  display: inline-flex; align-items: center; gap: 6px; margin: 0 0 12px;
  min-height: 44px; padding: 0 14px 0 10px; border-radius: 999px; cursor: pointer;
  font: inherit; font-size: 13px; font-weight: 600; color: var(--ink);
  background: var(--bg-2); border: 1px solid var(--line);
  transition: border-color .12s ease, background .12s ease;
}
.pol-back:hover { border-color: var(--line-2); background: color-mix(in oklab, var(--bg-2) 85%, var(--ink) 15%); }
.pol-back:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.pol-back svg { flex: 0 0 auto; }
.pol-dir-controls { max-width: 1100px; margin: 0 auto 16px; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.pol-dir-controls input, .pol-dir-controls select {
  background: var(--bg-2); border: 1px solid var(--line); border-radius: 12px;
  padding: 11px 13px; font-size: 16px; font-family: var(--sans); color: var(--ink); min-height: 44px;
}
.pol-dir-search { flex: 1 1 220px; min-width: 0; }
/* party drill-down chip (set by clicking a Parties-tab card) */
.pol-party-chip {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 44px; padding: 0 14px; border-radius: 999px; cursor: pointer;
  font: inherit; font-size: 13px; font-weight: 700; letter-spacing: .02em;
  color: var(--ink); background: color-mix(in oklab, var(--accent) 16%, var(--bg-2));
  border: 1px solid color-mix(in oklab, var(--accent) 40%, var(--line));
}
.pol-party-chip:hover { background: color-mix(in oklab, var(--accent) 24%, var(--bg-2)); }
.pol-party-chip:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.pol-dir-count { max-width: 1100px; margin: 0 auto 10px; color: var(--ink-faint); font-size: 12px; font-family: var(--mono); }
.pol-grid {
  max-width: 1100px; margin: 0 auto;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px;
}
.pol-card {
  display: grid; gap: 6px; padding: 10px; border: 1px solid var(--line); border-radius: 12px;
  background: var(--surface-soft); text-align: left; cursor: pointer; color: inherit; font: inherit;
  align-content: start;
}
.pol-card:hover { border-color: var(--line-2); background: var(--surface-hover); }
.pol-card:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.pol-card-photo { position: relative; line-height: 0; }
.pol-card .pol-photo { width: 100%; height: auto; aspect-ratio: 1; border-radius: 12px; }
.pol-card .pol-monogram { font-size: 40px; }
.pol-card-badge {
  position: absolute; top: 7px; right: 7px; font-size: 11px; font-weight: 700;
  /* the photo wrapper is line-height:0 to kill the img gap — restore it here or
     the badge text ("PAS") collapses to a squeezed sliver. */
  line-height: 1.5; padding: 2px 8px; white-space: nowrap;
  box-shadow: 0 1px 6px rgba(0,0,0,.45);
}
/* uniform card height: reserve a fixed 2-line name, 1-line seat, 1-line socials */
.pol-card-name {
  font-family: var(--font-display); font-weight: 700; font-size: 16px; line-height: 1.2;
  color: var(--ink); margin-top: 2px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  min-height: 2.4em;
}
.pol-card-seat { font-size: 11px; color: var(--ink-dim); font-family: var(--mono); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pol-card .pol-socials-compact { margin-top: 2px; min-height: 26px; flex-wrap: nowrap; overflow: hidden; }
/* the socials row is always present (even for the 3 MPs with none) so heights match */
.pol-card-socials-spacer { min-height: 26px; margin-top: 2px; }
.pol-soc-more {
  display: inline-grid; place-items: center; min-width: 26px; height: 26px; padding: 0 5px;
  border-radius: 8px; border: 1px dashed var(--line); color: var(--ink-faint);
  font-family: var(--mono); font-size: 11px; flex: 0 0 auto;
}
.pol-dir-src { max-width: 1100px; margin: 20px auto 0; color: var(--ink-faint); font-size: 11px; line-height: 1.5; }
.pol-dir-empty { max-width: 1100px; margin: 30px auto; color: var(--ink-dim); text-align: center; }
.pol-party-grid {
  max-width: 1100px; margin: 0 auto;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 12px;
}
.pol-party-card {
  min-height: 44px; display: grid; gap: 12px; padding: 14px;
  border: 1px solid var(--line); border-radius: 12px;
  background: var(--surface-soft); color: inherit; font: inherit; text-align: left; cursor: pointer;
  transition: background .12s, border-color .12s, transform .04s;
}
.pol-party-card:hover { border-color: var(--line-2); background: var(--surface-hover); }
.pol-party-card:active { transform: translateY(1px); }
.pol-party-card:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.pol-party-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-width: 0; }
.pol-party-mark {
  min-width: 52px; max-width: 100%; min-height: 44px; padding: 0 13px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 12px; color: #fff; font-family: var(--font-display); font-size: 20px; font-weight: 800;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.14), 0 8px 22px rgba(0,0,0,.28);
}
.pol-party-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.pol-party-stats span {
  min-width: 0; padding: 9px 10px; border: 1px solid var(--line); border-radius: 12px;
  background: var(--surface-soft-2);
}
.pol-party-stats small { display: block; color: var(--ink-faint); font-family: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: .06em; }
.pol-party-stats b { display: block; margin-top: 3px; font-size: 20px; line-height: 1; }
.pol-party-meta { display: grid; gap: 4px; }
.pol-party-meta span { color: var(--ink-faint); font-family: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: .06em; }
.pol-party-meta b { color: var(--ink-dim); font-size: 13px; line-height: 1.35; font-weight: 600; }
.pol-party-samples { list-style: none; display: grid; gap: 6px; margin: 0; padding: 0; }
.pol-party-samples li { min-width: 0; display: grid; gap: 1px; }
.pol-party-samples b, .pol-party-samples span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pol-party-samples b { font-size: 13px; }
.pol-party-samples span { color: var(--ink-faint); font-family: var(--mono); font-size: 11px; }
.pol-party-open { align-self: end; color: var(--ink); font-size: 12px; font-weight: 700; }

/* ===== politician full-profile pop-up ===== */
.pol-modal {
  width: min(480px, calc(100vw - 28px)); max-height: min(88vh, 760px);
  margin: auto; padding: 0; border: 1px solid var(--line-2); border-radius: 16px;
  background: var(--panel); color: var(--ink); overflow: hidden;
}
.pol-modal::backdrop { background: var(--dialog-backdrop); backdrop-filter: blur(4px); }
.pol-modal-shell { padding: 18px; overflow-y: auto; max-height: inherit; overscroll-behavior: contain; }
.pol-modal-close {
  position: absolute; top: 12px; right: 12px; width: 40px; height: 40px; border-radius: 12px;
  display: grid; place-items: center; border: 1px solid var(--line); background: var(--bg-2);
  color: var(--ink-dim); cursor: pointer;
}
.pol-modal-close:hover { color: var(--ink); border-color: var(--line-2); }
.pol-modal-close svg { width: 18px; height: 18px; }
.pol-modal-head { display: flex; gap: 14px; align-items: flex-start; padding-right: 44px; }
.pol-modal-photo { width: 96px; height: 96px; border-radius: 12px; }
.pol-modal-photo.pol-monogram { font-size: 34px; }
.pol-modal-id { min-width: 0; display: grid; gap: 4px; }
.pol-modal-id h2 { font-family: var(--font-display); font-size: 22px; line-height: 1.1; margin: 0; }
.pol-modal-party { margin: 2px 0 0; font-size: 13px; color: var(--ink-dim); }
.pol-modal-seat { font-size: 13px; margin: 0; }
.pol-modal-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); gap: 8px; margin-top: 16px; }
.pol-stat { display: grid; gap: 3px; padding: 10px; border: 1px solid var(--line); border-radius: 12px; background: var(--surface-soft); }
.pol-stat span { color: var(--ink-faint); font-family: var(--mono); font-size: 10px; letter-spacing: .05em; text-transform: uppercase; }
.pol-stat b { color: var(--ink); font-family: var(--mono); font-size: 18px; line-height: 1.1; }
.pol-stat small { color: var(--ink-faint); font-size: 11px; }
.pol-modal-bio { font-size: 14px; line-height: 1.6; color: var(--ink-dim); margin: 16px 0 0; }
.pol-modal-edu { margin-top: 14px; }
.pol-modal .pol-socials { margin-top: 14px; }
.pol-modal-links { display: flex; gap: 16px; margin-top: 12px; font-size: 13px; }
.pol-modal-seatbtn {
  margin-top: 18px; width: 100%; min-height: 46px; border-radius: 12px;
  border: 1px solid var(--line-2); background: var(--bg-2); color: var(--ink);
  font-family: var(--sans); font-size: 14px; font-weight: 600; cursor: pointer;
}
.pol-modal-seatbtn:hover { border-color: var(--accent); color: var(--accent); }
.pol-modal-close:focus-visible, .pol-modal-seatbtn:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}

/* ===== PRN / politician full bento pop-up =====
   Hierarchy: party-tinted hero → primary role/stats → prose → quieter meta tiles.
   Avoids the "wall of identical grey boxes" look. */
.candidate-modal {
  width: min(1080px, calc(100vw - 28px));
  max-height: min(92dvh, 900px);
  border-radius: 20px;
  border: 1px solid color-mix(in oklab, var(--line) 80%, var(--ink) 20%);
  background: var(--panel);
  box-shadow:
    0 0 0 1px color-mix(in oklab, var(--ink) 4%, transparent),
    0 28px 80px rgba(0, 0, 0, .55);
}
.cand-modal-shell {
  position: relative;
  max-height: inherit;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 18px;
  --cc: var(--accent);
  --ccfg: #0b0e13;
}
.candidate-modal .cand-modal-close {
  z-index: 5;
  top: 10px;
  right: 10px;
}
.cand-grid {
  display: block;
  column-count: 2;
  column-gap: 14px;
  column-fill: balance;
}
.cand-tile {
  min-width: 0;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: color-mix(in oklab, var(--bg-2) 88%, var(--panel));
  padding: 14px 16px;
  box-shadow: inset 0 1px 0 color-mix(in oklab, var(--ink) 4%, transparent);
}
.cand-grid > .cand-tile {
  width: 100%;
  margin: 0 0 14px;
  break-inside: avoid;
}
.cand-grid > .cand-tile:not(.cand-hero):not([hidden]) { display: inline-block; }
/* ---- HERO: party colour wash + portrait ring ---- */
.cand-hero {
  column-span: all;
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 18px;
  align-items: center;
  padding: 20px 60px 20px 20px;
  overflow: hidden;
  isolation: isolate;
  border-color: color-mix(in oklab, var(--cc) 38%, var(--line));
  background:
    radial-gradient(ellipse 70% 140% at 0% 40%, color-mix(in oklab, var(--cc) 42%, transparent), transparent 58%),
    radial-gradient(ellipse 50% 100% at 100% 0%, color-mix(in oklab, var(--cc) 16%, transparent), transparent 50%),
    linear-gradient(155deg,
      color-mix(in oklab, var(--cc) 20%, var(--panel)) 0%,
      var(--panel) 52%,
      color-mix(in oklab, var(--bg-2) 70%, var(--panel)) 100%);
  box-shadow:
    inset 0 1px 0 color-mix(in oklab, var(--cc) 28%, transparent),
    inset 0 -1px 0 color-mix(in oklab, var(--ink) 3%, transparent);
}
.cand-hero::after {
  content: "";
  position: absolute;
  right: -8%;
  top: -40%;
  width: 46%;
  height: 180%;
  background: radial-gradient(circle, color-mix(in oklab, var(--cc) 18%, transparent), transparent 68%);
  pointer-events: none;
  z-index: 0;
}
.cand-hero > * { position: relative; z-index: 1; }
.cand-photo-wrap {
  flex: 0 0 auto;
  width: 112px;
  height: 112px;
  border-radius: 20px;
  padding: 3px;
  background: linear-gradient(145deg,
    color-mix(in oklab, var(--cc) 85%, white),
    color-mix(in oklab, var(--cc) 40%, transparent) 55%,
    color-mix(in oklab, var(--ink) 12%, transparent));
  box-shadow:
    0 14px 36px color-mix(in oklab, var(--cc) 28%, transparent),
    0 0 0 1px color-mix(in oklab, var(--cc) 20%, transparent);
}
.cand-modal-photo {
  width: 100%;
  height: 100%;
  border-radius: 20px;
  object-fit: cover;
  object-position: center 12%;
  border: 0;
  display: grid;
  place-items: center;
  background: color-mix(in oklab, var(--cc) 55%, #1a2030);
}
.cand-modal-photo.pol-monogram {
  font-size: 34px;
  font-weight: 800;
  color: #fff;
  text-shadow: 0 1px 0 rgba(0,0,0,.25);
}
.cand-hero-id { min-width: 0; display: grid; gap: 8px; }
.cand-hero h2 {
  margin: 0;
  font-family: var(--font-display, var(--sans));
  font-size: clamp(26px, 3.6vw, 42px);
  font-weight: 700;
  line-height: 1.02;
  letter-spacing: -0.02em;
  color: var(--ink);
}
.cand-seat { margin: 0; font-size: 13px; line-height: 1.35; }
.cand-meta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 2px;
}
.cand-meta-chip {
  display: inline-flex;
  align-items: center;
  min-height: 26px;
  padding: 0 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-dim);
  background: color-mix(in oklab, var(--ink) 7%, transparent);
  border: 1px solid color-mix(in oklab, var(--ink) 8%, transparent);
}
.cand-pill-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 2px; }
.cand-pill-row .pill {
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .02em;
  padding: 6px 12px;
  border-radius: 999px;
  box-shadow: 0 4px 14px color-mix(in oklab, var(--cc) 30%, transparent);
}
.cand-kicker {
  color: color-mix(in oklab, var(--cc) 55%, var(--ink-faint));
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
}
/* ---- tile variants (not all the same grey slab) ---- */
.cand-role {
  border-color: var(--line);
  background: color-mix(in oklab, var(--bg-2) 88%, var(--panel));
  box-shadow: none;
}
.cand-role .cand-kicker { color: var(--ink-faint); }
.cand-role-text {
  margin: 10px 0 0;
  color: var(--ink);
  font-size: 16px;
  font-weight: 700;
  line-height: 1.35;
  letter-spacing: -0.01em;
}
.cand-summary {
  background: color-mix(in oklab, var(--bg-2) 70%, var(--panel));
}
.cand-summary p, .cand-tile > p {
  margin: 10px 0 0;
  color: var(--ink-dim);
  font-size: 14px;
  line-height: 1.6;
  max-width: 62ch;
}
.cand-facts {
  background: color-mix(in oklab, var(--panel) 40%, var(--bg-2));
}
.cand-facts-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  margin-top: 12px;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid var(--line);
  background: var(--line);
}
.cand-fact {
  display: grid;
  gap: 6px;
  padding: 14px 14px 12px;
  border: 0;
  border-radius: 0;
  background: var(--bg-2);
}
.cand-fact span {
  color: var(--ink-faint);
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.cand-fact b {
  min-width: 0;
  color: var(--ink);
  font-family: var(--font-display, var(--sans));
  font-size: 18px;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.02em;
  overflow-wrap: anywhere;
}
.cand-fact small { color: var(--ink-faint); font-size: 12px; font-weight: 600; }
.cand-list {
  margin: 10px 0 0;
  padding-left: 18px;
  color: var(--ink-dim);
  display: grid;
  gap: 7px;
  font-size: 13px;
  line-height: 1.45;
}
.cand-track .cand-list, .cand-election .cand-list {
  list-style: none;
  padding-left: 0;
  counter-reset: cand-step;
}
.cand-track .cand-list li, .cand-election .cand-list li {
  position: relative;
  padding: 8px 10px 8px 36px;
  border-radius: 12px;
  background: color-mix(in oklab, var(--ink) 4%, transparent);
  border: 1px solid color-mix(in oklab, var(--ink) 5%, transparent);
}
.cand-track .cand-list li::before, .cand-election .cand-list li::before {
  counter-increment: cand-step;
  content: counter(cand-step);
  position: absolute;
  left: 8px;
  top: 50%;
  transform: translateY(-50%);
  width: 20px;
  height: 20px;
  border-radius: 8px;
  display: grid;
  place-items: center;
  font-size: 10px;
  font-weight: 800;
  font-family: var(--mono);
  color: var(--ccfg, #0b0e13);
  background: color-mix(in oklab, var(--cc) 75%, white);
}
.cand-party .cand-list {
  list-style: none;
  padding-left: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.cand-party .cand-list li {
  border: 1px solid color-mix(in oklab, var(--cc) 28%, var(--line));
  background: color-mix(in oklab, var(--cc) 12%, var(--bg-2));
  color: var(--ink);
  border-radius: 999px;
  padding: 7px 12px;
  font-weight: 700;
  font-size: 13px;
  line-height: 1.2;
}
.cand-news {
  border-color: color-mix(in oklab, var(--accent) 22%, var(--line));
}
.cand-source-links, .cand-news-list { display: grid; gap: 8px; margin-top: 10px; }
.cand-news-list a {
  display: grid;
  gap: 4px;
  color: var(--ink);
  text-decoration: none;
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 11px 12px;
  background: color-mix(in oklab, var(--accent) 6%, var(--bg-2));
  transition: border-color .12s, background .12s, transform .04s;
}
.cand-news-list a:hover {
  border-color: color-mix(in oklab, var(--accent) 40%, var(--line));
  background: color-mix(in oklab, var(--accent) 10%, var(--bg-2));
}
.cand-news-list a:active { transform: translateY(1px); }
.cand-source-links a {
  color: var(--ink-dim);
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: 12px;
  padding: 9px 11px;
  background: color-mix(in oklab, var(--ink) 4%, transparent);
  font-size: 13px;
  font-weight: 650;
  transition: color .12s, background .12s, border-color .12s;
}
.cand-source-links a:hover {
  color: var(--ink);
  border-color: var(--line);
  background: color-mix(in oklab, var(--ink) 7%, transparent);
  text-decoration: none;
}
.cand-sources {
  background: transparent;
  border-style: dashed;
  box-shadow: none;
}
.cand-news-list small, .cand-source-note { color: var(--ink-faint); font-size: 12px; line-height: 1.4; }
.cand-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 16px;
}
.cand-seatbtn, .pol-modal-seatbtn.cand-seatbtn {
  flex: 1 1 200px;
  margin-top: 0;
  min-height: 48px;
  padding: 0 18px;
  border: 0;
  border-radius: 12px;
  cursor: pointer;
  font: inherit;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ccfg, #0b0e13);
  background: linear-gradient(180deg,
    color-mix(in oklab, var(--cc) 92%, white),
    color-mix(in oklab, var(--cc) 78%, black));
  box-shadow:
    0 1px 0 color-mix(in oklab, white 22%, transparent) inset,
    0 10px 24px color-mix(in oklab, var(--cc) 32%, transparent);
  transition: filter .12s, transform .04s;
}
.cand-seatbtn:hover { filter: brightness(1.06); }
.cand-seatbtn:active { transform: translateY(1px); filter: brightness(.97); }
.cand-seatbtn:focus-visible { outline: 2px solid var(--focus, var(--accent)); outline-offset: 3px; }
.cand-actions .cand-seatbtn:nth-child(n+2) {
  color: var(--ink);
  background: var(--bg-2);
  border: 1px solid var(--line);
  box-shadow: none;
}
.cand-actions .cand-seatbtn:nth-child(n+2):hover {
  filter: none;
  border-color: var(--line-2);
  background: color-mix(in oklab, var(--bg-2) 85%, var(--ink) 15%);
}
.cand-socials { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }
.cand-socials a {
  display: inline-flex;
  align-items: center;
  min-height: 28px;
  padding: 0 10px;
  border-radius: 8px;
  font-size: 12px;
  font-weight: 650;
  color: var(--ink-dim);
  background: color-mix(in oklab, var(--ink) 7%, transparent);
  border: 1px solid color-mix(in oklab, var(--ink) 8%, transparent);
  text-decoration: none;
}
.cand-socials a:hover { color: var(--ink); border-color: var(--line-2); text-decoration: none; }
@media (max-width: 760px) {
  .candidate-modal {
    width: min(100vw - 20px, 620px);
    max-height: min(90dvh, calc(100dvh - 20px - env(safe-area-inset-top) - env(safe-area-inset-bottom)));
    margin: auto;
    border-radius: 16px;
  }
  .cand-modal-shell { padding: 12px; max-height: inherit; }
  .candidate-modal .cand-modal-close {
    top: 10px;
    right: 10px;
    width: 40px;
    height: 40px;
  }
  .cand-grid { column-count: 1; column-gap: 0; }
  .cand-grid > .cand-tile { margin-bottom: 10px; }
  .cand-hero {
    padding: 16px 48px 16px 14px;
    grid-template-columns: 76px minmax(0, 1fr);
    gap: 12px;
  }
  .cand-photo-wrap { width: 76px; height: 76px; border-radius: 16px; }
  .cand-modal-photo, .cand-modal-photo.pol-monogram { border-radius: 16px; font-size: 24px; }
  .cand-hero h2 { font-size: clamp(22px, 6vw, 28px); }
  .cand-facts-grid { grid-template-columns: 1fr; }
  .cand-fact b { font-size: 16px; }
}
@media (prefers-reduced-motion: reduce) {
  .cand-seatbtn, .cand-news-list a { transition: none; }
}

/* community-sourced (web-searched) socials — visibly distinct from Wikidata-verified */
.pol-socials-note { font-size: 11px; margin: 4px 0 0; }

/* PRN coalition manifesto pledges on the candidate card */
/* mobile seat card: a compact link to the manifesto modal instead of the full pledges */
.prn-pledges-btn {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; min-height: 46px; margin-top: 14px; padding: 12px 16px; cursor: pointer;
  font: inherit; font-size: 14px; font-weight: 600; color: var(--ink);
  background: var(--bg-2); border: 1px solid var(--line); border-radius: var(--radius, 12px);
  transition: border-color .12s ease, background .12s ease;
}
.prn-pledges-btn:hover { border-color: var(--line-2); background: color-mix(in oklab, var(--bg-2) 85%, var(--ink) 15%); }
.prn-pledges-btn:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
/* mobile election panel: the 56-seat live board (reuses the bento table renderer) */
.mobile-live-board { display: grid; gap: 6px; }
/* all-candidates browser: 172 runners grouped by seat inside the candidate dialog */
.prn-all-shell { padding: 18px; }
.prn-all-title { font-family: var(--font-display); font-size: 18px; font-weight: 700; margin: 0 40px 12px 0; }
.prn-all-groups { display: grid; gap: 16px; max-height: min(72vh, 640px); overflow-y: auto; padding-right: 4px; }
.prn-all-seat { display: grid; gap: 8px; }
.prn-all-seathead {
  display: flex; align-items: center; gap: 6px; width: 100%; min-height: 40px;
  font: inherit; font-size: 13px; color: var(--ink); text-align: left; cursor: pointer;
  background: var(--bg-2); border: 1px solid var(--line); border-radius: 12px; padding: 8px 12px;
}
.prn-all-seathead b { font-family: var(--mono); font-size: 12px; color: var(--accent); }
.prn-all-seathead:hover { border-color: var(--line-2); }
.prn-all-seathead:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.prn-all-list { list-style: none; margin: 0; padding: 0 2px; display: grid; gap: 6px; }
.prn-all-cand { display: flex; align-items: center; gap: 10px; font-size: 13px; min-width: 0; }
/* personPhotoHTML puts the class on the img/monogram itself, not a wrapper */
.prn-all-cand .prn-all-photo {
  width: 32px; height: 32px; border-radius: 50%; flex: 0 0 auto;
  object-fit: cover; font-size: 11px;
}
.prn-all-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prn-all-cand .pill { flex: 0 0 auto; }
.prn-pledges { display: grid; gap: 12px; }
.prn-pledge-coal { border: 1px solid var(--line); border-radius: 12px; padding: 11px 13px; background: var(--surface-soft); }
.prn-pledge-h { display: flex; align-items: center; gap: 8px; font-size: 13px; margin-bottom: 8px; }
.prn-pledge-list { margin: 0; padding-left: 18px; display: grid; gap: 4px; }
.prn-pledge-list li { font-size: 13px; line-height: 1.45; color: var(--ink-dim); }
.prn-pledge-src { display: inline-block; margin-top: 8px; }

/* ============================================================================
   PRN "bento" dashboard (Johor election) — additive, landscape tablets & up
   (min-width 1000px catches iPad landscape 1024/1180/1366; phones & portrait
   tablets keep the map+panel flow). Kept in sync with PRN_BENTO_MQ in app.js.
   ============================================================================ */
#state-bento { display: none; }
@media (min-width: 1000px) {
  body.bento-on #stage,
  body.bento-on #panel { display: none; }
  body.bento-on #state-bento {
    display: flex; flex-direction: column; gap: 12px;
    grid-column: 1 / -1; grid-row: 1 / -1;   /* span under the fixed topbar; padding clears it */
    height: 100%; min-height: 0; overflow: auto;   /* min-height:0 so the 1fr map row can shrink to fit */
    /* nav strip bottoms out at ~69px — equal 16px breathing room on all sides */
    padding: 85px 16px 16px;
  }
}
.bento-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.bento-title { display: flex; align-items: center; gap: 10px; font-size: 20px; font-weight: 700; }
.bento-title .live-dot { width: 9px; height: 9px; }
.bento-close { margin: 0; width: auto; }

/* three rows, filling the height: meta strip · map+spotlight · pledges.
   flex:1 + min-height:min-content → the grid fills the viewport when content fits,
   but NEVER shrinks below its rows' minimums (minmax floors + max-content row 1).
   min-height:0 here used to let flex squeeze the grid box below its tracks, so the
   overflowing tiles painted OVER the following siblings (news strip / source line)
   instead of pushing them down. With min-content, short (iPad-landscape) heights
   bottom out at the row minimums and #state-bento scrolls the overflow cleanly
   (SVGs are absolutely positioned, so they can never inflate a track). */
.bento-grid {
  display: grid; gap: 12px; flex: 1; min-height: min-content;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  /* middle row (map + spotlight) gets priority height so the spotlight shows every
     candidate + the incumbent without scrolling; pledges take the natural remainder */
  grid-template-rows: auto minmax(340px, 1fr) auto;
  grid-template-areas:
    "dates dates stand stand"
    "map   map   spot  spot"
    "creg  creg  creg  creg";
}
/* map/spot can shrink inside 1fr rows; stand (donut) must NOT — min-height:0 was
   letting the seats-by-coalition card collapse to the title only, with the chart
   painting outside the white tile. */
.bento-map, .bento-spot { min-height: 0; }
.bento-grid:not(.is-state) .bento-stand { min-height: 0; }
/* short landscape (iPad 768/834 tall): tighten so it fits with minimal scroll */
@media (min-width: 1000px) and (max-height: 840px) {
  .bento-grid { gap: 10px; grid-template-rows: auto minmax(270px, 1fr) auto; }
  .bento-tile { padding: 12px 14px; gap: 7px; }
  .bento-count-big { font-size: clamp(32px, 3.6vw, 48px); }
}
.bento-count { grid-area: count; } .bento-countreg { grid-area: creg; } .bento-map { grid-area: map; } .bento-stand { grid-area: stand; }
.bento-dates { grid-area: dates; } .bento-reg { grid-area: reg; } .bento-spot { grid-area: spot; } .bento-pledge { grid-area: pledge; }
/* "who's leading now" line under the seats-by-coalition donut on election night */
.bento-live-under {
  margin-top: 12px; padding-top: 12px;
  border-top: 1px solid color-mix(in oklab, var(--line) 70%, transparent);
  display: grid; gap: 6px;
}
.bento-live-under .prn-live-tally-h { font-size: 11px; letter-spacing: .04em; text-transform: uppercase; }
.bento-live-under .sharebar { height: 8px; border-radius: 999px; overflow: hidden; display: flex; }
.bento-live-under .sharebar-key { display: flex; flex-wrap: wrap; gap: 4px 12px; font-size: 12px; }
.bento-live-under .state-bloc { display: inline-flex; align-items: center; gap: 5px; }
.bento-live-under .state-bloc .sw { width: 9px; height: 9px; border-radius: 4px; flex: 0 0 auto; }

.bento-tile {
  background: var(--panel); border: 1px solid var(--line); border-radius: 16px;
  padding: 15px 16px; min-width: 0; display: flex; flex-direction: column; gap: 9px;
}
.bento-kicker { font-size: 11px; text-transform: uppercase; letter-spacing: .09em; color: var(--ink-dim); font-weight: 600; }
.bento-foot { margin: 2px 0 0; }

/* countdown hero */
.bento-count { justify-content: center; background: linear-gradient(158deg, #13212c, var(--panel)); }
.bento-count-big { font-family: var(--mono); font-weight: 600; font-size: clamp(38px, 4.4vw, 64px); line-height: .95; color: var(--accent-2); }
.bento-count-big span { font-family: var(--sans); font-size: 16px; color: var(--ink-dim); margin-left: 8px; font-weight: 500; }
.bento-count-sub { font-size: 12px; }
.bento-count.is-live { background: linear-gradient(158deg, #10262a, var(--panel)); }
.bento-count.is-live .bento-count-big { color: var(--accent); }

/* state map tile — fills its grid cell, keeps aspect via preserveAspectRatio.
   The SVG is absolutely positioned so a portrait-shaped state (Selangor, Perak…)
   can never inflate the grid row through intrinsic aspect-ratio sizing. */
.bento-map-wrap { position: relative; flex: 1; min-height: 220px; }
.bento-map-svg { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }
/* stroke-width is in CSS px via non-scaling-stroke — without it, small states
   (Perlis, Penang, FT) zoom in hard via viewBox and inflate map-unit strokes
   into thick white outlines while large states (Sarawak, Johor, Pahang) look thin. */
.bento-seat {
  stroke: var(--stroke);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
  stroke-linejoin: round;
  cursor: pointer;
  transition: filter .15s;
}
.bento-seat:hover { filter: brightness(1.3); }
.bento-seat.sel { stroke: var(--select); stroke-width: 1.8; paint-order: stroke; }

/* standings */
.bento-standings-bar { height: 16px; }
.bento-stand .sharebar-key { margin-top: 8px; }
.bento-maj { margin-top: auto; font-size: 12px; }

/* key dates */
.bento-dates-row { display: flex; flex-direction: column; gap: 8px; }
.bento-date { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; padding: 8px 10px; border-radius: 12px; background: var(--bg-2); }
.bento-date span { font-size: 12px; } .bento-date b { font-family: var(--mono); font-size: 13px; }
.bento-date.is-poll { background: color-mix(in oklab, var(--accent) 16%, var(--bg-2)); border: 1px solid color-mix(in oklab, var(--accent) 35%, transparent); }
.bento-date.is-poll b { color: var(--accent); }

/* register CTA */
.bento-reg { text-decoration: none; color: var(--ink); transition: border-color .15s, transform .15s; }
.bento-reg:hover { border-color: var(--accent); transform: translateY(-1px); }
.bento-reg-b { font-size: 13px; line-height: 1.5; color: var(--ink-dim); margin: 0; flex: 1; }
.bento-reg-cta { font-size: 13px; font-weight: 600; color: var(--accent); }

/* combined countdown + voter-registration tile: two halves in one rounded box
   (placed AFTER .bento-tile so flex-direction:row wins the same-specificity cascade) */
/* one long thin horizontal strip: countdown (left) + voter-check (right), each row-laid.
   flex:0 0 auto + min-height so the auto grid row can't squeeze it to nothing. */
.bento-countreg { flex-direction: row; gap: 0; padding: 0; overflow: hidden; min-height: 64px; flex: 0 0 auto; }
.bento-cr-count {
  flex: 1 1 0; min-width: 0; display: flex; flex-direction: row; align-items: center; gap: 14px;
  padding: 12px 20px; background: linear-gradient(158deg, #13212c, var(--panel));
}
.bento-cr-count .bento-count-big {
  flex: 0 0 auto; display: inline-flex; align-items: baseline; gap: 5px;
  font-family: var(--mono); font-weight: 600; font-size: 28px; line-height: 1; color: var(--accent-2);
}
.bento-cr-count .bento-count-big span { font-family: var(--sans); font-size: 13px; color: var(--ink-dim); font-weight: 500; }
.bento-cr-cap { display: flex; flex-direction: column; line-height: 1.3; min-width: 0; }
.bento-cr-cap b { font-size: 13px; font-weight: 600; }
.bento-cr-cap .muted { font-size: 12px; }
.bento-countreg.is-live .bento-cr-count { background: linear-gradient(158deg, #10262a, var(--panel)); }
.bento-countreg.is-live .bento-count-big { color: var(--accent); }
.bento-cr-reg {
  flex: 1 1 0; min-width: 0; display: flex; flex-direction: row; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 20px; border-left: 1px solid var(--line);
  text-decoration: none; color: var(--ink); transition: background .15s;
}
.bento-cr-q { font-size: 14px; font-weight: 600; min-width: 0; }
.bento-cr-reg .bento-reg-cta { flex: 0 0 auto; font-size: 13px; font-weight: 600; color: var(--accent); white-space: nowrap; }
.bento-cr-reg:hover { background: color-mix(in oklab, var(--accent) 7%, transparent); }

/* seat spotlight */
.bento-spot { overflow: hidden; }
#bento-spot-body { display: flex; flex-direction: column; gap: 8px; min-height: 0; overflow: auto; }
.bento-spot-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; padding: 24px; text-align: center; flex: 1; }
.bento-spot-mark { font-size: 28px; opacity: .6; }
.bento-spot-head h3 { margin: 2px 0 0; font-size: 18px; }
.bento-spot-kicker { font-size: 11px; color: var(--ink-dim); }
.bento-spot-cands { display: flex; flex-direction: column; gap: 6px; }
.bento-spot-inc { font-size: 12px; margin: 4px 0 0; }
.bento-spot-elec { font-size: 12px; }

/* pledges */
.bento-pledge-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px; }
.bento-pledge-col { min-width: 0; }

/* pledge block: per-coalition note + "not released yet" pending state */
.prn-pledge-note { font-size: 12px; line-height: 1.45; margin: 4px 0 7px; color: var(--ink-dim); }
.prn-pledge-pending { font-size: 13px; line-height: 1.45; margin: 7px 0 2px; font-style: italic; }
.prn-pledge-coal.is-pending { opacity: .82; }

/* current-holder block in the seat spotlight (who holds the seat now + their votes) */
.prn-inc { margin: 2px 0 8px; padding: 10px 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.prn-inc-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.prn-inc-kicker { font-size: 11px; text-transform: uppercase; letter-spacing: .08em; color: var(--ink-dim); font-weight: 600; }
.prn-inc-name { font-size: 16px; font-weight: 600; margin-top: 4px; }
.prn-inc-stat { font-size: 12px; margin-top: 1px; }
/* 2022 margin bar — coalition-coloured share of the vote the incumbent won */
.prn-margin-bar { height: 6px; border-radius: 999px; background: rgba(255,255,255,.07); overflow: hidden; margin: 8px 0 6px; }
.prn-margin-bar span { display: block; height: 100%; border-radius: 999px; }
/* competitiveness badge */
.prn-comp { flex: 0 0 auto; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; padding: 3px 8px; border-radius: 999px; border: 1px solid var(--line-2); color: var(--ink-dim); white-space: nowrap; }
.prn-comp-marginal { background: color-mix(in oklab, var(--accent-2) 20%, var(--bg-2)); border-color: color-mix(in oklab, var(--accent-2) 45%, transparent); color: var(--accent-2); }
.prn-comp-leaning { color: var(--ink-dim); }
.prn-comp-safe { color: var(--ink-faint); border-color: var(--line); }
.bento-spot-meta { display: block; font-size: 12px; margin-top: 3px; line-height: 1.4; }

/* candidate cards in the bento spotlight (beside the map) */
.bento-cand-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 8px; align-content: start; }
.bento-cand-grid:has(.prn-cc.has-profile) { grid-template-columns: repeat(auto-fit, minmax(min(100%, 310px), 1fr)); }
.prn-cc {
  width: 100%;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--bg-2);
  color: inherit;
  font: inherit;
  text-align: left;
  appearance: none;
  -webkit-appearance: none;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.prn-cc[role="button"], button.prn-cc { cursor: pointer; transition: border-color .12s ease, background .12s ease, transform .08s ease; }
.prn-cc[role="button"]:hover, button.prn-cc:hover { border-color: var(--line-2); background: color-mix(in oklab, var(--bg-2) 88%, var(--ink) 12%); }
.prn-cc[role="button"]:active, button.prn-cc:active { transform: translateY(1px); }
.prn-cc[role="button"]:focus-visible, button.prn-cc:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }
.prn-cc.is-inc { border-color: var(--line-2); }   /* the INCUMBENT chip carries the emphasis — no accent edging */
.prn-cc-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.prn-cc-id { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.prn-cc-name { font-size: 14px; font-weight: 600; line-height: 1.3; display: inline-flex; align-items: baseline; flex-wrap: wrap; gap: 6px; }
.prn-cc-inc { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; padding: 2px 6px; border-radius: 4px; background: color-mix(in oklab, var(--cc) 30%, transparent); color: var(--ink); }
.prn-cc-alias { font-size: 11px; }
.prn-cc-head .pill { flex: 0 0 auto; align-self: flex-start; }
.prn-cc-extra { display: flex; flex-direction: column; gap: 5px; }
.prn-cc-sym { font-size: 11px; }
.prn-cc-news { display: flex; flex-direction: column; gap: 4px; }
.prn-cc-newslink { display: flex; flex-direction: column; font-size: 11px; line-height: 1.3; gap: 1px; }
.prn-cc-newst { color: var(--ink); }
.prn-cc.has-profile { gap: 10px; }
.prn-cc.has-profile .prn-cc-head { display: grid; grid-template-columns: 44px minmax(0, 1fr) auto; align-items: start; }
.prn-cc.has-profile .prn-cc-id { min-height: 44px; justify-content: center; }
.prn-cc.has-profile .prn-cc-head .pill { max-width: 112px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prn-profile-photo { width: 44px; height: 44px; border-radius: 12px; object-fit: cover; border: 1px solid var(--line); }
.prn-profile { border-top: 1px solid var(--line); padding-top: 9px; display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.prn-profile-meta, .prn-profile-sources { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-faint); }
.prn-profile-quality { letter-spacing: 0; text-transform: none; font-size: 11px; font-weight: 600; color: var(--ink-dim); border: 1px solid var(--line); border-radius: 999px; padding: 2px 7px; }
.prn-profile-role { font-size: 12px; font-weight: 650; line-height: 1.3; color: var(--ink); }
.prn-profile-summary { margin: 0; color: var(--ink-dim); font-size: 12px; line-height: 1.45; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.prn-profile-list, .prn-profile-timeline { display: grid; gap: 4px; font-size: 12px; line-height: 1.35; color: var(--ink-dim); }
.prn-profile-list > span, .prn-profile-timeline > span, .prn-profile-partyhist > span { font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-faint); }
.prn-profile-list ul, .prn-profile-timeline ol { margin: 0; padding-left: 16px; display: grid; gap: 3px; }
.prn-profile-partyhist { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.prn-profile-partyhist b { font-size: 11px; line-height: 1.2; font-weight: 650; color: var(--ink); background: var(--surface-soft-2); border: 1px solid var(--line); border-radius: 999px; padding: 4px 8px; }
.prn-profile-sources a { color: var(--ink-dim); text-transform: none; letter-spacing: 0; font-weight: 650; text-decoration: none; border-bottom: 1px solid var(--line-2); }
.prn-profile-sources a:hover { color: var(--ink); border-bottom-color: var(--ink); }
.prn-cc-open { align-self: flex-start; margin-top: 1px; font-size: 11px; font-weight: 700; color: var(--ink); border: 1px solid var(--line); border-radius: 999px; padding: 4px 8px; background: var(--surface-soft-2); }

/* seat-spotlight candidates as a compact HORIZONTAL row (all fit, no scroll).
   Each card is a vertical mini: photo on top, name, party pill. The whole card
   is clickable (opens the full profile modal) so the text hint is dropped here.
   These win over .has-profile since a compact card can carry both classes. */
/* the row keeps its natural height (flex:0 0 auto) so cards never get squished and
   clip their party pill; when there are more candidates than fit, it scrolls sideways */
.bento-cand-row { display: flex; flex: 0 0 auto; gap: 8px; align-items: stretch; overflow-x: auto; overflow-y: hidden; padding-bottom: 2px; scrollbar-width: thin; }
.bento-cand-row .prn-cc { flex: 1 0 128px; min-width: 128px; }   /* fill when few, scroll sideways when many */
/* desktop seat-spotlight row: compact cards become VERTICAL minis (photo on top) so
   they tile across the fixed-height tile. Scoped to the row — elsewhere a compact card
   keeps its natural horizontal head. */
.bento-cand-row .prn-cc.is-compact { align-items: center; text-align: center; gap: 4px; padding: 7px 8px; }
.bento-cand-row .prn-cc.is-compact .prn-cc-head { display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 6px; width: 100%; }
.bento-cand-row .prn-cc.is-compact .prn-cc-id { min-height: 0; align-items: center; text-align: center; gap: 4px; }
.bento-cand-row .prn-cc.is-compact .prn-cc-name { justify-content: center; font-size: 12px; line-height: 1.2;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.bento-cand-row .prn-cc.is-compact .prn-cc-head .pill { align-self: center; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 10px; padding: 3px 8px; }
.bento-cand-row .prn-cc.is-compact .pol-photo.prn-profile-photo { width: 32px; height: 32px; }
.bento-cand-row .prn-cc.is-compact .prn-cc-inc { font-size: 10px; padding: 1px 4px; }
/* shared: a compact card is just photo + name + party — drop the profile-only bits */
.prn-cc.is-compact .prn-cc-open, .prn-cc.is-compact .prn-cc-alias { display: none; }
.prn-cc.is-compact { min-height: 0; }
/* mobile seat-card compare list: keep cards short, but show a real tap affordance */
.prn-cands-compare .prn-cc.is-compact { min-height: 76px; gap: 6px; }
.prn-cands-compare .prn-cc.is-compact .prn-cc-open {
  display: inline-flex;
  align-self: flex-start;
  margin-top: 1px;
}
/* tighten the head + "currently held by" block so the whole spotlight fits without
   the body scrolling (Danial: the card must not scroll) */
#bento-spot .bento-spot-head h3 { font-size: 16px; margin: 1px 0 0; }
#bento-spot .bento-spot-meta { margin-top: 2px; }
#bento-spot .prn-inc { padding: 6px 0; margin: 1px 0 3px; }
#bento-spot .prn-inc-name { font-size: 14px; margin-top: 2px; }
#bento-spot .prn-inc .prn-margin-bar { height: 5px; margin: 4px 0 3px; }
#bento-spot .prn-inc-stat { font-size: 12px; }
#bento-spot .bento-cand-label { margin: 0 0 5px; }

/* PRN spotlight: 2026 runners + Rick-fed tonight count */
.prn-spot-runners { margin: 4px 0 2px; min-width: 0; }
.prn-tonight {
  margin: 6px 0 4px;
  padding: 8px 0 6px;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  min-width: 0;
}
.prn-tonight-h {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 6px;
}
.prn-tonight-st {
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--line);
  color: var(--ink-dim);
  background: var(--surface-soft-2);
  flex: 0 0 auto;
}
.prn-tonight-st-leading {
  color: #f0c674;
  border-color: color-mix(in oklab, #f0c674 45%, var(--line));
  background: color-mix(in oklab, #f0c674 16%, transparent);
}
.prn-tonight-st-called,
.prn-tonight-st-official {
  color: #7dcea0;
  border-color: color-mix(in oklab, #7dcea0 45%, var(--line));
  background: color-mix(in oklab, #7dcea0 16%, transparent);
}
.prn-tonight-st-awaiting {
  color: var(--ink-faint);
}
.prn-tonight-empty {
  margin: 0;
  font-size: 12px;
  line-height: 1.4;
}
.prn-tonight-field { display: grid; gap: 5px; }
.prn-tonight-row {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(48px, 1fr) auto;
  gap: 6px 8px;
  align-items: center;
  font-size: 12px;
}
.prn-tonight-row.is-lead .prn-last-name { color: var(--ink); font-weight: 650; }
.prn-tonight-lead {
  display: inline-block;
  margin-left: 4px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: #f0c674;
  vertical-align: middle;
}
.prn-tonight-sum {
  margin-top: 6px;
  font-size: 12px;
  line-height: 1.35;
}
#bento-spot .prn-tonight { margin-top: 4px; }
#bento-spot .prn-tonight-row .prn-last-bar { height: 5px; }

/* tabbed manifestos in the bento pledges tile (one coalition at a time) */
.prn-pl-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.prn-pl-tab { font: inherit; font-size: 12px; font-weight: 600; line-height: 1; padding: 8px 13px; border-radius: 999px; border: 1px solid var(--line); background: var(--bg-2); color: var(--ink-dim); cursor: pointer; display: inline-flex; align-items: center; gap: 7px; transition: color .12s, border-color .12s, background .12s; }
.prn-pl-tab::before { content: ""; width: 8px; height: 8px; border-radius: 999px; background: var(--cc, var(--line-2)); flex: 0 0 auto; }
.prn-pl-tab:hover { color: var(--ink); border-color: var(--line-2); }
.prn-pl-tab.on { color: var(--ink); border-color: var(--cc); background: color-mix(in oklab, var(--cc) 22%, var(--bg-2)); }
.prn-pl-panel { min-height: 150px; }   /* PH's 8 pledges vs PN's pending note — no row jump on tab switch */
.prn-pl-panel .prn-pledge-coal { border: 0; padding: 0; background: none; }
.prn-pl-panel .prn-pledge-h { font-size: 13px; margin-bottom: 6px; }
.prn-pl-panel .prn-pledge-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 4px 28px; }

/* seat search in the bento map tile */
.bento-map-controls {
  display: flex; align-items: center; gap: 10px;
  flex: 0 0 auto; min-width: 0;
  position: relative;
  z-index: 6; /* above the map SVG so the open results list isn't covered */
}
.bento-search { position: relative; flex: 1 1 auto; min-width: 0; z-index: 1; }
.bento-q { width: 100%; min-height: 44px; font: inherit; font-size: 13px; padding: 0 14px; border-radius: 999px; border: 1px solid var(--line); background: var(--bg-2); color: var(--ink); }
.bento-q:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-color: var(--focus); }
.bento-q::placeholder { color: var(--ink-faint); }
.bento-q.is-hover-preview::placeholder { color: var(--ink); opacity: 1; }
/* Open UP over the map (search sits at the bottom of the explore card). Opening
   downward was clipped/blocked by the stats tile below (later in DOM paint order). */
.bento-results {
  position: absolute;
  bottom: calc(100% + 6px);
  top: auto;
  left: 0;
  right: 0;
  z-index: 40;
  background: var(--panel);
  border: 1px solid var(--line-2);
  border-radius: 12px;
  box-shadow: 0 14px 34px rgba(0,0,0,.55);
  max-height: min(280px, 42vh);
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  pointer-events: auto;
}
.bento-result { display: block; width: 100%; text-align: left; font: inherit; font-size: 13px; padding: 9px 13px; background: none; border: 0; color: var(--ink); cursor: pointer; }
.bento-result b { color: var(--accent); font-weight: 600; margin-right: 7px; }
.bento-result:hover { background: var(--bg-2); }

/* spotlight: "Standing in 2026" section label + the last-result bar chart */
.bento-cand-label { font-size: 10px; text-transform: uppercase; letter-spacing: .08em; font-weight: 600; margin: 2px 0 7px; }
.prn-last { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); }
.prn-last-h { font-size: 10px; text-transform: uppercase; letter-spacing: .08em; font-weight: 600; margin-bottom: 9px; }
.prn-last-row { display: grid; grid-template-columns: minmax(110px, 1.1fr) 2fr auto; align-items: center; gap: 12px; margin-bottom: 8px; }
.prn-last-lbl { min-width: 0; display: flex; flex-direction: column; line-height: 1.25; }
.prn-last-name { font-size: 12px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.prn-last-party { font-size: 11px; }
.prn-last-bar { height: 8px; border-radius: 999px; background: rgba(255,255,255,.06); overflow: hidden; }
.prn-last-bar span { display: block; height: 100%; border-radius: 999px; }
.prn-last-pct { font-size: 12px; color: var(--ink-dim); min-width: 36px; text-align: right; }

/* ============================================================================
   Generic state-dashboard tiles (bento mode = state) + header chips
   ============================================================================ */
.bento-head-actions { display: flex; align-items: center; gap: 10px; }
.bento-prn-toggle {
  display: inline-flex; align-items: center; gap: 7px;
  font: inherit; font-size: 13px; font-weight: 600; line-height: 1;
  min-height: 44px; padding: 9px 14px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--line-2); background: var(--bg-2); color: var(--ink-dim);
  transition: color .12s, border-color .12s, background .12s;
}
.bento-prn-toggle .live-dot { width: 7px; height: 7px; }
.bento-prn-toggle:hover { color: var(--ink); border-color: var(--accent); }
.bento-prn-toggle.on { color: var(--ink); border-color: var(--accent); background: color-mix(in oklab, var(--accent) 16%, var(--bg-2)); }

/* state-mode grid, FOUR cards: gov · makeup on top; one explore card (map +
   spotlight together — one section); one stats card (key numbers + economy) */
.bento-grid.is-state {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-template-areas:
    "gov     stand"
    "explore explore"
    "stats   stats";
  /* row 1 is max-content, NOT auto: on short viewports an auto row gets compressed
     below its content (gov card clipped to one line, donut card overflowing under the
     explore card). max-content can't be squeezed — the grid overflows #state-bento,
     which scrolls (by design, see .bento-grid comment above). */
  grid-template-rows: max-content minmax(380px, 1fr) auto;
}
/* election-night: insert full-width live seat table between map and runners */
.bento-grid.is-state.is-prn-live {
  grid-template-areas:
    "gov     stand"
    "explore explore"
    "live    live"
    "stats   stats";
  grid-template-rows: max-content minmax(300px, 1fr) auto auto;
}
.bento-gov { grid-area: gov; } .bento-stand { grid-area: stand; } .bento-explore { grid-area: explore; } .bento-statsrow { grid-area: stats; }
.bento-livetable { grid-area: live; min-height: 0; }

/* ---- election-night live strip (above the bento grid) ---- */
.bento-live-strip {
  width: 100%; max-width: 1000px; margin: 0 auto 12px;
  display: grid; gap: 12px;
  padding: 14px 16px;
  border-radius: 16px;
  border: 1px solid var(--line);
  background: linear-gradient(135deg, color-mix(in oklab, var(--accent) 10%, var(--panel)), var(--panel));
  box-shadow: inset 0 1px 0 color-mix(in oklab, var(--accent) 12%, transparent);
}
.bento-live-strip.is-hot {
  border-color: color-mix(in oklab, var(--accent) 40%, var(--line));
  background: linear-gradient(135deg, color-mix(in oklab, #e11 12%, var(--panel)), color-mix(in oklab, var(--accent) 8%, var(--panel)));
}
.bento-live-strip-h { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.bento-live-strip-title { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.bento-live-strip-title b { font-size: 14px; letter-spacing: .02em; }
.bento-live-strip-title .muted { font-size: 12px; }
.bento-live-strip .live-chip {
  display: inline-flex; align-items: center; min-height: 28px; padding: 0 10px;
  border-radius: 999px; font-size: 11px; font-weight: 800; letter-spacing: .06em;
  color: #fff; background: #c81e1e;
  box-shadow: 0 0 0 0 rgba(200, 30, 30, .45); animation: live-pulse 1.6s ease infinite;
}
@keyframes live-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(200, 30, 30, .4); }
  50% { box-shadow: 0 0 0 6px rgba(200, 30, 30, 0); }
}
.bento-live-metrics {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px;
}
.bento-live-metric {
  display: flex; flex-direction: column; gap: 4px;
  padding: 10px 12px; border-radius: 12px;
  background: color-mix(in oklab, var(--ink) 4%, transparent);
  border: 1px solid color-mix(in oklab, var(--ink) 6%, transparent);
}
.bento-live-metric .muted { font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; }
.bento-live-metric b { font-family: var(--font-display, var(--sans)); font-size: clamp(22px, 3vw, 32px); line-height: 1; letter-spacing: -.02em; }
.bento-live-metric b small { font-size: .55em; color: var(--ink-dim); font-weight: 600; }
/* per-coalition "who's ahead" bar in the election-night strip, under the metrics */
.bento-live-ahead { display: grid; gap: 7px; margin-top: 4px; }
.bento-live-ahead .sharebar { height: 9px; border-radius: 999px; overflow: hidden; display: flex; }
.bento-live-ahead .sharebar > span { display: block; height: 100%; }
.bento-live-ahead .sharebar-key { display: flex; flex-wrap: wrap; gap: 5px 14px; font-size: 13px; }
.bento-live-ahead .state-bloc { display: inline-flex; align-items: center; gap: 6px; }
.bento-live-ahead .state-bloc .sw { width: 10px; height: 10px; border-radius: 4px; flex: 0 0 auto; }
.bento-live-meta { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; }
.bento-live-legend { display: flex; flex-wrap: wrap; gap: 10px; }
.bento-live-leg { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--ink-dim); }
.bento-live-leg i { width: 9px; height: 9px; border-radius: 4px; display: block; background: var(--line-2); }
.bento-live-leg.st-awaiting i { background: #5a6574; }
.bento-live-leg.st-leading i { background: #d97706; }
.bento-live-leg.st-called i { background: #16a34a; }
.bento-live-leg.st-official i { background: #2563eb; }
.bento-live-updated { font-size: 12px; }

/* ---- 56-seat live table ---- */
.bento-livetable { padding: 12px 14px 10px; gap: 8px; }
.bento-livetable-head {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px;
}
.bento-live-filters { display: flex; flex-wrap: wrap; gap: 6px; }
.bento-live-chip {
  min-height: 32px; padding: 0 11px; border-radius: 999px; cursor: pointer;
  font: inherit; font-size: 12px; font-weight: 700;
  border: 1px solid var(--line); background: var(--bg-2); color: var(--ink-dim);
  pointer-events: auto;
  touch-action: manipulation;
  -webkit-user-select: none;
  user-select: none;
}
.bento-live-chip:hover { border-color: var(--line-2); color: var(--ink); }
.bento-live-chip.on { background: color-mix(in oklab, var(--accent) 18%, var(--bg-2)); border-color: color-mix(in oklab, var(--accent) 40%, var(--line)); color: var(--ink); }
.bento-live-chip:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.bento-livetable-scroll {
  max-height: min(340px, 42vh); overflow: auto; border-radius: 12px;
  border: 1px solid var(--line); background: color-mix(in oklab, var(--bg-2) 70%, var(--panel));
}
.bento-live-table {
  width: 100%;
  table-layout: fixed;          /* lock columns so every row lines up */
  border-collapse: collapse;
  font-size: 13px;
}
.bento-live-table col.col-code { width: 3.4rem; }
.bento-live-table col.col-seat { width: 16%; }
.bento-live-table col.col-status { width: 5.4rem; }
.bento-live-table col.col-leader { width: auto; }
.bento-live-table col.col-party { width: 4.8rem; }
.bento-live-table col.col-bloc { width: 4rem; }
.bento-live-table col.col-maj { width: 3.4rem; }
/* Desktop keeps full columns; party column always shows leader's party */
.bento-live-table .col-party {
  white-space: nowrap;
  font-weight: 700;
}
.bento-live-table th {
  position: sticky; top: 0; z-index: 1;
  text-align: left; padding: 9px 8px;
  font-size: 10px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  color: var(--ink-faint); background: var(--panel); border-bottom: 1px solid var(--line);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bento-live-table td {
  padding: 8px 8px;
  border-bottom: 1px solid color-mix(in oklab, var(--line) 70%, transparent);
  vertical-align: middle;
  overflow: hidden;
}
.bento-live-cell {
  display: block;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.bento-live-table .col-code {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--ink-dim);
}
.bento-live-table .col-status {
  text-align: left;
}
.bento-live-table .col-maj {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  font-feature-settings: "tnum" 1;
}
.bento-live-table th.col-maj { text-align: right; }
.bento-live-table .col-bloc {
  white-space: nowrap;
}
.bento-live-row { cursor: pointer; transition: background .1s; }
.bento-live-row:hover { background: color-mix(in oklab, var(--ink) 5%, transparent); }
.bento-live-row.is-sel { background: color-mix(in oklab, var(--accent) 12%, transparent); }
.bento-live-row:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.bento-live-st {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 4.6rem; min-height: 22px; padding: 0 8px;
  border-radius: 999px; font-size: 11px; font-weight: 700; letter-spacing: .03em;
  background: color-mix(in oklab, var(--ink) 6%, transparent); color: var(--ink-dim);
  white-space: nowrap;
  box-sizing: border-box;
}
.bento-live-st.st-leading { background: color-mix(in oklab, #d97706 22%, transparent); color: #fbbf24; }
.bento-live-st.st-called { background: color-mix(in oklab, #16a34a 22%, transparent); color: #4ade80; }
.bento-live-st.st-official { background: color-mix(in oklab, #2563eb 22%, transparent); color: #93c5fd; }
.bento-live-coal {
  display: inline-flex; align-items: center; gap: 6px;
  min-width: 0; max-width: 100%; white-space: nowrap;
}
.bento-live-coal .sw { width: 9px; height: 9px; border-radius: 4px; flex: 0 0 auto; }
.bento-live-empty { text-align: center; padding: 18px 10px !important; }
.bento-live-row.just-called, .bento-seat.just-called {
  animation: seat-flash 1.1s ease;
}
@keyframes seat-flash {
  0% { filter: brightness(1.8) saturate(1.3); }
  40% { filter: brightness(1.35) saturate(1.15); }
  100% { filter: none; }
}
.bento-seat.st-leading { stroke: #fbbf24; stroke-width: 1.2; }
.bento-seat.st-called, .bento-seat.st-official { stroke: rgba(255,255,255,.55); stroke-width: 1; }
@media (max-width: 760px) {
  .bento-live-metrics { grid-template-columns: 1fr 1fr 1fr; gap: 6px; }
  .bento-live-metric b { font-size: 20px; }
  .bento-livetable-scroll { max-height: 280px; }
  .bento-live-table { font-size: 12px; }
  .bento-live-table th, .bento-live-table td { padding: 7px 8px; }
}
@media (prefers-reduced-motion: reduce) {
  .bento-live-strip .live-chip, .bento-live-row.just-called, .bento-seat.just-called { animation: none; }
}
.bento-explore { min-height: 0; position: relative; z-index: 3; overflow: visible; }
.bento-explore-inner { flex: 1; min-height: 0; display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: 20px; overflow: visible; }
.bento-explore-map { min-width: 0; min-height: 0; display: flex; flex-direction: column; gap: 9px; overflow: visible; position: relative; }
.bento-explore-map .bento-map-wrap { min-height: 240px; z-index: 0; }
.bento-explore-spot { min-width: 0; min-height: 0; display: flex; flex-direction: column; gap: 9px; border-left: 1px solid var(--line); padding-left: 20px; }
.bento-explore-spot #bento-spot-body { min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 10px; }
/* stats card: key numbers + economy side by side */
.bento-stats-inner { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); gap: 22px; }
.bento-stats-inner .bento-econ { border-left: 1px solid var(--line); padding-left: 22px; }
.bento-stats-inner .bento-kicker { margin-bottom: 8px; }

/* dl rows inside tiles: reuse the panel's .state-ctx typography, tile-tightened */
.bento-ctx { margin: 0; }
.bento-ctx dt, .bento-ctx dd { padding: 8px 2px; font-size: 13px; }
.bento-stats { margin-top: 8px; }
.bento-records-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 10px; margin-top: 2px; }
.bento-spot-runner { font-size: 12px; margin-top: 4px; }
.bento-spot-result { margin-top: 10px; }

/* the politicians directory overlay covers the dashboard; it returns on close */
@media (min-width: 1000px) {
  body.politicians-open #state-bento { display: none; }
}

/* leadership tile: large state identity · current MB/KM/Premier */
.bento-gov { padding: 18px 20px; }
.bento-gov-split {
  flex: 1;
  min-height: min-content;
  display: grid;
  grid-template-columns: minmax(150px, .9fr) minmax(0, 1.35fr);
  gap: 24px;
  align-items: stretch;
  width: 100%;
}
.bento-gov-split.solo { grid-template-columns: minmax(0, 1fr); }
.bento-gov-emblem-pane {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-start;
  gap: 14px;
  min-width: 0;
  min-height: min-content;
  padding: 2px 20px 2px 0;
  border-right: 1px solid var(--line, rgba(255,255,255,.08));
  box-sizing: border-box;
}
.bento-gov-state-name {
  align-self: flex-start;
  flex: 0 0 auto;
  font-family: var(--font-display);
  font-size: clamp(26px, 2.3vw, 34px);
  font-weight: 700;
  line-height: 1.05;
  color: var(--ink);
  letter-spacing: 0;
}
/* silver shimmer sweeping through the state-title letters, left → right:
   the text becomes a silver gradient fill (background-clip:text) whose bright
   band travels across on a loop with a rest between passes. text-fill-color
   beats the color rules, and the whole thing is @supports-gated so an old
   engine keeps plain var(--ink) letters instead of transparent ones. */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .bento-gov-state-name {
    background-image: linear-gradient(105deg,
      #b9c0ca 0%, #b9c0ca 40%, #ffffff 50%, #b9c0ca 60%, #b9c0ca 100%);
    background-size: 300% 100%;
    background-position: 100% 0;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: state-name-shimmer 4.5s ease-in-out infinite;
  }
  /* light theme: dark letters, a silver glint passes through */
  html[data-theme="light"] .bento-gov-state-name {
    background-image: linear-gradient(105deg,
      var(--ink) 0%, var(--ink) 40%, #aab5c2 50%, var(--ink) 60%, var(--ink) 100%);
  }
  @media (prefers-reduced-motion: reduce) {
    .bento-gov-state-name { animation: none; background-position: 50% 0; }
  }
}
@keyframes state-name-shimmer {
  0%   { background-position: 100% 0; }   /* band waits off the LEFT edge */
  55%  { background-position: 0% 0; }     /* sweeps through to exit RIGHT */
  100% { background-position: 0% 0; }     /* rest until the next pass */
}
/* the isolated-state map heading floats over the fluid backdrop, which is dark in
   BOTH themes — theme ink goes near-black in light mode and vanishes against it.
   So the heading is always light: silver shimmer (same treatment as the bento
   state title) where background-clip:text is supported, plain light ink where not. */
#state-label { color: #e7edf4; }
#state-label .label-sub { color: #cfd6df; }
#state-label .label-tier { color: #b9c0ca; border-color: rgba(231, 237, 244, .35); }
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  #state-label .label-main {
    background-image: linear-gradient(105deg,
      #b9c0ca 0%, #b9c0ca 40%, #ffffff 50%, #b9c0ca 60%, #b9c0ca 100%);
    background-size: 300% 100%;
    background-position: 100% 0;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: state-name-shimmer 4.5s ease-in-out infinite;
    text-shadow: none;
  }
  /* the tier chip inside the heading keeps a solid fill — it's a badge, not glint */
  #state-label .label-tier { -webkit-text-fill-color: #b9c0ca; }
  #state-label .label-tier:hover:not(:disabled) { -webkit-text-fill-color: #e7edf4; }
  @media (prefers-reduced-motion: reduce) {
    #state-label .label-main { animation: none; background-position: 50% 0; }
  }
}
/* seat-card district name — bigger, with the same shimmer as the state titles.
   The card is a solid panel (white in light mode), so unlike the map heading this
   needs BOTH theme variants: silver on dark, ink with a silver glint on light. */
#panel .seat-head h2,
#panel.seat-detail #state-info .seat-head h2,
.seat-head h2 {
  font-size: clamp(26px, 2.4vw, 34px);
  line-height: 1.05;
}
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .seat-head h2 {
    background-image: linear-gradient(105deg,
      #b9c0ca 0%, #b9c0ca 40%, #ffffff 50%, #b9c0ca 60%, #b9c0ca 100%);
    background-size: 300% 100%;
    background-position: 100% 0;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: state-name-shimmer 4.5s ease-in-out infinite;
  }
  html[data-theme="light"] .seat-head h2 {
    background-image: linear-gradient(105deg,
      var(--ink) 0%, var(--ink) 40%, #aab5c2 50%, var(--ink) 60%, var(--ink) 100%);
  }
  @media (prefers-reduced-motion: reduce) {
    .seat-head h2 { animation: none; background-position: 50% 0; }
  }
}
/* the same silver glint sweeps through every search-bar placeholder (home card,
   bento seat search, politician directory, map-inspect district filter). The base
   stays ink-faint so it still reads as a placeholder; only the passing band lights
   up. Same @supports gate: without background-clip:text the plain ::placeholder
   color rules above keep working and nothing turns transparent. */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .search input::placeholder,
  .bento-q::placeholder,
  .pol-dir-search::placeholder,
  .map-inspect-search::placeholder {
    background-image: linear-gradient(105deg,
      var(--ink-faint) 0%, var(--ink-faint) 40%, #dbe3ec 50%, var(--ink-faint) 60%, var(--ink-faint) 100%);
    background-size: 300% 100%;
    background-position: 100% 0;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: state-name-shimmer 4.5s ease-in-out infinite;
  }
  /* light theme: faint letters, a darker-silver glint passes through */
  html[data-theme="light"] .search input::placeholder,
  html[data-theme="light"] .bento-q::placeholder,
  html[data-theme="light"] .pol-dir-search::placeholder,
  html[data-theme="light"] .map-inspect-search::placeholder {
    background-image: linear-gradient(105deg,
      var(--ink-faint) 0%, var(--ink-faint) 40%, #aab5c2 50%, var(--ink-faint) 60%, var(--ink-faint) 100%);
  }
  /* hover-preview keeps its brighter text: same shimmer, ink base instead of faint */
  .bento-q.is-hover-preview::placeholder {
    background-image: linear-gradient(105deg,
      var(--ink) 0%, var(--ink) 40%, #ffffff 50%, var(--ink) 60%, var(--ink) 100%);
  }
  html[data-theme="light"] .bento-q.is-hover-preview::placeholder {
    background-image: linear-gradient(105deg,
      var(--ink) 0%, var(--ink) 40%, #aab5c2 50%, var(--ink) 60%, var(--ink) 100%);
  }
  @media (prefers-reduced-motion: reduce) {
    .search input::placeholder,
    .bento-q::placeholder,
    .pol-dir-search::placeholder,
    .map-inspect-search::placeholder { animation: none; background-position: 50% 0; }
  }
}
/* Stable generous frame; object-fit:contain keeps portrait and landscape crests whole. */
.bento-gov-emblem-pane .state-emblem,
.bento-gov-emblem-pane .bento-gov-emblem {
  width: min(140px, 100%);
  height: 132px;
  max-width: 100%;
  max-height: 132px;
  display: grid;
  place-items: center;
  position: relative;
  flex: 0 0 auto;
  min-width: 0;
  min-height: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  overflow: hidden;
  box-sizing: border-box;
}
/* absolutely positioned: 100% resolves against the box itself, not the auto grid
   row — an intrinsically square crest in the non-square (140x132) box otherwise
   computes to 140x140 and gets sliced by the box's overflow:hidden */
.bento-gov-emblem-pane .state-emblem img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center;
  display: block;
}
.bento-gov-emblem-pane .state-emblem-fallback {
  width: 100%;
  height: 100%;
  min-height: 0;
  border-radius: 16px;
  font-size: 28px;
  font-weight: 700;
}
.bento-gov-yb-pane {
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 14px;
  padding-left: 2px;
}
.bento-gov-head { display: flex; align-items: center; gap: 16px; }
/* faces sit near the top of full-body Commons shots — bias the square crop up */
.pol-photo.bento-gov-photo { width: 84px; height: 84px; border-radius: 16px; flex: 0 0 auto; object-fit: cover; object-position: center 12%; font-size: 22px; }
.bento-gov-id { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.bento-gov-title { font-size: 12px; }
.bento-gov-id strong { font-size: 18px; line-height: 1.2; }
.bento-gov-id p { margin: 4px 0 0; font-size: 13px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.bento-gov .yb-credit { margin: 4px 0 0; font-size: 10px; }
html[data-theme="light"] .bento-gov-emblem-pane {
  border-right-color: rgba(15, 23, 42, 0.08);
}
@media (max-width: 1100px) {
  .bento-gov-split { grid-template-columns: minmax(125px, .85fr) minmax(0, 1.25fr); gap: 16px; }
  .bento-donut { gap: 12px; }
  .bento-gov-emblem-pane .state-emblem,
  .bento-gov-emblem-pane .bento-gov-emblem {
    width: min(118px, 100%);
    height: 118px;
    max-height: 118px;
  }
  .pol-photo.bento-gov-photo { width: 76px; height: 76px; }
}

/* incumbent portrait inside the "currently held by" block */
.prn-inc-row { display: flex; align-items: flex-start; gap: 12px; }
.prn-inc-main { flex: 1; min-width: 0; }
.pol-photo.prn-inc-photo { width: 52px; height: 52px; border-radius: 12px; flex: 0 0 auto; object-fit: cover; object-position: center 12%; font-size: 16px; }
.prn-inc .yb-credit { margin: 5px 0 0; font-size: 10px; }

/* politicians directory: roster tabs */
.pol-dir-tabs-wrap {
  max-width: 1100px;
  margin: 0 auto 18px;
  overflow-x: auto;
  scrollbar-width: none;
}
.pol-dir-tabs-wrap::-webkit-scrollbar { display: none; }
.pol-dir-tabs {
  display: inline-flex;
  max-width: 100%;
  vertical-align: top;
}
/* manifesto pledges pane (Politicians → Manifesto tab) */
.pol-pledges-pane {
  max-width: 1100px;
  margin: 0 auto;
  min-height: 200px;
}
.pol-pledges-body {
  padding: 4px 0 12px;
}
.pol-pledges-body .prn-pl-panel {
  min-height: 180px;
  margin-top: 4px;
}
.pol-pledges-body .prn-pledge-coal {
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 14px 16px;
  background: var(--surface-soft);
}
.pol-pledges-body .prn-pledge-list {
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}

/* explore-card layer chips: both tiers visible, tap to flip the choropleth */
/* the layer switch is a segmented pill, same look as the main Parliament/DUN toggle
   (.seg.chip), sized to sit on the same line as search */
.bento-map-seg { flex: 0 0 auto; }
.seg.chip.bento-map-seg button { min-height: 44px; padding: 0 13px; font-size: 11px; letter-spacing: .02em; white-space: nowrap; }
.bento-map-count {
  flex: 0 0 auto; display: inline-flex; align-items: center; min-height: 44px;
  padding: 0 14px; border-radius: 999px; background: var(--bg-2); color: var(--ink);
  font-size: 11px; font-weight: 700; letter-spacing: .02em; white-space: nowrap;
}

/* ---- dashboard chrome in the nav bar (wide screens, bento open) ----
   State identity lives in the leadership card; PRN toggle + close join the icon cluster.
   The centre pills keep centring via auto margins while the bar fills out. */
.topbar-actions[hidden] { display: none; }
/* bento actions (PRN toggle + close) sit in the right cluster, left of the theme button */
.topbar-actions {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
  min-width: 0;
}
/* permanent centre title — always "MyPolitik", same pill slot state titles used */
.topbar-context {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  z-index: 1;
  pointer-events: auto;
}
.topbar-title {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 18px;
  margin: 0;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--glass);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 700;
  letter-spacing: 0;
  line-height: 1;
  color: var(--ink);
  white-space: nowrap;
  cursor: pointer;
}
.topbar-title:hover { border-color: var(--line-2); }
.topbar-title:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.topbar-title .brand-word b { color: var(--accent); font-weight: 800; }
.topbar-context .bento-title {
  display: inline-flex; align-items: center; gap: 9px;
  min-height: 44px; padding: 0 16px;
  font-family: var(--font-display); font-size: 20px; font-weight: 700; letter-spacing: 0; white-space: nowrap;
  background: var(--glass); border: 1px solid var(--line); border-radius: 999px;
  backdrop-filter: blur(8px);
}
.topbar-context .bento-title .live-dot { width: 8px; height: 8px; }
/* official state / federal territory emblem badges */
.state-emblem {
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 auto; overflow: hidden;
  background: var(--state-emblem-bg);
  border: 1px solid var(--line);
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.16);
}
.state-emblem img { display: block; width: 100%; height: 100%; object-fit: contain; }
.state-emblem-fallback {
  color: #fff; font-weight: 800; letter-spacing: .02em; line-height: 1;
}
.bento-crest {
  width: 30px; height: 30px; margin-left: 0; padding: 0; border-radius: 0;
  background: transparent; border: 0; box-shadow: none; overflow: visible;
}
.bento-crest.state-emblem-fallback { padding: 0; font-size: 11px; }
.topbar-actions .prn-close-btn {
  margin: 0; width: auto; border-radius: 999px; padding: 0 16px; min-height: 44px;
  background: var(--glass); backdrop-filter: blur(8px); border-color: var(--line);
}
body.bento-on #topbar { justify-content: flex-start; }
body.bento-on #topbar .top-controls { margin-inline: auto; }
/* Align the right cluster (close / PRN toggle + theme) with the bento's 1000px rail.
   Theme stays the rightmost control; actions sit just left of it on the same baseline. */
@media (min-width: 1000px) {
  body.bento-on #topbar {
    /* content area is full viewport (no sidebar at this breakpoint) */
    padding-inline: max(14px, calc((100vw - 1000px) / 2));
  }
}
@media (min-width: 640px) {
  /* topbar is offset by the sidebar (232px / 60px collapsed) — match that in the rail math */
  body.bento-on #topbar {
    padding-inline: max(14px, calc((100vw - 232px - 1000px) / 2));
  }
  body.sb-collapsed.bento-on #topbar {
    padding-inline: max(14px, calc((100vw - 60px - 1000px) / 2));
  }
}

/* wide screens: the nav is a solid black strip (pills sit ON it), content passes under */
@media (min-width: 1000px) {
  #topbar {
    background: var(--topbar-strip);
    backdrop-filter: blur(10px);
    border-bottom: 1px solid var(--line);
  }
}

/* dashboard/directory open: the centre tier/mode pills are redundant. The bento has
   its own layer chips, and the politicians directory has its own roster tabs. */
body.bento-on #top-controls,
body.politicians-open #top-controls { display: none; }

/* Top cards contribute their full intrinsic height; the max-content row sizes to the
   taller leadership/coalition card so neither the crest nor donut can be clipped. */
.bento-grid.is-state .bento-stand,
.bento-grid.is-state .bento-gov {
  align-self: stretch;
  min-height: min-content;
  height: auto;
  justify-content: flex-start;
  gap: 14px;
}
.bento-donut {
  flex: 0 0 auto !important; /* never flex-shrink the chart out of the card */
  min-height: 140px;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 20px;
  width: 100%;
  box-sizing: border-box;
}
.bento-donut-svg {
  width: 120px;
  height: 120px;
  flex: 0 0 120px;
  display: block;
  overflow: visible;
}
.bento-donut-total { font-family: var(--mono); font-size: 24px; font-weight: 600; fill: var(--ink); }
.bento-donut-sub { font-size: 10px; letter-spacing: .08em; text-transform: uppercase; fill: var(--ink-dim); }
.bento-donut-legend {
  min-width: 0;
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
  justify-content: center;
}
.bento-donut-row { display: flex; align-items: baseline; gap: 8px; font-size: 13px; color: var(--ink-dim); flex-wrap: wrap; }
.bento-donut-row .sw { width: 10px; height: 10px; border-radius: 4px; flex: 0 0 auto; align-self: center; }
.bento-donut-row .bento-donut-name { color: var(--ink); font-weight: 600; }
.bento-donut-row b { font-size: 14px; color: var(--ink); }
.bento-donut-row.is-lead .bento-donut-name { font-weight: 700; }

/* very large screens: cap the dashboard's width and centre it — cards shouldn't
   stretch across an ultrawide */
.bento-grid, .bento-foot, .bento-news, .bento-live-strip { width: 100%; max-width: 1000px; margin-inline: auto; }

/* ---- news strip on the election dashboard (reviewer ask). Headline + source + link
   only; graceful — renders only when there's matched coverage ---- */
.bento-news {
  margin-top: 14px; padding: 14px 16px;
  background: var(--bg-1, rgba(20, 22, 26, .55)); border: 1px solid var(--line); border-radius: 16px;
}
/* Light mode: translucent dark strip was unreadable on the grid — solid soft-red card */
html[data-theme="light"] .bento-news {
  background: #fde8e6;
  border: 1px solid #f0b4ae;
  color: #1a1c20;
  box-shadow: none;
}
html[data-theme="light"] .bento-news-title {
  color: #b42318;
}
html[data-theme="light"] .bento-news-all {
  color: #b42318;
}
html[data-theme="light"] .bento-news .news-t {
  color: #14161a;
  font-weight: 600;
}
html[data-theme="light"] .bento-news .news-meta {
  color: #6b4a47;
}
html[data-theme="light"] .bento-news-note {
  color: #7a5c58;
}
html[data-theme="light"] .bento-news .news-link:hover {
  background: color-mix(in oklab, #f8877f 22%, #fff);
}
html[data-theme="light"] .bento-news .muted {
  color: #7a5c58;
}
.bento-news-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.bento-news-title { margin: 0; font-size: 13px; font-weight: 700; letter-spacing: .01em; }
/* full campaign-news list (no separate News nav page) */
.bento-news-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 2px;
  max-height: min(480px, 52vh);
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
}
.news-link {
  display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
  padding: 7px 8px; margin: 0 -8px; border-radius: 12px; text-decoration: none; color: inherit;
}
.news-link:hover { background: color-mix(in oklab, var(--accent) 8%, transparent); }
.news-t { font-size: 14px; font-weight: 600; line-height: 1.35; min-width: 0; }
.news-meta { font-size: 11px; white-space: nowrap; flex: 0 0 auto; max-width: 42%; overflow: hidden; text-overflow: ellipsis; }
.bento-news-note { margin: 8px 0 0; font-size: 11px; }
.bento-news-note + .bento-news-note { margin-top: 4px; }
/* news modal list (see-all) */
.news-modal-list { list-style: none; margin: 6px 0 0; padding: 0; display: grid; gap: 2px; }
.news-modal-list .news-t { font-size: 14px; }
.news-empty { padding: 20px 4px; font-size: 14px; }
@media (max-width: 560px) {
  .news-link { flex-direction: column; gap: 2px; }
  .news-meta { white-space: normal; }
}

/* ============================================================================
   Navigation sidebar — present from 640px up so the layout stays consistent
   across window sizes (it boots collapsed to the 60px icon strip; expanding is
   temporary). Only true phone widths (<640px) fall back to the hamburger menu.
   ============================================================================ */
#sidebar { display: none; }
@media (min-width: 640px) {
  #sidebar {
    position: fixed; inset: 0 auto 0 0; width: 232px; z-index: 60;
    display: flex; flex-direction: column; gap: 2px;
    padding: 14px 12px 12px;
    background: var(--topbar-strip); backdrop-filter: blur(10px);
    border-right: 1px solid var(--line);
  }
  #app { margin-left: 232px; }
  #topbar { left: 232px; }
  /* the sidebar owns brand / nav / language — topbar keeps theme + bento actions */
  #topbar .brand-home, #topbar #top-map, #topbar #top-politicians,
  #topbar #top-info, #topbar #top-share,
  #topbar .topicons { display: none; }
  body.politicians-open #politicians-view { left: 232px; }
  body.politicians-open .pol-dir { left: 232px; }
  body.dewan-open .pol-dir { left: 232px; }
}
.sb-brand {
  display: flex; align-items: center; gap: 6px;
  font-family: var(--font-display); font-size: 20px; font-weight: 700; color: var(--ink);
  min-height: 44px; background: none; border: 0; cursor: pointer; padding: 6px 10px 14px; text-align: left;
}
.sb-brand .brand-word b { font-weight: 800; }
.sb-brand .brand-symbol { font-size: 24px; line-height: 1; }
.sb-nav { display: flex; flex-direction: column; gap: 2px; }
.sb-item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  min-height: 44px; padding: 9px 10px; border-radius: 8px; border: 0; background: none;
  font: inherit; font-size: 14px; color: var(--ink-dim); text-align: left; cursor: pointer;
  transition: background .12s, color .12s;
}
.sb-item:hover { background: var(--surface-hover-2); color: var(--ink); }
.sb-item.on { background: var(--surface-hover); color: var(--ink); font-weight: 600; }
.sb-brand:focus-visible, .sb-item:focus-visible, .sb-collapse:focus-visible, .sb-lang button:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}
.sb-ic { width: 22px; height: 22px; display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; }
.sb-ic .nav-icon { width: 22px; height: 22px; }
.sb-live .live-dot { width: 8px; height: 8px; margin-right: 2px; }
.sb-section {
  font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .09em;
  color: var(--ink-faint); margin: 16px 10px 6px;
}
.sb-states { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 1px; }
.sb-state { font-size: 13px; min-height: 44px; padding: 7px 10px; gap: 8px; }
.sb-state-emblem {
  width: 30px; height: 30px; padding: 2px; border-radius: 8px;
  background: var(--state-emblem-bg);
  position: relative;   /* anchors the map-hover glint sweep */
  transition: transform .18s ease, box-shadow .18s ease;
}
.sb-state-emblem.state-emblem-fallback { padding: 0; font-size: 10px; }
/* hovering a state on the map (or its sidebar row) glints its sidebar emblem:
   the tile pops up slightly and a diagonal glare band sweeps across it on the
   shared shimmer keyframes — the emblem's overflow:hidden clips the band to
   the rounded tile. */
.sb-state.is-map-hover .sb-state-emblem {
  transform: translateY(-2px) scale(1.14);
  /* keep the base inset edge, add lift shadow */
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.16), 0 4px 10px rgba(0,0,0,.4);
}
.sb-state.is-map-hover .sb-state-emblem::after {
  content: "";
  position: absolute; inset: 0;
  background-image: linear-gradient(105deg,
    transparent 0%, transparent 40%, rgba(255,255,255,.7) 50%, transparent 60%, transparent 100%);
  background-size: 300% 100%;
  background-position: 100% 0;
  animation: state-name-shimmer 2.4s ease-in-out infinite;
  pointer-events: none;
}
/* light theme: a white glare vanishes on the pale tile — sweep silver instead */
html[data-theme="light"] .sb-state.is-map-hover .sb-state-emblem::after {
  background-image: linear-gradient(105deg,
    transparent 0%, transparent 40%, rgba(170,181,194,.6) 50%, transparent 60%, transparent 100%);
}
@media (prefers-reduced-motion: reduce) {
  .sb-state.is-map-hover .sb-state-emblem::after { animation: none; background-position: 50% 0; }
}
.sb-state-name {
  min-width: 0;
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sb-state-hover-label {
  position: fixed;
  left: 68px;
  top: 0;
  z-index: 80;
  transform: translateY(-50%);
  max-width: min(220px, calc(100vw - 84px));
  padding: 7px 10px;
  border: 1px solid var(--line-2);
  border-radius: 8px;
  background: var(--tooltip-bg, rgba(8,11,16,.94));
  color: var(--ink);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
  pointer-events: none;
}
.sb-state-hover-label[hidden] { display: none; }
/* live-election state row (Johor): translucent red + left→right pulse — replaces
   the separate sidebar PRN button */
.sb-state-dot {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  margin-right: 2px;
  background: #fff;
}
.sb-state-badge {
  flex: 0 0 auto;
  min-height: 20px;
  display: inline-flex;
  align-items: center;
  padding: 3px 6px;
  border-radius: 8px;
  background: color-mix(in oklab, var(--danger) 18%, transparent);
  color: var(--danger);
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
}
.sb-state.is-election {
  position: relative;
  z-index: 0;
  overflow: hidden;
  isolation: isolate;
  color: #fff;
  border: 1px solid color-mix(in oklab, var(--danger) 55%, transparent);
  background: color-mix(in oklab, var(--danger) 24%, transparent);
  text-shadow: 0 1px 2px rgba(0, 0, 0, .35);
}
.sb-state.is-election::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 55%;
  z-index: 0;
  background: linear-gradient(
    90deg,
    transparent 0%,
    color-mix(in oklab, var(--danger) 42%, transparent) 45%,
    color-mix(in oklab, var(--danger) 14%, transparent) 70%,
    transparent 100%
  );
  transform: translateX(-120%);
  animation: live-badge-sweep 2.4s ease-in-out infinite;
  pointer-events: none;
  will-change: transform;
}
.sb-state.is-election > * { position: relative; z-index: 1; }
.sb-state.is-election .sb-state-name { color: #fff; }
.sb-state.is-election:hover {
  background: color-mix(in oklab, var(--danger) 36%, transparent);
  border-color: color-mix(in oklab, var(--danger) 75%, transparent);
  color: #fff;
}
.sb-state.is-election.on,
.sb-state.is-election.is-prn-on {
  background: color-mix(in oklab, var(--danger) 42%, transparent);
  border-color: color-mix(in oklab, var(--danger) 80%, transparent);
  font-weight: 650;
}
@media (prefers-reduced-motion: reduce) {
  .sb-state.is-election::before { display: none; animation: none; }
}
.sb-foot { margin-top: auto; padding-top: 10px; border-top: 1px solid var(--line); display: flex; align-items: center; gap: 2px; }
.sb-small { width: auto; font-size: 13px; padding: 7px 9px; }
.sb-lang { margin-left: auto; }
.sb-lang button {
  font: inherit; font-size: 11px; font-weight: 600; padding: 6px 9px; min-width: 44px; min-height: 44px;
  border: 0; background: none; color: var(--ink-faint); border-radius: 8px; cursor: pointer;
}
.sb-lang button.on { background: var(--surface-hover); color: var(--ink); }

/* ---- collapsible rail: 232px ⇄ 60px icon strip; content reflows beside it ---- */
@media (min-width: 640px) {
  #sidebar { transition: width .12s ease, padding .12s ease; }
  #app { transition: margin-left .12s ease; }
  #topbar { transition: left .12s ease; }
  /* the map stage and the bottom panel are FIXED full-bleed layers — offset them
     beside the rail too, so the sidebar never covers the map */
  #stage { left: 232px; transition: left .12s ease; }
  #panel { left: 232px; transition: left .12s ease; }
  body.sb-collapsed #stage, body.sb-collapsed #panel { left: 60px; }
  /* the open rail carries the brand and the language switch, so the top bar
     drops its copies; the collapsed rail hides its own and the top bar's return */
  body:not(.sb-collapsed) .topbar-title,
  body:not(.sb-collapsed) .topbar-lang { display: none; }
  body.sb-collapsed #sidebar { width: 60px; padding: 14px 8px 12px; }
  body.sb-collapsed #app { margin-left: 60px; }
  body.sb-collapsed #topbar { left: 60px; }
  body.sb-collapsed.politicians-open #politicians-view { left: 60px; }
  body.sb-collapsed.politicians-open .pol-dir { left: 60px; }
  body.sb-collapsed.dewan-open .pol-dir { left: 60px; }
  body.sb-collapsed .sb-brand,
  body.sb-collapsed .sb-label,
  body.sb-collapsed .sb-section,
  body.sb-collapsed .sb-foot { display: none; }
  body.sb-collapsed .sb-top { justify-content: center; padding-bottom: 10px; }
  body.sb-collapsed .sb-item { justify-content: center; padding: 10px 0; }
  body.sb-collapsed .sb-states {
    display: flex;
    flex: 1 1 auto;
    min-height: 0;
    gap: 2px;
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid var(--line);
    overflow-y: auto;
    scrollbar-width: none;
  }
  body.sb-collapsed .sb-states::-webkit-scrollbar { display: none; }
  body.sb-collapsed .sb-state {
    position: relative;
    width: 44px;
    min-height: 44px;
    padding: 0;
    border-radius: 12px;
  }
  body.sb-collapsed .sb-state-name { display: none; }
  body.sb-collapsed .sb-state-emblem {
    width: 34px;
    height: 34px;
    padding: 2px;
    border-radius: 8px;
  }
  body.sb-collapsed .sb-state-emblem.state-emblem-fallback { font-size: 10px; }
  body.sb-collapsed .sb-state-dot {
    position: absolute;
    top: 7px;
    right: 6px;
    width: 7px;
    height: 7px;
    margin: 0;
  }
}
.sb-top { display: flex; align-items: center; justify-content: space-between; gap: 6px; padding-bottom: 8px; }
.sb-collapse {
  flex: 0 0 auto; width: 44px; height: 44px; display: grid; place-items: center;
  border: 0; border-radius: 8px; background: none; color: var(--ink-faint); cursor: pointer;
}
.sb-collapse svg { width: 22px; height: 22px; }
.sb-collapse:hover { background: var(--surface-hover-2); color: var(--ink); }

/* manifesto pledges dialog (opened from the sidebar) */
.pledges-modal { width: min(720px, calc(100vw - 40px)); }
.pledges-modal-h { margin: 0 0 12px; font-size: 18px; }
.pledges-modal .prn-pl-panel { min-height: 180px; }

/* ============================================================================
   SNOW SKIN — SnowUI-inspired look for the wide-screen chrome (sidebar, header,
   dashboard). Borderless surfaces separated by contrast, 16-20px radii, soft
   pills, colored card titles, accent KPI cards. Party colours stay untouched
   (they're data); mobile keeps the classic look (everything here is scoped to
   the sidebar/topbar/bento which only exist on wide screens).
   ============================================================================ */
:root {
  --snow-page: #16181c;
  --snow-card: #212429;
  --snow-inner: #2a2d33;
  --snow-inner-hi: #33373e;
  --snow-blue: #8AB4F8;
  --snow-peri: #C6C7F8;
  --snow-green: #A1E3CB;
  --snow-red: #F8877F;
  --snow-blue-fg: var(--snow-blue);
  --snow-peri-fg: var(--snow-peri);
  --snow-green-fg: var(--snow-green);
  --snow-red-fg: var(--snow-red);
  --snow-blue-fill: var(--snow-blue);
  --snow-peri-fill: var(--snow-peri);
  --snow-green-fill: var(--snow-green);
  --snow-red-fill: var(--snow-red);
  --snow-dark-ink: #14161A;
  --snow-card-glass: color-mix(in oklab, var(--snow-card) 95%, transparent);
  --snow-inner-glass: color-mix(in oklab, var(--snow-inner) 84%, transparent);
}

html[data-theme="light"] {
  --snow-page: #f3f5f8;
  --snow-card: #ffffff;
  --snow-inner: #edf1f5;
  --snow-inner-hi: #e2e7ee;
  --snow-blue-fg: #2f64a3;
  --snow-peri-fg: #5d5aa8;
  --snow-green-fg: #247a61;
  --snow-red-fg: #b5473f;
  --snow-blue-fill: #dbeaff;
  --snow-peri-fill: #e6e3ff;
  --snow-green-fill: #d8f2e7;
  --snow-red-fill: #ffe0dd;
  --snow-dark-ink: #161a22;
  --snow-card-glass: color-mix(in oklab, var(--snow-card) 96%, transparent);
  --snow-inner-glass: color-mix(in oklab, var(--snow-inner) 88%, transparent);
}
/* tiles: near-solid glass, slightly 3D — a lit top edge (inset highlight) +
   tight contact shadow + soft ambient lift, and a whisper of top-light gradient
   on the surface. Dark mode leans on the highlight (shadows read poorly on
   near-black); light mode leans on real drop shadows. */
.bento-tile {
  background: var(--snow-card-glass); border: 1px solid rgba(255,255,255,.035);
  border-radius: 20px; padding: 18px 20px; backdrop-filter: blur(6px);
  background-image: linear-gradient(180deg, rgba(255,255,255,.028), transparent 30%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.055),
    0 1px 2px rgba(0,0,0,.35),
    0 14px 34px -14px rgba(0,0,0,.55);
}
html[data-theme="light"] .bento-tile {
  border-color: rgba(15,23,42,.08);
  background-image: none;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.9),
    0 1px 2px rgba(15,23,42,.06),
    0 12px 28px -12px rgba(15,23,42,.16);
}
.bento-grid { gap: 16px; }
/* card titles: sentence case in the display face to echo the state title, all one
   neutral colour — on this site colour means party data, so titles stay out of it */
.bento-kicker {
  text-transform: none; letter-spacing: 0; color: var(--ink);
  font-family: var(--font-display); font-size: 18px; font-weight: 700; line-height: 1.15;
}
.bento-gov-state-name { color: var(--ink); }
html[data-theme="light"] .bento-gov-emblem-pane {
  border-right-color: rgba(15, 23, 42, 0.08);
}
/* inner boxes: soft surfaces, no borders — .prn-cc/.prn-inc are shared with the
   mobile panel, so those pieces are scoped to wide screens only */
.bento-date, .bento-records-grid .state-stat, .bento-ctx dt { border: 0; }
.bento-date { background: var(--snow-inner-glass); border-radius: 12px; }
.bento-records-grid .state-stat { background: var(--snow-inner-glass); border-radius: 12px; padding: 12px 14px; }
@media (min-width: 1000px) {
  #state-bento .prn-cc, #pledges-modal .prn-cc { border: 0; background: var(--snow-inner-glass); border-radius: 12px; }
  #state-bento .prn-inc, #state-bento .bento-spot-result { border-color: var(--snow-inner-hi); }
}
/* election KPI cards: two accents like SnowUI's stat row */
.bento-count { background: var(--snow-blue-fill); }
.bento-count .bento-kicker, .bento-count .bento-count-sub { color: var(--snow-dark-ink); }
.bento-count .bento-count-big { color: var(--snow-dark-ink); }
.bento-count .bento-count-big span { color: rgba(20,22,26,.65); }
.bento-count.is-live { background: var(--snow-green-fill); }
.bento-count.is-live .bento-count-big { color: var(--snow-dark-ink); }
.bento-reg { background: var(--snow-peri-fill); border: 0; }
.bento-reg .bento-kicker, .bento-reg .bento-reg-b { color: var(--snow-dark-ink); }
.bento-reg .bento-reg-b { color: rgba(20,22,26,.75); }
.bento-reg .bento-reg-cta { color: var(--snow-dark-ink); font-weight: 700; }
.bento-reg:hover { border: 0; filter: brightness(1.04); transform: translateY(-1px); }
/* countdown+register strip: two SnowUI accent halves in one rounded bar */
.bento-countreg { background: transparent; padding: 0; overflow: hidden; }
.bento-cr-count { background: var(--snow-blue-fill); }
.bento-cr-count .bento-count-big, .bento-cr-cap b { color: var(--snow-dark-ink); }
.bento-cr-count .bento-count-big span, .bento-cr-cap .muted { color: rgba(20,22,26,.7); }
.bento-countreg.is-live .bento-cr-count { background: var(--snow-green-fill); }
.bento-cr-reg { background: var(--snow-peri-fill); border-left: 0; }
.bento-cr-reg .bento-cr-q, .bento-cr-reg .bento-reg-cta { color: var(--snow-dark-ink); }
.bento-cr-reg .bento-reg-cta { font-weight: 700; }
.bento-cr-reg:hover { background: var(--snow-peri-fill); filter: brightness(1.03); }
/* controls: soft gray pills, no borders (.prn-close-btn/.prn-pl-tab shared with the
   mobile panel — scope to the wide chrome + the pledges dialog) */
.bento-tier-chip, .bento-map-count, .bento-q, .bento-prn-toggle, .sb-collapse,
#state-bento .prn-pl-tab, #pledges-modal .prn-pl-tab,
.topbar-actions .prn-close-btn {
  border: 0; background: var(--snow-inner); color: var(--ink-dim);
}
.bento-tier-chip.on { background: var(--snow-inner-hi); color: var(--ink); }
.bento-prn-toggle.on { background: color-mix(in oklab, var(--snow-blue-fill) 52%, var(--snow-inner)); color: var(--ink); }
.bento-q:focus { outline: 2px solid var(--focus); border: 0; }
.bento-results { border: 0; background: var(--snow-inner); }
.bento-result:hover { background: var(--snow-inner-hi); }
/* topbar: no solid strip — it's empty on the overview and the map should reach the top;
   the bento title/close carry their own styling, and the dashboard bg sits under it */
@media (min-width: 1000px) {
  #topbar { background: transparent; border-bottom: 0; backdrop-filter: none; }
  .topbar-context .bento-title {
    background: none; border: 0; padding: 0 4px;
    font-family: var(--font-display); font-size: 20px; font-weight: 700; letter-spacing: 0;
    backdrop-filter: none;
  }
  .topbar-actions .prn-close-btn { background: var(--snow-inner); border: 0; backdrop-filter: none; }
  body.bento-on #state-bento {
    background:
      linear-gradient(to right,  var(--grid-line) 1px, transparent 1px) 0 0 / var(--grid-size) var(--grid-size),
      linear-gradient(to bottom, var(--grid-line) 1px, transparent 1px) 0 0 / var(--grid-size) var(--grid-size),
      radial-gradient(120% 90% at 50% 0%, var(--bento-page-top) 0%, var(--snow-page) 72%);
  }
}
/* sidebar: flat, borderless, pill active */
@media (min-width: 640px) {
  #sidebar { background: var(--snow-page); border-right: 0; }
  #topbar { left: 232px; }
  .sb-item { border-radius: 12px; }
  .sb-item:hover { background: var(--snow-inner); }
  .sb-item.on { background: var(--snow-inner-hi); }
  .sb-foot { border-top: 1px solid var(--snow-inner); }
  .sb-lang button.on { background: var(--snow-inner-hi); }
}
/* explore card internals */
.bento-explore-spot { border-left-color: var(--snow-inner-hi); }
.bento-stats-inner .bento-econ { border-left-color: var(--snow-inner-hi); }
.bento-ctx dt, .bento-ctx dd { border-bottom-color: var(--snow-inner); }
.theme-toggle { position: relative; }
.theme-toggle .theme-sun,
.theme-toggle .theme-moon { grid-area: 1 / 1; transition: opacity .12s ease, transform .12s ease; }
html[data-theme="dark"] .theme-toggle .theme-sun,
html[data-theme="light"] .theme-toggle .theme-moon { opacity: 1; transform: scale(1); }
html[data-theme="dark"] .theme-toggle .theme-moon,
html[data-theme="light"] .theme-toggle .theme-sun { opacity: 0; transform: scale(.82); pointer-events: none; }

/* ===== politician bento: vacancy chips (directory card + profile hero) ===== */
.cand-vacant-chip {
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  padding: 2px 6px; border-radius: 4px;
  border: 1px solid rgba(210, 162, 76, .55); color: #d2a24c; background: rgba(210, 162, 76, .12);
}
.pol-card-vacant {
  display: inline-block; margin-left: 6px; padding: 1px 5px; border-radius: 4px;
  border: 1px solid rgba(210, 162, 76, .55); color: #d2a24c; background: rgba(210, 162, 76, .1);
  font-family: var(--mono); font-size: 10px; font-weight: 700;
  letter-spacing: .05em; text-transform: uppercase; vertical-align: 2px;
}
html[data-theme="light"] .cand-vacant-chip,
html[data-theme="light"] .pol-card-vacant {
  color: #8a6116; border-color: rgba(138, 97, 22, .5); background: rgba(210, 162, 76, .16);
}

/* Flat card policy: no decorative accent rail on an individual row or card. */
.cand-news-list a {
  border-left-width: 1px;
  border-left-color: var(--line);
}
.results button.active { box-shadow: none; }

/* White mode is deliberately flat: suppress elevation from legacy and future components. */
html[data-theme="light"],
html[data-theme="light"] *,
html[data-theme="light"] *::before,
html[data-theme="light"] *::after {
  box-shadow: none !important;
  text-shadow: none !important;
}
/* Map edition: existing floating controls and state dashboard, refined for PRN Melaka. */
:root{--map-ui-surface:#181c24;--map-ui-border:#384352;--map-ui-muted:#b1bdcb;--map-ui-focus:#66e0cf}
#state-label .label-sub{display:none!important}
#state-label .label-main{display:inline-flex;align-items:center;gap:12px;flex-wrap:wrap;justify-content:center;line-height:1.3}
#state-label .label-tier{min-height:36px;display:inline-flex;align-items:center;justify-content:center;padding:6px 12px;vertical-align:middle}
.search input::placeholder,.bento-q::placeholder,.map-inspect-search::placeholder{background:none!important;-webkit-text-fill-color:var(--map-ui-muted)!important;color:var(--map-ui-muted)!important;animation:none!important;opacity:1}
.election-launch{width:100%;display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:52px;margin:0 0 10px;padding:10px 14px;border:1px solid #537b78;border-radius:12px;background:#192f31;color:#e7f9f5;text-align:left;font:inherit;cursor:pointer}
.election-launch:hover{background:#254244;border-color:var(--map-ui-focus)}
.election-launch-title{display:flex;align-items:center;gap:8px;font-size:13px;font-weight:700;white-space:nowrap}
.election-launch-dot{width:7px;height:7px;border-radius:50%;background:var(--map-ui-focus)}
.election-launch-meta{font-size:11px;line-height:1.5;color:#c5e6df}
button:focus-visible,a:focus-visible,input:focus-visible,[role=button]:focus-visible{outline:2px solid var(--map-ui-focus);outline-offset:3px}
.bento-seat:focus-visible{stroke:#fff;stroke-width:1.5;outline:none}
.bento-tile,.prn-cc{border-color:var(--map-ui-border)}
.bento-spot .muted,.prn-cc .muted,.bento-dates .muted,.bento-countreg .muted{color:var(--map-ui-muted)}
.bento-q,.map-inspect-search,.search input{font-size:16px!important}
.prn-cc{min-height:100px}.prn-cc-name{overflow-wrap:anywhere}
.candidate-modal .cand-sources a{min-height:44px;display:inline-flex;align-items:center}
.candidate-modal .cand-summary p,.candidate-modal .cand-pledge-status p{font-size:14px;line-height:1.6}
@media(min-width:1000px){.bento-grid.is-prn{align-items:stretch}.bento-spot{min-height:320px}#bento-spot-body{max-height:none}.bento-search input{min-height:44px}.bento-close,.bento-prn-toggle{min-height:44px}.bento-map-controls{gap:12px}.bento-cand-grid{gap:10px}}
@media(max-width:860px){
 #panel-empty .election-launch{display:flex;flex-direction:column;align-items:flex-start;gap:3px;min-height:62px;padding:10px 14px}
 #panel-empty{padding-bottom:max(12px,env(safe-area-inset-bottom))}
 .search input{min-height:48px}.loc-fab,.loc-btn,.iconbtn,.card-back,.share-icon,.cand-modal-close{min-width:44px;min-height:44px}
 #state-label{max-width:calc(100vw - 32px);width:max-content}
 #state-label .label-main{font-size:clamp(23px,6vw,32px);gap:10px}
 #state-label .label-tier{font-size:10px;min-height:36px}
 body.map-inspect.prn-mode #panel-state #map-inspect-tray{max-height:48dvh;overflow:auto;overscroll-behavior:contain;padding-bottom:max(12px,env(safe-area-inset-bottom))}
 .prn-mobile-title{font-size:16px!important;line-height:1.4}.prn-mobile-meta,.prn-mobile-hint{font-size:12px!important;color:var(--map-ui-muted)}
 .prn-mobile-summary .sharebar-key{display:none}.prn-mobile-summary .sharebar{height:5px}
 /* Count night: the party key IS the result — keep it on phones (hidden only for the campaign field bar). */
 .prn-mobile-summary.is-live:not(.is-compact) .sharebar-key{display:flex;margin-top:6px;font-size:12px}.prn-mobile-summary .prn-mobile-board-h{display:none}
 .prn-mobile-summary .prn-mobile-cands{margin-top:10px;min-height:44px}
 .prn-mobile-summary{padding-bottom:8px}.map-inspect-row{margin-top:8px}
 .map-inspect-select-button,.map-inspect-option,.map-inspect-more{min-height:48px}
 .map-inspect-select-list{max-height:36dvh;overflow:auto;background:var(--map-ui-surface);border-color:var(--map-ui-border)}
 .map-inspect-search{min-height:48px}.map-inspect-option{font-size:14px}
 .candidate-modal{width:calc(100vw - 20px);max-width:560px;max-height:calc(100dvh - 24px - env(safe-area-inset-top) - env(safe-area-inset-bottom))}
 .candidate-modal .cand-modal-shell{overflow:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}
 .candidate-modal .cand-hero h2{font-family:var(--sans);font-size:clamp(20px,5.7vw,27px);line-height:1.25;overflow-wrap:anywhere}
 .candidate-modal .cand-photo-wrap{width:56px;height:56px}.candidate-modal .cand-hero{grid-template-columns:56px minmax(0,1fr);padding-right:38px}
 .prn-all-shell{padding:16px}.prn-all-title{font-size:22px}.prn-all-seathead{min-height:44px}.prn-all-cand{min-height:52px}
 .seat-detail-main{overscroll-behavior:contain}.prn-cands-compare{gap:10px}
 .topbar-lang button,.sb-lang button{min-width:44px;min-height:44px}
}
@media(prefers-reduced-motion:reduce){*,*::before,*::after{scroll-behavior:auto!important}}

/* Stable text paint: avoid shimmer clipping across the flag, title and nested chip. */
#state-label .label-main{background:none!important;-webkit-text-fill-color:#e7edf4!important;animation:none!important;font-family:var(--sans);font-weight:650;overflow:visible}
#state-label .label-flag{position:static;display:block;margin:0;transform:none}
.election-facts{display:flex;flex-direction:column;gap:12px}.election-facts h2{font:650 24px/1.2 var(--sans);margin:0}.election-facts p{font-size:13px;margin:0}.election-fact-chips{display:flex;flex-wrap:wrap;gap:8px}.election-fact-chips span{border:1px solid var(--map-ui-border);border-radius:8px;padding:6px 9px;font-size:12px}.election-facts a{min-height:44px;display:inline-flex;align-items:center;color:var(--map-ui-focus)}.election-facts .prn-pledges-btn{margin-top:0}
.map-return-btn{display:none}
@media(max-width:860px){
 .map-return-btn{display:flex;align-items:center;min-height:44px;margin:8px 0 16px;border:1px solid var(--map-ui-border);border-radius:8px;background:var(--map-ui-surface);color:var(--ink);padding:8px 12px;font:inherit;font-size:13px}
 .map-inspect-row{display:flex;gap:8px;width:100%;min-width:0}.map-inspect-select{flex:1;min-width:0;width:auto}.map-inspect-select-button{width:100%;min-width:0}.map-inspect-select-button>span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.map-inspect-more{flex:0 0 auto;min-width:56px;padding:8px}.map-inspect-locate{flex-shrink:0}
 .map-inspect-tray.has-selection .prn-mobile-cands,.map-inspect-tray.has-selection .prn-mobile-chips,.map-inspect-tray.has-selection .prn-mobile-hint,.map-inspect-tray.has-selection .prn-mobile-summary .sharebar{display:none}
 .map-inspect-tray.has-selection .prn-mobile-summary{padding-bottom:0}.map-inspect-tray.has-selection .prn-mobile-summary .prn-mobile-meta{margin-bottom:0}
 .election-seat-preview strong{font-size:18px}.election-seat-preview{min-height:80px}
}

.candidate-modal .cand-kicker{color:var(--map-ui-muted)!important}.candidate-modal p{color:#c3ced9}.all-candidate-filter{display:flex;flex-direction:column;gap:8px;margin:16px 0 10px;font-size:13px;color:var(--map-ui-muted)}.all-candidate-filter input{width:100%;min-height:48px;border:1px solid var(--map-ui-border);border-radius:8px;background:var(--map-ui-surface);color:var(--ink);font:16px var(--sans);padding:10px 12px}.prn-all-cand{padding:0!important}.prn-all-candidate-btn{display:flex;align-items:center;gap:10px;min-height:64px;width:100%;padding:10px;border:0;background:transparent;color:var(--ink);font:inherit;text-align:left;cursor:pointer}.prn-all-candidate-btn:hover{background:var(--snow-inner-hi)}.prn-all-candidate-btn .prn-all-name{flex:1;min-width:0;overflow-wrap:anywhere}.prn-all-candidate-btn .pill{flex-shrink:0}

/* Explicit hidden rules beat the directory's authored flex/grid display rules. */
.prn-all-seat[hidden],.prn-all-cand[hidden]{display:none!important}
.prn-all-candidate-btn .prn-all-name{white-space:normal!important;overflow:visible!important;text-overflow:clip!important;font-size:13px;line-height:1.45}
.election-seat-preview{display:flex!important;flex-direction:column!important;align-items:flex-start!important;gap:6px!important;text-align:left}
.election-seat-preview>span,.election-seat-preview>strong,.election-seat-preview>p{display:block;max-width:100%;margin:0;line-height:1.4}
.election-history-details{margin:18px 0;border-top:1px solid var(--map-ui-border)}.election-history-details summary{min-height:48px;padding:14px 0;cursor:pointer;font-size:13px;color:var(--map-ui-muted)}

.election-launch[hidden]{display:none!important}
@media(min-width:1000px){.bento-explore-spot .bento-cand-grid{display:grid!important;grid-template-columns:repeat(2,minmax(0,1fr))!important;overflow:visible!important;gap:10px}.bento-explore-spot .prn-cc{width:auto!important;min-width:0!important;max-width:none!important;height:auto!important;min-height:110px}.bento-explore-spot .prn-cc-name,.bento-explore-spot .prn-cc-name>span{white-space:normal!important;overflow:visible!important;text-overflow:clip!important;-webkit-line-clamp:unset!important;line-height:1.4}.prn-mode .bento-seat.st-awaiting{fill:#556578!important;stroke:#aab8c6;stroke-width:.4}.prn-mode .bento-seat.sel{stroke:#ffd166;stroke-width:1.4}}

/* Mobile election journey: map → every candidate, with a searchable seat list. */
.mobile-election-switch{display:none}
.mobile-election-find h2{font:650 18px/1.35 var(--sans);margin:0 0 4px}
.mobile-election-find p{font-size:14px;line-height:1.5;margin:0;color:var(--ink-dim)}
.mobile-seat-heading{display:flex;justify-content:space-between;align-items:center;gap:12px}
.mobile-seat-heading h2{font:650 24px/1.25 var(--sans);margin:4px 0;overflow-wrap:anywhere}
.mobile-seat-heading p,.mobile-candidate-count{font-size:14px;line-height:1.5;margin:0 0 12px}
.mobile-map-reset{min-height:48px;padding:10px 16px;border:1px solid var(--line);border-radius:12px;background:var(--surface-soft-2);color:var(--ink);font:600 14px var(--sans);cursor:pointer}
.map-inspect-option[hidden],.map-inspect-noresult[hidden],.map-inspect-select-list[hidden]{display:none!important}
@media(max-width:860px){
 body.prn-mode{--ink-dim:#b9c4d1;--ink-faint:#b2bdca}
 body.prn-mode #panel-state .seat-detail-main{font-size:16px;line-height:1.5}
 body.map-inspect.prn-mode #panel-state #map-inspect-tray{max-height:62dvh;border:1px solid var(--map-ui-border);border-bottom:0;background:var(--map-ui-surface);box-shadow:none;padding:16px 16px max(16px,env(safe-area-inset-bottom));border-radius:20px 20px 0 0}
 body.map-inspect.prn-mode #panel-state #map-inspect-tray.has-selection{max-height:66dvh}
 .mobile-election-find{margin-bottom:20px}.mobile-election-find .map-inspect-row{margin-top:12px}
 .mobile-election-find .map-inspect-select-list{position:relative;inset:auto!important;margin:8px 0 0;max-height:38dvh;width:100%}
 .mobile-election-switch{display:block;margin:0 0 12px}.mobile-election-switch>label{font-size:14px;color:var(--ink-dim)}
 .mobile-election-switch .map-inspect-select-list{position:relative;inset:auto!important;margin-top:8px;width:100%}
 .prn-cands-compare,.prn-cands-compare:has(.prn-cc.has-profile){display:grid!important;grid-template-columns:minmax(0,1fr)!important;gap:12px;overflow:visible}
 .prn-cands-compare .prn-cc.is-compact{width:100%;min-width:0;min-height:104px;height:auto;padding:16px;text-align:left;border-radius:12px;background:var(--surface-soft-2);box-shadow:none}
 .prn-cands-compare .prn-cc .prn-cc-head{display:grid!important;grid-template-columns:44px minmax(0,1fr)!important;gap:8px 12px;align-items:center;width:100%}
 .prn-cands-compare .prn-cc .prn-cc-id{min-width:0}.prn-cands-compare .prn-cc .pill{grid-column:2;max-width:100%;white-space:normal;font-size:13px}
 .prn-cands-compare .prn-cc .prn-cc-name,.prn-cands-compare .prn-cc .prn-cc-name>span{font-size:16px;line-height:1.45;white-space:normal;overflow:visible;display:inline; -webkit-line-clamp:unset}
 .prn-cands-compare .prn-cc.is-compact .prn-cc-open{display:block;border:0;padding:0;margin:8px 0 0;font-size:13px;color:var(--ink-dim);background:none}
 .prn-cands-compare .prn-profile-photo{grid-row:span 2}.prn-cands-compare .prn-cc-inc{font-size:12px}
 .map-inspect-option{font-size:16px;line-height:1.45;padding:12px;white-space:normal;min-height:52px}.map-inspect-option-yb{font-size:13px}
 .map-inspect-select-button,.map-inspect-locate,.mobile-map-reset,.map-return-btn{min-height:48px}.map-inspect-locate{min-width:48px}
 .prn-mobile-meta,.prn-mobile-hint{font-size:14px!important}.election-history-details summary{font-size:16px;min-height:48px}
 .candidate-modal .cand-summary p,.candidate-modal .cand-pledge-status p{font-size:16px}
 body.prn-mode .map-return-btn{font-size:16px}.prn-seat-head h2{font-size:24px}
}
html[data-theme="light"] body.prn-mode{--ink-dim:#445365;--ink-faint:#4c5b6b;--map-ui-surface:#f8fafc;--map-ui-border:#cad2dd;--map-ui-focus:#006b60}
@media(max-height:500px) and (max-width:860px){body.map-inspect.prn-mode #panel-state #map-inspect-tray.has-selection{max-height:72dvh}}
@media(max-width:860px){
 .mobile-election-switch>p{font-size:14px;color:var(--ink-dim);margin:0 0 8px}
 .search input,.map-inspect-search{font-size:16px;min-height:48px}
 .map-inspect-select-button{font-size:16px!important;text-align:left}
 .candidate-modal .cand-modal-close,.iconbtn,.card-back{min-width:48px;min-height:48px}
 .mobile-seat-candidates .election-history-details{margin-bottom:0}
}
@media(max-width:860px){
 #stage{background:var(--bg,#101318)}
 .mobile-election-find .map-inspect-select-list.open{box-shadow:none}
 .prn-mode .seat-detail-actions{margin-top:20px}
}
