/* ──────────────────────────────────────────────────────────────────────────
   ULTRA BYAR — SEASONS. The additive layer, and nothing but.

   THE RULE THIS FILE OBEYS: it styles NOTHING that already exists. Every
   selector below starts at `.sn`, which is a container that only exists when
   a tenant is entitled to Seasons AND has switched them on. There is no
   `body {}`, no `.hero {}`, no `:root {}` override anywhere in this file — so
   with Seasons off the page is byte-for-byte what it was, and with Seasons on
   the base design is untouched underneath. SeasonLayerTest fails the build if
   that ever stops being true.

   HOW THE SEASON IS FELT WITHOUT REPAINTING ANYTHING: `backdrop-filter`
   recolours what is ALREADY painted behind the layer — autumn warms the page,
   winter cools it — the way a filter over a lens changes a photograph without
   repainting the room. The first build tried a coloured gradient with
   mix-blend-mode: multiply instead, and a browser check killed it: a fixed
   z-indexed overlay is its own stacking context, so there is nothing behind it
   to blend with and the gradient landed as a translucent film that turned the
   headline from black to washed grey. A filter has no such problem — black
   text stays black.

   TWO THINGS THAT WOULD BREAK IT, both avoided deliberately:
     • `contain: paint` (or `filter`/`opacity` on an ancestor) forms a BACKDROP
       ROOT, which clips the backdrop to that ancestor and leaves the filter
       with nothing to work on. `.sn` therefore has no containment.
     • painting the tint OVER the page instead of filtering it — see above.

   The layer is inert: pointer-events:none the whole way down, aria-hidden on
   the container, and it sits below the navigation on both surfaces (z-index 30
   against the tenant nav's 100 and the platform nav's 40), so nothing a
   visitor needs to tap is ever covered.
   ────────────────────────────────────────────────────────────────────────── */

.sn {
    position: fixed;
    inset: 0;
    z-index: 30;
    pointer-events: none;
    overflow: hidden;
    /* NO `contain` here — see the note above. It would form a backdrop root
       and the season's light would have nothing to fall on. */
}

/* The season's light. Applied from first paint rather than faded in: a tint
   that arrives late reads as a page that flickered. */
.sn-tint {
    position: absolute;
    inset: 0;
    -webkit-backdrop-filter: var(--sn-filter, none);
    backdrop-filter: var(--sn-filter, none);
}

/* A breath of the season's own colour at the top and bottom edges, and
   NOTHING across the middle band where the words are — the gradient is fully
   transparent from 26% to 74%, so no text ever sits under it. */
.sn-sky {
    position: absolute;
    inset: 0;
    opacity: 0;
    transition: opacity 900ms ease;
    background: linear-gradient(180deg,
        var(--sn-sky-1, transparent) 0%,
        transparent 26%,
        transparent 74%,
        var(--sn-sky-2, transparent) 100%);
}
.sn.sn-lit .sn-sky { opacity: .55; }

/* Weather at the corners of the screen — the season's mid tone, kept to the
   margins by radial gradients that are transparent well before the centre. */
.sn-vig {
    position: absolute;
    inset: -8%;
    opacity: 0;
    transition: opacity 1200ms ease;
    background:
        radial-gradient(90% 46% at 50% -6%, var(--sn-glow, transparent) 0%, transparent 62%),
        radial-gradient(90% 46% at 50% 106%, var(--sn-soft, transparent) 0%, transparent 60%);
}
.sn.sn-lit .sn-vig { opacity: .22; }

/* One canvas for every moving thing: motes, petals, cirrus, leaves, snow,
   and winter's accumulation. One rAF loop, parked when the tab is hidden. */
.sn-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    opacity: 0;
    transition: opacity 1200ms ease;
}
.sn.sn-lit .sn-canvas { opacity: 1; }

/* Summer's glare: a warm bloom at the top edge that breathes. No particles
   fall in summer — light does the work (the canvas draws the cirrus). */
.sn[data-season="summer"] .sn-glaze {
    position: absolute;
    inset: 0 0 auto 0;
    height: 40vh;
    background: radial-gradient(70% 100% at 50% 0%, var(--sn-soft, #FDE68A) 0%, transparent 68%);
    opacity: 0;
    animation: sn-breathe 9s ease-in-out infinite;
}
.sn.sn-lit[data-season="summer"] .sn-glaze { opacity: .3; }
.sn:not([data-season="summer"]) .sn-glaze { display: none; }

@keyframes sn-breathe {
    0%, 100% { transform: translateY(0) scale(1); }
    50%      { transform: translateY(-1.2%) scale(1.04); }
}

/* Winter's frost creeps in from the corners as the page is scrolled; JS sets
   --sn-depth from the scroll position, so the deeper you go the colder it
   looks. The only season that BUILDS instead of looping. */
.sn[data-season="winter"] .sn-frost {
    position: absolute;
    inset: 0;
    background:
        radial-gradient(34% 26% at 0% 0%,   #fff 0%, transparent 64%),
        radial-gradient(34% 26% at 100% 0%, #fff 0%, transparent 64%),
        radial-gradient(42% 24% at 0% 100%, #fff 0%, transparent 62%),
        radial-gradient(42% 24% at 100% 100%, #fff 0%, transparent 62%);
    opacity: calc(var(--sn-depth, 0) * .45);
    transition: opacity 400ms linear;
}
.sn:not([data-season="winter"]) .sn-frost { display: none; }

/* A visitor who has asked their device for less movement gets the season's
   colour and none of its motion. The canvas still paints ONE frame (JS), so
   the page still looks like the season — it simply stops moving. */
@media (prefers-reduced-motion: reduce) {
    .sn-sky, .sn-vig, .sn-canvas { transition: none; }
    .sn[data-season="summer"] .sn-glaze { animation: none; }
}

/* A phone gets the season, not a fireworks display: less colour at the edges,
   and JS scales the particle count by the same reasoning. */
@media (max-width: 640px) {
    .sn.sn-lit .sn-sky { opacity: .42; }
    .sn.sn-lit .sn-vig { opacity: .16; }
}

/* Print: paper has no weather. */
@media print {
    .sn { display: none !important; }
}
