/* ============================================================================
   Shared newsroom styles (from the Saxony-Anhalt 2026 dashboard); Sweden overrides live in se.css
   Dark, information-dense newsroom UI. Desktop first.
   ========================================================================= */

:root{
  /* surfaces & ink -------------------------------------------------------- */
  --plane:      #090b0f;
  --surface-1:  #12161d;   /* panel surface — the validator's reference surface */
  --surface-2:  #171c25;
  --surface-3:  #1d2430;
  --hair:       #232b37;
  --hair-soft:  #1b212b;

  --ink:        #f2f5f9;
  --ink-2:      #a9b4c4;
  --ink-3:      #8793a6;   /* the quietest text: ≥ 5:1 on every surface */
  --ink-4:      #4a5464;   /* rules, dots and separators only — too faint for text */

  /* status ---------------------------------------------------------------- */
  --good:     #0ca30c;
  --warning:  #fab219;
  --serious:  #ec835a;
  --critical: #d03b3b;
  --live:     #38d47a;

  /* The change map's diverging scale (orange = loss, teal = gain, grey = no
     change) is built in app.js — see RAMP_LOSS / RAMP_GAIN — because the steps
     are chosen there. */

  --no-data:  #262d38;

  --radius: 10px;
  --radius-sm: 6px;
  --shadow: 0 1px 2px rgba(0,0,0,.5), 0 8px 24px -12px rgba(0,0,0,.7);

  --font: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --mono: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;

  color-scheme: dark;
}

*{ box-sizing: border-box; }

/* The UA rule for [hidden] is display:none, which any author `display` value
   beats. Several panels here are flex/grid AND toggled with the hidden
   attribute, so make the attribute authoritative. */
[hidden]{ display: none !important; }

html{ scroll-behavior: smooth; scroll-padding-top: 84px; }

body{
  margin:0;
  background: var(--plane);
  color: var(--ink);
  font: 400 14px/1.45 var(--font);
  -webkit-font-smoothing: antialiased;
}

h1,h2,h3{ margin:0; font-weight:600; letter-spacing:-.01em; }

code{ font-family: var(--mono); font-size:.92em; color: var(--ink-2); }

::selection{ background:#2AAEE8; color:#04070c; }

/* ── scrollbars ─────────────────────────────────────────────────────────── */
*::-webkit-scrollbar{ width:10px; height:10px; }
*::-webkit-scrollbar-track{ background: transparent; }
*::-webkit-scrollbar-thumb{ background: var(--surface-3); border-radius:6px; border:2px solid var(--surface-1); }
*::-webkit-scrollbar-thumb:hover{ background:#2a3442; }

/* ══ header ══════════════════════════════════════════════════════════════ */
.topbar{
  position: sticky; top:0; z-index: 900;
  display:flex; align-items:center; gap:24px;
  /* The bar spans the window, but its contents line up with main's 1620 px
     column (28 px padding inside it) rather than with the window's edges. */
  padding:10px max(28px, calc((100% - 1620px) / 2 + 28px));
  background: rgba(9,11,15,.88);
  backdrop-filter: blur(14px);
  border-bottom:1px solid var(--hair);
}
.brand{ display:flex; align-items:center; gap:11px; flex:0 0 auto; }
.brand-mark{
  width:34px; height:34px; border-radius:8px;
  display:grid; place-items:center;
  background: linear-gradient(145deg,#2AAEE8,#1d6fb0);
  color:#04070c; font-weight:800; font-size:13px; letter-spacing:.02em;
}
.brand-text h1{ font-size:16px; line-height:1.1; }
.brand-text h1 .yr{ color: var(--ink-3); font-weight:500; }
.brand-text p{ margin:1px 0 0; font-size:11px; color: var(--ink-3); }

.nav{ display:flex; gap:2px; flex:1 1 auto; overflow-x:auto; }
.nav a{
  padding:6px 11px; border-radius: var(--radius-sm);
  font-size:12.5px; font-weight:500; color: var(--ink-3);
  text-decoration:none; white-space:nowrap;
}
.nav a:hover{ color: var(--ink); background: var(--surface-2); }
.nav a.active{ color: var(--ink); background: var(--surface-3); }

.livebox{ flex:0 0 auto; text-align:right; }
.live-pill{
  display:inline-flex; align-items:center; gap:7px;
  padding:4px 11px 4px 9px; border-radius:100px;
  font-size:11.5px; font-weight:600; letter-spacing:.03em; text-transform:uppercase;
  border:1px solid var(--hair); background: var(--surface-2); color: var(--ink-2);
}
.live-pill .dot{ width:7px; height:7px; border-radius:50%; background: var(--ink-4); }
.live-pill[data-state="live"]{ color:#8ff0bb; border-color:#1c5c3a; background:#0e2419; }
.live-pill[data-state="live"] .dot{ background: var(--live); animation: pulse 2s ease-in-out infinite; }
.live-pill[data-state="fetching"]{ color:#bcd8f5; border-color:#1e4470; background:#0d1a29; }
.live-pill[data-state="fetching"] .dot{ background:#4a93e8; animation: pulse .9s ease-in-out infinite; }
.live-pill[data-state="error"]{ color:#ffb3b3; border-color:#6a2020; background:#2a1010; }
.live-pill[data-state="error"] .dot{ background: var(--critical); }
.live-pill[data-state="stale"]{ color:#ffd79a; border-color:#6b4a12; background:#241a08; }
.live-pill[data-state="stale"] .dot{ background: var(--warning); }
@keyframes pulse{ 0%,100%{opacity:1} 50%{opacity:.28} }

/* every unit counted: the green of the "All districts counted" tag, but still —
   the pulse would say something is still coming in */
.live-pill[data-state="done"]{ color:#8ff0bb; border-color:#1c5c3a; background:#0e2419; }
.live-pill[data-state="done"] .dot{ background: var(--live); }

.live-meta{ margin-top:3px; font-size:11px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.live-meta .sep{ margin:0 5px; color: var(--ink-4); }
/* the heartbeat: quieter than the result time, but always present */
.chk-time{ color: var(--ink-3); }

/* ══ toast ═══════════════════════════════════════════════════════════════ */
.toast-rail{ position: fixed; top:70px; left:0; right:0; z-index:1000; display:grid; place-items:center; pointer-events:none; }
.toast{
  display:flex; align-items:center; gap:10px;
  padding:9px 18px; border-radius:100px;
  background: linear-gradient(180deg,#1a7f4c,#12623a);
  border:1px solid #2fbd77; color:#eafff3;
  box-shadow: 0 8px 32px -8px rgba(47,189,119,.5);
  font-size:13px; animation: toastIn .35s cubic-bezier(.2,.9,.3,1);
}
.toast strong{ letter-spacing:.09em; font-size:11.5px; }
.toast span{ color:#b6ecd0; font-size:12px; }
@keyframes toastIn{ from{ opacity:0; transform: translateY(-14px) scale(.96);} to{ opacity:1; transform:none; } }

/* ══ layout ══════════════════════════════════════════════════════════════ */
main{ padding:16px 28px 40px; max-width:1620px; margin:0 auto; }

.banner{
  display:flex; align-items:center; gap:10px;
  padding:11px 16px; margin-bottom:14px;
  border-radius: var(--radius); border:1px solid var(--hair);
  background: var(--surface-2); color: var(--ink-2); font-size:13px;
}
.banner-icon{ font-size:15px; }
.banner[data-kind="wait"]{ border-color:#2a3a55; background:#0d1522; color:#bcd0ea; }
.banner[data-kind="error"]{ border-color:#6a2020; background:#1e0e0e; color:#ffc0c0; }
.banner[data-kind="stale"]{ border-color:#6b4a12; background:#1d1608; color:#ffdda8; }
.banner[data-kind="sim"]{ border-color:#a02020; background:#2b0d0d; color:#ffd4d4; }

/* Rehearsal mode must be impossible to overlook or mistake for live results. */
.is-simulated .banner[data-kind="sim"]{ position: sticky; top:64px; z-index:850; }
.is-simulated main{ box-shadow: inset 0 0 0 2px #a02020; border-radius: 4px; }
.is-simulated .brand-mark{ background: linear-gradient(145deg,#e0554f,#a02020); }
.is-simulated .brand-text h1::after{
  content:"SIMULATED"; margin-left:8px; padding:2px 7px; border-radius:100px;
  background:#a02020; color:#fff; font-size:10px; font-weight:800; letter-spacing:.08em; vertical-align:middle;
}

.grid{ display:grid; grid-template-columns: repeat(12,1fr); gap:14px; margin-bottom:14px; }
.span4{ grid-column: span 4; } .span5{ grid-column: span 5; }
.span6{ grid-column: span 6; } .span7{ grid-column: span 7; }
.span8{ grid-column: span 8; } .span12{ grid-column: span 12; }

/* ── hero ────────────────────────────────────────────────────────────────
   The three things worth looking at on election night, all in one screen:
   the party percentages, the seat arithmetic, and the map. Results and seats
   stack on the left; the map takes the full height of the right column.
   ───────────────────────────────────────────────────────────────────────── */
.hero{
  display:grid;
  grid-template-columns: minmax(0, 5.6fr) minmax(0, 6.4fr);
  grid-template-rows: min-content minmax(400px, 1fr) min-content;
  gap:14px; margin-bottom:14px;
  /* A definite height is what lets the middle row be bounded: the results
     table then scrolls inside its card instead of stretching the page, and the
     map gets the whole column. Sized so the three panels share one screen. */
  /* Tall enough that the status bar, the results table and the seats
     all get real room; the map fills whatever that comes to. */
  height: calc(100vh - 132px);
  min-height: 1010px;
}
.hero-status{ grid-column:1; grid-row:1; margin-bottom:0; }
.hero-results{ grid-column:1; grid-row:2; }
.hero-seats{ grid-column:1; grid-row:3; }
/* Saxony-Anhalt is a tall state, so the map takes the whole column height
   rather than sitting in a wide, short box. */
/* The map ends level with the seat card. */
.hero-map{ grid-column:2; grid-row:1 / span 3; }

.panel{
  background: var(--surface-1);
  border:1px solid var(--hair);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  display:flex; flex-direction:column;
  min-width:0;
}
.panel-head{
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding:11px 14px; border-bottom:1px solid var(--hair-soft);
  min-height:44px;
}
.panel-head h2{ font-size:13px; letter-spacing:.02em; text-transform:uppercase; color: var(--ink-2); }
.panel-foot{
  padding:9px 14px; border-top:1px solid var(--hair-soft);
  font-size:11.5px; color: var(--ink-3); line-height:1.45;
}
#compareFoot{ display:flex; align-items:center; flex-wrap:wrap; }
.right-tools{ display:flex; align-items:center; gap:10px; }

.tag{
  font-size:10.5px; font-weight:600; letter-spacing:.05em; text-transform:uppercase;
  padding:3px 8px; border-radius:100px;
  background:#2a1f08; color:#f4c76a; border:1px solid #5b4413;
}
.tag-quiet{ background: var(--surface-3); color: var(--ink-3); border-color: var(--hair); }
.tag-official{ background:#0e2419; color:#8ff0bb; border-color:#1c5c3a; }

/* ══ status bar ══════════════════════════════════════════════════════════
   Supporting context, not the headline — one slim row so results, seats and
   map all start within the first screen.
   ═════════════════════════════════════════════════════════════════════════ */
.kpibar{
  display:flex; align-items:stretch; gap:0;
  background: var(--surface-1); border:1px solid var(--hair);
  border-radius: var(--radius); box-shadow: var(--shadow);
  margin-bottom:0px; overflow:hidden;
}
/* Label above value: the bar now shares the left column with the results
   table, so the items have to be narrow. */
.kpi-item{
  flex:1 1 0; min-width:0;
  display:flex; flex-direction:column; justify-content:center; gap:1px;
  padding:8px 12px; border-right:1px solid var(--hair-soft);
}
.kpi-item:last-child{ border-right:0; }
.k-label{
  font-size:10.5px; letter-spacing:.05em; text-transform:uppercase;
  color: var(--ink-3); font-weight:600; white-space:nowrap;
  display:inline-flex; align-items:center; gap:5px;
}
.k-value{
  font-size:19px; line-height:1.15; font-weight:650; letter-spacing:-.02em;
  color: var(--ink); font-variant-numeric: tabular-nums;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
/* Wraps to a second line rather than cutting off: "Above 5%" lists the parties
   that are in, and an ellipsis hid exactly those names. */
.k-sub{
  font-size:11px; line-height:1.35; color: var(--ink-3); font-variant-numeric: tabular-nums;
  display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:2; overflow:hidden;
}
.kpi-lead{ display:inline-flex; align-items:center; gap:6px; min-width:0; }
.kpi-lead .swatch{ width:9px; height:9px; border-radius:2px; flex:0 0 auto; }
.kpi-progress{ flex:1.45 1 0; }
.kpi-progress .progress{ margin:3px 0 2px; }

.progress{ height:5px; border-radius:100px; background: var(--surface-3); overflow:hidden; }
.progress-fill{
  height:100%; border-radius:100px;
  background: linear-gradient(90deg,#2AAEE8,#57d0ff);
  transition: width .5s cubic-bezier(.3,.8,.4,1);
}

/* Drawn at 14 px so it stays out of the way; the ::after extends what takes the
   click or tap to 30 px without moving anything around it. */
.info{
  position:relative;
  width:14px; height:14px; padding:0; border-radius:50%;
  border:1px solid var(--hair); background: var(--surface-3); color: var(--ink-3);
  font-size:9.5px; font-weight:700; line-height:1; cursor:help; font-family: var(--font);
}
.info::after{ content:""; position:absolute; inset:-8px; }
.info:hover, .info:focus-visible{ color: var(--ink); border-color: var(--ink-3); }
.info:focus-visible{ outline:2px solid #2AAEE8; outline-offset:2px; }

/* ══ tables ══════════════════════════════════════════════════════════════ */
.tablewrap{ overflow:auto; flex:1 1 auto; min-height:0; }
.tablewrap-short{ max-height:250px; }
.tablewrap-tall{ max-height:520px; }
/* The statewide panel shows the parties that matter at a glance and scrolls
   the long tail of micro-parties, so the card stays compact while the
   percentages themselves get bigger. */
/* The table fills whatever height the row gets and scrolls the long tail of
   micro-parties inside the card; the map's height governs the row, not the
   party count. */
.hero-results > .tablewrap{ max-height:none; }

.tbl{ width:100%; border-collapse: collapse; font-size:12.5px; font-variant-numeric: tabular-nums; }
.tbl th{
  position: sticky; top:0; z-index:2;
  background: var(--surface-1);
  padding:8px 10px; text-align:left; white-space:nowrap;
  font-size:10.5px; font-weight:600; letter-spacing:.05em; text-transform:uppercase;
  color: var(--ink-3); border-bottom:1px solid var(--hair);
}
.tbl th.num, .tbl td.num{ text-align:right; }
.tbl td{ padding:6px 10px; border-bottom:1px solid var(--hair-soft); white-space:nowrap; }
.tbl tbody tr:hover{ background: var(--surface-2); }
.tbl tbody tr.clickable{ cursor:pointer; }
.tbl tbody tr.selected{ background:#152233; box-shadow: inset 2px 0 0 #2AAEE8; }
.tbl tbody tr.muted td{ color: var(--ink-3); }
/* Rows, list items and headers that act on a click can be reached and used
   from the keyboard; this is where the focus is. */
.tbl tbody tr[tabindex]:focus-visible,
.ranklist li[tabindex]:focus-visible,
.tbl-sort th[data-sort]:focus-visible{ outline:2px solid #2AAEE8; outline-offset:-2px; }

.tbl-sort th[data-sort]{ cursor:pointer; user-select:none; }
.tbl-sort th[data-sort]:hover, .tbl-sort th[data-sort]:focus-visible{ color: var(--ink-2); }
.tbl-sort th[data-sort]::after{ content:""; display:inline-block; width:8px; }
.tbl-sort th[data-sort][data-dir="asc"]::after{ content:" ▲"; color:#2AAEE8; }
.tbl-sort th[data-sort][data-dir="desc"]::after{ content:" ▼"; color:#2AAEE8; }

/* party cell */
.pcell{ display:flex; align-items:center; gap:8px; min-width:0; }
.swatch{ width:9px; height:16px; border-radius:2px; flex:0 0 auto; }
.pname{ overflow:hidden; text-overflow:ellipsis; }
/* Statewide table: the share bar is the row's own background, so the party,
   its percentage and its strength read as one object. The bar is confined to
   the first cell — it never runs under the change / votes / 2021 / seats
   figures, which are read as numbers, not lengths. */
.tbl-parties .c-main{ width:56%; min-width:230px; position:relative; }
.tbl-parties tr.below td{ opacity:.62; }
.tbl-parties td{ padding:0 9px; height:38px; }
.tbl-parties th{ padding:6px 9px; }
.tbl-parties td.c-main{ padding:0; }

/* .22 rather than more: the party's English name is written across the wash,
   and it has to stay readable (≥ 5:1) on every party's colour, yellow included. */
.rowbar{
  position:absolute; left:0; top:3px; bottom:3px;
  border-radius:0 3px 3px 0; opacity:.22;
  transition: width .55s cubic-bezier(.3,.8,.4,1);
}
.tbl-parties tr:hover .rowbar, .tbl-parties tr:focus-visible .rowbar{ opacity:.34; }

.rowmain{
  position:relative;                       /* above the wash */
  display:grid; grid-template-columns: 10px 1fr auto;
  align-items:center; gap:9px; height:100%; padding:0 12px 0 9px;
}
.rowmain .swatch{ width:10px; height:21px; border-radius:2px; }
.rowmain .pname{ font-size:14.5px; font-weight:550; }
.pgloss{ color: var(--ink-2); font-weight:400; }
.rowpct{ font-weight:680; font-size:21px; letter-spacing:-.02em; font-variant-numeric: tabular-nums; }

.tbl-parties td:nth-child(2){ font-size:14px; }          /* change vs 2021 */
.tbl-parties td:nth-child(3),
.tbl-parties td:nth-child(4){ font-size:11.5px; color: var(--ink-3); }
.tbl-parties td:nth-child(5){ font-size:16px; font-weight:650; }

/* horizontal bar inside a table cell.
   4px rounded data-end, anchored to the baseline, 2px surface gap. */
.bar{ position:relative; height:16px; border-radius:3px; background: var(--surface-3); overflow:hidden; }
.bar > i{
  display:block; height:100%;
  border-radius:0 4px 4px 0;
  transition: width .55s cubic-bezier(.3,.8,.4,1);
}
.bar > b{
  position:absolute; inset:0; left:auto; right:0; width:1px;
  background: var(--ink-4);
}
/* The 5% line the seat distribution turns on, kept where the shares are read. */
.bar-th5{
  position:absolute; top:-1px; bottom:-1px; width:0;
  border-left:1px dashed rgba(242,245,249,.42);
}

.delta{ font-weight:600; }
.delta.up{ color:#7fd6a2; }
.delta.down{ color:#f2938f; }
.delta.flat{ color: var(--ink-3); }

.flip{ display:inline-block; padding:1px 7px; border-radius:100px; font-size:10px; font-weight:700; letter-spacing:.04em; }
.flip.hold{ background: var(--surface-3); color: var(--ink-3); border:1px solid var(--hair); }
.flip.gain{ background:#1a1030; color:#c3aef5; border:1px solid #3d2a6b; }

/* ══ seats ═══════════════════════════════════════════════════════════════ */
/* Seat card: hemicycle and breakdown side by side so the card stays short. */
.seat-body{ display:flex; align-items:stretch; gap:6px; padding:8px 12px 4px; min-height:0; }
/* Before any votes exist there is no hemicycle and no breakdown to show, so the
   card collapses to its heading and the explanation in the footer. */
.seat-body.seat-empty{ display:none; }
.hemi{ position:relative; flex:0 1 360px; min-width:0; max-width:380px; align-self:center; }
.hemi svg{ width:100%; height:auto; display:block; }
.hemi-centre{
  position:absolute; left:0; right:0; bottom:2px;
  display:flex; flex-direction:column; align-items:center; pointer-events:none;
}
.hemi-total{ font-size:32px; font-weight:680; letter-spacing:-.025em; line-height:1; }
.hemi-cap{ font-size:10.5px; letter-spacing:.08em; text-transform:uppercase; color: var(--ink-3); margin-top:1px; }
.hemi circle{ transition: fill .4s ease; }

.seat-table{ flex:1 1 0; min-width:0; max-height:180px; }
.tbl-seats td{ padding:4px 8px; }
.tbl-seats th{ padding:6px 8px; }
.tbl-seats td:nth-child(2){ font-size:15px; font-weight:680; }

/* small inline flag, e.g. a party with no 2022 result */
.mflag{
  flex:0 0 auto; font-size:10px; font-weight:700; letter-spacing:.05em; text-transform:uppercase;
  padding:1px 5px; border-radius:100px; cursor:help; justify-self:start;
  background: var(--surface-3); color: var(--ink-3); border:1px solid var(--hair);
}

/* ══ map ═════════════════════════════════════════════════════════════════ */
.panel-map{ min-height:0; }
.map-controls{ display:flex; gap:10px; align-items:center; }
.ctl{ display:flex; align-items:center; gap:6px; font-size:11px; color: var(--ink-3); white-space:nowrap; }
.ctl > span{ letter-spacing:.03em; text-transform:uppercase; font-weight:600; font-size:10px; }
select, .mini-search, input[type="search"], .btn{
  font-family: var(--font); font-size:12px;
  background: var(--surface-3); color: var(--ink);
  border:1px solid var(--hair); border-radius: var(--radius-sm);
  padding:5px 8px; outline:none;
}
select:focus-visible, input:focus-visible, .btn:focus-visible{ border-color:#2AAEE8; box-shadow:0 0 0 2px rgba(42,174,232,.25); }
.btn{ cursor:pointer; }
.btn:hover{ background:#242c39; }
.btn-ghost{ background:transparent; }

.searchrow{ display:flex; gap:8px; padding:8px 12px; border-bottom:1px solid var(--hair-soft); }
.search{ position:relative; flex:1 1 auto; }
.search input{ width:100%; padding:7px 10px; }
.results{
  position:absolute; z-index:800; top:calc(100% + 4px); left:0; right:0;
  max-height:320px; overflow:auto;
  background: var(--surface-2); border:1px solid var(--hair);
  border-radius: var(--radius-sm); box-shadow: var(--shadow);
}
.results div{ padding:7px 11px; cursor:pointer; font-size:12.5px; border-bottom:1px solid var(--hair-soft); }
.results div:last-child{ border-bottom:0; }
.results div:hover, .results div.hi{ background: var(--surface-3); }
.results .rmeta{ color: var(--ink-3); font-size:11px; margin-left:7px; }
.results .rkind{
  float:right; font-size:10px; letter-spacing:.05em; text-transform:uppercase;
  color: var(--ink-3); padding-top:2px;
}
.results .rempty{ color: var(--ink-3); cursor:default; }

/* The map and its detail panel share one stage inside the map card; the panel
   is a zero-width strip until something is selected, so the map keeps the whole
   card to itself the rest of the time. */
.map-stage{ display:flex; flex:1 1 auto; min-height:0; align-items:stretch; }
#map{ flex:1 1 auto; min-width:0; min-height:320px; background:#0c1016; }
.map-side{
  flex:0 0 0; width:0; min-width:0; overflow:hidden;
  border-left:1px solid var(--hair); background: var(--surface-1);
  display:flex; flex-direction:column;
  transition: width .22s cubic-bezier(.3,.8,.4,1), flex-basis .22s cubic-bezier(.3,.8,.4,1);
}
.panel-map.has-selection .map-side{ flex:0 0 352px; width:352px; }
.side-head{
  display:flex; align-items:center; justify-content:space-between; gap:8px;
  padding:9px 12px; border-bottom:1px solid var(--hair-soft); flex:0 0 auto;
}
/* The selected area's name is the panel's headline, not a caption above it. */
.side-head h3{ font-size:17px; font-weight:650; letter-spacing:-.01em; line-height:1.2; color: var(--ink); overflow-wrap:anywhere; }
.btn-close{
  flex:0 0 auto; min-width:30px; min-height:30px; display:grid; place-items:center;
  font-size:18px; line-height:1; padding:0 0 2px; color: var(--ink-3);
}
.btn-close:hover{ color: var(--ink); }
#detailBody{ flex:1 1 auto; min-height:0; overflow:auto; padding:12px; }
.leaflet-container{ background:#0c1016; font-family: var(--font); outline:none; }
/* The optional OSM overlay is a light basemap; darken it to sit under the
   choropleth without fighting it. */
.osm-dark{ filter: invert(1) hue-rotate(180deg) brightness(.62) contrast(.9) saturate(.5); }
.leaflet-control-layers{ background: var(--surface-2) !important; border:1px solid var(--hair) !important; color: var(--ink-2); border-radius: var(--radius-sm) !important; }
.leaflet-control-layers-toggle{ background-color: var(--surface-2) !important; }
.leaflet-control-layers label{ font-size:12px; }
.leaflet-control-layers-expanded{ padding:8px 10px !important; }
.leaflet-control-attribution{ background: rgba(9,11,15,.8) !important; color: var(--ink-3) !important; font-size:10px !important; }
.leaflet-control-attribution a{ color: var(--ink-2) !important; }
.leaflet-bar a{ background: var(--surface-2) !important; color: var(--ink) !important; border-color: var(--hair) !important; }
.leaflet-bar a:hover{ background: var(--surface-3) !important; }
.leaflet-tooltip.wkr-tip{
  background: rgba(13,17,24,.97); border:1px solid var(--hair);
  color: var(--ink); border-radius: var(--radius-sm); box-shadow: var(--shadow);
  padding:8px 10px; font-size:12px; white-space:nowrap;
}
.leaflet-tooltip.wkr-tip::before{ display:none; }
.wkr-tip .t-name{ font-weight:650; margin-bottom:3px; }
.wkr-tip .t-row{ display:flex; align-items:center; gap:7px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.wkr-tip .t-row .swatch{ width:8px; height:8px; border-radius:2px; }
.wkr-tip .t-muted{ color: var(--ink-3); font-size:11px; margin-top:3px; }

.legend{ display:flex; flex-wrap:wrap; align-items:center; gap:5px 14px; padding:9px 14px; border-top:1px solid var(--hair-soft); }
.legend-item{ display:flex; align-items:center; gap:6px; font-size:11px; color: var(--ink-2); }
.legend-item .swatch{ width:11px; height:11px; border-radius:3px; }
.legend-title{ font-size:10px; letter-spacing:.06em; text-transform:uppercase; color: var(--ink-3); font-weight:600; margin-right:2px; }
.legend-ramp{ display:flex; align-items:center; gap:0; }
.legend-ramp i{ width:26px; height:11px; display:block; }
.legend-ramp i:first-child{ border-radius:3px 0 0 3px; }
.legend-ramp i:last-child{ border-radius:0 3px 3px 0; }
.legend-scale{ display:flex; justify-content:space-between; font-size:10px; color: var(--ink-3); }


/* ══ detail panel ════════════════════════════════════════════════════════ */
/* The detail panel carries its own height and follows you down the map
   instead of being stretched to match it. */
.d-sec{ min-width:0; }
.d-stats{ grid-template-columns: repeat(2, minmax(0,1fr)); }
#detailBody{ overflow:auto; flex:1 1 auto; padding:12px 14px; min-height:0; }
.detail-empty p{ color: var(--ink-3); font-size:12.5px; margin:0; }
.d-head{ margin-bottom:12px; }
.d-name{ font-size:18px; font-weight:650; letter-spacing:-.01em; }
.d-sub{ font-size:11.5px; color: var(--ink-3); margin-top:3px; }
.d-stats{ display:grid; grid-template-columns: repeat(2,1fr); gap:7px; margin-bottom:13px; }
.d-stat{ background: var(--surface-2); border:1px solid var(--hair-soft); border-radius: var(--radius-sm); padding:7px 9px; }
.d-stat > span:first-child{ display:block; font-size:10px; letter-spacing:.05em; text-transform:uppercase; color: var(--ink-3); }
.d-stat strong{ font-size:15px; font-weight:600; font-variant-numeric: tabular-nums; }
.d-h{ font-size:10.5px; letter-spacing:.06em; text-transform:uppercase; color: var(--ink-3); font-weight:600; margin:14px 0 7px; }
.d-h:first-child{ margin-top:0; }
.d-rows{ display:flex; flex-direction:column; gap:4px; }
.d-row{ display:grid; grid-template-columns: 14px 1fr 52px 62px 60px; align-items:center; gap:7px; font-size:12px; font-variant-numeric: tabular-nums; }
.d-row.has-cand{ align-items:start; }
.d-row.has-cand .swatch{ margin-top:2px; }
/* Candidate name (and the "Other" bundle count) sit under the party, quietly. */
.rsub{
  display:block; font-style:normal; font-size:10.5px; color: var(--ink-3);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; margin-top:1px;
}
.d-row .swatch{ width:9px; height:14px; border-radius:2px; }
.d-row .rname{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.d-row .rpct{ text-align:right; font-weight:600; }
.d-row .rvotes{ text-align:right; color: var(--ink-3); font-size:11px; }
.d-row .rdelta{ text-align:right; font-size:11.5px; }
.d-note{ font-size:11px; color: var(--ink-3); background: var(--surface-2); border:1px solid var(--hair-soft); border-radius: var(--radius-sm); padding:8px 10px; margin-top:12px; line-height:1.5; }
.d-bar{ grid-column: 2 / -1; height:4px; border-radius:2px; background: var(--surface-3); overflow:hidden; margin-top:-2px; }
.d-bar > i{ display:block; height:100%; border-radius:0 2px 2px 0; }

/* ══ comparison ══════════════════════════════════════════════════════════
   Vertical column pairs — 2021 beside 2026 for each party, both rising from a
   shared baseline, so the year-on-year move reads as a difference in height.
   The plot holds only the value area so the gridlines line up with the bars;
   the labels sit in a matching strip beneath it.
   ═══════════════════════════════════════════════════════════════════════════ */
.compare{ padding:14px 14px 10px; overflow:auto; flex:1 1 auto; min-height:0; }
.cmp-chart{ display:flex; gap:8px; height:100%; min-height:270px; }
.cmp-main{ flex:1 1 auto; min-width:0; display:flex; flex-direction:column; }

.cmp-axis{
  position:relative; flex:0 0 32px;
  margin-bottom:46px;                        /* matches the label strip */
}
.cmp-axis span{
  position:absolute; right:0; transform: translateY(50%);
  font-size:10.5px; color: var(--ink-3); font-variant-numeric: tabular-nums; white-space:nowrap;
}

.cmp-plot{
  position:relative; flex:1 1 auto; min-height:0;
  display:flex; align-items:flex-end; gap:3px;
}
.cmp-grid{
  position:absolute; left:0; right:0; height:0;
  border-top:1px solid var(--hair-soft); pointer-events:none;
}
.cmp-grid:first-of-type{ border-top-color: var(--hair); }

.cmp-col{ position:relative; flex:1 1 0; min-width:0; height:100%; }
.cmp-bars{ display:flex; align-items:flex-end; justify-content:center; gap:2px; height:100%; }
.cmp-bars i{
  display:block; width:44%; max-width:19px; min-width:5px;
  border-radius:3px 3px 0 0;
  transition: height .55s cubic-bezier(.3,.8,.4,1);
}
.cmp-21{ opacity:.36; }                      /* last time, receded */
.cmp-26{ opacity:1; }
.cmp-col:hover .cmp-bars i{ filter: brightness(1.2); }

.cmp-labels{
  flex:0 0 46px; display:flex; gap:3px;
  border-top:1px solid var(--hair); padding-top:5px;
}
.cmp-foot{
  flex:1 1 0; min-width:0;
  display:flex; flex-direction:column; align-items:center; gap:2px;
}
.cmp-foot .swatch{ width:14px; height:3px; border-radius:2px; flex:0 0 auto; }
.cmp-lbl{
  font-size:11px; color: var(--ink-2); text-align:center; line-height:1.15;
  max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.cmp-d{ font-size:11px; font-weight:650; font-variant-numeric: tabular-nums; }

.cmp-key{ display:flex; gap:14px; margin-right:10px; }
.cmp-key i{ display:inline-block; width:12px; height:8px; border-radius:2px; background: var(--ink-3); margin-right:5px; vertical-align:middle; }
.cmp-key .k21 i{ opacity:.36; }

/* ══ charts ══════════════════════════════════════════════════════════════ */
/* Grows with the card so the plot keeps a readable aspect instead of
   becoming a wide sliver. */
.chartwrap{ position:relative; flex:1 1 auto; min-height:300px; padding:12px 14px 2px; }
.chartwrap canvas{ width:100% !important; }
.chart-empty{
  position:absolute; inset:0; display:grid; place-items:center; text-align:center;
  color: var(--ink-3); font-size:12.5px; padding:0 40px; margin:0;
}
.chart-legend{ display:flex; flex-wrap:wrap; gap:5px; padding:4px 14px 12px; }
.chart-legend button{
  display:flex; align-items:center; gap:6px;
  padding:3px 9px; border-radius:100px; cursor:pointer;
  border:1px solid var(--hair); background: var(--surface-2); color: var(--ink-2);
  font:500 11.5px var(--font);
}
.chart-legend button .swatch{ width:9px; height:9px; border-radius:2px; }
.chart-legend button[aria-pressed="false"]{ opacity:.4; }
.chart-legend button:hover{ border-color: var(--ink-4); }

/* ══ ranking ═════════════════════════════════════════════════════════════ */
.rank-controls{ display:flex; flex-wrap:wrap; gap:9px; padding:11px 14px; border-bottom:1px solid var(--hair-soft); }
.rank-controls select{ max-width:130px; }
.seg{ display:inline-flex; border:1px solid var(--hair); border-radius: var(--radius-sm); overflow:hidden; }
.seg button{
  border:0; padding:6px 11px; cursor:pointer;
  background: var(--surface-3); color: var(--ink-3);
  font:500 11.5px var(--font); border-right:1px solid var(--hair);
}
.seg button:last-child{ border-right:0; }
.seg button.on{ background:#1e3550; color:#bcdcff; }
.seg button:focus-visible{ outline:2px solid #2AAEE8; outline-offset:-2px; }
.seg-sm button{ padding:4px 9px; font-size:11px; }

.ranklist{ list-style:none; margin:0; padding:6px 8px; overflow:auto; flex:1 1 auto; max-height:430px; min-height:0; counter-reset: rk; }
.ranklist li{
  display:grid; grid-template-columns: 22px 1fr auto; align-items:center; gap:9px;
  padding:6px 7px; border-radius: var(--radius-sm); cursor:pointer; font-size:12.5px;
}
.ranklist li:hover{ background: var(--surface-2); }
.ranklist li .rk{ color: var(--ink-3); font-size:11px; text-align:right; font-variant-numeric: tabular-nums; }
.ranklist li .nm{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ranklist li .nm em{ display:block; font-style:normal; font-size:10.5px; color: var(--ink-3); }
.ranklist li .vl{ font-weight:650; font-variant-numeric: tabular-nums; text-align:right; }
.ranklist .empty{ color: var(--ink-3); padding:14px 8px; cursor:default; display:block; }

.chk{ display:flex; align-items:center; gap:6px; font-size:11.5px; color: var(--ink-3); cursor:pointer; white-space:nowrap; }
.chk input{ accent-color:#2AAEE8; }
.mini-search{ width:210px; }

/* ══ diagnostics ═════════════════════════════════════════════════════════ */
#diagBody{ padding:12px 14px 14px; }
.diag-grid{ display:grid; grid-template-columns: repeat(auto-fill,minmax(190px,1fr)); gap:8px; }
.diag-cell{ background: var(--surface-2); border:1px solid var(--hair-soft); border-radius: var(--radius-sm); padding:8px 10px; }
.diag-cell span{ display:block; font-size:10px; letter-spacing:.05em; text-transform:uppercase; color: var(--ink-3); }
.diag-cell strong{ font-size:13px; font-weight:600; font-variant-numeric: tabular-nums; word-break:break-all; }
.diag-cell.bad strong{ color:#f2938f; }
.diag-cell.warn strong{ color:#f4c76a; }
.diag-cell.ok strong{ color:#8ff0bb; }
.diag-h{ font-size:10.5px; letter-spacing:.06em; text-transform:uppercase; color: var(--ink-3); margin:16px 0 7px; font-weight:600; }
.diag-list{ display:flex; flex-direction:column; gap:5px; }
.diag-item{ display:flex; gap:9px; font-size:12px; padding:6px 9px; border-radius: var(--radius-sm); background: var(--surface-2); border:1px solid var(--hair-soft); }
.diag-item .lvl{ font-size:10px; font-weight:700; letter-spacing:.05em; padding:1px 6px; border-radius:100px; height:fit-content; }
.diag-item.ok .lvl{ background:#0e2419; color:#8ff0bb; }
.diag-item.warn .lvl{ background:#241a08; color:#f4c76a; }
.diag-item.err .lvl{ background:#2a1010; color:#ffb3b3; }
.diag-log{ font-family: var(--mono); font-size:11px; color: var(--ink-3); max-height:220px; overflow:auto; background: var(--surface-2); border:1px solid var(--hair-soft); border-radius: var(--radius-sm); padding:9px 11px; }
.diag-log div{ padding:1px 0; white-space:pre-wrap; }
.diag-log .e{ color:#f2938f; }
.diag-log .c{ color:#8ff0bb; }

/* ══ tooltip ═════════════════════════════════════════════════════════════ */
.tooltip{
  position:fixed; z-index:1200; max-width:320px;
  background: rgba(13,17,24,.98); border:1px solid var(--hair);
  border-radius: var(--radius-sm); box-shadow: var(--shadow);
  padding:9px 11px; font-size:11.5px; line-height:1.5; color: var(--ink-2);
  pointer-events:none;
}
.tooltip strong{ color: var(--ink); display:block; margin-bottom:3px; }

/* ══ page footer ═════════════════════════════════════════════════════════ */
.pagefoot{
  max-width:1620px; margin:0 auto; padding:0 28px 34px;
  font-size:11px; color: var(--ink-3); line-height:1.6;
}
.pagefoot p{ margin:0 0 5px; }

/* ══ responsive ══════════════════════════════════════════════════════════ */
@media (max-width:1400px){
  .span7,.span8{ grid-column: span 12; }
  .span5,.span4{ grid-column: span 12; }
}
/* Below 1200 px the results, the seats and the map no longer fit side by side,
   so the hero becomes one column. Above it — 1280, 1366 and 1440 px laptops
   included — all three share the first screen. HERO_TWO_COL in app.js and the
   hero rules in de.css use the same width. */
@media (max-width:1199px){
  .hero{ grid-template-columns: minmax(0, 1fr); grid-template-rows: auto auto auto auto;
         height:auto; min-height:0; }
  .hero-results > .tablewrap{ max-height:430px; }
  .hero-status{ grid-column:1; grid-row:1; }
  .hero-results{ grid-column:1; grid-row:2; }
  .hero-map{ grid-column:1; grid-row:3; }
  .hero-seats{ grid-column:1; grid-row:4; }
  #map{ min-height:560px; }
}
@media (max-width:1100px){
  html{ scroll-padding-top:128px; }
  .kpibar{ flex-wrap:wrap; }
  .kpi-item{ flex:1 1 32%; border-bottom:1px solid var(--hair-soft); }
  .span6{ grid-column: span 12; }
  /* The section links drop to a row of their own rather than disappearing:
     the page is long, and on a phone they are the only way around it. */
  .nav{ order:10; flex:1 1 100%; margin:0 -4px; }
}
@media (max-width:900px){
  /* Too narrow for a side panel beside the map: let it take the full width. */
  .map-stage{ flex-direction:column; }
  .panel-map.has-selection .map-side{ flex:0 0 auto; width:100%; border-left:0; border-top:1px solid var(--hair); max-height:420px; }
  .panel-map.has-selection #map{ min-height:360px; }
}
@media (max-width:760px){
  html{ scroll-padding-top:8px; }
  main{ padding:12px 12px 30px; }
  .pagefoot{ padding:0 12px 30px; }
  /* Not sticky on a phone: with the election switch, the live status and the
     section links it is ~170 px, a fifth of the screen held for good. */
  .topbar{ position:static; flex-wrap:wrap; gap:10px; padding:10px 12px; }
  .is-simulated .banner[data-kind="sim"]{ top:0; }
  .livebox{ text-align:left; }
  /* Two KPIs to a row, counting progress across the top: the five used to
     stack into ~370 px, and no party result was on the first screen. */
  .kpi-item{ flex:1 1 40%; }
  .kpi-progress{ flex-basis:100%; }
  /* Statewide table: party and share, change, seats. Votes and the previous
     share are in the detail panel and the comparison chart. */
  .tbl-parties th:nth-child(3), .tbl-parties td:nth-child(3),
  .tbl-parties th:nth-child(4), .tbl-parties td:nth-child(4){ display:none; }
  #map{ min-height:420px; }
  .seat-body{ flex-direction:column; }
  .seat-table{ max-height:none; }
  .d-row{ grid-template-columns: 14px 1fr 48px 58px; }
  .d-row .rvotes{ display:none; }
  .mini-search{ width:140px; }
  .tbl{ font-size:12px; }
}

/* Touch: every control at least ~40 px tall, the size a fingertip can hit. */
@media (pointer: coarse){
  .seg button, .btn, select, .mini-search, input[type="search"]{ min-height:40px; }
  .chart-legend button{ min-height:36px; }
  .btn-close{ min-width:40px; min-height:40px; }
  .info::after{ inset:-13px; }
}

@media (prefers-reduced-motion: reduce){
  *{ animation-duration:.01ms !important; transition-duration:.01ms !important; }
  html{ scroll-behavior:auto; }
}
