/* ==========================================================================
   Weather page — "chart plate" styling, matching the site's Atlas aesthetic
   (parchment + sienna, EB Garamond + IBM Plex Mono).
   ========================================================================== */

:root {
    /* site-wide star cursor (mirrors main.css), reduced to a dot over the map */
    --cursor-plus: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'><g fill='%23b8431f'><polygon points='12,2 10,9.8 14,9.8'/><polygon points='22,12 14.2,10 14.2,14'/><polygon points='12,22 10,14.2 14,14.2'/><polygon points='2,12 9.8,10 9.8,14'/></g><circle cx='12' cy='12' r='1' fill='%232b1f15'/></svg>") 12 12, crosshair;
    --cursor-plus-click: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'><g fill='%23b8431f'><polygon points='12,2 10,9.8 14,9.8'/><polygon points='22,12 14.2,10 14.2,14'/><polygon points='12,22 10,14.2 14,14.2'/><polygon points='2,12 9.8,10 9.8,14'/></g><rect x='10' y='10' width='4' height='4' fill='%232b1f15'/></svg>") 12 12, pointer;
    --cursor-dot: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'><circle cx='6' cy='6' r='2.6' fill='%23b8431f'/><circle cx='6' cy='6' r='0.9' fill='%232b1f15'/></svg>") 6 6, crosshair;
    --bg: #f4efe5;
    --ink: #2b1f15;
    --muted: #6b5840;
    --faint: #a8967a;
    --accent: #b8431f;
    --rule: rgba(43, 31, 21, 0.10);
    --rule-strong: rgba(43, 31, 21, 0.25);
    --card: #fbf8f1;
}

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

html { cursor: var(--cursor-plus); }
a, button, input[type="range"], label, select, summary {
    cursor: var(--cursor-plus-click);
}
#map, #map .leaflet-grab, #map .leaflet-interactive, #map .leaflet-container {
    cursor: var(--cursor-dot);
}

body {
    background: var(--bg);
    color: var(--ink);
    font-family: 'EB Garamond', Georgia, serif;
    font-size: 17px;
    line-height: 1.45;
}

.mono { font-family: 'IBM Plex Mono', monospace; }

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

main { max-width: 780px; margin: 0 auto; padding: 0 0.75rem 2rem; }

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

.plate {
    max-width: 780px;
    margin: 0 auto;
    padding: 1.2rem 0.75rem 0;
    position: relative;
}
/* Available to assistive technology and to crawlers, drawn nowhere. Clipped
   rather than display:none, which would take it out of the outline too. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}
.plate-sub-row {
    display: flex;
    align-items: baseline;
    gap: 0.6rem;
    flex-wrap: wrap;
    margin: 0.25rem 0 0.8rem;
}
.plate-sub {
    font-size: 0.72rem;
    color: var(--muted);
    letter-spacing: 0.12em;
}
#loc-btn.picking { background: var(--accent); border-color: var(--accent); color: #fff; }
/* my-location: a symbol-only button, sized to sit level with the words */
#loc-me { padding: 0.15rem 0.4rem; }
#loc-me svg { display: inline-block; width: 1.1em; height: 1.1em; vertical-align: -0.2em; }
#loc-me:hover, #loc-me:focus-visible { color: var(--ink); border-color: var(--ink); }
#loc-me.note { color: var(--muted); }
/* place search: a quiet input in the location row; results drop below it */
#loc-search { position: relative; display: inline-block; }
#loc-q {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 0.7rem;
    padding: 0.15rem 0.5rem;
    background: none;
    border: 1px solid var(--rule);
    color: var(--ink);
    width: 11.5em;
    outline: none;
}
#loc-q:focus { border-color: var(--rule-strong); }
#loc-q::placeholder { color: var(--faint); }
#loc-q::-webkit-search-cancel-button { display: none; }
#loc-results {
    position: absolute;
    left: 0;
    top: 100%;
    z-index: 20;
    min-width: 100%;
    width: max-content;
    max-width: 78vw;
    list-style: none;
    background: var(--card);
    border: 1px solid var(--rule-strong);
    font-size: 0.7rem;
}
#loc-results li { padding: 0.25rem 0.55rem; color: var(--muted); }
#loc-results li[role="option"] { cursor: var(--cursor-plus-click); color: var(--ink); }
#loc-results li[role="option"]:hover, #loc-results li[role="option"]:focus {
    background: var(--accent); color: #fff; outline: none;
}
#loc-results li .sub { color: inherit; opacity: 0.7; margin-left: 0.4em; }
#map.picking { cursor: crosshair; }
#map.picking .leaflet-grab { cursor: crosshair; }
.plate-rule {
    border-top: 1px solid var(--rule-strong);
    border-bottom: 1px solid var(--rule-strong);
    height: 4px;   /* double rule, chart-plate style */
}

/* ==========================================================================
   Two weights of expandable.

   A .wx-section is a real section of the page that simply is not first-pass:
   the map, the climatology chart, the outlook, the records. It keeps the
   heading it had when it was a <section> and reads as one, with a disclosure
   marker; opening it is how you go past the glance. A .data-notes is the
   quieter tier nested inside — "about these numbers", the provenance and the
   caveats — and stays small mono type so it never competes with the section
   it explains.

   Everything above the first .wx-section (conditions, air quality reading,
   the seven-day bricks) is the first pass and is never collapsed.
   ========================================================================== */

.wx-section {
    border-top: 1px solid var(--rule);
    margin-top: 1.1rem;
}
.wx-section > summary {
    list-style: none;
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    padding: 0.85rem 0 0.2rem;
}
.wx-section > summary::-webkit-details-marker { display: none; }
/* The marker is drawn rather than inherited so it can sit on the heading's
   baseline and rotate; the native triangle aligns to the line box. */
.wx-section > summary::before {
    content: '';
    flex: none;
    width: 0.42em;
    height: 0.42em;
    border-right: 1.5px solid var(--faint);
    border-bottom: 1.5px solid var(--faint);
    transform: rotate(-45deg) translate(-0.1em, -0.1em);
    transition: transform 0.18s ease, border-color 0.18s ease;
}
.wx-section[open] > summary::before {
    transform: rotate(45deg) translate(-0.05em, -0.05em);
}
.wx-section > summary:hover::before { border-color: var(--accent); }
.wx-section > summary h2 {
    display: inline;
    font-size: 1.45rem;
    font-weight: 500;
}
/* One header for the whole backward-looking half. Not a disclosure — just a
   line that says the page has stopped talking about what is coming. */
.group-head {
    font-size: 0.68rem;
    font-weight: 400;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    font-family: 'IBM Plex Mono', monospace;
    color: var(--faint);
    margin: 2.4rem 0 0.2rem;
}
.wx-section > summary:hover h2 { color: var(--accent); }
.wx-section > .wx-body { padding-bottom: 0.6rem; }

/* A closed section reserves nothing, so the collapsed page is just the
   first pass plus a stack of headings. */
.wx-section:not([open]) > .wx-body { display: none; }

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

.mode-row { display: flex; gap: 0.4rem; margin-bottom: 0.55rem; }
.mode-btn {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 0.78rem;
    letter-spacing: 0.05em;
    padding: 0.35rem 0.8rem;
    background: none;
    border: 1px solid var(--rule-strong);
    color: var(--muted);
    cursor: var(--cursor-plus-click);
}
.mode-btn.active {
    background: var(--ink);
    border-color: var(--ink);
    color: var(--bg);
}

#map-wrap { position: relative; }
#map {
    height: 62vh;
    min-height: 340px;
    border: 1px solid var(--rule-strong);
    background: #e9e2d2;
}

/* Sepia-tone the basemap only — data panes stay untouched. */
.leaflet-pane.basemap-pane { filter: sepia(0.28) saturate(0.75) brightness(1.02); }
.hillshade-tiles { mix-blend-mode: multiply; }

/* Honest pixels: never let the browser smooth data rasters. */
.leaflet-pane.data-pane img { image-rendering: pixelated; }

#map-loading {
    position: absolute;
    inset: 0;
    z-index: 940;
    background: rgba(244, 239, 229, 0.45);
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
    align-items: center;
    justify-content: center;
    pointer-events: none;
}
#map-loading[hidden] { display: none; }
#map-loading .spin {
    width: 34px; height: 34px;
    border: 3px solid rgba(184, 67, 31, 0.25);
    border-top-color: var(--accent);
    border-radius: 50%;
    animation: wxspin 0.9s linear infinite;
}
@keyframes wxspin { to { transform: rotate(360deg); } }
#map-loading span { font-size: 0.66rem; letter-spacing: 0.14em; color: var(--muted); }

#map-tip {
    position: absolute;
    z-index: 960;
    background: var(--card);
    border: 1px solid var(--rule-strong);
    padding: 0.18rem 0.5rem;
    font-size: 0.68rem;
    color: var(--ink);
    pointer-events: none;
    white-space: nowrap;
}

#map-banner {
    position: absolute;
    top: 0; left: 0; right: 0;
    z-index: 900;
    background: rgba(184, 67, 31, 0.92);
    color: #fff;
    font-size: 0.74rem;
    padding: 0.35rem 0.6rem;
}

/* ---------------- time readout + slider ---------------- */

#radar-controls { margin-top: 0.55rem; }

#hrrr-mode-row { font-size: 0.72rem; margin-bottom: 0.45rem; }
.row-label { color: var(--faint); letter-spacing: 0.1em; font-size: 0.62rem; margin-right: 0.2rem; }
.mini-btn {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 0.7rem;
    padding: 0.15rem 0.5rem;
    background: none;
    border: 1px solid var(--rule-strong);
    color: var(--muted);
    cursor: var(--cursor-plus-click);
}
.mini-btn.active { background: var(--accent); border-color: var(--accent); color: #fff; }
#avg-mode-wrap { margin-left: 0.6rem; }

#fs-btn, #map-refresh {
    position: absolute;
    top: 10px; right: 10px;
    z-index: 950;
    width: 34px; height: 34px;
    font-size: 1.05rem;
    line-height: 1;
    background: var(--card);
    border: 1px solid var(--rule-strong);
    color: var(--ink);
    cursor: var(--cursor-plus-click);
}
/* refresh sits inboard of fullscreen, same corner stack */
#map-refresh { right: 52px; }
#map-refresh:hover { border-color: var(--accent); color: var(--accent); }
#map-refresh[disabled] { cursor: default; color: var(--muted); }
/* The glyph spins, not the button: a rotating bordered square reads as the
   control itself coming loose. */
#map-refresh .glyph { display: inline-block; line-height: 1; }
#map-refresh.spinning .glyph { animation: mr-spin 0.9s linear infinite; }
@keyframes mr-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
    #map-refresh.spinning .glyph { animation: none; }
    #map-refresh.spinning { opacity: 0.5; }
}
#goes-larger, #region-larger {
    position: absolute;
    top: 10px;
    left: 10px;
    z-index: 950;
    font-family: 'IBM Plex Mono', monospace;
    font-size: 0.72rem;
    padding: 0.35rem 0.7rem;
    background: var(--card);
    border: 1px solid var(--rule-strong);
    color: var(--ink);
    cursor: var(--cursor-plus-click);
}
#goes-larger:hover, #region-larger:hover { border-color: var(--accent); color: var(--accent); }
/* the region button is the common one, so it takes the corner; GOES's
   resolution button (GOES mode only, and only when the image is coarse)
   steps below it on the rare occasion both are up */
#goes-larger { top: 52px; }

#map-wrap.fullscreen {
    position: fixed;
    inset: 0;
    z-index: 2000;
    background: var(--bg);
}
#map-wrap.fullscreen #map { height: 100%; min-height: 0; border: none; }
body.no-scroll { overflow: hidden; }

.opacity-row { margin-top: 0.45rem; font-size: 0.72rem; display: flex; align-items: center; gap: 0.5rem; }
#layer-opacity { flex: 1; max-width: 260px; accent-color: var(--accent); }

#time-readout {
    font-size: 0.82rem;
    letter-spacing: 0.02em;
    min-height: 1.3em;
}
#time-readout .src { color: var(--muted); }
#time-readout .fx  { color: var(--accent); }

#slider-wrap { margin-top: 0.45rem; }

#slider-groups {
    display: flex;
    justify-content: space-between;
    font-size: 0.62rem;
    letter-spacing: 0.14em;
    color: var(--faint);
    margin-bottom: 0.15rem;
}
#grp-fx { color: #c68a6e; }

#slider-track { position: relative; height: 40px; }

#time-slider {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    -webkit-appearance: none;
    appearance: none;
    background: transparent;
    margin: 0;
    z-index: 5;
    cursor: var(--cursor-plus-click);
}
#time-slider::-webkit-slider-runnable-track { height: 100%; background: transparent; }
#time-slider::-moz-range-track { height: 100%; background: transparent; }
#time-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 14px; height: 30px;
    margin-top: 5px;
    background: var(--accent);
    border: 1px solid var(--ink);
    border-radius: 2px;
}
#time-slider::-moz-range-thumb {
    width: 12px; height: 28px;
    background: var(--accent);
    border: 1px solid var(--ink);
    border-radius: 2px;
}

#ticks {
    position: absolute;
    left: 7px; right: 7px;   /* align with thumb travel */
    top: 0; bottom: 0;
    pointer-events: none;
}
.tick {
    position: absolute;
    top: 12px;
    width: 2px; height: 16px;
    margin-left: -1px;
    background: var(--faint);
    opacity: 0.5;
}
.tick.loaded { background: var(--ink); opacity: 0.75; }
.tick.fx { background: #c68a6e; }
.tick.fx.loaded { background: var(--accent); opacity: 0.9; }
.tick.hour { height: 22px; top: 9px; }

#now-divider {
    position: absolute;
    top: 2px; bottom: 2px;
    width: 0;
    border-left: 1px dashed var(--ink);
    pointer-events: none;
}
#now-divider span {
    position: absolute;
    top: -2px; left: 3px;
    font-size: 0.58rem;
    letter-spacing: 0.1em;
    color: var(--muted);
}

.legend-row { margin-top: 0.5rem; }
#dbz-canvas {
    display: block;
    width: 100%;
    height: 13px;
    image-rendering: pixelated;   /* the legend obeys the same rule as the data */
    border: 1px solid var(--rule-strong);
}
#dbz-labels {
    position: relative;
    height: 1.1rem;
    font-size: 0.62rem;
    color: var(--muted);
}
#dbz-labels span { position: absolute; transform: translateX(-50%); }
#dbz-labels .unit { right: 0; left: auto; transform: none; color: var(--faint); }
#ir-canvas {
    display: block;
    width: 100%;
    height: 13px;
    image-rendering: pixelated;
    border: 1px solid var(--rule-strong);
}
#ir-labels {
    position: relative;
    height: 1.1rem;
    font-size: 0.62rem;
    color: var(--muted);
}
#ir-labels span { position: absolute; transform: translateX(-50%); }
#ir-labels .unit { right: 0; left: auto; transform: none; color: var(--faint); }
#ir-legend { margin-top: 0.5rem; }

/* ---------------- MRMS controls ---------------- */

#mrms-controls { margin-top: 0.6rem; }
.mrms-btn-row { display: flex; gap: 0.4rem; }
.mrms-btn {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 0.78rem;
    padding: 0.3rem 0.75rem;
    background: none;
    border: 1px solid var(--rule-strong);
    color: var(--muted);
    cursor: var(--cursor-plus-click);
}
.mrms-btn.active { background: var(--accent); border-color: var(--accent); color: #fff; }

#mrms-valid { font-size: 0.72rem; color: var(--muted); margin-top: 0.4rem; }

#mrms-legend {
    display: flex;
    margin-top: 0.45rem;
    border: 1px solid var(--rule-strong);
    overflow: hidden;
}
.mrms-bin { flex: 1; }
.mrms-bin .swatch { height: 16px; }
.mrms-bin .lbl {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 0.58rem;
    color: var(--muted);
    text-align: left;
    padding: 1px 0 1px 2px;
    border-left: 1px solid var(--rule);
}

.data-notes {
    margin-top: 0.8rem;
    border: 1px solid var(--rule);
    background: var(--card);
}
.data-notes summary {
    cursor: var(--cursor-plus-click);
    padding: 0.4rem 0.65rem;
    font-size: 0.68rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--muted);
    list-style-position: inside;
}
.data-notes summary:hover { color: var(--accent); }
.data-notes .dn-body {
    padding: 0.1rem 0.85rem 0.6rem;
    border-top: 1px solid var(--rule);
    font-size: 0.86rem;
    line-height: 1.5;
}
.data-notes .dn-body p { margin-top: 0.55rem; }
.data-notes .dn-body strong { font-weight: 600; }

/* ---------------- forecast section ---------------- */

.forecast-section { margin-top: 1.2rem; }
.forecast-section h2 {
    font-size: 1.45rem;
    font-weight: 500;
}
.src-tag {
    font-size: 0.68rem;
    letter-spacing: 0.12em;
    color: var(--bg);
    background: var(--ink);
    padding: 0.15rem 0.45rem;
    vertical-align: 0.25em;
}
#fc-meta { font-size: 0.7rem; color: var(--muted); letter-spacing: 0.04em; margin: 0.25rem 0 0.8rem; }

/* Day / night bricks. The grid runs on HALF-day columns — 2N+1 of them,
   set inline by app.js — so a day card spans columns 2i+1..2i+2 and the
   night that follows it spans 2i+2..2i+3, landing half a card to the
   right. Read down the two rows and each night sits under the seam
   between the day it starts on and the morning it ends on, which is
   exactly the span it describes. The row is not allowed to wrap (the
   offset only reads as a brick course when it is one continuous course);
   the narrow layout below drops to a single column instead. */
/* The week is one or more brick COURSES stacked vertically; app.js decides how
   many days each holds so cards never fall below a readable width. Every
   course carries the same column count, so a short final course leaves empty
   columns instead of stretching its cards wider than the ones above. */
#day-cards {
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
}
.brick-course {
    display: grid;
    /* grid-template-columns is set inline: repeat(2N+1, 1fr) */
    gap: 0.3rem 0.28rem;
    /* Stretch, not start: a day carrying all three precip lines is taller
       than its neighbours, and cards of ragged height in one course read as
       broken masonry. Each grid ROW equalises independently, so the day cards
       match each other and the night cards match each other. */
    align-items: stretch;
}
.day-card, .night-card {
    background: var(--card);
    border: 1px solid var(--rule);
    grid-column: var(--c) / span 2;
    min-width: 0;
}
.day-card { grid-row: 1; padding: 0.45rem 0.4rem 0.5rem; }
.night-card {
    grid-row: 2;
    padding: 0.35rem 0.4rem 0.4rem;
    /* Night reads cooler and quieter: no parchment lift, a dashed top edge
       picking up the seam it straddles. */
    background: rgba(43, 31, 21, 0.035);
    border-color: transparent;
    border-top: 1px dashed var(--rule-strong);
}
.day-card .dc-day { font-size: 0.9rem; font-weight: 600; line-height: 1.2; }
.day-card .dc-date { font-size: 0.58rem; color: var(--faint); letter-spacing: 0.05em; }
.day-card .dc-temps { margin-top: 0.25rem; font-size: 1.15rem; }
.night-card .nc-day {
    font-size: 0.56rem;
    letter-spacing: 0.06em;
    color: var(--muted);
    white-space: nowrap;
}
.night-card .nc-temps { margin-top: 0.1rem; font-size: 0.95rem; }
.dc-temps .hi, .nc-temps .hi { color: var(--accent); font-weight: 500; }
.dc-temps .lo, .nc-temps .lo { color: var(--muted); font-weight: 500; }
.dc-temps .sd, .nc-temps .sd { font-size: 0.6rem; color: var(--faint); }
.dc-nbm { font-size: 0.62rem; color: var(--faint); margin-top: 0.1rem; white-space: nowrap; }
.dc-nbm .sd { color: var(--faint); }
.dc-nbm .diverge { color: var(--accent); }
/* The exceedance ladder — up to three lines of the same shape, "P% ≥amount
   mm", driest at the top. The median carries the stronger ink so the eye
   lands on the ordinary outcome and reads the bounds off it. Sized to fit the
   widest form ("50% ≥12.4 mm") inside a ~95 px brick without wrapping. */
.day-card .dc-precip { font-size: 0.66rem; color: var(--muted); margin-top: 0.3rem; white-space: nowrap; }
.day-card .dc-precip + .dc-precip { margin-top: 0.02rem; }
.day-card .dc-bound { color: var(--faint); }
/* Td and gust: two lines in the ~95 px brick, one line with a separator
   once the narrow layout gives the row its full width. */
.day-card .dc-wind { font-size: 0.62rem; color: var(--faint); margin-top: 0.08rem; white-space: nowrap; }
.day-card .dc-wind span { display: block; }

/* No narrow-screen special case: the brick courses above handle it. This
   previously collapsed to a single stacked column below 700 px, which threw
   away the day/night offset at widths where two or three days per course
   still fit comfortably. app.js picks the course size from the measured
   width instead, so the shape survives all the way down. */

.fc-loading { color: var(--muted); font-size: 0.8rem; }
.wfo-key { font-family: 'IBM Plex Mono', monospace; font-size: 0.7rem; }

/* ---------------- observations ---------------- */

/* Below the column layout's comfortable width the grid would squeeze the
   readings; each part gets its own line instead. */
/* Reading | attribution | sun times. Column 1 sizes to the wider of the two
   readings, so the station label and the monitor label begin at the same x
   instead of one trailing its data and the other flushed to the far edge. */
.now-block {
    font-size: 0.85rem;
    margin: 1.1rem 0 0;
    padding-bottom: 0.7rem;
    border-bottom: 1px solid var(--rule);
    display: grid;
    /* Readings sized to content and never squeezed; the label column takes
       what is left. Monitor names run long ("Miami Fire Station #5"), and if
       anything has to wrap it should be the attribution, not the temperature. */
    grid-template-columns: max-content minmax(0, 1fr);
    align-items: baseline;
    column-gap: 1rem;
    row-gap: 0.3rem;
}
.src-note { color: var(--faint); font-size: 0.7rem; }
#aq-values .aq-v { font-weight: 500; }
/* Narrow: the two columns cannot both hold their content, and squeezing the
   label column turns a monitor name into one word per line. Each part gets a
   full-width line instead, reading down as value then source. MUST stay after
   the grid rule above — a media query adds no specificity, so declaring it
   earlier would simply lose. */
@media (max-width: 700px) {
    .now-block { display: block; }
    .now-block > span { display: block; }
    .now-block > .src-note { margin-bottom: 0.4rem; }
    .now-block > .src-note:last-child { margin-bottom: 0; }
}
#aq-values .aq-v { font-weight: 500; }

#aq-chart { margin: 0.2rem 0 0.9rem; }
#aq-chart svg { display: block; }
.aq-progress { font-size: 0.62rem; color: var(--faint); margin-top: 0.15rem; }
#aq-meta { font-size: 0.68rem; color: var(--faint); }
/* Category legend: the canonical AirNow swatch beside its name. The swatches
   carry the real colours; the numbers in the strip use darkened equivalents,
   since #ffff00 as text on parchment is unreadable. */
.aq-legend { font-size: 0.66rem; color: var(--muted); line-height: 1.9; }
.aq-chip { white-space: nowrap; margin-right: 0.9em; }
.aq-chip i {
    display: inline-block;
    width: 0.62em;
    height: 0.62em;
    margin-right: 0.25em;
    border: 1px solid var(--rule-strong);
    vertical-align: baseline;
}

/* Sun + moon, under the coordinates and above the location buttons. */
.sky-row {
    display: flex;
    align-items: center;
    gap: 0.9rem;
    margin: 0.3rem 0 0;
    opacity: 0.75;
    font-size: 0.78rem;
    white-space: nowrap;
}
.sky-item {
    font: inherit;
    color: inherit;
    background: none;
    border: 0;
    padding: 0.1rem 0;
    display: inline-flex;
    align-items: center;
}
.sky-item:focus-visible { outline: 1px solid var(--accent); outline-offset: 2px; }
.sun-glyph { vertical-align: -1px; margin-right: 3px; }

/* Hover / tap / focus label for the glyphs. Positioned against the document
   (not the trigger) so it is never clipped by an ancestor's overflow. */
.sky-tip {
    position: absolute;
    z-index: 60;
    max-width: 15rem;
    padding: 0.35rem 0.5rem;
    background: var(--card);
    border: 1px solid var(--rule-strong);
    color: var(--ink);
    font-family: 'IBM Plex Mono', monospace;
    font-size: 0.7rem;
    line-height: 1.45;
    white-space: pre-line;      /* the label's \n is the line break */
    pointer-events: none;
    box-shadow: 0 2px 6px rgba(43, 31, 21, 0.12);
}

/* ===== Site header + hamburger (matches the rest of the site; adapted
   from the shared header styles with this page's palette vars). The
   thought-cloud corner map (cloud-hud.js) docks its trigger into this
   header automatically, like on the other visual pages. ===== */
:root { --header-height: 64px; }
body { padding-top: var(--header-height); }
.site-header {
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    height: var(--header-height);
    padding: 0 1.5rem;
    background: linear-gradient(to bottom, var(--bg) 0%, var(--bg) 80%, transparent 100%);
    font-family: 'EB Garamond', Georgia, serif;
    font-size: 0.875rem;
}
.site-nav { display: flex; align-items: center; gap: 1.5rem; }
.nav-item { position: relative; display: flex; align-items: center; }
.nav-link {
    color: var(--muted);
    text-decoration: none;
    letter-spacing: 0.02em;
    transition: color 0.15s ease;
    padding: 0.5rem 0;
    display: block;
}
.nav-link:hover { color: var(--ink); text-decoration: none; }
.nav-link em { font-style: italic; }
.nav-link.active { color: var(--accent); }
.nav-item.static-breadcrumb { display: flex; align-items: center; }
.breadcrumb-divider { margin: 0 0.5rem; color: var(--faint); flex-shrink: 0; }
.breadcrumb-current {
    color: var(--faint);
    font-style: italic;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 30vw;
    display: inline-block;
    padding: 0.5rem 0;
}
.hamburger {
    display: none;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    width: 24px; height: 24px;
    background: none; border: none; padding: 0;
    margin-left: auto;
}
.hamburger span {
    display: block;
    width: 100%; height: 2px;
    background: var(--ink);
    transition: transform 0.15s ease, opacity 0.15s ease;
}
.mobile-menu {
    position: fixed;
    inset: 0;
    background: var(--bg);
    z-index: 999;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.25s ease, visibility 0s 0.25s;
}
.mobile-menu.open {
    opacity: 1;
    visibility: visible;
    transition: opacity 0.25s ease, visibility 0s 0s;
}
.mobile-menu-content { padding: calc(var(--header-height) + 2rem) 1.5rem 2rem; }
.mobile-menu .mobile-nav-item { margin-bottom: 1.5rem; }
.mobile-menu .mobile-nav-link {
    display: block;
    font-size: 1.25rem;
    color: var(--ink);
    text-decoration: none;
    margin-bottom: 0.5rem;
}
.mobile-menu .mobile-nav-link em { font-style: italic; }
.mobile-menu .mobile-nav-link.active { color: var(--accent); }
@media (max-width: 768px) {
    :root { --header-height: 56px; }
    .site-header { padding: 0 1rem; }
    .site-nav { display: none; }
    .hamburger { display: flex; }
    .site-header.menu-open .hamburger span:nth-child(1) {
        transform: rotate(45deg) translate(5px, 5px);
    }
    .site-header.menu-open .hamburger span:nth-child(2) { opacity: 0; }
    .site-header.menu-open .hamburger span:nth-child(3) {
        transform: rotate(-45deg) translate(5px, -5px);
    }
}
/* (the cloud-hud trigger and the hamburger both carry margin-left: auto —
   whichever is visible ends up right-aligned; the hud hides itself below
   1024 px, the hamburger only shows below 768 px) */

/* Aurora watch banner — appears only when forecast Kp crosses the
   latitude-derived threshold */
#aurora-banner {
    margin: 1.1rem 0 -0.4rem;
    border: 1px solid var(--accent);
    background: rgba(184, 67, 31, 0.07);
    font-size: 0.8rem;
}
#aurora-head {
    padding: 0.45rem 0.7rem;
    cursor: var(--cursor-plus-click);
    color: var(--accent);
    letter-spacing: 0.04em;
}
#aurora-head .aurora-more { text-decoration: underline; opacity: 0.8; }
#aurora-detail {
    padding: 0.15rem 0.7rem 0.55rem;
    line-height: 1.55;
    font-size: 0.74rem;
}
#aurora-detail a { color: var(--accent); }

/* NWS active-alerts banner shares the aurora banner's look */
#alert-banner {
    margin: 1.1rem 0 -0.4rem;
    border: 1px solid var(--accent);
    background: rgba(184, 67, 31, 0.07);
    font-size: 0.8rem;
}
#alert-head {
    padding: 0.45rem 0.7rem;
    cursor: var(--cursor-plus-click);
    color: var(--accent);
    letter-spacing: 0.04em;
}
#alert-detail {
    padding: 0.15rem 0.7rem 0.55rem;
    line-height: 1.55;
    font-size: 0.74rem;
}
.alert-block + .alert-block { margin-top: 0.6rem; }

/* chart hit-rects are tap targets — give them the site click cursor */
#climo-chart svg rect { cursor: var(--cursor-plus-click); }

/* Forecast verification panel (on-demand) */
#verif-table { border-collapse: collapse; font-size: 0.74rem; margin: 0.3rem 0 0.5rem; }
#verif-table th { text-align: left; font-weight: 400; color: var(--faint); padding: 0 1.1em 0.25em 0; }
#verif-table td { padding: 0.12em 1.1em 0.12em 0; }
.verif-sum { margin: 0.3rem 0; }
.verif-note { color: var(--faint); font-size: 0.7rem; margin-top: 0.35rem; }
#obs-current .big { font-size: 1.5rem; color: var(--accent); font-weight: 500; }
#obs-current .age { color: var(--faint); font-size: 0.7rem; }
#obs-week { border-collapse: collapse; font-size: 0.74rem; width: 100%; max-width: 430px; }
#obs-week th {
    text-align: left; font-weight: 400; color: var(--faint);
    font-size: 0.62rem; letter-spacing: 0.1em;
    border-bottom: 1px solid var(--rule-strong); padding: 0.15rem 0.9rem 0.2rem 0;
}
#obs-week td { padding: 0.18rem 0.9rem 0.18rem 0; border-bottom: 1px solid var(--rule); color: var(--muted); }
#obs-week td:first-child { color: var(--ink); }

/* ---------------- climo chart ---------------- */

#climo-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem 1.1rem;
    font-size: 0.66rem;
    color: var(--muted);
    margin: 0.4rem 0 0.5rem;
}
#climo-legend .lg { display: inline-flex; align-items: center; gap: 0.35rem; }
#climo-legend .sw { width: 11px; height: 11px; display: inline-block; }
#climo-chart { position: relative; }
#climo-chart svg { display: block; }
#climo-chart .cc-tick { fill: var(--faint); font-family: 'IBM Plex Mono', monospace; }
#climo-chart .cc-panel {
    fill: var(--muted);
    font-family: 'IBM Plex Mono', monospace;
    letter-spacing: 0.12em;
}
#cc-tip {
    position: absolute;
    background: var(--card);
    border: 1px solid var(--rule-strong);
    padding: 0.2rem 0.5rem;
    font-family: 'IBM Plex Mono', monospace;
    font-size: 0.66rem;
    color: var(--ink);
    pointer-events: none;
    max-width: min(270px, 78vw);   /* wraps on mobile instead of overflowing */
    line-height: 1.5;
    z-index: 10;
}

/* ---------------- climate explorer ---------------- */

/* Three rows of toggles. Station chips take their own hue when on (a
   place is its colour everywhere); panel and layer chips take ink, so the
   accent never doubles as a station. */
.ce-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem 0.35rem;
    margin: 0.35rem 0;
    font-size: 0.7rem;
}
.ce-row .row-label { min-width: 4.4em; }
.ce-chip { display: inline-flex; align-items: center; gap: 0.35em; }
.ce-chip.active:not(.ce-station) { background: var(--ink); border-color: var(--ink); color: var(--bg); }
.ce-chip:disabled { opacity: 0.4; cursor: default; }
.ce-chip .sw { width: 9px; height: 9px; display: inline-block; flex: none; }
.ce-station.active { background: var(--hue); border-color: var(--hue); color: #fff; }
.ce-station.active .sw { background: #fff !important; opacity: 0.85; }
.ce-elev { color: inherit; opacity: 0.65; font-size: 0.62rem; }
.ce-seg { display: inline-flex; }
.ce-seg .ce-chip + .ce-chip { margin-left: -1px; }

/* Each DRAW chip shows its own mark, so the chart carries no legend: the
   controls are the legend. Marks are drawn in currentColor so they invert
   with the chip. */
.ce-chip .mk { display: inline-block; width: 14px; flex: none; }
.ce-chip .mk-median { height: 0; border-top: 1.2px solid currentColor; }
.ce-chip .mk-year { height: 0; border-top: 3px solid currentColor; position: relative; }
.ce-chip .mk-year::after {
    content: ''; position: absolute; right: -2px; top: -3.5px;
    width: 5px; height: 5px; border-radius: 50%; background: currentColor;
}
.ce-chip .mk-iqr { height: 9px; background: currentColor; opacity: 0.45; }
.ce-chip .mk-p90 { height: 9px; background: currentColor; opacity: 0.2; }
.ce-chip .mk-ext { height: 0; border-top: 1.5px dotted currentColor; }
.ce-chip:disabled .mk { opacity: 0.5; }
.now-block > span[hidden] { display: none; }
.ce-chip .mk-frost { height: 0; border-top: 1px dashed currentColor; position: relative; }
.ce-chip .mk-frost::after {
    content: ''; position: absolute; left: 4px; right: 4px; top: 1px;
    height: 3px; border-radius: 2px; background: currentColor; opacity: 0.7;
}
/* the year picker: a select dressed as the chip it follows */
.ce-year {
    appearance: none; -webkit-appearance: none;
    margin-left: -1px; padding-right: 1.2em;
    background: transparent url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='8' height='6'><path d='M0 0h8L4 6z' fill='%236b5840'/></svg>") no-repeat right 0.35em center;
    color: var(--muted);
}
#climate-chart .ce-diff { fill: var(--muted); }
#climate-chart .ce-hot { font-weight: 600; }
#climate-chart .ce-sel { fill: rgba(43, 31, 21, 0.08); stroke: rgba(43, 31, 21, 0.35); stroke-width: 1; pointer-events: none; }
#climate-chart svg { cursor: var(--cursor-plus); user-select: none; -webkit-user-select: none; }
.ce-zoomout { margin-left: 0.6rem; }
#climate-chart { position: relative; }
#climate-chart svg { display: block; touch-action: pan-y; }
#climate-chart .cc-tick { fill: var(--faint); font-family: 'IBM Plex Mono', monospace; }
#climate-chart .cc-panel {
    fill: var(--muted);
    font-family: 'IBM Plex Mono', monospace;
    letter-spacing: 0.12em;
}
/* readout and cursor label sit over bands: a parchment halo keeps them
   legible without a box */
#climate-chart .ce-ro, #climate-chart .ce-hair-label {
    fill: var(--ink);
    font-family: 'IBM Plex Mono', monospace;
    paint-order: stroke;
    stroke: var(--bg);
    stroke-width: 3px;
    stroke-linejoin: round;
    pointer-events: none;
}
#climate-chart .ce-hair-label { fill: var(--muted); }
#climate-meta {
    font-size: 0.64rem;
    color: var(--faint);
    line-height: 1.6;
    margin: 0.35rem 0 0.2rem;
}
#climate-meta b { font-weight: 500; }

/* ---------------- footer ---------------- */

.attrib {
    max-width: 780px;
    margin: 2.5rem auto 0;
    padding: 0.8rem 0.75rem 1.6rem;
    border-top: 1px solid var(--rule-strong);
    font-size: 0.62rem;
    line-height: 1.7;
    color: var(--faint);
}
.attrib a { color: var(--muted); }

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

.mode-btn .lbl-short { display: none; }
@media (max-width: 480px) {
    .mode-btn .lbl-full { display: none; }
    .mode-btn .lbl-short { display: inline; }
}

@media (max-width: 640px) {
    body { font-size: 16px; }
    .plate h1 { font-size: 1.9rem; }
    #map { height: 52vh; }
}

/* Phone width: app.js keeps the week as a single course of fixed-width cards
   (breakpoint must match SCROLL_MQ there) and the course scrolls sideways.
   Negative margins let the row bleed to the viewport edge so a half-visible
   card hints that there is more to swipe. */
.brick-course.scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
    padding-bottom: 0.3rem;
    margin: 0 -0.75rem;                /* = main's side padding */
    padding-left: 0.75rem;
    padding-right: 0.75rem;
    scroll-snap-type: x proximity;
}
.brick-course.scroll .day-card { scroll-snap-align: start; }

/* ---- CPC outlook maps -------------------------------------------------- */
/* Every CPC image is 3300x2550; the frame carries that aspect ratio so the
   space is reserved before the image lands and the page never reflows when
   one arrives or when the lead time is switched. */
.cpc-pair {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.9rem;
    margin-top: 0.6rem;
}
.cpc-pair figure { margin: 0; }
.cpc-frame {
    aspect-ratio: 3300 / 2550;
    background: var(--card);
    border: 1px solid var(--rule-strong);
    overflow: hidden;
}
.cpc-frame img { width: 100%; height: 100%; object-fit: contain; display: block; }
.cpc-pair figcaption {
    color: var(--faint);
    font-size: 0.68rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    margin-top: 0.25rem;
}


/* ---- Forecast discussions ----------------------------------------------
   A .wx-sub is the middle weight: a disclosure nested inside a .wx-section,
   one per product, with the section's marker at h3 size. Lighter than a
   section heading, heavier than the mono "about" notes. */
.wx-sub { border-top: 1px solid var(--rule); }
.wx-sub:first-of-type { border-top: none; }
.wx-sub > summary {
    list-style: none;
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    padding: 0.55rem 0 0.35rem;
    cursor: var(--cursor-plus-click);
}
.wx-sub > summary::-webkit-details-marker { display: none; }
.wx-sub > summary::before {
    content: '';
    flex: none;
    width: 0.38em;
    height: 0.38em;
    border-right: 1.5px solid var(--faint);
    border-bottom: 1.5px solid var(--faint);
    transform: rotate(-45deg) translate(-0.1em, -0.1em);
    transition: transform 0.18s ease, border-color 0.18s ease;
}
.wx-sub[open] > summary::before {
    transform: rotate(45deg) translate(-0.05em, -0.05em);
}
.wx-sub > summary:hover::before { border-color: var(--accent); }
.wx-sub > summary h3 {
    display: inline;
    font-size: 1rem;
    font-weight: 500;
    margin: 0;
}
.wx-sub > summary:hover h3 { color: var(--accent); }
.wx-sub-tag {
    font-family: 'IBM Plex Mono', monospace;
    font-weight: 400;
    font-size: 0.66rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--faint);
    margin-left: 0.5rem;
}
.wx-sub > .disc-body { padding: 0 0 0.7rem; }
.afd-meta { color: var(--faint); font-size: 0.7rem; margin-bottom: 0.4rem; }
.afd-text {
    font-family: inherit;
    font-size: 0.72rem;
    line-height: 1.45;
    white-space: pre-wrap;
    max-height: 60vh;
    overflow-y: auto;
    margin: 0;
    color: var(--muted);
}

/* ---- Recent months + extremes ------------------------------------------ */
#hist-status { color: var(--faint); font-size: 0.72rem; margin: 0.2rem 0 0.5rem; }
#hist-table { border-collapse: collapse; font-size: 0.74rem; width: 100%; max-width: 560px; }
#hist-table th {
    text-align: left; font-weight: 400; color: var(--faint);
    font-size: 0.68rem; letter-spacing: 0.08em; text-transform: uppercase;
    padding: 0 0.9rem 0.3rem 0; border-bottom: 1px solid var(--rule-strong);
}
#hist-table td {
    padding: 0.18rem 0.9rem 0.18rem 0;
    border-bottom: 1px solid var(--rule);
    color: var(--muted);
}
#hist-table td:first-child { color: var(--ink); white-space: nowrap; }
.hist-partial { color: var(--accent); cursor: help; }
#extremes-body { font-size: 0.74rem; color: var(--muted); margin-top: 0.3rem; }
.ex-row { padding: 0.15rem 0; border-bottom: 1px solid var(--rule); }
.ex-row strong { color: var(--ink); font-weight: 500; }
.ex-scope { color: var(--accent); }
.ex-none { color: var(--muted); }
.ex-prov { color: var(--faint); font-size: 0.92em; }
.ex-day { color: var(--ink); display: inline-block; min-width: 4.2em; }

@media (max-width: 640px) {
    .cpc-pair { grid-template-columns: 1fr; }
    #hist-table { font-size: 0.7rem; }
    #hist-table th, #hist-table td { padding-right: 0.5rem; }
}

/* ---- reserved space for async blocks ----------------------------------- */
/* Skeletons carry the final geometry so nothing below them moves when data
   lands (the day cards alone were shifting the map down 335 px on desktop
   and 635 px on mobile). The bar is the "loading bar" in the reserved
   space: present enough to read as pending, quiet enough to ignore. */
.sk-bar {
    display: inline-block;
    width: 100%;
    max-width: 5.5em;
    height: 0.62em;
    vertical-align: middle;
    background: currentColor;
    opacity: 0.10;
    animation: skpulse 1.6s ease-in-out infinite;
}
.day-card.sk .dc-day .sk-bar { max-width: 4.2em; }
.day-card.sk .dc-temps .sk-bar { max-width: 2.6em; }
.sk .dc-nbm .sk-bar { max-width: 6.5em; }
.day-card.sk .dc-precip .sk-bar { max-width: 5em; }
.night-card.sk .nc-day .sk-bar { max-width: 7em; }
.night-card.sk .nc-temps .sk-bar { max-width: 2.6em; }
tr.sk .sk-bar { max-width: 4em; height: 0.55em; }
@keyframes skpulse { 0%, 100% { opacity: 0.10; } 50% { opacity: 0.20; } }
@media (prefers-reduced-motion: reduce) {
    .sk-bar { animation: none; }
}

/* A real card omits its NBM line when that line would only repeat the
   headline, so the cards keep the skeleton's height rather than shrinking
   by one row when that happens. */
.day-card { min-height: 8.4rem; }
.night-card { min-height: 3.5rem; }
#fc-meta { min-height: 1.1em; }

/* The chart's own height (climo-chart.js): 16 + 2*panelH + 30 + 34 +
   precipH + 24, with the narrow variant below host width 520 (= viewport
   544 given main's max-width and padding). Cleared inline after the first
   draw so a chart without the precip panel doesn't leave a gap. */
#climo-chart { min-height: 509px; }
@media (max-width: 544px) { #climo-chart { min-height: 454px; } }
#extremes-body { min-height: 4.5em; }
