/* Inter, self-hosted — the same face Tiara's mobile dashboard uses, so the two
   read as one family. Local woff2, no CDN, so the page still needs nothing but
   its own origin. */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('fonts/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('fonts/jetbrains-mono-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

/* weather.kog.farm — public neighbour weather page.

   Built on the K.O.G. dashboard's actual visual system, not just its palette:
   glass panels floating over ambient radial lighting and film grain, each panel
   carrying an inset light edge on top, a dark edge beneath, and a specular
   sweep across its upper border.

   The two themes are the dashboard's two themes. Dark is the indoor/evening
   look. Light is the "outdoor" mode Justin built for reading an iPad in direct
   Hawaii sun: near-opaque surfaces, ambient lighting and grain switched off,
   deep saturated accents, and a global font-weight boost. That is exactly the
   condition most neighbours will read this page in, so it is the daytime
   default. */

:root {
  /* ── DARK (indoor / after sunset) ───────────────────────────────── */
  --bg-primary:    #1a2436;
  --bg-secondary:  #111827;
  --bg-tertiary:   #243047;
  --bg-elevated:   #2d3d56;

  --glass-surface: rgba(26, 36, 54, 0.85);
  --glass-border:  rgba(255, 255, 255, 0.12);
  --glass-bright:  rgba(255, 255, 255, 0.22);
  --glass-sweep:   rgba(255, 255, 255, 0.06);

  --ink:    #ffffff;
  --ink-2:  #e6ecf5;   /* was 85% white — solid renders crisper on glass */
  --ink-3:  #aebbcd;   /* was 55% white (5.8:1); solid lifts it to 7.6:1 */

  --accent:       #7df4ff;
  --accent-soft:  rgba(125, 244, 255, 0.14);
  --series-prior: #78889e;
  --warm:         #ffc987;
  --good:         #86efcd;
  --warn:         #ffc987;
  --crit:         #ffb3bc;

  --border-subtle: rgba(255, 255, 255, 0.06);
  --bg-subtle:     rgba(255, 255, 255, 0.03);

  /* Chart series + axis tokens. app.js reads these by literal name. */
  --prior:      #78889e;
  --line:       rgba(255, 255, 255, 0.22);
  --line-soft:  rgba(255, 255, 255, 0.09);
  --rule:       rgba(255, 255, 255, 0.20);

  --shadow-md:    0 4px 12px rgba(0,0,0,0.35), 0 1px 3px rgba(0,0,0,0.18);
  --shadow-inset: inset 0 1px 0 rgba(255,255,255,0.08), inset 0 -1px 0 rgba(0,0,0,0.15);

  --radius: 12px;
  --ts: 1;                       /* text scale, driven by the header control */
  --f-xs: calc(11px * var(--ts));
  --f-sm: calc(13px * var(--ts));
  --f-base: calc(14px * var(--ts));
  --f-md: calc(15px * var(--ts));
  --f-lg: calc(18px * var(--ts));
  --f-xl: calc(22px * var(--ts));
  --f-hero: calc(64px * var(--ts));
  --f-big: calc(40px * var(--ts));
  --f-stat: calc(27px * var(--ts));
  --sans: 'Inter', system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  --body-weight: 400;

  color-scheme: dark;
}

/* ── LIGHT (the dashboard's "outdoor" mode) ───────────────────────── */
:root[data-theme="light"] {
  --bg-primary:    #d5dce8;
  --bg-secondary:  #dfe5ee;
  --bg-tertiary:   #cad3e0;
  --bg-elevated:   #e8edf4;

  --glass-surface: rgba(220, 227, 237, 0.95);
  --glass-border:  rgba(0, 30, 70, 0.15);
  --glass-bright:  rgba(0, 30, 70, 0.28);
  --glass-sweep:   rgba(255, 255, 255, 0.75);

  --ink:    #050d1a;
  --ink-2:  #0f1d33;
  --ink-3:  #2c3e58;

  --accent:       #00616e;   /* 5.54:1 on panel — was #007a8a at 3.92:1 */
  --accent-soft:  rgba(0, 97, 110, 0.13);
  --series-prior: #5a6b84;
  --warm:         #a85800;
  --good:         #006d48;
  --warn:         #a85800;
  --crit:         #aa2830;

  --border-subtle: rgba(0, 30, 70, 0.08);
  --bg-subtle:     rgba(0, 30, 70, 0.04);

  --prior:      #5a6b84;
  --line:       rgba(0, 30, 70, 0.30);
  --line-soft:  rgba(0, 30, 70, 0.13);
  --rule:       rgba(0, 40, 85, 0.34);

  --shadow-md:    0 4px 12px rgba(0,0,0,0.10), 0 1px 3px rgba(0,0,0,0.08);
  --shadow-inset: inset 0 1px 0 rgba(255,255,255,0.70), inset 0 -1px 0 rgba(0,0,0,0.06);

  --body-weight: 500;          /* sunlight readability boost */
  color-scheme: light;
}

/* Three text sizes for readers who need them. Chosen over browser zoom because
   zoom also scales the charts and satellite image, which are already legible;
   this moves only type, and keeps the layout intact. */
:root[data-text="lg"] { --ts: 1.16; }
:root[data-text="xl"] { --ts: 1.34; }
:root[data-text="lg"] body, :root[data-text="xl"] body { line-height: 1.62; }
:root[data-text="xl"] .prose p { max-width: 58ch; }

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg-primary);
  color: var(--ink);
  font: var(--body-weight) var(--f-md)/1.55 var(--sans);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  transition: background .45s ease, color .45s ease;
}
:root[data-theme="light"] body { -webkit-font-smoothing: auto; }

/* Ambient radial lighting — the glass needs something to sit on. */
body::before {
  content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(ellipse 80% 50% at 15% 0%,   rgba(103, 232, 249, 0.035) 0%, transparent 60%),
    radial-gradient(ellipse 60% 40% at 85% 100%, rgba(110, 231, 183, 0.025) 0%, transparent 50%),
    radial-gradient(ellipse 70% 60% at 50% 50%,  rgba( 96, 165, 250, 0.015) 0%, transparent 70%);
  transition: opacity .45s ease;
}

/* Film grain, for tactile surface quality. */
body::after {
  content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  opacity: 0.015;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  transition: opacity .45s ease;
}

/* Outdoor mode kills both — glare beats atmosphere in direct sun. */
:root[data-theme="light"] body::before,
:root[data-theme="light"] body::after { opacity: 0; }

.wrap { max-width: 880px; margin: 0 auto; padding: 0 16px; position: relative; z-index: 1; }

.skip { position: absolute; left: -9999px; background: var(--bg-elevated); color: var(--ink); padding: 10px 14px; z-index: 30; }
.skip:focus { left: 12px; top: 12px; }

:where(a) { color: var(--accent); }
:where(button, select, a):focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }

/* ═══ the glass panel — the signature surface ═══════════════════════ */
.card {
  position: relative; overflow: hidden;
  background: var(--glass-surface);
  backdrop-filter: blur(24px) saturate(1.2);
  -webkit-backdrop-filter: blur(24px) saturate(1.2);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md), var(--shadow-inset);
  padding: 16px;
  margin-bottom: 14px;
}
/* specular sweep along the top edge */
.card::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 1px;
  background: linear-gradient(90deg, transparent 10%, var(--glass-sweep) 50%, transparent 90%);
  pointer-events: none;
}

/* accent variant for the forecast — mirrors the dashboard's rain panel */
.card.accent {
  background: linear-gradient(135deg, rgba(12,18,32,0.85) 0%, rgba(13,31,60,0.85) 100%);
  border: 2px solid rgba(125, 244, 255, 0.42);
}
:root[data-theme="light"] .card.accent {
  background: linear-gradient(135deg, rgba(226,234,242,0.96) 0%, rgba(203,225,231,0.96) 100%);
  border: 2px solid rgba(0, 122, 138, 0.5);
}

/* ═══ header ════════════════════════════════════════════════════════ */
.top {
  position: sticky; top: 0; z-index: 20;
  background: rgba(0, 0, 0, 0.72);
  backdrop-filter: blur(24px) saturate(1.2);
  -webkit-backdrop-filter: blur(24px) saturate(1.2);
  border-bottom: 1px solid rgba(0, 255, 242, 0.12);
  box-shadow: 0 1px 20px rgba(0, 255, 242, 0.05);
}
:root[data-theme="light"] .top {
  background: rgba(202, 211, 224, 0.97);
  border-bottom: 3px solid var(--accent);
  box-shadow: 0 1px 12px rgba(0,0,0,0.06);
}

.topbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding-top: 11px; padding-bottom: 9px; flex-wrap: nowrap; }
.brand { display: flex; align-items: center; gap: 10px; min-width: 0; overflow: hidden; }
.brand b { display: block; font-size: var(--f-md); font-weight: 700; letter-spacing: -0.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--ink); }
.brand small { display: block; font-size: var(--f-xs); color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mark {
  width: 46px; height: 46px; border-radius: 11px; flex: none;
  object-fit: cover; display: block;
  border: 1px solid var(--glass-border);
  box-shadow: var(--shadow-inset), 0 0 14px rgba(125,244,255,.10);
}
:root[data-theme="light"] .mark { box-shadow: var(--shadow-inset); }
.topright { display: flex; align-items: center; gap: 8px; flex: none; }

.fresh {
  display: inline-flex; align-items: center; gap: 6px; min-width: 0; overflow: hidden;
  font: 600 var(--f-xs)/1 var(--sans);
  padding: 7px 10px; border-radius: 999px;
  background: var(--bg-subtle); color: var(--ink-2);
  border: 1px solid var(--glass-border);
  box-shadow: var(--shadow-inset);
  white-space: nowrap;
}
.fresh #freshText { overflow: hidden; text-overflow: ellipsis; }
.fresh .dot { width: 7px; height: 7px; border-radius: 50%; flex: none; color: var(--good); background: currentColor; box-shadow: 0 0 7px currentColor; }
.fresh[data-state="stale"] { color: var(--warn); } .fresh[data-state="stale"] .dot { color: var(--warn); }
.fresh[data-state="dead"]  { color: var(--crit); } .fresh[data-state="dead"] .dot  { color: var(--crit); }
@media (max-width: 430px) { .fresh { max-width: 150px; } }

.ghost {
  background: var(--bg-subtle); color: var(--ink-2);
  border: 1px solid var(--glass-border); border-radius: 999px;
  box-shadow: var(--shadow-inset);
  width: 33px; height: 33px; font-size: 15px; cursor: pointer; line-height: 1;
}
.ghost:hover { color: var(--ink); border-color: var(--glass-bright); }

.tabs { display: flex; gap: 2px; overflow-x: auto; scrollbar-width: none; }
.tabs::-webkit-scrollbar { display: none; }
.tab {
  appearance: none; background: none; border: 0; cursor: pointer;
  padding: 9px 13px 11px; color: var(--ink-3);
  font: 600 var(--f-base)/1 var(--sans); white-space: nowrap;
  border-bottom: 2px solid transparent;
}
:root[data-theme="light"] .tab { color: #1a2a42; font-weight: 700; }
.tab:hover { color: var(--ink-2); }
.tab.is-on { color: var(--ink); border-bottom-color: var(--accent); }
:root[data-theme="light"] .tab.is-on { color: var(--accent); }

/* ═══ layout ════════════════════════════════════════════════════════ */
main { padding-top: 18px; padding-bottom: 40px; }
.view { display: flex; flex-direction: column; }
.view[hidden] { display: none; }   /* must beat the rule above */

/* Flex/grid children default to min-width:auto, so a 700px chart viewBox
   would otherwise drag the whole column wider than a phone. */
.view > *, .card, .chart, .chartcard, .grid, .cell, .prose,
.statband, .stat, .toplist, .tl, .tl > div, .stations, .st { min-width: 0; }

h2.sec {
  font-size: var(--f-sm); text-transform: uppercase; letter-spacing: .085em;
  color: var(--ink-3); margin: 20px 0 9px; font-weight: 700;
}
h2.sec2 { font-size: var(--f-md); margin: 0 0 10px; }

/* ═══ hero ══════════════════════════════════════════════════════════ */
.hero { display: flex; align-items: center; justify-content: space-between; gap: 18px; flex-wrap: wrap; }
.temp { font-size: var(--f-hero); line-height: .95; font-weight: 700; letter-spacing: -0.04em; font-variant-numeric: tabular-nums; }
.temp .deg { font-size: 24px; font-weight: 600; color: var(--ink-3); margin-left: 3px; vertical-align: super; }
.hero-sub { margin-top: 7px; color: var(--ink-3); font-size: var(--f-sm); display: flex; gap: 10px; flex-wrap: wrap; }
.sky { color: var(--ink-2); }
.hero-side { display: flex; gap: 24px; }
.hs b { display: block; font-size: var(--f-xl); font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: -0.015em; }
.hs small { display: block; font-size: var(--f-xs); color: var(--ink-3); margin-top: 1px; }

/* ═══ forecast ══════════════════════════════════════════════════════ */
.fc-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.fc-head h2 { font-size: var(--f-md); margin: 0; }
.meter-fill {
  height: 100%; width: 0; border-radius: 999px;
  background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 55%, transparent), var(--accent));
  box-shadow: 0 0 12px var(--accent-soft);
  transition: width .6s ease;
}
.fc-note { margin: 0; font-size: var(--f-sm); color: var(--ink-2); }
.microdis { margin: 11px 0 0; font-size: var(--f-xs); color: var(--ink-3); line-height: 1.5; }
.microdis a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }

/* ═══ condition grid ════════════════════════════════════════════════ */
.grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(112px, 1fr));
  gap: 0; background: var(--glass-surface);
  border: 1px solid var(--glass-border); border-radius: var(--radius);
  overflow: hidden; margin-bottom: 14px; box-shadow: var(--shadow-md);
}
.cell b { display: block; font-size: var(--f-lg); font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
.cell b i { font-style: normal; font-size: var(--f-sm); font-weight: 600; color: var(--ink-3); margin-left: 2px; }
.cell small { display: block; font-size: var(--f-xs); color: var(--ink-3); margin-top: 2px; }

/* ═══ stat band ═════════════════════════════════════════════════════ */
.statband { display: flex; gap: 16px; flex-wrap: wrap; }
.stat.ghost { border-top-color: var(--glass-border); }
.stat b { display: block; font-size: var(--f-stat); font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: -0.025em; }
.stat.ghost b { color: var(--ink-2); }
.stat small { display: block; font-size: var(--f-xs); color: var(--ink-3); margin-top: 3px; }

/* ═══ charts ════════════════════════════════════════════════════════ */
.chartcard { padding-bottom: 12px; }
.chart { width: 100%; overflow-x: auto; }
.chart svg { display: block; width: 100%; max-width: 100%; height: auto; }
.cap { margin: 9px 0 0; font-size: var(--f-xs); color: var(--ink-3); }
.legend { display: flex; gap: 15px; flex-wrap: wrap; font-size: var(--f-xs); color: var(--ink-2); margin-bottom: 9px; }
.legend i { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 5px; vertical-align: -1px; font-style: normal; }
.tickTxt { font-family: var(--sans); font-weight: 600; fill: var(--ink-2); }
.valTxt  { font-family: var(--sans); font-weight: 700; fill: var(--ink); }

/* ═══ records / lists ═══════════════════════════════════════════════ */
.recs { display: grid; grid-template-columns: repeat(auto-fit, minmax(158px, 1fr)); gap: 15px; }
.rec b { display: block; font-size: var(--f-xl); font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: -0.015em; }
.rec small { display: block; font-size: var(--f-xs); color: var(--ink-3); margin-top: 2px; }
.rec small em { font-style: normal; color: var(--ink-2); }

.toplist { display: flex; flex-direction: column; gap: 7px; }
.tl { display: grid; grid-template-columns: 92px 1fr auto; align-items: center; gap: 10px; font-size: var(--f-sm); }
.tl span { color: var(--ink-2); font-variant-numeric: tabular-nums; }
.tl .bar {
  height: 16px; border-radius: 0 5px 5px 0;
  background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 55%, transparent), var(--accent));
  box-shadow: var(--shadow-inset);
}
.tl b { font-variant-numeric: tabular-nums; text-align: right; }

/* ═══ history picker ════════════════════════════════════════════════ */
.pickrow { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 13px; font-size: var(--f-sm); color: var(--ink-2); }
select {
  font: var(--body-weight) var(--f-base) var(--sans); color: var(--ink);
  background: var(--bg-subtle); border: 1px solid var(--glass-border);
  border-radius: 9px; padding: 8px 11px; max-width: 62%;
  box-shadow: var(--shadow-inset);
}

/* ═══ storm ═════════════════════════════════════════════════════════ */
.storm { border-left: 3px solid var(--ink-3); }
.storm.lvl-MONITOR  { border-left-color: var(--accent); }
.storm.lvl-WATCH, .storm.lvl-WARNING { border-left-color: var(--warn); }
.storm.lvl-CRITICAL { border-left-color: var(--crit); box-shadow: var(--shadow-md), var(--shadow-inset), 0 0 26px rgba(255,120,130,.14); }
.storm h2 { margin: 0 0 3px; font-size: var(--f-lg); letter-spacing: -0.01em; }
.storm .lvl { font: 700 var(--f-xs)/1 var(--sans); letter-spacing: .09em; text-transform: uppercase; color: var(--ink-3); }
.storm.lvl-WARNING .lvl, .storm.lvl-CRITICAL .lvl { color: var(--crit); }
.storm p { margin: 9px 0 0; font-size: var(--f-sm); color: var(--ink-2); }
.stormgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(128px, 1fr)); gap: 13px; margin-top: 14px; }
.stormgrid b { display: block; font-size: var(--f-lg); font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1.25; }
.stormgrid small { display: block; font-size: var(--f-xs); color: var(--ink-3); margin-top: 2px; }
.quiet { text-align: center; padding: 30px 12px; color: var(--ink-3); }
.quiet b { display: block; font-size: var(--f-lg); color: var(--ink-2); margin-bottom: 5px; }

/* ═══ prose / about ═════════════════════════════════════════════════ */
.prose h2 { font-size: var(--f-lg); margin: 0 0 8px; letter-spacing: -0.012em; }
.prose h3 { font-size: var(--f-md); margin: 19px 0 6px; }
.prose p { margin: 9px 0 0; color: var(--ink-2); font-size: var(--f-base); max-width: 64ch; }
.prose p b { color: var(--ink); }
.aside { border-left: 3px solid var(--accent); padding-left: 13px; margin-top: 15px !important; }
.warn { color: var(--warn); }
.fine p { font-size: var(--f-sm); color: var(--ink-3); }
.factgrid div b { display: block; font-size: var(--f-lg); font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: -0.015em; }
.factgrid div small { display: block; font-size: var(--f-xs); color: var(--ink-3); margin-top: 2px; }

.subjects { display: flex; flex-direction: column; gap: 10px; margin-top: 13px; }
.subj { display: grid; grid-template-columns: 1fr auto; gap: 8px; align-items: baseline; font-size: var(--f-sm); }
.subj .track { grid-column: 1 / -1; height: 8px; border-radius: 999px; background: var(--bg-subtle); overflow: hidden; box-shadow: var(--shadow-inset); }
.subj .fill { height: 100%; border-radius: 999px; background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 50%, transparent), var(--accent)); }
.subj .fill.zero { width: 3px !important; background: var(--ink-3); }
.subj b { font-weight: 600; color: var(--ink); }
.subj span { color: var(--ink-3); font-variant-numeric: tabular-nums; }

/* ═══ station comparison ════════════════════════════════════════════ */
.vs { display: grid; grid-template-columns: 1fr auto 1fr; gap: 12px; align-items: center; margin: 17px 0 10px; }
.vs-side {
  background: var(--bg-subtle); border: 1px solid var(--glass-border);
  border-radius: var(--radius); padding: 14px; box-shadow: var(--shadow-inset);
}
.vs-side b { display: block; font-size: calc(29px * var(--ts)); font-weight: 700; letter-spacing: -0.025em; font-variant-numeric: tabular-nums; color: var(--accent); }
.vs-side small { display: block; font-size: var(--f-xs); color: var(--ink-2); margin-top: 5px; line-height: 1.45; }
.vs-side small em { font-style: normal; color: var(--ink-3); }
.vs-mid { font: 700 var(--f-xs) var(--sans); color: var(--ink-3); text-transform: uppercase; letter-spacing: .11em; }

.stations { display: flex; flex-direction: column; gap: 7px; margin-top: 13px; }
.st { display: grid; grid-template-columns: 1fr 168px 46px; gap: 9px; align-items: center; font-size: var(--f-sm); padding-bottom: 7px; border-bottom: 1px solid var(--border-subtle); }
.st:last-child { border-bottom: 0; }
.st .nm { color: var(--ink); font-weight: 600; }
.st .dz, .st .di { color: var(--ink-3); font-variant-numeric: tabular-nums; font-size: var(--f-xs); }
.st .sc { font-variant-numeric: tabular-nums; font-weight: 700; text-align: right; }
.st .sc.hi { color: var(--accent); }
.st .sc.lo { color: var(--ink-3); }
.st-head { font-size: var(--f-xs); color: var(--ink-3); text-transform: uppercase; letter-spacing: .07em; border-bottom: 1px solid var(--glass-border); padding-bottom: 6px; }

/* ═══ footer ════════════════════════════════════════════════════════ */
.foot { padding: 24px 16px 36px; color: var(--ink-3); font-size: var(--f-xs); border-top: 1px solid var(--border-subtle); margin-top: 12px; position: relative; z-index: 1; }
.foot p { margin: 0 0 3px; }

@media (max-width: 560px) {
  .temp { font-size: 54px; }
  .hero { gap: 14px; }
  .hero-side { gap: 20px; width: 100%; }
  .brand small { display: none; }
}
@media (max-width: 520px) {
  .vs { grid-template-columns: 1fr; text-align: center; }
  .st { grid-template-columns: 1fr 118px 42px; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
}

/* ═══ single-page flow ══════════════════════════════════════════════
   Every section is always rendered; the nav jumps rather than swaps.
   scroll-margin keeps a jumped-to heading clear of the sticky header. */
.view { scroll-margin-top: 84px; }
.view[hidden] { display: none; }

.tab { text-decoration: none; display: inline-block; }

/* Chapter rule between sections, so a long scroll still reads as chapters. */
.chapter {
  margin: 34px 0 16px; padding-top: 22px;
  border-top: 1px solid var(--glass-border);
  position: relative;
}

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* ═══════════════════════════════════════════════════════════════════
   DASHBOARD GRID — dense multi-column panel rows, the way the farm
   dashboard lays out. Panels carry their own header strip; content is
   compact tiles rather than paragraphs of air.
   ═══════════════════════════════════════════════════════════════════ */
.row { display: grid; gap: 12px; margin-bottom: 12px; align-items: start; }
.row-2 { grid-template-columns: minmax(0,1fr) minmax(0,1fr); }
.row-3 { grid-template-columns: minmax(0,1fr) minmax(0,1fr) minmax(0,1fr); }
.span2 { grid-column: span 2; }

.panel {
  position: relative; overflow: hidden; min-width: 0;
  background: var(--glass-surface);
  backdrop-filter: blur(24px) saturate(1.2);
  -webkit-backdrop-filter: blur(24px) saturate(1.2);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md), var(--shadow-inset);
}
.panel::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 1px; z-index: 2;
  background: linear-gradient(90deg, transparent 10%, var(--glass-sweep) 50%, transparent 90%);
  pointer-events: none;
}
.phead {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 9px 13px; border-bottom: 1px solid var(--glass-border);
  background: var(--bg-subtle); min-height: 38px;
}
.phead h2 {
  margin: 0; font-size: var(--f-sm); font-weight: 700;
  text-transform: uppercase; letter-spacing: .075em; color: var(--ink-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ptag {
  font: 600 var(--f-xs)/1 var(--sans); color: var(--accent);
  background: var(--accent-soft); border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  padding: 4px 8px; border-radius: 999px; white-space: nowrap; font-variant-numeric: tabular-nums;
}
.pbody { padding: 13px; }
.pb-flush { padding: 0; }

/* full-width standalone panels keep the row rhythm */
main > .panel { margin-bottom: 12px; }

/* section titles between big groups */
.secttl {
  margin: 40px 0 16px; padding-top: 22px; position: relative;
  border-top: 2px solid var(--rule);
}
.secttl:first-of-type { margin-top: 6px; }
/* accent tick riding the rule, so a section start is unmistakable when scanning */
.secttl::before {
  content: ""; position: absolute; top: -2px; left: 0; width: 78px; height: 4px;
  background: var(--accent); border-radius: 3px;
  box-shadow: 0 0 14px var(--accent-soft);
}
.secttl h2 {
  margin: 0; font-size: calc(23px * var(--ts)); font-weight: 700;
  letter-spacing: -0.022em; color: var(--ink);
}
.secttl p {
  margin: 5px 0 0; font-size: var(--f-sm); color: var(--ink-3); max-width: 62ch;
}
@media (max-width: 640px) { .secttl { margin-top: 32px; } }

/* ── compact tile grid (the dashboard's 4-up pattern) ─────────────── */
.tiles {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(84px, 1fr));
  gap: 1px; background: var(--glass-surface);
  border-radius: 9px; overflow: hidden;
  margin-top: 12px;
}
.tiles.t2 { grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); }
.tile {
  background: var(--glass-surface); padding: 8px 9px; text-align: center;
  box-shadow: 0 0 0 1px var(--glass-border);
}
.tile b {
  display: block; font-size: var(--f-md); font-weight: 700; color: var(--accent);
  font-variant-numeric: tabular-nums; letter-spacing: -0.01em; line-height: 1.2;
}
.tile b i { font-style: normal; font-size: 10px; font-weight: 600; color: var(--ink-3); margin-left: 1px; }
.tile small {
  display: block; font-size: 10px; color: var(--ink-3); margin-top: 2px;
  text-transform: uppercase; letter-spacing: .03em; line-height: 1.25;
}

/* ── hero inside a panel ──────────────────────────────────────────── */
.hero { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.hero-side { display: flex; gap: 20px; }

/* ── satellite ────────────────────────────────────────────────────── */
.satwrap { margin: 0; position: relative; }
.satwrap img { display: block; width: 100%; height: auto; background: var(--bg-secondary); }
.satwrap .cap { margin: 0; padding: 9px 13px; border-top: 1px solid var(--glass-border); }
.segs { display: flex; gap: 3px; }
.seg {
  appearance: none; cursor: pointer; white-space: nowrap;
  font: 600 var(--f-xs)/1 var(--sans); padding: 5px 9px; border-radius: 7px;
  background: transparent; color: var(--ink-3); border: 1px solid transparent;
}
.seg:hover { color: var(--ink-2); }
.seg.on { background: var(--accent-soft); color: var(--accent); border-color: color-mix(in srgb, var(--accent) 30%, transparent); }

/* ── lightning callout ────────────────────────────────────────────── */
.lgt { margin-top: 12px; padding: 11px 12px; border-radius: 9px;
  background: var(--bg-subtle); border: 1px solid var(--glass-border); box-shadow: var(--shadow-inset); }

/* ── year-to-date block ───────────────────────────────────────────── */
.ytd b { display: block; font-size: var(--f-big); font-weight: 700; letter-spacing: -0.035em; font-variant-numeric: tabular-nums; line-height: 1; }
.ytd small { display: block; font-size: var(--f-xs); color: var(--ink-3); margin-top: 5px; }
.cmp { margin-top: 13px; display: flex; flex-direction: column; gap: 8px; }

/* ── storms as panels ─────────────────────────────────────────────── */
.storm { border-left: 3px solid var(--ink-3); }
.storm .pbody { padding-top: 11px; }

@media (max-width: 900px) {
  .row-3 { grid-template-columns: minmax(0,1fr) minmax(0,1fr); }
  .span2 { grid-column: span 2; }
}
@media (max-width: 640px) {
  .row-2, .row-3 { grid-template-columns: minmax(0,1fr); }
  .span2 { grid-column: span 1; }
  .hero-side { width: 100%; gap: 16px; }
}

/* storm approach chart sits flush under its tiles */

/* ═══ satellite, full width with zoom/pan ═══════════════════════════ */
.sat { margin-bottom: 12px; }
.satctl { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.loopbtn { border: 1px solid var(--glass-border); }
.loopbtn.on { background: var(--accent-soft); color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 35%, transparent); }

.satview {
  position: relative; overflow: hidden; background: var(--bg-secondary);
  aspect-ratio: 16 / 9; cursor: grab; touch-action: none;
}
.satview.dragging { cursor: grabbing; }
.satview img, .satview video {
  position: absolute; top: 50%; left: 50%; width: 100%; height: auto;
  transform-origin: 0 0; user-select: -webkit-auto; -webkit-user-drag: none;
  will-change: transform;
}
.satview video[hidden], .satview img[hidden] { display: none; }
@media (max-width: 700px) { .satview { aspect-ratio: 4 / 3; } }

.satzoom {
  position: absolute; right: 10px; bottom: 10px; display: flex; gap: 1px; z-index: 3;
  border-radius: 8px; overflow: hidden; border: 1px solid var(--glass-border);
  box-shadow: var(--shadow-md);
}
.satzoom button {
  appearance: none; border: 0; cursor: pointer; min-width: 32px; height: 30px;
  font: 600 var(--f-sm)/1 var(--sans); padding: 0 9px;
  background: rgba(10,14,22,.72); color: #fff;
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
}
.satzoom button:hover { background: rgba(10,14,22,.88); }
:root[data-theme="light"] .satzoom button { background: rgba(255,255,255,.86); color: #0f1d33; }
:root[data-theme="light"] .satzoom button:hover { background: #fff; }

.sathint {
  position: absolute; left: 10px; bottom: 12px; z-index: 3; pointer-events: none;
  font: 600 var(--f-xs)/1 var(--sans); padding: 6px 9px; border-radius: 7px;
  background: rgba(10,14,22,.6); color: rgba(255,255,255,.9);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  transition: opacity .4s ease;
}
.sathint.hide { opacity: 0; }
:root[data-theme="light"] .sathint { background: rgba(255,255,255,.82); color: #0f1d33; }


/* ═══ text size control ═════════════════════════════════════════════ */
.tsize { display: flex; gap: 1px; border-radius: 999px; overflow: hidden;
  border: 1px solid var(--glass-border); box-shadow: var(--shadow-inset); flex: none; }
.tsize button {
  appearance: none; border: 0; cursor: pointer; background: var(--bg-subtle);
  color: var(--ink-3); font-family: var(--sans); font-weight: 700;
  padding: 0 9px; height: 33px; line-height: 1;
}
.tsize button:nth-child(1) { font-size: 12px; }
.tsize button:nth-child(2) { font-size: 15px; }
.tsize button:nth-child(3) { font-size: 18px; }
.tsize button:hover { color: var(--ink-2); }
.tsize button.on { background: var(--accent-soft); color: var(--accent); }
@media (max-width: 560px) { .brand small { display: none; } }

/* Storm approach charts and the running total carry a year or a week of shape;
   they need height to be readable, not just width. */
.stormchart { margin-top: 12px; min-height: 238px; }
#chartCum { min-height: 240px; }
#chartMonthly { min-height: 210px; }
.chart svg { display: block; width: 100%; height: auto; }

/* per-horizon rain probabilities */
.fcrows { display: flex; flex-direction: column; gap: 10px; margin-top: 12px; }
.fcrow { display: grid; grid-template-columns: 1fr auto; gap: 8px; align-items: baseline;
  font-size: var(--f-sm); }
.fcrow span { color: var(--ink-2); }
.fcrow b { color: var(--accent); font-variant-numeric: tabular-nums;
  font-size: var(--f-md); font-weight: 700; }
.fcrow .trk { grid-column: 1 / -1; height: 8px; border-radius: 999px;
  background: var(--bg-subtle); overflow: hidden; box-shadow: var(--shadow-inset); }
.fcrow .fil { height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 55%, transparent), var(--accent)); }

/* Satellite navigation is opt-in: inactive it is just a picture the page
   scrolls past; activated it captures wheel and drag. The ring makes the
   difference obvious. */
.satview { cursor: zoom-in; }
.satview.nav { cursor: grab; box-shadow: inset 0 0 0 2px var(--accent); }
.satview.nav.dragging { cursor: grabbing; }
.satview:not(.nav) .sathint { opacity: 1; }

/* ═══ responsive: let rows collapse on content, not on fixed breakpoints ═══
   auto-fit + minmax means a panel reflows when it actually runs out of room,
   at any window size, instead of snapping at three hard widths. */
.row-2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr)); }
.row-3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 290px), 1fr)); }
/* A span-2 panel must stop spanning once the row is single-column, or it
   overflows the grid. */
@supports (grid-template-columns: subgrid) {
  .span2 { grid-column: span 2; }
}
@media (max-width: 700px) { .span2 { grid-column: auto; } }

/* Header wraps instead of squeezing: brand keeps the line, controls drop below. */
.topbar { flex-wrap: wrap; row-gap: 8px; }
.brand { flex: 1 1 200px; }
.topright { flex: 0 0 auto; margin-left: auto; }
@media (max-width: 480px) {
  .topright { width: 100%; justify-content: space-between; margin-left: 0; }
  .fresh { max-width: none; flex: 1 1 auto; }
}

/* Tiles reflow on content too, and never squeeze below legibility. */
.tiles { grid-template-columns: repeat(auto-fit, minmax(min(100%, 92px), 1fr)); }
.tiles.t2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 104px), 1fr)); }
.recs { grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr)); }
.stormgrid { grid-template-columns: repeat(auto-fit, minmax(min(100%, 120px), 1fr)); }

/* Satellite gets shorter as the window narrows rather than letterboxing. */
.satview { aspect-ratio: 16 / 9; max-height: 78vh; }
@media (max-width: 900px) { .satview { aspect-ratio: 3 / 2; } }
@media (max-width: 620px) { .satview { aspect-ratio: 1 / 1; } }

/* Long captions and legends wrap cleanly in a narrow panel. */
.phead { flex-wrap: wrap; row-gap: 6px; }
.satctl { flex: 1 1 auto; justify-content: flex-end; }
.segs { flex-wrap: wrap; }


/* ═══ the Hawaiian name for the rain ════════════════════════════════
   Taken from Tiara's mobile dashboard, which names rain the way this coast
   actually does. Shown with its English gloss, because most neighbours will
   not know them and the point is to share them, not to gate-keep. */
.uaname {
  display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap;
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border-subtle);
}
.uaname b {
  font-size: var(--f-lg); font-weight: 600; color: var(--accent);
  letter-spacing: -0.01em;
}
.uaname span { font-size: var(--f-sm); color: var(--ink-3); }

/* One storm per row: the approach chart carries five days of track and needs
   the width. Two-up made its labels collide. */
.stormlist { display: flex; flex-direction: column; gap: 12px; margin-bottom: 12px; }
.stormlist .panel { margin-bottom: 0; }
.stormchart { margin-top: 14px; min-height: 238px; }

/* The working call — what the numbers mean for someone heading out. */
.fieldcall {
  margin: 12px 0 0; padding: 11px 13px; border-radius: 10px;
  background: var(--accent-soft); border: 1px solid color-mix(in srgb, var(--accent) 26%, transparent);
  color: var(--ink); font-size: var(--f-base); font-weight: 600; line-height: 1.5;
}

.lede { margin: 0 0 12px; font-size: var(--f-sm); color: var(--ink-2); max-width: 62ch; }

/* The forecast used to sit in a half-width column beside Conditions, which left
   the other half of the row empty once Conditions grew. Full width instead: the
   three horizons run across, the supporting readings sit beside them. */
.fcgrid { display: grid; grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr);
  gap: 16px; align-items: start; margin-top: 12px; }
.fcgrid .fcrows { margin-top: 0; display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 170px), 1fr)); }
.fcgrid .tiles { margin-top: 0; }
@media (max-width: 720px) { .fcgrid { grid-template-columns: minmax(0, 1fr); } }

/* ═══ numerals ══════════════════════════════════════════════════════
   Every measured value on the dashboard is set in JetBrains Mono — it is
   the parent's numeric identity, and tabular figures stop the big readouts
   from twitching as they tick. Applied to value slots only; prose stays
   in Inter — including SVG chart labels, which mix words with numbers and
   whose width has to stay predictable inside a fixed chart margin. */
.temp, .hs b, .tile b, .stat b, .fcrow b, .subj span, .rec b, .val,
.st .sc, .cmpr b, .ptag, .mtile b, .modelfact b {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  letter-spacing: -0.01em;
}

/* comparison rows — built by string concatenation in app.js */
.cmpr { display: grid; grid-template-columns: 1fr auto; gap: 8px; align-items: baseline; font-size: var(--f-sm); }
.cmpr span { color: var(--ink-3); }
.cmpr b { color: var(--ink-2); font-variant-numeric: tabular-nums; }
.cmpr .trk { grid-column: 1 / -1; height: 6px; border-radius: 999px; background: var(--bg-subtle); overflow: hidden; }
.cmpr .fil { height: 100%; border-radius: 999px; background: var(--series-prior); }
.cmpr.ours .fil { background: var(--accent); }
.cmpr.ours b { color: var(--accent); }

/* Readout under the running-total chart. Lives in the DOM rather than the SVG
   so it wraps like text and stays legible at the largest type setting. */
.cumread {
  display: flex; flex-wrap: wrap; gap: 6px 16px; align-items: center;
  margin-top: 8px; padding: 8px 10px; border-radius: 8px;
  background: var(--bg-subtle); border: 1px solid var(--border-subtle);
  font-size: var(--f-sm); color: var(--ink-2);
}
.cumread em { font-style: normal; font-weight: 700; color: var(--ink); min-width: 5.5em; }
.cumread span { display: inline-flex; align-items: center; gap: 6px; }
.cumread i { width: 9px; height: 9px; border-radius: 2px; flex: none; }
.cumread b { font-family: var(--mono); font-variant-numeric: tabular-nums; color: var(--ink); }

/* Shown only when the station is live and every internet-fed panel is hours
   old — i.e. the LAN is up and the line is down. */
.netstate {
  margin: 14px 0 0; padding: 12px 14px; border-radius: 10px;
  background: color-mix(in srgb, var(--warn) 13%, transparent);
  border: 1px solid color-mix(in srgb, var(--warn) 42%, transparent);
  color: var(--ink); font-size: var(--f-sm); line-height: 1.55;
}
.netstate b { color: var(--warn); }

.satctl button[disabled] { opacity: .42; cursor: default; }

/* The farm name links out to its Google Maps listing. Underlined on hover only,
   so the header still reads as a title rather than a link farm. */
.maplink { color: inherit; text-decoration: none; border-bottom: 1px dotted currentColor; }
.maplink:hover, .maplink:focus-visible { color: var(--accent); border-bottom-style: solid; }

/* A satellite frame we could not refresh is dimmed, so it never reads as the
   current sky at a glance. The caption says why. */
#satImg.stale { filter: grayscale(.45) opacity(.72); }
.stalemark { color: var(--warn); font-weight: 600; }
