:root {
  --font-sans: "Instrument Sans", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-serif: "Instrument Sans", system-ui, sans-serif;
  --font-display: "Barlow Condensed", "Instrument Sans", sans-serif;
  --panel: rgba(255, 255, 255, 0.1);
  --panel-strong: rgba(255, 255, 255, 0.16);
  --panel-soft: rgba(255, 255, 255, 0.07);
  --inset: rgba(8, 13, 20, 0.5);
  --border: rgba(255, 255, 255, 0.17);
  --text: #ffffff;
  --muted: rgba(255, 255, 255, 0.72);
  --accent: #facc15;
  --accent-2: #8fd3ff;
  --glow: rgba(250, 204, 21, 0.28);
  --shadow: 0 24px 80px rgba(0, 0, 0, 0.28);
}

@keyframes wxSpin { to { transform: rotate(360deg); } }
@keyframes wxSpinSlow { to { transform: rotate(-360deg); } }
@keyframes wxDrop { 0% { transform: translateY(-4px); opacity: 0; } 20% { opacity: 1; } 100% { transform: translateY(11px); opacity: 0; } }
@keyframes wxFlake { 0% { transform: translateY(-4px) rotate(0deg); opacity: 0; } 25% { opacity: 1; } 100% { transform: translateY(11px) rotate(120deg); opacity: 0; } }
@keyframes wxDrift { 0%, 100% { transform: translateX(-1.4px); } 50% { transform: translateX(1.4px); } }
@keyframes wxBolt { 0%, 86%, 100% { opacity: .2; } 88%, 93% { opacity: 1; } 90% { opacity: .35; } }
@keyframes wxBreathe { 0%, 100% { opacity: .5; transform: scale(.94); } 50% { opacity: 1; transform: scale(1.06); } }
@keyframes wxPulse { 0% { box-shadow: 0 0 0 0 rgba(142, 230, 168, .5); } 70% { box-shadow: 0 0 0 8px rgba(142, 230, 168, 0); } 100% { box-shadow: 0 0 0 0 rgba(142, 230, 168, 0); } }

@media (prefers-reduced-motion: reduce) {
  .weather-icon [style*="animation"],
  .current-icon [style*="animation"] {
    animation: none !important;
  }
}

* {
  box-sizing: border-box;
}

* {
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--accent) 72%, #ffffff 8%) rgba(255, 255, 255, 0.36);
}

*::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

*::-webkit-scrollbar-track {
  background: rgba(255, 255, 255, 0.11);
  border-radius: 999px;
}

*::-webkit-scrollbar-thumb {
  border: 2px solid rgba(255, 255, 255, 0.34);
  border-radius: 999px;
  background: linear-gradient(180deg, var(--accent), var(--accent-2));
}

html,
body {
  scrollbar-width: none;
}

html::-webkit-scrollbar,
body::-webkit-scrollbar {
  display: none;
}

html {
  min-height: 100%;
  /* Nothing in this app is meant to pan sideways. `clip` (unlike `hidden`)
     never makes the root a scroll container, so a stray wide descendant can
     no longer open blank gutters beside the centered shell, and disabling
     x-axis overscroll stops the sideways rubber-band that made the layout
     drift off-center mid-scroll on trackpads and iOS. */
  overflow-x: clip;
  overscroll-behavior-x: none;
  /* iOS Safari inflates text after pinch-zoom/rotation in some layouts,
     which made map-legend tick labels overlap; pin the adjustment. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  /* The fallback background-color must be the TOP gradient color (--sky-0):
     iOS standalone paints the status-bar safe-area band from the root
     background-color when fixed elements (the animated canvas) are clipped
     out of it, and using the bottom color left a visibly darker flat strip
     across the very top of the app.

     The fallback *gradient* lives on body::before below rather than here:
     the previous html background relied on background-attachment: fixed,
     which iOS Safari treats as "scroll" — so the gradient stretched across
     the full document height and the safe-area bands (status bar in
     Safari/standalone, home-indicator strip) exposed a flat off-palette
     slice instead of the animated scene. */
  background-color: var(--sky-0, #075985);
  transition: background-color 220ms ease;
}

/* While the detail modal is open, match the root fallback color to the
   modal backdrop. iOS standalone clips fixed layers (the backdrop included)
   out of the status-bar and home-indicator bands and paints them from this
   background-color — without this they stayed bright sky blue, sandwiching
   the dark modal and making it look zoomed/shifted. */
html:has(body.modal-open) {
  background-color: #0b1222;
}

body {
  min-height: 100vh;
  min-height: 100dvh;
  margin: 0;
  color: var(--text);
  font-family: var(--font-sans);
  /* Keep the body transparent so the ::before gradient can paint iOS
     standalone safe-area bands beneath the canvas and glow layers. */
  background: transparent;
  overflow-x: clip;
  overscroll-behavior-x: none;
  transition: color 220ms ease;
}

/* Viewport-pinned fallback gradient that mirrors the canvas palette. A real
   fixed-position element (unlike background-attachment: fixed, which iOS
   ignores) stays glued to the viewport on Safari and iOS standalone, so the
   status-bar band, home-indicator strip, and rubber-band overscroll always
   show the same diagonal gradient as the animated canvas even when iOS
   intermittently drops the canvas's compositing layer out of those bands.
   Paint order: body::before (gradient) → #atmosphereCanvas (later in DOM,
   same z-index) → body::after glow (1) → .shell content (2). */
body::before {
  content: "";
  position: fixed;
  inset: -96px 0;
  z-index: 0;
  /* Keep the fallback's color stops aligned to the visible viewport despite
     the safe-area bleed. The canvas uses the same 96px offset. */
  background: linear-gradient(to bottom,
    var(--sky-0, #075985) 96px,
    var(--sky-1, #1d4ed8) calc(96px + 33.333vh),
    var(--sky-2, #0f172a) calc(96px + 66.666vh),
    var(--sky-3, var(--sky-2, #0f172a)) calc(96px + 100vh));
  pointer-events: none;
}

body[data-theme="sunny"] {
  --accent: #facc15;
  --accent-2: #38bdf8;
  --glow: rgba(250, 204, 21, 0.34);
}

body[data-theme="sunset"] {
  --accent: #fb7185;
  --accent-2: #fbbf24;
  --glow: rgba(251, 113, 133, 0.38);
}

body[data-theme="storm"] {
  --accent: #a78bfa;
  --accent-2: #22d3ee;
  --glow: rgba(34, 211, 238, 0.36);
}

body[data-theme="midnight"] {
  --accent: #2dd4bf;
  --accent-2: #a7f3d0;
  --glow: rgba(45, 212, 191, 0.34);
}

body[data-condition="rain"],
body[data-condition="drizzle"] {
  --accent: #7dd3fc;
  --accent-2: #c4b5fd;
  --glow: rgba(125, 211, 252, 0.24);
}

body[data-condition="fog"] {
  --accent: #d8dee9;
  --accent-2: #b9c7d8;
  --glow: rgba(216, 222, 233, 0.2);
}

body[data-condition="winter"] {
  --accent: #bfdbfe;
  --accent-2: #a5f3fc;
  --glow: rgba(191, 219, 254, 0.28);
}

#atmosphereCanvas {
  position: fixed;
  /* Bleed 96px past the top and bottom of the screen. On iOS 26/27
     standalone web apps the fixed-position viewport can start below the
     status bar (and dvh/lvh can exclude the safe areas), and momentum /
     rubber-band overscroll can briefly pull the page well past either edge —
     which left an uncovered band of flat fallback color across the status-bar
     buffer and home indicator. A generous overshoot keeps the canvas under
     the status bar and home indicator no matter how the viewport is resolved
     or how far an overscroll bounces; the extra gradient just renders
     offscreen. */
  top: -96px;
  left: 0;
  width: 100vw;
  height: calc(100vh + 192px);
  height: calc(100lvh + 192px);
  /* Never use a negative z-index here: iOS Safari (and standalone web apps)
     intermittently composite negative z-index fixed elements behind the
     document background, which made the animated gradient vanish — leaving
     the flat fallback color showing through the top band and anywhere the
     page scrolled. The canvas instead sits at z-index 0 with the page
     content (.shell) raised above it. */
  z-index: 0;
  /* Safari with the bottom address bar tints the exposed status-bar strip by
     sampling the background-color of fixed elements near the viewport edges —
     it ignores theme-color there and never samples canvas pixels, so without
     an explicit background-color the strip fell back to a flat default
     instead of blending with the animated gradient. The canvas paints opaque
     pixels over this color, so nothing changes inside the page. */
  background-color: var(--sky-0, #075985);
}

body::after {
  content: "";
  position: fixed;
  /* Overshoot the viewport top/bottom like #atmosphereCanvas so the glow
     overlay also covers the iOS status-bar and home-indicator regions.
     Sits above the canvas (z-index 0) but below the content shell (2). */
  inset: -96px 0;
  z-index: 1;
  /* Fade the decorative overlay in only across the first 80 visible pixels.
     If iOS omits fixed layers in its status-bar band, the transition meets
     the root color invisibly instead of creating a page-wide hard stripe. */
  -webkit-mask-image: linear-gradient(to bottom, transparent 96px, #000 176px);
  mask-image: linear-gradient(to bottom, transparent 96px, #000 176px);
  background:
    radial-gradient(circle at 80% 12%, var(--glow), transparent 28rem),
    radial-gradient(circle at 14% 85%, rgba(56, 189, 248, 0.18), transparent 24rem),
    linear-gradient(rgba(3, 7, 18, 0.1), rgba(3, 7, 18, 0.44));
  pointer-events: none;
  transition: background 520ms ease, opacity 520ms ease;
}

body[data-condition="rain"]::after,
body[data-condition="drizzle"]::after,
body[data-condition="fog"]::after {
  background:
    linear-gradient(rgba(3, 7, 18, 0.18), rgba(3, 7, 18, 0.5)),
    radial-gradient(circle at 72% 20%, var(--glow), transparent 28rem);
}

/* ── Night ──────────────────────────────────────
   `data-theme="midnight"` means "it is dark out where you are", whatever the
   weather is doing — so it combines with, rather than replaces, the condition
   accents above. The condition keeps its hue (rain stays blue, snow stays
   pale) at a lower intensity, and the overlay gets appreciably darker so the
   whole app reads as night rather than as a daytime scene with a dim sky. */
body[data-theme="midnight"]::after {
  background:
    radial-gradient(circle at 80% 12%, var(--glow), transparent 26rem),
    radial-gradient(circle at 14% 85%, rgba(45, 212, 191, 0.12), transparent 24rem),
    linear-gradient(rgba(2, 5, 14, 0.32), rgba(2, 5, 14, 0.66));
}

body[data-theme="midnight"][data-condition="rain"],
body[data-theme="midnight"][data-condition="drizzle"] {
  --accent: #93c5fd;
  --accent-2: #a5b4fc;
  --glow: rgba(96, 165, 250, 0.2);
}

body[data-theme="midnight"][data-condition="fog"] {
  --accent: #cbd5e1;
  --accent-2: #94a3b8;
  --glow: rgba(148, 163, 184, 0.16);
}

body[data-theme="midnight"][data-condition="winter"] {
  --accent: #bfdbfe;
  --accent-2: #93c5fd;
  --glow: rgba(191, 219, 254, 0.2);
}

body[data-theme="midnight"][data-condition="storm"] {
  --accent: #c4b5fd;
  --accent-2: #67e8f9;
  --glow: rgba(167, 139, 250, 0.22);
}

/* Precipitation and fog after dark: the scrim goes darker still, because the
   night sky bucket behind it is already close to black and the daytime
   version of this overlay washed it back out to grey. */
body[data-theme="midnight"][data-condition="rain"]::after,
body[data-theme="midnight"][data-condition="drizzle"]::after,
body[data-theme="midnight"][data-condition="fog"]::after,
body[data-theme="midnight"][data-condition="storm"]::after {
  background:
    linear-gradient(rgba(2, 5, 14, 0.4), rgba(2, 5, 14, 0.72)),
    radial-gradient(circle at 72% 18%, var(--glow), transparent 26rem);
}

.shell {
  /* Raised above the fixed canvas (0) and glow overlay (1) so the page reads
     normally while both background layers stay at non-negative z-index. */
  position: relative;
  z-index: 2;
  width: min(1440px, calc(100% - 32px));
  margin: 0 auto;
  padding: 28px 0 40px;
  padding-top: max(28px, env(safe-area-inset-top));
  padding-bottom: max(40px, calc(40px + env(safe-area-inset-bottom)));
}

.topbar,
.section-head,
.top-actions,
.tabs,
.tile-heading {
  display: flex;
  align-items: center;
}

.topbar {
  justify-content: space-between;
  gap: 24px;
  margin-bottom: 20px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 12px;
}

.brand-mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  flex: none;
  border-radius: 11px;
  overflow: hidden;
  box-shadow: 0 8px 22px rgba(2, 6, 23, 0.2);
}

.brand-mark img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.brand-text {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.live-eyebrow {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  color: rgba(255, 255, 255, 0.62);
  font-size: 11.5px;
  font-weight: 500;
  text-transform: none;
  letter-spacing: normal;
}

.live-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #8ee6a8;
  flex: none;
  animation: wxPulse 2.4s ease-out infinite;
}

.eyebrow {
  margin: 0 0 7px;
  color: var(--accent-2);
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.11em;
  text-transform: uppercase;
}

h1,
h2,
h3,
p {
  margin-top: 0;
}

h1,
h2 {
  font-family: var(--font-sans);
  letter-spacing: -0.012em;
  font-weight: 600;
}

h1 {
  margin-bottom: 0;
  font-size: 15.5px;
  line-height: 1.2;
  color: #fff;
}

h2 {
  margin-bottom: 12px;
  font-size: clamp(1.4rem, 2.4vw, 1.7rem);
  line-height: 1.15;
}

h3 {
  margin-bottom: 8px;
  font-size: 1.05rem;
}

.top-actions {
  gap: 12px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.location-search {
  position: relative;
  display: flex;
  gap: 8px;
  flex-wrap: nowrap;
}

.location-search input {
  width: min(280px, 42vw);
}

.location-search button {
  min-height: 42px;
  padding: 0 15px;
  color: var(--text);
  border: 1px solid color-mix(in srgb, var(--accent) 58%, transparent);
  border-radius: 14px;
  background: color-mix(in srgb, var(--accent) 18%, rgba(255, 255, 255, 0.12));
  cursor: pointer;
  font-weight: 800;
  transition: transform 160ms ease, border-color 180ms ease, background 180ms ease, box-shadow 180ms ease;
}

.location-search button:hover,
.refresh-button:hover,
.climate-search button:hover {
  transform: translateY(-1px);
  box-shadow: 0 12px 28px color-mix(in srgb, var(--accent) 18%, transparent);
}

.location-suggestions {
  position: absolute;
  z-index: 25;
  top: calc(100% + 8px);
  left: 0;
  width: min(360px, 72vw);
  max-height: 320px;
  padding: 8px;
  overflow: auto;
  border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--border));
  border-radius: 14px;
  background: rgba(5, 10, 22, 0.88);
  box-shadow: 0 22px 62px rgba(0, 0, 0, 0.36);
  backdrop-filter: blur(18px);
  animation: menuIn 160ms ease both;
}

.location-suggestions[hidden] {
  display: none;
}

/* One row per town: the row itself picks the place, the trailing star saves it
   to favorites without dismissing the dropdown. */
.location-suggestion {
  display: flex;
  align-items: center;
  gap: 2px;
  border-radius: 14px;
}

.location-suggestion:hover {
  background: color-mix(in srgb, var(--accent) 16%, rgba(255, 255, 255, 0.05));
}

.location-suggestion-heading {
  margin: 2px 4px 6px;
  color: var(--muted);
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.location-suggestions button {
  min-height: 48px;
  color: var(--text);
  text-align: left;
  border: 0;
  border-radius: 14px;
  background: transparent;
  cursor: pointer;
}

.location-suggestion-pick {
  flex: 1;
  min-width: 0;
  display: grid;
  gap: 2px;
  padding: 8px 10px;
}

.location-suggestion-pick strong,
.location-suggestion-pick span {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.location-favorite-btn {
  flex: none;
  display: grid;
  place-items: center;
  width: 38px;
  min-height: 38px;
  margin-right: 4px;
  padding: 0;
  color: var(--muted);
  opacity: 0.65;
  transition: color 140ms ease, opacity 140ms ease, transform 140ms ease;
}

.location-favorite-btn svg { fill: none; }

.location-favorite-btn:hover {
  opacity: 1;
  transform: scale(1.12);
}

/* A saved town keeps a filled amber star whether or not the row is hovered. */
.location-favorite-btn.active {
  color: #fbbf24;
  opacity: 1;
}

.location-favorite-btn.active svg {
  fill: currentColor;
}

.location-suggestions span {
  color: var(--muted);
  font-size: 0.78rem;
}

.select-wrap {
  display: grid;
  gap: 6px;
  min-width: 184px;
  color: var(--muted);
  font-size: 0.75rem;
  font-weight: 700;
}

select,
input,
button {
  font: inherit;
}

select,
input {
  min-height: 42px;
  color: var(--text);
  background: rgba(255, 255, 255, 0.15);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 0 12px;
  outline: none;
  transition: border-color 180ms ease, box-shadow 180ms ease, background 180ms ease;
}

select:focus,
input:focus,
button:focus-visible {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 28%, transparent);
}

.status-badge,
.flight-rule {
  border: 1px solid color-mix(in srgb, var(--accent) 54%, transparent);
  background: color-mix(in srgb, var(--accent) 16%, rgba(255, 255, 255, 0.13));
  box-shadow: 0 0 28px var(--glow);
}

.status-badge {
  border-radius: 999px;
  padding: 12px 16px;
  font-weight: 800;
  white-space: nowrap;
}

.tabs {
  gap: 8px;
  padding: 6px;
  margin-bottom: 18px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  border: none;
  border-radius: 16px;
  background: transparent;
  backdrop-filter: none;
}

.tab,
.refresh-button,
.climate-search button {
  min-height: 42px;
  border: 1px solid var(--border);
  border-radius: 12px;
  color: rgba(255, 255, 255, 0.82);
  background: var(--panel-soft);
  backdrop-filter: blur(16px);
  cursor: pointer;
  font-weight: 600;
  font-size: 0.85rem;
  letter-spacing: -0.006em;
  white-space: nowrap;
  transition: transform 160ms ease, border-color 180ms ease, background 180ms ease, color 180ms ease, box-shadow 180ms ease;
}

.tab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 0 16px;
}

/* `display: inline-flex` above outranks the browser's default `[hidden]` rule,
   so a tab hidden from script (the Coast tab away from the coast) needs this
   to actually disappear. */
.tab[hidden] {
  display: none;
}

.tab-icon {
  flex: none;
}

.tab.active {
  color: #12181f;
  border-color: transparent;
  background: #ffffff;
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.18);
}

.tab:hover:not(.active) {
  color: var(--text);
  border-color: rgba(255, 255, 255, 0.3);
  transform: translateY(-1px);
}

.refresh-button,
.climate-search button {
  color: var(--text);
  border-color: color-mix(in srgb, var(--accent) 55%, var(--border));
  background: color-mix(in srgb, var(--accent) 16%, var(--panel-soft));
}

.screen {
  display: none;
}

.screen.active {
  display: block;
  animation: screenIn 240ms ease both;
}

.tile {
  border: 1px solid var(--border);
  border-radius: 26px;
  background: var(--panel);
  box-shadow: var(--shadow);
  backdrop-filter: blur(26px) saturate(150%);
  transition: transform 180ms ease, border-color 220ms ease, background 260ms ease, box-shadow 260ms ease;
}

.tile:hover {
  border-color: color-mix(in srgb, var(--accent) 34%, var(--border));
}

.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 16px;
}

.forecast-banner {
  min-height: 360px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(180px, 280px);
  gap: 24px;
  align-items: end;
  padding: clamp(22px, 4vw, 44px);
  position: relative;
  overflow: hidden;
}

.forecast-banner::before {
  content: "";
  position: absolute;
  inset: 1px;
  border-radius: inherit;
  background:
    linear-gradient(115deg, color-mix(in srgb, var(--accent) 18%, transparent), transparent 38%),
    radial-gradient(circle at 82% 22%, var(--glow), transparent 16rem);
  pointer-events: none;
}

.forecast-banner > * {
  position: relative;
}

.summary,
.tile p,
.section-head span,
dd {
  color: var(--muted);
}

#current-title {
  font-size: clamp(1.6rem, 3vw, 2rem);
  font-weight: 600;
  letter-spacing: -0.026em;
  line-height: 1.08;
}

.summary {
  max-width: 460px;
  margin-bottom: 0;
  font-size: 15px;
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.76);
}

.temp-lockup {
  justify-self: end;
  text-align: right;
}

.current-icon {
  width: 108px;
  height: 108px;
  margin: 0 0 8px auto;
  filter: drop-shadow(0 0 22px var(--glow));
  transition: filter 360ms ease, transform 260ms ease;
  animation: floatSoft 4s ease-in-out infinite;
}

.current-icon svg {
  width: 100%;
  height: 100%;
}

.temp-lockup span {
  font-family: var(--font-display);
  font-size: clamp(4.5rem, 10vw, 7.4rem);
  font-weight: 200;
  line-height: 0.82;
  letter-spacing: -.01em;
}

.temp-lockup sup {
  font-family: var(--font-display);
  font-size: 2.1rem;
  font-weight: 300;
  color: rgba(255, 255, 255, 0.7);
}

/* Inline °F / °C switch sitting beside the big temperature */
.unit-switch {
  display: inline-flex;
  gap: 2px;
  vertical-align: top;
  margin: 6px 0 0 6px;
  padding: 4px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--panel-soft);
  backdrop-filter: blur(16px);
  cursor: pointer;
  font: inherit;
  transition: border-color 180ms ease, box-shadow 180ms ease;
}
.unit-switch:hover {
  border-color: rgba(255, 255, 255, 0.3);
}
.unit-switch .unit-opt {
  font-size: 0.85rem;
  font-weight: 600;
  line-height: 1;
  padding: 6px 14px;
  border-radius: 999px;
  color: rgba(255, 255, 255, 0.75);
  transition: background 160ms ease, color 160ms ease;
}
.unit-switch .unit-opt.active {
  color: #12181f;
  background: #ffffff;
}

.temp-lockup small {
  display: block;
  margin-top: 10px;
  color: var(--accent-2);
  font-size: 1rem;
  font-weight: 800;
}

.comfort-tile {
  display: grid;
  align-content: space-between;
  min-height: 360px;
  padding: 24px;
}

.tile-heading {
  justify-content: space-between;
  gap: 12px;
}

.tile-heading strong {
  color: var(--accent);
}

.comfort-ring {
  --ring-color: var(--accent);
  width: 190px;
  aspect-ratio: 1;
  margin: 12px auto;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background:
    radial-gradient(circle at center, rgba(10, 16, 22, 0.5) 0 56%, transparent 57%),
    conic-gradient(var(--ring-color) calc(var(--score) * 1%), rgba(255, 255, 255, 0.14) 0);
  box-shadow: 0 0 42px color-mix(in srgb, var(--ring-color) 50%, transparent);
  backdrop-filter: blur(4px);
  transition: background 420ms ease, box-shadow 420ms ease, transform 220ms ease;
}

.comfort-ring:hover {
  transform: scale(1.025);
}

.comfort-ring span {
  font-size: 3.4rem;
  font-weight: 800;
}

.comfort-condition {
  width: fit-content;
  margin: 0 auto;
  padding: 8px 12px;
  color: var(--fwi-color, var(--accent));
  border: 1px solid color-mix(in srgb, var(--fwi-color, var(--accent)) 50%, transparent);
  border-radius: 999px;
  background: var(--fwi-bg, rgba(255, 255, 255, 0.08));
  font-size: 0.82rem;
  font-weight: 900;
  text-transform: uppercase;
}

.metric-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
  gap: 12px;
  margin: 16px 0;
}

.metric {
  min-height: 120px;
  padding: 17px 19px;
  animation: cardIn 240ms ease both;
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.metric-head {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 9px;
  min-height: auto;
  width: 100%;
  flex-direction: row;
}

.metric-head .eyebrow {
  margin: 0;
  line-height: 1;
  font-size: 10.5px;
  letter-spacing: 0.14em;
  color: rgba(255, 255, 255, 0.62);
}

.ui-icon {
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  flex: 0 0 20px;
  margin: 0;
  color: rgba(255, 255, 255, 0.72);
  border: none;
  border-radius: 0;
  background: none;
  transition: transform 180ms ease;
  flex-shrink: 0;
}

.ui-icon svg {
  width: 16px;
  height: 16px;
  display: block;
  margin: auto;
  transform: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
  overflow: visible;
}

/* hourly chart and metric switcher are now always shown */

.metric:hover .ui-icon {
  transform: scale(1.08);
}

.metric span,
.daily-range,
.space-value {
  display: block;
  font-family: var(--font-display);
  font-size: 2.5rem;
  font-weight: 300;
  line-height: 0.88;
}

.metric small {
  color: rgba(255, 255, 255, 0.66);
  font-size: 12px;
  line-height: 1.45;
}

.hourly-panel,
.climate-card {
  padding: 22px;
}

.alerts-panel {
  margin: 16px 0;
}

.alert-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 6px;
}

.alert-head-count {
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
}

.alert-head-source {
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--muted);
  opacity: 0.75;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.alert-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* One tappable line per alert. Everything else — the headline paragraph, the
   full county list, the tag row — lives in the alert modal behind this tap. */
.alert-row {
  /* --alert-color / --alert-edge are set per row from the event's official
     weather.gov color, so the panel, the map polygon and the NWS map agree.
     They fall back to the theme accent for anything without a color. */
  --alert-color: var(--accent);
  --alert-edge: var(--accent);
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 12px;
  text-align: left;
  color: var(--text);
  cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--alert-color) 42%, var(--border));
  border-left: 4px solid var(--alert-color);
  border-radius: 10px;
  background: color-mix(in srgb, var(--alert-color) 13%, var(--card, rgba(255, 255, 255, 0.06)));
}

.alert-row:hover {
  border-color: color-mix(in srgb, var(--alert-edge) 62%, var(--border));
  border-left-color: var(--alert-edge);
  background: color-mix(in srgb, var(--alert-color) 22%, var(--card, rgba(255, 255, 255, 0.06)));
}

.alert-row-text {
  display: flex;
  flex: 1;
  min-width: 0;
  flex-direction: column;
  gap: 1px;
}

.alert-row-event {
  font-size: 0.9rem;
  font-weight: 800;
  line-height: 1.25;
}

.alert-row-meta {
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--muted);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.alert-row-chevron {
  flex: none;
  color: var(--muted);
  opacity: 0.7;
}

.alert-more {
  width: 100%;
  margin-top: 6px;
  padding: 7px 10px;
  color: var(--muted);
  font-size: 0.74rem;
  font-weight: 800;
  cursor: pointer;
  background: transparent;
  border: 1px dashed var(--border);
  border-radius: 10px;
}

.alert-more:hover {
  color: var(--text);
  border-style: solid;
}

.severity-severe,
.severity-extreme {
  --accent: #fb7185;
  --accent-2: #fecdd3;
}

.section-head {
  justify-content: space-between;
  gap: 18px;
  margin-bottom: 16px;
}

.hourly-strip {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 136px;
  gap: 10px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  /* A horizontal scroller clips vertically too — `overflow-y` resolves to
     `auto` the moment `overflow-x` is not `visible`, and there is no way to
     opt out. Hovering or keyboard-focusing an hour lifts the card 2px and
     paints a focus ring around it, both of which were being sliced off at the
     top edge of the strip. The padding is the scroll container's own space, so
     the lifted card has somewhere to go. */
  padding-top: 6px;
  padding-bottom: 8px;
}

.hour-card,
.daily-card {
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.06);
  backdrop-filter: blur(20px);
  overflow: hidden;
}

.hour-card {
  min-height: 166px;
  padding: 12px;
  color: var(--text);
  text-align: left;
  cursor: pointer;
  font: inherit;
  transition: transform 160ms ease, border-color 160ms ease, background 160ms ease;
}

.hour-card:hover,
.daily-card:hover {
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--accent) 54%, rgba(255,255,255,0.14));
  background: rgba(255, 255, 255, 0.13);
}

.weather-icon {
  display: block;
  width: 38px;
  height: 38px;
  margin: 8px 0;
  filter: drop-shadow(0 0 16px var(--glow));
}

.weather-icon svg {
  width: 100%;
  height: 100%;
}

.hour-temp {
  font-size: 1.45rem;
  font-weight: 800;
}

.hour-fwi {
  display: inline-flex;
  align-items: center;
  max-width: 100%;
  margin: 4px 0 6px;
  padding: 4px 7px;
  color: var(--fwi-color, var(--accent));
  border: 1px solid color-mix(in srgb, var(--fwi-color, var(--accent)) 46%, transparent);
  border-radius: 999px;
  background: var(--fwi-bg, rgba(255, 255, 255, 0.08));
  font-size: 0.66rem;
  font-weight: 900;
  line-height: 1.1;
  white-space: normal;
}

.hour-card.compact {
  min-width: 64px;
  min-height: auto;
  padding: 10px 0 11px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  background: rgba(255, 255, 255, 0.05);
}
.hour-card.compact strong {
  font-size: 11px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.66);
}
.hour-card.compact .hour-temp {
  font-family: var(--font-display);
  font-size: 27px;
  font-weight: 300;
  line-height: 0.88;
}
.hour-card.compact small {
  font-size: 10.5px;
  font-weight: 500;
  color: rgba(160, 215, 255, 0.85);
}
.hour-card.compact .weather-icon {
  width: 24px;
  height: 24px;
  margin: 0;
  filter: none;
}

.mini-line {
  display: block;
  margin-top: 8px;
  color: var(--muted);
  font-size: 0.74rem;
  font-weight: 700;
  line-height: 1.25;
}

.daily-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 12px;
}

.daily-card {
  min-height: 238px;
  padding: 16px;
  color: var(--text);
  text-align: left;
  cursor: pointer;
  font: inherit;
  transition: transform 160ms ease, border-color 160ms ease, background 160ms ease;
}

.daily-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
}

.daily-card .weather-icon {
  width: 44px;
  height: 44px;
  margin: 0;
  flex-shrink: 0;
}

.daily-card .daily-card-head .eyebrow {
  margin-bottom: 0;
}

.daily-card .eyebrow {
  margin-bottom: 4px;
}

.daily-badge-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  min-height: 22px;
  margin-bottom: 4px;
}

.daily-range {
  margin: 10px 0;
}

.daily-summary {
  min-height: 42px;
  margin-bottom: 12px;
  color: var(--muted);
  font-size: 0.9rem;
  line-height: 1.35;
}

.daily-chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  /* Breathing room between the summary text above and the chip row — the
     chips previously sat almost flush against the forecast sentence. */
  margin-top: 14px;
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 800;
}

.daily-chip-row span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  /* Icon hugs the pill's left end — the larger inset left it floating in
     the middle of the leading space, which read as misplaced. */
  padding: 5px 10px 5px 5px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.1);
}

/* Inline chip icons reuse uiIcon markup but drop its boxed treatment.
   The padding reset matters: the pill rule above targets every span in the
   row, so without it the icon box also picked up the pill's own padding —
   leaving the glyph floating mid-air left of the text. */
.daily-chip-row .ui-icon {
  width: 13px;
  height: 13px;
  flex: 0 0 13px;
  margin: 0;
  padding: 0;
  border: none;
  border-radius: 0;
  background: none;
  color: var(--accent-2);
}

.daily-chip-row .ui-icon svg {
  width: 11px;
  height: 11px;
  margin: 0;
  transform: none;
}

.daily-chip-row .chip-precip .ui-icon {
  color: #7dd3fc;
}

.daily-chip-row .chip-uv .ui-icon {
  color: var(--accent);
}

.daily-chip-row .pollen-chip .ui-icon {
  color: #86efac;
}

.daily-range-low {
  color: var(--muted);
  font-size: 1.1rem;
  font-weight: 700;
}

.pollen-chip {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 0.7rem;
  font-weight: 700;
  color: #86efac;
  background: rgba(134, 239, 172, 0.12);
  border: 1px solid rgba(134, 239, 172, 0.25);
  border-radius: 4px;
  padding: 2px 5px;
  white-space: nowrap;
}
.pollen-chip svg {
  flex-shrink: 0;
  stroke: #86efac;
}

/* Fullscreen: the stage leaves the document flow entirely and covers the
   header and tab bar too, so the map really is the whole screen. */
body.map-fullscreen {
  overflow: hidden;
}

body.map-fullscreen .map-stage {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  height: 100dvh;
  margin: 0;
  z-index: 60;
}

body.map-fullscreen .map-hud {
  top: max(12px, env(safe-area-inset-top));
}

/* Fullscreen runs to the physical edge of the screen, so the credit strip — and
   therefore everything stacked above it — has to clear the home indicator. */
body.map-fullscreen .map-stage {
  --map-credit-h: calc(22px + env(safe-area-inset-bottom, 0px));
}

body.map-fullscreen #radarMap .mapboxgl-ctrl-bottom-left,
body.map-fullscreen #radarMap .mapboxgl-ctrl-bottom-right {
  padding-bottom: env(safe-area-inset-bottom, 0px);
}

/* On the radar tab the map screen is sized to fill the viewport exactly, so
   the shell's bottom gutter has to go — otherwise the page is 40px taller than
   the window and the map can be scrolled partly off screen. */
body.map-mode .shell {
  padding-bottom: 0;
}

/* The stage is measured from its position on screen, so it must not be
   mid-slide when that measurement is taken. */
.map-screen.active {
  animation: none;
}

/* ═══════════════════════════════════════════════
   FULL-BLEED MAP STAGE
   The radar used to be a 16:9 panel stacked above a sidebar inside a tile.
   It now takes the whole screen below the tabs: the map is the page, and
   every control floats over it as a translucent panel.
═══════════════════════════════════════════════ */
.map-stage {
  /* Everything docked along the bottom of the map — the Mapbox credit strip and
     scale bar, the frame scrubber, the legends — is stacked from these, so a
     change to any one row pushes the others up instead of landing on top of
     them. The credit row is the floor. */
  --map-credit-h: 22px;
  --map-scrubber-h: 40px;
  --map-bottom-gap: 8px;
  /* Where the scrubber sits, and where a legend sits when there is no scrubber. */
  --map-dock-bottom: calc(var(--map-credit-h) + var(--map-bottom-gap));
  /* Where a legend sits when the scrubber is on screen. */
  --map-legend-bottom: calc(var(--map-dock-bottom) + var(--map-scrubber-h) + var(--map-bottom-gap));
  position: relative;
  /* Escape the shell's max-width and side gutters so the map runs edge to
     edge, then fill everything from the tabs down to the bottom of the
     viewport. --map-stage-top is measured in JS (see sizeMapStage) because
     the header/tab block's height depends on wrapping and safe-area insets. */
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  height: calc(100vh - var(--map-stage-top, 240px));
  height: calc(100dvh - var(--map-stage-top, 240px));
  min-height: 420px;
  overflow: hidden;
  isolation: isolate;
}

#radarMap {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  background: rgba(2, 6, 23, 0.52);
  overflow: hidden;
}

.radar-site-pill {
  min-width: 46px;
  height: 23px;
  padding: 0 8px;
  border: 1px solid rgba(125, 211, 252, 0.68);
  border-radius: 999px;
  background: rgba(8, 18, 35, 0.9);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.34);
  color: #d9f3ff;
  cursor: pointer;
  font: 700 10px/1 "IBM Plex Mono", "SFMono-Regular", Consolas, monospace;
  letter-spacing: 0.03em;
  pointer-events: auto;
  transition: scale 120ms ease, background 120ms ease, border-color 120ms ease;
}

.radar-site-pill:hover {
  scale: 1.08;
  border-color: #67e8f9;
  background: rgba(14, 42, 67, 0.96);
}

.radar-site-pill.active {
  border-color: #22d3ee;
  background: #22d3ee;
  box-shadow: 0 0 0 2px rgba(8, 18, 35, 0.86), 0 0 16px rgba(34, 211, 238, 0.58);
  color: #04121a;
}

/* Everything that floats over the map lives in one column pinned to the top of
   the stage: the control bar, then the panels beneath it. Laying the panels
   out *below* the bar in normal flow (rather than pinning them at a guessed
   offset) means a bar that wraps to two rows pushes them down instead of
   being covered by them. */
.map-hud {
  position: absolute;
  top: 12px;
  left: 12px;
  right: 12px;
  /* Stop above the docked scrubber and credit strip. The panels scroll inside
     whatever height that leaves, so a long layer list can no longer grow down
     across the timeline and the legends on a phone. */
  bottom: var(--map-legend-bottom);
  z-index: 6;
  display: flex;
  flex-direction: column;
  gap: 8px;
  /* The column spans the map so the panels can use its height, but only the
     controls themselves should swallow clicks — the rest passes to the map. */
  pointer-events: none;
}

.map-hud-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding-right: 46px; /* clear of the Mapbox zoom/compass stack */
  flex-shrink: 0;
}

.map-hud-bar > * {
  pointer-events: auto;
}

.map-hud-panels {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  flex: 1;
  min-height: 0;
}

.map-hud-title {
  margin: 0 auto 0 0;
  padding: 6px 12px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 999px;
  background: rgba(6, 12, 30, 0.78);
  backdrop-filter: blur(14px);
  font-size: 0.86rem;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 40%;
}

.map-hud-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 32px;
  padding: 0 12px;
  color: var(--muted);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 999px;
  background: rgba(6, 12, 30, 0.78);
  backdrop-filter: blur(14px);
  cursor: pointer;
  font: inherit;
  font-size: 0.76rem;
  font-weight: 700;
  transition: color 160ms ease, background 160ms ease, border-color 160ms ease;
}

.timeline-slider:disabled,
.play-btn:disabled {
  opacity: 0.45;
  cursor: default;
}

/* The HUD pills have to fit one row on a phone; the locate button carries a
   shorter label for narrow widths. */
.hud-label-narrow { display: none; }

.map-hud-btn.active {
  color: #12181f;
  border-color: transparent;
  background: #ffffff;
}

/* Panels float over the map instead of taking layout space away from it. */
.map-panel {
  pointer-events: auto;
  max-height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
  animation: mapPanelIn 180ms ease both;
}

.map-panel[hidden] {
  display: none;
}

@keyframes mapPanelIn {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}

#mapControlsPanel {
  width: min(400px, 100%);
}

.map-sidebar {
  width: min(300px, 100%);
  margin-left: auto; /* hugs the right edge even when the layer panel is closed */
  display: grid;
  gap: 12px;
  align-content: start;
  padding: 0;
}

.radar-controls {
  display: grid;
  grid-template-columns: auto minmax(160px, 1fr) auto;
  align-items: center;
  gap: 12px;
  margin-top: 12px;
  padding: 12px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.11);
}

.radar-controls button {
  min-height: 36px;
  padding: 0 14px;
  color: var(--text);
  border: 1px solid color-mix(in srgb, var(--accent) 48%, transparent);
  border-radius: 14px;
  background: color-mix(in srgb, var(--accent) 16%, rgba(255, 255, 255, 0.13));
  cursor: pointer;
  font-weight: 800;
}

.radar-controls input[type="range"] {
  width: 100%;
  accent-color: var(--accent);
}

.radar-controls span {
  min-width: 74px;
  color: var(--muted);
  font-size: 0.82rem;
  font-weight: 800;
  text-align: right;
}

#radarMap .mapboxgl-ctrl-group {
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 14px;
  background: rgba(2, 6, 23, 0.72);
}

#radarMap .mapboxgl-ctrl button {
  filter: invert(1);
}

/* ── Bottom credit strip ──
   The scale bar and the attribution are the map's floor: everything else docked
   at the bottom stacks above them (see --map-credit-h on .map-stage). They used
   to share the bottom-right corner and stack into a two-line block that ran
   straight through the legend on a phone, so they now sit in opposite corners,
   both clamped to one line at the height the rest of the layout assumes. */
#radarMap .mapboxgl-ctrl-bottom-left,
#radarMap .mapboxgl-ctrl-bottom-right {
  z-index: 2;
  display: flex;
  align-items: flex-end;
  height: var(--map-credit-h, 22px);
  pointer-events: none;
}

#radarMap .mapboxgl-ctrl-bottom-left .mapboxgl-ctrl,
#radarMap .mapboxgl-ctrl-bottom-right .mapboxgl-ctrl {
  margin: 0 6px 3px;
  pointer-events: auto;
}

#radarMap .mapboxgl-ctrl-scale {
  padding: 0 5px;
  border: 1px solid rgba(255, 255, 255, 0.28);
  border-top: 0;
  border-radius: 0 0 5px 5px;
  background: rgba(4, 10, 24, 0.66);
  color: rgba(226, 236, 250, 0.86);
  font-size: 9.5px;
  font-weight: 700;
  line-height: 14px;
  white-space: nowrap;
}

#radarMap .mapboxgl-ctrl-attrib {
  max-width: min(58vw, 420px);
  padding: 0 6px;
  border-radius: 7px;
  background: rgba(4, 10, 24, 0.66);
  font-size: 9.5px;
  line-height: 15px;
  /* One line, always: the credit strip's height is a layout constant. */
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

#radarMap .mapboxgl-ctrl-attrib a {
  color: rgba(226, 236, 250, 0.8);
}

/* Compact mode collapses to an "i" disc until tapped; the expanded panel opens
   upward so it never pushes the strip taller. */
#radarMap .mapboxgl-ctrl-attrib.mapboxgl-compact {
  min-height: 18px;
  background: rgba(4, 10, 24, 0.66);
}

#radarMap .mapboxgl-ctrl-attrib-button {
  width: 18px;
  height: 18px;
  background-color: rgba(255, 255, 255, 0.82);
  border-radius: 50%;
}

#radarMap .mapboxgl-ctrl-attrib.mapboxgl-compact-show .mapboxgl-ctrl-attrib-inner {
  max-width: min(70vw, 380px);
}

.layer-pills {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.layer-pills button {
  min-height: 34px;
  color: var(--muted);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.14);
  cursor: pointer;
  font-size: 0.78rem;
  font-weight: 800;
  transition: transform 160ms ease, border-color 180ms ease, background 180ms ease, color 180ms ease;
}

.layer-pills button.active {
  color: #12181f;
  border-color: transparent;
  background: #ffffff;
}

.layer-pills button:hover {
  transform: translateY(-1px);
}

.aviation-grid,
.space-readouts {
  display: grid;
  gap: 16px;
}

.metar-card,
.space-card {
  padding: 22px;
}

.metar-search-form {
  display: flex;
  gap: 6px;
  margin: 10px 0 4px;
}

.metar-search-input {
  flex: 1 1 auto;
  padding: 6px 10px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--panel-soft);
  backdrop-filter: blur(14px);
  color: var(--text);
  font-size: 0.85rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.metar-search-input::placeholder {
  text-transform: none;
  letter-spacing: normal;
  font-weight: 400;
  color: var(--muted);
}

.metar-search-btn,
.metar-search-clear {
  padding: 6px 12px;
  border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, 0.2);
  background: rgba(255, 255, 255, 0.08);
  color: inherit;
  font-size: 0.8rem;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
}

.metar-search-btn:hover,
.metar-search-clear:hover {
  background: rgba(255, 255, 255, 0.15);
}

.aviation-grid {
  grid-template-columns: minmax(0, 1.25fr) minmax(320px, 0.75fr);
}

.flight-rule {
  width: 112px;
  height: 112px;
  display: grid;
  place-items: center;
  margin: 18px 0;
  border-radius: 50%;
  color: var(--accent);
  font-size: 2rem;
  font-weight: 800;
}

pre {
  white-space: pre-wrap;
  margin: 0 0 16px;
  padding: 16px;
  color: #dff7ff;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 14px;
  background: rgba(2, 6, 23, 0.5);
}

dl {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin: 0;
}

dt {
  font-size: 0.75rem;
  color: var(--accent-2);
  font-weight: 800;
  text-transform: uppercase;
}

.detail-list dt {
  display: flex;
  align-items: center;
  gap: 5px;
}

.detail-list dt .ui-icon {
  width: 18px;
  height: 18px;
  flex: 0 0 18px;
  font-size: 0;
}

.detail-list dt .ui-icon svg {
  width: 11px;
  height: 11px;
}

dd {
  margin: 5px 0 0;
  font-weight: 700;
}

.space-readouts {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.space-item {
  padding: 16px;
  border: 1px solid rgba(255, 255, 255, 0.13);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.1);
}

.aurora-bar {
  height: 14px;
  margin: 24px 0 14px;
  overflow: hidden;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.12);
}

.aurora-bar span {
  display: block;
  height: 100%;
  border-radius: inherit;
  /* The gradient is sized to the full bar so a given Kp always lands on the
     same colour, instead of every reading being stretched across green→red. */
  background: linear-gradient(90deg, #22c55e, #facc15, #fb7185);
  background-size: var(--aurora-track, 100%) 100%;
  box-shadow: 0 0 24px var(--glow);
  transition: width 420ms ease;
}

.space-updated {
  margin-top: 10px;
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 700;
}

.climate-search {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.climate-search button {
  padding: 0 18px;
}

.climate-result {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
}

.climate-stat {
  min-height: 140px;
  padding: 18px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.1);
}

.climate-stat strong {
  display: block;
  margin-top: 10px;
  font-size: 1.7rem;
}

.detail-modal[hidden] {
  display: none;
}

.detail-modal {
  position: fixed;
  top: 0;
  left: 0;
  /* Sized to the *dynamic* viewport rather than inset:0, which resolves
     against the large (URL-bar-hidden) viewport on mobile Safari and centred
     the card against a box taller than what is actually on screen. JS
     overrides these while pinch or accessibility zoom is active so the whole
     card stays reachable inside the visual viewport. */
  width: 100vw;
  width: 100dvw;
  height: 100vh;
  height: 100dvh;
  z-index: 20;
  /* Flex (not grid) so the card's percentage max-height resolves against the
     overlay. */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 18px;
  overscroll-behavior: contain;
}

/* Freeze the page behind the modal *without moving it*. An earlier version
   switched the body to position:fixed with a negative top offset, which
   yanked the document out of flow the moment the popup opened and made the
   card visibly jump upward a beat after it appeared. Plain overflow:hidden on
   both the root and the body stops the scroll; iOS ignores it on the body
   alone, which is why the root carries it too. */
html.modal-open,
body.modal-open {
  overflow: hidden;
  touch-action: none;
}

.modal-backdrop {
  position: absolute;
  inset: 0;
  border: 0;
  background: rgba(2, 6, 23, 0.72);
  backdrop-filter: blur(10px);
  cursor: pointer;
  /* Drags on the backdrop must not pan the frozen page behind it. */
  touch-action: none;
}

.modal-card {
  position: relative;
  width: min(620px, 100%);
  max-height: min(720px, 100%);
  overflow: auto;
  overscroll-behavior: contain;
  /* The overlay sets touch-action:none to freeze the page; the card itself
     still has to scroll its own overflow. */
  touch-action: pan-y;
  padding: 24px;
}

#modalTitle {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: nowrap;
}
#modalTitle .weather-icon {
  width: 30px;
  height: 30px;
  margin: 0;
  flex-shrink: 0;
}

.alert-raw-desc {
  white-space: pre-wrap;
  word-break: break-word;
  font-family: inherit;
  font-size: 0.84rem;
  line-height: 1.6;
}

.modal-close {
  position: absolute;
  top: 14px;
  right: 14px;
  width: 36px;
  height: 36px;
  border: 1px solid var(--border);
  border-radius: 50%;
  color: var(--text);
  background: rgba(255, 255, 255, 0.17);
  cursor: pointer;
  font-size: 1.45rem;
  line-height: 1;
}

.modal-summary {
  color: var(--muted);
  line-height: 1.55;
}

.detail-list {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin-top: 16px;
}

/* ── Rich alert modal ── */
.alert-modal-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 10px;
}
.alert-modal-tag {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  background: rgba(148, 163, 184, 0.15);
  border: 1px solid rgba(148, 163, 184, 0.3);
  color: var(--muted);
}
/* The event chip leads the tag row and shows the alert's official color. */
.alert-modal-event-tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.alert-modal-swatch {
  width: 10px;
  height: 10px;
  border-radius: 3px;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.45);
}
.alert-modal-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
  font-size: 0.74rem;
  color: var(--muted);
  margin-bottom: 14px;
  padding-bottom: 12px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.alert-modal-area {
  flex: 1;
  text-align: right;
}
.alert-hazard-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 12px;
}
.alert-hazard-tag {
  padding: 3px 9px;
  border-radius: 10px;
  font-size: 0.72rem;
  font-weight: 700;
  background: rgba(251, 146, 60, 0.15);
  border: 1px solid rgba(251, 146, 60, 0.3);
  color: #fb923c;
}
.alert-section {
  margin-bottom: 12px;
}
.alert-section-label {
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 4px;
}
.alert-section p {
  line-height: 1.55;
  color: var(--text);
  font-size: 0.88rem;
}
.alert-level-table {
  margin: 14px 0;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 14px;
  overflow: hidden;
}
.alert-level-title {
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 8px 12px 6px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  background: rgba(255, 255, 255, 0.1);
}
.alert-level-row {
  display: flex;
  gap: 12px;
  padding: 9px 12px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  background: rgba(255, 255, 255, 0.15);
  opacity: 0.6;
}
.alert-level-row:last-child {
  border-bottom: none;
}
.alert-level-row.active-level {
  opacity: 1;
  background: rgba(255, 255, 255, 0.05);
}
.alert-level-label {
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  white-space: nowrap;
  padding-top: 1px;
  min-width: 76px;
}
.alert-level-desc {
  font-size: 0.8rem;
  color: var(--muted);
  line-height: 1.45;
}
.alert-level-row.active-level .alert-level-desc {
  color: var(--text);
}
.alert-tips {
  margin-top: 14px;
  padding: 12px 14px;
  border-left: 3px solid rgba(251, 146, 60, 0.6);
  background: rgba(251, 146, 60, 0.06);
  border-radius: 0 8px 8px 0;
}
.alert-tips-title {
  font-size: 0.8rem;
  font-weight: 700;
  margin-bottom: 8px;
  color: var(--text);
}
.alert-tips ul {
  margin: 0;
  padding-left: 18px;
}
.alert-tips li {
  font-size: 0.82rem;
  color: var(--muted);
  line-height: 1.5;
  margin-bottom: 4px;
}
.alert-tips p {
  font-size: 0.82rem;
  color: var(--muted);
  line-height: 1.5;
}
.alert-full-text {
  margin-top: 14px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.1);
}
.alert-full-text summary {
  padding: 10px 12px;
  cursor: pointer;
  font-size: 0.74rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
.alert-full-text[open] summary {
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.alert-full-text pre {
  margin: 0;
  padding: 10px 12px;
  white-space: pre-wrap;
  word-break: break-word;
  font-family: inherit;
  font-size: 0.8rem;
  line-height: 1.55;
  color: var(--muted);
  max-height: 320px;
  overflow-y: auto;
}

.lsr-cat-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-right: 5px;
  border-radius: 50%;
  vertical-align: 1px;
}

.alert-modal-source {
  margin-top: 14px;
  font-size: 0.7rem;
  color: rgba(148, 163, 184, 0.5);
}
.popup-alert-details-btn {
  display: block;
  width: 100%;
  margin-top: 10px;
  padding: 7px 12px;
  background: rgba(59, 130, 246, 0.15);
  border: 1px solid rgba(59, 130, 246, 0.35);
  border-radius: 10px;
  color: #93c5fd;
  font-size: 0.78rem;
  font-weight: 700;
  cursor: pointer;
  text-align: center;
  transition: background 120ms ease;
}
.popup-alert-details-btn:hover {
  background: rgba(59, 130, 246, 0.28);
}

.detail-list div {
  padding: 12px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.1);
}

/* ── Daily forecast modal ── */
.day-modal-hero {
  display: flex;
  align-items: center;
  gap: 18px;
  margin: 4px 0 16px;
}

.day-modal-temps {
  display: flex;
  align-items: baseline;
  gap: 6px;
  flex-shrink: 0;
}

.day-modal-high {
  font-size: 2.6rem;
  font-weight: 800;
  line-height: 1;
}

.day-modal-low {
  color: var(--muted);
  font-size: 1.4rem;
  font-weight: 700;
}

.day-modal-hero-meta {
  min-width: 0;
}

.day-modal-hero-meta .fwi-badge {
  font-size: 0.66rem;
  padding: 3px 9px;
  margin-bottom: 6px;
}

.day-modal-hero-meta p {
  margin: 0;
  color: var(--muted);
  font-size: 0.86rem;
  line-height: 1.4;
}

.day-night-split {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 10px;
  margin-bottom: 12px;
}

.dn-card {
  padding: 13px 14px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.1);
}

.dn-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.dn-head .weather-icon {
  width: 46px;
  height: 46px;
  margin: 0;
  flex-shrink: 0;
}

.dn-label {
  display: block;
  color: var(--accent-2);
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.dn-cond {
  margin: 6px 0 10px;
  font-size: 0.88rem;
  font-weight: 700;
  line-height: 1.35;
}

.dn-rows {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  color: var(--muted);
  font-size: 0.76rem;
  font-weight: 700;
}

.dn-rows span,
.day-modal-stat {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.dn-rows .ui-icon,
.day-modal-stat .ui-icon {
  width: 14px;
  height: 14px;
  flex: 0 0 14px;
  margin: 0;
  border: none;
  border-radius: 0;
  background: none;
  color: var(--accent-2);
}

.dn-rows .ui-icon svg,
.day-modal-stat .ui-icon svg {
  width: 12px;
  height: 12px;
  transform: none;
}

.day-modal-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(125px, 1fr));
  gap: 8px;
  margin-bottom: 12px;
}

.day-modal-stat {
  align-items: flex-start;
  gap: 8px;
  padding: 10px 12px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.1);
}

.day-modal-stat .ui-icon {
  margin-top: 2px;
}

.day-modal-stat small {
  display: block;
  color: var(--muted);
  font-size: 0.64rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.day-modal-stat strong {
  display: block;
  margin-top: 2px;
  font-size: 0.92rem;
}

.day-modal-fwi {
  margin-bottom: 12px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.1);
  overflow: hidden;
}

.day-modal-fwi summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  cursor: pointer;
  list-style: none;
  transition: background 140ms ease;
}

.day-modal-fwi summary::-webkit-details-marker {
  display: none;
}

.day-modal-fwi summary:hover {
  background: rgba(255, 255, 255, 0.04);
}

.day-modal-fwi .fwi-badge {
  font-size: 0.66rem;
  padding: 3px 9px;
}

.day-modal-fwi-sum {
  flex: 1;
  min-width: 0;
}

.day-modal-fwi-sum strong {
  display: block;
  font-size: 0.86rem;
}

.day-modal-fwi-sum small {
  display: block;
  margin-top: 2px;
  color: var(--muted);
  font-size: 0.74rem;
  line-height: 1.4;
}

.day-modal-fwi-chevron {
  flex-shrink: 0;
  color: var(--muted);
  transition: transform 180ms ease;
}

.day-modal-fwi[open] .day-modal-fwi-chevron {
  transform: rotate(180deg);
}

.fwi-breakdown {
  padding: 4px 14px 12px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.fwi-break-row {
  padding: 10px 0 2px;
}

.fwi-break-row + .fwi-break-row {
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}

.fwi-break-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}

.fwi-break-label {
  font-size: 0.8rem;
  font-weight: 700;
}

.fwi-break-label small {
  color: var(--muted);
  font-weight: 600;
}

.fwi-break-pts {
  font-size: 0.74rem;
  font-weight: 800;
  white-space: nowrap;
}

.fwi-break-bar {
  height: 5px;
  margin: 6px 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  overflow: hidden;
}

.fwi-break-bar span {
  display: block;
  height: 100%;
  border-radius: 999px;
}

.fwi-break-note {
  margin: 0 0 6px;
  color: var(--muted);
  font-size: 0.74rem;
  line-height: 1.4;
}

.day-modal-risks {
  display: grid;
  gap: 8px;
  margin-bottom: 12px;
}

.day-modal-risk {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid;
  border-radius: 10px;
}

.day-modal-risk-icon .ui-icon {
  width: 18px;
  height: 18px;
  flex: 0 0 18px;
  margin: 2px 0 0;
  border: none;
  background: none;
  color: inherit;
}

.day-modal-risk-icon .ui-icon svg {
  width: 15px;
  height: 15px;
  transform: none;
}

.day-modal-risk strong {
  display: block;
  font-size: 0.84rem;
}

.day-modal-risk small {
  display: block;
  margin-top: 2px;
  color: var(--muted);
  font-size: 0.74rem;
  line-height: 1.4;
}

.day-modal-text {
  padding: 12px 14px;
  border-left: 3px solid color-mix(in srgb, var(--accent-2) 55%, transparent);
  border-radius: 0 10px 10px 0;
  background: rgba(255, 255, 255, 0.1);
}

.day-modal-text p {
  margin: 8px 0 0;
  color: var(--muted);
  font-size: 0.84rem;
  line-height: 1.55;
}

@keyframes screenIn {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes cardIn {
  from {
    opacity: 0;
    transform: translateY(6px) scale(0.99);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

@keyframes menuIn {
  from {
    opacity: 0;
    transform: translateY(-4px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes floatSoft {
  0%, 100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-5px);
  }
}

@keyframes markerPulse {
  0% {
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 42%, transparent), 0 0 22px var(--glow);
  }
  100% {
    box-shadow: 0 0 0 16px color-mix(in srgb, var(--accent) 0%, transparent), 0 0 22px var(--glow);
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
    transition-duration: 0.001ms !important;
  }
}

@media (max-width: 1120px) {
  .metric-grid,
  .daily-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .hero-grid,
  .aviation-grid {
    grid-template-columns: 1fr;
  }

  .comfort-tile {
    min-height: auto;
  }
}

@media (max-width: 720px) {
  .shell {
    width: min(100% - 20px, 1440px);
    padding-top: max(18px, env(safe-area-inset-top));
  }

  .topbar {
    gap: 10px;
    margin-bottom: 14px;
  }

  .topbar,
  .section-head {
    align-items: flex-start;
    flex-direction: column;
  }

  .brand-mark {
    width: 32px;
    height: 32px;
  }

  .top-actions {
    gap: 8px;
  }

  .top-actions,
  .location-search,
  .climate-search,
  .select-wrap {
    width: 100%;
  }

  /* Search row stays as a flex row — input fills, button shrinks */
  .location-search {
    display: flex;
    flex-wrap: nowrap;
  }

  .location-search input {
    flex: 1;
    min-width: 0;
    width: auto;
  }

  .location-search button {
    flex-shrink: 0;
    width: auto;
    padding: 0 12px;
  }

  .climate-search input,
  .climate-search button {
    width: 100%;
  }

  /* Icon buttons and refresh stay compact in a row */
  .locate-me-btn,
  .notify-btn {
    min-height: 38px;
    padding: 0 10px;
  }

  .refresh-button {
    min-height: 38px;
    padding: 0 12px;
  }

  /* Compact status badge */
  .status-badge {
    font-size: 0.65rem;
    padding: 7px 10px;
  }

  .forecast-banner {
    min-height: 430px;
    grid-template-columns: 1fr;
  }

  .temp-lockup {
    justify-self: start;
    text-align: left;
  }

  .metric-grid,
  .climate-result,
  .space-readouts,
  dl {
    grid-template-columns: 1fr;
  }

  .daily-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .daily-card {
    min-height: auto;
    padding: 12px;
  }


  .current-icon {
    margin: 0 0 8px 0;
    width: 96px;
    height: 96px;
  }

  .tabs {
    border-radius: 14px;
  }

  .tab {
    padding: 0 12px;
  }
}

/* ── Locate Me button ─────────────────────────────── */
.locate-me-btn,
.notify-btn,
.settings-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  min-height: 42px;
  padding: 0 14px;
  color: var(--text);
  border: 1px solid color-mix(in srgb, var(--accent-2) 55%, transparent);
  border-radius: 14px;
  background: color-mix(in srgb, var(--accent-2) 15%, rgba(255, 255, 255, 0.12));
  cursor: pointer;
  font-weight: 800;
  font: inherit;
  white-space: nowrap;
  transition: transform 160ms ease, border-color 180ms ease, background 180ms ease, box-shadow 180ms ease;
}
.locate-me-btn:hover,
.notify-btn:hover,
.settings-btn:hover {
  transform: translateY(-1px);
  box-shadow: 0 10px 24px color-mix(in srgb, var(--accent-2) 18%, transparent);
}
.locate-me-btn:disabled,
.notify-btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  transform: none;
}

/* ═══════════════════════════════════════════════
   SETTINGS DIALOG
   Units and map customization. Rows are label-on-the-left / control-on-the-
   right, collapsing to stacked blocks once the row can no longer fit both.
═══════════════════════════════════════════════ */
.settings-section {
  margin-bottom: 22px;
}

.settings-section:last-child {
  margin-bottom: 0;
}

.settings-section h3 {
  margin: 0 0 4px;
  font-size: 0.95rem;
  font-weight: 800;
}

.settings-section-note {
  margin: 0 0 12px;
  color: var(--muted);
  font-size: 0.76rem;
  line-height: 1.45;
}

.settings-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 10px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
}

.settings-row:last-child {
  border-bottom: 0;
}

.settings-row-text {
  display: grid;
  gap: 2px;
  min-width: 0;
}

.settings-row-label {
  font-size: 0.86rem;
  font-weight: 700;
}

.settings-row-note {
  color: var(--muted);
  font-size: 0.7rem;
  line-height: 1.4;
}

.settings-choice {
  display: flex;
  flex: none;
  gap: 4px;
  padding: 3px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.05);
}

.settings-choice-wrap {
  flex-wrap: wrap;
}

.settings-choice button {
  min-height: 30px;
  padding: 0 11px;
  color: var(--muted);
  border: 0;
  border-radius: 9px;
  background: transparent;
  cursor: pointer;
  font: inherit;
  font-size: 0.74rem;
  font-weight: 800;
  white-space: nowrap;
  transition: color 140ms ease, background 140ms ease;
}

.settings-choice button:hover {
  color: var(--text);
}

.settings-choice button.active {
  color: #04121a;
  background: var(--accent);
}

/* Toggle switch */
.settings-switch {
  position: relative;
  flex: none;
  width: 46px;
  height: 26px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  cursor: pointer;
  transition: background 160ms ease, border-color 160ms ease;
}

.settings-switch.on {
  border-color: color-mix(in srgb, var(--accent) 70%, transparent);
  background: color-mix(in srgb, var(--accent) 62%, transparent);
}

.settings-switch-knob {
  position: absolute;
  top: 50%;
  left: 3px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #f8fbff;
  translate: 0 -50%;
  transition: left 160ms ease;
}

.settings-switch.on .settings-switch-knob {
  left: 23px;
}

.settings-favorites {
  display: grid;
  gap: 6px;
}

.settings-favorite {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.04);
  font-size: 0.82rem;
  font-weight: 700;
}

.settings-favorite span {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.settings-favorite button {
  flex: none;
  min-height: 28px;
  padding: 0 10px;
  color: #fca5a5;
  border: 1px solid rgba(248, 113, 113, 0.4);
  border-radius: 8px;
  background: rgba(248, 113, 113, 0.12);
  cursor: pointer;
  font: inherit;
  font-size: 0.7rem;
  font-weight: 800;
}

.settings-empty {
  margin: 0;
  color: var(--muted);
  font-size: 0.78rem;
  line-height: 1.5;
}

/* Narrow screens: the control moves under its label rather than squeezing. */
@media (max-width: 560px) {
  .settings-row,
  .settings-row-stack {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
  }
  .settings-choice {
    justify-content: space-between;
    flex-wrap: wrap;
  }
  .settings-choice button {
    flex: 1;
    padding: 0 8px;
  }
  .settings-switch {
    align-self: flex-start;
  }
}

/* Subscribed state — green treatment plus a status dot so it's obvious
   notifications are already on (clicking again turns them off). */
.notify-btn.subscribed {
  color: #d1fae5;
  border-color: color-mix(in srgb, #34d399 62%, transparent);
  background: color-mix(in srgb, #34d399 20%, rgba(255, 255, 255, 0.12));
}
.notify-btn.subscribed::before {
  content: "";
  width: 7px;
  height: 7px;
  flex-shrink: 0;
  border-radius: 50%;
  background: #34d399;
  box-shadow: 0 0 8px rgba(52, 211, 153, 0.85);
}
.notify-btn.subscribed:hover {
  box-shadow: 0 10px 24px color-mix(in srgb, #34d399 22%, transparent);
}

/* ── Map locate button overlay ────────────────────── */
/* Sits in the floating HUD bar alongside the panel toggles, so it is laid
   out by that flex row rather than pinned to a corner of the map. */
.map-locate-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 32px;
  padding: 0 12px;
  color: var(--text);
  border: 1px solid color-mix(in srgb, var(--accent-2) 55%, transparent);
  border-radius: 999px;
  background: rgba(6, 12, 30, 0.82);
  backdrop-filter: blur(14px);
  cursor: pointer;
  font: inherit;
  font-size: 0.76rem;
  font-weight: 800;
  transition: transform 160ms ease, background 160ms ease;
}
.map-locate-btn:hover {
  transform: translateY(-1px);
  background: color-mix(in srgb, var(--accent-2) 20%, rgba(2, 6, 23, 0.9));
}
.map-locate-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ── User GPS dot on map ──────────────────────────── */
.user-location-dot {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #38bdf8;
  border: 3px solid #fff;
  box-shadow: 0 0 0 4px rgba(56, 189, 248, 0.35);
  animation: gpsRipple 2s ease-in-out infinite;
}
@keyframes gpsRipple {
  0%, 100% { box-shadow: 0 0 0 4px rgba(56, 189, 248, 0.35); }
  50% { box-shadow: 0 0 0 10px rgba(56, 189, 248, 0.08); }
}

/* ── SPC threats grid ─────────────────────────────── */
.spc-threat-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  margin-top: 12px;
}
.spc-threat-item {
  padding: 12px 10px;
  border-radius: 14px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: rgba(255, 255, 255, 0.1);
  text-align: center;
}
.spc-threat-label {
  display: block;
  color: var(--muted);
  font-size: 0.68rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: 6px;
}
.spc-threat-val {
  display: block;
  font-size: 1.15rem;
  font-weight: 800;
}
.spc-torn { border-color: rgba(220, 38, 38, 0.35); }
.spc-wind { border-color: rgba(251, 146, 60, 0.35); }
.spc-hail { border-color: rgba(34, 197, 94, 0.35); }
.spc-torn .spc-threat-val { color: #f87171; }
.spc-wind .spc-threat-val { color: #fb923c; }
.spc-hail .spc-threat-val { color: #4ade80; }

/* ── Climate History layout ───────────────────────── */
.hist-loc-name {
  margin: 0;
  color: var(--muted);
  font-size: 0.82rem;
  font-weight: 700;
}

.climate-layout {
  display: grid;
  grid-template-columns: 320px minmax(0, 1fr);
  gap: 16px;
  align-items: start;
}

.climate-calendar-tile {
  padding: 18px;
  position: sticky;
  top: 16px;
  min-width: 0;
}

.climate-result-panel {
  display: grid;
  gap: 14px;
  min-width: 0;
  overflow: hidden;
}

.climate-message {
  padding: 28px;
  color: var(--muted);
  font-size: 0.95rem;
  font-weight: 700;
  text-align: center;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.1);
}

/* ── Historical calendar ──────────────────────────── */
.hist-cal-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 12px;
}

.hist-cal-title {
  display: flex;
  gap: 6px;
  flex: 1;
  justify-content: center;
}

.hist-select {
  min-height: 34px;
  padding: 0 8px;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--text);
  background: rgba(255, 255, 255, 0.15);
  border: 1px solid var(--border);
  border-radius: 10px;
}

.hist-cal-btn {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border: 1px solid var(--border);
  border-radius: 10px;
  color: var(--text);
  background: rgba(255, 255, 255, 0.12);
  cursor: pointer;
  font-size: 1.5rem;
  line-height: 1;
  font: inherit;
  transition: background 140ms ease, border-color 140ms ease;
}
.hist-cal-btn:hover:not(:disabled) {
  background: color-mix(in srgb, var(--accent) 18%, rgba(255, 255, 255, 0.14));
  border-color: color-mix(in srgb, var(--accent) 50%, transparent);
}
.hist-cal-btn:disabled {
  opacity: 0.35;
  cursor: default;
}

.hist-cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 3px;
}

.hist-dow {
  padding: 5px 2px;
  text-align: center;
  color: var(--muted);
  font-size: 0.65rem;
  font-weight: 800;
  text-transform: uppercase;
}

.hist-day {
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  border-radius: 10px;
  font-size: 0.8rem;
  font-weight: 700;
  border: 0;
  background: transparent;
  color: var(--text);
  cursor: pointer;
  font: inherit;
  transition: background 120ms ease, color 120ms ease;
}
.hist-day:hover:not(.disabled) {
  background: color-mix(in srgb, var(--accent) 20%, rgba(255, 255, 255, 0.12));
}
.hist-day.selected {
  background: #ffffff;
  color: #12181f;
  font-weight: 700;
  border: 1px solid transparent;
}
.hist-day.disabled,
.hist-day:empty {
  opacity: 0.22;
  cursor: default;
  pointer-events: none;
}

.hist-cal-note {
  margin: 10px 0 0;
  color: var(--muted);
  font-size: 0.68rem;
  font-weight: 700;
  text-align: center;
}

/* ── Historical result hero ───────────────────────── */
.hist-hero {
  padding: 22px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  overflow: hidden;
}

.hist-hero-left {
  min-width: 0;
  flex: 1 1 auto;
  overflow: hidden;
}

.hist-hero-left .eyebrow {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.hist-hero-icon {
  flex: 0 0 auto;
}

.hist-hero-icon .weather-icon {
  width: 88px;
  height: 88px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.hist-hero-icon .weather-icon svg {
  width: 88px;
  height: 88px;
}

.hist-temp-range {
  display: flex;
  align-items: baseline;
  gap: 4px;
  margin: 8px 0;
  font-size: 3rem;
  font-weight: 800;
  line-height: 1;
}
.hist-temp-hi { color: #fb923c; }
.hist-temp-lo { color: #7dd3fc; }
.hist-temp-sep { color: var(--muted); }

.hist-feels {
  color: var(--muted);
  font-size: 0.9rem;
  font-weight: 700;
  margin-top: 6px;
}

/* ── Historical hourly strip ──────────────────────── */
.hist-hourly-panel {
  padding: 18px;
  overflow: hidden;
  min-width: 0;
}

.hist-hourly-strip {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 100px;
  gap: 8px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  padding-bottom: 6px;
  margin-top: 12px;
}

.hist-hourly-item {
  padding: 10px 8px;
  text-align: center;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.1);
  font-size: 0.75rem;
}
.hist-hourly-time {
  color: var(--muted);
  font-weight: 800;
  font-size: 0.68rem;
  text-transform: uppercase;
  margin-bottom: 2px;
}

.hist-hourly-icon {
  margin: 2px auto;
  display: flex;
  align-items: center;
  justify-content: center;
}

.hist-hourly-icon .weather-icon {
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.hist-hourly-icon .weather-icon svg {
  width: 30px;
  height: 30px;
}
.hist-hourly-temp {
  font-size: 1.2rem;
  font-weight: 800;
  margin-bottom: 4px;
}
.hist-hourly-cond {
  color: var(--muted);
  font-size: 0.65rem;
  line-height: 1.2;
  margin-bottom: 4px;
}
.hist-hourly-wind {
  color: var(--accent-2);
  font-weight: 700;
  font-size: 0.7rem;
}
.hist-hourly-precip {
  color: #7dd3fc;
  font-weight: 700;
  font-size: 0.7rem;
  margin-top: 3px;
}

/* ── Historical stats grid ────────────────────────── */
.hist-stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 10px;
}

.hist-stat-card {
  padding: 16px;
  min-height: 100px;
  min-width: 0;
  overflow: hidden;
}

.hist-stat-head {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.hist-stat-head .ui-icon {
  flex: 0 0 auto;
}

.hist-stat-head .eyebrow {
  margin: 0;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.hist-stat-card strong {
  display: block;
  margin: 8px 0 4px;
  font-size: 1.4rem;
  font-weight: 800;
}
.hist-stat-card small {
  color: var(--muted);
  font-size: 0.75rem;
  font-weight: 700;
}

@media (max-width: 1120px) {
  .climate-layout {
    grid-template-columns: 1fr;
  }
  .climate-calendar-tile {
    position: static;
    min-width: 0;
    max-width: 100%;
  }
  .climate-result-panel {
    min-width: 0;
    max-width: 100%;
    overflow: hidden;
  }
}

@media (max-width: 720px) {
  .hist-stats-grid {
    grid-template-columns: repeat(2, 1fr);
  }
  .spc-threat-grid {
    grid-template-columns: repeat(3, 1fr);
  }
  .locate-me-btn span,
  .notify-btn span,
  .settings-btn span {
    display: none;
  }

  /* Prevent calendar from overflowing on narrow screens */
  .climate-calendar-tile {
    padding: 14px;
    overflow: hidden;
  }

  .hist-cal-nav {
    gap: 6px;
  }

  .hist-cal-title {
    gap: 4px;
    min-width: 0;
  }

  .hist-select {
    min-width: 0;
    max-width: 100%;
    font-size: 0.78rem;
    padding: 0 6px;
  }

  /* Keep hourly strip scrollable within its tile */
  .hist-hourly-panel {
    overflow: hidden;
  }

  .hist-hourly-strip {
    -webkit-overflow-scrolling: touch;
  }
}

@media (max-width: 480px) {
  .hist-stats-grid {
    grid-template-columns: 1fr 1fr;
  }

  .hist-temp-range {
    font-size: 2.4rem;
  }

  .hist-cal-nav {
    flex-wrap: nowrap;
    gap: 4px;
  }

  .hist-cal-btn {
    width: 30px;
    height: 30px;
    font-size: 1.2rem;
    flex-shrink: 0;
  }

  .hist-cal-title {
    flex: 1;
    min-width: 0;
    justify-content: center;
  }

  .hist-select {
    flex: 1;
    min-width: 0;
    font-size: 0.72rem;
    padding: 0 4px;
    min-height: 30px;
  }

  .climate-calendar-tile {
    padding: 10px;
  }
}

/* ═══════════════════════════════════════════════
   HOURLY CHART & METRIC SWITCHER
═══════════════════════════════════════════════ */
.hourly-metric-switcher {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.hourly-metric-switcher button {
  display: flex;
  align-items: center;
  gap: 5px;
  min-height: 32px;
  padding: 0 11px;
  color: var(--muted);
  border: 1px solid rgba(255, 255, 255, 0.13);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.12);
  cursor: pointer;
  font: inherit;
  font-size: 0.76rem;
  font-weight: 700;
  transition: transform 160ms ease, border-color 180ms ease, background 180ms ease, color 180ms ease;
}

.hourly-metric-switcher button:hover {
  transform: translateY(-1px);
  color: var(--text);
  border-color: rgba(255, 255, 255, 0.28);
}

.hourly-metric-switcher button.active {
  color: #12181f;
  border-color: transparent;
  background: #ffffff;
}

.hourly-chart-wrap {
  position: relative;
  height: 185px;
  margin: 12px 0 8px;
  border-radius: 16px;
  overflow: hidden;
  background: transparent;
  border: none;
}

@media (max-width: 600px) {
  .hourly-chart-wrap {
    height: 160px;
  }
}

.hourly-chart-svg {
  display: block;
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  touch-action: none;
}

.hourly-footer {
  display: flex;
  justify-content: flex-end;
  margin-top: 10px;
}

.hourly-footer #updatedAt,
#updatedAt {
  color: var(--muted);
  font-size: 0.76rem;
  font-weight: 700;
}

/* ═══════════════════════════════════════════════
   MAP LAYER CONTROLS
═══════════════════════════════════════════════ */
.map-controls-wrap {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 14px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 18px;
  /* Opaque enough to stay readable over bright radar returns and satellite
     imagery — the old translucent white washed out over pale basemaps. */
  background: rgba(6, 12, 30, 0.86);
  backdrop-filter: blur(18px);
  box-shadow: 0 18px 40px rgba(2, 6, 23, 0.45);
}

.layer-group-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.layer-group-label {
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: rgba(232, 240, 255, 0.4);
  min-width: 52px;
  flex-shrink: 0;
}

.layer-pills-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.layer-pills-row button {
  min-height: 30px;
  padding: 0 12px;
  color: var(--muted);
  border: 1px solid rgba(255, 255, 255, 0.13);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.13);
  cursor: pointer;
  font: inherit;
  font-size: 0.76rem;
  font-weight: 700;
  white-space: nowrap;
  transition: transform 160ms ease, border-color 180ms ease, background 180ms ease, color 180ms ease;
}

.layer-pills-row button:hover {
  transform: translateY(-1px);
  color: var(--text);
  border-color: rgba(255, 255, 255, 0.3);
}

.layer-pills-row button.active {
  color: #12181f;
  border-color: transparent;
  background: #ffffff;
}

/* SPC sub-controls */
.sub-controls {
  padding: 10px 0 2px;
  border-top: 1px solid rgba(255, 255, 255, 0.07);
  display: flex;
  flex-direction: column;
  gap: 8px;
  animation: subCtrlIn 200ms ease both;
}

.sub-controls[hidden] {
  display: none;
}

@keyframes subCtrlIn {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}

.ctrl-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.ctrl-row[hidden] {
  display: none;
}

.ctrl-label {
  font-size: 0.66rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: rgba(232, 240, 255, 0.45);
  min-width: 36px;
  flex-shrink: 0;
}

.ctrl-btn-group {
  display: flex;
  gap: 5px;
  flex-wrap: wrap;
}

.ctrl-btn-group button {
  min-height: 28px;
  padding: 0 10px;
  color: var(--muted);
  border: 1px solid rgba(255, 255, 255, 0.11);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.12);
  cursor: pointer;
  font: inherit;
  font-size: 0.74rem;
  font-weight: 700;
  transition: all 160ms ease;
}

.ctrl-btn-group button:hover {
  color: var(--text);
  border-color: rgba(255, 255, 255, 0.26);
  background: rgba(255, 255, 255, 0.06);
}

.ctrl-btn-group button.active {
  color: #ffa040;
  border-color: rgba(255, 160, 64, 0.5);
  background: rgba(255, 160, 64, 0.12);
}

/* Radar timeline row */
.radar-timeline-row {
  gap: 10px;
}

.play-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  min-height: 30px;
  padding: 0 12px;
  color: var(--text);
  border: 1px solid color-mix(in srgb, var(--accent) 50%, transparent);
  border-radius: 14px;
  background: color-mix(in srgb, var(--accent) 14%, rgba(255, 255, 255, 0.13));
  cursor: pointer;
  font: inherit;
  font-size: 0.78rem;
  font-weight: 800;
  transition: all 160ms ease;
  flex-shrink: 0;
}

.play-btn:hover {
  background: color-mix(in srgb, var(--accent) 22%, rgba(255, 255, 255, 0.16));
}

.timeline-slider,
.opacity-slider {
  flex: 1;
  min-width: 100px;
  accent-color: var(--accent);
  height: 4px;
  border: none;
  background: transparent;
  padding: 0;
}

.timeline-label {
  min-width: 60px;
  color: var(--muted);
  font-size: 0.76rem;
  font-weight: 700;
  text-align: right;
  white-space: nowrap;
}

/* Radar frames past now (the extrapolated tail of the reflectivity timeline)
   read in the accent colour, so it is obvious when the scrubber has left the
   observations behind. */
.timeline-label.forecast-frame,
.map-frame-scrubber .timeline-label.forecast-frame {
  color: var(--accent);
}

/* Opacity row */
#radarOpacityLabel {
  min-width: 34px;
  color: var(--muted);
  font-size: 0.74rem;
  font-weight: 700;
}

/* ═══════════════════════════════════════════════
   BOTTOM FRAME SCRUBBER (overlay on map)
   Play/pause, the scrubber and the frame's valid time, so the animation is
   usable without opening the Layers panel over the map. The MRMS product
   picker stays in the panel.
═══════════════════════════════════════════════ */
.map-frame-scrubber {
  position: absolute;
  /* Docked directly above the Mapbox credit strip. Both the strip's height and
     this bar's own height are layout constants (see .map-stage) so the legends
     can be stacked on top of it without guessing. */
  bottom: var(--map-dock-bottom);
  /* The scale bar and attribution live in the bottom corners, so the bar stops
     short of them rather than running edge to edge over the top. */
  left: 12px;
  right: 12px;
  z-index: 5;
  box-sizing: border-box;
  height: var(--map-scrubber-h);
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 14px;
  background: rgba(6, 12, 30, 0.86);
  backdrop-filter: blur(14px);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 999px;
}

.map-frame-scrubber[hidden] { display: none; }

.map-frame-scrubber .timeline-slider {
  flex: 1;
  min-width: 60px;
  margin: 0;
}

.map-frame-scrubber .timeline-label {
  min-width: 68px;
  color: rgba(232, 240, 255, 0.82);
  font-size: 0.72rem;
  /* The MRMS valid time can be long ("03:20 UTC 07/29"); it truncates rather
     than squeezing the scrubber on a phone. */
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Square icon-only play button for the scrubber; the panel's copy keeps its
   text label. */
.play-btn-icon {
  gap: 0;
  min-height: 28px;
  width: 28px;
  padding: 0;
  justify-content: center;
  border-radius: 50%;
}

.play-btn .pause-glyph { display: none; }
.play-btn.playing .play-glyph { display: none; }
.play-btn.playing .pause-glyph { display: block; }

/* Lift the legends clear of the scrubber while it's on screen. */
.map-stage:has(.map-frame-scrubber:not([hidden])) .spc-legend-box,
.map-stage:has(.map-frame-scrubber:not([hidden])) .mrms-legend-box {
  bottom: var(--map-legend-bottom);
}

@media (max-width: 600px) {
  /* A phone gets a shorter bar, and the attribution disc needs a little more
     room than the desktop credit line, so both constants move together. */
  .map-stage {
    --map-credit-h: 24px;
    --map-scrubber-h: 34px;
    --map-bottom-gap: 6px;
  }
  body.map-fullscreen .map-stage {
    --map-credit-h: calc(24px + env(safe-area-inset-bottom, 0px));
  }
  .map-frame-scrubber {
    left: 6px;
    right: 6px;
    padding: 0 10px;
    gap: 8px;
  }
  .map-frame-scrubber .timeline-label {
    min-width: 0;
    max-width: 84px;
    font-size: 0.68rem;
  }
}

/* ═══════════════════════════════════════════════
   SPC LEGEND BOX (overlay on map)
═══════════════════════════════════════════════ */
.spc-legend-box {
  position: absolute;
  bottom: var(--map-dock-bottom);
  right: 12px;
  z-index: 3;
  padding: 8px 10px;
  background: rgba(6, 12, 30, 0.92);
  backdrop-filter: blur(14px);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 14px;
  font-size: 0.66rem;
  min-width: 110px;
  pointer-events: none;
  animation: legendIn 200ms ease both;
}

@keyframes legendIn {
  from { opacity: 0; transform: scale(0.94) translateY(4px); }
  to { opacity: 1; transform: scale(1) translateY(0); }
}

.spc-legend-box[hidden] { display: none; }

/* Popups read above the legend boxes (z-index 10), and the legends fade out
   entirely while a popup is open — on phones the two stacked on top of each
   other and made the alert popup unreadable. */
.mapboxgl-popup {
  z-index: 11;
}

.map-stage:has(.mapboxgl-popup) .spc-legend-box,
.map-stage:has(.mapboxgl-popup) .mrms-legend-box {
  /* The legendIn entry animation fills 'both', so it must be cleared for
     opacity to take effect; closing the popup re-runs it as a fade-in. */
  animation: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 160ms ease, visibility 160ms ease;
}

.mrms-legend-box {
  position: absolute;
  bottom: var(--map-dock-bottom);
  left: 12px;
  z-index: 3;
  padding: 8px 8px 9px;
  background: rgba(6, 12, 30, 0.96);
  backdrop-filter: blur(14px);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 14px;
  font-size: 0.66rem;
  min-width: 170px;
  max-width: min(46vw, 240px);
  max-height: 220px;
  overflow-y: auto;
  pointer-events: none;
  animation: legendIn 200ms ease both;
}
.mrms-legend-box[hidden] { display: none; }

@media (max-width: 600px) {
  .mrms-legend-box {
    min-width: 0;
    /* Two legends can be on screen at once (radar left, SPC right). Capping
       each at just under half the width keeps them from meeting in the middle
       on a narrow phone. */
    max-width: min(44vw, 150px);
    left: 6px;
    padding: 5px 6px 6px;
    font-size: 0.62rem;
    /* The stage is short in landscape; never let a legend run past the top of
       the map or under the scrubber it is sitting on. */
    max-height: min(190px, 42vh);
  }
  .mrms-legend-box .legend-title {
    font-size: 0.68rem;
    margin-bottom: 6px;
  }
  .mrms-legend-box .legend-subtitle {
    font-size: 0.60rem;
    margin-bottom: 4px;
  }
  .mrms-legend-box .legend-gradient {
    width: 100%;
    height: 10px;
  }
  /* The tick values used to be dropped on phones because the box was crowded
     with a decode/status subtitle. That subtitle is gone, and a colour ramp
     with no numbers on it is not a legend — so the values stay, just smaller. */
  .mrms-legend-box .legend-ticks {
    font-size: 0.55rem;
  }
  .mrms-legend-box .legend-tick small {
    display: none;
  }
  .mrms-legend-section {
    margin-bottom: 8px;
  }
  .mrms-legend-section:last-child {
    margin-bottom: 0;
  }
  .spc-legend-box {
    max-width: min(44vw, 140px);
    min-width: 0;
    right: 6px;
    padding: 6px 8px;
    font-size: 0.62rem;
    max-height: min(190px, 42vh);
    overflow-y: auto;
    pointer-events: none;
  }

  /* An open panel covers most of a phone's map, legends included. Rather than
     leave a legend half-visible behind it, fade it out for as long as the panel
     is up — the same treatment a popup gets. */
  .map-stage:has(#mapControlsPanel:not([hidden])) .mrms-legend-box,
  .map-stage:has(#mapControlsPanel:not([hidden])) .spc-legend-box,
  .map-stage:has(#mapSidebar:not([hidden])) .mrms-legend-box,
  .map-stage:has(#mapSidebar:not([hidden])) .spc-legend-box {
    animation: none;
    opacity: 0;
    visibility: hidden;
    transition: opacity 160ms ease, visibility 160ms ease;
  }
}

.mrms-select {
  flex: 1;
  min-width: 0;
  background: rgba(255, 255, 255, 0.07);
  color: var(--text);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 10px;
  padding: 4px 8px;
  font-size: 0.78rem;
  cursor: pointer;
  appearance: auto;
}
.mrms-select:focus {
  outline: 1px solid rgba(56, 189, 248, 0.6);
}
.mrms-select option {
  background: #0f172a;
  color: #e8f0ff;
}

.satellite-select {
  width: min(100%, 290px);
}

.radar-palette-row {
  align-items: center;
}

.palette-file-btn,
.palette-reset-btn {
  min-height: 28px;
  padding: 5px 10px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.1);
  color: var(--text);
  cursor: pointer;
  font: inherit;
  font-size: 0.72rem;
  font-weight: 750;
}

.palette-file-btn:hover,
.palette-reset-btn:hover {
  border-color: rgba(56, 189, 248, 0.56);
  background: rgba(56, 189, 248, 0.12);
}

.palette-file-name {
  min-width: 0;
  max-width: 150px;
  overflow: hidden;
  color: var(--muted);
  font-size: 0.68rem;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.popup-mrms {
  color: rgba(56, 189, 248, 0.9);
}

.legend-title {
  font-size: 0.62rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  margin-bottom: 8px;
}

.legend-row {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 4px;
  color: rgba(232, 240, 255, 0.8);
}

.legend-swatch {
  width: 18px;
  height: 8px;
  border-radius: 2px;
  flex-shrink: 0;
}

.mrms-legend-box .legend-title {
  font-size: 0.72rem;
  font-weight: 900;
  letter-spacing: 0.035em;
  color: rgba(232, 240, 255, 0.62);
  margin-bottom: 8px;
  line-height: 1;
}

.mrms-legend-section {
  margin-bottom: 10px;
}

.mrms-legend-section:last-child {
  margin-bottom: 0;
}

.mrms-legend-box .legend-subtitle {
  font-size: 0.62rem;
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: 0.045em;
  color: rgba(232, 240, 255, 0.62);
  margin-bottom: 5px;
  line-height: 1.05;
}

.mrms-legend-box .legend-gradient {
  width: 160px;
  max-width: 100%;
  height: 11px;
  border-radius: 3px;
}

.mrms-legend-box .legend-ticks {
  width: 160px;
  max-width: 100%;
  /* Content-sized ticks spread across the bar: the old equal grid columns
     let the nowrap labels overlap each other when the box narrowed. */
  display: flex;
  justify-content: space-between;
  gap: 4px;
  align-items: start;
  color: rgba(232, 240, 255, 0.88);
  font-size: 0.6rem;
  line-height: 1.12;
  margin-top: 3px;
}

.mrms-legend-box .legend-tick {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.mrms-legend-box .legend-tick:not(:first-child):not(:last-child) {
  align-items: center;
}

.mrms-legend-box .legend-tick:last-child {
  align-items: flex-end;
}

.mrms-legend-box .legend-tick small {
  display: block;
  color: rgba(232, 240, 255, 0.88);
  font-size: 0.56rem;
  line-height: 1.05;
}

/* ═══════════════════════════════════════════════
   MAP OPTIONS (basemap selector)
═══════════════════════════════════════════════ */
.map-options-details {
  margin-top: 10px;
}

.map-options-details[open] .chevron {
  transform: rotate(180deg);
}

.map-options-summary {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.11);
  color: var(--muted);
  cursor: pointer;
  font: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  list-style: none;
  transition: background 160ms ease, color 160ms ease, border-color 160ms ease;
  user-select: none;
}

.map-options-summary:hover {
  background: rgba(255, 255, 255, 0.06);
  color: var(--text);
  border-color: rgba(255, 255, 255, 0.2);
}

.map-options-summary::-webkit-details-marker { display: none; }

.chevron {
  margin-left: auto;
  transition: transform 250ms ease;
}

.map-options-body {
  padding: 12px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-top: 0;
  border-radius: 0 0 8px 8px;
  background: rgba(255, 255, 255, 0.11);
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.map-opt-group {
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.map-opt-label {
  font-size: 0.66rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
}

.basemap-btns {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.basemap-btns button {
  min-height: 30px;
  padding: 0 11px;
  color: var(--muted);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.12);
  cursor: pointer;
  font: inherit;
  font-size: 0.76rem;
  font-weight: 700;
  transition: all 160ms ease;
}

.basemap-btns button:hover {
  color: var(--text);
  border-color: rgba(255, 255, 255, 0.26);
}

.basemap-btns button.active {
  color: var(--accent-2);
  border-color: color-mix(in srgb, var(--accent-2) 55%, transparent);
  background: color-mix(in srgb, var(--accent-2) 12%, rgba(255, 255, 255, 0.14));
}

/* ═══════════════════════════════════════════════
   MAPBOX POPUP ANIMATIONS & STYLING
═══════════════════════════════════════════════ */
.mapboxgl-popup-content {
  background: rgba(6, 12, 30, 0.96) !important;
  border: 1px solid rgba(255, 255, 255, 0.18) !important;
  border-radius: 12px !important;
  padding: 11px 13px !important;
  color: #f8fbff !important;
  font-family: "Inter", system-ui, sans-serif !important;
  font-size: 0.84rem !important;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255,255,255,0.05) !important;
  backdrop-filter: blur(20px) !important;
  max-width: 290px !important;
  /* Keep popups short enough to fit the visible map on phones — taller
     popups forced panning the map down to read or dismiss them. */
  max-height: 42vh !important;
  overflow-y: auto !important;
  animation: popupIn 220ms cubic-bezier(0.34, 1.56, 0.64, 1) both !important;
}

@keyframes popupIn {
  from {
    opacity: 0;
    transform: scale(0.88) translateY(6px);
  }
  to {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
}

.mapboxgl-popup-close-button {
  color: rgba(255, 255, 255, 0.55) !important;
  font-size: 18px !important;
  width: 28px !important;
  height: 28px !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  border-radius: 50% !important;
  top: 8px !important;
  right: 8px !important;
  transition: background 150ms ease, color 150ms ease !important;
}

.mapboxgl-popup-close-button:hover {
  background: rgba(255, 255, 255, 0.12) !important;
  color: #fff !important;
}

.mapboxgl-popup-anchor-bottom .mapboxgl-popup-tip {
  border-top-color: rgba(6, 12, 30, 0.96) !important;
}

.mapboxgl-popup-anchor-top .mapboxgl-popup-tip {
  border-bottom-color: rgba(6, 12, 30, 0.96) !important;
}

/* Popup content helpers */
.popup-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.popup-icon {
  width: 28px;
  height: 28px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
  flex-shrink: 0;
}

.popup-title {
  font-weight: 700;
  font-size: 0.88rem;
  color: #f8fbff;
  flex: 1;
  padding-right: 24px;
}

.popup-subtitle {
  font-size: 0.74rem;
  color: rgba(232, 240, 255, 0.6);
  margin-top: 1px;
}

.popup-stat {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 5px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

.popup-stat:last-child {
  border-bottom: none;
}

.popup-key {
  color: rgba(232, 240, 255, 0.55);
  font-size: 0.76rem;
}

.popup-val {
  font-weight: 700;
  font-size: 0.82rem;
  text-align: right;
}

.popup-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.popup-note {
  margin-top: 8px;
  padding: 7px 9px;
  border-radius: 10px;
  font-size: 0.76rem;
  color: rgba(232, 240, 255, 0.7);
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.07);
  line-height: 1.45;
}

/* Compact alert popup: header + one wrapping chip row + details button. */
.popup-compact .popup-header {
  margin-bottom: 7px;
  padding-bottom: 6px;
}

.popup-compact .popup-icon {
  width: 24px;
  height: 24px;
  font-size: 0.85rem;
}

.popup-chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.popup-chip {
  display: inline-block;
  max-width: 100%;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(255, 255, 255, 0.06);
  color: rgba(232, 240, 255, 0.85);
  font-size: 0.7rem;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.popup-compact .popup-alert-details-btn {
  margin-top: 8px;
  padding: 6px 10px;
}

/* ═══════════════════════════════════════════════
   ALERT POPUP NAVIGATION
═══════════════════════════════════════════════ */
.popup-alert-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 6px 0 10px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.09);
  margin-bottom: 8px;
}
.popup-nav-btn {
  background: rgba(255, 255, 255, 0.09);
  border: 1px solid rgba(255, 255, 255, 0.16);
  color: #e8f0ff;
  border-radius: 50%;
  width: 28px;
  height: 28px;
  font-size: 1.15rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.14s;
  padding: 0;
}
.popup-nav-btn:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.18);
}
.popup-nav-btn:disabled {
  opacity: 0.28;
  cursor: not-allowed;
}
.popup-nav-counter {
  font-size: 0.78rem;
  color: rgba(232, 240, 255, 0.55);
  min-width: 40px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* ═══════════════════════════════════════════════
   LSR MARKER ICONS
═══════════════════════════════════════════════ */
.lsr-marker {
  width: 34px;
  height: 34px;
  border-radius: 14px;
  border: 2px solid rgba(255,255,255,0.85);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 2px 10px rgba(0,0,0,0.55);
  transition: transform 160ms ease, box-shadow 160ms ease;
  color: #fff;
  background: #ef4444;
  animation: lsrPop 300ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
.lsr-marker svg {
  display: block;
  flex-shrink: 0;
}

@keyframes lsrPop {
  from { transform: scale(0); opacity: 0; }
  to { transform: scale(1); opacity: 1; }
}

.lsr-marker:hover {
  transform: scale(1.2);
  box-shadow: 0 4px 16px rgba(0,0,0,0.6);
}

/* ═══════════════════════════════════════════════
   LOCATION MARKER (blue circle)
═══════════════════════════════════════════════ */
.location-blue-dot {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #3b82f6;
  border: 3px solid #fff;
  box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.35), 0 2px 8px rgba(0,0,0,0.4);
  cursor: pointer;
  transition: box-shadow 160ms ease;
}

.location-blue-dot:hover {
  box-shadow: 0 0 0 5px rgba(59, 130, 246, 0.42), 0 3px 12px rgba(0,0,0,0.48);
}

/* ═══════════════════════════════════════════════
   FIRE WEATHER POPUP ACCENTS
═══════════════════════════════════════════════ */
.popup-fire { background: rgba(239, 68, 68, 0.15); border-color: rgba(239, 68, 68, 0.35); }
.popup-alert { background: rgba(251, 146, 60, 0.15); border-color: rgba(251, 146, 60, 0.35); }
.popup-rain { background: rgba(96, 165, 250, 0.15); border-color: rgba(96, 165, 250, 0.35); }
.popup-spc { background: rgba(250, 204, 21, 0.1); border-color: rgba(250, 204, 21, 0.25); }

/* ═══════════════════════════════════════════════
   FAIR WEATHER INDEX BADGE IN DAILY CARD
═══════════════════════════════════════════════ */
.fwi-badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 6px;
  border-radius: 999px;
  font-size: 0.58rem;
  font-weight: 800;
  letter-spacing: 0.03em;
  white-space: nowrap;
  flex-shrink: 0;
}

.spc-risk-badge {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 2px 6px;
  border-radius: 999px;
  font-size: 0.58rem;
  font-weight: 800;
  letter-spacing: 0.03em;
  white-space: nowrap;
  flex-shrink: 0;
}

/* ═══════════════════════════════════════════════
   MAP SIDEBAR ENHANCEMENTS
═══════════════════════════════════════════════ */
.sidebar-tile {
  padding: 14px 16px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 18px;
  /* Matches the layer panel's glass so both float legibly over the map. */
  background: rgba(6, 12, 30, 0.86);
  backdrop-filter: blur(18px);
  box-shadow: 0 18px 40px rgba(2, 6, 23, 0.45);
}

.sidebar-icon {
  display: inline-flex;
  align-items: center;
  vertical-align: middle;
  margin-right: 3px;
  opacity: 0.8;
}

.sidebar-tile .eyebrow {
  margin-bottom: 6px;
}

.sidebar-tile h3 {
  margin-bottom: 4px;
  font-size: 0.95rem;
}

.sidebar-chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-top: 8px;
}

.sidebar-chip {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 7px 8px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--panel-soft);
  text-align: center;
  flex: 1;
  /* Long values must wrap inside the chip instead of spilling out of the
     sidebar tile (e.g. SPC probability strings on narrow sidebars). */
  min-width: 0;
  overflow: hidden;
}

.sidebar-chip-label {
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 3px;
  max-width: 100%;
  overflow-wrap: anywhere;
}

.sidebar-chip-val {
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 400;
  line-height: 1.2;
  max-width: 100%;
  overflow-wrap: anywhere;
}

/* ═══════════════════════════════════════════════
   LAYER PILLS (keep original for backward compat)
═══════════════════════════════════════════════ */
.layer-pills {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.layer-pills button {
  min-height: 34px;
  color: var(--muted);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.14);
  cursor: pointer;
  font-size: 0.78rem;
  font-weight: 800;
  transition: transform 160ms ease, border-color 180ms ease, background 180ms ease, color 180ms ease;
}

.layer-pills button.active {
  color: #12181f;
  border-color: transparent;
  background: #ffffff;
}

.layer-pills button:hover {
  transform: translateY(-1px);
}

/* ═══════════════════════════════════════════════
   ALERT CARD — animated entry
═══════════════════════════════════════════════ */
.alert-row {
  animation: cardIn 280ms ease both;
}

.alert-row:nth-child(2) { animation-delay: 40ms; }
.alert-row:nth-child(3) { animation-delay: 80ms; }
.alert-row:nth-child(4) { animation-delay: 120ms; }

/* ═══════════════════════════════════════════════
   MODAL ANIMATION UPGRADE
═══════════════════════════════════════════════ */
.modal-card {
  animation: modalCardIn 260ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

@keyframes modalCardIn {
  from {
    opacity: 0;
    transform: scale(0.92) translateY(12px);
  }
  to {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
}

/* ═══════════════════════════════════════════════
   RESPONSIVE UPDATES FOR NEW ELEMENTS
═══════════════════════════════════════════════ */
@media (max-width: 720px) {
  .hourly-metric-switcher {
    justify-content: flex-start;
  }

  .layer-group-row {
    flex-wrap: wrap;
  }

  .map-controls-wrap {
    padding: 10px;
  }

  /* Phones: there is no room for the section heading alongside three control
     pills, and wrapping it to its own row eats a third of the map. Keep it in
     the accessibility tree (it is the section's aria-labelledby target) but
     take it out of the layout, and let the panels use the full width. */
  .map-hud {
    top: 8px;
    left: 8px;
    right: 8px;
    /* Deliberately not reset to a fixed inset: the HUD still has to stop above
       the scrubber and the credit strip (see .map-hud). */
    gap: 6px;
  }

  .map-hud-bar {
    gap: 6px;
    padding-right: 42px;
  }

  /* Four pills have to share a phone's width without wrapping to a second row
     that eats into the map. */
  .map-hud-btn,
  .map-locate-btn {
    min-height: 30px;
    padding: 0 9px;
    font-size: 0.7rem;
    gap: 4px;
  }

  .hud-label-wide { display: none; }
  .hud-label-narrow { display: inline; }

  .map-hud-title {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }

  .map-hud-panels {
    flex-direction: column;
  }

  #mapControlsPanel,
  .map-sidebar {
    width: 100%;
    margin-left: 0;
  }

  .hourly-metric-switcher button {
    padding: 0 9px;
    font-size: 0.72rem;
  }

  .layer-pills-row {
    gap: 5px;
  }

  .layer-pills-row button {
    min-height: 28px;
    padding: 0 10px;
    font-size: 0.72rem;
  }
}

/* Keep long alert/SPC labels inside popups and level tables on narrow screens. */
.alert-level-row {
  display: grid;
  grid-template-columns: minmax(0, 112px) minmax(0, 1fr);
  align-items: start;
}
.alert-level-label,
.alert-level-desc {
  min-width: 0;
  overflow-wrap: anywhere;
}
.alert-level-label {
  white-space: normal;
}
.popup-header > div:not(.popup-icon) {
  min-width: 0;
  flex: 1 1 auto;
}
.popup-title,
.popup-subtitle,
.popup-val {
  min-width: 0;
  overflow-wrap: anywhere;
}
.popup-title {
  padding-right: 8px;
}
.popup-stat {
  align-items: flex-start;
}
.popup-val {
  max-width: 62%;
}
.ctrl-btn-group button small {
  opacity: 0.7;
  font-size: 0.68em;
}

/* Experimental products (e.g. satellite precip rate) — flagged so the data is
   never mistaken for a validated, operational product. */
.ctrl-btn-group button.is-experimental {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.ctrl-btn-group button .exp-badge {
  padding: 1px 4px;
  border: 1px solid rgba(120, 200, 255, 0.45);
  border-radius: 5px;
  background: rgba(120, 200, 255, 0.14);
  color: #78c8ff;
  font-size: 0.62em;
  font-weight: 800;
  letter-spacing: 0.04em;
  line-height: 1.35;
}

.ctrl-btn-group button.is-experimental.active .exp-badge {
  border-color: rgba(255, 160, 64, 0.5);
  background: rgba(255, 160, 64, 0.16);
  color: #ffa040;
}

/* ==========================================================================
   COASTAL SCREEN — rip currents, tides and waves
   ========================================================================== */

.coastal-body {
  display: grid;
  /* Grid items default to min-width:auto, and the wide <select> labels inside
     the pickers would otherwise stretch the whole column past the viewport. */
  grid-template-columns: minmax(0, 1fr);
  gap: 16px;
}

.coastal-empty {
  padding: 40px clamp(22px, 4vw, 44px);
  text-align: center;
}

.coastal-empty-icon {
  display: inline-flex;
  margin-bottom: 12px;
  color: var(--accent-2);
}

.coastal-empty-icon .ui-icon {
  width: 40px;
  height: 40px;
  flex: 0 0 40px;
  color: inherit;
}

.coastal-empty-icon .ui-icon svg {
  width: 34px;
  height: 34px;
}

.coastal-empty h3 {
  margin: 0 0 8px;
  font-size: 1.35rem;
  font-weight: 600;
  letter-spacing: -0.02em;
}

.coastal-empty p {
  max-width: 56ch;
  margin: 0 auto;
  line-height: 1.55;
}

.coastal-presets {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin-top: 20px;
}

.coastal-preset {
  padding: 8px 15px;
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--panel-soft);
  font: inherit;
  font-size: 0.82rem;
  font-weight: 700;
  cursor: pointer;
  transition: background 180ms ease, border-color 180ms ease, transform 150ms ease;
}

.coastal-preset:hover {
  transform: translateY(-1px);
  border-color: color-mix(in srgb, var(--accent) 45%, var(--border));
  background: color-mix(in srgb, var(--accent) 14%, var(--panel-soft));
}

.beach-picker {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--panel-soft);
}

.beach-picker .mrms-select,
.coastal-panel .mrms-select {
  min-width: 0;
  max-width: 100%;
}

.beach-picker .ctrl-label {
  flex: none;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.6);
}

.coastal-hero {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: 16px;
}

.rip-tile,
.sea-tile,
.coastal-panel {
  padding: 22px;
}

.rip-tile {
  display: flex;
  flex-direction: column;
  gap: 14px;
  border-color: color-mix(in srgb, var(--rip-color, var(--accent)) 40%, var(--border));
}

.rip-badge {
  padding: 4px 10px;
  color: rgba(255, 255, 255, 0.82);
  border: 1px solid rgba(255, 255, 255, 0.24);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.09);
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.rip-dial {
  display: grid;
  place-items: center;
  gap: 4px;
  padding: 26px 16px;
  border: 1px solid color-mix(in srgb, var(--rip-color) 46%, transparent);
  border-radius: 20px;
  background:
    radial-gradient(circle at 50% 30%, color-mix(in srgb, var(--rip-color) 26%, transparent), transparent 72%),
    rgba(2, 6, 23, 0.34);
  box-shadow: inset 0 0 42px color-mix(in srgb, var(--rip-color) 20%, transparent);
}

.rip-level {
  font-family: var(--font-display);
  font-size: clamp(2.6rem, 7vw, 3.8rem);
  font-weight: 500;
  line-height: 0.92;
  letter-spacing: -0.01em;
  color: var(--rip-color);
  text-shadow: 0 0 28px color-mix(in srgb, var(--rip-color) 45%, transparent);
}

.rip-dial small {
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.62);
}

.rip-advice {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.55;
}

.rip-note {
  margin: 0;
  padding: 10px 12px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.06);
  font-size: 0.76rem;
  line-height: 1.5;
}

.rip-outlook {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(88px, 1fr));
  gap: 8px;
  margin-top: auto;
}

.rip-day {
  padding: 10px 8px;
  text-align: center;
  border: 1px solid color-mix(in srgb, var(--rip-color) 38%, transparent);
  border-radius: 12px;
  background: color-mix(in srgb, var(--rip-color) 12%, rgba(255, 255, 255, 0.04));
}

.rip-day strong {
  display: block;
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.62);
}

.rip-day span {
  display: block;
  margin-top: 3px;
  font-size: 0.94rem;
  font-weight: 800;
  color: var(--rip-color);
}

.sea-rows {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 14px;
  margin-top: 16px;
}

.sea-rows dd {
  font-size: 1.02rem;
}

.coastal-panel .section-head {
  margin-bottom: 14px;
  gap: 12px;
}

.coastal-panel .section-head h3 {
  margin: 0;
  font-size: 1.18rem;
  font-weight: 600;
  letter-spacing: -0.02em;
}

.coastal-panel .section-head span {
  font-size: 0.76rem;
  text-align: right;
}

.tide-chips {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px;
}

.tide-chip {
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--panel-soft);
}

.tide-chip.high {
  border-color: rgba(125, 211, 252, 0.42);
  background: rgba(56, 189, 248, 0.12);
}

.tide-chip.low {
  border-color: rgba(196, 181, 253, 0.38);
  background: rgba(167, 139, 250, 0.1);
}

.tide-chip-type {
  display: block;
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.62);
}

.tide-chip strong {
  display: block;
  margin: 3px 0 2px;
  font-family: var(--font-display);
  font-size: 1.6rem;
  font-weight: 400;
  line-height: 1;
}

.tide-chip small {
  color: rgba(255, 255, 255, 0.66);
  font-size: 0.72rem;
}

/* The charts are emitted as fixed-viewBox SVG and set their own aspect-ratio
   inline, so they scale uniformly instead of stretching the labels. */
.coastal-chart {
  margin: 16px auto 0;
  touch-action: pan-y;
}

.chart-readout {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: 4px 10px;
  margin: 14px 0 0;
  min-height: 1.3em;
}

.chart-readout strong {
  font-size: 0.95rem;
  font-weight: 800;
  color: var(--accent-2);
}

.chart-readout span {
  font-size: 0.74rem;
  color: rgba(255, 255, 255, 0.55);
}

.coastal-chart svg {
  display: block;
  overflow: visible;
}

.coastal-footnote {
  margin: 14px 0 0;
  font-size: 0.76rem;
  line-height: 1.5;
}

.coastal-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 7px;
  margin: 10px 0 0;
  font-size: 0.74rem;
}

.coastal-legend .swatch {
  width: 16px;
  height: 3px;
  border-radius: 999px;
  background: var(--c);
}

.coastal-legend .swatch.dashed {
  margin-left: 10px;
  background: repeating-linear-gradient(90deg, var(--c) 0 4px, transparent 4px 7px);
}

.wave-mode-switch {
  display: flex;
  flex: none;
  gap: 4px;
  padding: 3px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--panel-soft);
}

.wave-mode-switch button {
  padding: 5px 12px;
  color: rgba(255, 255, 255, 0.68);
  border: none;
  border-radius: 999px;
  background: transparent;
  font: inherit;
  font-size: 0.74rem;
  font-weight: 700;
  cursor: pointer;
  transition: background 160ms ease, color 160ms ease;
}

.wave-mode-switch button.active {
  color: #04121f;
  background: var(--accent-2);
}

.wave-days {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(76px, 1fr));
  gap: 10px;
  margin-top: 6px;
}

.wave-day {
  display: grid;
  justify-items: center;
  gap: 7px;
  padding: 12px 6px;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--panel-soft);
}

.wave-day strong {
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.66);
}

.wave-bar {
  display: flex;
  align-items: flex-end;
  width: 22px;
  height: 92px;
  overflow: hidden;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.1);
}

.wave-bar span {
  width: 100%;
  border-radius: inherit;
  background: linear-gradient(180deg, #7dd3fc, #2563eb);
}

.wave-day-value {
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 400;
  line-height: 1;
}

.wave-day small {
  color: rgba(255, 255, 255, 0.6);
  font-size: 0.68rem;
  text-align: center;
}

.surf-periods,
.waters-periods {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(268px, 1fr));
  gap: 12px;
}

.surf-period,
.waters-period {
  padding: 16px;
  border: 1px solid var(--border);
  border-radius: 16px;
  background: var(--panel-soft);
}

.surf-period h4,
.waters-period h4 {
  margin: 0 0 10px;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
}

.surf-period dl {
  grid-template-columns: minmax(0, 1fr);
  gap: 9px;
}

.surf-period dt {
  font-size: 0.66rem;
}

.surf-period dd {
  margin-top: 2px;
  font-size: 0.86rem;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.86);
}

.surf-prose dd {
  font-weight: 500;
  line-height: 1.5;
}

.waters-period p {
  margin: 0;
  font-size: 0.86rem;
  line-height: 1.55;
}

.waters-synopsis {
  margin: 0 0 14px;
  padding: 13px 15px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.06);
  font-size: 0.86rem;
  line-height: 1.55;
}

@media (max-width: 900px) {
  .coastal-hero {
    grid-template-columns: minmax(0, 1fr);
  }

  .coastal-panel .section-head {
    flex-wrap: wrap;
  }

  .coastal-panel .section-head span {
    text-align: left;
  }
}

@media (max-width: 600px) {
  .rip-tile,
  .sea-tile,
  .coastal-panel {
    padding: 17px;
  }

  .beach-picker {
    flex-wrap: wrap;
  }
}
