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

:root {
  /* Shared iPhone-dark rain-dawn glass theme: near-black depth, misty sage glass, and soft peach dawn highlights. */
  --bg-0: #05070a;
  --bg-1: #121722;
  --card-bg: rgba(221, 246, 229, 0.034);
  --card-bg-strong: rgba(221, 246, 229, 0.065);
  --card-border: rgba(190, 230, 199, 0.16);
  --card-shadow: 0 18px 44px rgba(0, 0, 0, 0.32);
  --text: #f3f7ef;
  --text-dim: rgba(243, 247, 239, 0.66);
  --accent: #9bd8b3;
  --accent-strong: #ffdca8;
  --accent-bg: rgba(255, 220, 168, 0.11);

  --precip-fg: #eaf6ff;
  --precip-bg: rgba(16, 34, 48, 0.55);

  /* Raw RGB triplets (no alpha) so rules that need a custom, one-off alpha
     can do rgba(var(--fg-rgb), 0.42) etc. and still flip correctly between
     themes, instead of hardcoding rgba(243,247,239,X) everywhere - which is
     exactly what made the map-overlay contrast bug from the last round
     tedious to track down. --glass-tint-rgb is the "dark tint" used by the
     map's floating glass cards (legend, corner buttons, layer menu,
     Leaflet's attribution) - those need to flip to a *light* tint in day
     mode, verified with the same contrast math as before (see .mapGlassCard
     below), since they float over the map/basemap rather than the app's own
     background. */
  --fg-rgb: 243, 247, 239;
  --glass-tint-rgb: 5, 7, 10;

  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --mesh-line: rgba(190, 230, 199, 0.082);
  --mesh-glow: var(--accent-strong);
}

/* ---------- Day (light) theme ----------
   Not just an inversion: kept the same sage/amber accent hues throughout so
   the app still reads as "the same app", but deepened accent-strong (amber)
   and accent (sage) enough to work as text/icon color on a light background
   - the original pale peach/sage (#ffdca8 / #9bd8b3) measure ~1.2-1.6:1
   against white, nowhere near WCAG's 3:1 floor for UI components, since
   they were only ever used at those tints for *backgrounds*, never text.
   Verified with the same contrast-ratio math as the outdoor-legibility
   pass: body text >=15:1, map-glass icons >=7:1 against the darkest
   realistic map content, and the deepened amber >=3.4:1 even in the
   worst-case dark-map-under-light-glass scenario. */
:root[data-theme="light"] {
  --bg-0: #f4f0e6;
  --bg-1: #fbf8f2;
  --card-bg: rgba(35, 70, 48, 0.045);
  --card-bg-strong: rgba(35, 70, 48, 0.075);
  --card-border: rgba(47, 122, 82, 0.22);
  --card-shadow: 0 14px 34px rgba(80, 65, 35, 0.16);
  --text: #23261f;
  --text-dim: rgba(35, 38, 31, 0.7);
  --accent: #2f7a52;
  --accent-strong: #8a5112;
  --accent-bg: rgba(138, 81, 18, 0.14);

  --precip-fg: #06304a;
  --precip-bg: rgba(196, 226, 242, 0.75);

  --fg-rgb: 35, 38, 31;
  --glass-tint-rgb: 255, 255, 255;

  --mesh-line: rgba(47, 122, 82, 0.1);
}

html, body {
  height: 100%;
  min-height: 100%;
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  background:
    radial-gradient(120% 55% at 50% -10%, rgba(255, 220, 168, 0.045), transparent 62%),
    linear-gradient(180deg, rgba(0, 0, 0, 0.14) 0%, transparent 35%, rgba(0, 0, 0, 0.1) 100%),
    linear-gradient(160deg, var(--bg-1) 0%, var(--bg-0) 100%);
  color: var(--text);
  overflow-x: hidden;
  overflow-y: auto;
  transition: background 0.3s var(--ease), color 0.3s var(--ease);
}
:root[data-theme="light"] body {
  background:
    radial-gradient(120% 55% at 50% -10%, rgba(138, 81, 18, 0.05), transparent 62%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.5) 0%, transparent 35%, rgba(255, 255, 255, 0.3) 100%),
    linear-gradient(160deg, var(--bg-1) 0%, var(--bg-0) 100%);
}

/* ---------- Touch ripple ---------- */
#rippleLayer {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 501;
  overflow: hidden;
}
.ripple {
  position: absolute;
  width: 14px;
  height: 14px;
  margin-left: -7px;
  margin-top: -7px;
  border: 2px solid rgba(var(--fg-rgb), 0.6);
  border-radius: 50%;
  animation: rippleAnim 0.7s var(--ease) forwards;
}
@keyframes rippleAnim {
  from { transform: scale(0.3); opacity: 0.65; }
  to { transform: scale(7); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .ripple { display: none; }
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

#meshBg {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}
#meshSvg {
  width: 100%;
  height: 100%;
  display: block;
}
.meshLine {
  fill: none;
  stroke: var(--mesh-line);
  stroke-width: 1;
}

#app {
  position: relative;
  z-index: 1;
  min-height: 100vh;
  height: 100vh;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 10px;
  padding-top: max(10px, env(safe-area-inset-top));
  padding-bottom: max(10px, env(safe-area-inset-bottom));
  padding-left: max(10px, env(safe-area-inset-left));
  padding-right: max(10px, env(safe-area-inset-right));
  /* Set explicitly here (not just relying on inheritance from html/body)
     so elements like #cityName/#currentTemp that have no color rule of
     their own always pick up a theme-correct value from their nearest
     ancestor, regardless of how any given browser recomputes color on the
     document root when the theme attribute changes. */
  color: var(--text);
  transition: color 0.3s var(--ease);
}

/* ---------- Top bar ---------- */
#topbar {
  flex: 0 0 auto;
  padding: 12px 16px;
  position: relative;
  overflow: hidden;
  background:
    linear-gradient(145deg, rgba(243, 247, 239, 0.095), rgba(190, 230, 199, 0.038) 44%, rgba(190, 230, 199, 0.022)),
    var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 24px;
  box-shadow:
    inset 0 1px 0 rgba(243, 247, 239, 0.14),
    inset 0 -22px 42px rgba(243, 247, 239, 0.018),
    var(--card-shadow);
  backdrop-filter: blur(9px) saturate(1.18);
  -webkit-backdrop-filter: blur(9px) saturate(1.18);
  transition: background 0.3s var(--ease), border-color 0.3s var(--ease), box-shadow 0.3s var(--ease);
}
#topbar::before {
  content: "";
  position: absolute;
  inset: 1px 1px auto 1px;
  height: 52%;
  border-radius: inherit;
  background: linear-gradient(180deg, rgba(243, 247, 239, 0.095), transparent 76%);
  pointer-events: none;
}
#topbar > * { position: relative; z-index: 1; }

#homeLink {
  display: inline-block;
  margin-bottom: 8px;
  color: var(--text-dim);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: none;
  text-decoration: none;
  transition: color 0.2s var(--ease);
}
#homeLink:hover,
#homeLink:focus-visible { color: var(--text); }
#homeLink:focus-visible {
  outline: 2px solid var(--accent-strong);
  outline-offset: 4px;
  border-radius: 4px;
}

/* Day/night toggle - top-right corner of the topbar, opposite the home
   link. Two icons (sun/moon) both live in the DOM; app.js toggles which is
   visible to match the *current* theme, same pattern already used for the
   radar play/pause icons. */
#themeToggle {
  position: absolute;
  top: 12px;
  right: 16px;
  z-index: 2;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1px solid rgba(255, 246, 235, 0.3);
  background: linear-gradient(145deg, rgba(243, 247, 239, 0.13), rgba(190, 230, 199, 0.055));
  color: var(--text);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(243, 247, 239, 0.13), 0 2px 10px rgba(0,0,0,0.18);
  backdrop-filter: blur(9px) saturate(1.12);
  -webkit-backdrop-filter: blur(9px) saturate(1.12);
  transition: background 0.2s ease, transform 0.15s var(--ease), color 0.3s var(--ease);
}
#themeToggle:hover { background: rgba(190, 230, 199, 0.14); }
#themeToggle:active { transform: scale(0.9); }
#themeIconSun.hidden,
#themeIconMoon.hidden { display: none; }

#locationBlock {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding-right: 40px; /* keep weather text clear of the theme toggle */
}

#searchToggle {
  background: linear-gradient(145deg, rgba(243, 247, 239, 0.13), rgba(190, 230, 199, 0.055));
  border: 1px solid rgba(255, 246, 235, 0.3);
  color: var(--text);
  border-radius: 50%;
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(243, 247, 239, 0.13), 0 2px 10px rgba(0,0,0,0.18);
  backdrop-filter: blur(9px) saturate(1.12);
  -webkit-backdrop-filter: blur(9px) saturate(1.12);
  transition: transform 0.2s var(--ease), background 0.2s ease;
}
#searchToggle:hover { background: rgba(190, 230, 199, 0.14); }
#searchToggle:active { transform: scale(0.9); }
#searchToggle.open { transform: rotate(90deg); }

#cityName {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: 0.3px;
  color: var(--text);
}
.wx-icon {
  width: 30px;
  height: 30px;
  display: block;
  filter: drop-shadow(0 3px 6px rgba(0,0,0,0.35));
}
#currentTemp {
  font-size: 30px;
  font-weight: 300;
  color: var(--text);
}
#currentCondition {
  font-size: 15px;
  color: rgba(var(--fg-rgb), 0.9);
}
#hiLo {
  font-size: 14px;
  color: rgba(var(--fg-rgb), 0.78);
}

/* Animated expand/collapse instead of an abrupt display:none swap */
#searchBox {
  max-width: 420px;
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  transform: translateY(-6px);
  transition: max-height 0.4s var(--ease), opacity 0.25s ease, transform 0.35s var(--ease), margin-top 0.4s var(--ease);
}
#searchBox.open {
  margin-top: 10px;
  max-height: 420px;
  opacity: 1;
  transform: translateY(0);
}
#searchInput {
  width: 100%;
  padding: 12px 14px;
  border-radius: 12px;
  border: 1px solid rgba(190, 230, 199, 0.12);
  outline: none;
  background: linear-gradient(180deg, rgba(243, 247, 239, 0.052), rgba(var(--glass-tint-rgb), 0.2));
  color: var(--text);
  font-size: 16px;
  box-shadow: inset 0 1px 0 rgba(243,247,239,0.085), inset 0 1px 4px rgba(0,0,0,0.3);
  backdrop-filter: blur(9px) saturate(1.12);
  -webkit-backdrop-filter: blur(9px) saturate(1.12);
  transition: box-shadow 0.2s ease, background 0.2s ease;
}
#searchInput:focus { background: rgba(var(--glass-tint-rgb), 0.22); box-shadow: inset 0 1px 4px rgba(0,0,0,0.3), 0 0 0 2px rgba(190, 230, 199, 0.13); }
#searchInput::placeholder { color: rgba(var(--fg-rgb), 0.55); }
#searchResults {
  margin-top: 6px;
  background: rgba(var(--glass-tint-rgb), 0.82);
  border: 1px solid var(--card-border);
  border-radius: 16px;
  overflow: hidden;
  backdrop-filter: blur(13px) saturate(1.16);
  -webkit-backdrop-filter: blur(13px) saturate(1.16);
  box-shadow: var(--card-shadow);
}
.searchResultItem {
  padding: 12px 14px;
  cursor: pointer;
  font-size: 14px;
  border-bottom: 1px solid rgba(190, 230, 199, 0.055);
  transition: background 0.15s ease;
}
.searchResultItem:last-child { border-bottom: none; }
.searchResultItem:hover, .searchResultItem:active { background: rgba(190, 230, 199, 0.09); }

/* ---------- Panels: 20 / 60 / 20 split ---------- */
.panel {
  position: relative;
  overflow: hidden;
  min-height: 0;
  border-radius: 24px;
  border: 1px solid var(--card-border);
  box-shadow:
    inset 0 1px 0 rgba(243, 247, 239, 0.105),
    var(--card-shadow);
}
.panel::before {
  content: "";
  position: absolute;
  inset: 1px 1px auto 1px;
  height: 88px;
  border-radius: inherit;
  background: linear-gradient(180deg, rgba(243, 247, 239, 0.08), transparent 78%);
  pointer-events: none;
  z-index: 1;
}

#hourly {
  flex: 2 0 0;
  display: flex;
  align-items: center;
  background:
    linear-gradient(145deg, rgba(243, 247, 239, 0.075), rgba(190, 230, 199, 0.032)),
    var(--card-bg);
  backdrop-filter: blur(9px) saturate(1.18);
  -webkit-backdrop-filter: blur(9px) saturate(1.18);
}
#mapPanel {
  flex: 6 0 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg-0);
}
#daily {
  flex: 0 0 auto;
  background:
    linear-gradient(145deg, rgba(243, 247, 239, 0.075), rgba(190, 230, 199, 0.032)),
    var(--card-bg);
  backdrop-filter: blur(9px) saturate(1.18);
  -webkit-backdrop-filter: blur(9px) saturate(1.18);
}

/* ---------- Hourly ---------- */
.scrollRow {
  position: relative;
  z-index: 2;
  display: flex;
  gap: 6px;
  overflow-x: auto;
  overflow-y: hidden;
  width: 100%;
  height: 100%;
  align-items: center;
  padding: 0 12px;
  scrollbar-width: none;
}
.scrollRow::-webkit-scrollbar { display: none; }

.hourCard {
  flex: 0 0 auto;
  width: 60px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  padding: 10px 4px;
  border-radius: 18px;
  background:
    radial-gradient(80% 70% at 20% 8%, rgba(243, 247, 239, 0.095), transparent 60%),
    rgba(190, 230, 199, 0.045);
  border: 1px solid rgba(190, 230, 199, 0.13);
  box-shadow: inset 0 1px 0 rgba(243,247,239,0.095);
  backdrop-filter: blur(8px) saturate(1.1);
  -webkit-backdrop-filter: blur(8px) saturate(1.1);
  transition: background 0.2s ease, transform 0.15s var(--ease);
}
.hourCard:active { transform: scale(0.94); }
.hourCard:first-child {
  background: var(--accent-bg);
  border-color: rgba(255, 220, 168, 0.28);
}
.hourCard .hLabel { color: rgba(var(--fg-rgb), 0.82); font-size: 12px; font-weight: 500; }
.hourCard .hIcon { width: 30px; height: 30px; }
.hourCard .hTemp { font-weight: 600; font-size: 15px; color: var(--text); }
.hourCard .hPrecip {
  font-size: 10px;
  min-height: 16px;
  color: var(--precip-fg);
  background: var(--precip-bg);
  padding: 1px 6px;
  border-radius: 8px;
  visibility: hidden;
}
.hourCard .hPrecip.show { visibility: visible; }

/* ---------- Map (Leaflet + RainViewer radar) ---------- */
#leafletMap {
  width: 100%;
  height: 100%;
  flex: 1 1 0;
  min-height: 0;
  background: var(--bg-0);
}

/* Restyle Leaflet's own controls to match the glass theme instead of its
   default white boxes. Uses --glass-tint-rgb/--fg-rgb (not fixed dark/
   light) so this flips correctly in day mode along with the rest of the
   map chrome - see the .mapGlassCard comment for why that matters. */
.leaflet-control-attribution {
  background: rgba(var(--glass-tint-rgb), 0.8) !important;
  color: rgba(var(--fg-rgb), 0.9) !important;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.leaflet-control-attribution a { color: var(--accent-strong) !important; }

/* Shared floating "glass" card look, reused by the legend and the map's
   corner buttons so they read as one visual system.
   The tint here used to be a fixed rgba(5,7,10,0.34) - fine over dark map
   content, but measured contrast collapses to ~2:1 (fails WCAG AA, which
   wants 3:1 for UI components / 4.5:1 for text) once the map underneath
   is bright: sunlit basemap labels, pale precip cells, bright OWM tiles.
   Bumped to 0.74 and, with day mode added, made theme-aware via
   --glass-tint-rgb/--fg-rgb (dark tint + white text at night, light tint +
   dark text by day) - re-verified with the same contrast math both ways:
   >=7:1 for night-mode icons against a near-white backdrop, and >=8:1 for
   day-mode icons against a near-black backdrop (dark radar/no-data,
   the darkest realistic content under a day-mode light tint). */
.mapGlassCard {
  background: linear-gradient(145deg, rgba(var(--fg-rgb), 0.085), rgba(var(--glass-tint-rgb), 0.74));
  border: 1px solid rgba(190, 230, 199, 0.28);
  backdrop-filter: blur(11px) saturate(1.15);
  -webkit-backdrop-filter: blur(11px) saturate(1.15);
  box-shadow: inset 0 1px 0 rgba(243, 247, 239, 0.105), 0 4px 12px rgba(0, 0, 0, 0.42);
}

/* ---------- Precipitation legend (top-left) ---------- */
#radarLegend {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 1000;
  width: 84px;
  padding: 10px 10px 8px;
  border-radius: 16px;
  font-size: 11px;
}
#legendTitle {
  font-weight: 600;
  color: var(--text);
  margin-bottom: 8px;
}
#legendScale {
  display: flex;
  gap: 8px;
  height: 64px;
}
#legendBar {
  flex: 0 0 auto;
  width: 12px;
  border-radius: 6px;
  /* Sampled from real rendered NOAA reflectivity tiles (not an invented
     scale) - light rain renders blue, ramping through teal/green and
     yellow to orange for heavier returns; red capping the "Extreme" end
     follows the standard NWS reflectivity convention (no live extreme
     cell was available to sample directly at verification time). This is
     real data-visualization color, not theme decoration, so it doesn't
     change between day/night mode. */
  background: linear-gradient(to top, #4a78b6 0%, #59c2b4 35%, #ffd400 68%, #ff7c00 88%, #e8392c 100%);
}
#legendLabels {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  /* Was a fixed var(--text-dim) - too faint once this card sits over
     unpredictable map brightness. rgba(var(--fg-rgb), 0.92) keeps that
     >=6:1 margin in both themes instead of just at night. */
  color: rgba(var(--fg-rgb), 0.92);
  line-height: 1.1;
}
#legendAttribution {
  margin-top: 8px;
  font-size: 9px;
  color: rgba(var(--fg-rgb), 0.78);
}

/* ---------- Map corner buttons (top-right) ---------- */
#mapButtons {
  position: absolute;
  top: 12px;
  right: 12px;
  /* Above the other map overlays (legend, base tiles) so the open layer
     menu always paints on top rather than getting stacked underneath. */
  z-index: 1100;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 10px;
}
#mapButtonGroup {
  display: flex;
  flex-direction: column;
  border-radius: 20px;
  overflow: hidden;
}
#mapButtonGroup button,
#searchListBtn {
  width: 38px;
  height: 38px;
  border: none;
  color: var(--text);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  /* Same tint as .mapGlassCard - these buttons define their own copy of
     that gradient rather than using the shared class. */
  background: linear-gradient(145deg, rgba(var(--fg-rgb), 0.085), rgba(var(--glass-tint-rgb), 0.74));
  backdrop-filter: blur(11px) saturate(1.15);
  -webkit-backdrop-filter: blur(11px) saturate(1.15);
  transition: background 0.2s ease, transform 0.15s var(--ease);
}
#mapButtonGroup { border: 1px solid rgba(190, 230, 199, 0.28); box-shadow: inset 0 1px 0 rgba(243, 247, 239, 0.105), 0 4px 12px rgba(0, 0, 0, 0.42); }
#mapButtonGroup button:first-child { border-bottom: 1px solid rgba(190, 230, 199, 0.28); }
#searchListBtn { border-radius: 50%; border: 1px solid rgba(190, 230, 199, 0.28); box-shadow: inset 0 1px 0 rgba(243, 247, 239, 0.105), 0 4px 12px rgba(0, 0, 0, 0.42); }
#mapButtonGroup button:hover,
#searchListBtn:hover { background: rgba(190, 230, 199, 0.14); }
#mapButtonGroup button:active,
#searchListBtn:active { transform: scale(0.92); }
#radarToggleBtn[aria-expanded="true"] { color: var(--accent-strong); }
#locateBtn.locating { color: var(--accent-strong); }

/* ---------- Map layer picker menu ---------- */
#layerMenu {
  display: flex;
  flex-direction: column;
  border-radius: 14px;
  padding: 4px;
  min-width: 132px;
}
#layerMenu.hidden { display: none; }
.layerOption {
  border: none;
  background: transparent;
  /* Same outdoor/theme-aware bump as the legend text, since this menu sits
     on the same map-overlay glass card. */
  color: rgba(var(--fg-rgb), 0.92);
  font-size: 13px;
  font-weight: 500;
  text-align: left;
  padding: 8px 10px;
  border-radius: 10px;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.layerOption:hover { background: rgba(190, 230, 199, 0.1); }
.layerOption.active {
  background: var(--accent-bg);
  color: var(--accent-strong);
  font-weight: 600;
}

@media (max-width: 480px) {
  #dailyList { padding: 6px 14px 30px; }
  #radarLegend { top: 8px; left: 8px; width: 72px; padding: 8px 8px 6px; }
  #legendScale { height: 52px; }
  #mapButtons { top: 8px; right: 8px; }
  #mapButtonGroup button, #searchListBtn { width: 34px; height: 34px; }
}

/* ---------- Daily ---------- */
#dailyList {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 6px 18px 24px;
}
.dayRow {
  flex: 1;
  display: grid;
  grid-template-columns: 68px 30px 1fr 32px auto 40px;
  align-items: center;
  gap: 10px;
  font-size: 14px;
  border-bottom: 1px solid var(--card-border);
  transition: background 0.2s ease;
}
.dayRow:last-child { border-bottom: none; }
.dayRow:active { background: rgba(190, 230, 199, 0.05); }
.dayRow .dLabel { font-weight: 500; color: var(--text); }
.dayRow .dIcon { width: 24px; height: 24px; }
.dayRow .dPrecip {
  font-size: 11px;
  color: var(--precip-fg);
  background: var(--precip-bg);
  text-align: center;
  padding: 2px 6px;
  border-radius: 8px;
  visibility: hidden;
  justify-self: end;
}
.dayRow .dPrecip.show { visibility: visible; }
.dayRow .dLow { color: rgba(var(--fg-rgb), 0.72); text-align: right; }
.dayRow .dHigh { font-weight: 500; text-align: right; color: var(--text); }

.barTrack {
  position: relative;
  height: 5px;
  border-radius: 3px;
  background: rgba(0,0,0,0.18);
  box-shadow: inset 0 1px 2px rgba(0,0,0,0.3);
}
.barFill {
  position: absolute;
  top: 0; bottom: 0;
  border-radius: 3px;
  background: var(--accent-strong);
  transition: left 0.4s var(--ease), width 0.4s var(--ease);
}

@media (max-width: 480px) {
  #cityName { font-size: 19px; }
  #currentTemp { font-size: 24px; }
  .hourCard { width: 50px; }
  .dayRow { grid-template-columns: 52px 24px 1fr 28px auto 36px; font-size: 13px; gap: 6px; }
  #searchInput { font-size: 16px; } /* prevents iOS auto-zoom on focus */
}
