/* To Grill or Not to Grill? — Weather Dashboard
   DAYBREAK theme: retro arcade grill on a grilling day. Light-blue sky
   background, pale grassy-green cards, ember-orange accents, chunky pixel
   borders with hard shadows, Press Start 2P display type, and a faint
   CRT scanline overlay.
   Base styles target phones (~390px); larger screens enhance via min-width queries. */

/* Self-hosted fonts: the page makes zero third-party requests on load.
   Inter is served as one variable file covering the full weight range. */
@font-face {
    font-family: "Inter";
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url("../fonts/inter-var-latin.woff2") format("woff2");
}
@font-face {
    font-family: "Press Start 2P";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("../fonts/pressstart2p-400-latin.woff2") format("woff2");
}
@font-face {
    font-family: "VT323";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("../fonts/vt323-400-latin.woff2") format("woff2");
}

:root {
    --text: #22331f;
    --muted: #4a5f4c;
    --ink: #22331f;
    --bg: #b7dcf0;
    --panel: #ddf0d0;
    --panel-edge: #b3d19e;
    --accent: #e86f0e;
    --accent-deep: #8f4404;
    --accent-2: #ffc53d;
    --accent-ink: #3a1c04;
    --tier-great: #1c6e2e;
    --tier-ok: #8a5a00;
    --tier-bad: #b52e2e;
    --radius: 4px;
    --shadow: 6px 6px 0 rgba(34, 51, 31, 0.30);
    --page-pad: 1rem;
    --font-pixel: "Press Start 2P", "Courier New", monospace;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    min-height: 100vh;
    min-height: 100dvh;
    display: flex;
    flex-direction: column; /* short pages: the lawn still lands on the viewport bottom */
    overflow-x: clip; /* The scene slides sideways during transitions. */
    color: var(--text);
    font-family: "VT323", "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    /* VT323's x-height runs small (0.40 vs Inter's 0.55): normalize it so
       existing type sizes read the same. Pixel display type opts out. */
    font-size-adjust: 0.546;
    background:
        radial-gradient(700px 380px at 50% -10%, rgba(255, 213, 79, 0.55), transparent 60%),
        radial-gradient(800px 500px at 100% 110%, rgba(255, 255, 255, 0.35), transparent 60%),
        linear-gradient(180deg, #cde9f9 0%, #b7dcf0 55%, #a8d3ec 100%);
    background-attachment: fixed;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
    touch-action: manipulation;
}

/* CRT scanlines: faint, non-interactive, off for reduced motion. */
body::after {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 50;
    pointer-events: none;
    background: repeating-linear-gradient(
        to bottom,
        transparent 0 2px,
        rgba(34, 51, 31, 0.06) 2px 4px
    );
}

button, input, a { -webkit-tap-highlight-color: transparent; }
button, input { font-family: inherit; }

::selection { background: rgba(255, 122, 26, 0.45); }

.page {
    position: relative;
    z-index: 1;
    max-width: 1060px;
    margin: 0 auto;
    padding: calc(1.5rem + env(safe-area-inset-top, 0px)) max(var(--page-pad), env(safe-area-inset-right, 0px)) calc(2.5rem + env(safe-area-inset-bottom, 0px)) max(var(--page-pad), env(safe-area-inset-left, 0px));
}

/* ---------- living sky: drifting pixel clouds, one lively-but-anchored pixel sun ---------- */
.sky-decor {
    position: fixed;
    inset: 0;
    z-index: 0;
    overflow: hidden;
    pointer-events: none;
}

/* Fresh pixel sun: flat minimal disc, chunky rays that
   alternate long/short in a stepped twinkle, plus a soft warm glow. */
.sun-wrap {
    position: absolute;
    top: 64px;
    right: 7%;
    filter: drop-shadow(0 0 14px rgba(255, 170, 40, 0.5));
}

.sun {
    position: relative;
    width: 8px;
    height: 8px;
    background: transparent;
    box-shadow:
        64px 48px #e8940f,
        72px 48px #e8940f,
        80px 48px #e8940f,
        88px 48px #e8940f,
        96px 48px #e8940f,
        104px 48px #e8940f,
        112px 48px #e8940f,
        56px 56px #ffd23e,
        64px 56px #ffd23e,
        72px 56px #ffd23e,
        80px 56px #ffd23e,
        88px 56px #ffd23e,
        96px 56px #ffd23e,
        104px 56px #ffd23e,
        112px 56px #ffd23e,
        120px 56px #ffd23e,
        48px 64px #e8940f,
        56px 64px #ffd23e,
        64px 64px #ffd23e,
        72px 64px #ffd23e,
        80px 64px #ffd23e,
        88px 64px #ffd23e,
        96px 64px #ffd23e,
        104px 64px #ffd23e,
        112px 64px #ffd23e,
        120px 64px #ffd23e,
        128px 64px #e8940f,
        48px 72px #e8940f,
        56px 72px #ffd23e,
        64px 72px #ffd23e,
        72px 72px #ffd23e,
        80px 72px #ffd23e,
        88px 72px #ffd23e,
        96px 72px #ffd23e,
        104px 72px #ffd23e,
        112px 72px #ffd23e,
        120px 72px #ffd23e,
        128px 72px #e8940f,
        48px 80px #e8940f,
        56px 80px #ffd23e,
        64px 80px #ffd23e,
        72px 80px #ffd23e,
        80px 80px #ffd23e,
        88px 80px #ffd23e,
        96px 80px #ffd23e,
        104px 80px #ffd23e,
        112px 80px #ffd23e,
        120px 80px #ffd23e,
        128px 80px #e8940f,
        48px 88px #e8940f,
        56px 88px #ffd23e,
        64px 88px #ffd23e,
        72px 88px #ffd23e,
        80px 88px #ffd23e,
        88px 88px #ffd23e,
        96px 88px #ffd23e,
        104px 88px #ffd23e,
        112px 88px #ffd23e,
        120px 88px #ffd23e,
        128px 88px #e8940f,
        48px 96px #e8940f,
        56px 96px #ffd23e,
        64px 96px #ffd23e,
        72px 96px #ffd23e,
        80px 96px #ffd23e,
        88px 96px #ffd23e,
        96px 96px #ffd23e,
        104px 96px #ffd23e,
        112px 96px #ffd23e,
        120px 96px #ffd23e,
        128px 96px #e8940f,
        48px 104px #e8940f,
        56px 104px #ffd23e,
        64px 104px #ffd23e,
        72px 104px #ffd23e,
        80px 104px #ffd23e,
        88px 104px #ffd23e,
        96px 104px #ffd23e,
        104px 104px #ffd23e,
        112px 104px #ffd23e,
        120px 104px #ffd23e,
        128px 104px #e8940f,
        48px 112px #e8940f,
        56px 112px #ffd23e,
        64px 112px #ffd23e,
        72px 112px #ffd23e,
        80px 112px #ffd23e,
        88px 112px #ffd23e,
        96px 112px #ffd23e,
        104px 112px #ffd23e,
        112px 112px #ffd23e,
        120px 112px #ffd23e,
        128px 112px #e8940f,
        56px 120px #ffd23e,
        64px 120px #ffd23e,
        72px 120px #ffd23e,
        80px 120px #ffd23e,
        88px 120px #ffd23e,
        96px 120px #ffd23e,
        104px 120px #ffd23e,
        112px 120px #ffd23e,
        120px 120px #ffd23e,
        64px 128px #e8940f,
        72px 128px #e8940f,
        80px 128px #e8940f,
        88px 128px #e8940f,
        96px 128px #e8940f,
        104px 128px #e8940f,
        112px 128px #e8940f;
    animation: sun-breathe 2.2s steps(2) infinite;
}

@keyframes sun-breathe {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.06); }
}

/* Ray frames: ::before shows long cardinals, ::after long diagonals;
   a stepped opacity swap makes them twinkle. */
.sun::before, .sun::after {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 8px;
    height: 8px;
}

.sun::before {
    box-shadow:
        88px 40px #ffc53d,
        96px 40px #ffc53d,
        88px 32px #ffc53d,
        96px 32px #ffc53d,
        88px 24px #ffc53d,
        96px 24px #ffc53d,
        88px 16px #ffc53d,
        96px 16px #ffc53d,
        88px 136px #ffc53d,
        96px 136px #ffc53d,
        88px 144px #ffc53d,
        96px 144px #ffc53d,
        88px 152px #ffc53d,
        96px 152px #ffc53d,
        88px 160px #ffc53d,
        96px 160px #ffc53d,
        40px 88px #ffc53d,
        40px 96px #ffc53d,
        32px 88px #ffc53d,
        32px 96px #ffc53d,
        24px 88px #ffc53d,
        24px 96px #ffc53d,
        16px 88px #ffc53d,
        16px 96px #ffc53d,
        136px 88px #ffc53d,
        136px 96px #ffc53d,
        144px 88px #ffc53d,
        144px 96px #ffc53d,
        152px 88px #ffc53d,
        152px 96px #ffc53d,
        160px 88px #ffc53d,
        160px 96px #ffc53d,
        136px 136px #ffd964,
        144px 136px #ffd964,
        136px 144px #ffd964,
        144px 144px #ffd964,
        144px 144px #ffd964,
        152px 144px #ffd964,
        144px 152px #ffd964,
        152px 152px #ffd964,
        136px 40px #ffd964,
        144px 40px #ffd964,
        136px 48px #ffd964,
        144px 48px #ffd964,
        144px 32px #ffd964,
        152px 32px #ffd964,
        144px 40px #ffd964,
        152px 40px #ffd964,
        40px 136px #ffd964,
        48px 136px #ffd964,
        40px 144px #ffd964,
        48px 144px #ffd964,
        32px 144px #ffd964,
        40px 144px #ffd964,
        32px 152px #ffd964,
        40px 152px #ffd964,
        40px 40px #ffd964,
        48px 40px #ffd964,
        40px 48px #ffd964,
        48px 48px #ffd964,
        32px 32px #ffd964,
        40px 32px #ffd964,
        32px 40px #ffd964,
        40px 40px #ffd964;
    animation: rays-a 1.8s steps(1) infinite;
}

.sun::after {
    box-shadow:
        88px 40px #ffc53d,
        96px 40px #ffc53d,
        88px 32px #ffc53d,
        96px 32px #ffc53d,
        88px 136px #ffc53d,
        96px 136px #ffc53d,
        88px 144px #ffc53d,
        96px 144px #ffc53d,
        40px 88px #ffc53d,
        40px 96px #ffc53d,
        32px 88px #ffc53d,
        32px 96px #ffc53d,
        136px 88px #ffc53d,
        136px 96px #ffc53d,
        144px 88px #ffc53d,
        144px 96px #ffc53d,
        136px 136px #ffd964,
        144px 136px #ffd964,
        136px 144px #ffd964,
        144px 144px #ffd964,
        144px 144px #ffd964,
        152px 144px #ffd964,
        144px 152px #ffd964,
        152px 152px #ffd964,
        152px 152px #ffd964,
        160px 152px #ffd964,
        152px 160px #ffd964,
        160px 160px #ffd964,
        160px 160px #ffd964,
        168px 160px #ffd964,
        160px 168px #ffd964,
        168px 168px #ffd964,
        136px 40px #ffd964,
        144px 40px #ffd964,
        136px 48px #ffd964,
        144px 48px #ffd964,
        144px 32px #ffd964,
        152px 32px #ffd964,
        144px 40px #ffd964,
        152px 40px #ffd964,
        152px 24px #ffd964,
        160px 24px #ffd964,
        152px 32px #ffd964,
        160px 32px #ffd964,
        160px 16px #ffd964,
        168px 16px #ffd964,
        160px 24px #ffd964,
        168px 24px #ffd964,
        40px 136px #ffd964,
        48px 136px #ffd964,
        40px 144px #ffd964,
        48px 144px #ffd964,
        32px 144px #ffd964,
        40px 144px #ffd964,
        32px 152px #ffd964,
        40px 152px #ffd964,
        24px 152px #ffd964,
        32px 152px #ffd964,
        24px 160px #ffd964,
        32px 160px #ffd964,
        16px 160px #ffd964,
        24px 160px #ffd964,
        16px 168px #ffd964,
        24px 168px #ffd964,
        40px 40px #ffd964,
        48px 40px #ffd964,
        40px 48px #ffd964,
        48px 48px #ffd964,
        32px 32px #ffd964,
        40px 32px #ffd964,
        32px 40px #ffd964,
        40px 40px #ffd964,
        24px 24px #ffd964,
        32px 24px #ffd964,
        24px 32px #ffd964,
        32px 32px #ffd964,
        16px 16px #ffd964,
        24px 16px #ffd964,
        16px 24px #ffd964,
        24px 24px #ffd964;
    animation: rays-b 1.8s steps(1) infinite;
}

@keyframes rays-a {
    0%, 49% { opacity: 1; }
    50%, 100% { opacity: 0; }
}

@keyframes rays-b {
    0%, 49% { opacity: 0; }
    50%, 100% { opacity: 1; }
}


/* Pixel clouds: blocky white puffs with a shaded base, drifting slowly at
   sun/moon height so they occasionally cross in front of them. */
.cloud-track {
    position: absolute;
    animation: drift linear infinite;
}

.cloud-track.t1 { top: 76px; animation-duration: 115s; }
.cloud-track.t1 .cloud { transform: scale(2.1); }
.cloud-track.t2 { top: 108px; animation-duration: 85s; animation-delay: -38s; }
.cloud-track.t2 .cloud { transform: scale(1.6); }
.cloud-track.t3 { top: 58px; animation-duration: 150s; animation-delay: -95s; }
.cloud-track.t3 .cloud { transform: scale(2.7); opacity: 0.92; }
/* Storm head: a fourth, lower cloud bank that only shows during rain. */
.cloud-track.t4 { top: 148px; animation-duration: 70s; animation-delay: -20s; display: none; }
.cloud-track.t4 .cloud { transform: scale(3.4); opacity: 0.95; }
body.sky-rain .cloud-track.t4 { display: block; }

@keyframes drift {
    from { transform: translateX(-15vw); }
    to { transform: translateX(115vw); }
}

.cloud {
    position: relative;
    width: 7px;
    height: 7px;
    color: #ffffff;
    box-shadow:
        14px 0, 21px 0,
        7px 7px, 14px 7px, 21px 7px, 28px 7px;
}

.cloud::after {
    content: "";
    position: absolute;
    top: 14px;
    left: 0;
    width: 7px;
    height: 7px;
    color: #d7ecf7;
    box-shadow:
        0 0, 7px 0, 14px 0, 21px 0, 28px 0, 35px 0;
}

/* Pixel moon: blocky pale disc with crater pixels, upper-left at night. */
.moon-wrap {
    position: absolute;
    top: 28px;
    left: 12%;
    display: none;
}

body.sky-night .moon-wrap { display: block; }

/* Stars were seeded but never styled — tiny pixel dots, night only,
   with a slow stepped twinkle. */
.stars {
    position: absolute;
    top: 0;
    left: 0;
    width: 3px;
    height: 3px;
    background: transparent;
    opacity: 0;
    pointer-events: none;
}

body.sky-night .stars {
    opacity: 1;
    animation: star-twinkle 4s steps(2) infinite;
}

@keyframes star-twinkle {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.5; }
}

.moon {
    position: relative;
    width: 8px;
    height: 8px;
    color: #f6eeda;
    box-shadow:
        16px 0, 24px 0, 32px 0, 40px 0,
        8px 8px, 16px 8px, 24px 8px, 32px 8px, 40px 8px, 48px 8px,
        0 16px, 8px 16px, 16px 16px, 24px 16px, 32px 16px, 40px 16px, 48px 16px, 56px 16px,
        0 24px, 8px 24px, 16px 24px, 24px 24px, 32px 24px, 40px 24px, 48px 24px, 56px 24px,
        0 32px, 8px 32px, 16px 32px, 24px 32px, 32px 32px, 40px 32px, 48px 32px, 56px 32px,
        0 40px, 8px 40px, 16px 40px, 24px 40px, 32px 40px, 40px 40px, 48px 40px, 56px 40px,
        8px 48px, 16px 48px, 24px 48px, 32px 48px, 40px 48px, 48px 48px,
        16px 56px, 24px 56px, 32px 56px, 40px 56px;
}

.moon::after {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 8px;
    height: 8px;
    color: #ddcfa8;
    box-shadow: 16px 24px, 24px 24px, 40px 40px;
}

/* Living lawn: a pixel-grass strip along the bottom of the page flow,
   blades swaying in a stepped two-frame cycle. */
.lawn {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    height: 92px;
    image-rendering: pixelated;
}

/* Night palette: deep blue gradient; sun sleeps, clouds go slate. */
/* Cards deepen to match so the pale day-green doesn't float on the night. */
body.sky-night {
    background:
        radial-gradient(700px 380px at 50% -10%, rgba(120, 140, 200, 0.25), transparent 60%),
        linear-gradient(180deg, #0e1830 0%, #16233f 55%, #1d2c4e 100%);
    --panel: #22303f;
    --panel-edge: #3a4f63;
    --text: #eef3ea;
    --muted: #a8bccf;
    --ink: #0d1622;
    --shadow: 6px 6px 0 rgba(0, 0, 0, 0.35);
    --tier-great: #5fce73;
    --tier-ok: #ffc53d;
    --tier-bad: #ff8a8a;
    /* The day light-blue insets go deep slate so they don't glow on the night. */
    --bg: #16283e;
}

body.sky-night .sun-wrap { display: none; }
body.sky-night .cloud { color: #54648a; }
body.sky-night .cloud::after { color: #42506e; }

/* Night legibility: brighter ember headers, dark pixel shadows, dim placeholder. */
body.sky-night #cityInput::placeholder { color: rgba(168, 188, 207, 0.55); }
body.sky-night .card-eyebrow { color: #ffa03c; text-shadow: 2px 2px 0 rgba(0, 0, 0, 0.55); }
body.sky-night .cook-suggest { color: #ffa03c; }
body.sky-night .verdict-score,
body.sky-night .temp-big { text-shadow: 3px 3px 0 rgba(0, 0, 0, 0.45); }

/* Cloudy: sun ducks away, clouds go gray. */
body.sky-cloudy .sun-wrap { display: none; }
body.sky-cloudy .cloud { color: #ccd6e2; }
body.sky-cloudy .cloud::after { color: #a9b7c9; }

/* Cloudy: the sky itself cools a shade so overcast reads at a glance,
   still clearly brighter than the gloom/rain gray. */
body.sky-cloudy:not(.sky-night) {
    background:
        radial-gradient(700px 380px at 50% -10%, rgba(255, 213, 79, 0.28), transparent 60%),
        linear-gradient(180deg, #a9c6da 0%, #9db8ce 60%, #92adc5 100%);
    background-attachment: fixed;
}

/* Fog: a washed-out white-out. The mist bands roll in thick, the sun hides,
   clouds go pale, the lawn mutes, and the boxes follow suit. */
body.sky-fog:not(.sky-night) {
    background: linear-gradient(180deg, #c6d1d8 0%, #b9c4cc 60%, #aeb9c1 100%);
    background-attachment: fixed;
    --panel: #c2cdd2;
    --panel-edge: #9fabb2;
    --text: #22302e;
    --muted: #44534f;
    --shadow: 6px 6px 0 rgba(34, 48, 46, 0.32);
}
body.sky-fog .sun-wrap { display: none; }
body.sky-fog .cloud { color: #d8dee3; }
body.sky-fog .cloud::after { color: #c2ccd3; }
body.sky-fog .mist { opacity: 1; }

/* Rain: small minimalist drops, two depths of stepped rainfall. */
body.sky-rain .sun-wrap { display: none; }
body.sky-rain .cloud { color: #9fb0c4; }
body.sky-rain .cloud::after { color: #7e90a8; }

/* Day rain feels like a rainy day: the sky itself turns overcast gray-blue,
   and the clouds go low and dark like storm heads. sky-gloom is the same
   mood for overcast days with rain on the way (no falling rain faked). */
body.sky-rain:not(.sky-night),
body.sky-gloom:not(.sky-night) {
    background:
        radial-gradient(800px 500px at 100% 110%, rgba(255, 255, 255, 0.12), transparent 60%),
        linear-gradient(180deg, #9fb3c4 0%, #8fa3b8 55%, #8296ad 100%);
    background-attachment: fixed;
}
body.sky-rain:not(.sky-night) .cloud,
body.sky-gloom:not(.sky-night) .cloud { color: #6e8098; }
body.sky-rain:not(.sky-night) .cloud::after,
body.sky-gloom:not(.sky-night) .cloud::after { color: #55677f; }
body.sky-gloom .cloud-track.t4 { display: block; }
body.sky-gloom .mist { opacity: 0.7; }

/* Thunderstorm sky goes darker than plain rain: a storm should feel
   heavier than the rain that comes with it. */
body.sky-storm:not(.sky-night) {
    background:
        radial-gradient(800px 500px at 100% 110%, rgba(255, 255, 255, 0.08), transparent 60%),
        linear-gradient(180deg, #6e7f92 0%, #5d6f84 55%, #4d5f75 100%);
    background-attachment: fixed;
}

/* Gloomy boxes: on rainy or rain-coming days the cards trade pale grassy
   green for muted slate-sage, so the whole page feels overcast instead of
   just the sky. Ember-orange accents stay bright against the gloom. */
body.sky-rain:not(.sky-night),
body.sky-gloom:not(.sky-night) {
    --panel: #b3c1b5;
    --panel-edge: #8d9f90;
    --text: #1c2a21;
    --muted: #3b4e42;
    --shadow: 6px 6px 0 rgba(28, 42, 33, 0.38);
}

/* Low mist band that drifts in during rain. */
.mist {
    position: absolute;
    left: -10%;
    right: -10%;
    bottom: 6%;
    height: 110px;
    opacity: 0;
    background: linear-gradient(180deg, transparent, rgba(222, 232, 242, 0.32) 55%, rgba(222, 232, 242, 0.5));
    filter: blur(6px);
    animation: mist-drift 26s ease-in-out infinite alternate;
}
body.sky-rain .mist { opacity: 1; }
body.sky-night .mist {
    background: linear-gradient(180deg, transparent, rgba(140, 160, 190, 0.16) 55%, rgba(140, 160, 190, 0.26));
}
.mist.m2 { bottom: 17%; height: 80px; animation-duration: 34s; animation-delay: -12s; }
@keyframes mist-drift {
    from { transform: translateX(-4%); }
    to { transform: translateX(4%); }
}

.rain {
    position: absolute;
    inset: -40px 0 0 0;
    opacity: 0;
    /* Tiny minimalist drops, scattered by hand inside a large tile so
       they don't line up in a grid. Slate-blue reads on the day sky. */
    --drop: rgba(105, 135, 175, 0.7);
    background-image:
        radial-gradient(ellipse 1.5px 7px at 18px 12px, var(--drop) 55%, transparent 75%),
        radial-gradient(ellipse 1.5px 7px at 52px 30px, var(--drop) 55%, transparent 75%),
        radial-gradient(ellipse 1.5px 7px at 88px 16px, var(--drop) 55%, transparent 75%),
        radial-gradient(ellipse 1.5px 7px at 112px 48px, var(--drop) 55%, transparent 75%),
        radial-gradient(ellipse 1.5px 7px at 36px 58px, var(--drop) 55%, transparent 75%),
        radial-gradient(ellipse 1.5px 7px at 70px 74px, var(--drop) 55%, transparent 75%),
        radial-gradient(ellipse 1.5px 7px at 104px 82px, var(--drop) 55%, transparent 75%),
        radial-gradient(ellipse 1.5px 7px at 22px 92px, var(--drop) 55%, transparent 75%),
        radial-gradient(ellipse 1.5px 7px at 58px 100px, var(--drop) 55%, transparent 75%),
        radial-gradient(ellipse 1.5px 7px at 96px 60px, var(--drop) 55%, transparent 75%),
        radial-gradient(ellipse 1.5px 7px at 8px 44px, var(--drop) 55%, transparent 75%),
        radial-gradient(ellipse 1.5px 7px at 120px 96px, var(--drop) 55%, transparent 75%);
    background-size: 126px 108px;
}

/* Night rain stays pale so it reads on the dark sky. */
body.sky-night .rain { --drop: rgba(200, 220, 245, 0.75); }

body.sky-rain .rain { opacity: 1; }
body.sky-rain .r1 { animation: rainfall 1.1s steps(11) infinite; }
body.sky-rain .r2 {
    background-image:
        radial-gradient(ellipse 1px 5px at 24px 18px, var(--drop) 55%, transparent 75%),
        radial-gradient(ellipse 1px 5px at 66px 42px, var(--drop) 55%, transparent 75%),
        radial-gradient(ellipse 1px 5px at 110px 24px, var(--drop) 55%, transparent 75%),
        radial-gradient(ellipse 1px 5px at 140px 66px, var(--drop) 55%, transparent 75%),
        radial-gradient(ellipse 1px 5px at 44px 84px, var(--drop) 55%, transparent 75%),
        radial-gradient(ellipse 1px 5px at 92px 100px, var(--drop) 55%, transparent 75%),
        radial-gradient(ellipse 1px 5px at 128px 112px, var(--drop) 55%, transparent 75%),
        radial-gradient(ellipse 1px 5px at 12px 60px, var(--drop) 55%, transparent 75%),
        radial-gradient(ellipse 1px 5px at 80px 8px, var(--drop) 55%, transparent 75%);
    background-size: 150px 126px;
    opacity: 0.45;
    animation: rainfall-far 1.7s steps(13) infinite;
}

@keyframes rainfall {
    from { background-position: 0 0; }
    to { background-position: 0 108px; }
}

@keyframes rainfall-far {
    from { background-position: 0 0; }
    to { background-position: 0 126px; }
}

/* Thunderstorm: one distant, soft lightning pulse per cycle — the single
   detail that makes a storm read as a storm. Kept deliberately subtle. */
.lightning {
    position: absolute;
    inset: 0;
    display: none;
    background: radial-gradient(600px 380px at 72% 0%, rgba(255, 255, 255, 0.6), transparent 70%);
    animation: lightning-pulse 9s linear infinite;
    pointer-events: none;
}
body.sky-storm .lightning { display: block; }
@keyframes lightning-pulse {
    0%, 90.9%, 93.9%, 95.9%, 100% { opacity: 0; }
    92%, 95% { opacity: 0.45; }
    93% { opacity: 0.12; }
}

/* Snow: soft flakes drift down in slow stepped layers. */
body.sky-snow .sun-wrap { display: none; }
body.sky-snow .cloud { color: #e8eef5; }
body.sky-snow .cloud::after { color: #c9d4e2; }

/* Snow: icy pale-blue boxes to match the winter mood. */
body.sky-snow:not(.sky-night) {
    --panel: #ccd9e6;
    --panel-edge: #a5bccd;
    --text: #1d2a33;
    --muted: #3d5266;
    --shadow: 6px 6px 0 rgba(29, 42, 51, 0.35);
}

.snow {
    position: absolute;
    inset: -40px 0 0 0;
    opacity: 0;
    /* Flakes scattered by hand inside a large tile, same anti-grid trick. */
    background-image:
        radial-gradient(circle at 22px 30px, rgba(255, 255, 255, 0.95) 2px, transparent 3px),
        radial-gradient(circle at 78px 14px, rgba(255, 255, 255, 0.95) 2px, transparent 3px),
        radial-gradient(circle at 120px 52px, rgba(255, 255, 255, 0.95) 2px, transparent 3px),
        radial-gradient(circle at 48px 88px, rgba(255, 255, 255, 0.95) 2px, transparent 3px),
        radial-gradient(circle at 100px 110px, rgba(255, 255, 255, 0.95) 2px, transparent 3px),
        radial-gradient(circle at 14px 128px, rgba(255, 255, 255, 0.95) 2px, transparent 3px),
        radial-gradient(circle at 132px 96px, rgba(255, 255, 255, 0.9) 1.5px, transparent 2.5px);
    background-size: 144px 144px;
}

body.sky-snow .snow { opacity: 1; }
body.sky-snow .s1 { animation: snowfall 3.4s steps(14) infinite; }
body.sky-snow .s2 {
    background-image:
        radial-gradient(circle at 36px 24px, rgba(255, 255, 255, 0.9) 1.5px, transparent 2.5px),
        radial-gradient(circle at 96px 60px, rgba(255, 255, 255, 0.9) 1.5px, transparent 2.5px),
        radial-gradient(circle at 150px 36px, rgba(255, 255, 255, 0.9) 1.5px, transparent 2.5px),
        radial-gradient(circle at 66px 120px, rgba(255, 255, 255, 0.9) 1.5px, transparent 2.5px),
        radial-gradient(circle at 138px 140px, rgba(255, 255, 255, 0.9) 1.5px, transparent 2.5px);
    background-size: 180px 180px;
    opacity: 0.6;
    animation: snowfall-far 5.2s steps(18) infinite;
}

@keyframes snowfall {
    from { background-position: 0 0; }
    to { background-position: 0 144px; }
}

@keyframes snowfall-far {
    from { background-position: 0 0; }
    to { background-position: 0 180px; }
}

/* Night keeps its weather: darker slate clouds so rain, snow and overcast
   still read on the dark sky. The moon stays up while the weather plays. */
body.sky-night.sky-rain .cloud { color: #3d4c68; }
body.sky-night.sky-rain .cloud::after { color: #2e3b53; }
body.sky-night.sky-snow .cloud { color: #6b7d99; }
body.sky-night.sky-snow .cloud::after { color: #525f78; }
body.sky-night.sky-cloudy .cloud { color: #46566f; }
body.sky-night.sky-cloudy .cloud::after { color: #364357; }

@media (max-width: 640px) {
    .moon-wrap { transform: scale(0.7); transform-origin: top left; }
    .lawn { height: 56px; }
}

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

.site-header { text-align: center; margin-bottom: 1.5rem; }

.brand-eyebrow {
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 0 0.9rem;
    font-family: var(--font-pixel);
    font-size-adjust: none;
    font-size: 0.7rem;
    line-height: 1.8;
    letter-spacing: 0.08em;
    color: var(--accent-deep);
    text-shadow: 2px 2px 0 rgba(255, 255, 255, 0.7);
}
/* The icon hangs off the text instead of joining the centered line,
   so the words sit on the true optical center. */
.eyebrow-text { position: relative; }
.eyebrow-icon {
    position: absolute;
    right: calc(100% + 0.45rem);
    top: 50%;
    transform: translateY(-50%);
}

.site-header h1 {
    margin: 0;
    font-family: var(--font-pixel);
    font-size-adjust: none;
    font-size-adjust: none;
    font-size: 1.28rem;
    line-height: 1.7;
    text-wrap: balance; /* no orphaned "GRILL?" on its own line */
    color: var(--text);
    text-shadow: 3px 3px 0 rgba(255, 255, 255, 0.65);
}

.tagline { margin: 0.9rem 0 0; color: var(--muted); font-size: 1rem; }

/* ---------- cards ---------- */

.card {
    background: var(--panel);
    /* Translucent fill, opaque frame: the weather shows through the glass
       while the chunky pixel border and hard shadow stay solid. The first
       line is the fallback for browsers without color-mix. */
    background: color-mix(in srgb, var(--panel) 90%, transparent);
    border: 3px solid var(--ink);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    animation: rise 0.3s steps(3) both;
}

[hidden] { display: none !important; }

@keyframes rise {
    from { opacity: 0; transform: translateY(14px); }
    to { opacity: 1; transform: none; }
}

/* ---------- search ---------- */

.search-card { padding: 1.25rem; margin-bottom: 1.25rem; }

.search-row { display: flex; flex-direction: column; gap: 0.75rem; }

#cityInput {
    width: 100%;
    min-height: 52px;
    padding: 0.85rem 2.75rem 0.85rem 1.25rem;
    font-size: 1rem; /* 16px: prevents iOS auto-zoom on focus */
    color: var(--text);
    background: var(--bg);
    border: 3px solid var(--panel-edge);
    border-radius: var(--radius);
    outline: none;
    transition: border-color 0.15s, box-shadow 0.15s;
}

#cityInput::placeholder { color: rgba(74, 95, 76, 0.6); }

#cityInput:focus {
    border-color: var(--accent);
    box-shadow: 4px 4px 0 rgba(34, 51, 31, 0.35);
}

/* Clear button inside the search field: a crisp CSS-drawn X in a soft
   circle, so it stays perfectly centered and legible in day and night. */
.clear-btn {
    position: absolute;
    right: 10px;
    top: 50%;
    transform: translateY(-50%);
    width: 32px;
    height: 32px;
    padding: 0;
    background: rgba(34, 51, 31, 0.10);
    border: none;
    border-radius: 50%;
    cursor: pointer;
    opacity: 0.8;
}
.clear-btn::before,
.clear-btn::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: 14px;
    height: 2.5px;
    border-radius: 2px;
    background: var(--text);
    transform: translate(-50%, -50%) rotate(45deg);
}
.clear-btn::after { transform: translate(-50%, -50%) rotate(-45deg); }
.clear-btn:hover { opacity: 1; background: rgba(34, 51, 31, 0.20); }
.clear-btn:active { transform: translateY(-50%) scale(0.92); }
body.sky-night .clear-btn { background: rgba(238, 243, 234, 0.14); }
body.sky-night .clear-btn:hover { background: rgba(238, 243, 234, 0.26); }
.clear-btn[hidden] { display: none; }

#searchBtn {
    min-height: 52px;
    padding: 0.85rem 1.75rem;
    font-family: var(--font-pixel);
    font-size-adjust: none;
    font-size: 0.8rem;
    line-height: 1.7;
    color: var(--accent-ink);
    background: var(--accent);
    border: 3px solid var(--ink);
    border-radius: var(--radius);
    cursor: pointer;
    box-shadow: 4px 4px 0 var(--ink);
    transition: transform 0.1s, box-shadow 0.1s;
}

#searchBtn:hover:not(:disabled) { filter: brightness(1.08); }
#searchBtn:active:not(:disabled) { transform: translate(2px, 2px); box-shadow: 2px 2px 0 var(--ink); }
#searchBtn:disabled { opacity: 0.65; cursor: wait; }

/* Tertiary action: a quiet centered text link on phones (the amber Search
   button owns the CTA); a compact icon button grouped in the search row
   on larger screens. */
.locate-btn {
    align-self: center;
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    min-height: 44px;
    padding: 0.5rem 0.9rem;
    background: var(--panel);
    border: 3px solid var(--ink);
    border-radius: var(--radius);
    box-shadow: 3px 3px 0 var(--ink);
    color: var(--muted);
    font-size: 0.92rem;
    font-weight: 600;
    cursor: pointer;
    transition: color 0.15s, transform 0.1s, box-shadow 0.1s;
}

.locate-btn:hover:not(:disabled) { color: var(--text); }
.locate-btn:active:not(:disabled) { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--ink); }
.locate-btn:disabled { opacity: 0.65; cursor: wait; }
.locate-btn .locate-icon { font-size: 1rem; line-height: 1; }

button:focus-visible, a:focus-visible {
    outline: 2px solid var(--accent-deep);
    outline-offset: 2px;
}

.form-error {
    margin: 0.9rem 0 0;
    padding: 0.7rem 1rem;
    font-size: 0.92rem;
    color: #a32c2c;
    background: rgba(207, 58, 58, 0.10);
    border: 3px solid var(--tier-bad);
    border-radius: var(--radius);
}

.history {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.625rem;
    margin-top: 1rem;
}

.history-label {
    font-family: var(--font-pixel);
    font-size-adjust: none;
    font-size: 0.65rem;
    line-height: 1.8;
    color: var(--muted);
    margin-right: 0.25rem;
}

/* Recents ride a single scrollable rail instead of wrapping: one slim row
   on every screen size, so a long history never crowds the search card.
   The fading right edge hints that more chips sit off-screen. */
#recent-searches {
    display: flex;
    flex-wrap: nowrap;
    gap: 0.5rem;
    list-style: none;
    margin: 0;
    padding: 4px 1.5rem 7px 4px;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
}
/* The fade hint appears only when chips actually overflow the line —
   otherwise the rail sits as a plain row. */
#recent-searches.is-overflowing {
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 2rem), transparent);
    mask-image: linear-gradient(90deg, #000 calc(100% - 2rem), transparent);
}
#recent-searches::-webkit-scrollbar { display: none; }
#recent-searches button { flex: 0 0 auto; }

#recent-searches button {
    display: inline-flex;
    align-items: center;
    min-height: 40px;
    max-width: 15rem;
    padding: 0.45rem 0.9rem;
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--text);
    background: var(--bg);
    border: 3px solid var(--ink);
    border-radius: var(--radius);
    box-shadow: 3px 3px 0 var(--ink);
    cursor: pointer;
    /* One tidy line per chip — long names ellipsis instead of wrapping. */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: transform 0.1s, box-shadow 0.1s;
}

#recent-searches button:hover { transform: translate(1px, 1px); box-shadow: 2px 2px 0 var(--ink); }
#recent-searches button:active { transform: translate(3px, 3px); box-shadow: 0 0 0 var(--ink); }

/* ---------- alert banner ---------- */

.alert-banner {
    display: flex;
    gap: 0.8rem;
    align-items: flex-start;
    padding: 1rem 1.15rem;
    margin-bottom: 1.25rem;
    background: rgba(255, 93, 93, 0.10);
    border: 3px solid var(--tier-bad);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    animation: rise 0.3s steps(3) both;
}

.alert-icon { font-size: 1.5rem; line-height: 1.3; flex-shrink: 0; }

.alert-title { margin: 0; font-weight: 800; font-size: 1rem; }

.alert-headline { margin: 0.3rem 0 0; color: var(--muted); font-size: 0.9rem; line-height: 1.45; }

/* ---------- verdict hero ---------- */

.verdict-card { padding: 1.5rem 1.25rem; margin-bottom: 1.25rem; }

.card-eyebrow {
    margin: 0 0 0.75rem;
    font-family: var(--font-pixel);
    font-size-adjust: none;
    font-size: 0.68rem;
    line-height: 1.8;
    letter-spacing: 0.06em;
    color: var(--accent-deep);
    text-shadow: 2px 2px 0 rgba(255, 255, 255, 0.6);
    text-align: center;
}

/* Mobile: the verdict is the star — score first, big and centered. */
.verdict-main {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    text-align: center;
    gap: 0.4rem 1.1rem;
}

.verdict-score {
    order: -1;
    font-family: var(--font-pixel);
    font-size-adjust: none;
    font-size: 2.2rem;
    line-height: 1.2;
    white-space: nowrap;
    text-shadow: 3px 3px 0 rgba(255, 255, 255, 0.6);
}

.verdict-score-max { font-family: var(--font-pixel); font-size-adjust: none; font-size: 0.7rem; color: var(--muted); }

/* The Maltipoo mascot: chunky pixel pup, gently idling. */
.mascot {
    image-rendering: pixelated;
    width: 72px;
    height: 72px;
    animation: mascot-idle 1.6s steps(2) infinite;
}

@keyframes mascot-idle {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-4px); }
}

.verdict-score-wrap {
    order: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
}

/* Segmented score bar: fills chunk by chunk like a health bar. */
.score-bar {
    display: flex;
    gap: 3px;
    padding: 4px;
    background: rgba(255, 255, 255, 0.55);
    border: 2px solid var(--ink);
    border-radius: 4px;
}

.score-bar .seg {
    width: 14px;
    height: 10px;
    background: rgba(34, 51, 31, 0.14);
    border-radius: 2px;
}

.score-bar .seg.on { background: var(--tier-great); }
.tier-ok .score-bar .seg.on { background: var(--tier-ok); }
.tier-bad .score-bar .seg.on { background: var(--tier-bad); }

/* Verdict stamp: slams in like a rubber stamp, with a squash-and-settle. */
.verdict-card.stamp { animation: stamp-in 0.5s steps(6) both; }

@keyframes stamp-in {
    0% { opacity: 0; transform: scale(1.7) rotate(-4deg); }
    55% { opacity: 1; transform: scale(0.94) rotate(0.8deg); }
    75% { transform: scale(1.02) rotate(-0.3deg); }
    100% { opacity: 1; transform: scale(1) rotate(0deg); }
}

/* Impact thud: the page shudders for a beat when the verdict lands.
   The sky stays still; only the ground moves. Killed by reduced motion. */
@keyframes impact-shake {
    0% { transform: translate(0, 0); }
    25% { transform: translate(2px, -1px); }
    50% { transform: translate(-2px, 1px); }
    75% { transform: translate(1px, 1px); }
    100% { transform: translate(0, 0); }
}
body.impact .page { animation: impact-shake 0.22s steps(4) both; }

/* Cloud front: a gust of pixel clouds sweeps across the live scene — no
   wash, no box. The scene's own blow-out hides the content swap, so the
   front is pure atmosphere. */
.wipe {
    position: fixed;
    inset: 0;
    z-index: 2000;
    pointer-events: none;
    overflow: hidden;
    opacity: 0;
}

/* Moonlit clouds for night arrivals. */
.wipe[data-tone="night"] .wcloud { color: #e2e9f6; }
.wipe[data-tone="night"] .wcloud::after { color: #aeb9d4; }

.wcloud {
    position: absolute;
    left: var(--wx);
    top: var(--wy);
    width: 7px;
    height: 7px;
    color: #ffffff;
    transform: scale(var(--ws));
    box-shadow:
        14px 0, 21px 0,
        7px 7px, 14px 7px, 21px 7px, 28px 7px;
    animation: wcloud-bob 1s steps(2) infinite alternate;
    animation-delay: var(--wd, 0s);
}

.wcloud::after {
    content: "";
    position: absolute;
    top: 14px;
    left: 0;
    width: 7px;
    height: 7px;
    color: #cfd9e6;
    box-shadow:
        0 0, 7px 0, 14px 0, 21px 0, 28px 0, 35px 0;
}

@keyframes wcloud-bob {
    from { margin-top: 0; }
    to { margin-top: -7px; }
}

/* Two more silhouettes so the front doesn't look stamped: flat stratus
   and small wisps next to the default cumulus puff. */
.wcloud-stratus {
    box-shadow:
        7px 0, 14px 0, 21px 0, 28px 0, 35px 0,
        0 7px, 7px 7px, 14px 7px, 21px 7px, 28px 7px, 35px 7px, 42px 7px;
}
.wcloud-stratus::after {
    box-shadow: 7px 0, 14px 0, 21px 0, 28px 0, 35px 0, 42px 0;
}
.wcloud-wisp {
    box-shadow:
        7px 0, 14px 0,
        0 7px, 7px 7px, 14px 7px, 21px 7px;
}
.wcloud-wisp::after {
    box-shadow: 0 0, 7px 0, 14px 0, 21px 0;
}

/* A dimmer back layer drifts slower (shorter travel, chunkier steps)
   for parallax depth behind the main front. */
.wipe-back {
    position: absolute;
    inset: 0;
}
.wipe.cover .wipe-back { animation: wback-cover 0.55s steps(8) both; }
.wipe.reveal .wipe-back { animation: wback-reveal 0.55s steps(8) both; }
@keyframes wback-cover { from { transform: translateX(0); } to { transform: translateX(30%); } }
@keyframes wback-reveal { from { transform: translateX(30%); } to { transform: translateX(130%); } }
.wipe-back .wcloud {
    color: #dde6f2;
    opacity: 0.55;
    animation-duration: 1.6s;
}
.wipe-back .wcloud::after { color: #b7c3d9; }
.wipe[data-tone="night"] .wipe-back .wcloud { color: #c3cde6; }
.wipe[data-tone="night"] .wipe-back .wcloud::after { color: #8f9ab8; }

.wipe.cover { animation: wipe-cover 0.55s steps(12) both; }
.wipe.reveal { animation: wipe-reveal 0.55s steps(12) both; }

@keyframes wipe-cover {
    from { opacity: 0; transform: translateX(-100%); }
    to { opacity: 1; transform: translateX(0); }
}

@keyframes wipe-reveal {
    from { opacity: 1; transform: translateX(0); }
    to { opacity: 0; transform: translateX(100%); }
}

/* FCP-style push: the old scene blows off ahead of the front… */
@keyframes scene-blow-out {
    to { transform: translateX(72px); opacity: 0; }
}
/* …and the new scene settles in behind it as the front clears. */
@keyframes scene-settle-in {
    from { transform: translateX(-72px); opacity: 0; }
    to { transform: translateX(0); opacity: 1; }
}
main.blow-out { animation: scene-blow-out 0.45s ease-in both; }
main.settle-in { animation: scene-settle-in 0.55s ease-out both; }

.verdict-copy { min-width: 0; order: 2; flex: 1 1 100%; } /* mobile: mascot + score share one hero band, copy drops below */

.verdict-text {
    margin: 0;
    font-family: var(--font-pixel);
    font-size-adjust: none;
    font-size: 1.12rem;
    line-height: 1.4; /* the pixel font ships tall; 1.7 left dead air */
}

.verdict-reasons {
    margin: 0.5rem auto 0;
    max-width: 34ch;
    color: var(--muted);
    font-size: 0.95rem;
    line-height: 1.5;
}

.verdict-card.tier-great { border-color: var(--tier-great); }
.verdict-card.tier-ok { border-color: var(--tier-ok); }
.verdict-card.tier-bad { border-color: var(--tier-bad); }

.tier-great .verdict-score { color: var(--tier-great); }
.tier-ok .verdict-score { color: var(--tier-ok); }
.tier-bad .verdict-score { color: var(--tier-bad); }

.best-window {
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    flex-wrap: wrap;
    gap: 0.6rem;
}

.window-icon { font-size: 1.35rem; }

/* Bottom row: best window left, share right — one action row
   instead of a lonely centered button. */
.verdict-actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.75rem 1.5rem;
    margin-top: 1.25rem;
    padding-top: 1.1rem;
    border-top: 3px solid var(--ink);
}
.verdict-actions .best-window { flex: 1 1 auto; margin-top: 0; padding-top: 0; border-top: 0; }
.verdict-actions .share-btn { margin: 0 0 0 auto; }

.best-window p { margin: 0; font-size: 1rem; line-height: 1.45; }

/* ---------- grill rig picker ---------- */

.rig-picker {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.35rem;
    margin-bottom: 0.6rem;
}

.rig-label {
    font-family: var(--font-pixel);
    font-size-adjust: none;
    font-size: 0.62rem;
    line-height: 1.8;
    color: var(--muted);
}

.rig-options {
    display: inline-flex;
    background: var(--bg);
    border: 3px solid var(--ink);
    border-radius: var(--radius);
    box-shadow: 3px 3px 0 var(--ink);
    padding: 0.2rem;
    gap: 0.15rem;
}

.rig-btn {
    border: 0;
    background: transparent;
    color: var(--muted);
    font: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    padding: 0.4rem 0.7rem;
    border-radius: 2px;
    cursor: pointer;
    white-space: nowrap;
}

.rig-btn:hover { color: var(--text); }

.rig-btn[aria-pressed="true"] {
    background: var(--accent);
    color: var(--accent-ink);
}

.rig-blurb {
    margin: 0 0 1rem;
    text-align: center;
    color: var(--muted);
    font-size: 0.85rem;
    min-height: 1.2em;
}

.cook-suggest {
    margin: 0.6rem auto 0;
    max-width: 38ch;
    font-size: 0.95rem;
    line-height: 1.5;
    color: var(--accent-deep);
}

.share-btn {
    display: block;
    margin: 1.25rem auto 0;
    border: 3px solid var(--ink);
    background: var(--panel-edge);
    color: var(--text);
    font-family: var(--font-pixel);
    font-size-adjust: none;
    font-size: 0.7rem;
    line-height: 1.7;
    padding: 0.8rem 1.2rem;
    border-radius: var(--radius);
    box-shadow: 4px 4px 0 var(--ink);
    cursor: pointer;
    transition: transform 0.1s, box-shadow 0.1s;
}

.share-btn:hover { filter: brightness(1.15); }
.share-btn:active { transform: translate(2px, 2px); box-shadow: 2px 2px 0 var(--ink); }

.sunset-line {
    margin: 0.6rem 0 0;
    text-align: center;
    color: var(--muted);
    font-size: 0.85rem;
}

/* ---------- current conditions ---------- */

.current-card { padding: 1.5rem 1.25rem; margin-bottom: 1.5rem; }

.empty-state { text-align: center; padding: 1.5rem 0.75rem; }

/* Landing: the pup tends the grill, same pup as the verdict card.
   The grill stays optically centered; the pup sits in the right gutter. */
.landing-row {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: end;
}

.pixel-grill { grid-column: 2; }

.landing-mascot {
    grid-column: 3;
    justify-self: start;
    image-rendering: pixelated;
    width: 64px;
    height: 64px;
    margin: 0 0 6px 0.75rem;
    animation: mascot-idle 1.6s steps(2) infinite;
}

@media (max-width: 480px) {
    .landing-mascot { width: 48px; height: 48px; margin-left: 0.5rem; }
    .verdict-actions .share-btn { margin: 0 auto; }
    /* Shrink the front on small screens: the biggest cloud would
       otherwise fill three-quarters of a phone viewport. */
    .wcloud { transform: scale(calc(var(--ws) * 0.55)); }
}

.pixel-grill {
    width: 208px;
    height: 156px;
    image-rendering: pixelated;
    image-rendering: crisp-edges;
}

.empty-state p { color: var(--muted); font-size: 1rem; line-height: 1.55; margin: 1rem 0 0; }

body:not(.has-data) .current-main,
body:not(.has-data) .stat-row { display: none; }

body.has-data #currentEmpty { display: none; }

.current-main {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem 1.5rem;
    flex-wrap: wrap;
}

.current-place h2 {
    margin: 0;
    font-family: var(--font-pixel);
    font-size-adjust: none;
    font-weight: 400;
    font-size: clamp(0.72rem, 2.4vw, 0.95rem);
    line-height: 1.9;
}

.muted { color: var(--muted); margin: 0.35rem 0 0; font-size: 0.95rem; }

.current-condition {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    margin-top: 0.8rem;
}

.weather-icon { font-size: 2.6rem; line-height: 1; }

.condition-desc {
    font-family: var(--font-pixel);
    font-size-adjust: none;
    font-size: 0.66rem;
    line-height: 1.9;
    font-weight: 400;
}

.temp-big {
    font-family: var(--font-pixel);
    font-size-adjust: none;
    font-size: 2.4rem;
    line-height: 1.2;
    text-shadow: 3px 3px 0 rgba(255, 255, 255, 0.6);
}

/* High/low + feels-like tucked under the big temp to fill the header. */
.current-temp-wrap {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.3rem;
}
.temp-meta {
    font-size: 0.85rem;
    color: var(--muted);
    white-space: nowrap;
}

/* Phones: keep the temp in a right-hand column next to the city info.
   With wrapping allowed it dropped onto its own row and looked stranded. */
@media (max-width: 640px) {
    .current-main { flex-wrap: nowrap; align-items: flex-start; gap: 1rem; }
    .current-place { flex: 1 1 auto; min-width: 0; }
    .current-place .muted { font-size: 0.82rem; }
    .current-temp-wrap { flex: 0 0 auto; }
    .temp-big { font-size: 1.9rem; }
    .temp-meta { font-size: 0.78rem; }
    /* Keep the condition on one line next to its icon in the narrow column. */
    .current-condition { gap: 0.5rem; margin-top: 0.6rem; }
    .weather-icon { font-size: 2rem; }
    .condition-desc { font-size: 0.6rem; white-space: nowrap; }
}

.stat-row {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 0.625rem;
    margin-top: 1.5rem;
    padding-top: 1.25rem;
    border-top: 3px solid var(--ink);
}

.stat {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    padding: 0.8rem 0.9rem;
    background: var(--bg);
    border: 3px solid var(--ink);
    border-radius: var(--radius);
    min-width: 0;
}

.stat-label {
    font-family: var(--font-pixel);
    font-size-adjust: none;
    font-size: 0.6rem;
    line-height: 1.8;
    color: var(--muted);
}

.stat-value { font-size: 1.2rem; font-weight: 700; }

.stat-sub { font-size: 0.83rem; font-weight: 500; color: var(--muted); }

.uv-badge {
    align-self: flex-start;
    padding: 0.28rem 0.8rem;
    font-size: 1.05rem;
    font-weight: 700;
    color: #fff;
    border: 2px solid var(--ink);
    border-radius: var(--radius);
    text-shadow: 1px 1px 0 var(--ink);
}

.uv-low { background-color: #357a28; }
.uv-moderate { background-color: #c07a10; }
.uv-severe { background-color: #c22f2f; }

.aqi-badge {
    align-self: flex-start;
    padding: 0.28rem 0.8rem;
    font-size: 1.05rem;
    font-weight: 700;
    color: #fff;
    border: 2px solid var(--ink);
    border-radius: var(--radius);
    text-shadow: 1px 1px 0 var(--ink);
    white-space: nowrap;
}

.aqi-good { background-color: #357a28; }
.aqi-moderate { background-color: #a67c0a; }
.aqi-usg { background-color: #c2570f; }
.aqi-unhealthy { background-color: #c22f2f; }
.aqi-very { background-color: #7a2fb8; }
.aqi-na { background-color: var(--panel-edge); color: var(--muted); text-shadow: none; }

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

.section-title {
    margin: 0 0 0.85rem 0.25rem;
    font-family: var(--font-pixel);
    font-size-adjust: none;
    font-size: 0.8rem;
    line-height: 1.8;
    color: var(--text);
    text-shadow: 2px 2px 0 rgba(255, 255, 255, 0.6);
}

/* Phones + tablets: horizontal snap carousel that bleeds to the screen edges. */
.forecast-grid {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(228px, 262px);
    gap: 0.75rem;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--page-pad);
    margin-inline: calc(var(--page-pad) * -1);
    padding: 0.25rem var(--page-pad) 1rem;
    scrollbar-width: none;
}

.forecast-grid::-webkit-scrollbar { display: none; }

/* Unclassed <p> wrappers (e.g. around the verdict pill) get no browser margins. */
.forecast-card > p:not([class]) { margin: 0; }

.forecast-card {
    scroll-snap-align: start;
    padding: 1.2rem 1rem;
    text-align: center;
    transition: transform 0.1s;
    cursor: pointer;
}

.forecast-card:hover { transform: translate(-1px, -1px); box-shadow: 7px 7px 0 rgba(34, 51, 31, 0.35); }

.forecast-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* Chevron cue: rotates when the day is expanded. */
.expand-cue { display: block; width: 1.25rem; height: 1.25rem; margin: 0.7rem auto 0; }

.expand-cue::before {
    content: "";
    display: block;
    width: 0.55rem;
    height: 0.55rem;
    margin: 0.25rem auto 0;
    border-right: 2px solid var(--muted);
    border-bottom: 2px solid var(--muted);
    transform: rotate(45deg);
    transition: transform 0.2s ease;
}

.forecast-card[aria-expanded="true"] .expand-cue::before { transform: rotate(225deg); }

/* Day-detail panel: one shared panel below the forecast grid. Tapping a
   forecast day fills it — sibling cards never change size. */
.day-detail {
    margin-top: 1.25rem;
    padding: 1.25rem;
}

.day-detail-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 0.75rem;
}

.day-detail-title {
    margin: 0;
    font-size: 1.05rem;
    font-weight: 700;
    letter-spacing: -0.01em;
}

.day-detail-close {
    flex-shrink: 0;
    width: 2.25rem;
    height: 2.25rem;
    padding: 0;
    border-radius: var(--radius);
    border: 3px solid var(--ink);
    box-shadow: 3px 3px 0 var(--ink);
    background: var(--bg);
    color: var(--text);
    font-size: 0.95rem;
    line-height: 1;
    cursor: pointer;
    transition: transform 0.1s, box-shadow 0.1s;
}

.day-detail-close:hover { filter: brightness(1.2); }
.day-detail-close:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--ink); }

.day-detail .day-best-window { margin-top: 0; }

/* Best 3-hour window at the top of an expanded day. */
.day-best-window {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0.15rem 0 0.45rem;
    padding: 0.55rem 0.7rem;
    border-radius: var(--radius);
    background: rgba(255, 197, 61, 0.10);
    border: 2px solid var(--tier-ok);
    font-size: 0.85rem;
    font-weight: 600;
    line-height: 1.4;
}

.day-best-window .bw-score {
    margin-left: auto;
    flex-shrink: 0;
    padding: 0.15rem 0.55rem;
    border-radius: var(--radius);
    background: rgba(255, 197, 61, 0.22);
    font-size: 0.78rem;
    font-weight: 700;
    white-space: nowrap;
}

.day-best-window.none {
    background: var(--bg);
    border-color: var(--panel-edge);
    color: var(--muted);
    font-weight: 500;
}

.hour-row {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.42rem 0.15rem;
    border-bottom: 1px solid var(--panel-edge);
}

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

.hour-time { min-width: 3.1rem; color: var(--muted); font-weight: 600; font-size: 0.8rem; white-space: nowrap; }
.hour-icon { font-size: 1.2rem; line-height: 1; }
.hour-temp { font-weight: 700; font-size: 0.95rem; white-space: nowrap; }
.hour-rain { margin-left: auto; color: #8fb8d8; font-weight: 600; font-size: 0.8rem; white-space: nowrap; }
.hour-gusts { color: var(--muted); font-size: 0.8rem; white-space: nowrap; }
.hour-empty { color: var(--muted); font-size: 0.85rem; text-align: center; margin: 0.5rem 0; }

.forecast-date { margin: 0; font-size: 0.9rem; font-weight: 600; }

.forecast-icon { font-size: 2.1rem; line-height: 1.4; margin: 0.3rem 0; }

.forecast-temp { margin: 0.2rem 0 0.7rem; font-size: 1.55rem; font-weight: 800; letter-spacing: -0.02em; }

.verdict-pill {
    display: inline-block;
    margin: 0.5rem 0 0.75rem;
    padding: 0.4rem 0.85rem;
    font-size: 0.78rem;
    font-weight: 700;
    border-radius: var(--radius);
    border: 2px solid var(--ink);
    white-space: nowrap;
}

.verdict-pill.tier-great {
    color: var(--tier-great);
    background: rgba(143, 209, 79, 0.12);
}

.verdict-pill.tier-ok {
    color: var(--tier-ok);
    background: rgba(255, 197, 61, 0.12);
}

.verdict-pill.tier-bad {
    color: var(--tier-bad);
    background: rgba(255, 93, 93, 0.12);
}

.forecast-meta {
    display: flex;
    justify-content: space-between;
    gap: 0.5rem;
    margin: 0.32rem 0;
    font-size: 0.83rem;
    color: var(--muted);
}

.forecast-meta span:last-child {
    color: var(--text);
    font-weight: 600;
    text-align: right;
    white-space: nowrap;
}

/* ---------- fire weather ---------- */
/* Slim companion to the verdict: fire weather can veto the grill decision,
   so it sits directly under the verdict card instead of at the page bottom.
   The all-clear state stays quiet; real alerts get the loud treatment. */
.fire-card { padding: 1rem 1.25rem; margin-bottom: 1.25rem; }
.fire-card .card-eyebrow { margin-bottom: 0.55rem; }

.fire-status {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin: 0;
    font-size: 0.92rem;
    font-weight: 600;
    line-height: 1.5;
}

.fire-status-icon { font-size: 1.25rem; flex-shrink: 0; }
.fire-status.all-clear { color: var(--muted); font-weight: 500; font-size: 0.88rem; }
.fire-status.neutral { font-size: 0.85rem; font-weight: 500; color: var(--muted); }

/* Quiet fire state: slim banner instead of a tall card. */
.fire-card.fire-quiet { padding: 0.8rem 1.25rem; }
.fire-card.fire-quiet .card-eyebrow { margin-bottom: 0.35rem; }
.fire-card.fire-quiet .fire-status { font-size: 0.85rem; }
.fire-card.fire-quiet .burn-ban {
    margin-top: 0.35rem;
    padding-top: 0.35rem;
    border-top-width: 2px;
    font-size: 0.8rem;
}

.fire-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 0.75rem;
}

.fire-item {
    padding: 0.9rem 1rem;
    background: var(--bg);
    border: 3px solid var(--ink);
    border-left: 6px solid var(--panel-edge);
    border-radius: var(--radius);
}

.fire-event { margin: 0; font-weight: 800; font-size: 0.95rem; }
.fire-headline { margin: 0.3rem 0 0; color: var(--muted); font-size: 0.88rem; line-height: 1.5; }
.fire-times { margin: 0.45rem 0 0; font-size: 0.8rem; font-weight: 600; color: var(--muted); }

.fire-sev-extreme, .fire-sev-severe { border-left-color: var(--tier-bad); }
.fire-sev-moderate { border-left-color: var(--tier-ok); }
.fire-sev-minor, .fire-sev-unknown { border-left-color: var(--panel-edge); }

/* County burn-ban link: points at the real source, never faked data. */
.burn-ban {
    margin: 0.7rem 0 0;
    padding-top: 0.7rem;
    border-top: 3px solid var(--ink);
    font-size: 0.82rem;
    line-height: 1.55;
    color: var(--muted);
}

.burn-ban a { color: var(--accent); font-weight: 600; text-decoration: none; white-space: nowrap; }
.burn-ban a:hover { text-decoration: underline; }

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

.site-footer {
    margin-top: 2rem;
    text-align: center;
    color: var(--muted);
    font-size: 0.85rem;
    line-height: 1.6;
}

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

/* each attribution gets its own line, stacked */
.site-footer .credit { display: block; white-space: nowrap; }
.site-footer .credit-sep { display: none; }

/* The lawn rides at the bottom of the page flow (never glued to the
   viewport), with the privacy line resting on it. */
.lawn-wrap { position: relative; margin-top: auto; }
.lawn-wrap .lawn { position: relative; bottom: auto; display: block; }
.lawn-wrap .privacy-note {
    position: absolute;
    left: 50%;
    bottom: 12px;
    transform: translateX(-50%);
    margin: 0;
    width: max-content;
    max-width: calc(100% - 2rem);
    text-align: center;
    font-size: 0.75rem;
    color: #2f3d2b;
    text-shadow: 0 1px 2px rgba(255, 255, 255, 0.45);
    pointer-events: none;
}
body.sky-night .lawn-wrap .privacy-note { color: #dfe6d8; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6); }

/* City autocomplete: geocoding suggestions drop down under the input. */
.suggest-wrap { position: relative; min-width: 0; }
/* Lift the search card above later sections so the dropdown never slides
   under the verdict card. */
.search-card { position: relative; z-index: 10; }
@media (min-width: 640px) {
    .suggest-wrap { flex: 1 1 auto; }
}
.suggest {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    z-index: 60;
    margin: 0;
    padding: 0.35rem;
    list-style: none;
    background: var(--panel);
    border: 3px solid var(--ink);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
}
.suggest[hidden] { display: none; }
.suggest li {
    padding: 0.55rem 0.8rem;
    border-radius: 6px;
    cursor: pointer;
    font-size: 0.95rem;
    line-height: 1.35;
}
.suggest li.active { background: rgba(34, 51, 31, 0.12); }
.suggest-sub { color: var(--muted); font-size: 0.8rem; margin-left: 0.5rem; }

/* ---------- larger screens ---------- */

@media (min-width: 640px) {
    .search-row { flex-direction: row; }
    #searchBtn { flex-shrink: 0; }
    .locate-btn {
        align-self: stretch;
        flex-shrink: 0;
        width: 52px;
        min-height: 52px;
        padding: 0;
        justify-content: center;
        background: var(--panel);
        border: 3px solid var(--ink);
        box-shadow: 3px 3px 0 var(--ink);
    }
    .locate-btn:hover:not(:disabled) { filter: brightness(1.2); color: var(--text); }
    .locate-btn .locate-text { display: none; }
    .locate-btn .locate-icon { font-size: 1.25rem; }
}

@media (min-width: 720px) {
    :root { --page-pad: 1.5rem; }

    .site-header { margin-bottom: 2rem; }
    .site-header h1 { font-size: clamp(1.05rem, 2.8vw, 1.45rem); }
    .tagline { font-size: 1.05rem; }

    .search-card { padding: 1.5rem; margin-bottom: 1.5rem; }

    .current-card { padding: 2rem; margin-bottom: 2rem; }
    .current-place h2 { font-size: clamp(0.85rem, 2vw, 1.05rem); }
    .weather-icon { font-size: 3rem; }
    .condition-desc { font-size: 0.72rem; }
    .temp-big { font-size: clamp(1.9rem, 5vw, 2.7rem); }

    /* Desktop verdict: horizontal row, score pinned right. */
    .verdict-card { padding: 2rem; margin-bottom: 1.5rem; }
    .fire-card { padding: 1.2rem 1.5rem; margin-bottom: 1.5rem; }
    .card-eyebrow { text-align: left; }
    .verdict-main {
        flex-direction: row;
        flex-wrap: nowrap;
        align-items: center;
        text-align: left;
        gap: 1.25rem;
    }
    .verdict-copy { flex: 1; order: 1; }
    /* The score is its own column pinned to the card's right edge. */
    .verdict-score-wrap { order: 2; margin-left: auto; align-items: flex-end; }
    .verdict-score { font-size: 1.6rem; }
    .mascot { width: 72px; height: 72px; }
    .verdict-score-max { font-size: 0.65rem; }
    .verdict-text { font-size: clamp(0.95rem, 2.4vw, 1.2rem); margin-top: 0; }
    .verdict-reasons { margin: 0.3rem 0 0; max-width: none; font-size: 1rem; }
    .cook-suggest { margin-left: 0; margin-right: 0; max-width: none; }
    .best-window { justify-content: flex-start; text-align: left; }
    .best-window p { font-size: 1.05rem; }
    .sunset-line { text-align: left; }

    .alert-banner { padding: 1.1rem 1.4rem; margin-bottom: 1.5rem; }
}

@media (min-width: 800px) {
    .stat-row { grid-template-columns: repeat(4, 1fr); gap: 0.75rem; }
    .stat-value { font-size: 1.35rem; }
}

@media (min-width: 1024px) {
    /* Desktop: five-up grid, no carousel. */
    .forecast-grid {
        grid-auto-flow: row;
        grid-template-columns: repeat(5, 1fr);
        grid-auto-columns: unset;
        overflow: visible;
        scroll-snap-type: none;
        margin-inline: 0;
        padding: 0;
        gap: 1rem;
    }
}



/* Boost mode: the landing grill flares up while a search runs. */
.pixel-grill.boost {
    animation: grill-boost 0.6s steps(3) infinite;
    filter: drop-shadow(0 0 8px rgba(255, 122, 26, 0.8));
}

@keyframes grill-boost {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.06); }
}

#loadStatus {
    font-family: var(--font-pixel);
    font-size-adjust: none;
    font-size: 0.8rem;
    color: var(--accent-deep);
}

/* ---------- game feel ---------- */
/* Blinking arcade prompt on the landing state. */
.press-start {
    margin: 1rem 0 0;
    font-family: var(--font-pixel);
    font-size-adjust: none;
    font-size: 0.7rem;
    line-height: 1.8;
    letter-spacing: 0.1em;
    color: var(--accent-deep);
    animation: blink 1.1s steps(2, start) infinite;
}

@keyframes blink {
    to { visibility: hidden; }
}

/* Verdict card snaps in with a stepped pop. */
.verdict-card { animation: pop-in 0.35s steps(4) both; }

@keyframes pop-in {
    from { opacity: 0; transform: scale(0.85); }
    to { opacity: 1; transform: scale(1); }
}


/* Forecast cards cascade in one after another. */
.forecast-card:nth-child(1) { animation-delay: 0.05s; }
.forecast-card:nth-child(2) { animation-delay: 0.12s; }
.forecast-card:nth-child(3) { animation-delay: 0.19s; }
.forecast-card:nth-child(4) { animation-delay: 0.26s; }
.forecast-card:nth-child(5) { animation-delay: 0.33s; }

/* Day-detail panel snaps open. */
.day-detail { animation: pop-in 0.25s steps(3) both; }

/* Failed search: the search card shakes its head. */
.shake { animation: shake-x 0.4s steps(4); }

@keyframes shake-x {
    0%, 100% { transform: translateX(0); }
    25% { transform: translateX(-7px); }
    75% { transform: translateX(7px); }
}

/* Reduced motion: every game-feel animation off, full stop.
   Kept last in the file so no rule above can override it. */
@media (prefers-reduced-motion: reduce) {
    body::after { display: none; }
    .sky-decor { display: none; }
    .lightning { display: none; }
    .wipe { display: none; }
    *, *::before, *::after { animation: none !important; transition: none !important; }
    .forecast-card:hover, #searchBtn:hover:not(:disabled), #recent-searches button:hover, .locate-btn:hover:not(:disabled) { transform: none; }
    .forecast-grid { scroll-snap-type: none; }
}
