/* ---------- typeface: Uni Neue, the Vidi Vaka brand font ----------
   WOFF2 copies of the files vidivaka.mk already serves (wp-content/themes/hello-theme-child-master/fonts/).
   Weights: 300 Book, 400 Regular, 700 Bold, 800 Heavy, 900 Black (+ Regular italic). */
@font-face { font-family: 'Uni Neue'; src: url('../assets/fonts/UniNeueBook.woff2') format('woff2'); font-weight: 300; font-style: normal; font-display: swap; }
@font-face { font-family: 'Uni Neue'; src: url('../assets/fonts/UniNeueRegular.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Uni Neue'; src: url('../assets/fonts/UniNeueRegular-Italic.woff2') format('woff2'); font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: 'Uni Neue'; src: url('../assets/fonts/UniNeueBold.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: 'Uni Neue'; src: url('../assets/fonts/UniNeueHeavy.woff2') format('woff2'); font-weight: 800; font-style: normal; font-display: swap; }
@font-face { font-family: 'Uni Neue'; src: url('../assets/fonts/UniNeueBlack.woff2') format('woff2'); font-weight: 900; font-style: normal; font-display: swap; }

* { margin: 0; padding: 0; box-sizing: border-box; }

:root {
  --bg: #0e1116;
  --text: #e8e4dc;
  --muted: #9a958b;
  --accent: #e2714b;
  --card-bg: rgba(14, 17, 22, 0.88);
  --font: 'Uni Neue', 'Segoe UI', system-ui, -apple-system, 'Helvetica Neue', Arial, sans-serif;
}

html { scroll-behavior: auto; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  overflow-x: hidden;
  overflow-anchor: none;
}

/* ---------- scroll progress ---------- */
#progress {
  position: fixed;
  top: 0;
  left: 0;
  height: 3px;
  width: 0;
  background: var(--accent);
  z-index: 60;
}

/* ---------- sticky graphic ---------- */
#graphic {
  position: sticky;
  top: 0;
  width: 100%;
  height: 100vh;
  overflow: hidden;
  z-index: 0;
}

#map { width: 100%; height: 100%; display: block; }

#map .region { stroke: none; transition: opacity .4s ease; }
#map .region.dim { opacity: .2; }
#map .region.hl { opacity: 1; stroke: #f5efe6; stroke-width: 1.4; vector-effect: non-scaling-stroke; }
#map .country-borders {
  fill: none;
  stroke: var(--bg);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
  stroke-linejoin: round;
}
#map .mk-outline {
  fill: none;
  stroke: #fff;
  stroke-width: 2.2;
  vector-effect: non-scaling-stroke;
  stroke-linejoin: round;
  opacity: 0;
  transition: opacity 0.8s ease;
}
#map .mk-outline.hl { opacity: 1; }

/* map dimming per scene */
#map g.world { transition: opacity 1.2s ease; }
body[data-scene="0"] #map g.world { opacity: 0.22; }
body[data-scene="5"] #map g.world { opacity: 0.07; }
body[data-scene="6"] #map g.world { opacity: 0.05; }
body:is([data-scene="7"], [data-scene="8"], [data-scene="9"]) #map g.world { opacity: 0.05; }
body:is([data-scene="10"], [data-scene="11"], [data-scene="12"]) #map g.world { opacity: 0.04; }
body[data-scene="13"] #map g.world { opacity: 0.05; }
body[data-scene="14"] #map g.world { opacity: 0.06; }
/* scenes 15-20 are full-bleed skies that hide the map completely, so keep it near-invisible like the
   other full-bleed scenes. Before, 15 sat at 0.3 and 16-20 had no rule at all (default 1.0), so during
   the 15 -> 16 crossfade the colourful choropleth flashed through both half-transparent layers */
body:is([data-scene="15"], [data-scene="16"], [data-scene="17"], [data-scene="18"], [data-scene="19"], [data-scene="20"]) #map g.world { opacity: 0.04; }
body[data-scene="4"] #map .mk-outline { opacity: 1; }

/* ---------- big number (scene 4) ---------- */
#bignum {
  position: absolute;
  right: 6vw;
  top: 50%;
  transform: translateY(-50%);
  text-align: right;
  opacity: 0;
  pointer-events: none;
  transition: opacity 1s ease;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
}
body[data-scene="4"] #bignum { opacity: 1; }
#bignum .num {
  font-size: clamp(90px, 16vw, 220px);
  font-weight: 900;
  line-height: 0.9;
  color: #fff;
  text-shadow: 0 0 40px rgba(126, 72, 99, 0.9);
}
body[data-scene="4"] #bignum .num { animation: pulse 2.6s ease-in-out 3; }
#bignum .cap {
  display: inline-block;
  margin-top: 14px;
  font-size: 15px;
  color: var(--text);
  max-width: 340px;
  background: rgba(14, 17, 22, 0.72);
  padding: 10px 14px;
  border-radius: 5px;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.85);
  backdrop-filter: blur(3px);
}
@keyframes pulse {
  0%, 100% { text-shadow: 0 0 30px rgba(126, 72, 99, 0.6); }
  50% { text-shadow: 0 0 70px rgba(226, 113, 75, 0.95); }
}
/* Skopje vs. Tirana — fades in once the countUp + pulse have landed */
#bignum .cmp {
  display: inline-block;
  text-align: left;
  width: min(260px, 70vw);
  margin-top: 10px;
  background: rgba(14, 17, 22, 0.72);
  padding: 12px 14px;
  border-radius: 5px;
  backdrop-filter: blur(3px);
  opacity: 0;
  transition: opacity .6s ease;
}
body[data-scene="4"] #bignum .cmp { opacity: 1; transition-delay: 1.5s; }
#bignum .cmp .row { display: flex; align-items: center; margin-bottom: 6px; font-size: 12px; }
#bignum .cmp .row .label { width: 70px; text-align: right; padding-right: 10px; color: var(--text); line-height: 1.2; }
#bignum .cmp .row .label small { display: block; color: var(--muted); font-size: 10px; }
#bignum .cmp .row .track { flex: 1; background: rgba(232, 228, 220, 0.07); border-radius: 2px; }
#bignum .cmp .row .bar { height: 16px; width: 0; border-radius: 2px; background: #5a6472; transition: width .8s cubic-bezier(0.22, 1, 0.36, 1); }
#bignum .cmp .row.mk .bar { background: var(--accent); }
#bignum .cmp .row .val { width: 44px; padding-left: 8px; color: var(--muted); font-variant-numeric: tabular-nums; }
#bignum .cmp .row.mk .val { color: #fff; font-weight: 600; }
body[data-scene="4"] #bignum .cmp .row .bar { width: var(--w); transition-delay: 1.7s; }

/* ---------- top-10 bar chart (scene 5) ---------- */
#chart {
  position: absolute;
  right: 5vw;
  top: 50%;
  transform: translateY(-50%);
  width: min(560px, 55vw);
  font-family: var(--font);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.9s ease;
}
body[data-scene="5"] #chart { opacity: 1; }
#chart .chart-title { font-size: 14px; color: var(--text); line-height: 1.4; margin-bottom: 16px; }
#chart .chart-src { font-size: 11px; color: var(--muted); margin-top: 14px; }
#chart .row { display: flex; align-items: center; margin-bottom: 7px; font-size: 12px; }
#chart .row .label { width: 34%; text-align: right; padding-right: 10px; color: var(--text); line-height: 1.2; }
#chart .row .label small { display: block; color: var(--muted); font-size: 10px; }
#chart .row .track { flex: 1; background: rgba(232, 228, 220, 0.07); border-radius: 2px; }
#chart .row .bar {
  height: 22px;
  width: 0;
  border-radius: 2px;
  background: #5a6472;
  transition: width .25s ease-out, box-shadow .5s ease, filter .5s ease;
}
/* --pop (0..1) is set by scrubChart() once every bar has landed: a glow on the four Macedonian
   rows, plus a one-shot pop (.popped, added once --pop reaches 1) — it overshoots then settles
   into a slightly-enlarged resting state (not back to 1) and holds it for the rest of the scene,
   so the four bars that matter stay visibly marked, not just flash and revert */
#chart .row.mk .bar {
  background: var(--accent);
  box-shadow: 0 0 calc(var(--pop, 0) * 14px) rgba(226, 113, 75, calc(var(--pop, 0) * 0.7));
  filter: brightness(calc(1 + var(--pop, 0) * 0.12));
  transform-origin: left center;
}
#chart .row.mk .bar.popped { animation: chartRowPop .5s cubic-bezier(0.34, 1.56, 0.64, 1) forwards; }
@keyframes chartRowPop {
  0% { transform: scaleY(1); }
  55% { transform: scaleY(1.22); }
  100% { transform: scaleY(1.08); }
}
#chart .row .val { width: 44px; padding-left: 8px; color: var(--muted); font-variant-numeric: tabular-nums; }
#chart .row.mk .val { color: #fff; font-weight: 600; }

/* ---------- lost life-years silhouettes (scene 6) ---------- */
#years {
  position: absolute;
  right: 5vw;
  top: 50%;
  transform: translateY(-50%);
  width: min(540px, 55vw);
  font-family: var(--font);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.9s ease;
}
body[data-scene="6"] #years { opacity: 1; }
#years .years-title { font-size: 15px; color: var(--text); line-height: 1.45; margin-bottom: 18px; }
#years .years-title strong { color: #fff; font-size: 17px; }
#years .years-grid { display: flex; flex-wrap: wrap; gap: 6px; }
#years .years-grid svg {
  width: 26px;
  height: 26px;
  fill: var(--accent);
  opacity: 0;
  transform: translateY(8px) scale(0.6);
  transition: opacity 0.4s ease, transform 0.4s ease;
}
/* silhouettes are revealed progressively by scroll (revealYears in main.js) */
#years .years-grid svg.shown { opacity: 0.92; transform: none; }
#years .years-grid svg.half.shown { opacity: 0.35; }
#years .years-note { font-size: 12px; color: var(--muted); margin-top: 16px; line-height: 1.5; }
#years .years-src { font-size: 11px; color: var(--muted); margin-top: 8px; }

/* ---------- pollution sources donut (scene 7) ---------- */
#sources {
  position: absolute;
  right: 5vw;
  top: 50%;
  transform: translateY(-50%);
  width: min(600px, 58vw);
  font-family: var(--font);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.9s ease;
}
body:is([data-scene="7"], [data-scene="8"], [data-scene="9"]) #sources { opacity: 1; }
#sources .sources-title { font-size: 15px; color: var(--text); line-height: 1.45; margin-bottom: 14px; }
#sources .sources-flex { display: flex; align-items: center; gap: 22px; }
#sources .donut { width: min(320px, 34vw); flex-shrink: 0; }
#sources .donut .center-big { font-size: 64px; font-weight: 900; fill: #fff; font-family: var(--font); }
#sources .donut .center-small { font-size: 15px; fill: #b5b0a6; }
#sources .sources-legend { flex: 1; font-size: 13px; }
#sources .sources-legend .srow { display: flex; align-items: baseline; margin-bottom: 8px; }
#sources .sources-legend .srow .sw { width: 11px; height: 11px; border-radius: 2px; margin-right: 9px; flex-shrink: 0; align-self: center; }
#sources .sources-legend .srow .nm { color: var(--text); }
#sources .sources-legend .srow .pc { margin-left: auto; padding-left: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
#sources .sources-legend .srow.lead .nm, #sources .sources-legend .srow.lead .pc { color: #fff; font-weight: 600; }
#sources .sources-winter {
  font-size: 12.5px;
  color: var(--text);
  margin-top: 14px;
  padding: 8px 12px;
  border-left: 3px solid var(--accent);
  background: rgba(226, 113, 75, 0.08);
  line-height: 1.5;
}
#sources .sources-src { font-size: 11px; color: var(--muted); margin-top: 10px; line-height: 1.5; }

/* ---------- valley inversion (scene 8) — full-bleed ---------- */
#inversion {
  position: absolute;
  inset: 0;
  font-family: var(--font);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.9s ease;
}
body:is([data-scene="10"], [data-scene="11"], [data-scene="12"]) #inversion { opacity: 1; }
#inversion .valley { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
#inversion .inv-head {
  position: absolute;
  top: 3.5vh;
  left: 50%;
  transform: translateX(-50%);
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  max-width: 92vw;
}
#inversion .inv-src {
  position: absolute;
  bottom: 14px;
  right: 20px;
  font-size: 11px;
  color: var(--muted);
  line-height: 1.5;
  max-width: 26vw;
  text-align: right;
}
#inversion .inv-labels text { font-size: 13.5px; fill: #e8e4dc; paint-order: stroke; stroke: rgba(7, 10, 17, 0.85); stroke-width: 3px; stroke-linejoin: round; }
#inversion .inv-gauge .temp { font-size: 15px; fill: #e8e4dc; font-weight: 600; paint-order: stroke; stroke: rgba(7, 10, 17, 0.85); stroke-width: 3px; stroke-linejoin: round; }
#inversion .inv-labels .mount { font-size: 12px; fill: #6d7b92; letter-spacing: 0.08em; stroke: none; }

/* two-state inversion: canvas smoke + haze/lid/night/labels scrubbed from JS (invSetState) */
#inversion .inv-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; pointer-events: none; }
#inversion .haze { opacity: 0.08; }
#inversion .inv-lid { opacity: 0; }
#inversion .inv-night { opacity: 0; }
#inversion .lid-label, #inversion .haze-label { opacity: 0; }
#inversion .inv-gauge { opacity: 0; }
#inversion .city-lights { opacity: 0.2; }
/* the picture is drawn once for wide screens and once for tall ones; invFit() sets .is-portrait */
#inversion .valley .only-port { display: none; }
#inversion .valley.is-portrait .only-port { display: inline; }
#inversion .valley.is-portrait .only-land { display: none; }
#inversion .stars .tw { animation: invtwinkle 5s ease-in-out infinite; animation-delay: var(--d, 0s); }
@keyframes invtwinkle { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }
#inversion .beacon { animation: invbeacon 2.4s steps(1) infinite; }
@keyframes invbeacon { 0%, 60% { opacity: 1; } 61%, 100% { opacity: 0.12; } }
/* darker corners pull the eye to the valley */
#inversion::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: radial-gradient(ellipse 85% 75% at 50% 62%, transparent 52%, rgba(3, 5, 9, 0.5) 100%);
}
#inversion .inv-state {
  font-family: var(--font);
  font-size: 15px; color: var(--text);
  background: rgba(14, 17, 22, 0.62);
  padding: 8px 16px; border-radius: 4px;
  text-align: center; max-width: 88vw;
}

/* ---------- trend lines 2005-2023 (scene 9) ---------- */
#trend {
  position: absolute;
  right: 5vw;
  top: 50%;
  transform: translateY(-50%);
  width: min(640px, 58vw);
  font-family: var(--font);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.9s ease;
}
body[data-scene="13"] #trend { opacity: 1; }
#trend .trend-title { font-size: 15px; color: var(--text); line-height: 1.45; margin-bottom: 10px; }
#trend .trendchart { width: 100%; display: block; }
#trend .trend-note { font-size: 11px; color: var(--muted); margin-top: 10px; line-height: 1.5; }
#trend .trend-src { font-size: 11px; color: var(--muted); margin-top: 4px; }
#trend .grid line { stroke: rgba(232, 228, 220, 0.1); }
#trend .grid text, #trend .xaxis text { font-size: 12px; fill: var(--muted); }
#trend path.tline { fill: none; stroke-linejoin: round; stroke-linecap: round; }
#trend .tlabel { font-size: 13px; }
#trend .tlabel tspan.pct { font-weight: 700; }
#trend .tlabel tspan.stillfirst { font-size: 11px; font-style: italic; fill: var(--muted); }

/* ---------- stations over limit (scene 10) ---------- */
#stations {
  position: absolute;
  right: 5vw;
  top: 50%;
  transform: translateY(-50%);
  width: min(560px, 55vw);
  font-family: var(--font);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.9s ease;
}
body[data-scene="14"] #stations { opacity: 1; }
#stations .st-title { font-size: 15px; color: var(--text); line-height: 1.45; margin-bottom: 12px; }
#stations .st-map { width: 100%; height: 46vh; max-height: 420px; display: block; }
#stations .st-map .st-outline { fill: rgba(232, 228, 220, 0.05); stroke: rgba(232, 228, 220, 0.35); stroke-width: 1; }
#stations .st-map .st-dot { fill: #4a5462; transition: fill 0.5s ease, r 0.4s ease; }
#stations .st-map .st-dot.lit {
  fill: #e2714b;
  filter: drop-shadow(0 0 5px rgba(226, 113, 75, 0.9));
}
#stations .st-readout { font-size: 17px; color: var(--text); margin-top: 6px; }
#stations .st-readout .st-yr { font-family: var(--font); }
#stations .st-readout .st-num { color: #e2714b; font-size: 22px; font-family: var(--font); }
#stations .st-note { font-size: 13px; color: var(--text); margin-top: 8px; }
#stations .st-caption { font-size: 11px; color: var(--muted); margin-top: 8px; line-height: 1.5; font-style: italic; }
#stations .st-src { font-size: 11px; color: var(--muted); margin-top: 8px; }

/* ---------- clean-air finale (scenes 11-15) ---------- */
/* hand-over with #livenow (which paints ABOVE this layer): two half-transparent layers fading at once
   let whatever is behind them show through mid-fade. So this one is fully there the instant scene 16
   starts (hidden under the live sky, which has the same colours at its worst level) and #livenow alone
   fades out over it; scrolling back, it stays put until #livenow has faded back in on top, then drops */
#cleanair {
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0s linear 1.2s;
  font-family: var(--font);
}
body:is([data-scene="16"], [data-scene="17"], [data-scene="18"], [data-scene="19"], [data-scene="20"]) #cleanair { opacity: 1; transition: none; }
#cleanair .citysky { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
#cleanair .skyline path { fill: #0b0f15; }
/* finale background is scroll-scrubbed from JS (applyClean) — no per-scene rules */
#cleanair .sky { fill: #2b2620; }
#cleanair .sun { fill: #f5c186; opacity: 0; }
/* no `fill` here on purpose: the haze colour + soft top edge come from the rect's own gradient (see the
   <linearGradient> in index.html); a CSS fill would override it. Opacity is still scrubbed from JS. */
#cleanair .smog { opacity: 0.72; }
#cleanair .pm circle { fill: #b9b3a5; }
#cleanair .ca-solar path { fill: #4a6ea0; stroke: #6b8bbd; stroke-width: 0.6; }
#cleanair .pg-a { opacity: var(--ca-a, 0.55); }
#cleanair .pg-b { opacity: var(--ca-b, 0.55); }
#cleanair .pg-c { opacity: var(--ca-c, 0.55); }
#cleanair .pg-d { opacity: var(--ca-d, 0.55); }
body:is([data-scene="16"], [data-scene="17"], [data-scene="18"], [data-scene="19"], [data-scene="20"]) #cleanair .pm circle {
  animation: pmfloat var(--dur) ease-in-out var(--del) infinite;
}
@keyframes pmfloat {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-16px); }
}
/* at the top, not the bottom: the street trees (and the extra ones added in the middle) stand along the
   bottom edge, and the centred pill used to sit right on top of five of them */
#cleanair .ca-disclaimer {
  position: absolute;
  top: 14px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 11px;
  color: var(--muted);
  background: rgba(14, 17, 22, 0.6);
  padding: 5px 12px;
  border-radius: 3px;
  max-width: 92vw;
  text-align: center;
  transition: opacity 0.3s ease;
}
/* the finale sky stays fixed behind the quiz while the quiz's top edge fades in over it; this caption is pinned
   to that sky and would ghost through the fade, so it steps aside as soon as the quiz comes into view (JS) */
body.quiz-in #cleanair .ca-disclaimer { opacity: 0; }

/* ---------- live air quality (scene 15) ---------- */
#livenow {
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
  /* out of reach once faded: the panel holds a city picker and two buttons, and a merely transparent
     one kept swallowing taps (and tab stops) over the middle of every other scene */
  visibility: hidden;
  transition: opacity 1.2s ease, visibility 0s linear 1.2s;
  font-family: var(--font);
}
body[data-scene="15"] #livenow { opacity: 1; visibility: visible; transition: opacity 1.2s ease, visibility 0s; }
#livenow .livesky { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
#livenow .skyline path { fill: #0b0f15; }
#livenow .sky, #livenow .smog { transition: all 1.8s ease; }
#livenow .sky { fill: #33455a; }
#livenow[data-level="0"] .sky { fill: #3d5c7d; }
#livenow[data-level="1"] .sky { fill: #37506b; }
#livenow[data-level="2"] .sky { fill: #33455a; }
#livenow[data-level="3"] .sky { fill: #2e3844; }
#livenow[data-level="4"] .sky { fill: #2b2620; }
#livenow .smog { opacity: 0.2; }   /* fill = the rect's own gradient, same as #cleanair */
#livenow[data-level="0"] .smog { opacity: 0.03; }
#livenow[data-level="1"] .smog { opacity: 0.12; }
#livenow[data-level="2"] .smog { opacity: 0.3; }
#livenow[data-level="3"] .smog { opacity: 0.5; }
#livenow[data-level="4"] .smog { opacity: 0.72; }
/* particle field is a 2D canvas whose particle COUNT reflects the live µg/m³ (see main.js) */
#livenow .livecanvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; pointer-events: none; }

#livenow .ln-panel {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(420px, 92vw);
  background: var(--card-bg);
  border: 1px solid rgba(232, 228, 220, 0.14);
  border-radius: 6px;
  padding: 22px 26px;
  text-align: center;
  pointer-events: auto;
}
#livenow .ln-panel .kicker { color: #e25b5b; }
#livenow .ln-city { font-family: var(--font); font-weight: 700; font-size: 24px; color: #fff; margin: 8px 0 4px; }
#livenow .ln-reading { margin: 6px 0 2px; }
#livenow .ln-value { font-family: var(--font); font-size: 64px; font-weight: 900; color: var(--lv-color, #e8e4dc); line-height: 1; }
#livenow .ln-unit { font-size: 14px; color: var(--muted); }
#livenow .ln-label { font-size: 15px; font-weight: 600; color: var(--lv-color, var(--muted)); min-height: 20px; }
#livenow .ln-who { font-size: 12px; color: var(--muted); margin-top: 6px; }
#livenow .ln-pick { display: block; margin-top: 16px; font-size: 13px; color: var(--text); }
#livenow .ln-select {
  display: block;
  margin: 8px auto 0;
  padding: 7px 12px;
  font-size: 15px;
  background: #1a2029;
  color: var(--text);
  border: 1px solid rgba(232, 228, 220, 0.25);
  border-radius: 4px;
  min-width: 220px;
}
#livenow .ln-actions { display: flex; gap: 10px; justify-content: center; margin-top: 12px; }
#livenow .ln-actions button {
  font-family: inherit;
  font-size: 13px;
  color: var(--text);
  background: rgba(232, 228, 220, 0.08);
  border: 1px solid rgba(232, 228, 220, 0.25);
  border-radius: 4px;
  padding: 7px 14px;
  cursor: pointer;
}
#livenow .ln-actions button:hover { background: rgba(232, 228, 220, 0.16); }
#livenow .ln-actionmsg { font-size: 12px; color: var(--muted); margin-top: 6px; min-height: 15px; }
#livenow .ln-meta { font-size: 11px; color: var(--muted); margin-top: 10px; min-height: 16px; }
#livenow .ln-error { font-size: 13px; color: #e2714b; margin-top: 10px; }
#livenow .ln-attrib { font-size: 10px; color: var(--muted); margin-top: 12px; border-top: 1px solid rgba(232, 228, 220, 0.12); padding-top: 8px; line-height: 1.5; }

/* scale bar (scene 11 + escalation): mild non-linear µg/m³ scale with a sliding pointer */
#livenow .ln-scale {
  position: absolute;
  top: 3.5vh;
  left: 50%;
  transform: translateX(-50%);
  width: min(560px, 90vw);
  font-family: var(--font);
  z-index: 2;
  pointer-events: none;
}
#livenow .lns-title {
  font-size: 11px; letter-spacing: 0.14em;
  color: var(--text); text-align: center; margin-bottom: 7px;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
}
#livenow .lns-bar { position: relative; height: 10px; border-radius: 3px; box-shadow: 0 1px 4px rgba(0,0,0,0.4); }
#livenow .lns-pointer {
  position: absolute; top: -8px; left: 0;
  width: 0; height: 0;
  border-left: 6px solid transparent; border-right: 6px solid transparent;
  border-bottom: 8px solid #fff;
  transform: translateX(-50%);
  filter: drop-shadow(0 1px 2px rgba(0,0,0,0.6));
  transition: opacity 0.3s ease;   /* hidden while there is no reading to point at */
}
#livenow .lns-ticks { position: relative; height: 30px; margin-top: 4px; }
#livenow .lns-ticks span {
  position: absolute; transform: translateX(-50%);
  font-size: 11px; color: var(--text); text-align: center; white-space: nowrap;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.85);
}
#livenow .lns-ticks span small { display: block; font-size: 9px; color: var(--accent); letter-spacing: 0.04em; }

/* ---------- closing card (scene 20) ---------- */
/* two classes on purpose: the plain `.card { max-width: 380px }` further down the file used to win over a
   single-class rule here, so this card never got its own width. 440px keeps its right edge clear of the
   station and the sun on a laptop, where it now sits on the left like every other card */
.card.closing-card { max-width: 440px; }
.closing-card h2 { font-weight: 800; font-size: clamp(26px, 3.4vw, 38px); color: #fff; line-height: 1.15; margin: 10px 0 16px; }
.closing-card .cite { margin-top: 18px; border-top: 1px solid rgba(232, 228, 220, 0.15); padding-top: 12px; }
.closing-card .cite-head { margin: 0 0 8px; font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; }
.closing-card .cite-list { list-style: none; margin: 0; }
.closing-card .cite-list li { margin: 0 0 5px; line-height: 1.4; }
.closing-card .cite a { color: var(--text); text-decoration: underline; text-decoration-color: rgba(232, 228, 220, 0.35); text-underline-offset: 2px; }
.closing-card .cite a:hover, .closing-card .cite a:focus-visible { color: #fff; text-decoration-color: var(--accent); }
.closing-card .cite-by { margin-top: 10px; }

/* ---------- legend ---------- */
#legend {
  position: absolute;
  left: 24px;
  bottom: 24px;
  font-family: var(--font);
  font-size: 11px;
  color: var(--muted);
  opacity: 0;
  transition: opacity 1s ease;
  pointer-events: none;
}
body:not([data-scene="0"]) #legend { opacity: 1; }
body:is([data-scene="5"], [data-scene="6"], [data-scene="7"], [data-scene="8"], [data-scene="9"], [data-scene="10"], [data-scene="11"], [data-scene="12"], [data-scene="13"], [data-scene="14"], [data-scene="15"], [data-scene="16"], [data-scene="17"], [data-scene="18"], [data-scene="19"], [data-scene="20"]) #legend { opacity: 0; }
#legend .legend-title { color: var(--text); font-size: 12px; margin-bottom: 8px; line-height: 1.35; }
#legend .swatches { display: flex; width: 216px; }
#legend .swatches span { height: 10px; flex: 1; }
#legend .ticks { display: flex; justify-content: space-between; width: 216px; margin-top: 3px; }
#legend .legend-src { margin-top: 10px; }

/* ---------- scroll steps ---------- */
#scrolly {
  position: relative;
  z-index: 1;
  margin-top: -100vh;   /* text scrolls over the sticky graphic */
  pointer-events: none;
}

.step {
  min-height: 100vh;
  display: flex;
  align-items: center;
  padding: 0 0 0 6vw;
}
.step.title-step { justify-content: center; padding: 0 24px; }
.step.title-step { min-height: 108vh; }
/* scene 20: the sky finishes clearing exactly when this step starts, and the old centred card was already
   96px into view by then, so the sunrise had no quiet moment. The 60vh of empty space on top gives the
   finished scene a beat on its own (same idiom as scenes 5, 6 and 16); the card is still centred in the
   last 100vh, so the resting view at the bottom of the page is unchanged. On desktop it sits on the left
   like every other card, so the finished skyline, station and sun stay visible beside it. */
.step.outro-step { min-height: 160vh; padding: 60vh 0 0 6vw; justify-content: flex-start; }
/* scene 11 is taller: interactive live read, then room to scroll the escalation to 167 */
.step.live-step { min-height: 240vh; }
/* scene 6: card enters late, same idiom as scene 5 now — the 4->5 camera move (back in from
   the Balkans to Macedonia-only) gets a beat with just the empty grid on screen first, then the
   card and the silhouette reveal land together; card exits once the YLL figure has landed,
   leaving the years bars to finish growing alone before scene 7's donut takes over */
.step[data-step="6"] { min-height: 150vh; align-items: flex-start; padding-top: 32vh; }
/* scene 9 (last of the donut group): card exits with room to spare before the crossfade to
   scene 10's inversion visual, so that visual isn't already on screen behind still-visible text */
.step[data-step="9"] { min-height: 150vh; align-items: flex-start; padding-top: 8vh; }
/* scene 12 (last of the inversion group): card exits with room to spare before the crossfade
   to scene 13's trend chart, same reasoning as scene 9 before it */
.step[data-step="12"] { min-height: 150vh; align-items: flex-start; padding-top: 8vh; }
/* scene 4: card exits once the "301" + Tirana comparison have landed — #bignum is its own
   fixed layer (independent of the card's scroll position) so it stays on screen regardless,
   giving the reader room to sit with the headline number and the Skopje-only map alone */
.step[data-step="4"] { min-height: 140vh; align-items: flex-start; padding-top: 8vh; }
/* scene 5: card enters late on purpose — the 301->chart crossfade gets a beat with nothing but
   the empty, stabilizing chart on screen before any text arrives, then the card and the bar
   growth land together; card exits once both lines have landed, bars keep growing behind it,
   then the four Macedonian rows get their quiet glow in the room left afterwards */
.step[data-step="5"] { min-height: 180vh; align-items: flex-start; padding-top: 38vh; }
/* scene 14 (stations) slightly taller: a beat on 2024, then 2025 */
.step[data-step="14"] { min-height: 150vh; }
/* scene 1 slightly taller: a beat on Iceland, then Finland/Sweden */
.step[data-step="1"] { min-height: 150vh; }
/* scene 3 slightly taller: a beat on the red neighbours, then Macedonia */
.step[data-step="3"] { min-height: 150vh; }
/* scene 13 (trend lines): card reads the setup, then gets out of the way — pinned near the top
   instead of centered, so it exits after the reader has the context, leaving the rest of the
   scroll for Macedonia's line to draw and hold alone above the collapsing pack, undistracted by text */
.step[data-step="13"] { min-height: 180vh; align-items: flex-start !important; padding-top: 8vh; }
/* finale recommendations (16-19): each card makes its point then exits, giving its own trace
   in the skyline (solar → trees → station → birds) room to resolve before the next arrives.
   applyClean()'s cp is scrubbed off these steps' real height (computeFinale), so widening them
   here automatically slows the whole clean-up down — no JS threshold retuning needed. */
.step[data-step="16"], .step[data-step="17"], .step[data-step="18"], .step[data-step="19"] {
  min-height: 150vh; align-items: flex-start; padding-top: 8vh;
}
/* scene 16 comes right after the live panel fades out over the finale sky: its card enters late, same
   idiom as scenes 5 and 6, so the sky settles with no text on it for a beat and the card arrives after
   (computeFinale reads the step's top, not its padding, so the clean-up timing is untouched) */
.step[data-step="16"] { padding-top: 32vh; }

/* during the escalation the picker/actions fade AND fold away, so the panel becomes a pure readout
   (a merely faded block kept its height and left a hole between the number and its explanation) */
#livenow .ln-controls {
  display: grid;
  grid-template-rows: 1fr;
  transition: grid-template-rows 0.5s ease, opacity 0.5s ease, visibility 0s;
}
#livenow .ln-controls-inner { min-height: 0; overflow: hidden; }
#livenow.escalating .ln-controls {
  grid-template-rows: 0fr;
  opacity: 0;
  visibility: hidden;    /* also takes the folded-away controls out of the tab order */
  pointer-events: none;
  transition: grid-template-rows 0.5s ease, opacity 0.5s ease, visibility 0s linear 0.5s;
}
/* "live data unavailable" belongs to the live read, not to the worst-day readout */
#livenow.escalating .ln-error { display: none; }
#livenow .ln-value { transition: color 0.6s ease; }

.card {
  max-width: 380px;
  background: var(--card-bg);
  border: 1px solid rgba(232, 228, 220, 0.12);
  backdrop-filter: blur(6px);
  padding: 26px 28px;
  border-radius: 4px;
  font-size: 18px;
  line-height: 1.55;
  pointer-events: auto;
}
.card p + p { margin-top: 14px; }
.card strong { color: #fff; }

.title-card { max-width: 620px; text-align: center; background: none; border: none; backdrop-filter: none; }
.title-card h1 {
  font-weight: 800;
  font-size: clamp(44px, 7vw, 84px);
  line-height: 1.05;
  margin: 18px 0 22px;
  color: #fff;
}
.title-card .lede { font-size: 21px; color: var(--text); }
.kicker {
  font-family: var(--font);
  font-size: 12px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent);
}
.hint { margin-top: 46px; color: var(--muted); font-size: 15px; }
.live-chip {
  display: inline-block;
  margin-top: 22px;
  font-family: var(--font);
  font-size: 13px;
  color: var(--text);
  border: 1px solid rgba(232, 228, 220, 0.25);
  border-radius: 999px;
  padding: 6px 16px;
  background: rgba(14, 17, 22, 0.55);
}
.live-chip strong { color: #fff; }
.live-chip .lc-label { color: var(--muted); }
.src { font-family: var(--font); font-size: 12px; color: var(--muted); }

@media (max-width: 1100px) {
  /* scene 4: "301" top-centre, card at the bottom (was overlapping on portrait) */
  #bignum { right: auto; left: 50%; top: 8vh; transform: translateX(-50%); text-align: center; align-items: center; }
  .step[data-step="4"] { align-items: flex-end; padding-top: 0; padding-bottom: 5vh; }
  .step[data-step="4"] .card { font-size: 15px; padding: 18px 20px; }
  /* scene 5: stack chart above, card below, to avoid overlap */
  #chart {
    right: auto;
    left: 50%;
    top: 6vh;
    transform: translateX(-50%);
    width: min(560px, 92vw);
  }
  .step[data-step="5"] { align-items: flex-end; padding-top: 0; padding-bottom: 4vh; }
  .step[data-step="5"] .card { font-size: 15px; padding: 18px 20px; }
  #years {
    right: auto;
    left: 50%;
    top: 6vh;
    transform: translateX(-50%);
    width: min(540px, 92vw);
  }
  #years .years-grid svg { width: 22px; height: 22px; }
  .step[data-step="6"] { align-items: flex-end; padding-top: 0; padding-bottom: 4vh; }
  .step[data-step="6"] .card { font-size: 15px; padding: 18px 20px; }
  #sources {
    right: auto;
    left: 50%;
    top: 5vh;
    transform: translateX(-50%);
    width: min(600px, 94vw);
  }
  #sources .donut { width: min(280px, 44vw); }
  .step[data-step="7"], .step[data-step="8"], .step[data-step="9"] { align-items: flex-end; padding-top: 0; padding-bottom: 4vh; }
  .step[data-step="7"] .card, .step[data-step="8"] .card, .step[data-step="9"] .card { font-size: 15px; padding: 18px 20px; }
  .step[data-step="10"], .step[data-step="11"], .step[data-step="12"] { align-items: flex-end; padding-top: 0; padding-bottom: 4vh; }
  .step[data-step="10"] .card, .step[data-step="11"] .card, .step[data-step="12"] .card { font-size: 15px; padding: 18px 20px; }
  #trend {
    right: auto;
    left: 50%;
    top: 5vh;
    transform: translateX(-50%);
    width: min(640px, 94vw);
  }
  /* !important: wins back over the desktop flex-start rule — on the narrow layout #trend
     already moves to the top, so the card belongs at the bottom same as every other scene here */
  .step[data-step="13"] { align-items: flex-end !important; padding-top: 0; padding-bottom: 4vh; }
  .step[data-step="13"] .card { font-size: 15px; padding: 18px 20px; }
  #stations {
    right: auto;
    left: 50%;
    top: 8vh;
    transform: translateX(-50%);
    width: min(560px, 92vw);
  }
  #stations .st-map { height: 40vh; }
  .step[data-step="14"] { align-items: flex-end; padding-bottom: 4vh; }
  .step[data-step="14"] .card { font-size: 15px; padding: 18px 20px; }
  .closing-card { font-size: 15px; }
  /* narrow layouts: the closing card is as wide as the screen, so keep it centred as before */
  .step.outro-step { justify-content: center; padding: 60vh 24px 0; }
}

/* users who prefer reduced motion get the story without flights and particles */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation: none !important;
    transition-duration: 0.01s !important;
  }
}

@media (max-width: 640px) {
  .step { padding: 0 16px; }
  .card { max-width: 100%; font-size: 16px; }
  #legend { left: 14px; bottom: 14px; }
  #legend .legend-title { font-size: 11px; }
  #legend .swatches, #legend .ticks { width: 168px; }
  /* scene 4: "301" up top, card at the bottom — no overlap on phones */
  #bignum { right: auto; left: 50%; top: 9vh; transform: translateX(-50%); text-align: center; align-items: center; }
  #bignum .num { font-size: clamp(76px, 24vw, 150px); }
  #bignum .cap { max-width: 88vw; font-size: 14px; }
  .step[data-step="4"] { align-items: flex-end; padding-top: 0; padding-bottom: 5vh; }
  .step[data-step="4"] .card { font-size: 15px; padding: 15px 18px; }
  /* live panel + scale: tighter on phones */
  #livenow .ln-panel { width: min(340px, 92vw); padding: 16px 18px; }
  #livenow .ln-city { font-size: 20px; }
  #livenow .ln-value { font-size: 52px; }
  #livenow .ln-scale { top: 2vh; }
  #stations .st-map { height: 34vh; }
  #stations .st-title, #stations .st-caption { font-size: 12px; }
  .chart-title, #years .years-title, #sources .sources-title, .trend-title, #stations .st-title { font-size: 13px; }
  /* closing card: Uni Neue sets the source list a little taller than the old fonts did, and on a 667px-tall
     phone the card has to fit the screen whole, so the list gets a notch smaller and tighter here */
  .closing-card .cite { font-size: 11px; margin-top: 14px; padding-top: 10px; }
  .closing-card .cite-list li { margin-bottom: 3px; line-height: 1.35; }
  /* ...and the card itself a little less padded: with the quiz button and 11 sources it was 3px taller than the screen */
  .card.closing-card { padding: 20px 22px; }
  .closing-card h2 { margin: 4px 0 12px; }
}
/* short phones (360x640 and below): one more notch of tightness so the closing card still fits the screen whole */
@media (max-width: 640px) and (max-height: 660px) {
  .card.closing-card { padding: 16px 18px; }
  .closing-card h2 { font-size: 24px; margin: 2px 0 10px; }
  .closing-card .cite { margin-top: 12px; padding-top: 8px; }
  .closing-card .cite-list li { margin-bottom: 2px; line-height: 1.3; }
}

/* ---------- quiz epilogue (after the closing card) ---------- */
/* entry button on the closing card */
.closing-card .quiz-cta { margin-top: 16px; }
.quiz-link {
  display: inline-block;
  font-size: 15px; font-weight: 700;
  color: #0e1116; background: var(--accent);
  border-radius: 999px; padding: 10px 20px;
  text-decoration: none;
  transition: background 0.15s ease;
}
.quiz-link:hover, .quiz-link:focus-visible { background: #f08a63; }
.quiz-link:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

/* a normal-flow section that scrolls over the sticky graphic: the top fades in from the finished sky,
   everything below is solid so the picture never shows through the questions */
#quiz {
  position: relative;
  z-index: 2;
  background: linear-gradient(to bottom, rgba(14, 17, 22, 0) 0, var(--bg) 22vh);
  padding: 26vh 24px 14vh;
}
.quiz-wrap { max-width: 640px; margin: 0 auto; }
.quiz-wrap h2 { font-weight: 800; font-size: clamp(30px, 4.6vw, 46px); line-height: 1.1; color: #fff; margin: 10px 0 14px; }
.quiz-intro { font-size: 18px; line-height: 1.5; color: var(--text); margin-bottom: 26px; }
.quiz-box {
  background: var(--card-bg);
  border: 1px solid rgba(232, 228, 220, 0.14);
  border-radius: 6px;
  padding: 26px 28px;
}
.q-count { font-size: 12px; letter-spacing: 0.22em; text-transform: uppercase; color: var(--accent); }
.q-text { font-weight: 800; font-size: clamp(21px, 3vw, 26px); line-height: 1.3; color: #fff; margin: 10px 0 20px; outline: none; }
.q-options { display: grid; gap: 10px; }
.q-opt {
  display: block; width: 100%; text-align: left;
  font: inherit; font-size: 18px; line-height: 1.4; color: var(--text);
  background: rgba(232, 228, 220, 0.06);
  border: 1px solid rgba(232, 228, 220, 0.22);
  border-radius: 6px; padding: 14px 16px;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.q-opt:hover:not(:disabled) { background: rgba(232, 228, 220, 0.13); }
.q-opt:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.q-opt:disabled { cursor: default; }
.q-opt.is-correct { border-color: #9fc2a8; background: rgba(159, 194, 168, 0.16); color: #fff; }
.q-opt.is-wrong { border-color: var(--accent); background: rgba(226, 113, 75, 0.16); color: #fff; }

.q-readout { font-weight: 900; font-size: 56px; line-height: 1; color: #fff; margin: 4px 0 12px; font-variant-numeric: tabular-nums; }
.q-range { display: block; width: 100%; height: 30px; margin: 0; background: transparent; -webkit-appearance: none; appearance: none; cursor: pointer; }
.q-range:disabled { cursor: default; opacity: 0.55; }
.q-range::-webkit-slider-runnable-track { height: 6px; border-radius: 3px; background: rgba(232, 228, 220, 0.22); }
.q-range::-moz-range-track { height: 6px; border-radius: 3px; background: rgba(232, 228, 220, 0.22); }
.q-range::-webkit-slider-thumb { -webkit-appearance: none; width: 26px; height: 26px; margin-top: -10px; border-radius: 50%; background: var(--accent); border: 3px solid #0e1116; box-shadow: 0 0 0 1px rgba(232, 228, 220, 0.4); }
.q-range::-moz-range-thumb { width: 20px; height: 20px; border-radius: 50%; background: var(--accent); border: 3px solid #0e1116; box-shadow: 0 0 0 1px rgba(232, 228, 220, 0.4); }
.q-range:focus-visible { outline: 2px solid #fff; outline-offset: 4px; }
.q-scale { display: flex; justify-content: space-between; font-size: 13px; color: var(--muted); margin-top: 2px; }
.q-note { font-size: 13px; color: var(--muted); margin: 12px 0 16px; }

.q-btn {
  font: inherit; font-size: 16px; font-weight: 700;
  border-radius: 999px; padding: 11px 26px;
  cursor: pointer;
  color: var(--text); background: none;
  border: 1px solid rgba(232, 228, 220, 0.3);
  transition: background 0.15s ease;
}
.q-btn:hover { background: rgba(232, 228, 220, 0.1); }
.q-btn.primary { color: #0e1116; background: var(--accent); border-color: var(--accent); }
.q-btn.primary:hover { background: #f08a63; }
.q-btn:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

.q-bars { margin: 14px 0 2px; }
.q-bar-row { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; font-size: 14px; }
.q-bar-label { width: 64px; color: var(--muted); }
.q-bar-track { flex: 1; height: 14px; background: rgba(232, 228, 220, 0.07); border-radius: 2px; overflow: hidden; }
.q-bar-fill { display: block; height: 100%; width: 0; border-radius: 2px; background: #5a6472; transition: width 0.7s cubic-bezier(0.22, 1, 0.36, 1); }
.q-bar-row.real .q-bar-fill { background: var(--accent); }
.q-bar-row.ref .q-bar-fill { background: #8db3d0; }
.q-bar-val { width: 56px; text-align: right; color: var(--text); font-variant-numeric: tabular-nums; }
.q-bar-row.real .q-bar-val { color: #fff; font-weight: 700; }

.q-verdict { font-weight: 800; font-size: 20px; margin: 18px 0 6px; }
.q-verdict.ok { color: #9fc2a8; }
.q-verdict.no { color: var(--accent); }
.q-explain { font-size: 17px; line-height: 1.5; color: var(--text); }
.q-source { font-size: 12px; line-height: 1.5; color: var(--muted); margin: 10px 0 18px; }
.q-source a { color: var(--text); text-decoration: underline; text-decoration-color: rgba(232, 228, 220, 0.35); text-underline-offset: 2px; }
.q-source a:hover, .q-source a:focus-visible { color: #fff; text-decoration-color: var(--accent); }

.q-score { font-size: 20px; color: var(--text); margin: 14px 0 4px; }
.q-score strong { font-weight: 900; font-size: 72px; line-height: 1; color: #fff; margin-right: 8px; }
.q-final { font-size: 18px; color: var(--text); margin-bottom: 22px; }
.q-actions { display: flex; flex-wrap: wrap; gap: 12px; }
.q-sharemsg { font-size: 13px; color: var(--muted); margin-top: 12px; min-height: 18px; word-break: break-word; }

@media (max-width: 640px) {
  #quiz { padding: 20vh 16px 12vh; }
  .quiz-intro { font-size: 16px; }
  .quiz-box { padding: 20px 18px; }
  .q-opt { font-size: 16px; padding: 13px 14px; }
  .q-readout { font-size: 46px; }
  .q-explain { font-size: 16px; }
  .q-score strong { font-size: 60px; }
  /* the closing card also carries the entry button now, and has to fit a phone screen whole */
  .closing-card .quiz-cta { margin-top: 12px; }
  .quiz-link { font-size: 14px; padding: 9px 18px; }
}

/* phones: the picture stops above a dark ground strip that carries the source line, so nothing is printed over the city */
@media (max-width: 640px) {
  #inversion .valley, #inversion .inv-canvas { height: calc(100% - 54px); }
  #inversion::before { content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 54px; background: #07090e; }
  #inversion .inv-src { left: 16px; right: 16px; bottom: 9px; max-width: none; text-align: left; font-size: 10.5px; line-height: 1.4; z-index: 2; }
}
