/* Malaysia Memilih — page-specific styles for index.html.
   Linked after the shared sheets (shell.css + component sheet) so these rules
   still override them, exactly as the previous inline <style> block did. */

:root {
  color-scheme: dark;
  --page: #080d16;
  --panel: #0e1523;
  --line: #202a3c;
  --muted: #8190a7;
  --red: #dc172b;
  --sky: #38bdf8;
  --teal: #166b68;
  --orange: #b96732;

  /* Constituency borders are neutral so a party fill is the only colour that
     carries meaning. Light theme flips this to near-black. */
  --seat-border: rgba(226, 232, 240, .78);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--page);
  color: #e5eaf2;
  font-family: "Plus Jakarta Sans", sans-serif;
}

button, input, select { font: inherit; }
button, summary { cursor: pointer; }
button { touch-action: manipulation; }
.hidden { display: none !important; }

button:focus-visible,
input:focus-visible,
select:focus-visible,
a:focus-visible,
summary:focus-visible {
  outline: 2px solid var(--sky);
  outline-offset: 3px;
}

/* Full-screen application frame */
.app {
  height: 100vh;
  height: 100svh;
  min-height: 630px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.header-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 29px;
  padding: 7px 12px;
  border: 1px solid #18202d;
  border-radius: 0;
  background: white;
  color: #18202d;
  text-decoration: none;
  font: 700 9px "JetBrains Mono", monospace;
  letter-spacing: .05em;
  text-transform: uppercase;
  white-space: nowrap;
}

.header-button.active {
  background: #080d16;
  color: white;
}

.header-button:hover {
  background: #eef2f6;
  color: #080d16;
}

.header-button.active:hover {
  background: #182335;
  color: white;
}

.header-button.tv-button {
  background: var(--red);
  border-color: var(--red);
  color: white;
}

.header-button.tv-button:hover {
  background: #b91525;
  color: white;
}

/* Compact election/map heading */
.overview-strip {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 16px 24px;
  background: #0e1422;
  border-bottom: 1px solid var(--line);
  position: relative;
}

.overview-strip::before {
  content: "";
  position: absolute;
  top: 0;
  left: 24px;
  width: 130px;
  height: 2px;
  background: var(--red);
}

.heading-accent {
  width: 7px;
  height: 34px;
  border-radius: 8px;
  background: var(--red);
  flex-shrink: 0;
}

.main-subtitle {
  margin: 4px 0 0;
  color: var(--muted);
  font-size: 9px;
}

.allocation {
  width: min(360px, 28vw);
  flex-shrink: 0;
}

.allocation-labels {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 6px;
  font: 600 9px "JetBrains Mono", monospace;
}

.allocation-track {
  height: 9px;
  display: flex;
  overflow: hidden;
  border-radius: 3px;
}

.allocation-track span:first-child {
  width: 74.3243%;
  background: var(--teal);
}

.allocation-track span:last-child {
  flex: 1;
  background: var(--orange);
}

.layer-switch {
  display: flex;
  padding: 3px;
  gap: 3px;
  background: #080d16;
  border: 1px solid #283248;
  border-radius: 6px;
  flex-shrink: 0;
}

.layer-button {
  border: none;
  background: transparent;
  color: #a3afc1;
  padding: 9px 14px;
  border-radius: 3px;
  font: 700 10px "JetBrains Mono", monospace;
  text-transform: uppercase;
  white-space: nowrap;
}

.layer-button[aria-pressed="true"] {
  background: var(--red);
  color: white;
}

/* A house this poll does not fill: visible, but out of reach. */
.layer-button:disabled {
  opacity: .38;
  cursor: not-allowed;
}

/* State selector */
.state-toolbar {
  flex: none;
  min-height: 46px;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 20px;
  background: #0b101b;
  border-bottom: 1px solid var(--line);
}

.state-caption {
  flex-shrink: 0;
  color: var(--muted);
  font: 600 10px "JetBrains Mono", monospace;
}

.state-caption span { color: #f43f5e; }

.state-scroll {
  min-width: 0;
  flex: 1;
  position: relative;
  display: flex;
  align-items: center;
  gap: 5px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: thin;
  scrollbar-color: #354056 transparent;
  padding: 3px 0 5px;
}

.state-chip {
  flex: none;
  min-width: 35px;
  border: 1px solid transparent;
  border-radius: 4px;
  background: #1b2434;
  color: #b8c4d7;
  padding: 6px 9px;
  font: 700 10px "JetBrains Mono", monospace;
  white-space: nowrap;
}

.state-chip:hover {
  border-color: #62718b;
  color: white;
}

.state-chip[aria-pressed="true"] {
  background: var(--red);
  border-color: #f04453;
  color: white;
}

.state-select {
  width: 160px;
  flex: none;
  color: #becadd;
  background: #111a2a;
  border: 1px solid #2a354c;
  border-radius: 5px;
  padding: 7px 9px;
  font-size: 11px;
}

.scroll-button {
  flex: none;
  width: 23px;
  height: 28px;
  border: 1px solid #283348;
  border-radius: 4px;
  background: #131c2b;
  color: #a7b7d0;
  font-size: 15px;
}

/* Map */
.map-stage {
  position: relative;
  flex: 1;
  min-height: 0;
  isolation: isolate;
  background:
    radial-gradient(
      ellipse at 50% 48%,
      #101b2a 0,
      #0b121d 48%,
      #070c14 88%
    );
}

#mapSvg {
  width: 100%;
  height: 100%;
  display: block;
  cursor: grab;
}

#mapSvg:active { cursor: grabbing; }

/*
  Every shape is an outline: the states and the constituencies are not
  coloured at all until a published result gives a seat its winner. A neutral
  border is the only thing a boundary is allowed to say on its own.
*/
.map-shape {
  cursor: pointer;
  vector-effect: non-scaling-stroke;
  /*
    An unfilled shape is only painted along its stroke, and SVG hit-testing
    follows the painted area — so without this, a state or seat with no result
    was clickable only on its 0.7px border and the interior fell through to the
    bare <svg>. `all` keeps the whole polygon interactive at any fill.
  */
  pointer-events: all;
  stroke: var(--seat-border);
  stroke-width: .7;
  stroke-opacity: .9;
  transition: filter .15s ease, stroke-width .15s ease, stroke .15s ease;
}

/* Federal-territory locator dots keep their own weight. */
.map-shape.marker {
  stroke-width: 1.2;
}

.map-shape:hover,
.map-shape:focus-visible {
  stroke: var(--sky);
  stroke-width: 1.6;
  filter: brightness(1.12);
  outline: none;
}

/*
  An unfilled shape has no result to preserve, so pointing at it may wash it.
  A `.filled` shape is somebody's seat or state on the strength of a published
  result: its fill stays put and only the outline moves.
*/
.map-shape:not(.filled):not(.seat):hover,
.map-shape:not(.filled):not(.seat):focus-visible {
  fill: rgba(56, 189, 248, .16);
}

.map-shape.selected:not(.seat):not(.filled) {
  fill: rgba(56, 189, 248, .5) !important;
}

.map-shape.selected:not(.seat),
.map-shape.seat.selected {
  stroke: var(--sky);
  stroke-width: 1.6;
}

.map-shape.seat.selected {
  stroke-width: 2.2;
  filter: brightness(1.2);
  outline: none;
}

.map-legend .legend-winner {
  background: linear-gradient(90deg, #38bdf8 0 33%, #f43f5e 33% 66%, #22c55e 66%);
}

.map-legend .legend-pending {
  background: transparent;
  border: 1px solid var(--seat-border);
}

.map-legend .legend-selected {
  background: rgba(56, 189, 248, .5);
  border: 1px solid var(--sky);
}

/* Active poll strip under the page title. */
.election-scope {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 8px 0 0;
  font: 700 9px "JetBrains Mono", monospace;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: #93a6bf;
}

.election-scope strong { color: #f1f5f9; }

.election-scope-tag {
  background: var(--red);
  color: #fff;
  padding: 2px 6px;
  border-radius: 3px;
  font-size: 8px;
}

.election-scope-date { color: #7c8ca3; }

/* Countdown to polling day (assets/countdown.js fills the value). */
.poll-countdown {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 8px 0 0;
  padding: 4px 9px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--panel-card);
}

.poll-countdown-label {
  font: 700 8px "JetBrains Mono", monospace;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
}

.poll-countdown-value {
  font: 700 10.5px "JetBrains Mono", monospace;
  letter-spacing: .04em;
  color: var(--text);
}

.poll-countdown[data-state="today"] {
  border-color: var(--emerald);
}

.poll-countdown[data-state="today"] .poll-countdown-value,
.poll-countdown[data-state="imminent"] .poll-countdown-value {
  color: var(--amber);
}

.poll-countdown[data-state="closed"] .poll-countdown-value { color: var(--muted); }

.map-label {
  fill: #d4dfec;
  font: 500 10px "JetBrains Mono", monospace;
  paint-order: stroke;
  stroke: #0a111c;
  stroke-width: 3px;
  stroke-linejoin: round;
  pointer-events: none;
}

.state-label-leader {
  stroke: #91a4bd;
  stroke-width: .7;
  stroke-opacity: .7;
  vector-effect: non-scaling-stroke;
  pointer-events: none;
}

.state-map-label {
  font-size: 10px;
  font-weight: 600;
}

.constituency-map-label {
  font-size: 8px;
  stroke-width: 2.5px;
}

.constituency-map-label tspan:first-child {
  fill: #f1f5f9;
  font-weight: 700;
}

.map-heading {
  position: absolute;
  z-index: 5;
  top: 18px;
  left: 22px;
  max-width: calc(100% - 360px);
  pointer-events: none;
}

.map-heading h2 {
  margin: 0;
  font-size: 13px;
  font-weight: 700;
}

.map-heading p {
  color: #798ba5;
  font-size: 10px;
  margin: 5px 0 0;
}

.zoom-stack {
  position: absolute;
  top: 78px;
  left: 18px;
  z-index: 10;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 6px;
  border: 1px solid #293248;
  border-radius: 9px;
  background: #0c1421e8;
}

.zoom-button {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border: none;
  background: #1c283b;
  color: #d3ddea;
  border-radius: 6px;
  font-size: 19px;
}

.zoom-button:hover { background: #2d3b53; }
.zoom-button svg { width: 18px; height: 18px; }

.zoom-button.reset {
  color: #fbbf24;
  border-top: 1px solid #344158;
}

.floating-search {
  position: absolute;
  z-index: 15;
  top: 16px;
  right: 20px;
  width: 285px;
  max-width: calc(100% - 40px);
}

.search-box {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 12px;
  background: #101827f5;
  border: 1px solid #2c3850;
  border-radius: 7px;
  box-shadow: 0 8px 24px #0002;
}

.search-box svg {
  width: 15px;
  height: 15px;
  color: #8395ae;
  flex: none;
}

.search-box input {
  width: 100%;
  min-width: 0;
  border: none;
  background: transparent;
  color: #e2e8f0;
  outline: none;
  font-size: 11px;
}

.search-box:focus-within { border-color: #38bdf8; }

.search-results {
  margin-top: 5px;
  padding: 5px;
  max-height: min(300px, 40vh);
  overflow-y: auto;
  overscroll-behavior: contain;
  background: #0d1626;
  border: 1px solid #334158;
  border-radius: 7px;
  box-shadow: 0 12px 35px #0007;
  scrollbar-width: thin;
}

.search-result {
  display: block;
  width: 100%;
  padding: 9px;
  background: transparent;
  color: #cdd7e5;
  border: none;
  border-radius: 4px;
  font-size: 11px;
  text-align: left;
}

.search-result:hover,
.search-result:focus-visible { background: #213047; }

.search-result small {
  display: block;
  margin-top: 3px;
  color: #8393aa;
  font-size: 9px;
}

.search-note {
  margin: 0;
  padding: 10px;
  color: #8596af;
  font-size: 10px;
  line-height: 1.6;
}

/* Clean data-only constituency popup */
.boundary-card {
  position: absolute;
  z-index: 10;
  right: 20px;
  bottom: 45px;
  width: 290px;
  max-width: calc(100% - 90px);
  background: #0e1725f2;
  border: 1px solid #334158;
  border-radius: 8px;
  box-shadow: 0 14px 45px #0005;
}

.boundary-card > summary {
  padding: 12px 14px;
  list-style: none;
}

.boundary-card > summary::-webkit-details-marker { display: none; }

.boundary-title-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
}

.boundary-eyebrow {
  color: #8a9ab1;
  font: 600 8px "JetBrains Mono", monospace;
  text-transform: uppercase;
  letter-spacing: .1em;
  margin-bottom: 5px;
}

.boundary-name {
  font-size: 12px;
  font-weight: 700;
  color: #7dd3fc;
  overflow-wrap: anywhere;
}

.boundary-content {
  padding: 12px 14px;
  border-top: 1px solid #29354a;
  max-height: min(250px, 34vh);
  overflow-y: auto;
  scrollbar-width: thin;
}

.boundary-content p {
  font-size: 10px;
  color: #93a4bc;
  line-height: 1.7;
  margin: 0 0 8px;
}

.map-legend {
  position: absolute;
  z-index: 5;
  bottom: 15px;
  left: 22px;
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  pointer-events: none;
  font: 9px "JetBrains Mono", monospace;
  color: #8c9cb2;
}

.map-legend span {
  display: flex;
  gap: 5px;
  align-items: center;
}

.map-legend i {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 2px;
}

.map-help {
  position: absolute;
  bottom: 14px;
  right: 20px;
  color: #61738d;
  font: 8px "JetBrains Mono", monospace;
  pointer-events: none;
}

.map-overlay {
  position: absolute;
  inset: 0;
  z-index: 4;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 16px;
  padding: 85px 70px;
  text-align: center;
  background: #080e18ed;
}

.map-overlay p {
  max-width: 630px;
  color: #a3b3ca;
  font-size: 12px;
  line-height: 1.9;
  overflow-wrap: anywhere;
}

.dark-button {
  border: 1px solid #33425b;
  border-radius: 5px;
  background: #172237;
  color: #b5dff4;
  padding: 8px 12px;
  font-size: 10px;
}

.tooltip {
  position: absolute;
  z-index: 30;
  pointer-events: none;
  max-width: min(280px, calc(100% - 20px));
  background: #101a2bf5;
  border: 1px solid #52617b;
  border-radius: 6px;
  padding: 10px 12px;
  box-shadow: 0 8px 25px #0006;
}

/* Status footer */
.status-bar {
  flex: none;
  min-height: 31px;
  display: flex;
  align-items: stretch;
  gap: 12px;
  border-top: 1px solid #253044;
  border-bottom: 1px solid #253044;
  background: #060a11;
  font: 9px "JetBrains Mono", monospace;
}

#mapStatus {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.status-seats {
  margin-left: auto;
  color: #bccbdd;
  white-space: nowrap;
}

/* Secondary dashboard */
.below-map {
  padding: 18px 24px 28px;
  max-width: 1600px;
  margin: 0 auto;
}

.source-row {
  display: flex;
  justify-content: space-between;
  gap: 18px;
  font-size: 10px;
  line-height: 1.8;
  color: #74859f;
}

.source-row p { margin: 0; }

.source-row a {
  color: #7dd3fc;
  white-space: nowrap;
}

.coverage-notice {
  margin: 12px 0;
  padding: 10px 12px;
  border: 1px solid #6f4c27;
  background: #33250f55;
  color: #d8bc87;
  border-radius: 6px;
  font-size: 10px;
  line-height: 1.8;
}

.dashboard-details {
  margin-top: 18px;
  border: 1px solid #263148;
  border-radius: 8px;
  background: #0d1523;
  overflow: hidden;
}

.dashboard-details > summary {
  padding: 16px 18px;
  font-size: 12px;
  font-weight: 700;
}

.dashboard-content {
  border-top: 1px solid #263148;
  padding: 18px;
}

.metric-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0,1fr));
  gap: 12px;
}

.metric {
  border: 1px solid #253149;
  border-radius: 7px;
  background: #111b2c;
  padding: 15px;
}

.metric-label {
  font: 9px "JetBrains Mono", monospace;
  color: #8a9ab2;
  text-transform: uppercase;
}

.metric-value {
  margin-top: 9px;
  font-size: 23px;
  font-weight: 800;
}

.metric-note {
  margin-top: 5px;
  font-size: 10px;
  color: #71839e;
}

.chart-grid {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 20px;
  margin-top: 24px;
}

.chart-panel { min-width: 0; }

.chart-panel h3 {
  margin: 0 0 14px;
  font-size: 12px;
  font-weight: 700;
}

.chart-container {
  height: 340px;
  position: relative;
}

.chart-notice {
  color: #91a2bb;
  font-size: 11px;
  line-height: 1.8;
}

.table-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  margin: 24px 0 12px;
}

.table-header input {
  color: #e5eaf2;
  background: #080f1b;
  border: 1px solid #33425b;
  padding: 8px 10px;
  border-radius: 5px;
  font-size: 11px;
  width: 210px;
  max-width: 45%;
}

.table-wrap { overflow-x: auto; }

table {
  width: 100%;
  border-collapse: collapse;
  text-align: left;
  font-size: 11px;
}

th {
  padding: 12px;
  background: #080f1b;
  color: #8596af;
  font: 9px "JetBrains Mono", monospace;
  text-transform: uppercase;
}

td {
  padding: 12px;
  border-bottom: 1px solid #202b3f;
  color: #a7b6cd;
}

td button {
  border: none;
  background: none;
  color: #7dd3fc;
  padding: 0;
  text-align: left;
}

.disclaimer {
  margin-top: 18px;
  font-size: 10px;
  line-height: 1.9;
  color: #62758f;
}

@media (min-width: 1600px) {
  .masthead { padding-inline: 36px; }
  .overview-strip { padding-inline: 34px; }
  .state-toolbar { padding-inline: 30px; }
}

@media (max-width: 1100px) {
  .allocation { display: none; }
  .state-select { width: 145px; }
  .desktop-action { display: none; }
}

@media (max-width: 700px) {
  .app { min-height: 650px; }

  .masthead {
    padding: 12px 14px;
    min-height: 60px;
    flex-wrap: wrap;
    gap: 12px;
  }

  .brand-name { font-size: 13px; }

  .brand-note {
    font-size: 7px;
    letter-spacing: .04em;
  }

  .brand-bars { height: 24px; }

  .header-button {
    padding: 7px 8px;
    font-size: 8px;
    flex-shrink: 0;
  }

  .overview-strip {
    padding: 12px 14px;
    flex-wrap: wrap;
    gap: 12px;
  }

  .overview-strip::before { left: 14px; }
  .main-title { font-size: 13px; }

  .layer-switch { margin-left: 19px; }
  .layer-button { padding: 7px 14px; font-size: 9px; }

  .state-toolbar { padding: 6px 10px; gap: 6px; }
  .state-caption { display: none; }
  .state-chip { padding: 6px 8px; }
  .state-select { width: 108px; font-size: 10px; }

  .map-heading {
    top: 12px;
    left: 14px;
    max-width: calc(100% - 28px);
  }

  .map-heading h2 { font-size: 11px; }
  .map-heading p { font-size: 9px; }

  .floating-search {
    top: 57px;
    right: 12px;
    width: 230px;
    max-width: calc(100% - 78px);
  }

  .zoom-stack {
    left: 10px;
    top: 57px;
    padding: 4px;
  }

  .zoom-button { width: 30px; height: 30px; }

  .boundary-card {
    right: 12px;
    bottom: 42px;
    width: 255px;
  }

  .boundary-content { max-height: 145px; }

  .map-legend {
    left: 12px;
    bottom: 14px;
    font-size: 8px;
    gap: 9px;
  }

  .map-help { display: none; }

  .map-overlay { padding: 100px 55px 55px; }
  .map-overlay p { font-size: 11px; }

  .status-tag { padding: 8px; font-size: 7px; }
  .status-seats { display: none; }

  .below-map { padding: 14px 12px 24px; }
  .source-row { flex-direction: column; gap: 5px; }

  .metric-grid {
    grid-template-columns: repeat(2,minmax(0,1fr));
  }

  .chart-grid { grid-template-columns: 1fr; }
  .dashboard-content { padding: 12px; }
}

/*
  Race to government — a floating card over the map itself, not a band that
  pushes the map down. It sits above the seat shapes but under the seat drawer
  and the search box, and the minimise control folds it back to its header when
  it covers a seat the reader wants to click.
*/
.race {
  position: absolute;
  z-index: 8;
  /*
    Held over the lower middle of the map: the corners belong to the heading,
    the zoom stack, the seat search and the boundary legend, and the west-coast
    state labels (Kuala Lumpur down to Melaka) sit in the lower left. Sitting
    above the legend keeps all of them readable.
  */
  left: 50%;
  bottom: 34px;
  transform: translateX(-50%);
  width: min(500px, calc(100% - 48px));
  padding: 12px 16px 13px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--panel-head);
  box-shadow: 0 10px 26px rgba(2, 6, 15, .38);
}

/* Folded: only the header line stays, so the map underneath is clickable. */
.race.is-minimized { padding-bottom: 11px; }

.race.is-minimized .race-sub,
.race.is-minimized .race-body {
  display: none;
}

.race-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
  flex-wrap: wrap;
}

.race-head h2 {
  margin: 0;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: .01em;
  color: var(--text-strong);
}

.race-sub {
  margin: 6px 0 0;
  font-size: 10.5px;
  line-height: 1.7;
  color: var(--muted);
}

.race-sub strong {
  font-size: 12px;
  color: var(--text);
}

.race-sep { margin: 0 6px; color: var(--muted); }

.race-head-meta {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  /* Keeps the note and the fold control on the right if the head wraps. */
  margin-left: auto;
}

/* The title and the count share one line, so folding the card keeps both. */
.race-title-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}

.race-declared {
  font-size: 9px;
  letter-spacing: .06em;
  color: var(--muted);
  white-space: nowrap;
}

/* The minimise control sits beside the provenance note, both outside the body
   so the card can fold to one line. */
.race-toggle {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin: -2px 0 0;
  padding: 2px 8px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: transparent;
  color: var(--muted);
  font: 700 9px "Plus Jakarta Sans", sans-serif;
  letter-spacing: .04em;
  white-space: nowrap;
  transition: color .15s ease, border-color .15s ease;
}

.race-toggle:hover,
.race-toggle:focus-visible {
  border-color: var(--text-soft);
  color: var(--text);
}

.race-toggle-icon {
  font: 700 11px "JetBrains Mono", monospace;
  line-height: 1;
}

/* Provenance note folded behind an info button, so the card stays short. */
.race-note-wrap {
  position: relative;
  padding-top: 1px;
}

.race-note-wrap > summary {
  width: 16px;
  height: 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line);
  border-radius: 50%;
  color: var(--muted);
  font: 700 9px "JetBrains Mono", monospace;
  list-style: none;
  cursor: pointer;
  user-select: none;
}

.race-note-wrap > summary::-webkit-details-marker { display: none; }

.race-note-wrap > summary:hover,
.race-note-wrap[open] > summary {
  border-color: var(--text-soft);
  color: var(--text);
}

.race-bar { position: relative; margin: 14px 0 20px; }

.race-track {
  position: relative;
  display: flex;
  height: 26px;
  border: 1px solid var(--line);
  border-radius: 5px;
  /* Sits one step off the panel, so undeclared seats read as empty track. */
  background: var(--panel-card);
  overflow: hidden;
}

.race-seg { height: 100%; min-width: 2px; }

.race-marker {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 2px;
  margin-left: -1px;
  background: var(--text-strong);
  box-shadow: 0 0 0 1px var(--panel);
}

.race-marker-label {
  position: absolute;
  top: 30px;
  transform: translateX(-50%);
  font-size: 8px;
  letter-spacing: .08em;
  color: var(--muted);
  white-space: nowrap;
}

.race-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 9px 20px;
  margin-top: 16px;
}

.race-party {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 10px;
  color: var(--text-soft);
}

.race-party i {
  width: 8px;
  height: 8px;
  border-radius: 2px;
  display: inline-block;
  flex: none;
}

.race-party b { color: var(--text); font-weight: 700; }

.race-party span {
  font: 9px "JetBrains Mono", monospace;
  color: var(--muted);
}

.race-empty,
.race-note {
  margin: 0;
  font-size: 10px;
  line-height: 1.7;
  color: var(--muted);
}

.race-note {
  position: absolute;
  top: 24px;
  right: 0;
  z-index: 6;
  width: 250px;
  padding: 9px 11px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: var(--panel);
  box-shadow: 0 12px 26px rgba(2, 6, 15, .45);
  font-size: 9.5px;
  line-height: 1.65;
}

@media (max-width: 760px) {
  .race {
    left: 10px;
    right: 10px;
    bottom: 30px;
    transform: none;
    width: auto;
    padding: 9px 12px 11px;
  }

  .race-legend { gap: 7px 14px; }
}

/* Short viewports keep the map usable: the card compacts before the map does. */
@media (max-height: 780px) {
  .race { padding: 6px 14px 8px; }
  .race-bar { margin: 6px 0 15px; }
  .race-track { height: 16px; }
  .race-marker-label { top: 20px; }
}

/* Live campaign and party manifestos (filled from /api/v1/campaign).

   Two tabs: the calendar and the party documents. Each tab is one horizontally
   scrolling row of cards — a phone swipes it, a desktop drags it or uses the
   arrow buttons — and every card opens the reader dialog further down. */
.campaign {
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--panel);
  padding: 16px 18px 14px;
  margin: 0 0 18px;
}

.campaign-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

.campaign-intro {
  min-width: 0;
  max-width: 62ch;
}

.campaign-head h2 {
  margin: 0;
  font-size: 13px;
  font-weight: 800;
  color: var(--text-strong);
}

.campaign-head p {
  margin: 6px 0 0;
  font-size: 10px;
  line-height: 1.7;
  color: var(--muted);
}

.campaign-filters {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  flex-wrap: wrap;
}

.campaign-filter {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.campaign-filter > span {
  font: 700 8.5px "JetBrains Mono", monospace;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted);
}

.campaign-filter select {
  min-width: 132px;
  padding: 6px 8px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--panel-card);
  color: var(--text);
  font-size: 10.5px;
}

/* ------------------------------------------------------------------ tabs */
.campaign-tabs {
  display: flex;
  gap: 4px;
  margin: 14px 0 0;
  border-bottom: 1px solid var(--line);
}

.campaign-tab {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-bottom: -1px;
  padding: 8px 12px;
  border: 0;
  border-bottom: 2px solid transparent;
  background: none;
  color: var(--muted);
  font: 700 10px "JetBrains Mono", monospace;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.campaign-tab:hover {
  color: var(--text);
}

.campaign-tab.active {
  border-bottom-color: var(--red);
  color: var(--text-strong);
}

.campaign-tab-count {
  padding: 1px 5px;
  border-radius: 3px;
  background: rgba(148, 163, 184, .16);
  font-size: 9px;
  letter-spacing: 0;
  color: var(--muted);
}

.campaign-tab.active .campaign-tab-count {
  color: var(--text);
}

.campaign-panel {
  padding-top: 12px;
}

/* -------------------------------------------------------------- carousel */
.campaign-carousel {
  position: relative;
}

.campaign-track {
  display: flex;
  gap: 12px;
  margin: 0;
  padding: 2px 2px 8px;
  list-style: none;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scroll-padding: 2px;
  scrollbar-width: thin;
}

.campaign-track::-webkit-scrollbar {
  height: 8px;
}

.campaign-track::-webkit-scrollbar-thumb {
  border-radius: 4px;
  background: rgba(148, 163, 184, .32);
}

.campaign-step {
  position: absolute;
  top: 50%;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  transform: translateY(-50%);
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--panel);
  color: var(--text);
  font-size: 15px;
  line-height: 1;
  box-shadow: 0 4px 12px rgba(2, 6, 16, .35);
}

.campaign-step.prev { left: -10px; }
.campaign-step.next { right: -10px; }

.campaign-step:hover {
  border-color: var(--sky);
  color: var(--sky);
}

.campaign-step:disabled {
  opacity: .35;
  cursor: default;
  box-shadow: none;
}

.campaign-card {
  display: flex;
  flex: 0 0 clamp(250px, 30vw, 320px);
  min-width: 0;
  scroll-snap-align: start;
}

/* One tile, one button: the photo is the card and the caption sits on it. */
.campaign-card-button {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--panel-card);
  color: #f8fafc;
  text-align: left;
  transition: border-color .15s ease, transform .15s ease;
}

.campaign-card-button:hover,
.campaign-card-button:focus-visible {
  border-color: var(--sky);
  transform: translateY(-2px);
}

.campaign-card-media {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: rgba(148, 163, 184, .12);
}

.campaign-card-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .35s ease;
}

.campaign-card-button:hover .campaign-card-media img {
  transform: scale(1.04);
}

/* No photograph yet: the tile still holds its place, washed in party colour. */
.campaign-card-media.empty {
  background:
    linear-gradient(155deg, rgba(2, 6, 16, .55), rgba(2, 6, 16, .88)),
    var(--campaign-dot, #475569);
}

.campaign-card-plate {
  position: absolute;
  inset: auto 0 0 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 30px 12px 11px;
  background: linear-gradient(
    180deg,
    rgba(3, 7, 15, 0) 0%,
    rgba(3, 7, 15, .55) 40%,
    rgba(3, 7, 15, .93) 100%
  );
}

.campaign-card-kicker {
  display: flex;
  align-items: center;
  gap: 6px;
  font: 700 8.5px "JetBrains Mono", monospace;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: rgba(226, 232, 240, .82);
}

/* The party's own colour, the same swatch the results list uses. */
.campaign-card-kicker::before,
.campaign-modal-kicker::before {
  content: "";
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  background: var(--campaign-dot, var(--muted));
}

.campaign-card-title {
  display: -webkit-box;
  margin: 0;
  overflow: hidden;
  font-size: 11.5px;
  font-weight: 700;
  line-height: 1.4;
  color: #f8fafc;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.campaign-card-meta {
  overflow: hidden;
  font-size: 9px;
  line-height: 1.5;
  color: rgba(226, 232, 240, .74);
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The "open" affordance: hover on a mouse, always on a touch screen. */
.campaign-card-open {
  position: absolute;
  top: 10px;
  right: 10px;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border: 1px solid rgba(255, 255, 255, .34);
  border-radius: 50%;
  background: rgba(3, 7, 15, .55);
  font-size: 11px;
  line-height: 1;
  color: #fff;
  opacity: 0;
  transition: opacity .15s ease;
}

.campaign-card-button:hover .campaign-card-open,
.campaign-card-button:focus-visible .campaign-card-open,
.campaign-card:focus-within .campaign-card-open {
  opacity: 1;
}

/* A touch screen has no hover, so the affordance is always on. */
@media (hover: none) {
  .campaign-card-open {
    opacity: 1;
  }
}

.campaign-card .campaign-live {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 1;
}

/* A party with nothing published yet: a tile of the same shape, no picture. */
.campaign-card-note {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 6px;
  width: 100%;
  aspect-ratio: 4 / 3;
  padding: 12px;
  border: 1px dashed var(--line);
  border-radius: 8px;
  background: var(--panel-card);
}

.campaign-card-note .campaign-card-kicker {
  color: var(--muted);
}

.campaign-card-note p {
  margin: 0;
  font-size: 10.5px;
  line-height: 1.55;
  color: var(--muted);
}

.campaign-live {
  padding: 1px 5px;
  border-radius: 3px;
  background: var(--emerald);
  font: 700 8px "JetBrains Mono", monospace;
  letter-spacing: .08em;
  color: #04160f;
}

/* A card that appeared since this browser last read the section. */
.campaign-new {
  padding: 1px 6px;
  border-radius: 3px;
  background: var(--red, #dc172b);
  font: 700 8px "JetBrains Mono", monospace;
  letter-spacing: .08em;
  color: #fff;
  text-transform: uppercase;
}

.campaign-card .campaign-new {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 1;
}

.campaign-hint {
  margin: 2px 0 0;
  font-size: 9px;
  color: var(--muted);
}

.campaign-empty {
  flex: 1 0 100%;
  margin: 0;
  padding: 14px 2px;
  font-size: 10px;
  line-height: 1.7;
  color: var(--muted);
}

/* ----------------------------------------------------------------- reader */
.campaign-modal {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.campaign-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(3, 7, 15, .72);
}

.campaign-modal-card {
  position: relative;
  display: flex;
  flex-direction: column;
  width: min(760px, 100%);
  max-height: 100%;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--panel);
  box-shadow: 0 24px 60px rgba(2, 6, 16, .55);
}

.campaign-modal-scroll {
  padding: 20px 22px 18px;
  overflow-y: auto;
}

.campaign-modal-close {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--panel);
  color: var(--text);
  font-size: 15px;
  line-height: 1;
}

.campaign-modal-close:hover {
  border-color: var(--red);
  color: var(--red);
}

.campaign-modal-figure {
  margin: 0 0 14px;
}

.campaign-modal-figure img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border: 1px solid var(--line-subtle);
  border-radius: 6px;
}

/* A Creative Commons photo travels with its credit, so the line stays visible
   wherever the picture is shown. */
.campaign-credit {
  margin: 6px 0 0;
  font-size: 8.5px;
  line-height: 1.5;
  color: var(--muted);
}

.campaign-modal-kicker {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 0;
  font: 700 9.5px "JetBrains Mono", monospace;
  letter-spacing: .05em;
  color: var(--muted);
}

.campaign-modal-card h3 {
  margin: 6px 0 0;
  font-size: 16px;
  line-height: 1.35;
  color: var(--text-strong);
}

.campaign-modal-meta {
  margin: 6px 0 0;
  font-size: 10px;
  line-height: 1.6;
  color: var(--muted);
}

.campaign-modal-summary {
  margin: 10px 0 0;
  font-size: 11.5px;
  font-weight: 600;
  line-height: 1.6;
  color: var(--text);
}

.campaign-modal-copy p {
  margin: 10px 0 0;
  font-size: 11.5px;
  line-height: 1.75;
  color: var(--text-soft);
}

.campaign-doc {
  display: inline-block;
  margin-top: 14px;
  font-size: 10.5px;
  line-height: 1.6;
  color: var(--sky);
  text-decoration: none;
}

.campaign-doc:hover {
  text-decoration: underline;
}

.campaign-modal-foot {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 10px 16px;
  border-top: 1px solid var(--line);
  background: var(--panel-card);
}

.campaign-modal-dismiss {
  padding: 7px 14px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--panel);
  color: var(--text);
  font: 700 9px "JetBrains Mono", monospace;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.campaign-modal-dismiss:hover {
  border-color: var(--sky);
  color: var(--sky);
}

body.campaign-modal-open {
  overflow: hidden;
}

@media (max-width: 900px) {
  .campaign-filters {
    width: 100%;
  }

  .campaign-filter {
    flex: 1 1 140px;
  }

  .campaign-filter select {
    min-width: 0;
    width: 100%;
  }

  /* Touch screens swipe the row; the arrows would sit on top of the cards. */
  .campaign-step {
    display: none;
  }
}

@media (max-width: 600px) {
  .campaign-modal {
    padding: 0;
  }

  .campaign-modal-card {
    width: 100%;
    height: 100%;
    border-radius: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  * { scroll-behavior: auto !important; }
}

@media print {
  .no-print { display: none !important; }

  .app {
    height: auto;
    min-height: 0;
    overflow: visible;
  }

  .map-stage { flex: none; height: 480px; }
  .masthead { border-bottom: 1px solid #999; }
  .below-map { max-width: none; }
}
