/* RetroForecast web — the early-90s cable weather visual system.
   Palette and chrome mirror the iOS app's RetroTheme.swift exactly. */

/* FONT DROP-IN: like the iOS app, the full WeatherStar-era look comes from a
   Star4000-style font you have rights to. Drop it in assets/fonts/ as
   Star4000.woff2 and it takes over automatically; VT323 (OFL, bundled) is the
   licensing-clean default. */
@font-face {
  font-family: 'Star4000';
  src: url('../assets/fonts/Star4000.woff2') format('woff2');
  font-display: swap;
}
@font-face {
  font-family: 'VT323';
  src: url('../assets/fonts/VT323.woff2') format('woff2');
  font-display: swap;
}

:root {
  --blue-top: #121C78;
  --blue-bottom: #030538;
  --panel-top: #1A298C;
  --panel-bottom: #080D4D;
  --border-light: #8C9EF2;
  --border-dark: #050826;
  --yellow: #FFD11A;
  --cyan: #73E6FF;
  --white: #FFFFFF;
  --header-orange: #FF780D;
  --header-magenta: #940D73;
  --alert-red: #F23029;
  --moon-pale: #F2F2BF;

  /* Retro chrome scale, the web port of RetroScale. JS ramps it 1.0 -> 2.0
     against a 1280x720 reference raster, measured on the *picture* rather
     than the window (see updateScale in main.js); phones stay at 1.0. */
  --k: 1;

  /* Widest a line of slide content gets. Now that the picture runs to 16:9,
     an uncapped stat row parks its label and its value a foot apart; this
     keeps label/value pairs readable while the panel still spans the frame. */
  --measure: calc(960px * var(--k));

  --font-display: 'Star4000', 'VT323', 'Courier New', monospace;
  /* Reading font. The pixel face is a broadcast typeface — it belongs on the
     slides, not on paragraphs someone has to actually read. Settings prose and
     the privacy/support documents use this instead. */
  --font-ui: ui-sans-serif, -apple-system, BlinkMacSystemFont, 'Segoe UI',
             Roboto, Helvetica, Arial, sans-serif;
  /* Fixed-px drop shadows: em-based ones double-print at display sizes. */
  --shadow-hard: 3px 3px 0 rgba(0, 0, 0, 0.8);
  --shadow-soft: 2px 2px 0 rgba(0, 0, 0, 0.7);
  --panel-radius: 10px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html, body { height: 100%; }

body {
  background: #000;
  font-family: var(--font-display);
  color: var(--white);
  overflow: hidden;
  -webkit-font-smoothing: none;
  text-rendering: optimizeSpeed;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}

/* The picture fills the viewport height always, and the viewport width up to
   16:9. Past that — ultrawides, maximized windows on very wide panels — it
   pillarboxes and centers rather than stretching the broadcast into a strip.
   Phones, tablets, and ordinary laptops (all <= 16:9) therefore fill edge to
   edge; only genuinely wider-than-broadcast canvases get side bars, and those
   read as a TV in a dark room, not as an unfinished column.

   The retro 4:3 feel is carried by the chrome scale (--k in main.js, which
   ramps with the picture size) rather than by starving the frame. */
#app {
  position: relative;
  width: min(100vw, calc(100dvh * 16 / 9));
  height: 100dvh;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  background: linear-gradient(to bottom, var(--blue-top), var(--blue-bottom));
  box-shadow: 0 0 calc(70px * var(--k)) rgba(60, 92, 220, 0.22);
  overflow: hidden;
}

/* ---------- Header: the sunburst bar ---------- */

#retro-header {
  display: flex;
  align-items: center;
  gap: calc(14px * var(--k));
  padding: calc(10px * var(--k)) calc(16px * var(--k));
  padding-top: max(calc(10px * var(--k)), env(safe-area-inset-top));
  background: linear-gradient(to right, var(--header-orange), var(--header-magenta));
  border-bottom: 2px solid var(--border-dark);
  flex: none;
}

.logo-block {
  display: flex;
  flex-direction: column;
  align-items: center;
  line-height: 0.95;
  padding: calc(6px * var(--k)) calc(10px * var(--k));
  background: linear-gradient(to bottom, var(--panel-top), var(--panel-bottom));
  border: 2px solid var(--yellow);
  border-radius: calc(6px * var(--k));
  box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.6);
  flex: none;
}
.logo-retro { font-size: calc(18px * var(--k)); color: var(--yellow); }
.logo-forecast { font-size: calc(14px * var(--k)); color: var(--white); }

.title-block {
  flex: 1 1 auto;
  min-width: 0;
  text-shadow: var(--shadow-hard);
}
#slide-title {
  font-size: calc(26px * var(--k));
  color: var(--white);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.05;
}
#location-name {
  font-size: calc(19px * var(--k));
  color: var(--yellow);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.clock-block {
  flex: none;
  text-align: right;
  text-shadow: var(--shadow-hard);
}
#clock-time {
  font-size: calc(24px * var(--k));
  color: var(--white);
  font-variant-numeric: tabular-nums;
  line-height: 1.05;
}
#clock-date { font-size: calc(17px * var(--k)); color: var(--yellow); }
#paused-chip[hidden] { display: none; }
#paused-chip {
  display: inline-block;
  font-size: calc(14px * var(--k));
  color: var(--blue-bottom);
  background: var(--yellow);
  border-radius: 4px;
  padding: 0 8px;
  text-shadow: none;
}

/* ---------- Stage & slides ---------- */

#stage {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  cursor: pointer;
}

.slide-layer {
  position: absolute;
  inset: 0;
  padding: 16px;
  opacity: 0;
  transition: opacity 0.5s ease-in-out;
  pointer-events: none;
}
.slide-layer.visible { opacity: 1; pointer-events: auto; }

/* The bordered blue panel every slide is built from (RetroPanel). */
.retro-panel {
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: calc(16px * var(--k));
  background: linear-gradient(to bottom, var(--panel-top), var(--panel-bottom));
  border: 2px solid var(--border-light);
  border-radius: var(--panel-radius);
  box-shadow: inset 0 0 0 2px rgba(5, 8, 38, 0.6);
  overflow: hidden;
}

.retro-divider {
  height: 2px;
  background: var(--border-light);
  opacity: 0.6;
  flex: none;
}

/* ---------- Vertical rhythm ----------

   Every slide is a column of *bands* inside the panel. A band sizes to its
   content, takes a weighted share of whatever height is left over, and
   centers its own content inside that share. Leftover height therefore turns
   into even breathing room between bands instead of pooling into one dead
   zone under the last row — which is what a fixed-height stack does once the
   picture is 900px+ tall.

   Repeating bands (forecast days, observation rows) grow to fill but stop at
   a max-height, so six rows on a 1440px-tall display read as a table with
   generous spacing rather than six lines marooned an inch apart. */

.band { min-height: 0; display: flex; flex-direction: column; justify-content: center; }

.cc-panel > *, .obs-table, .haz-wrap {
  width: 100%;
  max-width: var(--measure);
  margin-left: auto;
  margin-right: auto;
}

/* ---------- Current conditions ---------- */

.cc-panel { gap: calc(8px * var(--k)); }

.cc-headline {
  flex: 6 1 auto;
  min-height: 0;
  display: flex;
  gap: calc(20px * var(--k));
  align-items: center;
}
.cc-main {
  flex: 1 1 50%;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: calc(10px * var(--k));
}
.cc-main .retro-icon { filter: drop-shadow(3px 3px 0 rgba(0,0,0,0.6)); }
.cc-temp {
  font-size: calc(96px * var(--k));
  line-height: 0.9;
  color: var(--white);
  text-shadow: var(--shadow-hard);
}
.cc-cond {
  font-size: calc(30px * var(--k));
  color: var(--yellow);
  text-align: center;
  text-shadow: var(--shadow-hard);
  line-height: 1.05;
}
.cc-stats {
  flex: 1 1 50%;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: calc(10px * var(--k));
  justify-content: center;
}

.stat-row {
  display: flex;
  align-items: baseline;
  gap: 12px;
  font-size: calc(21px * var(--k));
  text-shadow: var(--shadow-soft);
  white-space: nowrap;
}
.stat-row .label { color: var(--yellow); }
.stat-row .value { color: var(--white); margin-left: auto; }
.stat-row .value.cyan { color: var(--cyan); }

.hourly-strip { flex: 3 1 auto; text-align: center; }
.cc-today { flex: 1.4 1 auto; }
.hourly-title {
  font-size: calc(21px * var(--k));
  color: var(--yellow);
  text-shadow: var(--shadow-hard);
  margin-bottom: calc(10px * var(--k));
}
.hourly-cells { display: flex; }
.hour-cell {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(7px * var(--k));
  text-shadow: var(--shadow-soft);
}
.hour-cell .hour { font-size: calc(16px * var(--k)); color: var(--cyan); }
.hour-cell .temp { font-size: calc(23px * var(--k)); color: var(--white); }

.today-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  max-width: calc(560px * var(--k));
  margin: 0 auto;
  width: 100%;
  text-shadow: var(--shadow-soft);
  white-space: nowrap;
}
.today-row .pair { display: flex; align-items: baseline; gap: calc(8px * var(--k)); }
.today-row .tag { font-size: calc(16px * var(--k)); color: var(--cyan); }
.today-row .tag.hi { color: var(--yellow); }
.today-row .head { font-size: calc(21px * var(--k)); color: var(--yellow); }
.today-row .val { font-size: calc(21px * var(--k)); color: var(--white); }

/* Steady-pressure arrow: rotate the up arrow, since the pixel font has no
   right arrow glyph. */
.arrow-steady { display: inline-block; transform: rotate(90deg); }

/* ---------- Latest observations table ---------- */

.obs-table {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: calc(8px * var(--k));
  height: 100%;
}
.obs-head, .obs-row {
  display: grid;
  grid-template-columns: 1fr calc(70px * var(--k)) calc(120px * var(--k)) calc(105px * var(--k));
  gap: 8px;
  align-items: center;
}
.obs-head {
  font-size: calc(18px * var(--k));
  color: var(--cyan);
}
.obs-head > :not(:first-child), .obs-row > :not(:first-child) { text-align: right; }
.obs-row {
  flex: 1 1 auto;
  /* Grow into the free height, but stop before rows drift so far apart that
     the table stops reading as one block. */
  max-height: calc(58px * var(--k));
  font-size: calc(24px * var(--k));
  text-shadow: var(--shadow-soft);
  min-height: 0;
}
.obs-row .city {
  color: var(--yellow);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.obs-row .val { color: var(--white); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

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

.regional-wrap { position: relative; height: 100%; border-radius: calc(var(--panel-radius) - 2px); overflow: hidden; }
.regional-canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.map-labels { position: absolute; inset: 0; pointer-events: none; }

/* City pins and leader lines. Crisp screen-resolution SVG rather than canvas:
   the map buffer is 260px tall and upscales ~3.5x, which turns a modest pin
   into a chunky block that hides more radar than the label did. */
.map-pins {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}
.map-pins .pin-halo { fill: var(--border-dark); }
.map-pins .pin-core { fill: var(--white); }
.map-pins .pin-core.center { fill: var(--yellow); }
.map-pins .leader-casing { stroke: var(--border-dark); }
.map-pins .leader { stroke: var(--border-light); }
.map-pins .leader.center { stroke: var(--yellow); }

/* No filled box. A boxed tag blanks out a whole rectangle of the radar it is
   annotating; a chyron-style hard outline occludes only the glyph ink, which
   is roughly a fifth of the pixels and is also what broadcast graphics
   actually did over video. The exact city position is marked by a pin drawn
   on the canvas, so the text is free to move off the weather — see the
   placement scoring in slides/regional.js. */
.map-label {
  --outline: calc(1.6px * var(--k));
  position: absolute;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 0 calc(2px * var(--k));
  white-space: nowrap;
  text-shadow:
    var(--outline) 0 0 var(--border-dark),
    calc(var(--outline) * -1) 0 0 var(--border-dark),
    0 var(--outline) 0 var(--border-dark),
    0 calc(var(--outline) * -1) 0 var(--border-dark),
    var(--outline) var(--outline) 0 var(--border-dark),
    calc(var(--outline) * -1) var(--outline) 0 var(--border-dark),
    var(--outline) calc(var(--outline) * -1) 0 var(--border-dark),
    calc(var(--outline) * -1) calc(var(--outline) * -1) 0 var(--border-dark);
}
.map-label .top { display: flex; align-items: center; gap: calc(4px * var(--k)); }
/* SVG ignores text-shadow, so the icon gets the same outline via drop-shadow
   or it would vanish into a bright echo. */
.map-label .retro-icon {
  filter:
    drop-shadow(1px 0 0 #050826) drop-shadow(-1px 0 0 #050826)
    drop-shadow(0 1px 0 #050826) drop-shadow(0 -1px 0 #050826);
}
.map-label .temp { font-size: calc(23px * var(--k)); color: var(--white); line-height: 1.15; }
.map-label.center .temp { color: var(--yellow); }
/* Cyan rather than yellow: yellow is a band in the radar ladder and would
   camouflage against moderate returns. Cyan appears nowhere in it. */
.map-label .name { font-size: calc(14px * var(--k)); color: var(--cyan); line-height: 1.15; }
.map-label.center .name { color: var(--yellow); }

/* Radar legend + timestamp: hidden until frames actually arrive, so a map
   with no radar coverage stays exactly as it was. */
.radar-chrome {
  position: absolute;
  inset: auto calc(6px * var(--k)) calc(5px * var(--k));
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: calc(10px * var(--k));
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.4s ease-in;
}
.radar-chrome.on { opacity: 1; }

.map-legend, .map-credit {
  display: flex;
  align-items: center;
  gap: calc(6px * var(--k));
  padding: calc(2px * var(--k)) calc(7px * var(--k));
  background: rgba(3, 5, 56, 0.8);
  border: 1px solid rgba(140, 158, 242, 0.6);
  border-radius: 4px;
  box-shadow: 1.5px 1.5px 0 rgba(0, 0, 0, 0.6);
}
.map-legend .cap { font-size: calc(11px * var(--k)); color: var(--cyan); }
.map-legend .ramp { display: flex; }
.map-legend i { width: calc(13px * var(--k)); height: calc(8px * var(--k)); }
.map-credit { align-items: baseline; }
.map-credit .stamp { font-size: calc(15px * var(--k)); color: var(--yellow); }
.map-credit .src { font-size: calc(11px * var(--k)); color: rgba(255, 255, 255, 0.65); }

/* ---------- Local forecast ---------- */

.local-wrap {
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: calc(14px * var(--k));
  padding: calc(8px * var(--k));
}
.local-seg {
  flex: 1 1 auto;
  min-height: 0;
  max-height: calc(150px * var(--k));
  display: flex;
  flex-direction: column;
  justify-content: center;
  text-shadow: var(--shadow-soft);
}
.local-seg .head {
  font-size: calc(26px * var(--k));
  color: var(--yellow);
  margin-bottom: calc(6px * var(--k));
}
.local-seg .body {
  font-size: calc(23px * var(--k));
  color: var(--white);
  line-height: 1.3;
}

/* ---------- Extended forecast ---------- */

.ext-wrap { display: flex; height: 100%; gap: calc(12px * var(--k)); align-items: center; }
.ext-wrap.rows { flex-direction: column; align-items: stretch; justify-content: center; }

.ext-card {
  flex: 1 1 0;
  min-width: 0;
  min-height: 0;
  /* Four columns across a 16:9 picture would otherwise be skyscrapers with
     the day, icon, and temps floating an inch apart. Cap the card shape and
     center the stack of cards instead. */
  aspect-ratio: 3 / 4;
  max-height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-evenly;
  gap: calc(10px * var(--k));
  padding: calc(10px * var(--k));
  background: rgba(3, 5, 56, 0.5);
  border: 1.5px solid rgba(140, 158, 242, 0.7);
  border-radius: 8px;
  box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.5);
  text-align: center;
}
.ext-card .day { font-size: calc(30px * var(--k)); color: var(--yellow); text-shadow: var(--shadow-soft); }
.ext-card .cond {
  font-size: calc(19px * var(--k));
  color: var(--white);
  text-shadow: var(--shadow-soft);
}
.ext-card .temps { width: 100%; max-width: calc(190px * var(--k)); }
.ext-card .temps .pair { display: flex; justify-content: space-between; align-items: baseline; }
.ext-card .tag { font-size: calc(17px * var(--k)); color: var(--cyan); }
.ext-card .tag.hi { color: var(--yellow); }
.ext-card .val { font-size: calc(30px * var(--k)); color: var(--white); text-shadow: var(--shadow-soft); }

/* Row layout (portrait): one full-width row per day. */
.ext-row {
  flex: 1 1 auto;
  min-height: 0;
  max-height: calc(122px * var(--k));
  display: flex;
  align-items: center;
  gap: calc(14px * var(--k));
  padding: calc(10px * var(--k)) calc(14px * var(--k));
  background: rgba(3, 5, 56, 0.5);
  border: 1.5px solid rgba(140, 158, 242, 0.7);
  border-radius: 8px;
  box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.5);
}
.ext-row .left { flex: none; width: calc(86px * var(--k)); display: flex; flex-direction: column; align-items: center; gap: calc(5px * var(--k)); }
.ext-row .day { font-size: calc(25px * var(--k)); color: var(--yellow); text-shadow: var(--shadow-soft); }
.ext-row .cond { flex: 1 1 auto; min-width: 0; font-size: calc(17px * var(--k)); color: var(--white); text-shadow: var(--shadow-soft); }
.ext-row .temps { flex: none; text-align: right; }
.ext-row .temps .pair { display: flex; justify-content: flex-end; align-items: baseline; gap: calc(8px * var(--k)); }
.ext-row .tag { font-size: calc(16px * var(--k)); color: var(--cyan); }
.ext-row .tag.hi { color: var(--yellow); }
.ext-row .val { font-size: calc(25px * var(--k)); color: var(--white); text-shadow: var(--shadow-soft); }

/* ---------- Hazards ---------- */

.haz-wrap { display: flex; flex-direction: column; height: 100%; }
.haz-lead {
  flex: 1.6 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: calc(8px * var(--k));
}
.haz-sevrow { display: flex; align-items: center; gap: calc(10px * var(--k)); }
.haz-chip {
  font-size: calc(18px * var(--k));
  color: var(--border-dark);
  padding: calc(2px * var(--k)) calc(10px * var(--k));
}
.haz-timing { font-size: calc(17px * var(--k)); color: var(--cyan); }
.haz-headline {
  font-size: calc(38px * var(--k));
  color: var(--white);
  line-height: 1.05;
  text-shadow: var(--shadow-hard);
}
.haz-detail {
  font-size: calc(22px * var(--k));
  color: var(--yellow);
  text-shadow: var(--shadow-soft);
}
.haz-source { display: flex; gap: calc(8px * var(--k)); align-items: baseline; }
.haz-source .origin { font-size: calc(14px * var(--k)); color: rgba(255, 255, 255, 0.75); }
.haz-source a { font-size: calc(14px * var(--k)); color: var(--cyan); }

.haz-row {
  flex: 1 1 auto;
  min-height: 0;
  max-height: calc(78px * var(--k));
  display: flex;
  align-items: center;
  gap: calc(10px * var(--k));
  padding: calc(8px * var(--k)) 0;
  text-shadow: var(--shadow-soft);
}
.haz-row .sevbar { flex: none; width: calc(5px * var(--k)); align-self: stretch; }
.haz-row .mid { flex: 1 1 auto; min-width: 0; }
.haz-row .mid .h { display: block; font-size: calc(19px * var(--k)); color: var(--white); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.haz-row .mid .d { display: block; font-size: calc(14px * var(--k)); color: rgba(255, 255, 255, 0.75); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.haz-row .when { flex: none; font-size: calc(14px * var(--k)); color: var(--cyan); }

.sim-badge {
  align-self: flex-start;
  font-size: calc(13px * var(--k));
  color: var(--border-dark);
  background: var(--cyan);
  padding: 1px 6px;
  margin-bottom: calc(8px * var(--k));
}

/* ---------- Stand by / signal lost ---------- */

.signal-wrap {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: calc(18px * var(--k));
  text-align: center;
}
.signal-head { font-size: calc(40px * var(--k)); color: var(--yellow); text-shadow: var(--shadow-hard); }
.signal-detail { font-size: calc(20px * var(--k)); color: var(--white); line-height: 1.4; }

/* Sign-on byline under the welcome card. Uppercased here rather than in the
   copy, so links.js can hold the publisher name in readable proper case for
   the settings fine print. */
.signal-byline {
  text-transform: uppercase;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: calc(8px * var(--k));
  margin-top: calc(6px * var(--k));
  font-size: calc(15px * var(--k));
  color: rgba(255, 255, 255, 0.7);
}
.signal-byline a { color: var(--cyan); text-decoration: none; }
.signal-byline a:hover { text-decoration: underline; }
.signal-byline .sep { color: rgba(255, 255, 255, 0.35); }
.blink { animation: blink 1.6s step-end infinite; }
@keyframes blink { 50% { opacity: 0.25; } }

/* ---------- Bottom bar: chips, ticker, attribution ---------- */

#retro-bottom {
  flex: none;
  display: flex;
  align-items: center;
  height: calc(44px * var(--k));
  padding-bottom: env(safe-area-inset-bottom);
  background: linear-gradient(to bottom, var(--panel-top), var(--blue-bottom));
  border-top: 2px solid var(--border-light);
}

.chip-row { display: flex; gap: calc(6px * var(--k)); padding: 0 calc(8px * var(--k)); }
.retro-chip {
  width: calc(30px * var(--k));
  height: calc(26px * var(--k));
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(to bottom, var(--panel-top), var(--panel-bottom));
  border: 1.5px solid rgba(140, 158, 242, 0.5);
  border-radius: 5px;
  box-shadow: 1.5px 1.5px 0 rgba(0, 0, 0, 0.5);
  color: rgba(255, 255, 255, 0.35);
  cursor: pointer;
}
.retro-chip.on { color: var(--yellow); border-color: var(--yellow); }
.retro-chip.pulse { animation: chip-pulse 1.2s ease-in-out infinite; }
@keyframes chip-pulse { 50% { box-shadow: 0 0 8px 2px rgba(255, 209, 26, 0.7); } }

.bar-divider { width: 1.5px; height: calc(24px * var(--k)); background: rgba(140, 158, 242, 0.5); flex: none; }

#ticker {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  height: 100%;
  display: flex;
  align-items: center;
}
#ticker-inner {
  display: flex;
  flex: none;              /* never let the bar squeeze the tiled strip */
  gap: 80px;               /* ticker.js owns this: it must match the measured cycle */
  white-space: nowrap;
  will-change: transform;
  font-size: calc(21px * var(--k));
  color: var(--white);
  text-shadow: var(--shadow-soft);
}

#attribution {
  flex: none;
  padding: 0 calc(10px * var(--k));
  font-size: calc(14px * var(--k));
  color: var(--cyan);
  text-decoration: none;
}
#attribution:hover { text-decoration: underline; }

/* ---------- CRT overlays ---------- */

#scanlines {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: repeating-linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.18) 0px,
    rgba(0, 0, 0, 0.18) 1px,
    transparent 1px,
    transparent 3px
  );
  mix-blend-mode: multiply;
  z-index: 40;
}
#scanlines.off { display: none; }

#vignette {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(ellipse at center, transparent 60%, rgba(0, 0, 0, 0.35) 100%);
  z-index: 41;
}

/* ---------- Retro icons ---------- */

.retro-icon { display: inline-block; image-rendering: pixelated; flex: none; }
.retro-icon svg { display: block; width: 100%; height: 100%; shape-rendering: crispEdges; }

/* ---------- Settings overlay ---------- */

#settings-overlay {
  position: absolute;
  inset: 0;
  z-index: 50;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}
#settings-overlay[hidden] { display: none; }

/* Settings is the one screen a viewer READS rather than watches, and it was
   also the only part of the UI whose type never scaled with --k — 13px fine
   print next to 30px broadcast graphics on a 1440p display. Everything here
   scales with the picture, sits at higher contrast, and renders antialiased
   instead of with the CRT's deliberately crunchy rasterization. */
#settings-panel {
  width: min(calc(560px * var(--k)), 100%);
  max-height: 92%;
  overflow-y: auto;
  background: linear-gradient(to bottom, var(--panel-top), var(--panel-bottom));
  border: 2px solid var(--border-light);
  border-radius: var(--panel-radius);
  box-shadow: inset 0 0 0 2px rgba(5, 8, 38, 0.6), 4px 4px 0 rgba(0, 0, 0, 0.5);
  padding: calc(20px * var(--k));
  cursor: default;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

.settings-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: calc(12px * var(--k));
  font-size: calc(24px * var(--k));
  color: var(--yellow);
  text-shadow: var(--shadow-soft);
  margin-bottom: calc(16px * var(--k));
}

.settings-section { margin-bottom: calc(20px * var(--k)); }
.settings-label {
  font-size: calc(18px * var(--k));
  color: var(--cyan);
  margin-bottom: calc(9px * var(--k));
  letter-spacing: 0.05em;
}
.settings-row { display: flex; gap: calc(10px * var(--k)); flex-wrap: wrap; align-items: center; }
.seg-row .seg.on { background: var(--yellow); color: var(--blue-bottom); border-color: var(--yellow); }

.retro-btn {
  font-family: var(--font-display);
  font-size: calc(19px * var(--k));
  color: var(--white);
  background: rgba(3, 5, 56, 0.6);
  border: 1.5px solid var(--border-light);
  border-radius: 5px;
  padding: calc(7px * var(--k)) calc(13px * var(--k));
  cursor: pointer;
  box-shadow: 1.5px 1.5px 0 rgba(0, 0, 0, 0.5);
}
.retro-btn:hover { border-color: var(--yellow); }

#loc-search {
  flex: 1 1 200px;
  font-family: var(--font-display);
  font-size: calc(20px * var(--k));
  color: var(--white);
  background: rgba(3, 5, 56, 0.8);
  border: 1.5px solid var(--border-light);
  border-radius: 5px;
  padding: calc(7px * var(--k)) calc(11px * var(--k));
  outline: none;
}
#loc-search:focus { border-color: var(--yellow); }

.loc-results { display: flex; flex-direction: column; gap: calc(4px * var(--k)); margin-top: calc(9px * var(--k)); }
.loc-results button {
  font-family: var(--font-display);
  font-size: calc(19px * var(--k));
  text-align: left;
  color: var(--white);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 4px;
  padding: calc(6px * var(--k)) calc(9px * var(--k));
  cursor: pointer;
}
.loc-results button:hover { border-color: var(--yellow); color: var(--yellow); }

.slide-toggles { display: flex; flex-wrap: wrap; gap: calc(9px * var(--k)) calc(18px * var(--k)); margin-top: calc(11px * var(--k)); }
.toggle-row { display: flex; align-items: center; gap: calc(8px * var(--k)); font-size: calc(19px * var(--k)); cursor: pointer; }
.toggle-row input { accent-color: var(--yellow); width: calc(17px * var(--k)); height: calc(17px * var(--k)); }

.vol-row { display: flex; align-items: center; gap: calc(10px * var(--k)); font-size: calc(19px * var(--k)); flex: 1; }
.vol-row input { flex: 1; accent-color: var(--yellow); }

.now-playing { font-size: calc(17px * var(--k)); color: var(--cyan); margin-top: calc(9px * var(--k)); min-height: calc(20px * var(--k)); }

/* Fine print is the densest text in the product and the part people squint
   at, so it drops the pixel face for the reading font and sentence case. */
.fine-print { border-top: 1px solid rgba(140, 158, 242, 0.4); padding-top: calc(14px * var(--k)); }
.fine-print p {
  font-family: var(--font-ui);
  font-size: calc(13px * var(--k));
  color: rgba(255, 255, 255, 0.88);
  line-height: 1.65;
  margin-bottom: calc(10px * var(--k));
}
.fine-print a { color: var(--cyan); }
.fine-print .keys { font-family: var(--font-display); font-size: calc(17px * var(--k)); color: var(--cyan); }
.fine-print .credit {
  border-top: 1px solid rgba(140, 158, 242, 0.25);
  padding-top: calc(12px * var(--k));
  font-size: calc(13.5px * var(--k));
}
.fine-print .credit a { text-decoration: none; font-weight: 600; }
.fine-print .credit a:hover { text-decoration: underline; }
.doc-links { display: flex; flex-wrap: wrap; gap: calc(6px * var(--k)) calc(14px * var(--k)); }
#app-store-link[hidden] { display: none; }
#app-store-link { display: block; margin-top: calc(6px * var(--k)); color: var(--yellow); font-weight: 600; }

/* ---------- Documents (privacy, support) ----------

   These are real documents — an App Review reviewer and an actual customer
   have to read them end to end — so the retro treatment is the frame only:
   the sunburst header and panel chrome around body copy set in the reading
   font at a comfortable measure. The pixel face stays on headings. */

body.doc { overflow: auto; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; }
body.doc #app { height: auto; min-height: 100dvh; width: min(100vw, 1100px); box-shadow: none; }

.doc-main { flex: 1 1 auto; padding: clamp(16px, 3vw, 34px); }
.doc-body {
  max-width: 74ch;
  margin: 0 auto;
  padding: clamp(20px, 3vw, 38px);
  background: linear-gradient(to bottom, var(--panel-top), var(--panel-bottom));
  border: 2px solid var(--border-light);
  border-radius: var(--panel-radius);
  box-shadow: inset 0 0 0 2px rgba(5, 8, 38, 0.6);
  font-family: var(--font-ui);
  font-size: 16px;
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.9);
}
.doc-body h1 {
  font-family: var(--font-display);
  font-size: 40px;
  font-weight: 400;
  color: var(--yellow);
  text-shadow: var(--shadow-soft);
  line-height: 1.1;
  margin-bottom: 6px;
}
.doc-body h2 {
  font-family: var(--font-display);
  font-size: 27px;
  font-weight: 400;
  color: var(--cyan);
  margin: 34px 0 10px;
  line-height: 1.2;
}
.doc-body h3 {
  font-size: 16px;
  font-weight: 700;
  color: var(--white);
  margin: 22px 0 6px;
}
.doc-body p, .doc-body li { margin-bottom: 12px; }
.doc-body ul { padding-left: 22px; }
.doc-body li { padding-left: 4px; }
.doc-body li::marker { color: var(--yellow); }
.doc-body a { color: var(--cyan); }
.doc-body strong { color: var(--white); }
.doc-body code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.9em;
  background: rgba(3, 5, 56, 0.6);
  padding: 1px 5px;
  border-radius: 3px;
}
.doc-updated { font-size: 14px; color: rgba(255, 255, 255, 0.6); margin-bottom: 26px; }
.doc-lede {
  border-left: 3px solid var(--yellow);
  padding: 2px 0 2px 16px;
  margin: 22px 0 26px;
  color: var(--white);
}
.doc-callout {
  border: 1.5px solid rgba(140, 158, 242, 0.7);
  border-radius: 8px;
  background: rgba(3, 5, 56, 0.45);
  padding: 16px 18px;
  margin: 24px 0;
}
.doc-callout p:last-child, .doc-body p:last-child { margin-bottom: 0; }
.doc-contact {
  font-family: var(--font-display);
  font-size: 26px;
  color: var(--yellow);
  word-break: break-all;
}
.doc-contact a { color: var(--yellow); text-decoration: none; }
.doc-contact a:hover { text-decoration: underline; }
.doc-nav { display: flex; flex-wrap: wrap; gap: 10px 20px; margin-top: 34px; padding-top: 18px; border-top: 1px solid rgba(140, 158, 242, 0.4); font-size: 15px; }
.doc-back {
  font-family: var(--font-display);
  font-size: 19px;
  color: var(--white);
  background: rgba(3, 5, 56, 0.6);
  border: 1.5px solid var(--border-light);
  border-radius: 5px;
  padding: 5px 12px;
  text-decoration: none;
  white-space: nowrap;
}
.doc-back:hover { border-color: var(--yellow); color: var(--yellow); }

@media (max-width: 520px) {
  .doc-body { font-size: 15px; padding: 18px; }
  .doc-body h1 { font-size: 30px; }
  .doc-body h2 { font-size: 22px; }
  .doc-contact { font-size: 20px; }
}

/* ---------- Compact height (landscape phones) ---------- */

@media (max-height: 480px) {
  .hourly-strip, .cc-today { display: none; }
  .cc-temp { font-size: 60px; }
  .cc-cond { font-size: 22px; }
  .stat-row { font-size: 16px; }
  #slide-title { font-size: 20px; }
  #location-name { font-size: 15px; }
  #clock-time { font-size: 18px; }
  #clock-date { font-size: 13px; }
  .haz-headline { font-size: 26px; }
  .local-seg .head { font-size: 20px; }
  .local-seg .body { font-size: 17px; }
  .signal-head { font-size: 30px; }
}

/* ---------- Narrow phones ---------- */

@media (max-width: 520px) {
  .cc-headline { flex-direction: column; align-items: stretch; justify-content: center; gap: 8px; }
  .cc-temp { font-size: 64px; }
  .cc-cond { font-size: 24px; }
  .stat-row { font-size: 17px; }
  .hourly-cells .hour-cell:nth-child(n+6) { display: none; }
  .obs-head, .obs-row { grid-template-columns: 1fr 52px 92px 78px; }
  .obs-row { font-size: 17px; max-height: 46px; }
  .obs-head { font-size: 14px; }
  .local-seg { max-height: 118px; }
  #slide-title { font-size: 19px; }
  #location-name { font-size: 14px; }
  #clock-time { font-size: 18px; }
  #clock-date { font-size: 12px; }
  .logo-retro { font-size: 14px; }
  .logo-forecast { font-size: 11px; }
  .ext-card .day, .ext-row .day { font-size: 20px; }
  .haz-headline { font-size: 28px; }
}
