/* The stage home page (Round 4). Every size is design px times --u (docs/round4-specs/T5-compose.md, numbers from docs/DESIGN-SPEC.md).
   Wide layout: the 852 px desktop reference; under 700 px: the 390 px phone reference. */

/* ---------- tokens ---------- */
:root { --u: calc(min(100vw, 1440px) / 852); }
@media (max-width: 699px) { :root { --u: calc(min(100vw, 600px) / 390); } }

body.stage {
  --sky: var(--navy-900);
  --text: var(--cream);
  --accent: var(--gold-300);           /* gold text; navy in light */
  --gold: var(--gold-300);             /* rules, borders, dots and arrows: gold in both modes */
  --button: var(--navy-800);
  --button-text: color-mix(in srgb, var(--cream) 92%, var(--navy-800));
  --body-text: color-mix(in srgb, var(--cream) 86%, var(--navy-900));
  --cta-glow: 0 0 calc(var(--u) * 18) color-mix(in srgb, var(--gold) 35%, transparent);
  --col: calc(var(--u) * 852);
  --veil: var(--sky);                  /* halos and scrims behind text over the art; a pale sky in light */
  --sides: black 85%, transparent;     /* the wide closed curtain's soft sides; light ends them inside the velvet, whose dark edge folds show on a pale sky */
  --bell-rx: 280; --bell-ry: 280;      /* the desktop closed curtain's side ellipse (u), per mode so each matches its reference's width; light is wider */
  --drape-lift: none;                  /* the open drapes' filter: light lifts them to the reference's bright red (js/fx/curtain.js draws the reveal with it) */
  --curtain-lift: none;                /* the same for the closed curtain: the light reference's velvet is lighter */
  /* About's scrim: soft in the dark, where a firm one shows as a dark oval on the snow; firm in light, where it is pale and the navy text needs it. */
  --about-scrim: color-mix(in srgb, var(--veil) 80%, transparent) 45%, transparent;
  /* Text over the scene: a tight halo of sky under the title shadow of the recipes, so every line keeps AA over bright snow and velvet. */
  --halo-dark: 0 0 .12em color-mix(in srgb, black 70%, transparent), 0 .04em .5em color-mix(in srgb, black 50%, transparent);
  --halo: 0 0 .12em color-mix(in srgb, var(--veil) 75%, transparent), 0 .04em .5em color-mix(in srgb, var(--veil) 55%, transparent);
}
:root[data-mode=light] body.stage {
  --gold: var(--stage-gold-light);
  --button: var(--stage-button-light);
  --button-text: var(--stage-curtain-text);
  --body-text: color-mix(in srgb, var(--cream) 85%, white);
  --cta-glow: none;
  --veil: color-mix(in srgb, var(--sky) 30%, white);
  --sides: black 76%, transparent 88%;
  --bell-rx: 330; --bell-ry: 480;
  --drape-lift: brightness(2);
  --curtain-lift: contrast(0.85) brightness(1.3);
  --about-scrim: color-mix(in srgb, var(--veil) 88%, transparent) 80%, transparent;
}
/* The chosen appearance for the browser's own parts (form controls, scroll bars), as css/appearance.css does on classic pages. */
:root[data-composition=stage][data-mode=light] { color-scheme: light; }
:root[data-composition=stage][data-mode=dark] { color-scheme: dark; }
@media (prefers-color-scheme: light) {
  :root:not([data-mode]) body.stage {
    --gold: var(--stage-gold-light);
    --button: var(--stage-button-light);
    --button-text: var(--stage-curtain-text);
    --body-text: color-mix(in srgb, var(--cream) 85%, white);
    --cta-glow: none;
    --veil: color-mix(in srgb, var(--sky) 30%, white);
    --sides: black 76%, transparent 88%;
    --bell-rx: 330; --bell-ry: 480;
    --drape-lift: brightness(2);
    --curtain-lift: contrast(0.85) brightness(1.3);
    --about-scrim: color-mix(in srgb, var(--veil) 88%, transparent) 80%, transparent;
  }
}

/* ---------- page (undoes the arcade's fixed single view from tokens.css) ---------- */
/* overflow-x on the root goes to the viewport, so the body's own clip applies to the body: nothing past the screen edge adds page width. */
html:has(body.stage) { height: auto; background: var(--navy-900); overflow-x: clip; }
body.stage {
  position: relative;
  height: auto;
  min-height: 100dvh;
  overflow: visible;
  overflow-x: clip;
  overscroll-behavior: auto;
  background: var(--sky);
  color: var(--text);
  font: 500 calc(var(--u) * 15) / 1.2 var(--font-stage);
}
.stage main, .stage .bar, .stage .foot { position: relative; z-index: 1; width: var(--col); margin-inline: calc((100% - var(--col)) / 2); }
:where(.stage) a { color: inherit; text-decoration: none; }
/* Gold in the dark; the navy accent in light, where gold on the pale sky would not reach 3:1. */
.stage :focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: calc(var(--u) * 4); }
.stage .notice { margin: 8px auto; padding: 8px 12px; max-width: 600px; background: var(--button); color: var(--button-text); border-radius: 8px; }

.skip-link { position: absolute; z-index: 10; left: 8px; top: -60px; padding: 10px 14px; background: var(--button); color: var(--button-text); border-radius: 8px; }
.skip-link:focus { top: 8px; }

/* ---------- scene: three plate bands behind everything ---------- */
.scene { position: absolute; inset: 0; z-index: 0; display: flex; flex-direction: column; overflow: hidden; pointer-events: none; }
.scene-band { position: relative; flex: none; }
.scene-band img { display: block; width: 100%; height: 100%; object-fit: fill; }
.scene-top { aspect-ratio: 887 / 585; z-index: 1; }
.scene-bottom { aspect-ratio: 887 / 754; z-index: 1; margin-top: auto; }
/* The snow band's file has 2 spare rows at each end: percentage margins follow the scene width, so -200%/887 is 2 plate rows. */
.scene-mid { flex: 1 1 0; min-height: 0; margin-block: calc(-200% / 887); }
.scene-points, .scene-riders, .scene-sky { position: absolute; inset: 0; }

/* ---------- bar ---------- */
/* Sticky from the start (no shift when it sticks); its sky fades in over the first 24 px of scroll: a scroll timeline, else js/site-nav.js sets data-scrolled. */
.stage .bar {
  position: sticky;
  top: 0;
  z-index: 3;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  height: calc(var(--u) * 67.5 + env(safe-area-inset-top));
  padding: env(safe-area-inset-top) max(calc(var(--u) * 37), env(safe-area-inset-right)) 0 max(calc(var(--u) * 42.5), env(safe-area-inset-left));
}
.stage .bar::after { content: ""; position: absolute; z-index: -1; inset: 0 calc((var(--col) - 100vw) / 2); background: color-mix(in srgb, var(--sky) 94%, transparent); box-shadow: 0 1px 0 color-mix(in srgb, var(--gold) 28%, transparent); opacity: 0; pointer-events: none; transition: opacity .2s; }
.stage .bar[data-scrolled]::after { opacity: 1; }
@supports (animation-timeline: scroll()) {
  .stage .bar::after { transition: none; animation: bar-fill linear both; animation-timeline: scroll(root); animation-range: 0 24px; }
}
@keyframes bar-fill { to { opacity: 1; } }
.bar-mark { position: absolute; top: 0; left: 0; width: 1px; height: 24px; visibility: hidden; pointer-events: none; }
.bar-menu { justify-self: start; display: flex; align-items: center; gap: calc(var(--u) * 27.5); padding: 0; color: var(--text); }
/* The open curtains reach up behind the bar: there the menu (and on desktop the log-in link) go cream on a dark halo, readable over velvet. */
.bar-menu, .bar-link { text-shadow: var(--halo), 0 0 .3em var(--veil), 0 0 .6em var(--veil); }
[data-reveal=open] .bar-menu { --text: var(--stage-curtain-text); --veil: black; --halo: var(--halo-dark); }
[data-reveal=open] .bar-link { --text: var(--stage-curtain-text); --veil: black; --halo: var(--halo-dark); text-shadow: var(--halo), 0 0 .3em var(--veil), 0 0 .6em var(--veil), 0 0 .6em var(--veil), 0 0 1em var(--veil), 0 0 1em var(--veil); }
.bar-menu-icon { filter: drop-shadow(0 0 calc(var(--u) * 2) var(--veil)); }
.bar-menu-icon { width: calc(var(--u) * 24.5); height: calc(var(--u) * 17); background: linear-gradient(currentColor 0 0) top / 100% calc(var(--u) * 2.2) no-repeat, linear-gradient(currentColor 0 0) center / 100% calc(var(--u) * 2.2) no-repeat, linear-gradient(currentColor 0 0) bottom / 100% calc(var(--u) * 2.2) no-repeat; }
.bar-menu-label { font-size: calc(var(--u) * 14); font-weight: 600; }
.bar-logo { justify-self: center; display: block; }
.bar-logo img { width: calc(var(--u) * 37.5); height: calc(var(--u) * 38.5); object-fit: contain; }
.bar-account { justify-self: end; display: flex; align-items: center; gap: calc(var(--u) * 26.5); }
.bar-link { font-size: calc(var(--u) * 13); font-weight: 600; color: var(--text); }
/* Signed in: the notifications bell and the account link (src/pages.ts bellAndAccount). */
.bar-account #esa-notifications { display: grid; place-items: center; min-width: 44px; min-height: 44px; color: var(--text); font-size: calc(var(--u) * 15); }
.bar-account .esa-account-link { display: flex; align-items: center; gap: calc(var(--u) * 8); min-height: 44px; max-width: calc(var(--u) * 180); color: var(--text); font-size: calc(var(--u) * 13); font-weight: 600; text-shadow: var(--halo); }
.bar-account .esa-account-link > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stage .esa-avatar-wrap { position: relative; flex: none; }
.stage .esa-avatar { width: calc(var(--u) * 26); height: calc(var(--u) * 26); object-fit: contain; }
.stage .esa-avatar-wrap[data-avatar=custom] .esa-avatar { border-radius: 50%; object-fit: cover; }
.stage #esa-notification-list { margin: calc(var(--u) * 70) max(16px, env(safe-area-inset-right)) auto auto; width: min(26rem, calc(100% - 2rem)); max-height: 60dvh; overflow: auto; padding: 1rem; border: 1px solid var(--gold); border-radius: 12px; background: var(--button); color: var(--button-text); font: 500 15px / 1.4 var(--font-stage); }
.stage #esa-notification-list a { color: inherit; text-decoration: underline; }

/* ---------- buttons ---------- */
.stage .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: calc(var(--u) * 12);
  min-height: 0;
  height: calc(var(--u) * 37);
  padding: 0 calc(var(--u) * 24);
  border: calc(var(--u) * 1.5) solid var(--gold);
  border-radius: calc(var(--u) * 9);
  background: color-mix(in srgb, var(--button) 88%, transparent);
  box-shadow: none;
  color: var(--button-text);
  font: 600 calc(var(--u) * 15.5) / 1 var(--font-stage);
  letter-spacing: 0;
  text-transform: none;
  white-space: nowrap;
  transition: color .15s, background-color .15s, border-color .15s, transform .16s ease-out;
}
.stage .btn:hover { background: var(--button); color: var(--text); }
.stage .btn[hidden] { display: none; }
.stage .btn-small { height: calc(var(--u) * 31.5); padding: 0 calc(var(--u) * 14); font-size: calc(var(--u) * 14); border-radius: calc(var(--u) * 8); }
.stage .btn-cta {
  height: calc(var(--u) * 56);
  padding: 0 calc(var(--u) * 32);
  border-width: calc(var(--u) * 2);
  border-radius: calc(var(--u) * 11);
  font-size: calc(var(--u) * 27.5);
  box-shadow: var(--cta-glow);
}
/* The arrow is drawn: the latin font subset has no U+2192. */
.btn-arrow { position: relative; flex: none; width: calc(var(--u) * 15); height: calc(var(--u) * 1.6); background: var(--gold); border-radius: 1px; }
.btn-arrow::after { content: ""; position: absolute; right: 0; top: 50%; width: calc(var(--u) * 7); height: calc(var(--u) * 7); border: solid var(--gold); border-width: calc(var(--u) * 1.6) calc(var(--u) * 1.6) 0 0; transform: translateY(-50%) rotate(45deg); transform-origin: 70% 30%; }
.btn-cta .btn-arrow { display: none; }

/* ---------- hero ---------- */
/* Page y 67.5 to 547: the paper sheet starts where the hero ends. */
.hero { position: relative; min-height: calc(var(--u) * 479.5); }
/* Art is placed in page coordinates: its box starts at the page top, under the bar. Clipped at the screen edges: a curtain running
   off the side must not widen the page (phones zoom out to fit it). */
.hero-art { position: absolute; inset: calc(var(--u) * -67.5) 0 0; overflow-x: clip; overflow-clip-margin: calc((100vw - var(--col)) / 2); pointer-events: none; }
/* Past 1440 px the open drapes are pinned to the screen edges (below), so the art may leave the column; the body's clip keeps the page width
   (Chrome ignores the calc() clip margin above). */
@media (min-width: 1441px) { .hero-art { overflow: visible; } }
.hero-art img { position: absolute; display: block; max-width: none; }
.hero-spill { display: none; }
[data-reveal=closed] :is(.curtain-open, .subject),
[data-reveal=open] .curtain-closed,
[data-reveal=none] :is(.curtain, .subject) { display: none; }

/* Closed: each still keeps the box of its half of hero.curtainClosed (160,14.5 528.5x472) and is scaled so its ink fills it; ink measured
   with sharp: left 50,45 393x699 and right 57,44 404x701 of 512x768, s = 472/699. Each box is the scaled still's full width (345.73u, so
   object-fit: cover keeps s at the 472u height) and clips it; object-position takes the transparent frame off the top and puts each inner
   edge 2u past the centre line, so no seam shows. All of it is then scaled 1.12 about the bell's axis (x 424.25u, the hero top), so the
   mass is as wide as the reference's. The reference's mass is a bell: gathered under the logo by a fan from a point 252.5u above
   the hero top (its top corners), soft at the sides (an ellipse of --bell-rx x --bell-ry, wider in light, whose --sides fade ends inside the velvet), solid through the middle, its hem fading into the snow.
   js/fx/curtain.js draws the same mask on the reveal's first frame. */
.curtain-closed { top: calc(var(--u) * 14.5); width: calc(var(--u) * 387.22); height: calc(var(--u) * 472); object-fit: cover; -webkit-mask-composite: source-in; mask-composite: intersect; filter: var(--curtain-lift); }
.curtain-left.curtain-closed { left: calc(var(--u) * 128.29); object-position: calc(var(--u) * -36.85) calc(var(--u) * -34.05); -webkit-mask-image: var(--mask-left); mask-image: var(--mask-left); }
.curtain-right.curtain-closed { left: calc(var(--u) * 332.99); object-position: calc(var(--u) * 46.01) calc(var(--u) * -33.15); -webkit-mask-image: var(--mask-right); mask-image: var(--mask-right); }
.hero-art {
  --fade-y: linear-gradient(transparent, black calc(var(--u) * 16) calc(var(--u) * 430), transparent calc(var(--u) * 472));
  --fan: black 30deg, transparent 37deg 323deg, black 330deg;
  --mask-left: conic-gradient(from 180deg at calc(var(--u) * 295.96) calc(var(--u) * -252.5), var(--fan)), radial-gradient(ellipse calc(var(--u) * var(--bell-rx)) calc(var(--u) * var(--bell-ry)) at calc(var(--u) * 295.96) calc(var(--u) * 235), var(--sides)), var(--fade-y);
  --mask-right: conic-gradient(from 180deg at calc(var(--u) * 91.26) calc(var(--u) * -252.5), var(--fan)), radial-gradient(ellipse calc(var(--u) * var(--bell-rx)) calc(var(--u) * var(--bell-ry)) at calc(var(--u) * 91.26) calc(var(--u) * 235), var(--sides)), var(--fade-y);
}

/* Open: each still stretched so its ink (of 512x768: left 32,46 423x684, right 68,44 391x697) lands on hero.curtainOpenLeft 17,9.5 208x395.5
   and hero.curtainOpenRight 627,20 216x373.5: scale x 208/423 and 216/391, y 395.5/684 and 373.5/697. */
.curtain-left.curtain-open { width: calc(var(--u) * 251.8); height: calc(var(--u) * 444.1); left: calc(var(--u) * 1.3); top: calc(var(--u) * -17.1); }
.curtain-right.curtain-open { width: calc(var(--u) * 282.8); height: calc(var(--u) * 411.6); left: calc(var(--u) * 589.4); top: calc(var(--u) * -3.6); }
/* The tails fade into the scene like the reference's (js/fx/curtain.js fades the reveal's last frames the same way); past the 1440 px column
   the drapes stay on the screen edges instead of hanging in mid-air at the column's. */
.curtain-open { -webkit-mask-image: linear-gradient(black 70%, transparent 85%); mask-image: linear-gradient(black 70%, transparent 85%); filter: var(--drape-lift); }
@media (min-width: 1441px) {
  .curtain-left.curtain-open { translate: calc((1440px - 100vw) / 2); }
  .curtain-right.curtain-open { translate: calc((100vw - 1440px) / 2); }
}
/* Above the hero copy's sky scrim (z-index 1), so the skiers keep their colour; they sit beside the text in both layouts. */
.subject { z-index: 2; object-fit: contain; object-position: bottom; }
.subject-left { left: calc(var(--u) * 92); top: calc(var(--u) * 335); width: calc(var(--u) * 212); height: calc(var(--u) * 168); }
.subject-right { left: calc(var(--u) * 560); top: calc(var(--u) * 350); width: calc(var(--u) * 182); height: calc(var(--u) * 158); }

.hero-copy { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: center; padding: calc(var(--u) * 72.9) calc(var(--u) * 24) 0; text-align: center; }
.hero-copy > * { margin: 0; }
[data-reveal=closed] .hero-copy { --text: var(--stage-curtain-text); --accent: var(--gold); --halo: var(--halo-dark); }
.hero-copy { color: var(--text); text-shadow: var(--halo); }
.hero-copy .btn { text-shadow: none; }
/* Over open sky the plate's snowy peaks sit behind the copy (the mockup has dark sky there): a soft scrim of sky colour. */
:is([data-reveal=open], [data-reveal=none]) .hero-copy::before { content: ""; position: absolute; z-index: -1; left: 50%; top: calc(var(--u) * 40); width: calc(var(--u) * 620); height: calc(var(--u) * 340); transform: translateX(-50%); background: radial-gradient(closest-side, color-mix(in srgb, var(--veil) 72%, transparent) 40%, transparent); pointer-events: none; }
.eyebrow { display: flex; align-items: center; gap: calc(var(--u) * 12); color: var(--accent); font-size: calc(var(--u) * 15.5); font-weight: 600; line-height: 1; letter-spacing: .2em; text-transform: uppercase; }
.eyebrow::before, .eyebrow::after { content: ""; width: calc(var(--u) * 44); height: calc(var(--u) * 1); background: var(--gold); }
/* Over open scenery the small eyebrow can sit on dark wood or bright snow: the wider halo the bar's text uses (on phones also a soft band of
   sky, below: theirs crosses the lodge; on desktop light the band shows as a pale pill). */
:is([data-reveal=open], [data-reveal=none]) .eyebrow { text-shadow: var(--halo), 0 0 .3em var(--veil), 0 0 .6em var(--veil); }
.hero .title {
  margin-top: calc(var(--u) * 17.3);
  max-width: calc(var(--u) * 700);
  font-size: calc(var(--u) * 59);
  font-weight: 700;
  line-height: 1.05;
  color: var(--text);
  text-wrap: balance;
}
.hero .title-long { font-size: calc(var(--u) * 46); }
.hero .title-xlong { font-size: calc(var(--u) * 38); }
.title-dot { color: var(--gold); }
.subtitle { margin-top: calc(var(--u) * 12.3); font-size: calc(var(--u) * 19); line-height: 1; color: var(--text); }
.status { margin-top: calc(var(--u) * 34.4); color: var(--accent); font-size: calc(var(--u) * 14.5); font-weight: 600; line-height: 1; letter-spacing: .2em; text-transform: uppercase; }
.countdown { display: flex; margin-top: calc(var(--u) * 14.3); }
/* A digit pair is 64.5u wide: 67u groups and 32u colons keep the reference's 99u pitch with room for it; nowrap so a pair never breaks. */
.cd-group { display: flex; flex-direction: column; align-items: center; width: calc(var(--u) * 67); }
.cd-num, .cd-colon { font-size: calc(var(--u) * 46); font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; white-space: nowrap; }
.cd-colon { width: calc(var(--u) * 32); }
.cd-label { margin-top: calc(var(--u) * 2); font-size: calc(var(--u) * 14); line-height: 1; }
.countdown ~ .btn-outline { margin-top: calc(var(--u) * 33.9); width: calc(var(--u) * 224.5); }
.hero .btn-cta { margin-top: calc(var(--u) * 26.6); width: calc(var(--u) * 232); }
.btn-cta + .btn-outline { margin-top: calc(var(--u) * 21); width: calc(var(--u) * 216.5); height: calc(var(--u) * 38); }
[data-state=empty] .hero-copy { padding-top: calc(var(--u) * 150); }
[data-state=empty] .hero .btn { margin-top: calc(var(--u) * 40); }
[data-state=closed] .hero-copy .btn { margin-top: calc(var(--u) * 26); }

/* ---------- arcade teaser ---------- */
.arcade-teaser { display: flex; flex-direction: column; align-items: center; padding-top: calc(var(--u) * 24); text-align: center; }
.arcade-teaser, .about-copy, .stage .foot { text-shadow: var(--halo); }
.stage :is(.arcade-title, .btn) { text-shadow: none; }
.section-heading { font-size: calc(var(--u) * 40); font-weight: 700; line-height: 1.1; color: var(--text); }
.section-sub { margin-top: calc(var(--u) * 12); font-size: calc(var(--u) * 17); color: var(--text); }
/* The title screen is darker than the slope behind it (the mockup's grid panel), which keeps its small print readable. */
.arcade-screen { position: relative; display: flex; flex-direction: column; align-items: center; margin-top: calc(var(--u) * 14); background: radial-gradient(closest-side, color-mix(in srgb, var(--veil) 60%, transparent) 50%, transparent); }
.arcade-logo { width: calc(var(--u) * 44); height: calc(var(--u) * 43); object-fit: contain; }
.arcade-presents { margin-top: calc(var(--u) * 4); color: var(--accent); font-size: calc(var(--u) * 10.4); font-weight: 600; letter-spacing: .14em; text-transform: uppercase; }
.arcade-title {
  margin-top: calc(var(--u) * 8);
  font-size: calc(var(--u) * 54);
  font-weight: 900;
  line-height: 1;
  letter-spacing: .06em;
  text-transform: uppercase;
  background: linear-gradient(color-mix(in srgb, var(--gold) 75%, white), var(--gold), color-mix(in srgb, var(--gold) 70%, black));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* A fixed dark-brown edge, as the reference draws it in both modes (an edge from the sky went pale in light). */
  filter: drop-shadow(0 0 calc(var(--u) * .8) var(--stage-arcade-edge)) drop-shadow(calc(var(--u) * .8) calc(var(--u) * 1.6) 0 var(--stage-arcade-shadow)) drop-shadow(0 0 calc(var(--u) * 14) color-mix(in srgb, var(--gold) 40%, transparent));
}
.arcade-grid { position: absolute; left: calc(var(--u) * -296); top: calc(var(--u) * 112.5); width: calc(var(--u) * 600); height: calc(var(--u) * 90); }
.arcade-play {
  position: relative;
  width: calc(var(--u) * 50.5);
  height: calc(var(--u) * 50);
  border: calc(var(--u) * 2) solid var(--gold);
  border-radius: 50%;
  background: color-mix(in srgb, var(--button) 88%, transparent);
}
.arcade-play::after { content: ""; position: absolute; left: 54%; top: 50%; transform: translate(-50%, -50%); border-style: solid; border-color: transparent transparent transparent var(--gold); border-width: calc(var(--u) * 9) 0 calc(var(--u) * 9) calc(var(--u) * 15); }
.arcade-teaser > .btn { margin-top: calc(var(--u) * 22); width: calc(var(--u) * 215); height: calc(var(--u) * 36.5); }

/* ---------- about ---------- */
.about { position: relative; display: grid; grid-template-columns: calc(var(--u) * 438) calc(var(--u) * 270); column-gap: calc(var(--u) * 35); align-items: start; padding: calc(var(--u) * 42) 0 0 calc(var(--u) * 30); }
.about-art { position: relative; grid-row: 1; padding-top: calc(var(--u) * 20.5); }
.about-backdrop { position: absolute; left: calc(var(--u) * -30); top: calc(var(--u) * -102.5); width: calc(var(--u) * 408); height: calc(var(--u) * 320); object-fit: contain; }
.about-photo { position: relative; display: block; width: calc(var(--u) * 438); height: calc(var(--u) * 255); object-fit: cover; -webkit-mask: linear-gradient(90deg, transparent, black 6%, black 94%, transparent), linear-gradient(transparent, black 6%, black 94%, transparent); -webkit-mask-composite: source-in; mask: linear-gradient(90deg, transparent, black 6%, black 94%, transparent), linear-gradient(transparent, black 6%, black 94%, transparent); mask-composite: intersect; }
.about-photo-empty { display: grid; place-items: center; -webkit-mask: none; mask: none; background: color-mix(in srgb, var(--navy-800) 60%, transparent); border: calc(var(--u) * 1) dashed var(--gold); border-radius: calc(var(--u) * 6); color: var(--body-text); font-size: calc(var(--u) * 14); }
.about-photo-empty::after { content: "Team photo coming soon"; }
/* The lantern of the bottom plate glows behind the text: a soft scrim of sky colour. */
.about-copy { display: flex; flex-direction: column; align-items: flex-start; position: relative; padding-left: calc(var(--u) * 4.5); }
/* The scrim reaches past the copy so it fades out on the art instead of ending on the box edge. */
.about-copy::before { content: ""; position: absolute; z-index: -1; inset: calc(var(--u) * -40) calc(var(--u) * -50); background: radial-gradient(closest-side, var(--about-scrim)); pointer-events: none; }
.about .section-heading { font-size: calc(var(--u) * 31); line-height: 1.05; }
.about-rule { width: calc(var(--u) * 45.5); height: calc(var(--u) * 2); margin-top: calc(var(--u) * 13); background: var(--gold); }
.about-copy p { margin-top: calc(var(--u) * 10); font-size: calc(var(--u) * 14.5); line-height: calc(var(--u) * 18); color: var(--body-text); }
.text-link { display: inline-flex; align-items: center; gap: calc(var(--u) * 10); margin-top: calc(var(--u) * 12); color: var(--accent); font-size: calc(var(--u) * 16.5); font-weight: 600; transition: color .15s; }
.text-link:hover { color: var(--text); }
/* Meet the team can cross the lantern's glow on the snow: the bar's wider halo, rather than a firmer scrim (a dark oval in the dark). */
.about-copy .text-link { text-shadow: var(--halo), 0 0 .3em var(--veil), 0 0 .6em var(--veil), 0 0 .6em var(--veil), 0 0 1em var(--veil), 0 0 1.4em var(--veil), 0 0 1.4em var(--veil), 0 0 1.4em var(--veil); }

/* ---------- buttons and links in motion (docs/ANIMATION-SPEC.md 13) ---------- */
/* Hover, on devices that hover: a gold glow behind the button, the arrow nudges 4u, a text link's underline draws from the left. */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .stage .btn::after { content: ""; position: absolute; inset: 0; border-radius: inherit; box-shadow: 0 0 calc(var(--u) * 16) color-mix(in srgb, var(--gold) 45%, transparent); opacity: 0; pointer-events: none; transition: opacity .24s ease-out; }
  .stage .btn:hover::after { opacity: 1; transition-duration: .18s; }
  .stage .btn, .stage .text-link { position: relative; }
  .stage :is(.btn, .text-link) .btn-arrow { transition: transform .24s cubic-bezier(.3, .7, .3, 1); }
  .stage :is(.btn, .text-link):hover .btn-arrow { transform: translateX(calc(var(--u) * 4)); }
  .stage .text-link::after { content: ""; position: absolute; left: 0; right: 0; bottom: calc(var(--u) * -3); height: 1px; background: currentColor; transform: scaleX(0); transform-origin: left; transition: transform .2s ease-out; }
  .stage .text-link:hover::after { transform: scaleX(1); }
}
/* Press, on every device. */
@media (prefers-reduced-motion: no-preference) {
  .stage .btn:active { transform: scale(.97) translateY(calc(var(--u) * 1)); transition-duration: .08s; }
}

/* ---------- page transitions (docs/ANIMATION-SPEC.md 14): the bar and the scene stay still, the page cross-fades ---------- */
/* Every stage page opts in here (/about and /arcade also in css/appearance.css). Chromium still skips some of these cross-document
   transitions, more often on narrow screens, and rejects its own ViewTransition with "Transition was aborted because of invalid state.
   ViewTransition opt-in disabled": a browser notice, not an error of ours (moving the opt-in out of the media query or inline does not
   change it); the page loads without the cross-fade. */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
}
.stage .bar { view-transition-name: bar; }
.stage .scene { view-transition-name: scene; }
.stage main { view-transition-name: main; }
::view-transition-group(bar), ::view-transition-group(scene), ::view-transition-new(bar), ::view-transition-new(scene) { animation: none; }
::view-transition-old(bar), ::view-transition-old(scene) { animation: none; opacity: 0; }
::view-transition-group(main), ::view-transition-old(main), ::view-transition-new(main), ::view-transition-group(root), ::view-transition-old(root), ::view-transition-new(root) { animation-duration: .18s; }

/* ---------- inner pages: their classic content (css/site.css) in the stage frame, until T10 restyles each page (a restyled page has data-page) ---------- */
/* The stage unit is 1px inside, so the shared buttons keep a body-text size; T10 sets its own. */
.stage:not([data-page]) main.page { --u: 1px; width: auto; max-width: 1120px; margin-inline: auto; font: 16px / 1.55 var(--font-ui); color: var(--body-ink); }
.stage:not([data-page]) main.page .btn { height: auto; min-height: 44px; }
:where(.stage:not([data-page]) .page) a { color: var(--accent-hi); text-decoration: underline; }
/* css/site.css styles the classic footer by the same class. */
.stage .foot { border: 0; font-family: var(--font-stage); font-weight: 500; letter-spacing: 0; text-transform: none; text-align: left; }

/* ---------- staff-built sections after About (T10 restyles them) ---------- */
.stage-sections { width: min(100% - 32px, 720px); margin: 0 auto; line-height: 1.5; }
.stage-sections:empty { display: none; }

/* ---------- footer ---------- */
.stage .foot {
  background: linear-gradient(transparent, color-mix(in srgb, var(--veil) 80%, transparent) 50%);
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: calc(var(--u) * 46) max(calc(var(--u) * 57.5), env(safe-area-inset-right)) max(calc(var(--u) * 22), env(safe-area-inset-bottom)) max(calc(var(--u) * 62), env(safe-area-inset-left));
  box-sizing: border-box;
  color: color-mix(in srgb, var(--text) 85%, transparent);
  font-size: calc(var(--u) * 12.3);
  line-height: 1;
}
.foot-name { margin: 0; }
.foot-links { display: flex; justify-content: space-between; gap: calc(var(--u) * 16); width: calc(var(--u) * 252); }
.foot-links a { position: relative; transition: color .15s; }
.foot-links a::before { content: ""; position: absolute; left: 50%; top: 50%; width: max(100%, 44px); height: max(100%, 44px); transform: translate(-50%, -50%); }
.foot-links a:hover { color: var(--text); }
/* The footer starts where About's last line ends: taps on its empty top go through to Meet the team's 44 px target (a z-index on the link
   cannot lift it out of main's stacking context). */
.stage .foot { pointer-events: none; }
.stage .foot a { pointer-events: auto; }

/* The one-time install hint (js/install-hint.js): css/mobile.css places it above the tab bar, which stage pages do not have. */
.stage .install-hint { position: fixed; z-index: 29; left: max(12px, env(safe-area-inset-left)); right: max(12px, env(safe-area-inset-right)); bottom: max(12px, env(safe-area-inset-bottom)); display: flex; align-items: center; gap: 8px; padding: 4px 4px 4px 12px; border: 1px solid var(--gold); border-radius: 10px; background: var(--button); color: var(--button-text); font: 500 15px / 1.35 var(--font-stage); }
.stage .install-hint p { flex: 1; margin: 0; }
.stage .install-hint-x { flex: none; width: 44px; height: 44px; border-radius: 8px; color: var(--gold); font: 400 28px / 1 var(--font-stage); }

/* The site banner (src/pages.ts siteBanner): css/site.css styles it on classic pages; stage pages do not load that sheet. */
.stage .announce { display: flex; align-items: center; justify-content: center; gap: 8px; margin: 0 0 24px; padding: 6px 6px 6px 16px; min-height: 48px; border: 1px solid var(--gold); border-radius: 10px; background: var(--button); color: var(--button-text); text-align: center; font: 600 15px / 1.35 var(--font-stage); }
.stage .announce[hidden] { display: none; } /* js/banner.js hides it at its end time */
.stage .announce-text { flex: 1; margin: 0; padding: 6px 0; }
.stage .announce-text a { color: inherit; }
.stage .announce-x { flex: none; display: grid; place-items: center; width: 44px; height: 44px; padding: 0; border: 0; border-radius: 8px; background: none; color: var(--gold); font: 400 28px / 1 var(--font-stage); cursor: pointer; }

/* Preview builds only: the fixture state switch. */
.fixture-toggle { position: fixed; z-index: 20; left: 8px; bottom: 8px; display: flex; gap: 4px; padding: 4px; background: var(--button); border-radius: 8px; font-size: 12px; }
.fixture-toggle form { display: flex; gap: 4px; margin: 0; }
.fixture-toggle :is(a, button) { padding: 6px 8px; color: var(--button-text); }
.fixture-toggle [aria-current] { color: var(--gold); }

/* Tap targets: 44 px whatever the unit works out to (the 1440 bar and text links too), without growing what is drawn. */
.stage :is(.btn, .bar-link, .bar-menu, .bar-logo, .text-link, .arcade-play) { position: relative; }
.stage :is(.btn, .bar-link, .bar-menu, .bar-logo, .text-link, .arcade-play)::before { content: ""; position: absolute; left: 50%; top: 50%; width: max(100%, 44px); height: max(100%, 44px); transform: translate(-50%, -50%); }

/* ---------- phone layout (the 390 px reference) ---------- */
@media (max-width: 699px) {
  body.stage { --col: calc(var(--u) * 390); }
  .scene-top { aspect-ratio: 724 / 607; }
  .scene-bottom { aspect-ratio: 724 / 840; }
  .scene-mid { margin-block: calc(-200% / 724); }

  .stage .bar { height: calc(var(--u) * 82.5 + env(safe-area-inset-top)); padding-right: max(calc(var(--u) * 13), env(safe-area-inset-right)); padding-left: max(calc(var(--u) * 29.1), env(safe-area-inset-left)); }
  .bar-menu-icon { width: calc(var(--u) * 24.6); height: calc(var(--u) * 16.8); }
  .bar-menu-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .bar-logo img { width: calc(var(--u) * 35.7); height: calc(var(--u) * 39.3); }
  .bar-account { gap: calc(var(--u) * 16.4); }
  .bar-link { font-size: calc(var(--u) * 11); }

  /* The top reference panel (794 tall) ends in snow: the paper starts below it. */
  .hero { min-height: calc(var(--u) * 727.5); }
  .hero-art { inset: calc(var(--u) * -82.5) 0 0; }
  /* Closed (phone files, ink left 63,57 491x873 and right 71,55 506x877 of 640x960): the mass 6.2,22.6 379x615 runs edge to edge,
     s = 615/873 and 615/877; bottom 6%. As in the reference, the mass is a bell gathered under the logo: a fan of about 65 degrees either
     side of the page centre at the image top leaves the bar's corners on open sky, and an ellipse rounds it to the screen edges at y 250
     and narrows the hem, so the side trees show. */
  .curtain-closed { top: calc(var(--u) * 22.6); height: calc(var(--u) * 676.3); }
  .curtain-left.curtain-closed { left: calc(var(--u) * 6.2); width: calc(var(--u) * 192.5); object-position: calc(var(--u) * -197.8) calc(var(--u) * -40.2); }
  .curtain-right.curtain-closed { left: calc(var(--u) * 192.7); width: calc(var(--u) * 192.5); object-position: calc(var(--u) * -49.8) calc(var(--u) * -38.6); }
  .hero-art {
    --fade-y: linear-gradient(black calc(var(--u) * 590), transparent calc(var(--u) * 640));
    --fan: black 62deg, transparent 68deg 292deg, black 298deg;
    /* The ellipse's soft edge ends inside the velvet in both modes (72% to 88%), so the bell keeps one silhouette. */
    --mask-left: conic-gradient(from 180deg at calc(var(--u) * 188.8) 0, var(--fan)), radial-gradient(ellipse calc(var(--u) * 249) calc(var(--u) * 428) at calc(var(--u) * 188.8) calc(var(--u) * 330), black 72%, transparent 88%), var(--fade-y);
    --mask-right: conic-gradient(from 180deg at calc(var(--u) * 2.3) 0, var(--fan)), radial-gradient(ellipse calc(var(--u) * 249) calc(var(--u) * 428) at calc(var(--u) * 2.3) calc(var(--u) * 330), black 72%, transparent 88%), var(--fade-y);
  }
  /* Open (phone files, ink left 40,57 529x856 and right 85,55 488x872 of 640x960) stretched onto 0,0.4 121.2x349.5 and 279.1,4.1 110.9x349.1:
     the reference draws the tied-back drapes narrow on the phone. */
  .curtain-left.curtain-open { width: calc(var(--u) * 146.6); height: calc(var(--u) * 392); left: calc(var(--u) * -9.2); top: calc(var(--u) * -22.9); }
  .curtain-right.curtain-open { width: calc(var(--u) * 145.5); height: calc(var(--u) * 384.3); left: calc(var(--u) * 259.8); top: calc(var(--u) * -17.9); }
  .subject-left { left: calc(var(--u) * 26.2); top: calc(var(--u) * 351.1); width: calc(var(--u) * 118.7); height: calc(var(--u) * 122.8); }
  .subject-right { left: calc(var(--u) * 253.8); top: calc(var(--u) * 365.9); width: calc(var(--u) * 110.5); height: calc(var(--u) * 113); }

  /* The phone reference sets its hero copy 10u right of the page centre (bar logo too); kept to match it. */
  .hero-copy { padding: calc(var(--u) * 134.3) calc(var(--u) * 6) 0 calc(var(--u) * 26); }
  .eyebrow { gap: calc(var(--u) * 10); font-size: calc(var(--u) * 13.5); }
  .eyebrow::before, .eyebrow::after { width: calc(var(--u) * 30); }
  :is([data-reveal=open], [data-reveal=none]) .eyebrow { background: color-mix(in srgb, var(--veil) 60%, transparent); box-shadow: 0 0 .6em .5em color-mix(in srgb, var(--veil) 60%, transparent); border-radius: 1em; }
  .hero .title { margin-top: calc(var(--u) * 29.2); max-width: calc(var(--u) * 360); font-size: calc(var(--u) * 49); }
  .hero .title-long { font-size: calc(var(--u) * 40); }
  .hero .title-xlong { font-size: calc(var(--u) * 33); }
  .subtitle { margin-top: calc(var(--u) * 9.4); font-size: calc(var(--u) * 19); }
  .status { margin-top: calc(var(--u) * 37.7); font-size: calc(var(--u) * 13.4); }
  :is([data-reveal=open], [data-reveal=none]) .hero-copy::before { width: calc(var(--u) * 380); height: calc(var(--u) * 470); }
  [data-reveal=open] .status { margin-top: calc(var(--u) * 152.5); font-size: calc(var(--u) * 18); font-weight: 700; letter-spacing: .12em; }
  .btn-cta .btn-arrow { display: block; width: calc(var(--u) * 18); height: calc(var(--u) * 2); }
  .countdown { margin-top: calc(var(--u) * 21.1); }
  .cd-group { width: calc(var(--u) * 52); }
  .cd-num, .cd-colon { font-size: calc(var(--u) * 35.8); }
  .cd-colon { width: calc(var(--u) * 25); }
  .cd-label { margin-top: calc(var(--u) * 3); font-size: calc(var(--u) * 11.5); }
  .stage .btn { gap: calc(var(--u) * 10); padding: 0 calc(var(--u) * 18); border-width: calc(var(--u) * 2); font-size: calc(var(--u) * 15); }
  .stage .btn-small { height: calc(var(--u) * 27.9); padding: 0 calc(var(--u) * 10); border-width: calc(var(--u) * 1.5); font-size: calc(var(--u) * 12); border-radius: calc(var(--u) * 7); }
  .countdown ~ .btn-outline { margin-top: calc(var(--u) * 48.2); width: calc(var(--u) * 232.3); height: calc(var(--u) * 41); }
  .hero .btn-cta { border-width: calc(var(--u) * 2.5); margin-top: calc(var(--u) * 22.8); width: calc(var(--u) * 223.1); height: calc(var(--u) * 46.3); font-size: calc(var(--u) * 22); }
  .btn-cta + .btn-outline { margin-top: calc(var(--u) * 17); width: calc(var(--u) * 193.2); height: calc(var(--u) * 34.8); font-size: calc(var(--u) * 13.5); }

  .arcade-teaser { padding-top: calc(var(--u) * 34); }
  .section-heading { font-size: calc(var(--u) * 30.5); }
  .section-sub { margin-top: calc(var(--u) * 12); font-size: calc(var(--u) * 13.5); }
  .arcade-screen { margin-top: calc(var(--u) * 16); }
  .arcade-logo { width: calc(var(--u) * 33.8); height: calc(var(--u) * 34.9); }
  .arcade-presents { font-size: calc(var(--u) * 7); }
  .arcade-title { font-size: calc(var(--u) * 33.6); }
  .arcade-grid { left: calc(var(--u) * -130); top: calc(var(--u) * 80); width: calc(var(--u) * 300); height: calc(var(--u) * 60); }
  .arcade-play { width: calc(var(--u) * 43.7); height: calc(var(--u) * 44.5); }
  .arcade-teaser > .btn { margin-top: calc(var(--u) * 10); width: calc(var(--u) * 171.8); height: calc(var(--u) * 31.8); font-size: calc(var(--u) * 12.5); }

  .about { display: flex; flex-direction: column; align-items: center; padding: calc(var(--u) * 20) 0 0; text-align: center; }
  .about-art { align-self: start; margin-left: calc(var(--u) * 11.9); padding-top: 0; }
  .about-backdrop { left: calc(var(--u) * 242); top: calc(var(--u) * -13.5); width: calc(var(--u) * 135.7); height: calc(var(--u) * 170.6); }
  .about-photo { width: calc(var(--u) * 342.8); height: calc(var(--u) * 184.1); }
  .about-copy { align-items: center; padding: 0 calc(var(--u) * 16); }
  .about-copy::before { inset: calc(var(--u) * -30) 0; }
  .about .section-heading { margin-top: calc(var(--u) * 2); font-size: calc(var(--u) * 26); }
  .about-rule { width: calc(var(--u) * 38.5); margin-top: calc(var(--u) * 6); }
  .about-copy p { max-width: calc(var(--u) * 262); margin-top: calc(var(--u) * 8); font-size: calc(var(--u) * 12.5); line-height: calc(var(--u) * 16); }
  .text-link { margin-top: calc(var(--u) * 8); font-size: calc(var(--u) * 14); }

  .stage .foot { flex-direction: column; align-items: center; gap: calc(var(--u) * 12); padding: calc(var(--u) * 90) max(calc(var(--u) * 16), env(safe-area-inset-right)) max(calc(var(--u) * 80), env(safe-area-inset-bottom)) max(calc(var(--u) * 16), env(safe-area-inset-left)); font-size: max(12px, calc(var(--u) * 10.4)); }
  .foot-links { width: calc(var(--u) * 259); }
}
