/* Visual system adapted from petragarmon.com: near-black ink on #f8f8f8, a
   true-black inverse mode, one soft pink accent, 20px radii and pill controls,
   a single-weight grotesque set tight.

   One rule holds the whole thing together: pink is UI, never data. Every mark
   on the map and in the charts uses the validated categorical trio
   (orange / blue / aqua), which clears CVD and contrast gates on both
   surfaces; the accent only ever appears on controls the reader operates. */

:root {
  --bg: #f8f8f8;
  --bg-raised: #ffffff;
  --bg-sunken: #efefef;
  --ink: #1a1a1a;
  --ink-2: rgba(0, 0, 0, .5);
  --ink-3: rgba(0, 0, 0, .3);
  --hairline: rgba(0, 0, 0, .12);
  --hairline-2: rgba(0, 0, 0, .06);
  --inverse-bg: #000000;
  --inverse-ink: #ffffff;
  --inverse-ink-2: rgba(255, 255, 255, .5);
  --inverse-hairline: rgba(255, 255, 255, .16);

  --accent: #ffb4b4;
  --accent-ink: #1a1a1a;

  --series-out: #eb6834;   /* unplanned, still out */
  --series-res: #2a78d6;   /* restored */
  --series-rep: #1baf7a;   /* registered report */
  --map-border: rgba(0, 0, 0, .20);
  --map-halo: #f8f8f8;

  --radius: 20px;
  --radius-sm: 12px;
  --pill: 999px;
  --gap: 12px;

  --font: "Inter Tight", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --timeline-h: 92px;
  color-scheme: light;
}

:root[data-theme="dark"] {
  --bg: #000000;
  --bg-raised: #0e0e0e;
  --bg-sunken: #141414;
  --ink: #ffffff;
  --ink-2: rgba(255, 255, 255, .5);
  --ink-3: rgba(255, 255, 255, .3);
  --hairline: rgba(255, 255, 255, .16);
  --hairline-2: rgba(255, 255, 255, .08);
  --inverse-bg: #f8f8f8;
  --inverse-ink: #1a1a1a;
  --inverse-ink-2: rgba(0, 0, 0, .5);
  --inverse-hairline: rgba(0, 0, 0, .14);

  --series-out: #d95926;
  --series-res: #3987e5;
  --series-rep: #199e70;
  --map-border: rgba(255, 255, 255, .22);
  --map-halo: #000000;
  color-scheme: dark;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-weight: 400;
  font-size: 15px;
  line-height: 1.2;
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: 100%;
}

button, select, input { font: inherit; color: inherit; }
button { cursor: pointer; border: 0; background: none; padding: 0; }

/* Every component here sets its own `display`, which quietly outranks the UA
   rule for [hidden] -- so `node.hidden = true` from JS did nothing on pills,
   legend rows or toggles. One authoritative rule instead of a per-component
   `[hidden]` twin. */
[hidden] { display: none !important; }

/* ---------- shell ---------- */

.app {
  display: grid;
  height: 100dvh;
  grid-template-columns: 1fr 380px;
  grid-template-rows: auto 1fr var(--timeline-h);
  grid-template-areas: "head head" "map side" "time time";
  gap: var(--gap);
  padding: var(--gap);
}

/* Closing the panel on a wide screen hands its column to the map. */
.app.side-hidden {
  grid-template-columns: 1fr;
  grid-template-areas: "head" "map" "time";
}
.app.side-hidden .side { display: none; }

/* ---------- header ---------- */

.head {
  grid-area: head;
  display: flex;
  align-items: center;
  gap: var(--gap);
  flex-wrap: wrap;
}

.brand { display: flex; align-items: baseline; gap: 10px; min-width: 0; }
.t-short { display: none; }
.brand h1 {
  margin: 0;
  font-size: 22px;
  font-weight: 400;
  letter-spacing: -.02em;
  white-space: nowrap;
}
.brand .sub {
  font-size: 13px;
  color: var(--ink-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.head-right { margin-left: auto; display: flex; align-items: center; gap: 8px; }

.pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 40px;
  padding: 0 16px;
  border-radius: var(--pill);
  background: var(--bg-raised);
  color: var(--ink);
  border: 1px solid var(--hairline);
  white-space: nowrap;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.pill:hover { border-color: var(--ink-3); }
.pill[aria-pressed="true"], .pill.is-on {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: transparent;
}
.pill:focus-visible, select:focus-visible, .scrub:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

select.pill {
  -webkit-appearance: none;
  appearance: none;
  padding-right: 34px;
  background-image:
    linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 18px) 18px, calc(100% - 13px) 18px;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  max-width: 260px;
}

.icon-btn {
  width: 40px; height: 40px; padding: 0;
  justify-content: center;
}
.icon-btn svg { width: 17px; height: 17px; display: block; }

/* The picker is the header's one flexible control -- it names the window being
   shown ("now", or an archived episode), and it is what gives way when the row
   runs out of room. */
select.pill#episodeSel { flex: 0 1 auto; min-width: 0; }

/* ---------- map ---------- */

.map-wrap {
  grid-area: map;
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg-sunken);
}
#map { position: absolute; inset: 0; }

.maplibregl-ctrl-group {
  border-radius: var(--radius-sm) !important;
  background: var(--bg-raised) !important;
  border: 1px solid var(--hairline);
  box-shadow: none !important;
}
.maplibregl-ctrl-group button + button { border-top: 1px solid var(--hairline-2) !important; }
.maplibregl-ctrl-group button span { filter: var(--ctrl-invert, none); }
:root[data-theme="dark"] .maplibregl-ctrl-group button span { filter: invert(1); }
.maplibregl-ctrl-attrib {
  background: color-mix(in srgb, var(--bg-raised) 88%, transparent) !important;
  border-radius: var(--pill) !important;
  font-size: 11px;
}
.maplibregl-ctrl-attrib a { color: var(--ink-2); }

/* The 2D/3D switch lives over the map's top-right corner rather than in the
   header: it acts on the map, and the phone header has no room for it. The
   MapLibre control stack is pushed below it. */
.map-tools {
  position: absolute;
  top: 12px; right: 12px;
  z-index: 3;
  display: flex; gap: 8px;
}
.view-seg {
  height: 38px; padding: 4px; flex: none;
  background: var(--bg-raised);
  border: 1px solid var(--hairline);
}
.view-seg button { height: 28px; min-width: 38px; font-size: 13px; }
.maplibregl-ctrl-top-right { padding-top: 46px; }

/* Floating clock + region chip over the map */
.map-overlay {
  position: absolute;
  top: 12px; left: 12px;
  display: flex; flex-direction: column; align-items: flex-start; gap: 8px;
  pointer-events: none;
  z-index: 2;
}
.map-overlay > * { pointer-events: auto; }

.clock {
  background: var(--bg-raised);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-sm);
  padding: 10px 14px;
}
.clock .time { font-size: 26px; letter-spacing: -.03em; font-variant-numeric: tabular-nums; }
.clock .date { font-size: 12px; color: var(--ink-2); margin-top: 2px; }
.clock .gap-note { font-size: 11px; color: var(--series-out); margin-top: 4px; }

.region-chip {
  display: none;
  align-items: center; gap: 8px;
  background: var(--accent); color: var(--accent-ink);
  border-radius: var(--pill); padding: 0 8px 0 14px; height: 34px;
  font-size: 13px;
}
.region-chip.on { display: inline-flex; }
.region-chip button {
  width: 20px; height: 20px; border-radius: 50%;
  display: grid; place-items: center; color: inherit;
}

/* Legend sits on the map because that is what it explains. */
.legend {
  position: absolute; left: 12px; bottom: 12px; z-index: 2;
  background: var(--bg-raised);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  display: flex; flex-direction: column; gap: 7px;
  font-size: 12px;
}
.legend-row { display: flex; align-items: center; gap: 8px; color: var(--ink-2); }
.legend-row b { font-weight: 400; color: var(--ink); }
.swatch { width: 11px; height: 11px; border-radius: 50%; flex: none; }
.swatch.out { background: var(--series-out); }
.swatch.res { background: var(--series-res); opacity: .55; }
.swatch.rep { background: var(--series-rep); }
.swatch.new { background: none; border: 1.5px solid var(--series-out); }
.swatch.resnew { background: none; border: 1.5px solid var(--series-res); }
.swatch.pln { background: none; border: 1.5px solid var(--ink-2); }

/* ---------- the 3D view ---------- */

/* The moving lens ring: over the map, under the chrome, and never in the way
   of a pointer event. */
#lens3d { position: absolute; inset: 0; z-index: 1; pointer-events: none; }

#lens3dRead {
  position: absolute; z-index: 2; pointer-events: none;
  transform: translate(-50%, 0); white-space: nowrap;
  background: var(--bg-raised);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-sm);
  padding: 5px 10px;
  font-variant-numeric: tabular-nums;
  text-align: center; line-height: 1.4;
}
#lens3dRead b { font-weight: 400; font-size: 16px; letter-spacing: -.02em; }
#lens3dRead .o { color: var(--series-out); }
#lens3dRead .r { color: var(--series-res); }
#lens3dRead .sep { color: var(--ink-3); margin: 0 7px; }

.legend-3d { gap: 9px; }
.legend-3d .l3-key { display: flex; flex-direction: column; gap: 7px; }
.legend-3d .hint { color: var(--ink-3); font-size: 11px; }
/* Column, not dot: the swatch says what the mark actually is. */
.swatch.bar { width: 6px; height: 14px; border-radius: 2px; opacity: 1; }
.l3-lens { display: flex; align-items: center; gap: 8px; }
.l3-lab { color: var(--ink-2); font-size: 11px;
  text-transform: uppercase; letter-spacing: .06em; }
#lensSizes { margin-left: auto; }
#lensSizes button { min-width: 26px; padding: 0 8px; height: 24px; font-size: 11.5px; }

/* 3D encodes connection magnitude, and only unplanned outages carry one, so
   the other two layer toggles have nothing to act on while it is up. */
.app.is-3d #tgReports, .app.is-3d #tgPlanned { opacity: .4; pointer-events: none; }

/* ---------- sidebar ---------- */

.side {
  grid-area: side;
  background: var(--bg-raised);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  padding: 16px;
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex; flex-direction: column; gap: 18px;
}

.side-bar {
  display: flex; align-items: center; justify-content: center;
  position: relative;
  min-height: 28px;
  margin: -4px 0 -10px;
  touch-action: none;          /* the sheet drag owns vertical gestures here */
}
.side-close {
  position: absolute; right: 0; top: 0;
  width: 30px; height: 30px; border-radius: var(--pill);
  display: grid; place-items: center;
  color: var(--ink-2); background: var(--bg-sunken);
}
.side-close:hover { color: var(--ink); }
.side-close svg { width: 15px; height: 15px; display: block; }

.stats { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.stat {
  background: var(--bg-sunken);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
}
.stat .k { font-size: 11px; color: var(--ink-2); text-transform: uppercase; letter-spacing: .06em; }
.stat .v {
  font-size: 28px; letter-spacing: -.035em; margin-top: 4px;
  font-variant-numeric: tabular-nums; line-height: 1;
}
/* The roll-up the headline came from: present, and clearly subordinate. */
.stat .sub {
  font-size: 11.5px; color: var(--ink-2); margin-top: 5px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.stat.out .v { color: var(--series-out); }
.stat.res .v { color: var(--series-res); }

.section-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
}
.section-head h2 {
  margin: 0; font-size: 12px; font-weight: 400;
  text-transform: uppercase; letter-spacing: .08em; color: var(--ink-2);
}

.seg { display: inline-flex; background: var(--bg-sunken); border-radius: var(--pill); padding: 3px; }
.seg button {
  height: 28px; padding: 0 12px; border-radius: var(--pill);
  font-size: 12px; color: var(--ink-2);
}
.seg button[aria-pressed="true"] { background: var(--accent); color: var(--accent-ink); }

.charts { display: flex; flex-direction: column; gap: 14px; }
.chart figcaption {
  display: flex; align-items: baseline; justify-content: space-between;
  font-size: 12px; color: var(--ink-2); margin-bottom: 4px;
}
.chart figcaption .cur {
  display: inline-flex; align-items: baseline; gap: 6px;
  font-size: 15px; color: var(--ink); font-variant-numeric: tabular-nums;
}
.chart figcaption .cur b { font-weight: 400; }
.chart figcaption .cur i {
  font-style: normal; font-size: 11.5px; color: var(--ink-2);
}
.chart svg { display: block; width: 100%; height: 92px; overflow: visible; }

.toggles { display: flex; flex-direction: column; gap: 8px; }
.toggle {
  display: flex; align-items: center; gap: 10px;
  height: 38px; padding: 0 12px;
  border-radius: var(--radius-sm);
  background: var(--bg-sunken);
  font-size: 13px;
  width: 100%;
  text-align: left;
}
.toggle .box {
  width: 16px; height: 16px; border-radius: 5px; flex: none;
  border: 1.5px solid var(--ink-3);
  display: grid; place-items: center;
}
.toggle[aria-pressed="true"] .box { background: var(--accent); border-color: transparent; }
.toggle[aria-pressed="true"] .box svg { display: block; }
.toggle .box svg { display: none; width: 10px; height: 10px; color: var(--accent-ink); }
.toggle .count {
  margin-left: auto; color: var(--ink); font-variant-numeric: tabular-nums;
  display: inline-flex; align-items: baseline; gap: 5px;
}
.toggle .count b { font-weight: 400; }
.toggle .count i { font-style: normal; font-size: 11px; color: var(--ink-3); }

.table-wrap { overflow-x: auto; }
table.reg { width: 100%; border-collapse: collapse; font-size: 12.5px; }
table.reg th, table.reg td { padding: 7px 4px; text-align: right; white-space: nowrap; }

/* The panel is 380px (330px from the 1080px breakpoint down), and four nowrap
   columns do not fit in it: "Dienvidkurzemes novads" alone wanted 146px and
   pushed the table into a horizontal scroll. Two levers fix it without cutting
   a column. The name wraps -- `anywhere` rather than `break-word` so it also
   lowers min-content, which is what actually stops the table from overflowing
   at the narrow breakpoint; in practice the surplus width means it only ever
   breaks at the space. And the numeric columns are sized by their headers, not
   their numbers ("Connections" at 11px was wider than any count it labels), so
   the header type comes down a step. */
table.reg th:first-child, table.reg td:first-child {
  text-align: left; white-space: normal; overflow-wrap: anywhere;
}
table.reg thead th {
  color: var(--ink-2); font-weight: 400; font-size: 10px;
  text-transform: uppercase; letter-spacing: .035em;
  border-bottom: 1px solid var(--hairline);
}
table.reg tbody tr { border-bottom: 1px solid var(--hairline-2); cursor: pointer; }
table.reg tbody tr:hover { background: var(--bg-sunken); }
table.reg tbody tr.sel { background: var(--accent); color: var(--accent-ink); }
table.reg td.num { font-variant-numeric: tabular-nums; }
table.reg td.num.lead { color: var(--ink); }
table.reg td.num:not(.lead) { color: var(--ink-2); }
table.reg tbody tr.sel td.num { color: inherit; }

.about { font-size: 12px; color: var(--ink-2); line-height: 1.45; }
.about a { color: var(--ink); }
.about h2 { font-size: 12px; font-weight: 400; text-transform: uppercase; letter-spacing: .08em; margin: 0 0 6px; }

/* ---------- timeline ---------- */

.time-bar {
  grid-area: time;
  background: var(--inverse-bg);
  color: var(--inverse-ink);
  border-radius: var(--radius);
  padding: 14px 20px;
  display: flex; align-items: center; gap: 18px;
}

.play {
  width: 48px; height: 48px; border-radius: 50%;
  background: var(--accent); color: var(--accent-ink);
  display: grid; place-items: center; flex: none;
}
.play svg { width: 18px; height: 18px; }

.scrub-wrap { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 7px; }

/* The scrubber is a range input restyled so the track can carry the
   played/unplayed split and the data-gap ticks behind it. */
.scrub {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 22px; background: none; margin: 0;
}
.scrub::-webkit-slider-runnable-track {
  height: 6px; border-radius: var(--pill);
  background: linear-gradient(to right,
    var(--accent) 0 var(--pct, 0%), var(--inverse-hairline) var(--pct, 0%) 100%);
}
.scrub::-moz-range-track {
  height: 6px; border-radius: var(--pill); background: var(--inverse-hairline);
}
.scrub::-moz-range-progress { height: 6px; border-radius: var(--pill); background: var(--accent); }
.scrub::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--accent);
  border: 3px solid var(--inverse-bg);
  margin-top: -8px;
}
.scrub::-moz-range-thumb {
  width: 22px; height: 22px; border-radius: 50%; border: 3px solid var(--inverse-bg);
  background: var(--accent);
}

.ticks { display: flex; justify-content: space-between; font-size: 11px; color: var(--inverse-ink-2); }

.speeds { display: flex; gap: 4px; flex: none; }
.speeds button {
  height: 32px; min-width: 40px; padding: 0 10px;
  border-radius: var(--pill);
  border: 1px solid var(--inverse-hairline);
  color: var(--inverse-ink-2);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
}
.speeds button[aria-pressed="true"] {
  background: var(--accent); color: var(--accent-ink); border-color: transparent;
}

/* ---------- popup ---------- */

.maplibregl-popup-content {
  background: var(--bg-raised);
  color: var(--ink);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  font-family: var(--font);
  font-size: 12.5px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, .12);
}
:root[data-theme="dark"] .maplibregl-popup-content { box-shadow: 0 8px 28px rgba(0, 0, 0, .6); }
.maplibregl-popup-tip { display: none; }
.maplibregl-popup-close-button { color: var(--ink-2); font-size: 18px; padding: 2px 7px; }
.pop-h { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.pop-h .swatch { width: 9px; height: 9px; }
.pop-h b { font-weight: 400; }
.pop-row { display: flex; gap: 10px; margin-top: 3px; }
.pop-row span:first-child { color: var(--ink-2); min-width: 84px; }
.pop-row span:last-child { font-variant-numeric: tabular-nums; }

/* ---------- chart interaction ---------- */

.crosshair { stroke: var(--ink); stroke-width: 1; opacity: .55; }
.hoverline { stroke: var(--ink-3); stroke-width: 1; }
.grid-line { stroke: var(--hairline); stroke-width: 1; }
.axis-label { fill: var(--ink-3); font-size: 10px; }
.peak-label { fill: var(--ink-2); font-size: 10px; font-variant-numeric: tabular-nums; }
.chart-hit { fill: transparent; cursor: crosshair; }

.tip {
  position: fixed; z-index: 40; pointer-events: none;
  background: var(--inverse-bg); color: var(--inverse-ink);
  border-radius: 10px; padding: 7px 10px; font-size: 12px;
  transform: translate(-50%, -140%); white-space: nowrap;
  font-variant-numeric: tabular-nums;
  opacity: 0; transition: opacity .1s ease;
}
.tip.on { opacity: 1; }

/* ---------- loading / error ---------- */

.veil {
  position: fixed; inset: 0; z-index: 50;
  background: var(--bg);
  display: grid; place-items: center; gap: 14px;
  align-content: center;
  text-align: center; padding: 24px;
}
.veil .msg { color: var(--ink-2); font-size: 14px; }
.spin {
  width: 26px; height: 26px; border-radius: 50%;
  border: 2px solid var(--hairline); border-top-color: var(--ink);
  animation: spin .8s linear infinite; margin: 0 auto;
}
@keyframes spin { to { transform: rotate(360deg); } }

.sheet-handle, .scrim { display: none; }

/* ---------- responsive ---------- */

@media (max-width: 1080px) {
  .app { grid-template-columns: 1fr 330px; }
  .brand .sub { display: none; }
}

@media (max-width: 860px) {
  :root { --timeline-h: 84px; --gap: 8px; }

  /* minmax(0, 1fr), not 1fr: a grid track's automatic minimum is its content's
     min-content width, and the header row's is wider than a phone. Without
     this the column grows past the viewport and takes the timeline with it. */
  .app {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto 1fr auto;
    grid-template-areas: "head" "map" "time";
  }

  .brand h1 { font-size: 18px; }
  .head-right { gap: 6px; }
  .map-tools { top: 8px; right: 8px; }
  .maplibregl-ctrl-top-right { padding-top: 42px; }

  /* Charts move into a bottom sheet that slides over the map. */
  .side {
    position: fixed;
    left: 8px; right: 8px; bottom: 8px;
    max-height: 76dvh;
    z-index: 30;
    transform: translateY(calc(100% + 16px));
    transition: transform .28s cubic-bezier(.4, 0, .2, 1);
    box-shadow: 0 -10px 40px rgba(0, 0, 0, .18);
    padding-top: 8px;
  }
  .side.open { transform: translateY(0); }
  :root[data-theme="dark"] .side { box-shadow: 0 -10px 40px rgba(0, 0, 0, .7); }

  /* A 4px bar is the affordance; the tap target around it is 40x28. */
  .sheet-handle {
    display: grid; place-items: center;
    width: 56px; height: 28px; padding: 0;
  }
  .sheet-handle span {
    display: block; width: 40px; height: 4px; border-radius: var(--pill);
    background: var(--ink-3);
  }

  .scrim {
    display: block; position: fixed; inset: 0; z-index: 25;
    background: rgba(0, 0, 0, .3);
    opacity: 0; pointer-events: none;
    transition: opacity .28s ease;
  }
  .scrim.on { opacity: 1; pointer-events: auto; }

  .stats { grid-template-columns: 1fr 1fr; }
  .time-bar { padding: 10px 12px; gap: 10px; }
  .play { width: 44px; height: 44px; }
  .speeds button { min-width: 34px; padding: 0 7px; height: 30px; font-size: 12px; }
  .legend { display: none; }
  /* The lens is the 3D view's whole interaction, so its presets survive the
     breakpoint the legend does not -- but the key above them does not fit. */
  .legend-3d { display: flex; padding: 7px 9px; }
  .legend-3d .l3-key { display: none; }
  .l3-lab { display: none; }
  #lens3dRead { font-size: 12px; padding: 4px 8px; }
  #lens3dRead b { font-size: 14px; }
  .clock .time { font-size: 20px; }
}

/* A phone header is one row that must fit: nothing wraps, the title takes what
   the controls leave, and it takes it as a shorter phrase rather than as an
   ellipsis. Wrapping instead would cost the map a second header row. */
@media (max-width: 560px) {
  .t-short { display: inline; }
  .head { flex-wrap: nowrap; gap: 6px; }
  .brand { flex: 0 1 auto; }
  .brand h1 {
    font-size: 15px; min-width: 0;
    overflow: hidden; text-overflow: ellipsis;
  }
  .t-long { display: none; }

  /* min-width: 0 is what lets this group shrink at all -- without it the icon
     buttons hold it at its content width and the title absorbs the whole
     deficit. The high shrink factor spends the picker's slack first, so the
     title stays whole down to ~360px and only then ellipsizes. */
  .head-right { gap: 5px; min-width: 0; flex-shrink: 8; }
  .pill { height: 36px; padding: 0 12px; }
  .icon-btn { width: 34px; height: 34px; }
  /* The picker gives way before the title does: "now" is short, and an episode
     name ellipsizes inside a select without looking broken. */
  select.pill#episodeSel {
    flex: 1 1 auto; min-width: 88px; max-width: 104px;
    padding-right: 28px;
    background-position: calc(100% - 15px) 15px, calc(100% - 10px) 15px;
  }

  .view-seg { height: 34px; padding: 3px; }
  .view-seg button { height: 28px; min-width: 32px; padding: 0 8px; font-size: 12px; }
  .maplibregl-ctrl-top-right { padding-top: 38px; }

  .time-bar { padding: 10px; gap: 8px; }
  .speeds { gap: 3px; }
  .speeds button { min-width: 32px; padding: 0 6px; }
}

/* Below ~360px the four speeds and the scrubber stop coexisting. */
@media (max-width: 359px) {
  .speeds button.wide { display: none; }   /* keep 1x / 5x / 20x */
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}
