/* boardgame.plus: Tonight's Feature, the game-night play area (plan docs/plans/active/2026-10-10-tonights-feature.md;
   contract docs/SCREEN-CONTRACT.md). Ported from the approved mock (tools/mocks/tonights-feature/). The game you land on
   fills the screen with its own art, its colours light the room, the lineup sits along the bottom.
   - The TV scale is --u (1/192 of the width or 1/108 of the height, whichever is smaller): 10px on a 1920x1080 TV,
     5px on a TV browser's 960x540. The root font size stays the browser's, so account.css (rem) keeps its look.
   - Stacked (phones, portrait tablets, short landscape): the same media query as STACK in games.mjs. --u is 10px there
     and the page scrolls vertically; everywhere else it is one window.
   - The room colours (--g1 main, --tint room, --on text on --g1) are set on <html> by night.js from
     games.mjs once a walk along the lineup settles, and blend over 0.9 s. King Fu's are the defaults (it opens the lineup, Kyle 2026-10-16). */
/* the two fonts are declared once, in account.css (which this page loads first): a second declaration fetched Archivo twice */

@property --g1{syntax:"<color>";inherits:true;initial-value:#ffd23f}
@property --tint{syntax:"<color>";inherits:true;initial-value:#220705}
@property --on{syntax:"<color>";inherits:true;initial-value:#111111}

:root{--u:min(calc(100vw / 192),calc(100vh / 108));--glide:cubic-bezier(.2,.9,.25,1.08);
  /* the 10-foot focus: an ink gap and a paper band at least 0.4% of the screen height (3px minimum), plus a lift */
  --gap:calc(.5 * var(--u));--ring:max(calc(.6 * var(--u)),.4vh,3px);--lift:calc(-1.3 * var(--u));
  --focus:0 0 0 var(--gap) var(--night),0 0 0 calc(var(--gap) + var(--ring)) var(--paper),0 0 calc(4 * var(--u)) var(--u) color-mix(in srgb,var(--g1) 55%,transparent);
  /* the sign-in card hangs under this header (account.css reads --vb and --hem) */
  --vb:calc(11.4 * var(--u));--hem:0px;
  transition:--g1 .9s ease,--tint .9s ease,--on .9s ease}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;overflow-x:clip}
body{margin:0;height:100svh;overflow:hidden;background:var(--tint);color:var(--paper);font:400 calc(2.4 * var(--u))/1.45 var(--body);-webkit-font-smoothing:antialiased}
h1,h2,h3,p,figure,ul,fieldset{margin:0}
ul{list-style:none;padding:0}
img,video{display:block}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;cursor:pointer}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
.sprite{position:absolute;width:0;height:0;overflow:hidden}
[hidden]{display:none!important}
:focus-visible{outline:var(--ring) solid var(--paper);outline-offset:var(--gap)}
svg.i{width:1em;height:1em;flex:none}

/* ---------- the scene: the game's own art, edge to edge; only the featured one drifts ---------- */
.scenes{position:fixed;inset:0;z-index:0;overflow:hidden;background:var(--tint)}
.scene{position:absolute;inset:0;opacity:0;visibility:hidden;transform:scale(1.05);transition:opacity 1.1s ease,transform 1.8s var(--glide),visibility 0s linear 1.1s}
.scene.on{opacity:1;visibility:visible;transform:none;transition:opacity 1.1s ease,transform 1.8s var(--glide),visibility 0s}
.art{position:absolute;inset:-2%}
.scene.on .art,.scene.out .art{animation:drift 32s ease-in-out infinite alternate}
.scene.on .art{will-change:transform}
.art img{position:relative;width:100%;height:100%;object-fit:cover}
/* the hero's blurred preview (tools/night-previews.mjs), there from the first paint; the art fades in over it */
.art::before{content:"";position:absolute;inset:0;background:var(--pv) 50% 50%/cover;filter:blur(calc(3 * var(--u)));transform:scale(1.15)}
/* framing: since the art pass (plan 2026-10-17-home-art-pass) every hero is a 16:9 picture drawn for this page, its subject
   along the top-right and the right edge, so laptops and TVs show it whole; the drift leans toward the subject */
.scene[data-for]{--kx:-1.5%;--ky:1%}
@keyframes drift{from{transform:scale(1.03) translate3d(0,0,0)}to{transform:scale(1.13) translate3d(var(--kx,-2%),var(--ky,-1%),0)}}
/* CRUZ's hero is the game's own city postcards (Kyle 2026-10-19): one seamless 6 x 5 grid of all 30
   (tools/night/make-cruz-wall.sh) repeated edge to edge over a tilted layer that sails diagonally by exactly one grid
   and loops, on phones too (Kyle: "across surfaces"). The grid loads only while CRUZ is featured; until it arrives the
   still copy (the img) shows, so the img asks only for its small copy (sizes="20vw"; Queen's does the same).
   --ta is the grid's width over its height, --tw its width on screen (the still is cut at the same scale). */
.tiles{--tilt:-8deg;--pc:1;--tw0:140vh;--tw0:140dvh;--tw:calc(var(--pc) * var(--tw0));--ta:1.6393;
  --cos:cos(var(--tilt));--sin:max(sin(var(--tilt)), -1 * sin(var(--tilt)));
  position:absolute;top:50%;left:50%;translate:-50% -50%;rotate:var(--tilt);overflow:hidden;
  /* sized from the tilt so the turned layer covers the screen's corners at any angle the tuner offers */
  width:calc(100vw * var(--cos) + 100vh * var(--sin) + 4vmax);height:calc(100vw * var(--sin) + 100vh * var(--cos) + 4vmax)}
.tiles i{--th:calc(var(--tw) / var(--ta));position:absolute;inset:calc(-1 * var(--th)) 0 0 calc(-1 * var(--tw));animation:sail 160s linear infinite}
.scene.on .tiles i,.scene.out .tiles i{background:url(/assets/night/cruz-tiles.webp) 0 0/var(--tw) var(--th) repeat}
@keyframes sail{to{transform:translate(var(--tw),var(--th))}}

.shade{position:fixed;inset:0;z-index:1;pointer-events:none;background:
  linear-gradient(90deg,color-mix(in srgb,var(--tint) 94%,transparent) 0%,color-mix(in srgb,var(--tint) 80%,transparent) 28%,color-mix(in srgb,var(--tint) 34%,transparent) 48%,transparent 62%),
  linear-gradient(0deg,color-mix(in srgb,var(--tint) 97%,transparent) 0%,color-mix(in srgb,var(--tint) 78%,transparent) 21%,transparent 44%),
  linear-gradient(180deg,color-mix(in srgb,var(--tint) 72%,transparent) 0%,transparent 17%)}
/* bias light: the screen's edges glow in the game's colour (gradients, not a blurred shadow, so a re-light is cheap) */
.glow{position:fixed;inset:0;z-index:8;pointer-events:none;opacity:.5;background:
  linear-gradient(90deg,var(--g1),transparent 7%,transparent 93%,var(--g1)),linear-gradient(0deg,var(--g1),transparent 9%,transparent 91%,var(--g1));mix-blend-mode:soft-light}

/* ---------- the room: one grid, so the hero, the clip and the lineup can never overlap ---------- */
.room{position:fixed;inset:0;z-index:4;display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-rows:auto minmax(0,1fr) auto auto;
  column-gap:calc(6 * var(--u));padding:0 calc(9.6 * var(--u)) calc(1.4 * var(--u));transition:opacity .5s ease}
/* the rules of boardgame.plus, as on every page (House Words, Kyle 2026-10-15): the room's last row, couch-readable */
.legal{grid-column:1/-1;grid-row:4;justify-self:center;display:flex;flex-wrap:wrap;justify-content:center;gap:calc(.6 * var(--u)) calc(2.4 * var(--u));
  position:relative;isolation:isolate;margin-top:var(--u);padding-top:calc(1.4 * var(--u));font:500 calc(2.4 * var(--u))/1.1 var(--body);color:rgba(244,236,225,.82)}
/* its dark bar runs the width of the window, down to the bottom edge (Kyle 2026-10-16: "a little space and maybe a black
   or faded bar"; room.css draws the same bar on every other page) */
.legal::before{content:"";position:absolute;z-index:-1;top:0;bottom:calc(-1.4 * var(--u));left:calc(50% - 50vw);right:calc(50% - 50vw);
  border-top:1px solid rgba(244,236,225,.1);background:linear-gradient(180deg,rgba(0,0,0,.42),rgba(0,0,0,.64))}
.legal a{color:inherit;text-decoration:underline;text-decoration-color:rgba(244,236,225,.4);text-underline-offset:.2em}
.legal a:hover,.legal a:focus-visible{color:var(--paper)}

/* ---------- top bar ---------- */
.top{grid-column:1/-1}
.vin{height:var(--vb);display:flex;align-items:center;gap:calc(1.6 * var(--u))}
.brand{display:block;flex:none}
.brand img{width:auto;height:calc(8.4 * var(--u));filter:drop-shadow(0 calc(.3 * var(--u)) calc(.6 * var(--u)) rgba(0,0,0,.5))}
.gap{flex:1}
/* Join and Sign in: the one button set (account.css, redesign plan 2026-10-14) sized in --u for the TV; Join is the bar's
   one highlighted control (.primary, in the featured game's colours) */
.top .btn,.jp .btn{--btn-h:max(calc(6.6 * var(--u)),44px);--btn-px:calc(2.4 * var(--u));--btn-f:calc(2.4 * var(--u));--btn-r:calc(.5 * var(--u));--btn-b:max(calc(.25 * var(--u)),2px);
  gap:calc(1.2 * var(--u));transition:transform .35s var(--spring),box-shadow .25s,background .25s}

.join svg{font-size:calc(2.8 * var(--u))}
/* Join a game's snake (Kyle 2026-10-19: "needs a snake stroke or pulse something that catches your eye"): a light that
   runs round its border; reduced motion holds it still, and gone */
@property --snake{syntax:'<angle>';inherits:false;initial-value:0deg}
.join::after{content:"";position:absolute;inset:calc(-1 * var(--btn-b));border-radius:inherit;padding:var(--btn-b);pointer-events:none;
  background:conic-gradient(from var(--snake),transparent 0 62%,var(--paper) 82%,#fff 88%,transparent 96%);
  -webkit-mask:linear-gradient(#000 0 0) content-box exclude,linear-gradient(#000 0 0);mask:linear-gradient(#000 0 0) content-box exclude,linear-gradient(#000 0 0);
  animation:snake 2.6s linear infinite}
@keyframes snake{to{--snake:360deg}}
html.still .join::after{animation:none;opacity:0}
.slots{display:flex;gap:calc(.45 * var(--u));margin-left:calc(.4 * var(--u))}
.slots i{display:block;width:calc(2.3 * var(--u));height:calc(2.9 * var(--u));border:max(calc(.2 * var(--u)),1px) solid currentColor;border-radius:calc(.3 * var(--u));opacity:.7}
.top .who{max-width:none}

.top .who svg{width:calc(2.6 * var(--u));height:calc(1.9 * var(--u))}



/* ---------- the hero copy: one block per game, stacked; the featured one fades up ---------- */
.hero{grid-column:1;grid-row:2;align-self:start;display:grid;width:min(calc(64 * var(--u)),100%);padding-top:calc(1.6 * var(--u))}
.copy{grid-area:1/1;display:flex;flex-direction:column;align-items:flex-start;min-width:0}
.copy:not(.on){pointer-events:none;visibility:hidden}
.copy>*{opacity:0;transform:translate3d(0,calc(1.8 * var(--u)),0);transition:opacity .3s ease,transform .4s ease}
.copy.on>*{opacity:1;transform:none;transition:opacity .6s ease,transform .85s var(--glide)}
.copy.on>:nth-child(1){transition-delay:.22s}.copy.on>:nth-child(2){transition-delay:.3s}.copy.on>:nth-child(3){transition-delay:.4s}
.copy.on>:nth-child(4){transition-delay:.48s}.copy.on>:nth-child(5){transition-delay:.56s}.copy.on>:nth-child(6){transition-delay:.64s}
.logo{margin-top:calc(1.6 * var(--u));display:flex;align-items:flex-end;transform-origin:left bottom}
.logo img{width:auto;height:auto;max-height:calc(19 * var(--u));max-width:min(calc(66 * var(--u)),100%);object-fit:contain;filter:drop-shadow(0 calc(.8 * var(--u)) calc(1.8 * var(--u)) rgba(0,0,0,.55))}
.logo img.crest{max-height:calc(26 * var(--u))}
/* Kyle 2026-10-10: "golden arrow and dogfight logos need to be bigger" */
.copy[data-for=dogfight] .logo img{max-height:calc(27 * var(--u))}
.facts{display:flex;flex-wrap:wrap;gap:var(--u);margin-top:calc(2.4 * var(--u))}
.facts li{font:700 calc(2.4 * var(--u))/1 var(--display);font-stretch:104%;padding:calc(1.1 * var(--u)) calc(1.6 * var(--u));border-radius:calc(.6 * var(--u));color:var(--paper);
  background:color-mix(in srgb,var(--tint) 74%,transparent);border:max(calc(.2 * var(--u)),1px) solid color-mix(in srgb,var(--g1) 70%,transparent)}
.line{margin-top:calc(2 * var(--u));max-width:calc(60 * var(--u));font:500 calc(2.8 * var(--u))/1.4 var(--body);color:#fff8ee;text-wrap:pretty;text-shadow:0 calc(.2 * var(--u)) var(--u) rgba(0,0,0,.75)}
.acts{display:flex;align-items:center;gap:calc(1.6 * var(--u));margin-top:calc(2.4 * var(--u));padding-bottom:calc(2.4 * var(--u))}
.play{--btn-h:max(calc(8 * var(--u)),44px);--btn-px:calc(4.2 * var(--u));--btn-f:calc(3.4 * var(--u));--btn-r:calc(.6 * var(--u));--btn-b:max(calc(.25 * var(--u)),2px);
  gap:calc(1.4 * var(--u));box-shadow:0 calc(1.6 * var(--u)) calc(3 * var(--u)) rgba(0,0,0,.45);transition:transform .35s var(--spring),box-shadow .25s}
.play svg{font-size:calc(2.8 * var(--u))}
/* Try it (King Fu repo plan 2026-10-22-selling-demo): the quieter choice after Play, the same set's outline button,
   shorter and smaller; the border, radius and font stay Play's (page-check match) */
.try{--btn-h:max(calc(6.6 * var(--u)),44px);--btn-px:calc(3 * var(--u));--btn-f:calc(2.6 * var(--u));--btn-r:calc(.6 * var(--u));--btn-b:max(calc(.25 * var(--u)),2px);
  transition:transform .35s var(--spring),box-shadow .25s}



/* the remote's focus: readable from the couch (keyboard mode is html.kb, set at the first arrow key) */
:is(.play,.top .btn,.jp .btn):focus-visible,html.kb :is(.play,.top .btn,.jp .btn):focus{outline:none;transform:translateY(var(--lift)) scale(1.05);box-shadow:var(--focus)}
.try:focus-visible,html.kb .try:focus{outline:none;transform:translateY(calc(var(--lift) / 2));box-shadow:var(--focus)}

/* ---------- the gameplay window: rolls in once you settle on a game ---------- */
.clipbox{grid-column:2;grid-row:2;align-self:start;width:calc(102 * var(--u));padding-top:calc(1.6 * var(--u))}
.clip{opacity:0;visibility:hidden;transform:translate3d(calc(7 * var(--u)),0,0) scale(.97);transition:opacity .35s ease,transform .5s ease,visibility 0s linear .5s}
.clip.show{opacity:1;visibility:visible;transform:none;transition:opacity .7s ease,transform 1s var(--glide),visibility 0s}
.screen{padding:calc(.8 * var(--u));border-radius:calc(1.2 * var(--u));background:var(--ink);box-shadow:0 0 0 calc(.3 * var(--u)) color-mix(in srgb,var(--g1) 85%,transparent),0 calc(3 * var(--u)) calc(6 * var(--u)) rgba(0,0,0,.55)}
.screen video{width:100%;aspect-ratio:16/9;object-fit:cover;border-radius:calc(.6 * var(--u));background:var(--ph-clip,#000) var(--pv-clip,none) 50% 50%/cover no-repeat;
  clip-path:inset(0 round calc(.6 * var(--u)));transition:filter .4s ease}
/* until its poster has arrived the clip window shows that poster tiny and blurred (night.css previews block), then the
   blur eases off it like a focus pull (a flat colour read as a pink slab for seconds on a slow line, soft-load plan) */
html.js .screen video:not([poster]){filter:blur(calc(1.4 * var(--u)))}
html.still .screen video{transition:none}
.clip.wide .screen video{aspect-ratio:2/1}
.clip{position:relative}
.screen{position:relative;z-index:1}
/* King Fu's hand of five, fanned over the clip's bottom-left corner (Kyle 2026-10-17: "card can stay as decorations on
   bottom left or around the video"; 2026-10-19: "put cards above on top layer and give a hand of 5") */
.kf{position:absolute;z-index:2;left:calc(-10 * var(--u));bottom:calc(1.5 * var(--u));display:flex;align-items:flex-end;pointer-events:none}
.kf img{width:calc(8.4 * var(--u));height:auto;aspect-ratio:2/3;object-fit:cover;border-radius:calc(.7 * var(--u));box-shadow:0 0 0 calc(.3 * var(--u)) #111,0 calc(1.6 * var(--u)) calc(3 * var(--u)) rgba(0,0,0,.5);animation:bob 4.6s ease-in-out infinite alternate}
.kf img+img{margin-left:calc(-5.4 * var(--u))}
.kf img:nth-child(1){rotate:-18deg;--y0:calc(.8 * var(--u))}
.kf img:nth-child(2){rotate:-9deg;--y0:calc(-.6 * var(--u));animation-delay:-.9s}
.kf img:nth-child(3){rotate:0deg;--y0:calc(-1.2 * var(--u));animation-delay:-1.8s}
.kf img:nth-child(4){rotate:9deg;--y0:calc(-.6 * var(--u));animation-delay:-2.7s}
.kf img:nth-child(5){rotate:18deg;--y0:calc(.8 * var(--u));animation-delay:-3.6s}
@keyframes bob{from{transform:translate3d(0,var(--y0,0),0)}to{transform:translate3d(0,calc(var(--y0,0px) - 1.8 * var(--u)),0)}}

/* ---------- the lineup ---------- */
.lineup{grid-column:1/-1;grid-row:3;position:relative;isolation:isolate;width:100%;max-width:calc(172 * var(--u));justify-self:center}
.lhead{display:flex;align-items:baseline;justify-content:space-between;gap:calc(2 * var(--u));margin-bottom:calc(5 * var(--u))}
.lhead h2{font:800 calc(2.6 * var(--u))/1.2 var(--display);font-stretch:108%;color:var(--paper)}
.hint{font:500 calc(2.4 * var(--u))/1.2 var(--body);color:rgba(244,236,225,.82)}
.lineup ul{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:calc(2.4 * var(--u))}
.lineup::after{content:"";position:absolute;left:calc(-2 * var(--u));right:calc(-2 * var(--u));bottom:calc(-2 * var(--u));height:max(calc(.3 * var(--u)),1px);z-index:-2;
  background:linear-gradient(90deg,transparent,var(--brass) 18%,var(--brass) 82%,transparent);opacity:.55}
.gm{display:block;width:100%;padding:0;border:0;background:none;text-align:left;transform-origin:50% 100%;transition:transform .55s var(--spring)}
.thumb{position:relative;display:block;aspect-ratio:16/9;border-radius:calc(.9 * var(--u));overflow:hidden;background:color-mix(in srgb,var(--ph,#000) 72%,#000);border:max(calc(.3 * var(--u)),2px) solid rgba(244,236,225,.24);
  box-shadow:0 calc(1.2 * var(--u)) calc(2.4 * var(--u)) rgba(0,0,0,.45);transition:box-shadow .3s,border-color .3s}
.thumb img{width:100%;height:100%;object-fit:cover;filter:saturate(.7) brightness(.72);transition:filter .45s,transform 1.2s var(--glide)}
.badge{position:absolute;left:var(--u);top:var(--u);padding:calc(.5 * var(--u)) calc(.9 * var(--u));border-radius:calc(.4 * var(--u));background:#ffd23f;color:#111;font:700 calc(2.4 * var(--u))/1 var(--body)}
.nm{display:block;margin-top:calc(1.3 * var(--u));font:700 calc(2.4 * var(--u))/1.2 var(--display);font-stretch:104%;color:rgba(244,236,225,.82);transition:color .3s}
.gm:hover .thumb img{filter:saturate(.9) brightness(.9)}
.gm.sel{transform:translateY(calc(-1.2 * var(--u)))}
.gm.sel .thumb{border-color:var(--g1);background:var(--ph,#000)} /* a card waits in its own picture's colour, dimmed like the picture */
.gm.sel .thumb img{filter:none}
.gm.sel .nm{color:var(--paper)}
.gm:focus{outline:none}
.gm:focus-visible,html.kb .gm:focus{transform:translateY(calc(-2.4 * var(--u))) scale(1.07)}
.gm:focus-visible .thumb,html.kb .gm:focus .thumb{border-color:var(--paper);box-shadow:var(--focus)}
.gm:focus-visible .thumb img,html.kb .gm:focus .thumb img{filter:none;transform:scale(1.06)}
.gm:focus-visible .nm,html.kb .gm:focus .nm{color:var(--paper)}
.spot{position:absolute;left:0;bottom:calc(-4.2 * var(--u));width:100px;height:calc(8 * var(--u));z-index:-1;border-radius:50%;pointer-events:none;transform-origin:0 50%;
  background:radial-gradient(closest-side,color-mix(in srgb,var(--g1) 75%,transparent),transparent);filter:blur(calc(1.2 * var(--u)));
  transform:translateX(var(--sx,0)) scaleX(var(--sk,0));transition:transform .65s var(--spring)}

/* ---------- join a game (a native dialog: the page behind is inert, Escape closes it) ---------- */
dialog.jd{width:min(calc(80 * var(--u)),calc(100vw - 32px));max-width:none;max-height:calc(100svh - 32px);margin:auto;padding:0;border:0;background:none;color:var(--paper);overflow:visible}
dialog.jd::backdrop{background:color-mix(in srgb,var(--night) 80%,transparent)}
.jp{padding:calc(4.4 * var(--u)) calc(5.2 * var(--u)) calc(4 * var(--u));border-radius:calc(.6 * var(--u));background:var(--night-2);border:max(calc(.3 * var(--u)),2px) solid var(--hair);
  border-top:calc(.9 * var(--u)) solid var(--g1);box-shadow:0 calc(4 * var(--u)) calc(8 * var(--u)) rgba(0,0,0,.6)}
html:not(.still) dialog.jd[open] .jp{animation:rise .45s var(--spring)}
.jp h2{font:800 calc(5.6 * var(--u))/1 var(--display);font-stretch:80%}
.jp>p{margin-top:var(--u);color:var(--muted);font-size:calc(2.6 * var(--u))}
.jp .jhint{margin-top:calc(.6 * var(--u));font-size:calc(2.2 * var(--u))}







.jc{position:relative;margin:calc(3 * var(--u)) 0 calc(3.4 * var(--u))}
.jc input{position:absolute;inset:0;width:100%;height:100%;padding:0;border:0;background:transparent;color:transparent;caret-color:transparent;font-size:16px;opacity:.01}
.jcells{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:calc(1.6 * var(--u));pointer-events:none}
.jcells i{display:grid;place-items:center;height:calc(17 * var(--u));min-height:72px;border-radius:calc(.5 * var(--u));border:max(calc(.3 * var(--u)),2px) solid color-mix(in srgb,var(--paper) 34%,transparent);background:var(--night);color:var(--paper);
  font:900 calc(9.4 * var(--u))/1 var(--display);font-style:normal;font-stretch:112%;transition:border-color .2s,box-shadow .2s,transform .3s var(--spring)}
.jcells i.full{border-color:var(--g1)}
.jc:focus-within .jcells i.at{border-color:var(--paper);box-shadow:0 0 0 calc(.7 * var(--u)) color-mix(in srgb,var(--g1) 75%,transparent);transform:translateY(calc(-.4 * var(--u)))}
.jrow{display:flex;gap:calc(1.6 * var(--u));flex-wrap:wrap}




/* the featured game's tables are joined inside it (King Fu): no code to type, the panel says so */
.jmsg{min-height:calc(3.2 * var(--u));margin-top:calc(2.4 * var(--u));font-weight:600;color:var(--paper)}

.toast{position:fixed;z-index:16;font-size:calc(2.4 * var(--u));top:calc(12 * var(--u));right:calc(9.6 * var(--u));max-width:calc(56 * var(--u));padding:calc(1.8 * var(--u)) calc(2.4 * var(--u));border-radius:calc(.5 * var(--u));background:var(--night-2);
  border-left:calc(.7 * var(--u)) solid var(--g1);box-shadow:0 calc(2 * var(--u)) calc(4 * var(--u)) rgba(0,0,0,.5);font-weight:600;opacity:0;transform:translate3d(0,calc(-1.4 * var(--u)),0);
  transition:opacity .3s,transform .45s var(--spring);pointer-events:none}
.toast.show{opacity:1;transform:none}
@keyframes rise{from{opacity:0;transform:translate3d(0,calc(2 * var(--u)),0)}to{opacity:1;transform:none}}


/* ---------- Kyle's tune (2026-10-17, tools/night/saves/home-2026-10-17.json): laptops and TVs only ----------
   Read as intent, not distances (plan 2026-10-17-home-art-pass): every move lined a piece up with the lineup's edges,
   so the room gets ONE edge, shared by the header, the hero, the clip and the lineup; Join a game sits beside the
   wordmark; the featured logo is centred over its words; the lineup rises. "Tonight's feature", the lineup heading and
   its hint go (the heading stays for screen readers). Where the tune asked for text under the couch floor (2.4u: the
   line, the footer, the header buttons' labels), the floor stays and the box around it shrinks instead. */
@media (min-aspect-ratio: 5001/4000) and (min-height: 501px) and (min-width: 761px){
  .room{--edge:max(calc(9.6 * var(--u)),calc((100vw - 172 * var(--u)) / 2));padding-left:var(--edge);padding-right:var(--edge)}
  .vin{margin-top:calc(2.8 * var(--u))}
  .gap{order:1}.top .who{order:2}
  .join{margin-left:calc(2.2 * var(--u))} /* Kyle 2026-10-19: closer to the wordmark */
  .top .btn{--btn-h:max(calc(5.4 * var(--u)),44px);--btn-px:calc(1.9 * var(--u))}
  .top .who{--btn-f:calc(1.9 * var(--u))} /* Kyle 2026-10-19: the account button's name smaller */
  /* Kyle 2026-10-19 (tools/night/saves/home-2026-10-19.json): every game's words left-aligned, in the order logo,
     line, tags, Play; the tags at four-fifths size */
  .logo{align-self:flex-start;margin-top:calc(4.5 * var(--u))}
  .line{order:1;margin-top:calc(3 * var(--u));font-size:calc(2.4 * var(--u))}
  .facts{order:2;margin-top:calc(1.8 * var(--u));gap:calc(.8 * var(--u))}
  .facts li{font-size:calc(1.92 * var(--u));padding:calc(.88 * var(--u)) calc(1.28 * var(--u))}
  .acts{order:3}
  .clipbox{width:calc(93 * var(--u));padding-top:calc(3.1 * var(--u))} /* the clip at ~91%, its right edge on the room's */
  .legal{font-size:calc(1.55 * var(--u))} /* Kyle 2026-10-19: "bottom footer way smaller" */
  /* the two tall logos (Kyle 2026-10-10: bigger) leave no room for the tune's extra gap: Play's ring would touch the lineup */
  .copy:is([data-for=dogfight],[data-for=arrow]) .line{margin-top:calc(2 * var(--u))}
  .acts{margin-top:calc(2 * var(--u))}
  .copy[data-for=kingfu] .logo img{max-height:calc(23.6 * var(--u))}
  .lineup .lhead{display:contents}.lineup .hint{display:none}
  .lineup{margin-bottom:calc(7.2 * var(--u))} /* Kyle 2026-10-19: the lineup a little lower */
}

/* ---------- stacked: phones, portrait tablets, short landscape (STACK in games.mjs) ---------- */
@media (max-aspect-ratio: 5/4), (max-height: 500px), (max-width: 760px){
  :root{--u:10px;--band:min(125vw,60svh);--vb:64px}
  body{height:auto;min-height:100svh;overflow:visible;font-size:1.7rem}
  .scenes,.shade,.glow{position:absolute;height:var(--band)}
  .scene .art img{object-position:84% 30%}.art::before{background-position:84% 30%} /* a phone's band shows the subject (top-right), not the calm middle */
  .tiles{--tw0:calc(1.4 * var(--band))} /* CRUZ's postcards at the still copy's scale in the phone's art band */
  .shade{background:linear-gradient(0deg,var(--tint) 0%,color-mix(in srgb,var(--tint) 82%,transparent) 26%,color-mix(in srgb,var(--tint) 30%,transparent) 55%,transparent 72%),
    linear-gradient(180deg,color-mix(in srgb,var(--tint) 80%,transparent) 0%,transparent 26%)}
  .room{position:relative;display:flex;flex-direction:column;padding:0;transition-duration:.35s}
  .top{order:-2}.clipbox{order:-1} /* Kyle 2026-10-18: on a phone the clip leads, right under the header */
  .vin{height:auto;min-height:64px;padding:12px max(12px,env(safe-area-inset-right)) 0 max(12px,env(safe-area-inset-left));gap:8px}
  .brand img{height:auto;width:186px}
  .top .btn{--btn-h:44px;--btn-px:12px;--btn-f:15px;--btn-r:4px;--btn-b:2px;gap:8px}
  .join svg,.slots{display:none}
  /* only the shown game holds space (the tallest, Golden Arrow's crest, left a gap under the rest); picking a game
     scrolls to the top, so the lineup moving below is never seen */
  .hero{position:relative;width:auto;padding:22px 20px 0}.copy:not(.on){position:absolute;top:22px;left:20px;right:20px}
  .logo{margin-top:0}
  /* the width the logo will load at (its sizes: 80vw on a phone, 40vw wider), stated up front, so the box has its final
     height from the first paint; width:auto left it 0 tall until the first bytes arrived, then jumped 120px */
  .logo img{width:var(--logo-w,40vw);max-height:120px;max-width:100%;object-position:left bottom} /* never min(..,100%): the wrapper shrinks to fit, so that 100% is circular and resolves to 0 */
  .logo img.crest{max-height:200px}
  .copy[data-for=dogfight] .logo img{max-height:160px}
  .facts{margin-top:14px}
  .facts li{font-size:14.5px;padding:9px 11px}
  .line{margin-top:14px;font-size:17px}
  .acts{margin-top:18px;width:100%;padding-bottom:4px}
  .play{flex:1;height:56px;justify-content:center;font-size:22px;padding:0 20px}
  .acts{gap:10px}.try{height:48px;font-size:18px;padding:0 18px}
  .clipbox{width:auto;margin:10px 20px 0;padding:0;align-self:stretch} /* the column's width from the first paint, not the video's (the TV rule's start sized it to whatever had loaded) */
  .clip{transform:none}
  .kf{display:none} /* Kyle 2026-10-17: on a phone the clip stands alone (a sliver of cards read as clutter) */
  .lineup{max-width:none;margin:30px 0 0;padding:0 20px 28px}
  .legal{margin:8px 0 0;padding:18px 20px 32px;font-size:15px;gap:6px 18px}
  .legal::before{left:0;right:0;bottom:0}
  .lineup .lhead{display:contents}
  .hint,.spot,.lineup::after{display:none}
  .lineup ul{grid-template-columns:1fr 1fr;gap:20px 14px}
  .gm.sel{transform:none}
  .gm:focus-visible,html.kb .gm:focus{transform:translateY(-4px)}
  .nm{font-size:16px;margin-top:8px}
  .badge{font-size:12px;left:6px;top:6px}
  .jp{padding:28px 20px 24px}.jp h2{font-size:32px}
  .jgames legend,.jopts label{font-size:15px}
  .jcells{gap:8px}.jcells i{height:72px;font-size:36px}
  .jgo,.jback{flex:1;height:56px;padding:0 20px;font-size:21px}
  .toast{top:auto;bottom:16px;left:16px;right:16px;max-width:none;font-size:15px}
  /* a short phone (iPhone SE, 667 tall) still shows Play on its first screen now the clip leads */
  @media (max-height:700px){
    .hero{padding-top:14px}.copy:not(.on){top:14px}
    .logo img{max-height:84px}.logo img.crest{max-height:112px}.copy[data-for=dogfight] .logo img{max-height:104px}
    .facts{margin-top:10px}.line{margin-top:10px}.acts{margin-top:14px}
  }
}
@media (max-width:760px){.logo img{--logo-w:80vw}} /* the logos' sizes on a phone (index.html) */
@media (max-width:420px){.top .who .wt{display:none}html.signed .top .who .wt{display:inline}.jw{display:none}
  /* a player's name arrives after the page (the service answers late on a slow line): the button eases open and Join
     glides over, instead of jumping 51px (soft-load plan) */
  .top .who{max-width:44px;overflow:hidden;white-space:nowrap;transition:max-width .45s var(--glide),transform .35s var(--spring),box-shadow .25s,background .25s}html.signed .top .who{max-width:60vw}
  html.still .top .who{transition:none}}

/* no JS: the first game stands, the lineup links go straight to each game, nothing waits on a script */
html:not(.js) .clipbox{display:none}

/* the composed reveal (soft-load plan, release 2): the room's words, clip and lineup wait together and fade in as one
   once the fonts and the logo are in (night.js, capped ~1.2 s), over the art's blurred preview, which never waits.
   Once per visit (the pre-paint script). Never under reduced motion. A CSS net shows the room at 2.5 s if night.js
   never runs: forwards only and no from-keyframe, so a room already shown never blinks */
html.js:not(.ready):not(.still) .room{opacity:0;pointer-events:none;animation:roomnet 0s 2.5s forwards}
html.js:not(.ready):not(.still) .room *{transition:none!important}
@keyframes roomnet{to{opacity:1;pointer-events:auto}}
/* soft entrances (plan 2026-10-19-soft-load): a picture (img.fade) shows once it has fully arrived, never painting in
   stripes; site.js marks it .in (.now: already there, or the net beat it, so no fade). JS only, and a 4 s net in case
   site.js never runs: an animation, not a transition, so the lineup's own filter and zoom transitions stay */
html.js img.fade:not(.in){opacity:0;animation:fadenet 0s 4s forwards}
html.js img.fade.in:not(.now){animation:fadein .3s ease both}
html.js .art img.fade.in:not(.now){animation-duration:.6s}
html.js .art img.fade:not(.in){animation-delay:12s} /* the hero waits over its preview: 902 KB takes ~5.5 s on a slow line */
@keyframes fadein{from{opacity:0}}
/* Join and Sign in arrive together when the scripts run (account.js adds Sign in, so Join waiting keeps it from jumping
   when Sign in lands): they fade in as one */
.top .join:not([hidden]),.top .who{animation:fadein .3s ease both}
@keyframes fadenet{to{opacity:1}}
/* previews:start (tools/night-previews.mjs writes this block; never edit it by hand) */
.scene[data-for=kingfu]{--pv:url(data:image/webp;base64,UklGRsABAABXRUJQVlA4ILQBAAAwCQCdASogABIAPm0ylUekIqIhKAgAgA2JbACdMoR495fwg+QG2A52nTZt5a/ZX0bkUem2Pjc+l/YDQv/SbczGlxELV4z8EEAaVQ3qnfrgyOjgAP7/LuaHdaLBxhEAaSDNH8RN7anX3PZmuGLwwwi1u/eA77acH05XOM5fzKmn2v/JciXJMgmIgipOS0sDRilsHINE92Bcrz/hGfseM3bC3uvznIBsCjwJd4P5saXnRmfbfN+HquypIwfeBxLDoiq62D8MQgwt9R+g+nTwygJxDWyZBzeVfiV0GV0jy6tqp8TAxPvzjlVF5jTHGIKcDzO3aSioLlSJLMLydHRV/8H+8h2QuPNdmFSY3n8YiRwT2IHsf1dL7lLsGPH6aC3YexUmAsBssOZpK48Js/OS5IHdX0TcdOnVD/kOftQX2t+9MQ5Jz9/fvh0acQHSjBC6kkEihDOb9NFV4p6gfIaCstPJyX1ofnzDRM6I9WeJFRA8IUEuoUjPjXZq6MESg8avUBlrBQOx6Qbz4Qg/0TtFiZXSeMDxj67SA/BsQMr5KjiFOYKyAZ5gfFYYhwwRRYJ/nabYQAAA)}
.gm[data-id=kingfu] .thumb{--ph:#584238}
html[data-game=kingfu]{--ph-clip:#aa6756;--pv-clip:url(data:image/webp;base64,UklGRhYCAABXRUJQVlA4IAoCAADwCgCdASogABIAPm0qkUWkIqGYBABABsS2AE6ZQjq7xq3DtBIf/QB5YHQA5pDUQPQA/W70z/Yw8lWlmvb8fL+9Ln3zpPO/sD9HAZ0i+sHg4aXabSBIG0pqiysmDMZZbCAA/veyU0q4zMehJhS10zgEvh/7gJXkbHGyW6ur9VprfenxAZEaiyf4PS3MAxnv3qVttByork7GUxtenX9R1LvSJK8pI/sr4d9F5Lg4b5ukQ+K+AhTdqP9btnfpO9+YdZcGEQch+tmXh8Y+kt2y9+L0cQdWJHb64tJO3Hzg1vvz/8cKYjpRMs/q7pFvKVWRawXSaQUVwaY8Ufa9y51OD7lMWgltZYTOt0x83VChJJfVMhy5R6eZ4cRkjPSBjDGpzoPWexK2DvpdoKskuwzFnP2Xjw7cI8yaiam8ji5E6s2h5iPXFFI6AKAlDSD67swHUgrKmKwfufRfe3jDHn02KyGJQADcGMnuRP7zpPi4k6r9cZi36v9okrr8S4m3YDX5RNyqlw5Lao49nkL5L45vUy2gvHukagGpG+aCxOEbJ4p6fdqKprjTMkMhHHjmRYqxOK+5kWKsUIv/LWLqu/vmlH1m/mOsmhvLkORc1Vv/A4/H7IZ/krKry36vJnq2npf3ujc/wT0R3IWGKcKBXjrx//NJnmyHHpt3/5pM82Sluj/J2XGxkl584y4XAAA=)}
.scene[data-for=dogfight]{--pv:url(data:image/webp;base64,UklGRmwBAABXRUJQVlA4IGABAADQCACdASogABIAPm0ylUekIqIhKAgAgA2JbACdMoR1d41whnAJig6d/sG4AaX/1AHPi+yF+t3pK3KU2UUsyp0RlFz20XRhonP79vRl90bAAP7zM7MH/5lE7BLyUGJXqOvHwsmJXeVfmn0MoCT5v4cseVR9P06lR/8bvf4zekqpf/+0QMH5BTBxzMXhluIPF/ZyZ0gMP/rqX+d4+eWa5eXBB+rTPW+Yu7Jm4w4Ww4oqd8aiKUNMYQjqbodHWs+LAvDDvJOxum5i02gG2wNp0xdioPzb6qqhMvHVZA0nMygo2UMIVJkSMEw8VlnrnEx+su9yR4zxHct7ZUXed6RpQWmLtXVJkcLQsKfJwF+is/NZ/74knmmZuJO97U/2haLteZPVA+cHFwq0SFN2BUB72wjcARG4iVZ9//w4PQhHAPreOxWxgS39rn99INixy+EKx4tyKX5OVIdWUuRznAKwAAAA)}
.gm[data-id=dogfight] .thumb{--ph:#737c72}
html[data-game=dogfight]{--ph-clip:#83724a;--pv-clip:url(data:image/webp;base64,UklGRkwBAABXRUJQVlA4IEABAABQBgCdASogABIAPm0ukkWkIqGYBABABsS1AE6Zb1gPpLFIG86VxnQdDLuy7KJcmsvVrEtsGNNet401OAD+yYQyTKRszFczKjdmvN6UqLSxw7vnNXNpOk6cMfu/XL9yfnVdDcKoP+y3/+Kyf98qaPN4qHTbWTyHWm7aTkCVcNWbwGf8GRswJwnXIELK9Q+M8rYrPC+8H7QcB4Bdu7taEj+VyGX7jFKzq4IPDeJ7/Oqrq2rjwuMf4Zi8XwpTzfwVTqayZSJZ4v8YI/Re+waBImLjCtayRjmQcg9ITskhyLo5IKSuiJpnc1UtrdaBO0ZkzlRVifVXtAWVdz7Wx24Bdsi8oN9FX5aWJHCobfZVG3J1rC7t25YQl3u+IX+7buAFWq9Ql0AjAVmC16n3Xurv3luDFHxmoaRsJ4KdtrRuNAAAAA==)}
.scene[data-for=queen]{--pv:url(data:image/webp;base64,UklGRr4BAABXRUJQVlA4ILIBAACQCACdASogABIAPm0qkUWkIqGYBABABsS2AE6ZQj2nQRQDmh9Qz9ED9AOslfMRjFYDmr/wGsDZ0q6AGA+3C6Cpa/10hr9fNdu+XuXeOAD+6gAmWS08fm1vRclnnK4PdkGhT3PAqYBTk7+yxxbO/n8bhJbFq9XOFwBrVUdfY2713kYB4Y80cnXxtm4wHYDBpVsrvk6q6/VPuyKMZnmo52xWDueKoXOIH0p99/+DACN8xttyKUz13hnwmW14f+F3FcWP/q39VegjLaAijGdtLuFSpo0eyzyF+LyP9KlyhcmegAz7rh4Vq2gWVWuB44noI9Lh7Bpds4FX8CdbYnktjGqn3dUjeeBuTpqvFIOe5nlbEl/fYYzF0O9xh4RDN15y5L1Hb11QPJHc5maxA8OVl0FqcKwPwLr9RWKgAxNdo8VNj8ICnJKCEQEGfwPv/LcXf24+x2mT7qaJ9ZMdKlpLLChwauoVj2d5wT5ZdC5rZXCUY3aa7hJHGMPwolCbz5IsTtIWqrgreLTrHPPWmKfY2nlb/MNIDvER2XHP4T/JhTjEk2Jb4mmXK4Y+vSuShcuwAAAAAA==)}
.gm[data-id=queen] .thumb{--ph:#6b4a29}
html[data-game=queen]{--ph-clip:#684a27;--pv-clip:url(data:image/webp;base64,UklGRkQBAABXRUJQVlA4IDgBAABQBgCdASogABIAPm0skkWkIqGYBABABsS2AE6ZQjgb2vjMrVVGgrgHWoOIJhaiWnVgI7X6a3KiGU16wAD+0V8jBhLB8DnRoZn+LEvW8QD5Q2wE3p33CAveanGMKRBRZZOUzPOxRkosMjNOdCxNc4F2LfhMHUIrG/o6yYejpZIj8+8seela4Ec1jGSV2Kd7sMt7+cB0lO5tI54pdLV9yT6wUaCgM0X0yJmSPcqmOvPtqmzTafL9CAfbp8gipFniHFN2pA1zwObZjarzXFSxboinSRzxA1aQaCGDMcmyJZ31RaI6CCksLc8GePtmyo5ZYTfsrTLQjSz6x8d2YRfd3nZxd4HZAr/ITT52uwjeRDVPt6RS9hGxCOFoaJcqov63lgfcD4V9EJoZdkMitU/Zli8IGPL9gYaAAAA=)}
.scene[data-for=berlin]{--pv:url(data:image/webp;base64,UklGRigBAABXRUJQVlA4IBwBAAAwBwCdASogABIAPm0ukkakIqGhKA1QgA2JbACdMsu48IFMAfpXgAHle+xmREZhQgY6B2d/g19Q+iV75l3A95ZEIIAA/v6gHjNmQu4g6o9AVF0glnR0j/AF3OqzhPHnN/1+0uiiv+anZPl8AwrLxs96ZBjRTK2wh7YxWLPBW1JwAXXhzUS6WKcHCYkll15CC8wH8Lrqn3cMgxtiD+9oc4Owxrx03eXDr3RwXyaxC7cyRVT8oFhsL9BZPaHOMEzhmK+5CLSxFZnsd++m6axd0l0quXlc3XUDUoy4fP9Wn9ZpW1BouzM+zoxarqU8f8eGyr9/aphG2n6lhz/iZrJnnO3lzkc/Ieeu/4aPVjN4GirzlMuDHGysONqloiMAAA==)}
.gm[data-id=berlin] .thumb{--ph:#5a3f2d}
html[data-game=berlin]{--ph-clip:#8a5137;--pv-clip:url(data:image/webp;base64,UklGRhACAABXRUJQVlA4IAQCAAAQCwCdASogABIAPm0qkUWkIqGYBABABsS2AE6ZQjq7xriqnDeaBqNsBzvP9m3i/1APQA/QD0qPYi/bX0nIlrPm3AHdp7/3OpqB9GAbzGATy4Ve7qkGlhHPT83e40whMoMAAP74lcpPtdqKKqznFfVntTmCOLDqyPtWcrHJnXFPNo/T+fYb2eg3KJD+GJsFMY/Nh1cZwhDHZwRkU/ltd8UVnD4DqcQQrJR+0b1f/wDVV6ExirP95PFEqMnZagXUa9MXxT9ZX307kkDxzB1378+fzBtVUzWsVG0JbbjR4W5qd+4Kp9Sof/yY74gtXl8t8zjfwv+FpmfWMokN//c+gDkhrMPQhnXjajOAL8v/l8PZ3coQ3sz4zxy2txml3PKFkx/n+NwVoLXXP/T2zsoWoNr2tFLI50OL/f2dbe3PTw4P6aJF/afNXZjKRBakRhjUNOI+YqD9lbTKbAImHqprjzPMLM5Yzeh4ScfxpZeaLa3WJUDzr4TTsD7EWfewH78JP0k96ST3PQQpGDe7vaPqvFp8nx/9R9UKYvCIil+6UyNLIBTULq/+O3/9oYaLb/a7/iEN/qmf/rThfj/gRA2MpKEDMA8NLI42hlfnCYJvKf+Du4qufnCYJu6/+Du4qj5QoQYn6hl6t5JQg5VMIMGF9I2XKATnXrUuH00N6wGSDtMzH6DAAAA=)}
.scene[data-for=cruz]{--pv:url(data:image/webp;base64,UklGRswBAABXRUJQVlA4IMABAADQCgCdASogABIAPm0sk0akIiGhMBgIAIANiWwAnTKEgQixd3WwzgQYDy/+gBzt/+K9QHQn+oBvEn7nfsAlAZKXiA4hO+Kvo1ACXwSvDtvenjUAKK+oadZNq0xqyMD6AAD79822xVOgrL5++wcXtnAUZRR1ex0urbNm5JtxafAt29z2WFJ3dVvbOerqypg8S666XZAuHPX9xWZx53iXwKRKPjShA9+WakjshQ/YQnnc2Z76KadFQ15H1Hw47P4I5eOgBzMn/fC0ixA7fb/Fh33dm//PvgTtZfLWo67hOa0jh/KyeiBLT7aRLQJdOLIBc8JIdtlgBtpsjxFJ16uShg2IUJo64rYMt9g0MJtiKbfOxw6A6VkF9VZJEKANS9k/OEor2N1OEk1TW657xMufrNnd0NjtMi/knSbn2csgofy+YzTqjtuiVyNXwThMpR8PbMB/lqcRNpvpl1Vk/p/M8t+xMevq8enV0eOWsD1WLnqxeMH4oxAaSBqdOqOLpNgDbPNMUMw/S6G7+2vvrZoaNJQEj85INivwBLriUOQB0X075NDPuzM9qamrpCYxxbmBXkRNfFzt+i/+ShQr1aL/5AAA)}
.gm[data-id=cruz] .thumb{--ph:#695f59}
html[data-game=cruz]{--ph-clip:#665649;--pv-clip:url(data:image/webp;base64,UklGRpwBAABXRUJQVlA4IJABAABwCACdASogABIAPm0skkWkIqGYBABABsS2AE6ZQeUHMlwJD/azOozby7/u0eDJI8QGkyZ0Fa6ck3arYWFnvUpfsbhGUxdMJaYfEC2AAP7l3Dqv4RzqLwn9HOAaL4sgyjEcVqbB1IG/66ekZKNl15lqyer6hbhR8dUUvVg3lbGjF78zRQINF1mlKnzc/zYlTlejpbafv9s6sPIZQrE7CsDSmJyI5PwN7ffhIXQCsOd4/vhGZCjx1kOPBLWt2c4qnUTGUQQ94TvpEIhPQpo1H/bWOR6eJ+M6ZqDSV5Ipcf11sJ84kKsLsxZjydXWdLcl9TJVlO3mFhEgUNUzaX12QLtF3RQxzR8P+lfB7dXzo/Uc7Nc+7eACtplGG830P3prXAVT+JJwArelJkJN13hX/T/gSz9VUp3qzRtcytFY9wPORIERt+YKfSxBOGlApKPBc/jsO4lCiv7m/9SR65TGW/uPTk3+O1higu9j/XrwUp83WNQWxBZp+qDrUd22zCf8dkg37mw+uy9/jskG/c2H0AAA)}
.scene[data-for=arrow]{--pv:url(data:image/webp;base64,UklGRlYBAABXRUJQVlA4IEoBAADQBgCdASogABIAPm0wlEakIqIhKAqogA2JYgCsMoPLEtPHMsmYr6PbewYjtdF7EWt6S7BEol0+Z2u7aIcWR4AA/v2fP97wyXS7uCFRU0zZ7snEGfmpZvxZHbBjdRO+QoUc6Ti1g0cJQVnMtAAiJ+BDb7d/P/+K4tWc45CNJGgKiXlC1vzvN11SzEcJGOBKxmL5k02JdHN+xk4cp8E7icvBiD8dBHzvbM5+Vt4zz8L6wDVG+PzsMqI0WZnCdLiOUt07BqatnBK79DvNdXGq2DXn3/wyYEqwOdnmaklVjGdkODPzm54wObiFqzm2MEd3GtrTnDRMCriIMu5Hjw8DDFdKcQ++461DN2Or3PRJRNs2oY2Bsz9u3lMUxtvwNPVSFq4mxsBB/eGAET0oI9oEcsOXhzmFGRihA80LxI1xD7i6OXCkbuXCijsLAAA=)}
.gm[data-id=arrow] .thumb{--ph:#595240}
html[data-game=arrow]{--ph-clip:#5e4616;--pv-clip:url(data:image/webp;base64,UklGRjIBAABXRUJQVlA4ICYBAADwBgCdASogABIAPm0skUWkIqGYBABABsS2AE6ZQjgb0bjOXDeA9f+tOfV33lhGgBxEW8UfxQK24cYtIvlTx9mGAP74pIvv59BpDLyNLhH7J/sLG92zQbpTxgyaDVXwSnXnlHG6HOTxPE6TMQKrlwOs/TgFegnPYu3f5BOgEajU6Bf8x3SpouGXnFAQpCu7wb2C9njCjASYCdW21MO5hedHoiBs2n4GvOJr5v7NdhFucN+sRQbvuaR/vtXb89iTBJadx7nYmIbfvHpt2KPxOQ7jrbE4EKUZMaRiz2MAdrGACL8WtRfmpULVGlKcONG+DN0d5i8+OY6aJbOVqGqc6eH0Hf1mavbvjRjhqQjFXvayFW0vUKKiE0ECOX/auRVGq6shcaOAAAA=)}
.scene[data-for=soon-1]{--pv:url(data:image/webp;base64,UklGRmIBAABXRUJQVlA4IFYBAADQBwCdASogABIAPm0ukkakIqGhMBgIAIANiWwAnTKDK4p//QBvAHPefsd8I6/YGwe8xioglFZquiVr1IbYKfyZo4BnjpkDBAD+9mIQhfurn7d6si3m+QggLAAMt35j9/rdw1QGrO52lHvxAO8dcgf3NV1p5dER8aL4u76/OKNRQncuBWzey60p9J4+KaQiMaMAd90kOMzHbVZWurK8qxFzqc9siRs3vHmP1vR30fkuavEumE2HVyjS+6Q6Kj1hy2b9IpOmJrywVqnyFha8e9/JFrjWWszyWWHdeoZDzIBp/jRrHggtPeFcsmObOjmftybfniPKLGm+xCJo71IKGHKZaFve+TAzRR3q8KlNwnhtV1Ba6EsR4VaumomEOCR70I1IHc8ZcWANeGfXNbdFgsMOrjYb8uavtPZMhOkj82QC83Jptx+vIwUraj0fkXfSABrU8QQVoAA=)}
.gm[data-id=soon-1] .thumb{--ph:#7a807d}
.scene[data-for=soon-2]{--pv:url(data:image/webp;base64,UklGRhoBAABXRUJQVlA4IA4BAACQBgCdASogABIAPm0ukUakIqGhKA1QgA2JagCdMyS3kS26BYiDjC8EYLaRMP2PaMslDuwbHV+vrmMYSB4AAP7+4xYkqBdWPckMf4+RlCCH6IhBx4Offe3wRIMCR5Lcd5juvebo2TP/xNBHnwwrUf1LZ+un5MLT0B46LZsAdnas5H4HwolM22yRdUkbT/E9sQVRVWLsMWzTcwncuLmfBq1PsqzwbKltd4AmJ8UHlihy+xQ+plOrQmJfqeHn9uX9yBLn7ffiA/nhn+XqaqgyJ4jqG/Z/6+/v22n3LEfq5wHd+J8xZjzfvkfAl1spg5xT73OLSY4ISIKURBOmaA0aiQSN/kRp959ElU1l3sKAAAA=)}
.gm[data-id=soon-2] .thumb{--ph:#443028}
.scene[data-for=soon-3]{--pv:url(data:image/webp;base64,UklGRqwBAABXRUJQVlA4IKABAACQCACdASogABIAPm0skkWkIqGYBABABsS2AE6ZQYwhAHkCNV6ADmSfUBvAHoAfrN1tZXge4bUAGfDckotcrWal9eHj3+eLBXjK77WwqAD+81kH7keiwalhAdPFCJ3YF62/5A5AWDbv1sW9wZQ6q7NNGcApcAcPQu3ApxvAZ7k1OnT+lZBK6GGr7zc2eW6Ulpxsi4OEIWOvTWGMeteSmQ8XvMbU8WB+wLD4YXYgPDENkiH3RUVKCFaGJF/PxE+F8J4BjJcQOkOLdJ2npQ93KCcAWldidaKA26uQZa3kSzMXroSoUyfayOnOR8nTQ/Idyp3PQtTnYyV8JBwryZu8Kgbn6WCthpS6A486VfPrdLyHKl7vdlwlzdA8JGkAMMakuziMOUFDJhi6b+dagC53cfNF2qmp/+Z4ys6UX/6my50b6jkp7TKR96Z+ZwyWKAPK+UTxsBC09ozI6F1y4d+J0Wd6TuOF9ETZzXz62VvDnzJlMSjXwvizhzu/9aSUpCy3bu2HZix3V3KKvSkD3xxGTZf35A98cRd6Hz+K9D5++AAAAA==)}
.gm[data-id=soon-3] .thumb{--ph:#4b444d}
/* previews:end */

/* reduced motion (html.still): everything that moves freezes in place; switches are near-instant */
html.still .scene .art,html.still .kf img,html.still .tiles i{animation-play-state:paused}
html.still :is(.scene,.scene.on){transform:none;transition:opacity .25s,visibility 0s}
html.still :is(.copy>*,.copy.on>*){transform:none;transition:opacity .2s}
html.still :is(.clip,.clip.show){transform:none;transition:opacity .2s}
html.still :is(.gm,.thumb img,.spot,.play,.try,.top .btn){transition:none}
html.still .gm:focus .thumb img{transform:none}
html.still{transition:none}
html.still img.fade.in:not(.now){animation-duration:.2s} /* calm, but never a picture drawn in stripes */
html.still .top :is(.join,.who){animation-duration:.2s}
/* the join panel is open: the art holds still so nothing re-renders behind it */
html.joining .scene .art,html.joining .tiles i{animation-play-state:paused}
/* the family link (plan 2026-10-22-brand-family, Kyle's Task 1b look): the sister site, an outline button after Join
   with that site's coin; it arrives with Join (night.js un-hides both) so the header never jumps. On a phone the
   header has no room, so the same link sits under the lineup instead. */
.family-sm .family img{width:calc(2.6 * var(--u));height:auto;flex:none}
/* the site tabs (Kyle 2026-10-23, direction C "exactly as mocked"): a slim strip over the header with both full
   wordmarks, this site's first, underlined in the featured game's colour; the other is the switch (the remote reaches
   it with Up from the header row). It takes the header's top spacing, so the room below moves less than a unit. On a
   phone the header has no room: the family link under the lineup stays the switch there. */
.sites{display:flex;align-items:flex-end;gap:calc(1.8 * var(--u));padding-top:calc(2.6 * var(--u));border-bottom:2px solid color-mix(in srgb,var(--paper) 14%,transparent)}
.site{display:block;padding:calc(.5 * var(--u)) calc(.6 * var(--u)) calc(.7 * var(--u));margin:0 calc(-.6 * var(--u)) -2px;border-bottom:calc(.4 * var(--u)) solid transparent}
.site img{display:block;width:auto;height:calc(3 * var(--u))}
.site.on{border-bottom-color:var(--g1,var(--accent));transition:border-color .5s}
.site.family img{opacity:.55;filter:saturate(.75);transition:opacity .2s,filter .2s}
.site.family:hover img,.site.family:focus-visible img,html.kb .site.family:focus img{opacity:1;filter:none}
.site.family{transition:transform .35s var(--spring),box-shadow .25s}
.site.family:focus-visible,html.kb .site.family:focus{outline:none;border-radius:calc(.5 * var(--u));transform:translateY(var(--lift));box-shadow:var(--focus)}
html.still .site.family{transition:none}
.sites + .vin{margin-top:0;height:calc(8.8 * var(--u))}
@media (max-aspect-ratio: 5/4), (max-height: 500px), (max-width: 760px){.sites{display:none}.sites + .vin{height:auto}}
/* the header's outline buttons (the family link, Sign in) sit over each game's hero art, and King Fu's flying cards ran
   through "Board games" (2026-10-23 polish pass): a dark see-through fill keeps their words on a calm ground */
.top .btn.outline{background:color-mix(in srgb,var(--ink) 62%,transparent)}
.top .btn.outline:hover{background:color-mix(in srgb,var(--paper) 12%,color-mix(in srgb,var(--ink) 62%,transparent))}
.family-sm{display:none}
@media (max-aspect-ratio: 5/4), (max-height: 500px), (max-width: 760px){
  .top .family{display:none}
  .family-sm{display:flex;justify-content:center;margin:16px 0 0}
  .family-sm .family img{width:22px}
}
/* boardgame.plus shows four games (plan 2026-10-22-brand-family, Kyle's pick B): the cards keep the six-card row's
   size and the row centres, so the clip and the logos keep their room. partygame.plus has six and fills the row. */
@media not all and (max-aspect-ratio: 5/4){@media not all and (max-height: 500px){@media not all and (max-width: 760px){
  html[data-brand="board"] .lineup ul{grid-template-columns:repeat(4,calc((100% - 5 * 2.4 * var(--u)) / 6));justify-content:center}
}}}
