/* Winter theme (31 Oct 2026, JOB_2026-10-31_causehub-winter-site.md): snow settled on the header edge with a few icicles, a
   soft snowfall with depth (in the home hero, and since 2 Nov 2026 behind the whole page), ice crystals and frost in the home hero,
   a snowbank on the footer arch with a small snowman. No Christmas
   items (they come later as the christmas folder, which loads this file and winter.js before its own). Colours only through
   tokens (Daylight and Lamplight); on the cream page the snow is drawn cool white with a blue-grey underside, so it reads in
   daylight too. CSS motion is only transform, opacity and a stroke drawing in, each with a fixed number of runs; everything
   that answers a tap (springs, puffs, the swirl) is winter.js, full pages only, never with reduced motion (the falling snow is
   winter.js too, on quiet pages as well). Classes, not the
   theme id, carry every rule, so a theme built on top of winter gets the same look. */
:root {
  --ws-snow: #FFFFFF; --ws-snow-0: rgba(255, 255, 255, 0); --ws-shade: #D2DEEB; --ws-edge: #A9BED6; --ws-ice: rgba(206, 228, 248, .96); --ws-ice-tip: rgba(206, 228, 248, .12);
  --ws-ice-shine: rgba(255, 255, 255, .9); --ws-crystal: #9CB9DA; --ws-crystal-core: #F4F9FF; --ws-frost: rgba(122, 158, 200, .4);
  --ws-fog: rgba(196, 216, 240, .55); --ws-sky: rgba(196, 218, 242, .5); --ws-sky-0: rgba(196, 218, 242, 0);
  --ws-scarf: #E0644F; --ws-scarf-stripe: #FBE3C8; --ws-knit: #E9A93A; --ws-band: #F6E6C4; --ws-coal: #2B2723; --ws-nose: #EE8A3A;
  --ws-arm: #7A5A3E; --ws-shadow: rgba(84, 112, 150, .2); --ws-glint: rgba(255, 255, 255, .95);
  --ws-flake: #D6E2F1; --ws-flake-edge: rgba(160, 186, 220, .5); --ws-flake-0: rgba(160, 186, 220, 0);
  --ws-bd-flake: #C2D2E7; --ws-bd-edge: rgba(128, 160, 204, .5); --ws-bd-0: rgba(128, 160, 204, 0); --ws-bd-a0: .75; --ws-bd-a1: .85; --ws-bd-a2: .5;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ws-snow: #EEF3F9; --ws-snow-0: rgba(238, 243, 249, 0); --ws-shade: #AFC0D4; --ws-edge: #7A8FA9; --ws-ice: rgba(190, 214, 240, .9); --ws-ice-tip: rgba(190, 214, 240, .1);
    --ws-ice-shine: rgba(255, 255, 255, .75); --ws-crystal: #8FB1D8; --ws-crystal-core: #EAF3FE; --ws-frost: rgba(196, 220, 248, .34);
    --ws-fog: rgba(120, 150, 196, .22); --ws-sky: rgba(84, 116, 168, .26); --ws-sky-0: rgba(84, 116, 168, 0);
    --ws-scarf: #D9604D; --ws-scarf-stripe: #F3DCC2; --ws-knit: #DFA23C; --ws-band: #EADBBD; --ws-coal: #24211E; --ws-nose: #E68436;
    --ws-arm: #9A7756; --ws-shadow: rgba(0, 0, 0, .3); --ws-glint: rgba(236, 244, 255, .95);
    --ws-flake: #FFFFFF; --ws-flake-edge: rgba(220, 232, 248, .5); --ws-flake-0: rgba(220, 232, 248, 0);
    --ws-bd-flake: #FFFFFF; --ws-bd-edge: rgba(220, 232, 248, .42); --ws-bd-0: rgba(220, 232, 248, 0); --ws-bd-a0: .5; --ws-bd-a1: .6; --ws-bd-a2: .26;
  }
}
:root[data-theme="dark"] {
  --ws-snow: #EEF3F9; --ws-snow-0: rgba(238, 243, 249, 0); --ws-shade: #AFC0D4; --ws-edge: #7A8FA9; --ws-ice: rgba(190, 214, 240, .9); --ws-ice-tip: rgba(190, 214, 240, .1);
  --ws-ice-shine: rgba(255, 255, 255, .75); --ws-crystal: #8FB1D8; --ws-crystal-core: #EAF3FE; --ws-frost: rgba(196, 220, 248, .34);
  --ws-fog: rgba(120, 150, 196, .22); --ws-sky: rgba(84, 116, 168, .26); --ws-sky-0: rgba(84, 116, 168, 0);
  --ws-scarf: #D9604D; --ws-scarf-stripe: #F3DCC2; --ws-knit: #DFA23C; --ws-band: #EADBBD; --ws-coal: #24211E; --ws-nose: #E68436;
  --ws-arm: #9A7756; --ws-shadow: rgba(0, 0, 0, .3); --ws-glint: rgba(236, 244, 255, .95);
  --ws-flake: #FFFFFF; --ws-flake-edge: rgba(220, 232, 248, .5); --ws-flake-0: rgba(220, 232, 248, 0);
    --ws-bd-flake: #FFFFFF; --ws-bd-edge: rgba(220, 232, 248, .42); --ws-bd-0: rgba(220, 232, 248, 0); --ws-bd-a0: .5; --ws-bd-a1: .6; --ws-bd-a2: .26;
}

/* Sprite parts (selectors match the symbol originals; the clones inherit the colours). */
.ws-snow { fill: var(--ws-snow); } .ws-snow-shade { fill: var(--ws-shade); }
.ws-st-snow { stop-color: var(--ws-snow); } .ws-st-shade { stop-color: var(--ws-shade); }
.ws-st-fade { stop-color: var(--ws-snow); stop-opacity: 0; } .ws-st-fade-shade { stop-color: var(--ws-edge); stop-opacity: 0; }
.ws-st-ice { stop-color: var(--ws-ice); } .ws-st-ice-tip { stop-color: var(--ws-ice-tip); }
.ws-ice-shine { stroke: var(--ws-ice-shine); }
.ws-cr-edge { stroke: var(--ws-crystal); } .ws-cr-core { stroke: var(--ws-crystal-core); } .ws-cr-hub { fill: var(--ws-crystal-core); stroke: var(--ws-crystal); stroke-width: 1.6; }

/* head: snow settled on the header's bottom edge, icicles on full pages; it scrolls away with the page like every head strip. */
.ws-head > .ws-cap { filter: drop-shadow(0 1px 0 var(--ws-edge)); }
.ws-head > .ws-cap-thin { top: -1px; }

/* The snow (winter.js builds the flakes once and plays their fall, flutter and wind as Web Animations of transform). Daylight flakes
   are a cool light grey-blue, the colour snow has against a bright sky, so they read on the cream page; Lamplight flakes are white.
   Far flakes are small and sharp, near ones big and soft. Without the script (or with reduced motion) the hosts stay empty or still. */
.ws-snow { position: absolute; left: 0; top: 0; width: 100%; overflow: hidden; }
.ws-ly { position: absolute; left: 0; top: 0; right: 0; bottom: 0; }
.ws-fw, .ws-ff { position: absolute; left: 0; top: 0; width: 0; height: 0; }
.ws-fl { position: absolute; left: 0; top: 0; border-radius: 50%;
  background: radial-gradient(closest-side, var(--ws-flake) 0, var(--ws-flake) 45%, var(--ws-flake-edge) 72%, var(--ws-flake-0) 100%); }
.ws-ly-0 .ws-fl { opacity: .72; }
.ws-ly-1 .ws-fl { opacity: .9; }
.ws-ly-2 .ws-fl { opacity: .55; background: radial-gradient(closest-side, var(--ws-flake) 0, var(--ws-flake) 12%, var(--ws-flake-edge) 55%, var(--ws-flake-0) 100%); }

/* backdrop (2 Nov 2026, Sergiu: "the snow falling should go on all the website, behind the texts, still look good and readable"): one
   fixed layer of falling snow behind the whole page, full and quiet pages. Under every card, text, button, field and the donate box
   (z-index -1: only the page's own background lies below it), never taking a tap. It starts at the sticky header's bottom edge, so
   the header's frosted glass never blurs moving snow; on a phone with the floating donate bar it ends above the bar, its last
   pixels fading out (a still mask, played by the compositor); the footer and every card hide the flakes that pass behind them, so
   they fall into the footer's snowbank. Reduced motion: not there at all (no motion, no falling snow). Its flakes have their own
   tokens: in Daylight a
   deeper blue-grey than the hero's (the cream page has no cold sky behind them), in Lamplight fainter (a white flake under light
   text would cost contrast); dark text stays at AA or better over a flake's centre in Daylight. */
.ws-backdrop { position: fixed; left: 0; right: 0; top: var(--head-h, 68px); bottom: 0; z-index: -1; overflow: hidden; contain: strict; }
.ws-snow-all { height: 100%; }
.ws-sheet { position: absolute; left: 0; top: 0; width: 100%; height: 0; }
.ws-backdrop .ws-fl { background: radial-gradient(closest-side, var(--ws-bd-flake) 0, var(--ws-bd-flake) 45%, var(--ws-bd-edge) 72%, var(--ws-bd-0) 100%); }
.ws-backdrop .ws-ly-0 .ws-fl { opacity: var(--ws-bd-a0); }
.ws-backdrop .ws-ly-1 .ws-fl { opacity: var(--ws-bd-a1); }
.ws-backdrop .ws-ly-2 .ws-fl { opacity: var(--ws-bd-a2); background: radial-gradient(closest-side, var(--ws-bd-flake) 0, var(--ws-bd-flake) 12%, var(--ws-bd-edge) 55%, var(--ws-bd-0) 100%); }
@media (max-width: 999px) {
  .has-give-bar .ws-backdrop { bottom: calc(76px + env(safe-area-inset-bottom, 0px));
    -webkit-mask-image: linear-gradient(#000 calc(100% - 90px), rgba(0, 0, 0, 0)); mask-image: linear-gradient(#000 calc(100% - 90px), rgba(0, 0, 0, 0)); }
}
@media (prefers-reduced-motion: reduce) { .ws-backdrop { display: none; } }

/* home.hero: cold light from the top, frost growing in the two top corners, the snowfall (behind the text), ice crystals. */
.ws-sky { position: absolute; left: 0; right: 0; top: 0; height: 460px; background: linear-gradient(var(--ws-sky), var(--ws-sky-0)); }
.ws-frost { position: absolute; top: 0; width: clamp(132px, 19vw, 250px); height: clamp(115px, 16.5vw, 217px); background: radial-gradient(closest-side at 0 0, var(--ws-fog), rgba(0, 0, 0, 0)); }
.ws-frost-l { left: 0; }
.ws-frost-r { right: 0; transform: scaleX(-1); }
.ws-fern { fill: none; stroke: var(--ws-frost); stroke-width: 1.15; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1; stroke-dashoffset: 0;
  animation: ws-grow 3.6s ease-out .5s 1 both; }
/* app.js plays the decorations again on a tap (season-replay, animation-name none for one frame); the frost has grown once and stays,
   so the corners never blink empty while someone plays with the snow. */
:root.season-replay .ws-hero .ws-fern { animation-name: ws-grow !important; }
.ws-snow-hero { height: 100%; max-height: 980px; -webkit-mask-image: linear-gradient(#000 84%, rgba(0, 0, 0, 0)); mask-image: linear-gradient(#000 84%, rgba(0, 0, 0, 0)); }
.ws-crystal { position: absolute; display: block; width: 44px; height: 44px; }
.ws-crystal > svg { width: 100%; height: 100%; animation: ws-sway 7s ease-in-out 1.2s 8 alternate; }
.ws-crystal-1 { left: max(28px, calc(50% - 566px)); top: 76px; width: 58px; height: 58px; }
.ws-crystal-2 { right: max(40px, calc(50% - 540px)); top: 52px; width: 40px; height: 40px; }
.ws-crystal-2 > svg { animation-duration: 8.5s; animation-delay: 2.2s; animation-direction: alternate-reverse; }
.ws-crystal-3 { left: max(118px, calc(50% - 486px)); top: 292px; width: 30px; height: 30px; }
.ws-crystal-3 > svg { animation-duration: 6.2s; animation-delay: .4s; }
.ws-crystal-4 { right: max(52px, calc(50% - 596px)); top: 318px; width: 64px; height: 64px; }
.ws-crystal-4 > svg { animation-duration: 9s; animation-delay: 3s; animation-direction: alternate-reverse; }
@media (max-width: 699px) {
  .ws-sky { height: 360px; }
  .ws-crystal-1 { left: 8px; top: 20px; width: 38px; height: 38px; }
  .ws-crystal-2 { right: 16px; top: 104px; width: 28px; height: 28px; }
  .ws-crystal-3, .ws-crystal-4 { display: none; }
}

/* cause.give (quiet): a little snow resting on the give box's top edge and one still crystal. */
.ws-give { top: -11px; right: 26px; width: 112px; height: 30px; }
.ws-give > svg { position: absolute; }
.ws-g-cap { left: 0; top: 0; width: 112px; height: 20px; filter: drop-shadow(0 1px 0 var(--ws-edge)); }
.ws-g-crystal { right: -16px; top: -12px; width: 24px; height: 24px; transform: rotate(14deg); }

/* foot (2 Nov 2026, Sergiu: the snow "should reach the footer and look wintery there"): a soft snowbank settled along the whole footer
   arch, thinning out at the steep ends where snow would slide off, with a mound and the small snowman sitting in it. Static: the
   falling flakes pass behind the footer (it is drawn over the backdrop), so each one sinks into the bank's powdery top and is gone; no
   pile grows and no flake is followed. Four copies of the arch, each a few pixels higher than the one under it (the stroke keeps
   its width at every screen size): a blue-grey shadow on the footer, the bank, its lumpy top, a soft powder above it. */
.ws-bank { position: absolute; left: 0; top: -40px; width: 100%; height: calc(var(--arch-sm) + 52px); }
.ws-bank > svg { position: absolute; left: 0; width: 100%; height: var(--arch-sm); }
.ws-bank-shade { top: 42px; } .ws-bank-shade path { stroke: url(#ws-g-bank-shade); stroke-width: 14px; }
.ws-bank-body { top: 34px; } .ws-bank-body path { stroke: url(#ws-g-bank); stroke-width: 18px; }
.ws-bank-top { top: 27px; filter: blur(1.6px); } .ws-bank-top path { stroke: url(#ws-g-bank); stroke-width: 14px; stroke-linecap: round; stroke-dasharray: 34 7 18 9 52 6 26 8 44 7; }
.ws-bank-powder { top: 21px; filter: blur(6px); opacity: .5; } .ws-bank-powder path { stroke: url(#ws-g-bank); stroke-width: 20px; }
@media (max-width: 699px) {
  .ws-bank-shade { top: 42px; } .ws-bank-shade path { stroke-width: 10px; }
  .ws-bank-body { top: 36px; } .ws-bank-body path { stroke-width: 13px; }
  .ws-bank-top { top: 31px; filter: blur(1.2px); } .ws-bank-top path { stroke-width: 10px; stroke-dasharray: 24 5 13 7 36 5 18 6 30 6; }
  .ws-bank-powder { top: 27px; filter: blur(4px); } .ws-bank-powder path { stroke-width: 14px; }
}
.ws-patch { position: absolute; right: 21%; bottom: -24px; width: 150px; height: 86px; transform-origin: 100% 100%; }
.ws-patch > * { position: absolute; }
.ws-mound { left: 14px; bottom: 6px; width: 112px; height: 18px; border-radius: 50%; background: radial-gradient(closest-side, var(--ws-snow) 58%, var(--ws-snow-0) 100%); }
.ws-snowman { left: 42px; bottom: 9px; width: 58px; height: 77px; transform-origin: 50% 96%; }
.ws-snowman > svg { width: 100%; height: 100%; }
.ws-sm-shadow { fill: var(--ws-shadow); } .ws-sm-arm { stroke: var(--ws-arm); } .ws-sm-coal { fill: var(--ws-coal); } .ws-sm-smile { stroke: var(--ws-coal); }
.ws-sm-nose { fill: var(--ws-nose); } .ws-sm-scarf { fill: var(--ws-scarf); } .ws-sm-stripe { stroke: var(--ws-scarf-stripe); }
.ws-sm-knit { fill: var(--ws-knit); } .ws-sm-band { fill: var(--ws-band); } .ws-sm-pom { fill: var(--ws-band); }
.ws-sm-hat { transform-box: fill-box; transform-origin: 50% 100%; }
.ws-glint { width: 5px; height: 5px; border-radius: 50%; background: radial-gradient(closest-side, var(--ws-glint), rgba(255, 255, 255, 0)); opacity: .2;
  animation: ws-glint 2.4s ease-in-out 1s 10 alternate; }
.ws-glint-1 { left: 12px; bottom: 16px; } .ws-glint-2 { left: 112px; bottom: 15px; animation-delay: 2.1s; } .ws-glint-3 { left: 128px; bottom: 9px; animation-delay: 3.3s; }
@media (max-width: 699px) { .ws-patch { transform: scale(.82); right: 14%; } }

/* The hint line under the visitor switch: only where tapping does something (full pages, motion allowed). */
.season-hint { margin: 0; font-size: .84rem; color: var(--ink-3); }
:root[data-season-level="quiet"] .season-hint, :root[data-season-off] .season-hint { display: none; }
@media (prefers-reduced-motion: reduce) { .season-hint { display: none; } }

@keyframes ws-grow { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes ws-sway { from { transform: translateY(0) rotate(-7deg); } to { transform: translateY(7px) rotate(9deg); } }
@keyframes ws-glint { from { opacity: .15; transform: scale(.6); } to { opacity: 1; transform: scale(1.3); } }

/* Puffs (winter.js): one layer over the window, made on the first tap, under the sticky header, never taking a tap; each puff flake
   is played once by the compositor and removed. */
.ws-fx-layer { position: fixed; left: 0; top: 0; right: 0; bottom: 0; overflow: hidden; z-index: 35; }
.ws-pf { position: absolute; left: 0; top: 0; width: 5px; height: 5px; margin: -2.5px 0 0 -2.5px; border-radius: 50%; opacity: 0;
  background: radial-gradient(closest-side, var(--ws-flake) 0, var(--ws-flake) 45%, var(--ws-flake-edge) 72%, var(--ws-flake-0) 100%); }
.ws-pf-near { width: 11px; height: 11px; margin: -5.5px 0 0 -5.5px; background: radial-gradient(closest-side, var(--ws-flake) 0, var(--ws-flake) 15%, var(--ws-flake-edge) 55%, var(--ws-flake-0) 100%); }
.ws-pf-glint { width: 7px; height: 7px; margin: -3.5px 0 0 -3.5px; background: radial-gradient(closest-side, #FFECBE 0, #FFECBE 30%, rgba(242, 189, 81, .85) 60%, rgba(242, 189, 81, 0) 100%); }
