/* Self-hosted fonts (OFL): Latin subsets made by design-src/scripts/subset-fonts.sh.
   Fraunces roman keeps wght 500-650, opsz 30-144, SOFT 30; the italic is the one style the
   page uses (500, opsz 144, SOFT 60), declared over 400-700 so other weights reuse it, not faux bold. */
@font-face{font-family:"Fraunces";font-style:normal;font-weight:500 650;font-display:swap;src:url(../fonts/fraunces-roman.woff2) format("woff2")}
@font-face{font-family:"Fraunces";font-style:italic;font-weight:400 700;font-display:swap;src:url(../fonts/fraunces-italic.woff2) format("woff2")}
@font-face{font-family:"Nunito";font-style:normal;font-weight:400 700;font-display:swap;src:url(../fonts/nunito.woff2) format("woff2")}
:root{
  --peach:#F5B98A; --cream:#FBE8D2; --red:#B4202B; --green:#3F8F3C; --rust:#B45A3C; --ink:#2C1E2A;
  --ink-soft:#4A3A47; --cream-deep:#F3D8B8; --paper:#FFF7EC;
  --ice:#DCEAF4; --ice-deep:#BFD8EA; --snow:#FFFDF9; --pine:#35685C; --wood:#7A5236;
  /* gold: bright golds for rules, fills and dark grounds; --gold-ink (≥4.5:1) for small text on light grounds */
  --gold:#B88A3E; --gold-soft:#E2C48A; --gold-ink:#7A5518;
  /* section grounds (owner's Oct 17 review: rich roses, oranges, blues and yellows instead of beiges) */
  --rose:#F49AB2; --tangerine:#F7A350; --sun:#FAD25A; --royal:#1F3F8F;
  --display:"Fraunces","Georgia",serif; --body:"Nunito","Segoe UI",system-ui,sans-serif;
  --nav-h:76px; --pad:clamp(20px,5vw,72px); --ease:cubic-bezier(.16,1,.3,1);
  --shadow-sm:0 2px 4px rgba(44,30,42,.06),0 10px 24px -14px rgba(44,30,42,.35);
  --shadow-lg:0 4px 10px rgba(44,30,42,.05),0 34px 60px -34px rgba(44,30,42,.5);
}
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:auto;-webkit-text-size-adjust:100%}
html.lenis,html.lenis body{height:auto}
.lenis.lenis-smooth{scroll-behavior:auto!important}
body{background:var(--cream);color:var(--ink);font-family:var(--body);line-height:1.55;overflow-x:hidden;transition:background-color .9s var(--ease)}
main{overflow-x:clip}
img{display:block;max-width:100%}
a{color:inherit}
h1,h2,h3{font-family:var(--display);font-variation-settings:"opsz" 144,"SOFT" 30;font-weight:600;line-height:1.02;text-wrap:balance;letter-spacing:-.022em}
h1 em,h2 em,h3 em,.quote em{font-weight:500;font-style:italic;font-variation-settings:"opsz" 144,"SOFT" 60}
.label{font:600 11px/1 var(--body);letter-spacing:.3em;text-transform:uppercase}
.wrap{padding-left:var(--pad);padding-right:var(--pad);max-width:1440px;margin:0 auto}
:focus-visible{outline:3px solid var(--red);outline-offset:4px;border-radius:4px}

/* buttons: deep cranberry with a lit top edge and a real offset shadow */
.btn{display:inline-flex;align-items:center;gap:10px;background:linear-gradient(180deg,#C02A36 0%,#A51C29 100%);color:#fff;text-decoration:none;font:700 15px/1 var(--body);letter-spacing:.03em;padding:16px 24px;border-radius:999px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.22),0 1px 2px rgba(120,16,26,.3),0 12px 22px -12px rgba(150,20,32,.65);
  transition:transform .35s var(--ease),box-shadow .35s var(--ease),filter .35s var(--ease)}
.btn:hover{transform:translateY(-1px);filter:brightness(1.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 2px 4px rgba(120,16,26,.3),0 18px 30px -14px rgba(150,20,32,.7)}
.btn:active{transform:translateY(0)}
.btn svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round}
.btn.ghost{background:transparent;color:var(--ink);box-shadow:inset 0 0 0 1px rgba(44,30,42,.55)}
.btn.ghost:hover{background:rgba(255,250,243,.5);box-shadow:inset 0 0 0 1px var(--ink),var(--shadow-sm);filter:none}
.btn.cream{background:var(--paper);color:var(--ink);box-shadow:var(--shadow-sm)}
.btn.big{font-size:17px;padding:20px 30px}


/* nav */
nav{position:fixed;top:0;left:0;right:0;z-index:90;height:var(--nav-h);display:flex;align-items:center;justify-content:space-between;padding:0 var(--pad);color:var(--ink);transition:transform .5s var(--ease),background .4s,box-shadow .4s,height .4s var(--ease),color .4s}
nav.scrolled{background:rgba(251,232,210,.86);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);box-shadow:0 1px 0 rgba(44,30,42,.08);height:64px}
nav.on-ink{color:var(--cream)}
nav.on-ink.scrolled{background:rgba(44,30,42,.82);box-shadow:0 1px 0 rgba(251,232,210,.12)}
.brand{display:flex;align-items:center;gap:12px;text-decoration:none;color:inherit}
.brand .mark{width:40px;height:40px;transition:width .4s var(--ease),height .4s var(--ease)}
nav.scrolled .brand .mark{width:32px;height:32px}
.brand .word{font:650 17px/1 var(--display);font-variation-settings:"opsz" 30,"SOFT" 30;letter-spacing:-.01em}
.brand .word small{display:block;font:700 9px/1.4 var(--body);letter-spacing:.24em;text-transform:uppercase;opacity:.75;margin-top:3px}
.links{display:flex;gap:28px;list-style:none;font:700 13px/1 var(--body);letter-spacing:.04em}
.links a{text-decoration:none;opacity:.85;position:relative}
.links a::after{content:"";position:absolute;left:0;right:0;bottom:-6px;height:2px;background:currentColor;transform:scaleX(0);transform-origin:left;transition:transform .35s var(--ease)}
.links a:hover::after{transform:scaleX(1)}
nav .btn{padding:13px 20px;font-size:13px}
@media (max-width:900px){.links{display:none}.brand .word small{display:none}nav .btn{padding:12px 16px}}

/* mark */
.mark{display:block}

/* ══ HERO ════════════════════════════════════════════════════════════════════════════════════════
   One measured composition. The cast + stable were rendered as a single image (canvas 3073×1447,
   design-src/layers/meta.json) and split into layers that share one canvas:
     --cs  canvas height in px      --cx  canvas left edge      --lift  how far the ground sits above 2vh
   Every scene layer is  left: --cx + k·--cs,  height (or width) j·--cs,  bottom: 2vh + --lift.
   Resize the scene by changing --cs, never by nudging one layer.
   The scene doesn't move: no layer has pointer parallax or a scroll tween, because any relative
   movement exposes the layers' baked snow above the bank.
   ══════════════════════════════════════════════════════════════════════════════════════════════ */
:root{
  /* desktop: scene hugs the right, copy on the left */
  --cs:min(74vh,calc((100vw - 360px)/2.1237));
  --cx:calc(99vw - 2.1237*var(--cs));
  /* just enough for the feet to clear the bottom controls (phones lift a fixed 58px, below) */
  --lift:max(0px,calc(1vh + 50px - .078*var(--cs)));
}
#hero{position:relative;height:100svh;min-height:640px;overflow:hidden;cursor:default;
  /* the backdrop scales with the cast, not the viewport, capped by viewport height so the domes and spires
     never rise behind the hero copy (contrast-swept at ten desktop sizes; re-run if the copy or backdrop changes) */
  --bgimg:url(../assets/img/hero-backdrop.webp);
  --bgcap:100vh;
  --bgh:max(min(calc(2.2*var(--cs)),var(--bgcap)),calc(100vw/2.466));
  /* above the image, lavender fills tall screens and fades into the image top; if the backdrop changes,
     resample its top-row colour and update these stops and background-color */
  background-color:#8b87bf;
  background-image:linear-gradient(to bottom,#d9d2ee 0,#aaa3d6 calc(55% - 0.5*var(--bgh)),#8b87bf calc(100% - var(--bgh) + 2px),rgba(139,135,191,0) calc(100% - var(--bgh) + 0.35*var(--cs))),var(--bgimg);
  background-size:100% 100%,auto var(--bgh);background-position:0 0,center bottom;background-repeat:no-repeat}

/* sky: holds the stable, the baked cast and the ground sparkles */
.sky{position:absolute;inset:0;overflow:hidden}
.sparkles{position:absolute;left:0;right:0;bottom:0;height:22vh;z-index:5;pointer-events:none}
.sparkles i{position:absolute;width:4px;height:4px;border-radius:50%;background:#fff;box-shadow:0 0 6px rgba(255,255,255,.9);animation:twinkle 3.2s ease-in-out infinite}
@keyframes twinkle{50%{opacity:.15;transform:scale(.6)}}
#snowc{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:10}

/* scene layers, back to front: Reindeer (z 5), the cast image (6: stable + Santa, Mrs. Claus and the bookkeeper elf, baked into
   hero-cast.webp by design-src/scripts/hero-cast.py), elf boy and elf girl (8, their own images so they can hop),
   invisible hit areas for Santa/Mrs. Claus/elf (9), snowbank (9), snowdrift (10).
   hero-cast.webp starts at the trio's left edge (x 289 of the 1447-tall canvas). */
.nativity{position:absolute;bottom:calc(2vh + var(--lift));height:var(--cs);pointer-events:none;left:calc(var(--cx) + 0.1997*var(--cs));width:auto;z-index:6}
.nativity img,.ch img{height:100%;width:auto;max-width:none;filter:saturate(1.14) drop-shadow(0 2px 3px rgba(60,40,60,.22))}
.nativity img{display:block}

/* characters: each .ch is a --cs-tall box on the canvas; tap one to talk */
.ch{position:absolute;bottom:calc(2vh + var(--lift));height:var(--cs);z-index:8;pointer-events:auto;cursor:pointer;will-change:transform;-webkit-tap-highlight-color:transparent}
.ch .fig{height:100%;transform-origin:50% 100%}
.ch:not(.ch-deer) .fig{transform:none!important}
.ch img{transform-origin:50% 100%}
.ch-boy{left:calc(var(--cx) + 0.0124*var(--cs))}
.ch-girl{left:calc(var(--cx) + 1.7146*var(--cs))}
.ch-deer{left:calc(var(--cx) + 1.8922*var(--cs));z-index:5}
/* Santa, Mrs. Claus and the elf are in hero-cast.webp; their 1×1 imgs are transparent hit areas sized to each figure */
.ch-santa,.ch-mrs,.ch-elf{z-index:9}
.ch-elf{left:calc(var(--cx) + 0.2059*var(--cs))}
.ch-mrs{left:calc(var(--cx) + 0.3649*var(--cs))}
.ch-santa{left:calc(var(--cx) + 0.4927*var(--cs))}
.ch-elf img{width:calc(var(--cs)*0.1762);opacity:0}
.ch-mrs img{width:calc(var(--cs)*0.1417);opacity:0}
.ch-santa img{width:calc(var(--cs)*0.2281);opacity:0}

/* speech bubbles sit just above each head (head tops measured from the artwork, as % of the --cs-tall box) */
/* tap (or hover) hop: squash, jump, bounce. It animates `translate`/`scale` (not `transform`, which .fig pins above), so it
   works before GSAP has loaded. site.js adds .hop; reduced motion turns animations off. Only the boy, girl and Reindeer
   have visible art in their .fig; the others are invisible hit areas. */
@keyframes hop{0%{translate:0 0;scale:1 1}14%{translate:0 0;scale:1.08 .9}47%{translate:0 -34px;scale:.96 1.06}72%{translate:0 0;scale:1.06 .94}86%{translate:0 -6px;scale:1 1}100%{translate:0 0;scale:1 1}}
.ch .fig.hop{animation:hop .85s cubic-bezier(.3,.7,.4,1)}
.ch-santa{--head:59.4%}.ch-elf{--head:57.9%}.ch-mrs{--head:56.1%}.ch-boy{--head:50.4%}.ch-girl{--head:49.3%}.ch-deer{--head:55.6%}
.ch .say{position:absolute;left:50%;bottom:calc(var(--head,100%) + 12px);transform:translate(calc(-50% + var(--nx,0px)),10px) scale(.9);background:#fff;color:var(--ink);
  font:650 clamp(13px,1.15vw,17px)/1.2 var(--display);font-variation-settings:"opsz" 30,"SOFT" 30;padding:10px 16px;border-radius:16px;width:max-content;max-width:min(62vw,320px);text-align:center;
  opacity:0;transition:opacity .25s var(--ease),transform .35s var(--ease);box-shadow:0 2px 6px rgba(44,30,42,.08),0 16px 30px -16px rgba(44,30,42,.45);pointer-events:none;z-index:9}
.ch .say::after{content:"";position:absolute;left:calc(50% - var(--nx,0px));top:100%;width:14px;height:14px;background:#fff;transform:translate(-50%,-7px) rotate(45deg);border-radius:2px}
/* a talking character comes forward so its bubble isn't hidden by the callout or the hunt items */
.ch.talk{z-index:12}
.ch.talk .say{opacity:1;transform:translate(calc(-50% + var(--nx,0px)),0) scale(1)}

/* one ground: a full-width snowbank from the bottom up to the feet line (.078cs above the canvas bottom).
   The wavy cap is sized from --cs (not the bank's height), so its troughs never dip below the feet at any width */
.bank{position:absolute;left:0;right:0;bottom:0;height:calc(2vh + var(--lift) + .078*var(--cs));z-index:9;pointer-events:none;
  background:linear-gradient(180deg,#F4E5E2 0,#EBD6D8 35%,#E2CAD2 70%,#D8C1D5 100%)}
.bank .cap{position:absolute;left:0;right:0;bottom:calc(100% - 1px);width:100%;height:calc(.024*var(--cs));display:block}

/* ── hidden-object hunt ── */
/* the Reindeer peeks out from behind the snowdrift; found, it lifts (site.js, yPercent -4) so its legs end inside the drift,
   and it stays behind the drift even while talking */
.ch-deer .fig{position:relative}
.ch-deer:not(.found) .fig{animation:peek 3.2s ease-in-out infinite}
@keyframes peek{0%,88%,100%{transform:translateY(19%)}92%{transform:translateY(14%) rotate(-3deg)}96%{transform:translateY(17%) rotate(3deg)}}
.ch-deer.found,.ch-deer.talk{z-index:9}
.ch-deer .nose{position:absolute;left:45%;top:30%;width:2.6vh;height:2.6vh;border-radius:50%;background:radial-gradient(circle,#ff6b6b,rgba(255,60,60,0) 70%);transform:translate(-50%,-50%) scale(0);pointer-events:none}
.ch-deer.found .nose{animation:glow 1.1s ease-in-out infinite}
@keyframes glow{0%,100%{transform:translate(-50%,-50%) scale(1.2);opacity:.9}50%{transform:translate(-50%,-50%) scale(2.4);opacity:.5}}
/* the "?" rides just above the antlers */
.ch-deer .q{position:absolute;left:44%;bottom:58%;width:36px;height:36px;background:#fff;border-radius:50%;display:grid;place-items:center;font:650 20px/1 var(--display);color:var(--red);box-shadow:0 8px 16px -8px rgba(44,30,42,.6);animation:qbob 1.8s ease-in-out infinite;pointer-events:none}
@keyframes qbob{50%{transform:translateY(-8px) rotate(8deg)}}
.ch-deer.found .q{display:none}

/* the snowdrift sits on the bank, its base fading into it; #peek is its hit area */
.hidey,#peek{position:absolute;left:calc(var(--cx) + 1.7505*var(--cs));bottom:calc(1.5vh + var(--lift));width:calc(var(--cs)*0.4596)}
.hidey{z-index:10;pointer-events:none}
.hidey svg{width:100%;height:auto;display:block;filter:drop-shadow(0 -6px 10px rgba(44,30,42,.12));-webkit-mask-image:linear-gradient(#000 62%,transparent 96%);mask-image:linear-gradient(#000 62%,transparent 96%)}
.hidey path[fill="#BFD8EA"]{fill:#DDB0AC}
.hidey path[fill="#DCEAF4"]{fill:#F1D3C9}
.hidey path[fill="#FFFDF9"]{fill:#FFF3EA}
#peek{height:calc(var(--cs)*0.302);z-index:11;background:transparent;border:0;cursor:pointer;border-radius:50% 50% 18px 18px}
#peek:focus-visible{outline:3px dashed var(--red)}

/* "Tap the snowdrift!": the arrow sits over the drift's centre (cx + 1.98cs) at every width; the label clears the
   girl's head (~.49cs) where there's room */
.findme{position:absolute;z-index:11;right:calc(100% - var(--cx) - 1.98*var(--cs) - 13px);bottom:calc(2vh + var(--lift) + max(.3*var(--cs),.5*var(--cs) - 44px));
  display:flex;flex-direction:column;align-items:flex-end;gap:4px;pointer-events:none;animation:nudge 1.6s ease-in-out infinite}
@keyframes nudge{50%{translate:0 -9px}}
.findme b{background:var(--red);color:#fff;font:650 clamp(13px,1.1vw,16px)/1.15 var(--display);font-variation-settings:"opsz" 30,"SOFT" 30;letter-spacing:.005em;padding:11px 17px;border-radius:16px;box-shadow:0 12px 22px -10px rgba(180,32,43,.8);white-space:nowrap}
.findme svg{width:34px;height:40px;fill:none;stroke:var(--red);stroke-width:3.4;stroke-linecap:round;stroke-linejoin:round}
.found-deer .findme{display:none}

/* candy cane and golden star */
.hunt{position:absolute;z-index:9;background:none;border:0;padding:0;cursor:pointer;-webkit-tap-highlight-color:transparent}
.hunt svg{width:100%;height:100%;overflow:visible}
.hunt:focus-visible{outline:3px dashed var(--red);outline-offset:6px;border-radius:8px}
.hunt.got{animation:gotit .7s var(--ease);pointer-events:none}
@keyframes gotit{40%{transform:scale(1.5) rotate(-12deg)}100%{transform:scale(1) rotate(0)}}
#cane{left:9%;bottom:5vh;width:44px;height:96px;transform:rotate(-14deg)}
#cane path{stroke-linecap:round}
#cane .stripe{opacity:.9}
/* the cane's white stripes need an edge to read against the snowbank */
#cane svg{filter:drop-shadow(0 0 1px rgba(90,40,60,.55)) drop-shadow(0 2px 2px rgba(90,40,60,.25))}
#gstar{left:calc(var(--cx) + 1.6511*var(--cs));top:auto;bottom:calc(2vh + var(--lift) + .8023*var(--cs));width:48px;height:48px;transform:translateX(-50%)}
#gstar path{fill:rgba(255,255,255,.55);stroke:rgba(255,255,255,.9);stroke-width:1.6;transition:fill .4s,stroke .4s}
#gstar.got path{fill:#FFD36A;stroke:#fff;filter:drop-shadow(0 0 12px rgba(255,211,106,.9))}

/* counter + sound */
.hud{position:absolute;right:var(--pad);bottom:3vh;z-index:11;display:flex;align-items:center;gap:10px}
.counter{display:flex;align-items:center;gap:12px;background:rgba(255,247,236,.92);backdrop-filter:blur(6px);padding:10px 16px;border-radius:999px;font:650 14px/1 var(--display);font-variation-settings:"opsz" 30,"SOFT" 30;color:var(--ink);box-shadow:var(--shadow-sm);transition:background .4s,color .4s}
.counter .dots{display:flex;gap:5px}
.counter .dots i{width:11px;height:11px;border-radius:50%;background:rgba(44,30,42,.18);transition:background .3s var(--ease),transform .3s var(--ease)}
.counter .dots i.on{background:var(--red);transform:scale(1.25)}
.counter.done{background:var(--green);color:#fff}
.counter.done .dots i{background:#fff}
.sfx{width:42px;height:42px;border-radius:50%;border:0;background:rgba(255,247,236,.92);backdrop-filter:blur(6px);display:grid;place-items:center;cursor:pointer;box-shadow:var(--shadow-sm)}
.sfx svg{width:20px;height:20px;fill:none;stroke:var(--ink);stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round}
.sfx .off{display:none}
.sfx.muted .on{display:none}.sfx.muted .off{display:block}

/* hero copy: on the left over the sky, no halos; every text colour measured ≥4.5:1 against the bare sky
   at 1440/1024/820/390 (recheck if the backdrop changes) */
.hero-copy{position:absolute;left:var(--pad);top:calc(var(--nav-h) + 3vh);z-index:9;pointer-events:none;width:min(540px,40vw);display:flex;flex-direction:column;align-items:flex-start;text-align:left;gap:12px}
/* the kicker sits on deep lavender: ink text, a red rule */
.hero-copy .label{color:var(--ink);display:flex;align-items:center;gap:12px}
.hero-copy .label i{display:inline-block;width:34px;height:2px;background:var(--red)}
.hero-copy h1{font-size:clamp(28px,3.5vw,52px);color:var(--ink);letter-spacing:-.028em;line-height:1}
.hero-copy h1 .l{display:block;overflow:hidden;padding-bottom:.08em;margin-bottom:-.08em}
.hero-copy h1 .l > span{display:block}
/* hero entrance in CSS, so it plays at once (GSAP loads after the hero): headline lines rise, then label/copy/CTAs fade up.
   `translate`, not `transform`, so it doesn't fight the minibook's tilt or hover. Reduced motion turns animations off. */
@keyframes h1rise{from{translate:0 110%}to{translate:0 0}}
@keyframes heroup{from{translate:0 20px;opacity:0}to{translate:0 0;opacity:1}}
.hero-copy h1 .l>span{animation:h1rise 1s var(--ease) both}
.hero-copy h1 .l:nth-child(2)>span{animation-delay:.09s}
.hero-copy h1 .l:nth-child(3)>span{animation-delay:.18s}
.hero-copy .label,.hero-copy>p:not(.label),.hero-cta,.minibook{animation:heroup .8s var(--ease) both}
.hero-copy .label{animation-delay:.48s}.hero-copy>p:not(.label){animation-delay:.56s}.hero-cta{animation-delay:.64s}.minibook{animation-delay:.72s}
.hero-copy h1 .w{display:inline-block;transition:transform .3s var(--ease);pointer-events:auto}
.hero-copy h1 .w:hover{transform:translateY(-6px) rotate(-3deg)}
.hero-copy h1 em{font-style:italic;color:var(--red)}
/* (also sizes the kicker, which is a <p>) */
.hero-copy p{font-size:clamp(14px,1.05vw,16px);max-width:46ch;color:var(--ink)}
/* facts: one quiet line */
.stickers{display:flex;flex-wrap:wrap;justify-content:flex-start;gap:6px 22px;margin-top:4px;pointer-events:auto}
.sticker{display:inline-flex;align-items:center;gap:6px;color:var(--ink);font:600 13px/1.2 var(--body);letter-spacing:.06em}
.sticker svg{width:11px;height:11px;fill:var(--gold)}
.hero-cta{display:flex;flex-wrap:wrap;gap:14px;align-items:center;justify-content:flex-start;pointer-events:auto}
/* the outline button gets a frosted fill where it crosses rooftops */
.hero-cta .btn.ghost{background:rgba(255,250,243,.78);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.minibook{position:absolute;right:var(--pad);top:calc(var(--nav-h) + 5vh);z-index:8;width:clamp(96px,8.5vw,140px);aspect-ratio:2/3;border-radius:6px;overflow:hidden;box-shadow:0 20px 30px -14px rgba(44,30,42,.6),0 0 0 1px rgba(44,30,42,.1);transform:rotate(-8deg);transition:transform .4s var(--ease);cursor:pointer}
.minibook:hover{transform:rotate(-2deg) translateY(-8px) scale(1.06)}
.minibook img{width:100%;height:100%;object-fit:cover;object-position:50% 30%}
.minibook span{position:absolute;left:0;right:0;bottom:0;background:var(--red);color:#fff;font:700 8px/1 var(--body);letter-spacing:.18em;text-transform:uppercase;padding:6px 8px;text-align:center}

/* wide desktops: more room for the copy, so the scene is capped by height sooner */
@media (min-width:1281px){:root{--cs:min(74vh,calc((100vw - 600px)/2.1237))}}
@media (min-width:1700px){#hero{--bgcap:112vh}}
/* short 1280-wide screens (1280×720 fails the contrast sweep at 100vh) */
@media (min-width:901px) and (max-width:1280px) and (max-height:760px){#hero{--bgcap:92vh}}
/* phones, and short desktop screens where "Read about the book" lands on the cast's heads (the minibook and nav link go to #story too) */
@media (max-width:900px),(max-height:700px){.hero-cta .ghost{display:none}}

/* ≤900px: copy on top, scene centred under it. #hero is copy + scene tall instead of a full viewport, so tall
   phones and tablets don't get a band of empty sky; everything is lifted 58px to clear the bottom controls */
@media (max-width:900px){
  :root{--cs:min(44.8vw,52vh);--cx:calc(50vw - 1.0622*var(--cs));--lift:58px}
  #hero{height:auto;min-height:0;padding-bottom:calc(var(--cs) + var(--lift) + 2vh + 7vh);
    --bgh:max(calc(2.5*var(--cs) + var(--lift)),calc(100vw/2.466))}
  /* in normal flow and centred with margins, not translateX(-50%): site.js scrubs a transform on .hero-copy */
  .hero-copy{position:relative;left:0;right:0;top:auto;margin:calc(var(--nav-h) + 6px) auto 0;width:calc(100% - 32px);align-items:center;text-align:center;gap:10px}
  .hero-copy h1{font-size:clamp(34px,10vw,46px)}
  .hero-copy p{font-size:15px;max-width:none;font-weight:500}
  .stickers,.hero-cta{justify-content:center}
  .minibook{display:none}
  .ch .say{font-size:13px;padding:8px 12px;max-width:70vw}
  .ch-deer .q{width:28px;height:28px;font-size:17px}
  .findme b{font-size:13px;padding:9px 14px}
  .findme svg{width:26px;height:30px}
  /* the cane stands in the snow just left of the boy (his figure starts at cx + .079cs); it stays above him so it's
     clickable (his transparent box would otherwise swallow taps), and its base fades into the bank */
  #cane{left:calc(var(--cx) - .04*var(--cs));bottom:calc(2vh + var(--lift) + .05*var(--cs));width:calc(.11*var(--cs));height:calc(.24*var(--cs));z-index:10}
  #cane svg{-webkit-mask-image:linear-gradient(#000 82%,transparent 97%);mask-image:linear-gradient(#000 82%,transparent 97%)}
  #gstar{left:20%;bottom:calc(2vh + var(--lift) + 1.05*var(--cs));width:38px;height:38px}
  .hud{left:16px;right:16px;bottom:1.5vh;justify-content:space-between}
  .counter{font-size:12.5px;padding:9px 13px;gap:9px}
}

/* ribbon: gold stars */
.ribbon{background:linear-gradient(180deg,#B32432,#9E1A27);box-shadow:inset 0 1px 0 rgba(255,255,255,.12),inset 0 -1px 0 rgba(0,0,0,.12);color:#fff;overflow:hidden;padding:15px 0;
  font:600 clamp(14px,1.3vw,18px)/1 var(--display);font-variation-settings:"opsz" 30,"SOFT" 30;text-transform:uppercase;letter-spacing:.14em;will-change:transform}
.ribbon .track{display:flex;gap:0;white-space:nowrap;width:max-content}
.ribbon span{display:inline-flex;align-items:center;gap:22px;padding-right:22px}
.ribbon svg{width:14px;height:14px;fill:var(--gold-soft)}

/* generic section */
section{position:relative}
.sec{padding:clamp(80px,12vh,140px) 0}
/* kickers on the bright grounds: deep cranberry text with a red rule (gold on the dark sections) */
.eyebrow{display:flex;align-items:center;gap:12px;color:#861620;margin-bottom:20px}
.eyebrow i{width:28px;height:1px;background:var(--red);display:inline-block}
#fun .eyebrow,#reason .eyebrow,#author .eyebrow{color:var(--gold-soft)}
#fun .eyebrow i,#reason .eyebrow i,#author .eyebrow i{background:var(--gold-soft)}
.h2{font-size:clamp(36px,4.6vw,68px);max-width:16ch}
.lede{font-size:clamp(17px,1.35vw,21px);max-width:52ch;color:var(--ink-soft);line-height:1.65}
.rv{opacity:1}
html.fx .rv{opacity:0;transform:translateY(28px)}
html.fx .rv.in{opacity:1;transform:none;transition:opacity .9s var(--ease),transform .9s var(--ease)}

/* story */
#story{background:var(--rose)}
#story .grid{display:grid;grid-template-columns:1.1fr .9fr;gap:clamp(32px,6vw,96px);align-items:center}
#story .grid p+p{margin-top:16px}
.deer-card{position:relative;background:var(--paper);border-radius:18px;padding:32px;box-shadow:var(--shadow-lg);border:1px solid rgba(44,30,42,.06);overflow:hidden;transition:transform .4s var(--ease)}
.deer-card:hover{transform:rotate(-1deg) scale(1.01)}
.deer-card .real{position:absolute;right:7%;top:9%;height:56%;width:auto;max-width:none;transform:scaleX(-1);filter:drop-shadow(0 14px 14px rgba(44,30,42,.25))}
.deer-card svg.deer{width:100%;height:auto;display:block}
.deer-card .cap{display:flex;justify-content:space-between;align-items:center;margin-top:18px;color:var(--ink-soft);gap:12px;flex-wrap:wrap}
.deer-card .cap b{font:600 22px/1 var(--display);font-variation-settings:"opsz" 30,"SOFT" 30;color:var(--red)}
@media (max-width:900px){#story .grid{grid-template-columns:1fr}.deer-card{padding:22px}}

/* trail (pinned horizontal) */
#trail{background:var(--tangerine);color:var(--ink)}
#trail .pin{height:100svh;display:flex;flex-direction:column;justify-content:center;overflow:hidden;padding-top:var(--nav-h)}
#trail .head{flex:none;display:flex;justify-content:space-between;align-items:flex-end;gap:24px;margin-bottom:10px}
#trail .head .h2{font-size:clamp(30px,3.6vw,54px)}
#trail .path{flex:none;position:relative;height:72px;margin:0 var(--pad) 8px;pointer-events:auto}
#trail .path svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
#trail .path .dash{fill:none;stroke:var(--ink);stroke-width:2.5;stroke-dasharray:10 12;stroke-linecap:round}
/* clickable boot prints, deep cranberry so they read on orange */
#trail .print{fill:#861620;opacity:0;cursor:pointer;transition:transform .2s var(--ease)}
#trail .print.pop{animation:pop .5s var(--ease)}
@keyframes pop{40%{transform:translateY(-14px) scale(1.5)}100%{transform:none}}
#trail .deer-marker{position:absolute;left:0;top:50%;height:100px;width:auto;transform:translate(-50%,-56%)}
#trail .deer-marker img{height:100%;width:auto;max-width:none;filter:drop-shadow(0 10px 10px rgba(44,30,42,.25))}
.rail{flex:none;display:flex;gap:clamp(16px,2.2vw,32px);padding:0 var(--pad);width:max-content;will-change:transform}
.frame{position:relative;width:clamp(220px,min(26vw,40svh),380px);aspect-ratio:3/4;border-radius:14px;overflow:hidden;background:var(--cream);box-shadow:var(--shadow-lg);flex:none}
.frame img{position:absolute;max-width:none;top:0;left:0}
.frame .name{position:absolute;left:0;right:0;bottom:0;background:var(--ink);color:var(--cream);padding:12px 16px 13px;display:flex;flex-direction:column;align-items:flex-start;gap:3px}
.frame .name b{font:600 20px/1 var(--display);font-variation-settings:"opsz" 30,"SOFT" 30}
.frame .name span{font:700 9.5px/1.2 var(--body);letter-spacing:.16em;text-transform:uppercase;opacity:.7}
.frame.f-char{background:var(--cream);transition:transform .3s var(--ease)}
.frame.f-char:hover{transform:translateY(-8px)}
.frame.f-char .orb{position:absolute;left:50%;top:46%;width:82%;aspect-ratio:1;border-radius:50%;transform:translate(-50%,-50%);background:radial-gradient(circle at 50% 30%,#FBE8D2 0%,var(--peach) 62%,var(--rust) 100%);opacity:.9}
.frame.f-char .v{position:absolute;left:50%;top:auto;bottom:52px;height:82%;width:auto;max-width:none;transform:translateX(-50%);transition:opacity .45s var(--ease);filter:drop-shadow(0 18px 18px rgba(44,30,42,.28))}
.frame.f-char .side{opacity:0}
.frame.f-char:hover .front,.frame.f-char:focus-within .front{opacity:0}
.frame.f-char:hover .side,.frame.f-char:focus-within .side{opacity:1}
.frame.f-char .name span::after{content:" · tap to turn"}
@media (hover:none){.frame.f-char .name span::after{content:""}}
.frame.f-end{background:linear-gradient(180deg,#B32432,#951826);color:#fff;display:flex;flex-direction:column;justify-content:space-between;padding:28px;box-shadow:none}
.frame.f-end h3{font-size:clamp(28px,3vw,42px);color:#fff}
@media (max-width:900px){
  #trail .pin{height:auto;padding:80px 0 60px;overflow:visible}
  #trail .head{flex-direction:column;align-items:flex-start}
  .rail{width:auto;overflow-x:auto;scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;margin:0;padding:12px 20px 20px}
  .frame{width:min(72vw,300px);scroll-snap-align:start}
  #trail .path{margin:0 20px 6px}
}

/* what's inside: royal blue, cream text, gold hairline panels */
#fun{background:var(--royal);color:var(--cream);padding:clamp(56px,8vh,96px) 0;position:relative;overflow:hidden}
#fun .h2{color:var(--cream);font-size:clamp(30px,3.6vw,52px)}
#fun .grid{display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(14px,2vw,26px);margin-top:36px}
#fun .blob{display:none}
.funcard{background:rgba(255,255,255,.06);border:1px solid rgba(226,196,138,.45);border-radius:16px;padding:28px 26px;display:flex;flex-direction:column;gap:14px;transition:transform .35s var(--ease),background .3s}
.funcard:hover{transform:translateY(-3px);background:rgba(255,255,255,.1);border-color:rgba(226,196,138,.5)}
.funcard svg{width:40px;height:40px;fill:none;stroke:var(--gold-soft);stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.funcard svg circle{fill:var(--gold-soft)}
.funcard b{font:600 21px/1.05 var(--display);font-variation-settings:"opsz" 30,"SOFT" 30;color:var(--cream)}
.funcard span{font-size:15px;color:rgba(251,232,210,.78);line-height:1.6}
@media (max-width:900px){#fun .grid{grid-template-columns:1fr 1fr;gap:12px}.funcard span{font-size:14px}}
@media (max-width:600px){#fun .grid{grid-template-columns:1fr}.funcard{display:grid;grid-template-columns:34px 1fr;column-gap:16px;row-gap:6px;align-items:start;padding:20px}.funcard svg{grid-row:span 2;width:34px;height:34px}}

/* reason (ink): a gold star */
#reason{color:var(--cream);background:var(--ink)}
#reason .inner{display:grid;grid-template-columns:.9fr 1.1fr;gap:clamp(32px,6vw,96px);align-items:center}
#reason .lede{color:rgba(251,232,210,.8)}
#reason .star-wrap{position:relative;aspect-ratio:1;max-width:460px;margin:0 auto;width:100%}
#reason .star-wrap svg{width:100%;height:100%;overflow:visible}
#reason .star-wrap circle[stroke]{stroke:var(--gold-soft)}
#reason .walker{position:absolute;left:-6%;bottom:-4%;height:66%;width:auto;max-width:none;transform:scaleX(-1);filter:drop-shadow(0 20px 24px rgba(0,0,0,.45));z-index:2}
#reason .quote{font:500 clamp(22px,2.3vw,32px)/1.35 var(--display);font-variation-settings:"opsz" 60,"SOFT" 30;color:var(--cream);margin-top:28px;max-width:26ch}
#reason .quote em{color:var(--gold-soft);font-style:italic}
#bigstar{fill:url(#goldstar);cursor:pointer}
#bigstar.spin{animation:spin 1s var(--ease)}
@keyframes spin{100%{transform:rotate(360deg)}}
@media (max-width:900px){#reason .inner{grid-template-columns:1fr}#reason .star-wrap{max-width:240px}}

/* series: Book One leads, the two follow-ons stack beside it (no empty cards) */
#series{background:var(--sun)}
#series .stack{position:relative;display:grid;grid-template-columns:1.15fr 1fr;grid-template-rows:auto auto;align-items:stretch;gap:clamp(16px,2.4vw,32px);margin-top:48px}
#series .card.hero-card{grid-row:span 2}
.card{background:var(--paper);border-radius:20px;padding:30px;min-height:0;display:flex;flex-direction:column;gap:14px;box-shadow:var(--shadow-lg);border:1px solid rgba(44,30,42,.07);transform-origin:50% 120%;transition:transform .35s var(--ease),box-shadow .35s var(--ease)}
.card:hover{transform:translateY(-4px);box-shadow:0 6px 14px rgba(44,30,42,.06),0 40px 70px -36px rgba(44,30,42,.55)}
.card .num{font:600 48px/1 var(--display);font-variation-settings:"opsz" 144,"SOFT" 30;color:var(--red);letter-spacing:-.03em}
.card h3{font-size:clamp(24px,2.2vw,32px)}
.card p{color:var(--ink-soft)}
.card .tag{margin-top:auto;display:inline-flex;align-items:center;gap:8px;color:var(--gold-ink);font:600 11px/1 var(--body);letter-spacing:.2em;text-transform:uppercase}
.card .tag i{width:8px;height:8px;border-radius:50%;background:currentColor;display:inline-block}
.card.hero-card{background:var(--ink);color:var(--cream);border-color:transparent}
.card.hero-card h3{color:var(--cream)}
.card.hero-card p{color:rgba(251,232,210,.8)}
.card.hero-card .tag,.card.hero-card .num{color:var(--gold-soft)}
.card .art{overflow:hidden;aspect-ratio:5/4;margin:-30px -30px 4px;border-radius:20px 20px 0 0;background:var(--peach)}
/* framed from just above Santa's head (y≈150 of 1043) so it isn't cut off */
.card .art img{display:block;width:100%;height:100%;object-fit:cover;object-position:50% 30%}
@media (max-width:900px){#series .stack{grid-template-columns:1fr}#series .card.hero-card{grid-row:auto}.card .art{aspect-ratio:4/3}.card .art img{object-position:50% 28%}}

/* Book One, the author, questions */
#book{background:var(--tangerine)}
.glance-soon{display:grid;grid-template-columns:auto 1fr;gap:clamp(28px,5vw,72px);align-items:center}
.glance-cover{width:clamp(140px,16vw,220px);height:auto;border-radius:6px;box-shadow:var(--shadow-lg);transform:rotate(-3deg)}
#author{background:var(--royal);color:var(--cream)}
#author .h2{color:var(--cream)}
#author .lede{color:rgba(251,232,210,.88)}
.author>div{max-width:820px}
#faq{background:var(--sun)}
.faq{margin-top:32px;max-width:820px;border-top:1px solid rgba(44,30,42,.3)}
.faq details{border-bottom:1px solid rgba(44,30,42,.3)}
.faq summary{cursor:pointer;list-style:none;padding:20px 44px 20px 0;position:relative;font:600 clamp(18px,1.6vw,22px)/1.3 var(--display);font-variation-settings:"opsz" 30,"SOFT" 30}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"+";position:absolute;right:6px;top:50%;transform:translateY(-50%);font:400 28px/1 var(--body);color:#861620}
.faq details[open] summary::after{content:"\2013"}
.faq p{padding:0 0 22px;max-width:62ch;color:var(--ink-soft);line-height:1.65}
@media (max-width:900px){.glance-soon{grid-template-columns:1fr}}

/* join */
#join{background:var(--rose);overflow:hidden}
#join .inner{display:grid;grid-template-columns:1fr auto;gap:40px;align-items:center}
#join .h2{font-size:clamp(40px,5.4vw,84px)}
#join .stamp{width:clamp(160px,18vw,240px);height:auto;color:var(--ink)}
#join .stamp .ring{fill:none;stroke:currentColor;stroke-width:2}
#join .stamp text{font:700 13.5px var(--body);letter-spacing:.28em;text-transform:uppercase;fill:currentColor}
#join .stamp use{color:var(--ink)}
@media (max-width:900px){#join .inner{grid-template-columns:1fr}#join .stamp{width:150px;justify-self:end;margin-top:-10px}}

/* launch-list form (#join) */
.signup{margin-top:30px;max-width:620px;display:grid;gap:16px;justify-items:start}
.signup .fields{display:grid;grid-template-columns:1fr 1.35fr;gap:14px;width:100%}
.signup .wide{grid-column:1/-1}
.signup label{display:grid;gap:7px;font:600 13px/1.2 var(--body);letter-spacing:.04em;color:var(--ink)}
.signup label i{font-style:normal;font-weight:400;color:var(--ink-soft)}
.signup input,.signup textarea{font:500 17px/1.2 var(--body);color:var(--ink);background:var(--paper);border:1px solid rgba(44,30,42,.35);border-radius:14px;padding:15px 16px;width:100%;
  box-shadow:inset 0 1px 2px rgba(44,30,42,.08);transition:border-color .2s,box-shadow .2s}
.signup textarea{resize:vertical;min-height:110px;line-height:1.45}
.signup input:focus,.signup textarea:focus{outline:none;border-color:var(--ink);box-shadow:0 0 0 3px rgba(134,22,32,.35)}
.signup .hp{position:absolute;left:-9999px;width:1px;height:1px;opacity:0}
.signup .btn[disabled]{opacity:.7;cursor:progress}
.signup .msg{min-height:1.4em;font:600 15px/1.4 var(--body);color:var(--ink)}
.signup.err .msg{color:#861620}
.signup.ok .msg{font:500 20px/1.35 var(--display);font-variation-settings:"opsz" 30,"SOFT" 30}
.signup.done .fields,.signup.done .btn{display:none}
@media (max-width:600px){.signup .fields{grid-template-columns:1fr}.signup .btn{width:100%;justify-content:center}}

/* footer */
footer{background:var(--ink);color:var(--cream);position:relative;overflow:hidden;padding:clamp(70px,10vh,120px) 0 40px}
footer .wm{position:absolute;right:-6vw;bottom:-8vw;width:44vw;max-width:620px;color:var(--cream);opacity:.07;pointer-events:none}
footer .grid{display:grid;grid-template-columns:1.2fr 1fr 1fr;gap:40px;position:relative}
footer h3{font-size:clamp(28px,3vw,44px);max-width:14ch;color:var(--cream);font-weight:500;font-style:italic;font-variation-settings:"opsz" 144,"SOFT" 60}
footer ul{list-style:none;display:grid;gap:12px;font:700 14px/1.3 var(--body)}
footer ul a{text-decoration:none;opacity:.85;word-break:break-word}
footer ul a:hover{opacity:1;text-decoration:underline;text-underline-offset:4px}
footer .label{opacity:.6;margin-bottom:16px;color:var(--gold-soft)}
footer .bottom{margin-top:60px;padding-top:22px;border-top:1px solid rgba(251,232,210,.14);display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;font-size:13px;opacity:.7;position:relative}
@media (max-width:900px){footer .grid{grid-template-columns:1fr}footer .wm{width:80vw;right:-20vw;bottom:-18vw}}

/* confetti */
#conf{position:fixed;inset:0;pointer-events:none;z-index:95}

/* reduced motion */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation:none!important;transition:none!important}
  html.fx .rv{opacity:1!important;transform:none!important}
  .ch,.ch .fig{transform:none!important;opacity:1!important}
  #snowc{display:none}
  .hero-copy h1 .l span{transform:none!important;opacity:1!important}
  .rail{transform:none!important;width:auto;overflow-x:auto;padding:12px var(--pad) 20px}
  #trail .pin{height:auto;padding:80px 0 60px}
  #trail .print{opacity:1!important}
  .card{transform:none!important;opacity:1!important}
  .funcard:hover,.card:hover,.frame.f-char:hover,.deer-card:hover{transform:none!important}
  #conf{display:none}
  .ribbon{transform:none!important}
  #bigstar{opacity:1!important;transform:none!important}
}

/* ── perf + a11y pass (Oct 18) ── */
/* portrait phones/tablets: the hero shows at most ~36% of the backdrop's width (it is 2.5·cs + lift tall,
   cs = 44.8vw), so a centre crop looks identical and is a third of the bytes. Same query as the preload in layout.tsx. */
@media (max-width:900px) and (max-aspect-ratio:1/1){#hero{--bgimg:url(../assets/img/hero-backdrop-phone.webp)}}
.sr-only{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
/* the red ring is under 3:1 on the dark grounds; use gold there */
footer :focus-visible,nav.on-ink :focus-visible{outline-color:var(--gold-soft)}
/* sections focused by the nav links (tabindex=-1) don't need a ring round the whole section */
[tabindex="-1"]:focus{outline:none}
/* was .6 opacity: 4.3:1 on ink */
footer .label{opacity:.75}
/* the three hit areas over the baked cast overlap a few px; Mrs. Claus's is the narrowest (25px on phones),
   so she sits on top to keep a full 24px tap/click target (WCAG 2.5.8). Stacking only, positions unchanged. */
.ch-mrs{z-index:10}

/* deferred below-the-fold images (data-defer in home.html, see app/page.tsx): until site.js gives them a src,
   keep the alt text from showing in the empty box. Without JS the <noscript> copy shows instead. */
img[data-src]{color:transparent}
/* !important: rules like `.card .art img{display:block}` are more specific */
@media (scripting:none){img[data-src]{display:none!important}}
