/* =============================================================================
   Laurel.WX
   Palette carried from laurelnetwork.com so this reads as part of the network.
   --accent is UI CHROME ONLY. The radar ramp is separate, because on a weather
   screen green already means light rain and letting it mean two things is a
   usability bug, not a style preference.
   ========================================================================== */
:root{
  --bg:#08080b;
  --panel:#0d0d14;
  --panel-2:#10101a;
  --line:rgba(255,255,255,.09);
  --line-2:rgba(255,255,255,.14);
  --text:#f4f4f7;
  --text-2:#c9c9d4;
  --muted:#9a9aa8;
  --dim:#66666f;
  --faint:#4a4a54;
  --accent:#43e08a;
  --accent-ink:#06200f;
  --warn:#f0a742;
  --alert:#ff6b5d;
  --cool:#39b6c8;
  --rain:#2b6fd4;
  --sans:Archivo,"Helvetica Neue",Helvetica,system-ui,sans-serif;
  --mono:"IBM Plex Mono",ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  --nav-h:60px;
  /* The bottom nav is --nav-h PLUS the home-indicator inset. Anything that
     reserves space for it must reserve both, or the last 34px of the page
     hides behind it on a notched phone. --nav-total is that full height. */
  --safe-b:env(safe-area-inset-bottom, 0px);
  --nav-total:calc(var(--nav-h) + var(--safe-b));
}

*{box-sizing:border-box}
html,body{height:100%}
body{
  margin:0;background:var(--bg);color:var(--text);
  font-family:var(--sans);font-size:15px;line-height:1.5;
  -webkit-font-smoothing:antialiased;
  overscroll-behavior-y:none;
}
.num{font-family:var(--mono);font-variant-numeric:tabular-nums}
button{font:inherit;color:inherit}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:3px}

#app{display:flex;flex-direction:column;min-height:100%}

/* ---------- top bar (desktop) ---------- */
.topbar{
  display:flex;align-items:center;gap:22px;height:54px;padding:0 20px;
  border-bottom:1px solid var(--line);background:#0a0a10;flex-shrink:0;
}
.brand{font-size:16px;font-weight:700;letter-spacing:-.01em}
.brand-accent{color:var(--accent)}
.tabs{display:none;gap:2px}
.tab{padding:7px 13px;font-size:13px;color:var(--muted);background:none;border:0;border-radius:3px;cursor:pointer}
.tab:hover{color:var(--text-2)}
.tab.is-on{color:var(--text);background:rgba(255,255,255,.07)}
.place{
  margin-left:auto;display:flex;align-items:center;gap:8px;padding:6px 12px;
  background:rgba(255,255,255,.05);border:1px solid var(--line);border-radius:3px;
  color:var(--muted);font-size:12.5px;cursor:pointer;
}
.place:hover{color:var(--text-2);border-color:var(--line-2)}

/* ---------- views ---------- */
main{flex-grow:1;min-height:0;position:relative}
.view{display:none;padding:14px 16px calc(var(--nav-total) + 20px) 16px;max-width:1180px;margin:0 auto}
.view.is-on{display:block}
#view-radar.is-on{display:block;padding:0;max-width:none}

/* ---------- bottom nav (phone) ---------- */
.bottomnav{
  position:fixed;left:0;right:0;bottom:0;display:flex;
  border-top:1px solid var(--line);background:#0c0c11;
  padding-bottom:env(safe-area-inset-bottom);z-index:40;
}
.bnav{
  flex:1;display:flex;flex-direction:column;align-items:center;gap:4px;
  padding:9px 0 10px 0;background:none;border:0;color:var(--dim);cursor:pointer;
  min-height:44px;
}
.bnav svg{width:19px;height:19px}
.bnav span{font-size:9.5px;letter-spacing:.04em}
.bnav.is-on{color:var(--accent)}

/* ---------- cards ---------- */
.card{border:1px solid var(--line);border-radius:5px;background:var(--panel);padding:16px 18px}
.card + .card{margin-top:14px}
.card-h{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}
.card-t{font-size:11px;font-weight:600;color:var(--muted);letter-spacing:.09em}

/* ---------- current conditions ---------- */
.now-top{display:flex;align-items:flex-start;justify-content:space-between;gap:16px}
.place-h{font-size:20px;font-weight:600;letter-spacing:-.01em}
.place-sub{font-size:10.5px;color:var(--dim);letter-spacing:.04em;margin-top:2px}
.temp-row{display:flex;align-items:baseline;gap:6px;margin-top:14px}
.temp-big{font-size:clamp(60px,17vw,80px);font-weight:500;line-height:.9;letter-spacing:-.04em}
.temp-unit{font-size:24px;color:var(--muted)}
.cond{font-size:14px;color:var(--text-2);margin-top:6px}
.hilo{display:flex;flex-direction:column;align-items:flex-end;gap:7px;padding-top:4px}
.hilo-row{display:flex;align-items:baseline;gap:6px}
.hilo-k{font-size:10px;color:var(--dim);letter-spacing:.06em}
.src{font-size:10.5px;color:var(--dim);line-height:1.6;margin-top:14px;letter-spacing:.02em}

.grid4{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:1px;background:var(--line);border:1px solid var(--line);border-radius:4px;overflow:hidden;margin-top:14px}
.cell{background:var(--panel-2);padding:11px 6px;display:flex;flex-direction:column;gap:5px;align-items:center}
.cell-k{font-size:9.5px;color:var(--dim);letter-spacing:.06em}
.cell-v{font-size:15px}

/* ---------- alert strip ---------- */
.alert{display:flex;align-items:center;gap:10px;padding:11px 13px;border-radius:4px;
  border:1px solid rgba(240,167,66,.30);background:rgba(240,167,66,.10);
  color:#f0c98a;font-size:12.5px;text-align:left;width:100%;cursor:pointer;margin-bottom:14px}
.alert svg{flex-shrink:0}
.alert.sev-severe,.alert.sev-extreme{border-color:rgba(255,107,93,.38);background:rgba(255,107,93,.11);color:#ffb3aa}
.alert-body{flex-grow:1}

/* ---------- WNC panel ---------- */
.wnc{border:1px solid rgba(67,224,138,.22);border-radius:5px;background:rgba(67,224,138,.05);padding:14px 16px;margin-top:14px}
.wnc-h{display:flex;align-items:center;gap:9px;margin-bottom:11px}
.wnc-t{font-size:11px;font-weight:600;color:var(--accent);letter-spacing:.08em}
.tag{font-size:8.5px;font-weight:700;color:var(--accent-ink);background:var(--accent);padding:2px 5px;border-radius:2px;letter-spacing:.05em}
.wnc-row{display:flex;align-items:center;gap:9px;padding:5px 0}
.dot{width:7px;height:7px;border-radius:50%;background:#3a3a44;flex-shrink:0}
.dot.on{background:var(--accent)}
.wnc-lab{flex-grow:1;font-size:12.5px;color:#8a8a96}
.wnc-lab.on{color:#dfe8e2}
.wnc-val{font-size:11px;color:#5a5a64}
.wnc-val.on{color:#7a8a80}
.wnc-note{font-size:10.5px;line-height:1.5;color:#6f7f76;border-top:1px solid rgba(67,224,138,.16);padding-top:10px;margin-top:8px}

/* ---------- charts ---------- */
.chart{width:100%;height:auto;display:block}
.legend{display:flex;gap:16px;flex-wrap:wrap;margin-bottom:10px}
.lg{display:flex;align-items:center;gap:6px;font-size:10.5px;color:var(--muted)}
.lg-line{width:14px;height:2px;border-radius:1px}
.lg-box{width:9px;height:9px;border-radius:1px}

/* ---------- 10 day ---------- */
.day{display:flex;align-items:center;gap:10px;padding:11px 0;border-bottom:1px solid rgba(255,255,255,.07)}
.day:last-child{border-bottom:0}
.day-n{width:46px;font-size:12.5px}
.day-bar{flex-grow:1;height:4px;background:rgba(255,255,255,.07);border-radius:2px;position:relative}
.day-fill{position:absolute;height:4px;border-radius:2px;background:linear-gradient(90deg,var(--cool),var(--warn))}
.day-lo{font-size:11.5px;color:var(--muted);width:30px;text-align:right}
.day-hi{font-size:11.5px;width:30px;text-align:right}
.day-pop{font-size:10px;color:#5f8fd6;width:30px;text-align:right}

/* ---------- stations ---------- */
.st{display:flex;align-items:center;gap:10px;padding:10px 0;border-bottom:1px solid rgba(255,255,255,.07)}
.st-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
.st-id{font-size:12px;width:76px}
.st-name{flex-grow:1;font-size:11.5px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.st-v{font-size:11.5px;color:var(--text-2)}
.q-good{background:var(--accent)}
.q-fair{background:#c9a227}
.q-poor{background:#6a4a52}

/* ---------- radar ---------- */
.radar-wrap{position:relative;width:100%;height:calc(100dvh - 54px - var(--nav-total))}
#map{position:absolute;inset:0}
.rd-top{position:absolute;top:10px;left:10px;right:10px;display:flex;gap:8px;z-index:10;pointer-events:none}
.rd-top > *{pointer-events:auto}
.glass{background:rgba(8,10,14,.88);border:1px solid var(--line-2);border-radius:4px;backdrop-filter:blur(8px)}
.rd-btn{padding:8px 11px;font-size:12px;cursor:pointer;color:var(--text-2)}
.rd-btn:hover{color:var(--text)}
.rd-bottom{position:absolute;left:10px;right:10px;bottom:10px;z-index:10;padding:11px 12px;display:flex;flex-direction:column;gap:10px}
.prod-row{display:flex;gap:5px}
.prod{flex:1;padding:8px 0;font-size:11px;font-weight:600;background:rgba(255,255,255,.05);border:1px solid var(--line-2);border-radius:3px;color:var(--text-2);cursor:pointer;min-height:34px}
.prod.is-on{background:var(--accent);border-color:var(--accent);color:var(--accent-ink);font-weight:700}
.tilt-row{display:flex;align-items:center;gap:8px}
.tilt-lab{font-size:9.5px;color:var(--dim);letter-spacing:.07em;flex-shrink:0}
.tilts{flex-grow:1;display:flex;gap:4px;overflow-x:auto}
.tilt{flex:1;min-width:38px;padding:6px 0;font-size:10px;background:rgba(255,255,255,.05);border:1px solid var(--line);border-radius:3px;color:var(--muted);cursor:pointer}
.tilt.is-on{background:rgba(67,224,138,.16);border-color:rgba(67,224,138,.45);color:var(--accent)}
.scale{height:7px;border-radius:2px;background:linear-gradient(90deg,#123b6b 0%,#2f7fd0 16%,#39b6c8 30%,#4fbf68 45%,#e8e04a 62%,#f0a33a 76%,#e8443c 88%,#c23fb0 100%)}
.scale-ax{display:flex;justify-content:space-between;font-size:8.5px;color:#5a5a64;margin-top:4px}
.transport{display:flex;align-items:center;gap:11px}
.play{width:38px;height:38px;flex-shrink:0;display:flex;align-items:center;justify-content:center;background:var(--accent);border:0;border-radius:50%;cursor:pointer}
.scrub{flex-grow:1;-webkit-appearance:none;appearance:none;height:4px;background:rgba(255,255,255,.14);border-radius:2px;cursor:pointer}
.scrub::-webkit-slider-thumb{-webkit-appearance:none;width:13px;height:13px;border-radius:50%;background:var(--text);cursor:pointer}
.scrub::-moz-range-thumb{width:13px;height:13px;border:0;border-radius:50%;background:var(--text);cursor:pointer}
.tstamp{font-size:9.5px;color:var(--dim);display:flex;justify-content:space-between}
.readout{position:absolute;top:60px;left:10px;width:190px;padding:11px 12px;z-index:10;display:none}
.readout.is-on{display:block}
.ro-v{font-size:23px;font-weight:600;color:var(--warn)}
.ro-row{display:flex;justify-content:space-between;font-size:10.5px;margin-top:5px}
.ro-k{color:var(--dim)}
.ro-note{font-size:10px;color:#8a7448;line-height:1.45;margin-top:8px;padding-top:8px;border-top:1px solid var(--line)}
.live{display:flex;align-items:center;gap:7px;font-size:9.5px;color:#7a8a80}
.live-dot{width:6px;height:6px;border-radius:50%;background:var(--accent)}

/* ---------- dialog ---------- */
.dlg{border:1px solid var(--line-2);border-radius:6px;background:var(--panel);color:var(--text);padding:0;max-width:340px;width:calc(100% - 32px)}
.dlg::backdrop{background:rgba(0,0,0,.6)}
.dlg-inner{padding:18px}
.dlg h2{margin:0 0 14px 0;font-size:16px}
.place-opt{display:flex;align-items:center;gap:10px;width:100%;padding:11px 12px;background:rgba(67,224,138,.08);border:1px solid rgba(67,224,138,.28);border-radius:4px;color:var(--accent);font-size:13px;cursor:pointer;min-height:44px}
.place-list{margin-top:12px;display:flex;flex-direction:column}
.place-item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;padding:11px 2px;background:none;border:0;border-top:1px solid var(--line);color:var(--text);font-size:13px;text-align:left;cursor:pointer;min-height:44px}
.place-item small{color:var(--dim);font-size:10px}
.dlg-close{margin-top:14px;width:100%;padding:10px;background:rgba(255,255,255,.05);border:1px solid var(--line);border-radius:4px;cursor:pointer;min-height:44px}

.muted{color:var(--muted)}
.err{padding:14px;border:1px solid rgba(255,107,93,.3);background:rgba(255,107,93,.08);border-radius:4px;color:#ffb3aa;font-size:13px}
.skel{color:var(--dim);font-size:13px;padding:8px 0}

/* ---------- desktop ---------- */
@media (min-width:860px){
  .tabs{display:flex}
  .bottomnav{display:none}
  :root{--nav-h:0px}
  .view{padding:20px 20px 40px 20px}
  .cols{display:grid;grid-template-columns:5fr 7fr;gap:16px;align-items:start}
  .cols-3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px;align-items:start;margin-top:14px}
  .cols-3 .card{margin-top:0}
  .radar-wrap{height:calc(100dvh - 54px)}
  :root{--safe-b:0px}
  .rd-bottom{left:auto;right:10px;width:420px}
  .readout{top:60px}
}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}

/* =============================================================================
   Ambient background, ported from laurelnetwork.com.
   z-index is negative so it sits behind everything without needing a stacking
   context on the app itself; body must stay transparent for it to show.
   ========================================================================== */
#ambient{
  position:fixed;inset:-12%;z-index:-3;
  filter:blur(46px) saturate(1.4) brightness(.9);
  transform:scale(1.15);pointer-events:none;
  background:
    radial-gradient(58% 58% at 26% 28%, rgba(29,185,84,.20), transparent 70%),
    radial-gradient(52% 52% at 78% 64%, rgba(42,108,255,.18), transparent 70%),
    radial-gradient(55% 55% at 60% 16%, rgba(166,75,255,.15), transparent 70%);
}
#fx{position:fixed;inset:0;z-index:-2;pointer-events:none;opacity:.55;transition:opacity 1.2s ease}
#vignette{
  position:fixed;inset:0;z-index:-1;pointer-events:none;
  background:
    radial-gradient(ellipse at center, transparent 42%, rgba(0,0,0,.22) 100%),
    linear-gradient(180deg, rgba(8,8,11,.04), rgba(8,8,11,.36));
}
/* Panels sit ON the wash, so they are translucent rather than solid - the same
   glassy treatment the rest of the network uses. */
html{background:var(--bg)}
/* body stays transparent so the fixed #ambient / #fx / #vignette layers behind
   it show through. <html> carries the ground instead: if neither paints, the
   browser canvas falls back to white, which shows as a white band whenever the
   page is overscrolled on a phone. */
body{background:transparent}
/* 0.62 let the ambient wash through hard enough that the dim greys - source
   lines, elevation, axis labels - lost their contrast against it. The glass
   reads the same at 0.86 and the small text stays legible. */
.card{background:rgba(15,15,22,.86);backdrop-filter:blur(14px)}
.wnc{background:rgba(20,32,26,.84);backdrop-filter:blur(14px)}
.topbar{background:rgba(10,10,16,.88);backdrop-filter:blur(14px)}
.bottomnav{background:rgba(11,11,16,.92);backdrop-filter:blur(16px)}
.cell{background:rgba(20,20,30,.82)}
/* The radar map is opaque on purpose: the wash must not tint weather data. */
#view-radar{background:#05070a}

.view-sw{display:flex;gap:2px;padding:3px}
.vsw{padding:6px 10px;font-size:11px;background:none;border:0;border-radius:3px;color:var(--muted);cursor:pointer;min-height:32px}
.vsw:hover{color:var(--text-2)}
.vsw.is-on{background:rgba(67,224,138,.16);color:var(--accent)}

/* ---------- 10 day calendar strip ----------
   A horizontal scroller with snap points. Ten day-cards will never fit
   legibly as rows on a phone, and a grid of ten squares makes each one too
   small to carry both the condition and the numbers. Scrolling keeps every
   card full size and makes "how far out am I looking" a physical gesture. */
.cal{
  display:flex;gap:8px;overflow-x:auto;scroll-snap-type:x mandatory;
  padding:2px 2px 12px 2px;margin:0 -2px;
  scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.18) transparent;
  -webkit-overflow-scrolling:touch;
}
.cal::-webkit-scrollbar{height:6px}
.cal::-webkit-scrollbar-thumb{background:rgba(255,255,255,.16);border-radius:3px}
.cal::-webkit-scrollbar-track{background:transparent}

.calc{
  flex:0 0 92px;scroll-snap-align:start;
  display:flex;flex-direction:column;align-items:center;gap:7px;
  padding:11px 8px 9px 8px;
  background:rgba(255,255,255,.035);border:1px solid var(--line);border-radius:5px;
  cursor:pointer;text-align:center;
  transition:background .14s ease,border-color .14s ease;
}
.calc:hover{background:rgba(255,255,255,.07);border-color:var(--line-2)}
.calc.is-on{background:rgba(67,224,138,.10);border-color:rgba(67,224,138,.42)}

.calc-h{display:flex;flex-direction:column;gap:1px;line-height:1.15}
.calc-d{font-size:10.5px;font-weight:600;letter-spacing:.07em;color:var(--text-2)}
.calc.is-on .calc-d{color:var(--accent)}
.calc-dt{font-size:9.5px;color:var(--dim);letter-spacing:.03em}

.calc-c{font-size:10px;color:var(--muted);line-height:1.25;min-height:25px;
  display:flex;align-items:center;text-align:center}

.calc-t{display:flex;align-items:baseline;gap:6px}
.calc-hi{font-size:19px;line-height:1}
.calc-lo{font-size:12.5px;color:var(--muted)}

/* Shared temperature scale across all ten cards, so bar position and length
   are comparable card to card rather than per-card decoration. */
.calc-bar{width:100%;height:3px;background:rgba(255,255,255,.07);border-radius:2px;position:relative}
.calc-fill{position:absolute;height:3px;border-radius:2px;
  background:linear-gradient(90deg,var(--cool),var(--warn))}

.calc-p{display:flex;flex-direction:column;gap:1px;font-size:10.5px;color:var(--dim);line-height:1.25}
.calc-p.is-wet{color:#5f8fd6}
.calc-amt{font-size:9.5px;color:var(--faint)}
.calc-p.is-wet .calc-amt{color:#4a6f9e}

/* Confidence rail: day 9 must not look as authoritative as today. */
.qbar{width:100%;height:2px;background:rgba(255,255,255,.06);border-radius:1px;margin-top:1px}
.qbar-f{height:2px;border-radius:1px}
.qbar-f.q-high{background:var(--accent)}
.qbar-f.q-medium{background:#8a9a5b}
.qbar-f.q-low{background:#5a5a64}

/* ---------- selected-day detail ---------- */
.cal-detail{border-top:1px solid var(--line);padding-top:13px;margin-top:2px}
.cd-top{display:flex;align-items:flex-start;justify-content:space-between;gap:14px}
.cd-day{font-size:15.5px;font-weight:600;letter-spacing:-.005em}
.cd-cond{font-size:12.5px;color:var(--text-2);margin-top:2px}
.cd-icon{flex-shrink:0;margin-top:1px}
.cd-say{font-size:13px;line-height:1.55;color:var(--text-2);margin:11px 0 0 0;max-width:62ch}
.cd-grid{margin-top:13px}
.cd-wind{font-size:10px;color:var(--dim);letter-spacing:.05em;margin-top:10px}
.cd-conf{display:flex;align-items:center;gap:7px;font-size:10.5px;margin-top:9px;color:var(--dim)}
.cd-dot{width:6px;height:6px;border-radius:50%;background:currentColor;flex-shrink:0}
.cd-conf.q-high{color:var(--accent)}
.cd-conf.q-medium{color:#a8b872}
.cd-conf.q-low{color:var(--muted)}

@media (min-width:720px){
  .calc{flex:0 0 100px}
  .cd-say{font-size:13.5px}
}

/* ---------- the written forecast ----------
   Always below the figures it describes, always labelled. The numbers are the
   product; this is a reading of them, and nothing about the styling should
   invite anyone to mistake which is which - so it takes the quieter surface
   and the accent appears only on the badge. */
.nar{margin-top:14px}
.nar-badge{
  font-size:8.5px;font-weight:700;letter-spacing:.07em;
  color:var(--accent);border:1px solid rgba(67,224,138,.35);
  padding:2px 6px;border-radius:2px;
}
.nar.is-stale{border-color:rgba(240,167,66,.32)}
.nar.is-stale .nar-badge{color:var(--warn);border-color:rgba(240,167,66,.4)}

.nar-head{font-size:16px;font-weight:600;line-height:1.35;letter-spacing:-.01em;margin-bottom:12px}
.nar-sec + .nar-sec{margin-top:13px}
.nar-k{font-size:9.5px;font-weight:600;color:var(--dim);letter-spacing:.08em;margin-bottom:4px}
.nar-p{font-size:13.5px;line-height:1.6;color:var(--text-2);margin:0;max-width:64ch}

.nar-watch{
  display:flex;flex-direction:column;gap:4px;padding:10px 12px;margin-bottom:12px;
  border:1px solid rgba(240,167,66,.30);background:rgba(240,167,66,.09);
  border-radius:4px;font-size:12.5px;line-height:1.5;color:#f0c98a;
}
.nar-watch-k{font-size:9px;font-weight:700;letter-spacing:.09em;color:var(--warn)}

.nar-day{display:flex;gap:11px;padding:6px 0;border-bottom:1px solid rgba(255,255,255,.055)}
.nar-day:last-child{border-bottom:0}
.nar-day-n{flex:0 0 34px;font-size:11px;color:var(--muted);padding-top:1px;letter-spacing:.03em}
.nar-day-t{flex:1;font-size:12.5px;line-height:1.5;color:var(--text-2)}

.nar-off{font-size:12.5px;color:var(--dim)}

/* =============================================================================
   Phones
   The layout above is already mobile-first - this section fixes what only
   shows up on a real handset: thumbs, notches, landscape, and the fact that a
   360px-wide screen is the narrowest thing this has to survive.
   ========================================================================== */

/* No page-level overflow guard here on purpose. `overflow-x:hidden` on html or
   body turns it into a scroll container, and with the existing height:100% that
   clips the page instead of protecting it. Wide content scrolls inside its own
   container (.cal, .tilts); verified at 360/375/393/852 px that nothing else
   crosses the viewport edge. */

/* iOS zooms the page when a control's text is under 16px and it gets focus.
   The only real input here is the radar scrubber, which has no text, but the
   rule costs nothing and prevents a surprise later. */
input,select,textarea{font-size:16px}

@media (max-width:859px){
  /* Touch targets. The WCAG floor is 44px; anything that sits under a thumb
     on a moving map needs it more than most. */
  .vsw{min-height:44px;padding:11px 12px}
  .tilt{min-height:44px;padding:12px 0;font-size:11px}
  .prod{min-height:44px}
  .rd-btn{min-height:44px;padding:11px 13px}
  /* The transport button is the one control people jab at while the map is
     moving under their thumb; 38px was measurably under the floor. */
  .play{width:44px;height:44px}

  /* The scrubber's visible track stays 4px, but a 4px-tall hit area on a
     touch screen is unusable. The input grows to 28px of transparent padding
     with the track drawn by the pseudo-elements instead of the box itself. */
  .scrub{height:28px;background:transparent;border-radius:0}
  .scrub::-webkit-slider-runnable-track{height:4px;border-radius:2px;background:rgba(255,255,255,.14)}
  .scrub::-moz-range-track{height:4px;border-radius:2px;background:rgba(255,255,255,.14)}
  .scrub::-webkit-slider-thumb{margin-top:-5px;width:15px;height:15px}
  .scrub::-moz-range-thumb{width:15px;height:15px}
  .tab,.bnav{min-height:44px}
  /* Measured at 91x33 in the audit - the location button is the most-tapped
     control in the top bar and was the only one under the 44px floor. */
  .place{min-height:44px;padding:10px 12px}

  /* The radar control bar is a stack of five rows. On a phone it was eating
     close to half the map, so the scale legend - the one row that is
     reference rather than control - loses its axis labels and slims down. */
  .rd-bottom{padding:10px 11px;gap:8px}
  .scale{height:6px}
  .scale-ax{font-size:8px;margin-top:3px}

  /* The readout panel is a tap result, and at 190px on a 360px screen it
     covered most of the storm the reader had just tapped. */
  .readout{width:calc(100% - 20px);max-width:230px}

  /* Cards lose a little inner padding so the numbers keep their size. */
  .card{padding:14px 15px}
  .view{padding-left:14px;padding-right:14px}
}

/* ---- narrow phones (360px and under) ---- */
@media (max-width:400px){
  /* Four stat columns at 360px leaves ~78px each, and "PRESSURE" over a
     five-character value is the first thing to break. Two rows of two keeps
     both the label and the number at full size. */
  .grid4{grid-template-columns:repeat(2,minmax(0,1fr))}

  /* The site button plus three view names does not fit on one line once
     "Transylvania" is one of them. Let the row wrap and give the switcher its
     own full-width line rather than shrinking the labels to nothing. */
  .rd-top{flex-wrap:wrap}
  .view-sw{width:100%;display:flex}
  .vsw{flex:1;padding:9px 4px;font-size:10.5px}
  /* The readout must clear the now-taller control row. */
  .readout{top:108px}

  .calc{flex:0 0 84px;padding:10px 6px 8px 6px}
  .calc-hi{font-size:18px}
  .temp-big{font-size:clamp(54px,16vw,72px)}
}

/* ---- landscape phones ----
   A 375px-tall viewport minus a 54px bar minus the nav leaves about 260px of
   map, and the radar controls alone were taller than that. In a short
   viewport the controls become a compact bar: the scale and the timestamp
   line go, since both are reference rather than control, and what remains is
   what a thumb actually needs. */
@media (max-height:520px) and (orientation:landscape){
  .radar-wrap{height:calc(100dvh - 54px - var(--nav-total))}
  .rd-bottom{left:auto;right:8px;bottom:8px;width:300px;padding:9px 10px;gap:7px}
  .rd-bottom .scale,.rd-bottom .scale-ax,.tstamp{display:none}
  /* The status line wraps to two lines in the narrow landscape panel and
     pushes it taller than the map can spare. */
  .live{font-size:8.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .tilt-row{gap:6px}
  .readout{top:56px;width:180px;padding:9px 10px}
  .ro-v{font-size:19px}
  /* Views that scroll need the room back too. */
  .view{padding-top:10px}
}

/* ---- coarse pointers ----
   Hover styling on a touch screen sticks after a tap, leaving a button
   looking selected when it is not. Only apply it where a pointer can hover. */
@media (hover:none){
  .calc:hover{background:rgba(255,255,255,.035);border-color:var(--line)}
  .tab:hover,.rd-btn:hover,.vsw:hover,.place:hover{color:inherit}
  .calc.is-on:hover{background:rgba(67,224,138,.10);border-color:rgba(67,224,138,.42)}
}

/* The calendar strip is the one place a phone user is expected to drag
   sideways, so it gets momentum scrolling and a scrollbar that does not
   occupy layout height on mobile. */
@media (max-width:859px){
  .cal{padding-bottom:8px}
  .cal::-webkit-scrollbar{height:0}
  .cal{scrollbar-width:none}
}

/* ---------- MapLibre chrome ----------
   The default controls ship light-on-white, which on this UI reads as a hole
   punched in the map. They are restyled to match the .glass panels rather than
   left as someone else's design sitting on top of ours. */
.maplibregl-ctrl-group{
  background:rgba(8,10,14,.88)!important;
  border:1px solid var(--line-2)!important;
  border-radius:4px!important;
  box-shadow:none!important;
  backdrop-filter:blur(8px);
}
.maplibregl-ctrl-group button{
  width:32px!important;height:32px!important;
  background:transparent!important;
  border-bottom:1px solid var(--line)!important;
}
.maplibregl-ctrl-group button:last-child{border-bottom:0!important}
.maplibregl-ctrl-group button:hover{background:rgba(255,255,255,.07)!important}
/* The glyphs are background images tinted for a light control. */
.maplibregl-ctrl-icon{filter:invert(1) brightness(.85)}
.maplibregl-ctrl-attrib{display:none}

@media (max-width:859px){
  /* Hidden on touch. Pinch-zoom is the natural gesture, the buttons are a
     desktop affordance, and at 393px the view switcher wraps to a second row
     and lands directly on top of them. */
  .maplibregl-ctrl-top-right{display:none}
}

/* The tilt row scrolls horizontally and gave no sign of it - the last
   elevation simply ran off the edge looking clipped. A fade at the right edge
   says "there is more" without adding a control. */
.tilts{
  -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 22px),transparent);
  mask-image:linear-gradient(90deg,#000 calc(100% - 22px),transparent);
}
.tilts::-webkit-scrollbar{height:0}
.tilts{scrollbar-width:none}
