/* Bricolage Grotesque, self-hosted (SIL OFL 1.1, see /fonts/OFL.txt): one variable font, weights 400-800. */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url(/fonts/bricolage-grotesque-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url(/fonts/bricolage-grotesque-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ==========================================================================
   Toybox Atlas tokens (docs/visual-design.md §2). Night Flight names stay as aliases, so CSS that
   is not restyled yet keeps working.
   ========================================================================== */
:root {
  color-scheme: light;

  /* ink and paper */
  --ink: #24170f;            /* text on every light surface: 16.2:1 on cream */
  --ink-2: #6b5444;          /* muted text on cream: 6.6:1 */
  --cream: #fff6e4;          /* default page background */
  --clay: #f3d9b1;           /* raised light surface: inputs, rows, chips */
  --clay-2: #e8c793;         /* hover / pressed light surface */

  /* section blocks (ink text on all of them) */
  --lemon: #ffc53d;
  --tangerine: #ff8a3d;
  --tangerine-ink: #b84a0c;  /* tangerine as text on cream: 4.9:1 (the logo accent) */
  --leaf: #5cc46a;
  --sky: #8fd4ff;

  /* dusk (round screen, dialogs over the round) */
  --cocoa: #2e2018;
  --cocoa-2: #3d2b20;
  --cocoa-3: #4f3a2c;
  --sand: #d9c4a8;

  /* signals */
  --go: #1f5a2a;
  --go-bright: #7ee081;
  --stop: #b23a22;
  --stop-bright: #ff7a59;
  --warn: #ff8a3d;

  /* toy depth: the solid moulded edge under buttons and cards */
  --edge-ink: color-mix(in srgb, var(--ink) 85%, transparent);
  --toy-1: 0 3px 0 var(--edge-ink);
  --toy-2: 0 5px 0 var(--edge-ink), 0 12px 24px -10px rgba(36, 23, 15, .35);
  --toy-3: 0 7px 0 var(--edge-ink), 0 22px 40px -14px rgba(36, 23, 15, .45);
  --outline: 0 0 0 2.5px var(--ink);

  /* surfaces next to the panorama (never over it) */
  --glass: #2e2018;          /* opaque: no backdrop-filter anywhere on the round screen */
  --veil: rgba(36, 23, 15, .78);
  --veil-solid: #2e2018;     /* lead veil over the panorama: opaque by rule */

  /* type (§2.2) */
  --font: 'Bricolage Grotesque', system-ui, sans-serif;
  --fs-hero: clamp(3.2rem, 8.5vw, 6.8rem);
  --fs-display: clamp(2rem, 4.4vw, 3.2rem);
  --fs-h2: 1.5rem;
  --fs-h3: 1.15rem;
  --fs-body: 1rem;
  --fs-small: .85rem;
  --fs-tag: .78rem;

  /* radius, spacing, layers (§2.3) */
  --r-xs: 6px; --r-sm: 10px; --r-md: 16px; --r-lg: 24px; --r-xl: 32px; --r-pill: 999px;
  --radius: var(--r-md);
  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-5: 24px; --sp-6: 32px; --sp-7: 48px; --sp-8: 72px; --sp-9: 112px;
  --z-stage: 2; --z-hud: 6; --z-dock: 7; --z-playdock: 8; --z-intro: 20; --z-react: 30;
  --z-countdown: 40; --z-scrim: 50; --z-toast: 3000;

  /* motion (§2.4) */
  --ease-out: cubic-bezier(.22, 1, .36, 1);
  --ease-in: cubic-bezier(.55, 0, 1, .45);
  --ease-in-out: cubic-bezier(.65, 0, .35, 1);
  --ease-spring: cubic-bezier(.34, 1.56, .64, 1);
  --ease-bounce: var(--ease-spring);
  --ease-flap: cubic-bezier(.5, 0, .75, 0);
  --t-instant: 90ms; --t-quick: 160ms; --t-base: 240ms; --t-slow: 420ms; --t-epic: 900ms;
  --stagger: 70ms;

  /* aliases (§2) */
  --bg: var(--cream); --panel: #ffffff; --panel-2: var(--clay);
  --text: var(--ink); --muted: var(--ink-2); --accent: var(--lemon);
  --good: var(--go); --bad: var(--stop);

  /* Night Flight aliases, mapped onto the daylight palette (to be removed when every page is restyled) */
  --ink-0: var(--ink); --ink-1: var(--cream); --ink-3: var(--clay); --ink-4: var(--clay-2);
  --line: rgba(36, 23, 15, .14); --line-strong: rgba(36, 23, 15, .3);
  --dim: var(--ink-2);
  --sodium: var(--lemon); --sodium-hot: #ffd76e; --sodium-ink: var(--ink);
  --ember: var(--tangerine); --signal: var(--stop); --aurora: var(--go); --skyline: #1d5d99; --paper: var(--cream);
  --glow-sodium: var(--outline);
  --glow-player: 0 0 0 2.5px var(--c, var(--ink));
  --edge: inset 0 0 0 1.5px var(--line-strong);
  --d1: var(--toy-1); --d2: var(--toy-2); --d3: var(--toy-3); --d-float: var(--toy-3);
  --fs-eyebrow: var(--fs-tag);
}
@supports (transition-timing-function: linear(0, 1)) {
  :root { --ease-bounce: linear(0, .36 18%, .9 36%, 1.06 48%, .98 62%, 1.01 78%, 1); }
}
/* Dusk surface: the round screen, dialogs over the round, the TV round. */
.dusk {
  color-scheme: dark;
  --bg: var(--cocoa); --panel: var(--cocoa-2); --panel-2: var(--cocoa-3);
  --text: var(--cream); --muted: var(--sand); --good: var(--go-bright); --bad: var(--stop-bright);
  --dim: var(--sand); --line: rgba(255, 246, 228, .14); --line-strong: rgba(255, 246, 228, .28);
  --ink-1: var(--cocoa); --ink-3: var(--cocoa-2); --ink-4: var(--cocoa-3); --skyline: var(--sky);
}

/* ---------- base ---------- */
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
html { scrollbar-gutter: stable; } /* same viewport width with or without a scrollbar: cross-document View Transitions abort when it changes */
body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: var(--fs-body);
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}
/* faint paper grain on daylight surfaces only (§2.3) */
body:not(.dusk) { background: url(/art/grain.svg) 0 0 / 220px 220px, var(--bg); }
body.dusk, body.lite { background: var(--bg); }
::selection { background: color-mix(in srgb, var(--lemon) 60%, transparent); color: var(--ink); }

/* Primary button (§3): lemon, ink outline, a solid moulded edge; it presses into the table.
   Hover/press use the individual `translate` property, so it composes with page transforms. The
   :where() parts keep specificity at the element level: any class rule (chips, tools) wins. */
button, .btn {
  font: inherit;
  border: 0;
  border-radius: var(--r-pill);
  padding: .8em 1.6em;
  background: var(--lemon);
  color: var(--ink);
  font-weight: 800;
  cursor: pointer;
  box-shadow: var(--outline), var(--toy-2);
  transition: translate var(--t-instant) var(--ease-out), box-shadow var(--t-instant) var(--ease-out),
    background-color var(--t-quick) var(--ease-out), color var(--t-quick) var(--ease-out);
}
.btn { display: inline-flex; align-items: center; justify-content: center; gap: .5em; text-decoration: none; }
button:where(:hover:not(:disabled)), .btn:where(:hover:not([aria-disabled='true'])) {
  translate: 0 -2px;
  box-shadow: var(--outline), var(--toy-3);
}
button:where(:active:not(:disabled)), .btn:where(:active:not([aria-disabled='true'])) {
  translate: 0 3px;
  box-shadow: var(--outline), var(--toy-1);
}
button:where(:disabled), .btn:where([aria-disabled='true']) {
  background: var(--clay); color: var(--ink-2); box-shadow: 0 0 0 2.5px var(--ink-2); translate: none; cursor: default;
}

/* Secondary: cream fill, ink outline, small edge. `.ghost` is also a player state on chips and energy
   bars, so it is scoped to buttons. */
button.ghost, .btn.ghost { background: var(--cream); color: var(--ink); box-shadow: var(--outline), var(--toy-1); }
button.ghost:not(:disabled):hover, .btn.ghost:hover { background: #fff; box-shadow: var(--outline), var(--toy-2); }
button.ghost:not(:disabled):active, .btn.ghost:active { box-shadow: var(--outline); translate: 0 3px; }
button.ghost:disabled { color: var(--ink-2); }
.dusk button.ghost, .dusk .btn.ghost { background: var(--cocoa-2); color: var(--cream); box-shadow: 0 0 0 2.5px var(--cream), 0 3px 0 rgba(0, 0, 0, .6); }

/* Big CTA: 64 px, a tiny figure glyph on the left that hops on hover. Tangerine on lemon blocks. */
button.big, .btn.big {
  --figure: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='6' r='4.2'/%3E%3Cpath d='M6.5 21v-6.2A5.5 5.5 0 0 1 12 9.3a5.5 5.5 0 0 1 5.5 5.5V21z'/%3E%3C/svg%3E");
  min-height: 64px; font-size: var(--fs-h2); padding: .45em 1.4em .45em 1.1em; gap: .45em;
}
button.big, .btn.big { display: inline-flex; align-items: center; justify-content: center; }
/* the glyph is centred on the label's capitals (a box centred on the line sits high next to them) */
button.big::before, .btn.big::before {
  content: ''; display: inline-block; width: .95em; height: .95em; flex: none; position: relative; top: .07em;
  background: currentColor;
  -webkit-mask: var(--figure) center / contain no-repeat;
  mask: var(--figure) center / contain no-repeat;
  transition: translate var(--t-quick) var(--ease-spring);
}
button.big:not(:disabled):hover::before, .btn.big:hover::before { translate: 0 -4px; }
.block[data-c='lemon'] :is(button.big, .btn.big) { background: var(--tangerine); }

/* text fields fill their row; selects size to their options (the lobby's .fields and .league-pick) */
input:not([type='checkbox'], [type='radio']), textarea { width: 100%; }
input, select, textarea {
  font: inherit;
  padding: .8em 1em;
  border-radius: var(--r-sm);
  border: 0;
  background: #fff;
  color: var(--ink);
  box-shadow: 0 0 0 2px var(--ink);
  transition: box-shadow var(--t-quick) var(--ease-out);
}
input:focus, select:focus, textarea:focus { outline: none; box-shadow: 0 0 0 2px var(--ink), 0 0 0 5px var(--lemon); }
input::placeholder { color: var(--ink-2); }
.dusk :is(input, select, textarea) { background: var(--cocoa-3); color: var(--cream); box-shadow: 0 0 0 2px var(--sand); }
.hidden { display: none !important; }
:focus-visible { outline: 3px solid var(--ink); outline-offset: 3px; }
.dusk :focus-visible { outline-color: var(--lemon); }
h1[tabindex='-1']:focus, h2[tabindex='-1']:focus { outline: none; } /* focus moved here for screen readers */
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* Language switch (i18n.js mountLangSwitch into any [data-lang-switch]): EN | DE toggle buttons. It takes the
   text colour of where it sits (footer, header), so it works on cream and on dusk. */
.lang-switch { display: inline-flex; gap: 2px; padding: 2px; border-radius: var(--r-pill); box-shadow: inset 0 0 0 1.5px currentColor; vertical-align: middle; }
.lang-switch button {
  font: inherit; font-size: .82em; font-weight: 800; letter-spacing: .04em; line-height: 1;
  min-width: 40px; min-height: 30px; padding: .35em .75em; border-radius: var(--r-pill);
  background: transparent; color: inherit; box-shadow: none; translate: none;
}
.lang-switch button:hover:not([aria-pressed='true']) { translate: none; box-shadow: none; background: color-mix(in srgb, currentColor 14%, transparent); }
.lang-switch button:active { translate: none; box-shadow: none; }
.lang-switch button[aria-pressed='true'] { background: var(--lemon); color: var(--ink); }
.legal-links .lang-switch { margin-left: .5em; }
.muted { color: var(--muted); }
.logo { font-weight: 800; letter-spacing: -.02em; }
.logo span { color: var(--tangerine-ink, #b84a0c); } /* tangerine darkened for text: 4.9:1 on cream (plain tangerine is 2.2:1) */
.dusk .logo span { color: var(--lemon); }
.error { color: var(--bad); min-height: 1.4em; }

/* ---------- type helpers (§2.2) ---------- */
.eyebrow { font-size: var(--fs-tag); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; font-style: normal; color: var(--muted); }
.display { font-size: var(--fs-display); font-weight: 800; letter-spacing: -.03em; line-height: 1.02; text-wrap: balance; }
.count { font-weight: 800; font-variant-numeric: tabular-nums; }
svg.icon { width: 1.25em; height: 1.25em; display: inline-block; vertical-align: -.25em; flex: none; }
/* Sticker headline: upright, 800, a solid offset shadow. Never italic, slanted or all caps. */
.sticker { font-weight: 800; color: var(--ink); line-height: 1.02; text-wrap: balance; text-shadow: 0 .06em 0 rgba(255, 255, 255, .55); }
.block[data-c='tangerine'] .sticker, .block[data-c='cocoa'] .sticker, .dusk .sticker, .sticker.on-dark { color: var(--cream); text-shadow: 0 .07em 0 var(--ink); }
.sticker.hero { font-size: var(--fs-hero); letter-spacing: -.035em; }
.sticker.display { font-size: var(--fs-display); letter-spacing: -.03em; }

/* ---------- layout and surfaces ---------- */
.stack { display: grid; gap: var(--gap, var(--sp-5)); align-content: start; }
.card { background: var(--panel); color: var(--text); border-radius: var(--r-lg); box-shadow: var(--outline), var(--toy-2); padding: var(--sp-5); }
:is(a, button).card { transition: translate var(--t-quick) var(--ease-out), box-shadow var(--t-quick) var(--ease-out); }
:is(a, button).card:hover { translate: 0 -3px; box-shadow: var(--outline), var(--toy-3); }

/* Section divider: kept for pages not restyled yet; a hairline in ink. */

/* Section block (§3, §2.3): full-bleed colour with a wavy top edge cut out of the previous block. */
.block {
  --block: var(--lemon);
  position: relative; background: var(--block); color: var(--ink);
  padding-block: var(--sp-9); padding-inline: 16px;
}
.block[data-c='lemon'] { --block: var(--lemon); }
.block[data-c='tangerine'] { --block: var(--tangerine); }
.block[data-c='leaf'] { --block: var(--leaf); }
.block[data-c='sky'] { --block: var(--sky); }
.block[data-c='cocoa'] { --block: var(--cocoa); color: var(--cream); }
.block::before {
  content: ''; position: absolute; left: 0; right: 0; top: -27px; height: 28px; pointer-events: none;
  background: var(--block);
  -webkit-mask: url(/art/wave.svg) left top / 120px 28px repeat-x;
  mask: url(/art/wave.svg) left top / 120px 28px repeat-x;
}

/* Choice tile (§3): card + diorama window or icon, title, 2 lines, a coloured tab on the top edge.
   Selected via aria-pressed / aria-checked / aria-selected = "true" or .is-selected. */
.tile {
  --tab: var(--lemon);
  position: relative; display: grid; gap: var(--sp-2); align-content: start; text-align: left;
  padding: var(--sp-4); border-radius: var(--r-lg); background: #fff; color: var(--ink); font-weight: 400;
  box-shadow: var(--outline), var(--toy-2);
  transition: translate var(--t-quick) var(--ease-out), box-shadow var(--t-quick) var(--ease-out), background-color var(--t-quick) var(--ease-out);
}
.tile::before {
  content: ''; position: absolute; left: var(--sp-5); top: -9px; width: 44px; height: 12px; border-radius: 6px 6px 0 0;
  background: var(--tab); box-shadow: 0 0 0 2.5px var(--ink); clip-path: inset(-4px -4px 2.5px -4px);
}
.tile[data-tab='sky'] { --tab: var(--sky); } .tile[data-tab='tangerine'] { --tab: var(--tangerine); }
.tile[data-tab='leaf'] { --tab: var(--leaf); } .tile[data-tab='clay'] { --tab: var(--clay); }
.tile:where(:hover:not(:disabled, [aria-disabled='true'])) { translate: 0 -3px; box-shadow: var(--outline), var(--toy-3); }
.tile-title { font-size: var(--fs-h3); font-weight: 700; margin: 0; }
.tile-text { font-size: var(--fs-small); color: var(--ink-2); margin: 0; }
.tile-window { aspect-ratio: 16 / 10; border-radius: var(--r-md); overflow: hidden; background: var(--sky); box-shadow: inset 0 0 0 2px var(--ink); }
.tile:is([aria-pressed='true'], [aria-checked='true'], [aria-selected='true'], .is-selected) {
  background: var(--lemon); translate: 0 3px; box-shadow: var(--outline), var(--toy-1);
}
.tile:is([aria-pressed='true'], [aria-checked='true'], [aria-selected='true'], .is-selected)::after {
  content: ''; position: absolute; right: -8px; top: -8px; width: 30px; height: 30px; border-radius: 50%;
  background: var(--leaf) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2324170f' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12.5 4.5 4.5L19 7.5'/%3E%3C/svg%3E") center / 18px no-repeat;
  box-shadow: 0 0 0 2.5px var(--ink); rotate: 8deg;
  animation: gp-pop var(--t-base) var(--ease-spring) both;
}
@keyframes gp-pop { from { scale: 0; } }

/* Puck token (§3): the 2D fallback figure. --c = pin colour, --size optional. */
.puck {
  --size: 40px;
  position: relative; display: inline-grid; place-items: center; flex: none;
  width: var(--size); height: var(--size); border-radius: 50%;
  background: var(--c, var(--lemon)); color: var(--ink);
  font: 800 calc(var(--size) * .36)/1 var(--font); letter-spacing: -.02em;
  box-shadow: 0 0 0 2.5px var(--ink), inset 0 -6px 0 rgba(0, 0, 0, .18);
  overflow: hidden;
}
.puck img { width: 100%; height: 100%; object-fit: cover; }

/* Chip / segmented control (§3): clay track, lemon thumb with an ink outline. Works with a group of
   buttons (aria-pressed) or radio labels. */
.seg { display: inline-flex; gap: 4px; padding: 4px; border-radius: var(--r-pill); background: var(--clay); box-shadow: inset 0 0 0 2px var(--ink); }
.seg > button, .seg > label > span {
  display: inline-block; padding: .45em 1em; border-radius: var(--r-pill); background: transparent; color: var(--ink);
  font-weight: 700; box-shadow: none; translate: none;
  transition: background-color var(--t-quick) var(--ease-out), box-shadow var(--t-quick) var(--ease-out);
}
.seg > button[aria-pressed='true'], .seg > label > input:checked + span { background: var(--lemon); box-shadow: 0 0 0 2px var(--ink); }
.seg > label { position: relative; } /* keeps the hidden radio inside its label (no off-screen overflow) */
.seg > label > input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; pointer-events: none; }
.dusk .seg { background: var(--cocoa-3); box-shadow: inset 0 0 0 2px var(--sand); }
.dusk .seg > button, .dusk .seg > label > span { color: var(--cream); }
.dusk .seg > button[aria-pressed='true'], .dusk .seg > label > input:checked + span { color: var(--ink); }

/* Tag / sticker (§3): a small rotated pill with an outline; colour per meaning. */
.sticker-tag {
  --tag: var(--lemon); --rot: -2deg;
  display: inline-block; padding: .3em .75em; border-radius: var(--r-pill);
  background: var(--tag); color: var(--ink); font-size: var(--fs-tag); font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  box-shadow: 0 0 0 2px var(--ink), 0 2px 0 var(--ink); rotate: var(--rot);
}
.sticker-tag.pop { animation: gp-pop var(--t-base) var(--ease-spring) both; }
.sticker-tag.good { --tag: var(--leaf); } .sticker-tag.bad { --tag: var(--stop-bright); }
.sticker-tag.info { --tag: var(--sky); } .sticker-tag.player { --tag: var(--c); }

/* Dialog (§3). :where() keeps it overridable by page CSS (game.css styles dialog.sheet too). */
:where(dialog.sheet) {
  border: 0; padding: var(--sp-5); border-radius: var(--r-xl); background: #fff; color: var(--ink);
  box-shadow: var(--outline), var(--toy-3); max-width: min(92vw, 520px);
}
:where(dialog.sheet)::backdrop { background: var(--veil); }
:where(dialog.sheet[open]) { animation: gp-sheet-in var(--t-base) var(--ease-spring) both; }
@keyframes gp-sheet-in { from { opacity: 0; scale: .94; } }

/* ---------- 3D views (public/avatar, §4.6) ----------
   <div class="stage-view" data-view="…"><div class="stage-fallback">posters / pucks</div></div>
   The stage adds a <canvas class="stage-canvas">; .is-live once its first frame is drawn. Give the
   view a size (aspect-ratio or height) so there is no layout shift. */
.stage-view { position: relative; overflow: hidden; isolation: isolate; contain: layout paint; }
.stage-fallback {
  position: absolute; inset: 0; display: grid; place-items: center;
  background-position: center; background-size: cover; background-repeat: no-repeat;
  transition: opacity var(--t-base) var(--ease-out);
}
.stage-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; opacity: 0; transition: opacity var(--t-base) var(--ease-out); pointer-events: none; }
.stage-view.is-live > .stage-canvas { opacity: 1; }
.stage-view.is-live:not(.show-poster) > .stage-fallback,
.stage-view.is-live > .stage-fallback:not([data-poster]) { opacity: 0; } /* the governor's minimal step shows posters under the figures */
.stage-canvas[hidden] { display: none; }
/* Depth behind the transparent canvas (docs/3d-lighting-research.md L5): a soft spotlight where the
   figures stand, the block colour darkening towards the rim, and a light vignette over the picture.
   Overlays only, so they work on any block colour the page gives the view; 0 GPU. */
.stage-view::before, .stage-view::after { content: ''; position: absolute; inset: 0; pointer-events: none; }
.stage-view::before {
  background: radial-gradient(120% 92% at 50% 40%, rgb(255 255 255 / .34) 0%, rgb(255 255 255 / .1) 34%, rgb(255 255 255 / 0) 56%, rgb(36 23 15 / .16) 100%);
}
.stage-view::after { background: radial-gradient(130% 110% at 50% 44%, rgb(36 23 15 / 0) 62%, rgb(36 23 15 / .14) 100%); }
.stage-view.is-fallback::after { display: none; }
/* A one-row strip that scrolls sideways with snap (§5.5 phone reveal): <div class="stage-scroll"> round
   a .stage-view mounted with { row: true }. The stage adds .is-row, sets --n (figures) and appends a
   .stage-snap row of snap points; each figure gets one --cell of width. Without .is-row it is a plain
   wrapper. */
.stage-scroll { position: relative; flex: none; min-width: 0; --cell: 96px; }
.stage-scroll.is-row {
  overflow: auto hidden; scroll-snap-type: x mandatory; overscroll-behavior-x: contain; scrollbar-width: none;
  border-radius: var(--r-lg); box-shadow: var(--outline), var(--toy-1);
}
.stage-scroll.is-row::-webkit-scrollbar { display: none; }
.stage-scroll.is-row > :is(.stage-view, .stage-snap) { width: max(100%, calc(var(--n, 1) * var(--cell))); }
.stage-scroll.is-row > .stage-view { border-radius: 0; box-shadow: none; }
.stage-snap { display: none; }
.stage-scroll.is-row > .stage-snap { position: absolute; inset: 0 auto 0 0; display: flex; pointer-events: none; }
.stage-snap > i { flex: 1 1 0; scroll-snap-align: center; }

/* ---------- pre-rendered backdrops (public/backdrop.js, §4.9) ----------
   host > .bd-back (sky, far, mist, mid) · the host's own children (.bd-stage, e.g. a transparent
   'lineup' .stage-view) · .bd-front (fore, front mist, particles). Parallax moves layers by transform
   only; the mist bands are a shared greyscale texture used as a luminance mask over the backdrop's
   mist colour, drifting in opposite directions (motion 'full' and 'mist'). */
.bd-host { position: relative; overflow: hidden; isolation: isolate; background: var(--bd-bg, #e9dcc4); }
.bd-back, .bd-front { position: absolute; inset: 0; pointer-events: none; }
.bd-back { z-index: 0; }
.bd-host > .bd-stage { position: absolute; inset: 0; z-index: 1; background: transparent !important; box-shadow: none; border-radius: 0; }
.bd-front { z-index: 2; }
.bd-layer { position: absolute; inset: -24px; will-change: transform; } /* bleed: parallax never shows an edge */
.bd-layer > img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 50%; display: block; user-select: none; }
.bd-soft .bd-far, .bd-soft .bd-mist { filter: blur(1.5px); }
.bd-soft .bd-mid { filter: blur(0.8px); }
.bd-mist { inset: -24px 0; overflow: hidden; }
.bd-mist-band {
  position: absolute; left: 0; width: 200%; height: 26%; top: calc(var(--bd-mist-at, 42%) - 13%);
  background: var(--bd-mist, #fff6e4); opacity: var(--bd-mist-o, .4);
  mask: url(/art/backdrops/v1/mist-a.webp) 0 0 / 50% 100% repeat-x luminance;
  animation: bd-drift 110s linear infinite;
}
.bd-mist-b {
  top: calc(var(--bd-mist-at, 42%) - 8%); height: 20%; opacity: calc(var(--bd-mist-o, .4) * .7);
  mask-image: url(/art/backdrops/v1/mist-b.webp); animation-duration: 170s; animation-direction: reverse;
}
.bd-mist-front .bd-mist-band { top: auto; bottom: -6%; height: 24%; opacity: calc(var(--bd-mist-o, .4) * .35); animation-duration: 80s; }
@keyframes bd-drift { to { transform: translateX(-50%); } }
.bd-particles { position: absolute; inset: 0; width: 100%; height: 100%; }
.bd-front::after { /* the vignette over the whole picture, live figures included */
  content: ''; position: absolute; inset: 0;
  background: radial-gradient(125% 105% at 50% 46%, rgb(36 23 15 / 0) 58%, rgb(36 23 15 / .22) 100%);
}
.bd-host > .bd-stage::before, .bd-host > .bd-stage::after { display: none; }
.bd-host > .bd-stage > .stage-fallback { place-items: end center; padding-bottom: 14%; } /* 2D pucks stand on the painted ground */
/* A 3D view that is its own backdrop host (stage.mount: every scene stands in a backdrop unless
   { backdrop: 'none' }): its canvas and fallback are the .bd-stage between the layers; the backdrop
   brings its own light and vignette, so the view's CSS spotlight is off. */
.stage-view.bd-host::before, .stage-view.bd-host::after { display: none; }
.bd-host > .stage-fallback.bd-stage { place-items: end center; align-content: end; padding-bottom: 14%; }
.bd-host[data-bd-motion="static"] .bd-mist-band { animation: none; }

/* ---------- tilt (fx.js tilt()): CSS vars --rx --ry --mx --my, written on pointer move ---------- */
.tilt-item { position: relative; transition: transform var(--t-base) var(--ease-out); }
.tilt-item.is-tilting { transform: perspective(900px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)); transition-duration: var(--t-instant); }
.tilt-item::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: radial-gradient(circle at var(--mx, 50%) var(--my, 50%), rgba(255, 197, 61, 0.1), transparent 60%);
  opacity: 0; transition: opacity var(--t-base) var(--ease-out);
}
.tilt-item.is-tilting::after { opacity: 1; }

/* ---------- split-flap (fx.js flap()) ----------
   <span class="flap lit"></span>; flap(el, 'ABCD') builds one .flap-cell per character. Size it with font-size. */
.flap {
  display: inline-flex; gap: 0.1em; vertical-align: middle;
  font-weight: 800; letter-spacing: 0.04em; font-variant-numeric: tabular-nums; line-height: 1;
}
.flap-cell {
  --flap-bg: var(--cocoa);
  position: relative; display: inline-block; min-width: 0.95em; height: 1.3em; padding: 0 0.1em;
  line-height: 1.3em; text-align: center; color: var(--cream);
  background: var(--flap-bg); border-radius: var(--r-xs);
  box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.55), inset 0 0 0 1px var(--line);
  perspective: 4em;
}
.flap-cell::after {
  content: ''; position: absolute; left: 0; right: 0; top: calc(50% - 0.5px); height: 1px; z-index: 3; pointer-events: none;
  background: rgba(0, 0, 0, 0.7); box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05);
}
.flap-ch { display: block; }
.flap-cell > span:not(.flap-ch) {
  position: absolute; inset: 0; display: block; padding: inherit; border-radius: inherit;
  background: var(--flap-bg); backface-visibility: hidden; will-change: transform;
}
.flap-cell.flipping > .flap-ch, .flap-fold { clip-path: inset(0 0 50% 0); }
.flap-bottom, .flap-unfold { clip-path: inset(50% 0 0 0); }
.flap-fold, .flap-unfold { z-index: 2; }
.flap.lit .flap-cell { color: var(--lemon); }

/* ---------- stamp (fx.js stamp()): the landing animation (stamp-pending → stamp-in) ---------- */
.stamp-pending { opacity: 0; }
.stamp-in { animation: gp-stamp-in 280ms var(--ease-spring) both; }
.stamp-in::after {
  content: ''; position: absolute; inset: -3px; border-radius: inherit; pointer-events: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--stamp) 35%, transparent);
  opacity: 0; animation: gp-stamp-ink 120ms linear 260ms both;
}
@keyframes gp-stamp-in {
  from { opacity: 0; transform: scale(1.35) rotate(calc(var(--rot) - 6deg)); }
  to { opacity: 1; transform: scale(1) rotate(var(--rot)); }
}
@keyframes gp-stamp-ink { 50% { opacity: 1; } }

/* ---------- seat token ---------- */
@keyframes gp-land { from { opacity: 0; transform: translateY(-40px) scale(0.7); } }
@keyframes gp-ring { from { opacity: 0.8; transform: scale(1); } to { opacity: 0; transform: scale(1.6); } }
.avatar {
  position: relative; display: inline-grid; place-items: center; flex: none; border-radius: 50%;
  background: var(--c, var(--ink-3)); color: var(--ink-0); font-weight: 800;
  box-shadow: 0 0 0 2px var(--ink-0), 0 0 0 3px color-mix(in srgb, var(--c, var(--ink-4)) 50%, transparent);
  transition: box-shadow var(--t-quick) var(--ease-out);
}

/* ---------- maps and their markers (Google Maps, public/gmap.js) ---------- */
.gp-pin {
  display: block; width: 26px; height: 26px; background: var(--c); border: 3px solid var(--ink-0);
  border-radius: 50% 50% 50% 0; transform: rotate(-45deg);
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.45); filter: drop-shadow(0 0 6px var(--c));
}
.gp-pin.drop { animation: gp-pin-drop 380ms var(--ease-spring) both; }
@keyframes gp-pin-drop {
  0% { transform: translateY(-28px) rotate(-45deg); opacity: 0; }
  60% { opacity: 1; }
  88% { transform: translateY(0) rotate(-45deg); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.7); }
  100% { transform: rotate(-45deg); }
}
/* Beacon: centred in its divIcon box whatever the icon size (inset 0 + margin auto). Text inside = a number. */
.gp-target {
  position: absolute; inset: 0; margin: auto; width: 16px; height: 16px;
  display: grid; place-items: center; border-radius: 50%;
  background: var(--sodium); color: var(--sodium-ink); font: 800 0.7rem/1 var(--font);
  box-shadow: 0 0 0 2px var(--paper), 0 0 14px rgba(255, 197, 61, 0.6);
}
.gp-target:not(:empty) { width: 22px; height: 22px; }
.gp-target::before, .gp-target::after {
  content: ''; position: absolute; inset: 0; border-radius: 50%; border: 2px solid var(--sodium); pointer-events: none;
  opacity: 0; animation: gp-beacon 1.1s var(--ease-out) 2 both;
}
.gp-target::after { animation-delay: 0.35s; }
@keyframes gp-beacon { from { opacity: 0.8; transform: scale(0.6); } to { opacity: 0; transform: scale(2.4); } }
.gp-dot {
  display: block; width: 100%; height: 100%; box-sizing: border-box; border-radius: 50%;
  background: var(--c); border: 3px solid #fff; box-shadow: 0 1px 4px rgba(0, 0, 0, .45);
}

/* The map box (the warm style itself is gmap.js STYLE). A failed load or a rejected key: the reason in the middle. */
.gp-map { background: #a9d3df; font-family: var(--font); }
.gp-map[data-error] { display: grid; place-items: center; }
.gp-map[data-error]::after {
  content: attr(data-error); max-width: 80%; padding: .6em 1em; border-radius: var(--r-md); text-align: center;
  background: var(--cream); color: var(--ink); font: 700 .9rem/1.3 var(--font); box-shadow: var(--outline);
}
/* HTML markers: .gp-mk sits on the spot, .gp-icon is the marker box (size and anchor from gmap.js). */
.gp-mk { position: absolute; width: 0; height: 0; }
.gp-mk:hover, .gp-mk.dragging { z-index: 2000 !important; }
.gp-icon { position: absolute; left: 0; top: 0; }
.gp-mk.drag .gp-icon { cursor: grab; touch-action: none; }
.gp-mk.dragging .gp-icon { cursor: grabbing; }
.gp-tip {
  position: absolute; left: 0; translate: -50% 0; display: none; white-space: nowrap; pointer-events: none;
  padding: 3px 9px; border-radius: var(--r-pill); background: var(--cream); color: var(--ink);
  font: 700 .8rem/1.2 var(--font); box-shadow: 0 0 0 2px var(--ink), 0 2px 0 rgba(36, 23, 15, .35);
}
.gp-tip.above { bottom: var(--off); }
.gp-tip.below { top: var(--off); }
.gp-mk:hover .gp-tip, .gp-tip.on { display: block; }
/* our + and − (gmap.js), top left, in the game's look */
.gp-zoom { display: grid; margin: 10px; border-radius: var(--r-sm); overflow: hidden; box-shadow: var(--outline), var(--toy-1); }
.gp-zoom button {
  width: 30px; height: 30px; padding: 0; border: 0; border-radius: 0; box-shadow: none; translate: none;
  background: var(--cream); color: var(--ink); font: 800 18px/30px var(--font); cursor: pointer;
}
.gp-zoom button + button { border-top: 1px solid var(--line-strong); }
.gp-zoom button:hover, .gp-zoom button:focus-visible { background: var(--clay); }

/* Low tier (fx.js perfTier()): no soft filters. */
body.lite .gp-pin { filter: none; }

/* ---------- page enter (§5.1) ---------- */
/* The cross-document opt-in (@view-transition) is an inline <style> in each page's <head>: in an
   external sheet Chrome reports "InvalidStateError: Transition was aborted … opt-in disabled" on load. */
.logo { view-transition-name: brand; }
.playdock { view-transition-name: playdock; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: var(--t-base); }
/* [data-enter] rises 16 px and fades in, --i × --stagger late. Without fx.js enter() it plays on load;
   with it (html.enter-ready) it waits until the element scrolls into view (.is-in). */
[data-enter] { animation: gp-rise var(--t-slow) var(--ease-out) both; animation-delay: calc(var(--i, 0) * var(--stagger)); }
.enter-ready [data-enter]:not(.is-in) { animation: none; opacity: 0; }
@keyframes gp-rise { from { opacity: 0; transform: translateY(16px); } }

/* ---------- reduced motion (§5.7): everything lands in its end state; nothing loops ----------
   html.force-reduced-motion mirrors it for test pages (the 3D lab). */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
  [data-enter], .stamp-in, .stamp-in::after, .gp-pin.drop, .tile::after, .sticker-tag.pop, dialog.sheet[open] { animation: none !important; }
  .enter-ready [data-enter]:not(.is-in) { opacity: 1; }
  .bd-mist-band { animation: none !important; }
  .stamp-pending { opacity: 1; }
  .gp-target::before { animation: none; opacity: .35; transform: scale(1.8); }
  .gp-target::after { animation: none; opacity: 0; }
  button, .btn, .tile, :is(a, button).card { translate: none !important; }
  button.big::before, .btn.big::before { translate: none !important; }
  button, .btn, input, .tile, .seg > *, .stage-canvas, .stage-fallback, .tilt-item, .tilt-item::after { transition: none !important; }
  .tilt-item.is-tilting { transform: none; }
}
.force-reduced-motion :is([data-enter], .puck.land-in, .tile::after, .sticker-tag.pop, .bd-mist-band) { animation: none !important; }
.force-reduced-motion :is(button, .btn, .tile) { translate: none !important; transition: none !important; }

/* ---------- host screen (couch TV, host.html: body.host; :where keeps the old specificity) ---------- */
.host:where(body) { display: grid; grid-template-rows: auto 1fr; height: 100vh; }
.host:where(body) header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 28px; font-size: 1.4rem;
}
.host:where(body) main { position: relative; overflow: hidden; }
:where(body.host) .join-url { font-size: 1.5rem; margin: 0.6em 0 1.2em; }
:where(body.host) .roster { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; max-width: 900px; margin: 0 auto 28px; }
.chip-name {
  background: var(--panel-2); padding: 0.45em 1em; border-radius: 999px; font-weight: 600;
  display: inline-flex; gap: 0.5em; align-items: center;
}
.chip-name i { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }
.chip-name.off { opacity: 0.4; }
.chip-name.locked { outline: 2px solid var(--good); }
.chip-name .kick { background: transparent; color: var(--muted); border: 0; padding: 0 0.2em; margin-left: 0.2em; font: inherit; font-size: 0.9em; cursor: pointer; line-height: 1; }
.chip-name .kick:hover, .chip-name .kick:focus-visible { color: var(--bad); }
.chip-name .kick.armed { color: var(--bad); font-weight: 700; }
.join-qr { margin: 0 auto 1.2em; display: grid; justify-items: center; gap: 8px; max-width: 320px; }
.join-qr svg { width: 220px; height: 220px; border-radius: 8px; display: block; }
.join-qr figcaption { text-align: center; }

.stage-photo { position: absolute; inset: 0; z-index: 0; background: #000; } /* own stacking context: the Glimpse card stays under the HUD */
.stage-photo img { width: 100%; height: 100%; object-fit: contain; }
.hud {
  position: absolute; left: 24px; right: 24px; bottom: 24px;
  display: flex; justify-content: space-between; align-items: flex-end; gap: 16px; pointer-events: none;
}
:where(body.host) .hud .roster { margin: 0; justify-content: flex-start; }
.timer {
  font-size: 3.5rem; font-weight: 800; min-width: 2.2em; text-align: center;
  background: rgba(18, 19, 28, 0.8); border-radius: var(--radius); padding: 0.1em 0.3em;
}
.timer.urgent { color: var(--bad); }

.reveal { display: grid; grid-template-columns: 1fr 380px; height: 100%; }
.reveal .map { height: 100%; }
.reveal aside { background: var(--panel); padding: 22px; overflow: auto; display: flex; flex-direction: column; gap: 14px; }
.reveal h2 { margin: 0; font-size: 1.6rem; line-height: 1.15; }
.reveal .thumb { width: 100%; border-radius: 12px; max-height: 180px; object-fit: cover; }
.credit { font-size: 0.8rem; }
.credit a { color: var(--muted); }
table.results { width: 100%; border-collapse: collapse; }
table.results td { padding: 6px 4px; border-bottom: 1px solid var(--panel-2); }
table.results td:last-child { text-align: right; font-weight: 700; }
.plus { color: var(--good); }
.minus { color: var(--bad); }
.tag { font-size: 0.75rem; background: var(--panel-2); border-radius: 6px; padding: 2px 6px; margin-left: 4px; }
.tag.gold { background: var(--accent); color: #1a1400; }

.podium { display: flex; gap: 18px; align-items: flex-end; justify-content: center; margin: 28px 0; }
.podium div { background: var(--panel); border-radius: var(--radius) var(--radius) 0 0; padding: 18px 26px; min-width: 160px; }
.podium .p1 { height: 220px; background: var(--accent); color: #1a1400; }
.podium .p2 { height: 170px; }
.podium .p3 { height: 130px; }
.podium b { display: block; font-size: 1.6rem; }

/* ---------- phone ---------- */
.phone { min-height: 100dvh; display: flex; flex-direction: column; }
.phone .screen { flex: 1; display: flex; flex-direction: column; padding: 16px; gap: 14px; }
.phone .join { justify-content: center; max-width: 420px; width: 100%; margin: 0 auto; }
.phone .join .code-input { text-transform: uppercase; letter-spacing: 0.3em; text-align: center; font-size: 1.6rem; font-weight: 800; }
.phone h1 { margin: 0 0 8px; font-size: 2.4rem; }
.phone .guess { padding: 0; gap: 0; }
.phone .guess .peek { height: 30dvh; background: #000; position: relative; }
.phone .guess .peek img { width: 100%; height: 100%; object-fit: contain; }
.phone .guess .peek .timer { position: absolute; right: 8px; top: 8px; z-index: 4; font-size: 1.6rem; } /* above the Glimpse card */
.phone .guess .peek.big { position: fixed; inset: 0; height: auto; z-index: 1000; }
.phone .guess .map { flex: 1; min-height: 240px; }
.controls { padding: 12px; background: var(--panel); display: grid; gap: 10px; }
.chips { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.chips button { background: var(--panel-2); color: var(--text); padding: 0.7em 0.4em; font-size: 0.95rem; }
.chips button.on { background: var(--accent); color: #1a1400; }
.big-msg { flex: 1; display: grid; place-items: center; text-align: center; font-size: 1.4rem; }
.big-msg strong { display: block; font-size: 3rem; }

@media (max-width: 900px) {
  .reveal { grid-template-columns: 1fr; grid-template-rows: 55% 45%; }
}

/* ---------- Street View ---------- */
.pano { position: absolute; inset: 0; }
.phone .expand {
  position: absolute; left: 8px; top: 8px; z-index: 5;
  padding: 0.3em 0.7em; background: rgba(18, 19, 28, 0.75);
}
#sv { background: #000; }
#go-start {
  position: absolute; left: 16px; top: 16px; z-index: 5;
  padding: 0.5em 1em; background: rgba(18, 19, 28, 0.8);
}
.phone #go-start { left: 52px; top: 8px; padding: 0.3em 0.8em; font-size: 0.9rem; }
.phone .guess .peek.big { z-index: 2000; } /* above the map and its markers */

/* Google's footer links (logo → Google Maps, "Report a problem") would reveal the spot in one tap.
   They stay visible as Google requires, but these transparent pads catch the taps. */
.sv-guard { position: absolute; inset: 0; pointer-events: none; z-index: 4; }
.sv-guard span { position: absolute; bottom: 0; pointer-events: auto; cursor: default; }
.sv-guard .left { left: 0; width: 96px; height: 34px; }
.sv-guard .right { right: 0; width: 440px; max-width: 70%; height: 26px; }
/* Still mode: the whole viewer is covered, so it can't be dragged or zoomed. */
.sv-guard.still { pointer-events: auto; cursor: default; }

/* ---------- game settings (host lobby / final) ---------- */
.settings { display: grid; gap: 12px; justify-items: center; margin: 0 auto 24px; max-width: 900px; }
.presets { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.presets button { background: var(--panel-2); color: var(--text); padding: 0.5em 1.2em; }
.presets button.on { background: var(--accent); color: #1a1400; }
.presets .custom { opacity: 0.5; cursor: default; }
.presets .custom.on { opacity: 1; }
.fields { display: flex; flex-wrap: wrap; gap: 10px 16px; justify-content: center; }
.fields label { display: grid; gap: 4px; font-size: 0.8rem; color: var(--muted); text-align: left; }
/* one ink outline (the input rule's box-shadow), no second border */
.fields select, .league-pick select { width: auto; max-width: 100%; font-size: 1rem; padding: .45em 2em .45em .75em; }
.loading-line { font-size: 1.6rem; }
.tag.good { background: var(--good); color: #0f1a0f; }

/* ---------- accounts and leagues ---------- */
.badge { font-size: 0.7rem; background: var(--good); color: #0f1a0f; border-radius: 999px; padding: 0 0.45em; }
.badge.rated { background: var(--accent); color: #1a1400; }
.small { font-size: 0.8rem; }
.small a, #final-league a { color: var(--muted); }
.account-bar { text-align: center; }
.account-bar a { color: var(--accent); }
.phone #signin { max-width: 460px; width: 100%; margin: 0 auto; }
.league-pick { display: grid; gap: 4px; font-size: 0.8rem; color: var(--muted); text-align: left; }
.league-pick select { min-width: 12em; }

/* Shown while the WebSocket reconnects. */
body.offline::after {
  content: 'Reconnecting…'; position: fixed; left: 50%; top: 10px; transform: translateX(-50%); z-index: 3000;
  background: var(--cocoa); color: var(--cream); padding: 0.4em 1em; border-radius: var(--r-pill); font-size: 0.9rem; font-weight: 600;
  box-shadow: var(--toy-2), inset 5px 0 0 var(--tangerine);
}
/* Messages for a few seconds. Kept in the page and only faded, so the live region is announced. */
.toast {
  --bar: var(--sodium);
  position: fixed; left: 50%; bottom: calc(var(--sv-footer, 0px) + 20px); transform: translate(-50%, 12px); z-index: var(--z-toast); max-width: min(90vw, 520px);
  background: var(--cocoa); color: var(--cream); padding: 0.7em 1.2em 0.7em 1.4em; border-radius: var(--r-md); margin: 0; font-weight: 600;
  box-shadow: var(--toy-2), inset 5px 0 0 var(--bar); opacity: 0; pointer-events: none;
  transition: opacity var(--t-base) var(--ease-out), transform var(--t-base) var(--ease-out);
}
.toast.show { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }
.toast.good { --bar: var(--go-bright); }
.toast.bad, .toast.error { --bar: var(--stop-bright); }
.toast.warn { --bar: var(--tangerine); }

/* ---------- 3-2-1 before a round (fx.js countdownRing), on every screen ---------- */
.ring { position: relative; width: 170px; height: 170px; display: grid; place-items: center; }
/* a soft disc behind the numeral, so the ring reads as one object on any background */
.ring::before {
  content: ''; position: absolute; inset: 9%; border-radius: 50%;
  background: radial-gradient(circle at 50% 40%, rgba(255, 246, 228, .1), rgba(255, 246, 228, .02) 70%);
  box-shadow: inset 0 0 0 1px rgba(255, 246, 228, .06);
}
/* overflow visible: the sweep's glow reaches past the viewBox (r 54 + stroke 3 + 6 px blur > 60) and was cut off */
.ring svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; transform: rotate(-90deg); }
.ring circle { fill: none; stroke-width: 6; }
.ring .track { stroke: var(--line); }
.ring .sweep { stroke: var(--sodium); stroke-linecap: round; filter: drop-shadow(0 0 6px rgba(255, 197, 61, 0.55)); }
.ring b { position: relative; font-size: 4.8rem; font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1; }
.ring b.tick { animation: ring-tick 420ms var(--ease-spring) both; }
@keyframes ring-tick { from { scale: 1.35; opacity: .25; } to { scale: 1; opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .ring b.tick { animation: none; } }
.lead {
  position: absolute; inset: 0; z-index: 6; display: grid; place-items: center;
  background: var(--veil-solid); /* opaque by rule: never a partial view of the panorama */
}
.phone .lead .ring { width: 120px; height: 120px; }
.phone .lead .ring b { font-size: 3.2rem; }
.ready-line { margin-top: 14px; font-size: 1rem; }

.lead-note { position: absolute; left: 0; right: 0; bottom: 8%; margin: 0; padding: 0 16px; text-align: center; font-size: 1.1rem; color: var(--muted); }
.phone .lead-note { font-size: 0.85rem; bottom: 6px; }
.twist-note { margin: 0; padding: 4px 12px 0; font-size: 0.85rem; text-align: center; }

/* Impressum / privacy links at the bottom of the entry screens */
.legal-links { margin-top: auto; text-align: center; font-size: 0.8rem; color: var(--muted); padding: 12px 16px 20px; }
.legal-links a { color: var(--muted); }

/* ---------- Stage 8: breakdown, highlights, awards, reactions ---------- */
.chip-name.away { opacity: 0.7; outline: 2px dashed var(--muted); }
.results .place { color: var(--muted); font-variant-numeric: tabular-nums; }
.results .parts { display: block; font-size: 0.78rem; line-height: 1.35; margin-top: 2px; font-weight: 400; }
.results .part.base { color: var(--text); }
.results .part.good { color: var(--good); }
.results .part.bad { color: var(--bad); }
.results .part.gold { color: var(--accent); }
.results .sep { color: var(--muted); }
.highlights { display: grid; gap: 8px; }
.highlights p {
  margin: 0; padding: 0.6em 0.9em; border-radius: 12px; font-size: 1.15rem; font-weight: 700;
  background: color-mix(in srgb, var(--accent) 18%, var(--panel-2)); border-left: 4px solid var(--accent);
}
.podium div { position: relative; }
.podium .place { display: block; font-size: 2.4rem; font-weight: 800; line-height: 1; opacity: 0.6; }
.awards { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 12px; max-width: 900px; margin: 0 auto 24px; text-align: left; }
.award { display: flex; gap: 12px; align-items: center; background: var(--panel); border-radius: var(--radius); padding: 12px 16px; }
.award .icon { font-size: 2rem; }
.award b { display: block; font-size: 1.1rem; }
.award span:not(.icon) { color: var(--muted); font-size: 0.95rem; }
.big-msg .breakdown { display: block; font-size: 0.95rem; margin-top: 6px; }
.phone #wait { position: relative; overflow: hidden; }
.reactions { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.reactions button { font-size: 1.9rem; min-height: 60px; padding: 0.2em; border-radius: 16px; line-height: 1; }
.reactions button:active { transform: scale(0.92); }
.reactions.cooling button { opacity: 0.5; }

/* Tour guide (stage 11), couch: the guide's phone shows the place full screen, nothing to pin with. */
.phone #guess.guiding .map, .phone #guess.guiding .controls, .phone #guess.guiding .expand, .phone #guess.guiding .twist-note { display: none; }
.host .guided { margin: 0 0 10px; font-weight: 700; }

/* Home turf (stage 13), couch: the phone's spot picker. */
.phone .turf { gap: 10px; }
.phone .turf h2 { margin: 0; }
.phone .turf .small { margin: 0; }
.phone #turf-map { flex: none; height: 60dvh; min-height: 240px; border-radius: var(--radius); }
.turf-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.turf-actions button { flex: 1; }

/* Stage 14: Underdog's call on the TV and phone reveal. */
:is(.phone, .host) .pick { margin: 12px 0; text-align: left; }
:is(.phone, .host) .pick > p, :is(.phone, .host) .pick-line { margin: 0 0 8px; font-size: 0.95rem; }
:is(.phone, .host) .pick .cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
:is(.phone, .host) .pick .card { display: grid; gap: 2px; justify-items: center; text-align: center; padding: 10px 6px; border-radius: var(--radius); background: var(--panel-2); color: var(--text); border: 2px solid transparent; font: inherit; }
:is(.phone, .host) .pick .card .icon { font-size: 1.5rem; }
:is(.phone, .host) .pick .card small { font-size: 0.75rem; opacity: 0.75; font-weight: 400; }
:is(.phone, .host) .pick .card.chosen, :is(.phone, .host) .pick button.card[aria-pressed="true"] { border-color: var(--good); }
:is(.phone, .host) .pick button.card:disabled { opacity: 1; cursor: default; }
@media (max-width: 420px) { :is(.phone, .host) .pick .cards { grid-template-columns: 1fr; } }

/* Glimpse (stage 10), Tour guide (stage 11) and Last Pin Standing (stage 12): shared by game, TV and phone. Hides the round's whole viewer, Google's footer
   included (never a partial cover); visibility keeps its size so the panorama loads behind the lead. */
.eyes-lead > img, .eyes-lead > .pano, .eyes-lead > .sv-guard, .eyes-lead > .go-start, .eyes-lead > .expand,
.eyes-shut > img, .eyes-shut > .pano, .eyes-shut > .sv-guard, .eyes-shut > .go-start, .eyes-shut > .expand { visibility: hidden; }
.eyes-card { position: absolute; inset: 0; display: none; place-items: center; align-content: center; gap: 6px;
  text-align: center; padding: 24px; background: #000; color: var(--text); z-index: 3; }
.eyes-card b { font-size: clamp(1.4rem, 4vw, 2.4rem); }
.eyes-shut > .eyes-card { display: grid; }
.blind > img, .blind > .pano, .blind > .sv-guard, .blind > .go-start, .blind > .expand { visibility: hidden; }
.listen-card { position: absolute; inset: 0; display: none; place-items: center; align-content: center; gap: 6px;
  text-align: center; padding: 24px; background: #000; color: var(--text); z-index: 3; }
.listen-card b { font-size: clamp(1.4rem, 4vw, 2.4rem); }
.blind > .listen-card { display: grid; }
.chip-name.ghost { opacity: 0.5; }
.chip-name .energy { width: 44px; margin-left: 8px; }
.rank-row .hit, .results .hit { display: block; color: var(--bad); font-size: 0.8rem; }
.my-energy { margin: 0; padding: 4px 12px 0; font-size: 0.85rem; text-align: center; }
.phone #guess.guiding .my-energy { display: none; }
.energy { display: inline-block; position: relative; width: 72px; height: 8px; border-radius: 4px; background: rgba(255,255,255,0.14); overflow: hidden; vertical-align: middle; }
.energy > i { position: absolute; inset: 0 auto 0 0; width: calc(var(--e, 1) * 100%); background: var(--good); transition: width 400ms ease-out; }
.energy.low > i { background: var(--bad); } /* under 25 % */
.energy.ghost > i { width: 0; }
@media (prefers-reduced-motion: reduce) { .energy > i { transition: none; } }

/* ---------- figure editor (look-editor.js, §4.8.2) ----------
   A sheet: the preview (live 3D on its puck, or the layered portrait on the pin-colour disc) beside a
   4 × 3 grid of portraits and the Face / Hat / Extras rows; stacked on phones. */
dialog.sheet.look-sheet { width: min(700px, calc(100vw - 24px)); max-width: none; max-height: calc(100dvh - 24px); overflow: auto; padding: var(--sp-5); }
.look-form { display: grid; gap: var(--sp-3); }
.look-form h2 { margin: 0; font-size: var(--fs-h2); }
.look-main { display: grid; grid-template-columns: minmax(180px, 240px) 1fr; gap: var(--sp-4); align-items: start; }
.look-preview { position: sticky; top: 0; }
.look-stage {
  position: relative; aspect-ratio: 1; border-radius: var(--r-lg); overflow: hidden;
  background: radial-gradient(circle at 50% 58%, color-mix(in srgb, var(--c, var(--lemon)) 70%, #fff) 0 46%, var(--sky) 47%);
  box-shadow: inset 0 0 0 2.5px var(--ink);
}
.look-stage .stage-view { position: absolute; inset: 0; }
.look-stage:has(.is-live) { background: var(--sky); } /* the live figure brings its own puck */
.look-stage .stage-fallback { place-items: end center; }
.look-portrait { width: 88%; aspect-ratio: 1; display: block; }
.look-portrait img.no-img, .look-sw img.no-img { visibility: hidden; }
.look-controls { display: grid; gap: var(--sp-3); min-width: 0; }
.look-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
.look-pick {
  position: relative; padding: 0; aspect-ratio: 1; border-radius: var(--r-md); overflow: hidden;
  background: var(--clay); box-shadow: 0 0 0 2px var(--ink); translate: none; min-width: 44px;
}
.look-pick:where(:hover:not(:disabled)) { translate: 0 -2px; box-shadow: 0 0 0 2px var(--ink), 0 3px 0 var(--edge-ink); }
.look-pick[aria-pressed='true'] { background: var(--lemon); box-shadow: 0 0 0 3px var(--ink), 0 0 0 6px var(--c, var(--lemon)); }
.look-pic { position: absolute; inset: 0; display: block; }
.look-pick .look-num { position: absolute; inset: 0; display: none; place-items: center; font-weight: 800; }
.look-pick.no-img .look-pic { visibility: hidden; }
.look-pick.no-img .look-num { display: grid; }
/* Face, Hat, Extras: a label over a row that wraps (never wider than the sheet) */
.look-row { display: grid; gap: 6px; min-width: 0; }
.look-label { font-weight: 700; }
.look-swatches { display: flex; flex-wrap: wrap; gap: 6px; }
.look-sw {
  position: relative; width: 44px; height: 44px; padding: 0; flex: none; border-radius: var(--r-md); overflow: hidden;
  background: var(--clay); box-shadow: 0 0 0 2px var(--ink); translate: none; color: var(--ink);
}
.look-sw:where(:hover:not(:disabled)) { translate: 0 -2px; box-shadow: 0 0 0 2px var(--ink), 0 3px 0 var(--edge-ink); }
.look-sw[aria-pressed='true'] { background: var(--lemon); box-shadow: 0 0 0 3px var(--ink), 0 0 0 6px var(--c, var(--lemon)); }
/* the portrait layer, cropped: the face (eyes and mouth) for faces, the top of the head for hats (crops
   for the portrait frame y 0.19–1.05 of public/dev-portraits.js FRAME; change both together) */
.look-sw img { position: absolute; max-width: none; pointer-events: none; }
[data-face] > img { width: 302%; height: 302%; left: -93%; top: -153%; }
[data-hat] > img { width: 140%; height: 140%; left: -20%; top: -5%; }
.look-sw-none { font-size: .78rem; font-weight: 800; }
.look-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.look-chips > button {
  padding: .45em .9em; min-height: 40px; border-radius: var(--r-pill); background: var(--clay); color: var(--ink);
  font-weight: 700; box-shadow: 0 0 0 2px var(--ink); translate: none;
}
.look-chips > button[aria-pressed='true'] { background: var(--lemon); box-shadow: 0 0 0 3px var(--ink); }
.look-note { margin: 0; }
.look-form .error:empty { min-height: 0; }
.look-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3); }
/* a quiet text action (no fill, no edge) */
button.link-btn {
  background: none; box-shadow: none; padding: .4em .2em; color: var(--ink); font-weight: 700;
  text-decoration: underline; text-underline-offset: .2em; translate: none; margin-left: auto;
}
button.link-btn:hover:not(:disabled) { background: none; box-shadow: none; translate: none; text-decoration-thickness: 2px; }
button.link-btn:active:not(:disabled) { translate: none; box-shadow: none; }
button.link-btn:disabled { background: none; box-shadow: none; }
@media (max-width: 560px) {
  dialog.sheet.look-sheet { padding: var(--sp-4); }
  .look-main { grid-template-columns: 1fr; }
  .look-stage { width: min(170px, 50vw); justify-self: center; }
  .look-grid { gap: 6px; }
  .look-preview { position: static; }
  .look-swatches { gap: 5px; }
  .look-sw { width: 42px; height: 42px; }
  .look-actions > button:not(.link-btn) { flex: 1 1 auto; }
  button.link-btn { margin-left: 0; width: 100%; text-align: center; }
}
/* a layered figure portrait (look.js paintPortrait): figure, accessory and hat images in one cell */
.portrait-stack { display: grid; width: 100%; height: 100%; min-width: 0; }
.portrait-stack > :is(img, canvas) { grid-area: 1 / 1; width: 100%; height: 100%; object-fit: contain; display: block; min-width: 0; }
/* the small figure button (join forms, lobbies): your portrait on your pin colour */
.figure-btn {
  --size: 56px;
  position: relative; flex: none; width: var(--size); height: var(--size); padding: 0; border-radius: 50%;
  display: inline-grid; place-items: center;
  background: var(--c, var(--lemon)); color: var(--ink); font-weight: 800; font-size: calc(var(--size) * .34);
  box-shadow: 0 0 0 2.5px var(--ink), inset 0 -6px 0 rgba(0, 0, 0, .18);
}
.figure-btn img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; }
.figure-btn .portrait-stack { border-radius: 50%; overflow: hidden; }
.figure-btn::after {
  content: '✎'; position: absolute; right: -4px; bottom: -4px; width: 22px; height: 22px; border-radius: 50%;
  display: grid; place-items: center; font-size: 12px; background: #fff; box-shadow: 0 0 0 2px var(--ink);
}

/* ---------- shirt prints (print-editor.js, print-gallery.js; the figure editor's "Shirt print" row) ----------
   The editor: a 24 × 24 grid (fills the sheet's width on phones, at least 13 px a square) beside the tools,
   colours, history buttons and a shirt preview. Light sheets on every page, also over a dusk screen. */
html dialog.sheet:is(.print-sheet, .print-picker, .print-ask) { background: #fff; color: var(--ink); box-shadow: var(--outline), var(--toy-3); }
dialog.sheet.print-sheet { width: min(760px, calc(100vw - 24px)); max-width: none; max-height: calc(100dvh - 24px); overflow: auto; padding: var(--sp-5); }
.print-form { display: grid; gap: var(--sp-3); }
.print-form h2, .print-picker h2, .print-ask h2 { margin: 0; font-size: var(--fs-h2); }
.print-main { display: grid; grid-template-columns: minmax(0, 432px) minmax(200px, 1fr); gap: var(--sp-4); align-items: start; }
.print-canvas-wrap { min-width: 0; }
.print-grid {
  display: block; width: 100%; aspect-ratio: 1; border-radius: var(--r-sm); background: #fbf5ea;
  box-shadow: 0 0 0 2.5px var(--ink); touch-action: none; cursor: crosshair; image-rendering: pixelated;
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
}
.print-grid:focus-visible { outline: 3px solid var(--ink); outline-offset: 4px; }
.print-side { display: grid; gap: var(--sp-3); min-width: 0; }
.print-tools, .print-history { display: flex; flex-wrap: wrap; gap: 6px; }
.print-tools > button, .print-history > button {
  padding: .45em .9em; min-height: 40px; border-radius: var(--r-pill); font-weight: 700; translate: none;
}
.print-tools > button { background: var(--clay); color: var(--ink); box-shadow: 0 0 0 2px var(--ink); }
.print-tools > button[aria-pressed='true'] { background: var(--lemon); box-shadow: 0 0 0 3px var(--ink); }
.print-history > button.ghost { box-shadow: 0 0 0 2px var(--ink); }
.print-history > button:disabled { box-shadow: 0 0 0 2px var(--ink-2); }
/* German tool words are longer (Rückgängig, Wiederholen): tighter buttons that share the row; where they still
   wrap (the narrow desktop side column), the wrapped one fills its row instead of dangling */
:lang(de) .print-history > button { padding-inline: .6em; flex: 1 1 auto; }
.print-palette { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 6px; padding: 4px; border-radius: var(--r-sm); }
.print-palette:focus-visible { outline: 3px solid var(--ink); outline-offset: 2px; }
.print-palette > [role='option'] {
  position: relative; aspect-ratio: 1; min-width: 32px; min-height: 32px; border-radius: var(--r-xs); cursor: pointer;
  background: var(--sw); box-shadow: 0 0 0 2px var(--ink);
}
.print-palette > [aria-selected='true'] { box-shadow: 0 0 0 3px var(--ink), 0 0 0 6px var(--lemon); z-index: 1; }
.print-palette > [aria-selected='true']::after {
  content: ''; position: absolute; inset: 30%; border-radius: 50%; background: #fff; box-shadow: 0 0 0 2px var(--ink);
}
.print-palette > .print-none {
  background: repeating-conic-gradient(#efe4d2 0 25%, #fbf5ea 0 50%) 0 0 / 12px 12px;
}
.print-palette > .print-none::before { /* the eraser: a red slash through the empty square */
  content: ''; position: absolute; left: 12%; right: 12%; top: calc(50% - 1.5px); height: 3px; border-radius: 2px; background: var(--stop); rotate: -45deg;
}
.print-preview { display: flex; align-items: center; gap: var(--sp-3); }
.print-preview p { margin: 0; }
.print-shirt { width: 96px; height: 96px; flex: none; border-radius: var(--r-md); background: var(--sky); box-shadow: inset 0 0 0 2px var(--ink); }
.print-save { display: grid; gap: 6px; }
:is(.print-sheet, .print-ask) .field { display: grid; gap: 6px; font-size: var(--fs-small); font-weight: 600; color: var(--ink-2); }
:is(.print-sheet, .print-ask) .field :is(input, textarea) { font-size: 1rem; font-weight: 400; }
:is(.print-sheet, .print-ask) .hint { font-weight: 400; }
.print-name { max-width: 360px; }
.print-guest, .look-print-signin, .look-print-beard, .print-signin { margin: 0; }
.print-form .error:empty { min-height: 0; }
.print-sheet .notice, .print-picker .notice { margin: 0; padding: 10px 14px; border-radius: var(--r-md); background: var(--clay); box-shadow: inset 0 0 0 2px var(--ink); color: var(--go); font-weight: 700; }
.print-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3); }
.print-empty-hint { margin-left: auto; }
.print-ask { width: min(440px, calc(100vw - 24px)); }
.print-ask-form { display: grid; gap: var(--sp-3); }
.print-ask-body { margin: 0; line-height: 1.45; }
.print-ask textarea { resize: vertical; min-height: 4.5em; }
.print-ask-actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
.print-ask button.danger { background: var(--stop); color: #fff; }

/* the picker sheet: "Your prints" and "Gallery" as tabs */
dialog.sheet.print-picker { width: min(640px, calc(100vw - 24px)); max-width: none; max-height: calc(100dvh - 24px); overflow: auto; padding: var(--sp-5); display: none; }
dialog.sheet.print-picker[open] { display: grid; gap: var(--sp-3); align-content: start; }
.print-picker-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
.print-picker-head .print-close { padding: .5em 1.1em; }
.print-tabs { display: inline-flex; gap: 4px; padding: 4px; justify-self: start; border-radius: var(--r-pill); background: var(--clay); box-shadow: inset 0 0 0 2px var(--ink); }
.print-tabs > button { padding: .45em 1.1em; background: transparent; box-shadow: none; translate: none; font-weight: 700; }
.print-tabs > button:hover:not(:disabled) { box-shadow: none; translate: none; background: var(--clay-2); }
.print-tabs > button[aria-selected='true'] { background: var(--lemon); box-shadow: 0 0 0 2px var(--ink); }
.print-panel { display: grid; gap: var(--sp-3); }
.print-panel[hidden] { display: none; }
.print-panel > p, .print-panel-top p { margin: 0; }
.print-panel-top { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); flex-wrap: wrap; }

/* a list of prints (picker, account page) */
.print-list-box { display: grid; gap: var(--sp-3); }
.print-list-box[aria-busy='true'] { opacity: .6; }
.print-list-box > p { margin: 0; }
.print-status:empty { display: none; }
.print-tiles { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(224px, 1fr)); gap: var(--sp-3); }
.print-tile {
  display: grid; grid-template-columns: 64px 1fr; gap: 8px 10px; align-items: center; padding: 10px;
  border-radius: var(--r-md); background: var(--cream); box-shadow: 0 0 0 2px var(--ink);
}
.print-tile-sw { width: 64px; height: 64px; border-radius: var(--r-sm); background: var(--sky); box-shadow: inset 0 0 0 2px var(--ink); }
.print-tile-text { display: grid; gap: 2px; min-width: 0; }
.print-tile-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.print-tile-actions { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
button.print-act { padding: .4em .9em; min-height: 36px; font-weight: 700; box-shadow: 0 0 0 2px var(--ink), 0 2px 0 var(--edge-ink); }
button.print-act:where(:hover:not(:disabled)) { translate: 0 -1px; box-shadow: 0 0 0 2px var(--ink), 0 3px 0 var(--edge-ink); }
button.link-btn.print-report { font-weight: 600; color: var(--ink-2); font-size: var(--fs-small); }
button.link-btn.print-report[aria-disabled='true'] { text-decoration: none; cursor: default; }
.print-more { justify-self: center; }
/* "Make public": a small switch */
button.print-switch {
  grid-column: 1 / -1; justify-self: start; display: inline-flex; align-items: center; gap: 8px; padding: 2px 0;
  background: none; box-shadow: none; translate: none; color: var(--ink); font-weight: 700; font-size: var(--fs-small);
}
button.print-switch:hover:not(:disabled), button.print-switch:active:not(:disabled) { translate: none; box-shadow: none; }
button.print-switch:disabled { background: none; box-shadow: none; opacity: .6; }
.print-switch-track { position: relative; width: 44px; height: 26px; flex: none; border-radius: var(--r-pill); background: var(--clay); box-shadow: inset 0 0 0 2px var(--ink); transition: background-color var(--t-quick) var(--ease-out); }
.print-switch-thumb { position: absolute; top: 4px; left: 4px; width: 18px; height: 18px; border-radius: 50%; background: #fff; box-shadow: 0 0 0 2px var(--ink); transition: translate var(--t-quick) var(--ease-spring); }
.print-switch[aria-checked='true'] .print-switch-track { background: var(--leaf); }
.print-switch[aria-checked='true'] .print-switch-thumb { translate: 18px 0; }
@media (prefers-reduced-motion: reduce) { .print-switch-track, .print-switch-thumb { transition: none; } }

/* the figure editor's row */
.look-print-cur canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.look-print-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.look-print-actions > button { padding: .45em .9em; min-height: 40px; font-weight: 700; translate: none; box-shadow: 0 0 0 2px var(--ink), 0 2px 0 var(--edge-ink); }
.look-print-actions > button:where(:hover:not(:disabled)) { translate: 0 -1px; box-shadow: 0 0 0 2px var(--ink), 0 3px 0 var(--edge-ink); }

@media (max-width: 640px) {
  .print-main { grid-template-columns: 1fr; }
  .print-palette { grid-template-columns: repeat(9, minmax(0, 1fr)); }
}
@media (max-width: 420px) {
  dialog.sheet:is(.print-sheet, .print-picker) { width: calc(100vw - 12px); max-height: calc(100dvh - 12px); padding: var(--sp-3); border-radius: var(--r-lg); }
  .print-palette { gap: 4px; padding: 2px; }
  .print-palette > [role='option'] { min-width: 0; min-height: 0; }
  .print-actions > button { flex: 1 1 auto; }
  .print-empty-hint { margin-left: 0; width: 100%; text-align: center; }
  .print-tiles { grid-template-columns: 1fr; gap: var(--sp-2); }
  .print-tile { grid-template-columns: 56px minmax(0, 1fr) auto; padding: 8px; }
  .print-tile-sw { width: 56px; height: 56px; }
  .print-tile-actions { grid-column: 3; grid-row: 1; flex-direction: column; align-items: stretch; gap: 4px; }
}
.print-list-box a, .look-print-signin a, .print-guest a { color: var(--ink); font-weight: 700; }
