/* ============================================================
   ⭐⭐⭐ v0.487 — THE GLOWING ICE CAVE sits behind the whole rink. (Odaroo.)
   ⚠⚠⚠ EVERY PIECE OF FURNITURE ON THIS SCREEN MUST PAINT ABOVE IT, AND THAT IS NOT AUTOMATIC.
   A POSITIONED element at z-index 0 paints at step 8 of the cascade — AFTER the backgrounds AND the
   text of every NON-positioned sibling. That is precisely how Ink Panik's side column ended up
   unreadable under its nightscape in v0.483. #rinkSide is a plain flex child with no position of
   its own, so it is given one here; everything else on the screen already carries a z-index.
   The pre-flight's inkBackdropFaults() checks this on every game, every run — but a rule you have
   to be reminded of by a test is one worth writing down where the backdrop is declared. */
#rkCave{position:absolute; inset:0; width:100%; height:100%; z-index:0;
  pointer-events:none; image-rendering:pixelated; image-rendering:crisp-edges; opacity:.95;}
#rinkSide{position:relative; z-index:6;}
/* ⭐⭐ v0.487 — AND THE HUD GETS REAL PANELS. Against a plain screen these boxes could be bare text;
   against a moving aurora they cannot — Odaroo asked for dark semi-opaque plates so nothing bleeds
   through. Frost-white on deep ice-blue, one treatment for all of them, and every one of them is
   allowed to shrink its text rather than overflow. */
/* ⚠⚠ v0.491 — THE EXIT CUE IS NO LONGER GIVEN A PLATE, AND THAT PLATE WAS THE "EXTRA TILE".
   This rule handed `.rg-cue` the same dark bordered box the HUD wears — so the square below the
   exit was drawn as a framed, glowing panel sitting ON the ice, which reads as another tile to
   work out. Odaroo photographed exactly that. The cue is now nothing but a red triangle. */
#scr-rink .rk-hud{
  background:#0a1524d9; border:2px solid #4a7fa8; border-radius:7px;
  padding:5px 10px; box-shadow:0 0 14px #2fa3a055, 2px 2px 0 #04090cAA;
  color:#e9fbff; text-shadow:0 0 6px #2fa3a0; max-width:92%;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
/* the arrow stays RED on the ice — it is the one "go here" mark on the board and the ice-blue
   treatment every other cue wears would have made it just another cold thing to look at */
/* the two clocks under the inklings keep their cream plate but gain an edge that reads on ice */
#scr-rink .rkclk{border-color:#4a7fa8; box-shadow:0 0 10px #2fa3a055;}
/* ⭐⭐ v0.486 — THE FLOOR-CLEAR BANNER, which replaces the dialog that used to stop the run between
   every floor. It rides up over the ice and goes; the next floor is already being laid under it.
   ⚠ pointer-events:none — the D-pad is directly below and a tap must reach it. */
.rkFlash{position:absolute; left:50%; top:34%; transform:translate(-50%,-50%); z-index:60;
  pointer-events:none; text-align:center; white-space:nowrap;
  background:#0b1a20d9; border:2px solid #8ff0d2; border-radius:8px; padding:7px 14px;
  box-shadow:0 0 18px #2fa3a077, 3px 3px 0 #04090cAA;
  animation:rkFlashUp 1.25s ease-out forwards;}
.rkFlash b{display:block; font-family:var(--fontD); font-size:12px; letter-spacing:1.5px; color:#e9fbff; text-shadow:0 0 8px #2fa3a0;}
.rkFlash i{display:block; font-style:normal; font-family:var(--fontD); font-size:8px; letter-spacing:1px; color:#8ff0d2; margin-top:4px;}
@keyframes rkFlashUp{0%{opacity:0; transform:translate(-50%,-30%) scale(.86)}
  16%{opacity:1; transform:translate(-50%,-50%) scale(1)}
  72%{opacity:1; transform:translate(-50%,-56%) scale(1)}
  100%{opacity:0; transform:translate(-50%,-90%) scale(.97)}}
/* ⭐ v0.486 — the +Ns a clear pays back, floating off the clock. Fixed-position and pointer-blind:
   it is drawn over the ice and must never take a tap meant for the D-pad. */
/* ⭐⭐ v0.526 — AND IT SITS BESIDE THE CLOCK, ON THE SIDE THAT CLOCK FACES: `.atR` for my clock at
   the left edge of the screen, `.atL` for the rival's at the right edge. Both flash OUTWARD, away
   from their own screen edge, so neither can be shoved off it on the folded phone.
   ⚠⚠ THE TWO SIDES NEED TWO KEYFRAMES AND CANNOT SHARE ONE. The whole effect is a transform, and a
   transform carries the -100%/0 that parks the box to the correct side of its anchor point — so a
   single set of keyframes would drag the rival's figure across on top of their own clock the
   moment the animation took over. Anything added here goes in BOTH.
   ⚠ Fixed-position and pointer-blind: it is drawn over the ice and must never take a tap meant for
   the D-pad. */
.rkBonus{position:fixed; z-index:9500; pointer-events:none; white-space:nowrap;
  font-family:var(--fontD); font-size:13px; color:#8ff0d2; text-shadow:0 0 8px #2fa3a0, 1px 1px 0 #0b1a20;}
.rkBonus.atR{transform:translate(0,-50%); animation:rkBonusR .95s ease-out forwards;}
.rkBonus.atL{transform:translate(-100%,-50%); animation:rkBonusL .95s ease-out forwards;}
@keyframes rkBonusR{0%{opacity:0; transform:translate(-4px,-50%) scale(.7)}
  14%{opacity:1; transform:translate(0,-50%) scale(1.25)}
  34%{opacity:1; transform:translate(0,-50%) scale(1)}
  70%{opacity:1; transform:translate(0,-70%) scale(1)}
  100%{opacity:0; transform:translate(0,-110%) scale(.96)}}
@keyframes rkBonusL{0%{opacity:0; transform:translate(calc(-100% + 4px),-50%) scale(.7)}
  14%{opacity:1; transform:translate(-100%,-50%) scale(1.25)}
  34%{opacity:1; transform:translate(-100%,-50%) scale(1)}
  70%{opacity:1; transform:translate(-100%,-70%) scale(1)}
  100%{opacity:0; transform:translate(-100%,-110%) scale(.96)}}
/* ============================================================
   INKVILLE — rink.css
   Ink Rink and the Rink Royale online readout

   Part of the game.css split. Loaded as <link> tags from index.html in
   THIS ORDER — the cascade depends on it. Do not reorder the links.
   ============================================================ */
/* ============================================================
   ⭐ v0.380 — RINK ROYALE: the online readout.
   It lives in #rinkSide — the left column the rink already reserves under the inkling — because
   that is where every game in Inkville puts its stats, and because a box that lives there can
   never end up sitting on top of the ice on either fold. Everything is sized to the 88px column
   (124px unfolded) and wraps rather than clipping.
   ============================================================ */
.rkn-panel{border:3px solid var(--ink); background:var(--paper2); box-shadow:2px 2px 0 #1b151055;
  padding:4px 3px 5px; text-align:center; display:flex; flex-direction:column; gap:3px;}
.rkn-panel.mine{border-color:#2e7d4f; background:#eaf8ee;}
.rkn-panel.theirs{border-color:#8a6416; background:#fbf1d8;}
.rkn-vs{font-family:var(--fontD); font-size:7px; letter-spacing:1px; line-height:1.3;}
.rkn-vs b{display:block; opacity:.6; font-size:6px; letter-spacing:2px;}
.rkn-vs span{display:block; word-break:break-all; color:#3a2f26;}
.rkn-turn{font-family:var(--fontD); font-size:7px; letter-spacing:1px; padding:2px 1px;
  border:2px solid var(--ink); background:var(--ink); color:var(--cream); line-height:1.25;}
.rkn-panel.mine .rkn-turn{background:#f4c542; color:#1b1510; border-color:#8a6416;
  animation:rknPulse 1.4s ease-in-out infinite;}
@keyframes rknPulse{0%,100%{transform:scale(1)} 50%{transform:scale(1.05)}}
.rkn-clock{line-height:1;}
.rkn-clock b{font-family:var(--fontD); font-size:19px; color:#1b1510; display:block;}
.rkn-clock b.low{color:#a8241a; animation:rknPulse .5s ease-in-out infinite;}
.rkn-clock i{font-family:var(--fontD); font-style:normal; font-size:6px; letter-spacing:1px; opacity:.7;}
.rkn-row{display:flex; justify-content:space-between; align-items:center; gap:3px;
  font-family:var(--fontD); font-size:7px; letter-spacing:.5px; color:#3a2f26;}
.rkn-row b{font-size:8px; color:#1b1510;}
.rkn-wait{border-top:2px dashed #1b151055; padding-top:3px; line-height:1.35;}
.rkn-wait b{display:block; font-family:var(--fontD); font-size:7px; letter-spacing:.5px; color:#1b1510;}
.rkn-wait i{display:block; font-family:var(--fontD); font-style:normal; font-size:6px; letter-spacing:.5px; color:#3a2f26;}
.rkn-wait u{display:block; text-decoration:none; font-size:7px; opacity:.7; color:#3a2f26;}
.rkn-wait.on b{animation:rknBreathe 1.5s ease-in-out infinite;}
@keyframes rknBreathe{0%,100%{opacity:1} 50%{opacity:.42}}
/* ⭐ v0.444 — THE RIVAL'S OWN FLOOR, LIVE, UNDER THE READOUT. It is sized in JS against the column
   it sits in (rkMiniFloor), never against the screen, so it cannot outgrow the 88px fold. */
.rkn-mihead{display:flex; justify-content:space-between; align-items:baseline; gap:3px; margin-top:2px;
  font-family:var(--fontD); font-size:6px; letter-spacing:.5px; color:#3a2f26;}
.rkn-mihead span{overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.rkn-mihead b{font-size:7px; color:#1b1510;}
.rkn-mini{position:relative; margin:0 auto; width:100%; border:2px solid var(--ink); background:#dceefa; overflow:hidden;}
.rkn-mini i{position:absolute; display:block;}
.rkn-mini .mw{background:#7fa9c4;}
.rkn-mini .mr{background:#3a2f26;}
.rkn-mini .mx{background:var(--gold);}
.rkn-mini .mp{background:#c93a22; border-radius:50%; box-shadow:0 0 0 1px #1b1510;
  transition:left .2s linear, top .2s linear;}
.rkn-mini .mp.clear{background:#2e9e4f;}
.rkn-mini .mp.broke{background:#1b1510; animation:rknPulse .4s ease-in-out infinite;}
.rkn-mini.broke{filter:saturate(.4) brightness(.8);}
.rkn-mistat{font-family:var(--fontD); font-size:6px; letter-spacing:.5px; color:#3a2f26; margin-top:1px;}
@media (min-width:640px){ .rkn-mihead{font-size:8px;} .rkn-mihead b{font-size:9px;} .rkn-mistat{font-size:8px;} }
/* ⭐ v0.444 — THE PREP COUNT: 3 · 2 · 1 · GO, laid over the ice that is about to go live. It sits
   INSIDE #rinkBoard, so it can never be anywhere but on the board on either fold. */
.rk-prep{position:absolute; inset:0; z-index:20; display:flex; flex-direction:column;
  align-items:center; justify-content:center; gap:4px; background:#1b151088; pointer-events:none;}
.rk-prep b{font-family:var(--fontD); font-size:46px; color:var(--cream);
  text-shadow:3px 3px 0 #1b1510, 0 0 16px #9fd0ffaa;}
.rk-prep b.pop{animation:rkPrepPop .42s var(--pop,ease-out) both;}
.rk-prep i{font-family:var(--fontD); font-style:normal; font-size:9px; letter-spacing:2px; color:var(--gold);
  text-shadow:2px 2px 0 #1b1510;}
.rk-prep.go b{color:#8ff0a8; animation:rkPrepPop .5s ease-out both;}
@keyframes rkPrepPop{0%{transform:scale(1.9); opacity:0}45%{transform:scale(1); opacity:1}100%{transform:scale(1); opacity:1}}
.rkn-out{width:100%; margin-top:2px;}
.rkn-out span{font-size:7px!important; letter-spacing:1px;}
@media (min-width:640px){ .rkn-out span{font-size:9px!important;} }
/* while it is their floor, the ice reads as untouchable — you are watching, not skating */
#rinkBoard.rk-spect{filter:saturate(.72) brightness(.96);}
#rinkBoard.rk-spect::before{opacity:.8;}
@media (min-width:640px){
  .rkn-vs{font-size:9px;} .rkn-vs b{font-size:7px;}
  .rkn-turn{font-size:9px;} .rkn-clock b{font-size:24px;} .rkn-clock i{font-size:7px;}
  .rkn-row{font-size:8px;} .rkn-row b{font-size:10px;}
  .rkn-wait b{font-size:8px;} .rkn-wait i{font-size:7px;} .rkn-wait u{font-size:8px;}
}
.rk-prize .rk-art{width:50px; height:50px; margin:3px auto;}
.rk-prize .rk-art svg{width:100%; height:100%;}
.rk-prize .rk-nm{font-family:var(--fontD); font-size:7px; line-height:1.35; min-height:18px;}
.rk-cardw{width:72px; margin:3px auto 1px; pointer-events:none;}   /* the FULL cartridge on the wall — the SAME album face, never a re-cut */
.rk-cardw .card{width:100%; font-size:7px;}
.rk-cardw .card .nm{white-space:nowrap; overflow:visible; font-size:6px; letter-spacing:0;}   /* NICKELODEON-length names stay whole */
.rk-hrow{display:flex; justify-content:center; gap:3px; margin-top:5px;}
.rk-heart{width:14px; height:12px; display:inline-block;}
.rk-heart svg{width:100%; height:100%; display:block;}
.rk-heart.off{filter:grayscale(1) brightness(.5); opacity:.5;}
.rk-you{padding-top:6px;}
.rk-you .rk-unm{font-size:8px; opacity:.9; position:relative; z-index:3; min-height:10px;}   /* the name owns its lane — no hat pile covers it */
.rk-you .rk-av{margin-top:9px; overflow:visible;}
/* ⭐ v3.42 — rink bar stats + the exit-roulette odds rows */
.rk-barstats{font-size:9px; letter-spacing:1px; color:#cbb8d8; white-space:nowrap;}
.rk-barstats b{color:#f4c542; font-weight:normal; font-size:11px;}
@media (max-width:400px){ .rk-barstats{font-size:8px;} .rk-barstats b{font-size:10px;} }
.rk-raterows{display:flex; flex-direction:column; gap:3px; width:min(78%,230px); margin:8px auto 0;}
.rk-rate2{display:flex; align-items:center; justify-content:space-between; gap:6px; font-family:var(--fontD); font-size:9px; letter-spacing:1px; padding:3px 8px; background:var(--paper2); border:2px solid var(--ink); opacity:.85;}
.rk-rate2 b{font-size:11px; margin-left:auto;}
.rk-rate2.now{background:var(--gold); opacity:1;}
.rk-up{display:inline-block; font-family:var(--fontD); font-size:9px; color:#fdf6e3; background:#1f7a3f; border:2px solid var(--ink); padding:1px 5px; box-shadow:2px 2px 0 #0005; animation:pulse 1.2s ease-in-out infinite;}
.rk-rates .rk-rate{display:flex; justify-content:space-between; gap:4px; font-family:var(--fontD); font-size:6px; padding:2px 3px; margin-top:2px; opacity:.75;}
.rk-rates .rk-rate.now{background:var(--gold); color:var(--ink); opacity:1; outline:2px solid var(--ink); font-size:7px; animation:pulse 1.2s ease-in-out infinite;}   /* THIS is the tier on the wall right now */
.rkbox.rk-low{border-color:var(--red)!important; animation:rkLowGlow .55s ease-in-out infinite alternate;}
/* ⭐⭐⭐ v0.497 — THE SOLO CLOCK LIVES UNDER THE INKLING NOW, NOT ON THE RINK'S BOTTOM WALL.
   (Odaroo: "remove any timer from the bottom of the screen — it goes UNDERNEATH their inkling.")
   It used to be `position:absolute; bottom:3px` inside #rinkBoard, riding the ice's own bottom rail
   since v3.58. It is now a plain block dropped into the universal `.vsind` slot, which is where the
   ONLINE match has hung its two clocks since v0.451 — so both modes put the same readout in the same
   place. It carries `.rkclk` for the look, and everything here is only what the id has to override.
   ⚠ `position:static` is not tidying-up: the id beats `.rkclk` on specificity, so leaving the old
   absolute positioning in place would have pinned the new box to the bottom of the screen while
   claiming to be under the portrait. */
#rkTime{position:static; transform:none; left:auto; bottom:auto; margin-top:2px;}
#rkTime b{font-size:inherit; color:inherit; margin-left:0;}
#rkTime.rk-low, #rkTime.low{color:var(--red); border-color:var(--red);}
#rkTime.rk-low{border-color:var(--red)!important; animation:rkLowGlow .55s ease-in-out infinite alternate;}
#rkTime.rk-low b{color:var(--red);}
/* #rkLogo (the ICE-INK wordmark under the inkling) removed in v3.63 — "just the clean inkling, nothing else" */
.ssOverlay.bsOv.rk-intro{animation:rkIntroFly 1.75s var(--pop) both;}   /* slams in, holds, then SKATES off the right edge */
@keyframes rkIntroFly{0%{opacity:0; transform:translateX(-45vw);}14%{opacity:1; transform:translateX(0);}68%{opacity:1; transform:translateX(0);}100%{opacity:0; transform:translateX(65vw) rotate(3deg);}}
@keyframes rkLowGlow{from{box-shadow:2px 2px 0 #1b151055}to{box-shadow:0 0 14px 4px #c93a22cc}}
#rkP10{position:fixed; z-index:96; font-family:var(--fontD); font-size:22px; color:#3fbf5f; text-shadow:2px 2px 0 #1b1510, 0 0 10px #3fbf5f88; pointer-events:none; animation:rkP10 1.1s ease-out forwards;}
@keyframes rkP10{0%{opacity:0; transform:translate(-50%,26px) scale(.5)}18%{opacity:1; transform:translate(-50%,8px) scale(1.25)}70%{opacity:1; transform:translate(-50%,-6px) scale(1)}100%{opacity:0; transform:translate(-50%,-22px) scale(.9)}}
.rk-prize.gold{background:var(--gold); animation:rgShine 1.6s ease-in-out infinite;}
@media (min-width:560px){   /* the unfolded stage: bigger boxes, pulled toward the middle beside the big rink — but TIGHT so all six fit and the PRIZE card is never cut */
  #rinkSide{width:120px; gap:5px;}
  .rkbox{padding:4px 4px 5px;}
  .rkbox .rk-l{font-size:9px;}
  .rkbox .rk-v{font-size:18px;}
  .rkbox .rk-av{width:46px; height:52px;}
  .rk-cardw{width:80px;}
  .rk-prize .rk-art{width:78px; height:78px;}
  .rk-prize .rk-nm{font-size:9px; min-height:22px;}
}
/* ⚠⚠⚠ v0.508 — THE GLIDE DURATION RIDES A CUSTOM PROPERTY, NOT `style.transitionDuration`.
   `transitionDuration` is a LIST that applies to every property in the transition, so the moment
   the opacity fade below joined the list, JS setting the duration also stretched the fade. A var
   only touches the two lines it is written into. Set it with p.style.setProperty('--rkg', '.11s'). */
#rinkP{position:absolute; z-index:5;
  transition:left var(--rkg,.11s) linear, top var(--rkg,.11s) linear;}
/* home parade — classic left-to-right walkers */
#parade{position:relative; height:42px; margin:0 4px; overflow:hidden; flex:none; z-index:5;
  border-top:2px dashed #1b151044;}
.pwalk{position:absolute; bottom:2px; width:32px; height:34px; animation:paradeWalk linear infinite;}
@keyframes paradeWalk{from{left:-12%}to{left:104%}}
/* album family pages */
.famtabs{display:flex; flex-wrap:wrap; justify-content:center; gap:0 3px; overflow:visible; padding:6px 2px 0; align-items:flex-end; border-bottom:3px solid var(--ink); margin-bottom:6px;}   /* SIX file-folder tabs on one binder */
.famtab{font-size:8px; padding:6px 7px 5px; border:2px solid var(--ink); border-bottom:0; border-radius:7px 7px 0 0; background:var(--paper2);
  cursor:pointer; white-space:nowrap; font-family:var(--fontD); flex:none; box-shadow:inset 0 -5px 5px -5px #1b151088;}
.famtab.on{background:var(--cream); color:var(--ink); padding-bottom:8px; margin-bottom:-3px; box-shadow:none;}
.grid.fampage{display:block; max-width:760px; margin:0 auto; width:100%;}
/* ⭐⭐⭐ v0.767 — THE ALBUM'S SECTION HEADING. The tabs are gone; every family is a heading on one
   long scroll, cut to the same pattern as the badge wall's `.ach-sec` so the two screens read as one
   idea. The tally sits on the right, and the NEW / ⬆ chips only appear when they have news. */
.fam-sec{font-family:var(--fontD); font-size:calc(11px * var(--gs,1)); letter-spacing:calc(1px * var(--gs,1));
  display:flex; align-items:center; gap:calc(6px * var(--gs,1));
  margin:calc(14px * var(--gs,1)) 0 calc(6px * var(--gs,1));
  border-bottom:calc(3px * var(--gs,1)) solid var(--ink); padding-bottom:calc(3px * var(--gs,1));}
.fam-sec-n{margin-left:auto; opacity:.65; font-size:calc(9px * var(--gs,1));}
.fam-new{font-size:calc(8px * var(--gs,1)); background:var(--red); color:var(--cream);
  border:2px solid var(--ink); padding:1px calc(5px * var(--gs,1)); line-height:1.5;}
.fam-up{font-size:calc(8px * var(--gs,1)); background:var(--gold); color:var(--ink);
  border:2px solid var(--ink); padding:1px calc(5px * var(--gs,1)); line-height:1.5;}
@media (min-width:520px){ .fam-sec{font-size:calc(15px * var(--gs,1));} .fam-sec-n{font-size:calc(12px * var(--gs,1));}
  .fam-new,.fam-up{font-size:calc(11px * var(--gs,1));} }
/* ⚠ THE CARD'S OWN DOT MUST SIT INSIDE ITS FRAME. Every other notification dot in the game hangs
   half off its tile (v0.748) — a cart cannot, because `.card` carries the Game-Boy `clip-path` that
   cuts the notch, and a clip-path clips absolutely positioned children too. Offsetting it outward
   would simply delete it. */
/* ⚠ AND IT HANGS ON THE RIGHT, UNDER THE NOTCH. Top-LEFT is the cart's COST box — the dot sat on
   the number and hid it. The top-RIGHT 12x10px is cut away by the notch, so the dot starts below it. */
.cardnew{position:absolute; top:13px; right:3px; width:13px; height:13px; border-radius:50%;
  background:var(--red); border:2px solid var(--ink); z-index:14;
  box-shadow:0 0 0 2px var(--cream), 2px 2px 0 rgba(27,21,16,.5); animation:cardNewPulse 1.4s ease-in-out infinite;}
@keyframes cardNewPulse{0%,100%{transform:scale(1)}50%{transform:scale(1.18)}}
.famgrid{display:grid; grid-template-columns:repeat(4,minmax(0,82px)); gap:6px; align-content:start; justify-content:center;}   /* v3.112 — smaller cards, four across, centred on the fold */
@media (min-width:520px){ .famgrid{grid-template-columns:repeat(6,minmax(0,108px)); gap:10px;} }   /* unfolded: six across, centred */
/* ⭐ v3.93 — GALLERY view: ONE big card per row, a vertical flip-book of everything you own */
.gal1{display:flex; flex-direction:column; align-items:center; gap:16px; padding:6px 0 20px;}
.gal1 .card{width:min(72vw,270px);}
.gal1-missh{font-family:var(--fontD); font-size:10px; letter-spacing:2px; color:var(--cream); opacity:.6; margin:14px 0 2px; text-align:center;}
/* v3.107 — the view toggle spans the full grid row and STICKS to the top of the scroll, always above
   everything (it was falling into the gallery's left column, sliding behind the card wall and the pad). */
.collviews{display:flex; justify-content:center; gap:6px; margin:2px 0 6px; grid-column:1/-1;
  position:sticky; top:-8px; z-index:60; padding:8px 0 6px; background:var(--cream);
  box-shadow:0 4px 8px -4px #1b151033;}
.collview{pointer-events:auto;}
.collview{font-family:var(--fontD); font-size:9px; letter-spacing:1px; padding:6px 14px; background:var(--paper2); border:2px solid var(--ink); color:var(--ink); cursor:pointer;}
.collview.on{background:var(--red); color:var(--cream);}
/* pixel DDR */
.ddr-wrap{height:200px; max-width:340px;}
.ddr-t{border:3px solid var(--gold); padding:3px 0 0; display:flex; align-items:center; justify-content:center;}
.ddr-t svg{width:19px; height:19px; animation:tpulse var(--q,.5s) steps(2) infinite;}
@keyframes tpulse{0%,100%{transform:scale(1)}50%{transform:scale(1.18)}}
.ddr-note{width:36px; height:36px; margin-left:0;}   /* bigger, easier-to-read dance notes */
.ddr-t svg{width:36px; height:36px; display:block; margin:0 auto;}   /* target arrows = EXACT same size as the movers */
.ddr-t{font-size:0; padding:3px 0;}
/* ⭐ v3.42 — INK TAR HERO showstopper skin: the REAL five frets at the BOTTOM, notes fall onto them, touch only */
.ddr-wrap.ithskin .ddr-field{background:linear-gradient(#1a1026,#0d0b12);
  background-image:repeating-linear-gradient(90deg,transparent 0 calc(20% - 1px),#ffffff12 calc(20% - 1px) 20%),linear-gradient(#1a1026,#0d0b12);}   /* the standalone's five lane columns, drawn as thin dividers */
.ithskin .ddr-targets.ith-fretrow{top:auto; bottom:0; gap:5px; padding:0 4px 4px; pointer-events:auto; z-index:5;}
.ddr-t.ith-fretT{border:3px solid #00000088!important; border-radius:26px 26px 6px 6px; background:var(--lc);
  box-shadow:0 4px 0 #00000066, inset 0 3px 0 #ffffff55; height:46px; padding:0!important; cursor:pointer; pointer-events:auto;}
.ddr-t.ith-fretT.press{transform:translateY(4px) scale(.96); filter:brightness(1.75); box-shadow:0 0 14px var(--lc);}
.ddr-note.ith-gemQ{width:16.5%; height:18px; border-radius:6px; background:var(--lc);   /* v3.43 — a LINE across the lane, exactly the standalone's .ith-note bar, no more falling balls */
  border:2px solid #00000077; box-shadow:0 0 10px var(--lc);}
.ddr-note.ith-gemQ.nhit{background:var(--gold); box-shadow:0 0 16px var(--gold);}
.ddr-note.ith-gemQ.nmiss{filter:grayscale(1) brightness(.5);}
.ddr-note svg{width:100%; height:100%;
  filter:drop-shadow(0 0 3px #fdf6e3cc) drop-shadow(2px 2px 0 #000);}
.ddr-btn{max-width:58px; height:44px; display:flex; align-items:center; justify-content:center;}
.ddr-btn svg{width:21px; height:21px;}
.dpad-b svg{width:20px; height:20px;}
.simpad svg{width:26px; height:26px;}
.arrowfill svg{width:100%; height:100%;}
.ddr-judge{font-size:12px;}
#ddrCombo,#ddrMult{font-size:12px;}
/* ============================================================
   ⭐⭐⭐ v0.448 — RINK ROYALE, STRIPPED BACK.
   The left-hand panel is gone (see the note on rkPanel). What is left: a clock under each inkling,
   two numbers of HUD, and a 3-2-1 box over a COVERED floor between turns.
   ============================================================ */
/* the clock in the universal VS indicator slot, under its own inkling */
.rkclk{font-family:var(--fontD); font-size:11px; letter-spacing:.5px; color:var(--ink);
  background:#fffdf4ee; border:3px solid var(--ink); box-shadow:2px 2px 0 #1b151055;
  padding:3px 5px; text-align:center; min-width:52px; line-height:1;
  /* ⚠ ONLY THE TRANSFORM TRANSITIONS. A font-size transition made the size of the live clock a
     moving target — janky to look at, and impossible to assert on, since the value read back is
     whatever the animation happens to be part-way through. The step is instant; the beat is the
     animation. */
  transition:transform .18s ease;}
/* ⭐ WHOSE TURN IT IS: the live clock is bigger and it beats like a heart */
.rkclk.live{font-size:15px; padding:5px 7px; min-width:64px; animation:rkclkBeat 1s ease-in-out infinite;}
@keyframes rkclkBeat{0%,100%{transform:scale(1)} 45%{transform:scale(1.13)}}
/* ⭐ UNDER TEN SECONDS: red, and bigger again — the urgency has to be felt, not read */
/* ⭐ v0.491 — A FULL CLOCK READS "MAX" AND IT READS IT IN GREEN, exactly as the solo run's own
   clock has since v3.43. ⚠ The word is WIDER than the figure it replaces at the same size, so the
   min-width below has to hold "MAX" as well as "29.9" — it is the longest-value rule again. */
/* ⚠ NOT the solo clock's #2e9e4f: that green sits on the DARK ice, and this plate is cream — the
   pre-flight measured it at 3.3:1 against 4.5:1 required. Same word, same meaning, darker ink. */
.rkclk.maxed{color:#1c6b35; border-color:#1c6b35;}
.rkclk.low{color:var(--red); border-color:var(--red); font-size:14px;}
.rkclk.live.low{font-size:18px; animation:rkclkBeat .45s ease-in-out infinite;}
@media (min-width:560px){
  .rkclk{font-size:14px; min-width:66px;}
  .rkclk.live{font-size:20px; min-width:82px;}
  .rkclk.low{font-size:18px;} .rkclk.live.low{font-size:24px;}
}
/* the whole HUD: which floor, and how many rocks are on it */
.rk-hud{position:absolute; left:50%; transform:translateX(-50%); z-index:10; text-align:center;
  top:calc(6px * var(--gs,1) + env(safe-area-inset-top,0px)); pointer-events:none; line-height:1.25;}
.rk-hud b{display:block; font-family:var(--fontD); font-size:12px; letter-spacing:2px; color:var(--cream);
  text-shadow:2px 2px 0 #1b1510;}
.rk-hud i{display:block; font-family:var(--fontD); font-style:normal; font-size:7px; letter-spacing:1px;
  color:var(--gold); text-shadow:2px 2px 0 #1b1510;}
@media (min-width:560px){ .rk-hud b{font-size:17px;} .rk-hud i{font-size:10px;} }
/* ⭐ THE COVER — this is what makes "no map preview" true rather than a promise */
.rk-cover{position:absolute; inset:0; z-index:19; background:#12303f;
  background-image:repeating-linear-gradient(45deg,#16394b 0 8px,#12303f 8px 16px);}
.rk-prep{position:absolute; inset:0; z-index:20; display:flex; flex-direction:column;
  align-items:center; justify-content:center; gap:6px; pointer-events:none;}
.rk-prep b{font-family:var(--fontD); font-size:46px; color:var(--cream);
  text-shadow:3px 3px 0 #1b1510, 0 0 16px #9fd0ffaa;}
.rk-prep b.pop{animation:rkPrepPop .42s var(--pop,ease-out) both;}
.rk-prep i{font-family:var(--fontD); font-style:normal; font-size:9px; letter-spacing:2px; color:var(--gold);
  text-shadow:2px 2px 0 #1b1510;}
@keyframes rkPrepPop{0%{transform:scale(1.9); opacity:0}45%{transform:scale(1); opacity:1}100%{transform:scale(1); opacity:1}}
@media (min-width:560px){ .rk-prep b{font-size:74px;} .rk-prep i{font-size:13px;} }

/* ⭐ v0.451 — THE RINK'S TURN REEL: centred at the top, between the two name strips, wearing the
   same film leader the usernames and Crown's turn bar wear. Every status line goes through it. */
.rk-turn{position:absolute; left:50%; transform:translateX(-50%); z-index:11; pointer-events:none;
  top:calc(6px * var(--gs,1) + env(safe-area-inset-top,0px)); max-width:46vw; text-align:center;}
.rk-turn .rkt-in{display:inline-block; font-family:var(--fontD); font-size:8px; letter-spacing:1.5px;
  line-height:13px; padding:0 9px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:100%;
  color:#ffd6cc; background:#1b1510f2; border-top:4px solid #ffffff; border-bottom:4px solid #ffffff;
  position:relative;}
/* ⭐ v0.567 — CENTRED AND MIRRORED, like every other strip in the game. The tile puts the hole in
   the MIDDLE of its 9px period and the layer is centred, so the run of perforations is symmetric
   about the middle of the sign instead of starting hard against its left edge. (These are punched
   through a cream leader rather than painted on black, which is why they are drawn here as
   ::before/::after rather than pulled from --film-tile — the ink and the paper are swapped.) */
.rk-turn .rkt-in::before,.rk-turn .rkt-in::after{content:""; position:absolute; left:0; right:0; height:4px;
  background-image:linear-gradient(90deg,transparent 0 3px,#1b1510 3px 6px,transparent 6px 9px);
  background-size:9px 4px; background-position:center; background-repeat:repeat-x;}
.rk-turn .rkt-in::before{top:-4px;} .rk-turn .rkt-in::after{bottom:-4px;}
/* ⭐⭐⭐ v0.701 — THE STRIP IS THE MATCH CLOCK NOW, SO IT IS NEUTRAL. It used to turn gold and pulse
   on your turn, which was the right styling for the words "YOUR TURN" and is the wrong styling for
   a figure: a clock belongs to the MATCH, not to either player (the same rule #crTurn.crt-clock has
   carried on Disc-Ink since v0.643). Whose turn it is, is the red arrow's job now.
   ⚠ The `.mine` class is still toggled by rkTurnReel and still means something to the rest of the
   rink — it is only its paint here that is dropped. Do not delete the class. */
.rk-turn.mine .rkt-in{color:#ffd6cc; background:#1b1510f2; animation:none;}
@media (min-width:560px){ .rk-turn .rkt-in{font-size:12px; line-height:18px; padding:0 14px;} }
/* the FLOOR readout drops below the reel so the two never share a line */
/* ⭐⭐⭐ v0.719 — THE FLOOR BOX MOVES INTO THE EMPTY RIVAL SLOT, ON THE HEADER ROW.
   (Odaroo, 2026-08-06: "there should only be one film reel on the time. Now it looks like there are
   two.") It was centred at the top of the screen and, once --hudtop doubled in v0.718, it landed
   square on the header clock — two strips of film, one on the other, measured at both folds. Its own
   run clock is deleted (see rkFloorBox); a solo run has no rival, so the right-hand half of the
   header row is empty on every screen, and one word of run info is exactly what fits there.
   ⚠ `top` IS WRITTEN FROM JS, off the reel's measured centre (vsClockFace, via `data-onreel`) —
   never from a constant here, which is the mistake this replaces. This rule only supplies the
   fallback for the frames before the reel exists.
   ⚠ translateY(-50%) and NOT translateX: JS writes a CENTRE line, and the box is pinned by its
   right edge so it can never drift back under the clock as it grows. */
.rk-hud{left:auto; right:calc(8px * var(--gs,1));
  top:calc(30px * var(--gs,1) + env(safe-area-inset-top,0px));
  transform:translateY(-50%); max-width:34%;}
@media (min-width:560px){ .rk-hud{top:calc(40px * var(--gs,1) + env(safe-area-inset-top,0px));} }
/* the clock sits UNDER the inkling with real daylight, never over its face */
.vsind .rkclk{margin-top:2px;}
/* ⭐⭐⭐ v0.500 — THE ARMED RINK: THE STAGE IS SET, THE ICE IS NOT DEALT YET.
   (Odaroo: "the FULL STAGE must load first… everything EXCEPT the ice tiles.") The cave, the walls,
   the exit and its arrow are all there and lit; only the rocks and the skater are held back, and
   they FADE in on GO rather than snapping, so the reveal reads as the stage coming alive.
   ⚠ visibility, NOT display. The board's geometry is measured while it is armed (the pre-flight
   checks the ice fits the screen, and the well is sized from it) — `display:none` would collapse
   every tile to nothing and hand back measurements of an empty box. */
/* ⚠⚠⚠ v0.508 — THIS RULE DELETED THE SLIDE FOR EIGHT BUILDS. `transition` is a SHORTHAND: a later,
   HIGHER-SPECIFICITY rule (two IDs here, against one for #rinkP) REPLACES the whole declaration, it
   does not add to it. So from v0.500 the skater had an opacity transition and nothing else — every
   glide was an instant teleport to the far wall, which is exactly what Odaroo reported. Anything
   that must run ALONGSIDE an existing transition has to RESTATE it, the same trap as `animation`. */
#rinkBoard .rtile.rrock{transition:opacity .34s ease-out;}
#rinkBoard #rinkP{transition:left var(--rkg,.11s) linear, top var(--rkg,.11s) linear, opacity .34s ease-out;}
#rinkBoard.rkArmed .rtile.rrock, #rinkBoard.rkArmed #rinkP{visibility:hidden; opacity:0;}

/* ============================================================
   ⭐⭐⭐ v0.515 — THE RED ARROW THAT NAMES THE FIRST SKATER. THE COIN IS GONE.

   Both inklings stand side by side and a bold red arrow shuffles between them — fast at first,
   decelerating, landing on one, blinking three times over a bell. It runs once, before the
   3 · 2 · 1 · GO, and it is a TELLING rather than a deciding: the room has already answered who
   opens, and both machines land on the same inkling without a word crossing the wire.

   ⚠⚠ THE BOX IS A FIXED WIDTH AND SO IS EVERY PIECE IN IT, AND THAT IS NOT A STYLE CHOICE. It is
   anchored by a percentage transform, and a box that re-measures itself as its message changes
   ("WHO SKATES FIRST…" is not the width of "YOU SKATE FIRST") slides visibly across the ice while
   it speaks. That is the exact bug the Crown coin had in v0.485, and the rule it produced is in
   CLAUDE.md: A POSITION MAY NEVER DEPEND ON WHAT THE WORDS SAY. Anything added in here comes out
   of this width.
   ⚠ v0.563 — AND NOTHING INSIDE IT MOVES EITHER. The arrow turns round on the spot and the discs
   only light up; there is no translate and no scale anywhere in the shuffle, so no amount of
   shuffling can move any part of the picture. The one thing that animates is the winner's pulse,
   after everything has stopped.
   ============================================================ */
.rk-pick{position:absolute; left:50%; top:46%; transform:translate(-50%,-50%); z-index:22;
  width:calc(190px * var(--gs,1)); text-align:center; pointer-events:none;
  display:flex; flex-direction:column; align-items:center; gap:calc(9px * var(--gs,1));}
.rk-pick .rkp-row{width:100%; display:flex; align-items:center; justify-content:space-between;}
/* the two contenders — same disc the coin's faces were, side by side instead of back to back */
.rk-pick .rkp-face{position:relative; flex:0 0 auto;
  width:calc(58px * var(--gs,1)); height:calc(58px * var(--gs,1));
  display:flex; align-items:center; justify-content:center; border-radius:50%;
  font-family:var(--fontD); font-style:normal; font-size:calc(9px * var(--gs,1)); letter-spacing:.5px;
  overflow:hidden; white-space:nowrap; padding:0 4px; color:#1b1510;
  border:calc(3px * var(--gs,1)) solid #1b1510; box-shadow:0 3px 0 #00000066;
  transition:transform .16s ease-out, box-shadow .16s ease-out, opacity .09s steps(1);}
/* ⭐⭐ v0.526 — BOTH SIDES WEAR THE PORTRAIT FRAME, NOT A COIN FACE. The gold and the pale blue
   were the toss's two faces and they outlived the coin by ten builds. One cream frame each, the
   same paper the game-bar portrait sits on, so what you are looking at is plainly two PLAYERS
   being pointed at rather than heads and tails. A frame bought in the Mart re-colours the ring
   through the `.fr-*` classes rkFirstPick adds (they all set border-color/box-shadow !important),
   which is exactly why the ring is a plain border here and nothing more decorated. */
.rk-pick .rkp-me,.rk-pick .rkp-them{background:var(--cream,#f2ead6);}
/* the one the arrow is pointing at right now leans forward and lights up */
/* ⚠⚠ v0.563 — IT LIGHTS UP, IT DOES NOT GROW. (Odaroo: "the red arrows are shifting/sliding across
   the screen — they should STAY CENTERED.") A `scale(1.1)` on one disc and then the other, seventeen
   times in two seconds, is read as the whole selector rocking from side to side — the discs are the
   only landmarks in the box, so anything that moves them moves the picture. Nothing in this overlay
   changes SIZE or POSITION during the shuffle any more; the glow alone says which side is lit. */
.rk-pick .rkp-face.lit{box-shadow:0 3px 0 #00000066, 0 0 calc(16px * var(--gs,1)) #e03a24cc;}
.rk-pick .rkp-face.off{opacity:.25;}
/* ⚠ the sprite is a FRACTION of the disc, never pixels — the disc is already scaled by --gs on
   both folds, and a fixed sprite would burst out of it on the narrow one */
.rk-pick .rkp-ink{display:flex; align-items:center; justify-content:center; width:78%; height:78%;}
.rk-pick .rkp-ink svg{width:100%; height:100%; display:block;}
/* ⭐⭐ v0.526 — THE ARROW IS A PLAIN RED TRIANGLE, AND IT DOES NOT GLIDE. (Odaroo: "a SIMPLE RED
   TRIANGLE — same design as the exit/back button triangle, three corners, red, simple… it should
   NOT animate smoothly — just SNAP between left and right.")
   ⚠⚠ THE TRANSITION IS GONE ON PURPOSE. It used to swing across on an .085s ease, so at the fast
   end of the shuffle the arrow was never actually AT either side — it was permanently in flight
   somewhere in the middle, which is exactly what "don't animate it smoothly" is about. With no
   transition the shape is on one side or the other and nowhere else, and the deceleration is read
   entirely from the GAPS between snaps (the schedule in rkFirstPick), which is how a game-show
   selector reads anyway.
   ⚠ Three corners via clip-path, the same way `.rg-tri` (the exit cue on the ice) draws its
   triangle — one shape written once, identical on every device, and free to mirror. */
.rk-pick .rkp-arrow{flex:0 0 auto; display:block; background:var(--red,#e0231a);
  width:calc(34px * var(--gs,1)); height:calc(34px * var(--gs,1));
  clip-path:polygon(0 0, 100% 50%, 0 100%);
  filter:drop-shadow(0 1px 0 #1b1510) drop-shadow(0 0 calc(6px * var(--gs,1)) #e03a2488);
  transition:opacity .06s steps(1);}
/* ⚠⚠⚠ v0.563 — THE ARROW NEVER MOVES. IT ONLY TURNS ROUND.
   (Odaroo: "they should STAY CENTERED in the middle of the screen… appear centered showing
   left-right-left-right alternating, then STOP, then flash/pulse.")
   It used to lean 6px towards whichever side it was pointing at and 9px when it locked — three
   positions, snapped between seventeen times, which is precisely the sliding that was reported. The
   direction is now carried by the MIRROR and nothing else, so the triangle is nailed to the centre
   of the row for the whole ceremony and only its three corners change hands. ⚠ Do not put a
   translate back in here to "make the point clearer": the point is made by the glow on the disc it
   is aimed at, and by the flash when it lands. */
.rk-pick .rkp-arrow.at-them{transform:scaleX(1);}
.rk-pick .rkp-arrow.at-me{transform:scaleX(-1);}
/* LOCKED: it stops turning and PULSES on the spot — the flash that says "this one, and we are done".
   ⚠ It is a `scale` ANIMATION, not a transform one: `transform` is already spoken for above by the
   mirror, and an animation on the shorthand would replace that and flip the triangle back to facing
   right on the winner's side (the `animation`-shorthand trap in CLAUDE.md, one property along).
   `scale` is an independent property, so the pulse and the mirror compose. */
@keyframes rkPickPulse{0%,100%{scale:1;} 50%{scale:1.28;}}
.rk-pick .rkp-arrow.lock{animation:rkPickPulse .30s steps(2,end) infinite;}
.rk-pick .rkp-arrow.off{opacity:0;}
/* ⚠⚠ IT WRAPS TO TWO LINES INSIDE A FIXED HEIGHT, and both halves of that matter. The worst case
   is twelve characters of name (the room's cap) plus "SKATES FIRST", and on one nowrap line that
   ellipses away the only word that says who won. But letting the box GROW would move it: the whole
   thing is anchored by translate(-50%,-50%), so a taller message re-centres itself higher up the
   ice as it speaks — the same fault as a width that depends on the words. Two lines, reserved. */
.rk-pick .rkc-say{width:100%; font-family:var(--fontD); font-size:calc(9px * var(--gs,1));
  letter-spacing:1px; line-height:1.5; color:var(--cream); text-shadow:2px 2px 0 #1b1510;
  overflow:hidden; white-space:normal; box-sizing:border-box;
  height:calc(28px * var(--gs,1)); display:flex; align-items:center; justify-content:center;}
@media (min-width:560px){
  .rk-pick{width:calc(260px * var(--gs,1));}
  .rk-pick .rkp-face{width:calc(78px * var(--gs,1)); height:calc(78px * var(--gs,1));
    font-size:calc(12px * var(--gs,1));}
  /* ⚠ v0.526 — SQUARE ON BOTH FOLDS. The wide rule still carried the old chevron's 62×40 box,
     which stretched the triangle's three corners into a long thin dart on the unfolded phone —
     the same shape has to be the same shape at both sizes. */
  .rk-pick .rkp-arrow{width:calc(46px * var(--gs,1)); height:calc(46px * var(--gs,1));}
  .rk-pick .rkc-say{font-size:calc(12px * var(--gs,1)); height:calc(38px * var(--gs,1));}
}
/* (v0.518 — a stray extra '}' lived here. A top-level closing brace is not harmless: the parser
   recovers from it by skipping to the NEXT one, which quietly ate the whole first rule of any block
   appended after it. It cost this session a real half-hour of "my CSS is not loading".) */


/* ============================================================
   ⭐⭐⭐ v0.518 — THE RINK'S BOXES ARE STRIPS OF FILM. (Odaroo, 2026-08-03: "rework the floor number
   box and all the pop-ups to look like film reels — the same style as the username display and the
   inkling display on the main menu, same font, and keep it readable.")
   The rink was the last screen still wearing the v0.487 "ice panels": dark blue plates with cyan
   borders and a glow. They were built to survive the aurora behind them, which they did — but they
   are the only furniture in the whole game that is not the film strip everything else wears, so the
   rink read as a screen from a different game sitting next to its own username reels.
   ⚠⚠ THE RECIPE IS .inkfilm IN css/hub.css AND IT IS RESTATED HERE, NOT INHERITED. Two reasons, and
   both have bitten before. (1) `background` is a SHORTHAND: `#scr-rink .rk-hud` sets it, and an id+
   class selector beats a bare class, so the sprocket holes .inkfilm paints as a background-IMAGE
   were being silently wiped — exactly the trap css/crown.css records at #crTurn. (2) The holes have
   to be redrawn at this box's own scale anyway. If .inkfilm's numbers change, change these with it.
   ⚠ READABILITY IS THE POINT, NOT A CONSTRAINT ON IT. Cream #fdf6e3 on the strip's #0d0a08 leader is
   19.3:1 — far above the 4.5:1 crReadable demands, and better than the cream-on-ice-blue it
   replaces. The gold used for the second line is only ever a SECOND line, so it is lifted to the
   brighter --gold2 to clear the bar on its own.
   ============================================================ */
#scr-rink .rk-hud, #scr-rink .rk-hud.inkfilm{
  background:#0d0a08; border:0; border-radius:0; box-shadow:0 calc(2px * var(--gs,1)) 0 rgba(13,10,8,.55);
  border-top:calc(2px * var(--gs,1)) solid #0d0a08; border-bottom:calc(2px * var(--gs,1)) solid #0d0a08;
  padding:calc(6px * var(--gs,1)) calc(10px * var(--gs,1));
  color:#fdf6e3; text-shadow:none; line-height:1.3;
  /* v0.567 - the same holes, now CENTRED and MIRRORED. The recipe is --film-tile in css/base.css
     and it is pulled in by var rather than copied, so this strip can never drift from the reel. */
  background-image:linear-gradient(to right,
     transparent 0 calc((var(--film-per) - var(--film-w))/2 * var(--gs,1)),
     var(--film-hole) calc((var(--film-per) - var(--film-w))/2 * var(--gs,1)) calc((var(--film-per) + var(--film-w))/2 * var(--gs,1)),
     transparent calc((var(--film-per) + var(--film-w))/2 * var(--gs,1)) calc(var(--film-per) * var(--gs,1))),
    linear-gradient(to right,
     transparent 0 calc((var(--film-per) - var(--film-w))/2 * var(--gs,1)),
     var(--film-hole) calc((var(--film-per) - var(--film-w))/2 * var(--gs,1)) calc((var(--film-per) + var(--film-w))/2 * var(--gs,1)),
     transparent calc((var(--film-per) + var(--film-w))/2 * var(--gs,1)) calc(var(--film-per) * var(--gs,1)));
  background-size:calc(var(--film-per) * var(--gs,1)) calc(var(--film-h) * var(--gs,1)), calc(var(--film-per) * var(--gs,1)) calc(var(--film-h) * var(--gs,1));
  background-position:center calc(var(--film-in) * var(--gs,1)), center calc(100% - var(--film-in) * var(--gs,1));
  background-repeat:repeat-x, repeat-x;}
/* ⚠ THE HOLES NEED ROOM OR THEY SIT ON THE LETTERS. The plate's old 5px of padding was sized for a
   plain border; a film leader spends its top and bottom 3px on sprockets, so the text has to start
   below them. That is the same sum #crTurn's note describes, paid out of the padding above. */
#scr-rink .rk-hud b.rkfl{display:block; font-family:var(--fontD); font-size:calc(11px * var(--gs,1));
  letter-spacing:calc(1.5px * var(--gs,1)); color:#fdf6e3; text-shadow:none; line-height:1.25;}
/* ⚠ THE TOTAL TIME IS FIXED-WIDTH AND CENTRED, so the box does not breathe once a second as the
   digits change. A width that depends on what the words say is the v0.484 coin-toss fault, and this
   box is anchored by translateX(-50%) — it would slide sideways every tick. `ch` on a display face
   is close enough to monospace here, and the box is min-width'd rather than fixed so a run past
   99 minutes grows instead of clipping. */
#scr-rink .rk-hud i.rktt{display:block; font-family:var(--fontD); font-style:normal;
  font-size:calc(9px * var(--gs,1)); letter-spacing:calc(1px * var(--gs,1)); color:var(--gold2);
  text-shadow:none; margin-top:calc(2px * var(--gs,1)); min-width:5ch; line-height:1.25;}
@media (min-width:560px){
  #scr-rink .rk-hud b.rkfl{font-size:calc(15px * var(--gs,1));}
  #scr-rink .rk-hud i.rktt{font-size:calc(12px * var(--gs,1));}
}
/* ⭐⭐⭐ v0.725 — THE ONLINE SHAPE: A CAPTION OVER A NUMBER, IN THE LEFT COLUMN.
   In a match the header row's right-hand half belongs to the rival's name, so the floor number is
   stacked under my own inkling instead (rkFloorBox / vsClockFace) — and the column the online rink
   reserves there is only ~70px wide folded. "FLOOR 12" on one line is ~84px of ink and would have
   simply moved the collision onto the ice, so online it re-shapes into two short lines.
   ⚠ `max-width` is what keeps that promise; the plate is `white-space` unset, so a wider label
   would grow the box rather than wrap it.
   ⚠ NO transform here — JS writes a plain top for this variant, not a centre line, and the shared
   translateY(-50%) above is switched off inline.
   ⭐⭐⭐ v0.734 — AND IT MOVED AGAIN, TO DIRECTLY UNDER THE CLOCK. (Odaroo: "put it under the time…
   a little bit of spacing… center it too… a little bit bigger, as wide as the length of the timer
   is.") So the ~70px left-column clamp that shaped this box is GONE: `min-width` is written from JS
   off the clock's own measured box (vsClockFace), and a `max-width` here would fight it — a box
   narrower than the figure it must match is the whole thing this build is undoing.
   ⚠ NO transform and NO max-width in this rule: JS writes a plain top and an explicit
   translateX(-50%), and the width comes from the clock. */
#scr-rink .rk-hud.rk-hud-col{text-align:center; max-width:none;
  padding:calc(4px * var(--gs,1)) calc(8px * var(--gs,1));}
#scr-rink .rk-hud.rk-hud-col i.rkflc{display:block; font-family:var(--fontD); font-style:normal;
  font-size:calc(8px * var(--gs,1)); letter-spacing:calc(1px * var(--gs,1));
  color:var(--gold2); text-shadow:none; line-height:1.2;}
#scr-rink .rk-hud.rk-hud-col b.rkfl{font-size:calc(19px * var(--gs,1)); letter-spacing:0; line-height:1.15;}
@media (min-width:560px){
  #scr-rink .rk-hud.rk-hud-col i.rkflc{font-size:calc(10px * var(--gs,1));}
  #scr-rink .rk-hud.rk-hud-col b.rkfl{font-size:calc(25px * var(--gs,1));}
}
/* ⭐ THE FLOOR-CLEAR BANNER — the one pop-up an ordinary floor still shows. Same strip, and it keeps
   its ride-up animation untouched: .rkFlash's transform is animated by rkFlashUp, so nothing here
   may write `transform` or the banner would sit still. Only the skin changes. */
.rkFlash{background:#0d0a08; border:0; border-radius:0;
  border-top:calc(2px * var(--gs,1)) solid #0d0a08; border-bottom:calc(2px * var(--gs,1)) solid #0d0a08;
  box-shadow:0 calc(2px * var(--gs,1)) 0 rgba(13,10,8,.55);
  padding:calc(7px * var(--gs,1)) calc(14px * var(--gs,1));
  /* v0.567 - the same holes, now CENTRED and MIRRORED. The recipe is --film-tile in css/base.css
     and it is pulled in by var rather than copied, so this strip can never drift from the reel. */
  background-image:linear-gradient(to right,
     transparent 0 calc((var(--film-per) - var(--film-w))/2 * var(--gs,1)),
     var(--film-hole) calc((var(--film-per) - var(--film-w))/2 * var(--gs,1)) calc((var(--film-per) + var(--film-w))/2 * var(--gs,1)),
     transparent calc((var(--film-per) + var(--film-w))/2 * var(--gs,1)) calc(var(--film-per) * var(--gs,1))),
    linear-gradient(to right,
     transparent 0 calc((var(--film-per) - var(--film-w))/2 * var(--gs,1)),
     var(--film-hole) calc((var(--film-per) - var(--film-w))/2 * var(--gs,1)) calc((var(--film-per) + var(--film-w))/2 * var(--gs,1)),
     transparent calc((var(--film-per) + var(--film-w))/2 * var(--gs,1)) calc(var(--film-per) * var(--gs,1)));
  background-size:calc(var(--film-per) * var(--gs,1)) calc(var(--film-h) * var(--gs,1)), calc(var(--film-per) * var(--gs,1)) calc(var(--film-h) * var(--gs,1));
  background-position:center calc(var(--film-in) * var(--gs,1)), center calc(100% - var(--film-in) * var(--gs,1));
  background-repeat:repeat-x, repeat-x;}
.rkFlash b{color:#fdf6e3; text-shadow:none;}
.rkFlash i{color:var(--gold2); text-shadow:none;}
/* ⭐ THE COUNT-IN'S STATUS LINE. The big 3 · 2 · 1 is deliberately left alone — it is a number the
   size of the screen, not a box, and dressing it as a strip of film would shrink the one thing on
   that frame that is meant to be enormous. It is the LINE UNDER it that is a label, and that is
   what becomes the reel. */
.rk-prep i{display:inline-block; font-family:var(--fontD); color:#fdf6e3; text-shadow:none;
  background:#0d0a08; letter-spacing:calc(1.5px * var(--gs,1));
  border-top:calc(2px * var(--gs,1)) solid #0d0a08; border-bottom:calc(2px * var(--gs,1)) solid #0d0a08;
  padding:calc(5px * var(--gs,1)) calc(10px * var(--gs,1));
  /* v0.567 - the same holes, now CENTRED and MIRRORED. The recipe is --film-tile in css/base.css
     and it is pulled in by var rather than copied, so this strip can never drift from the reel. */
  background-image:linear-gradient(to right,
     transparent 0 calc((var(--film-per) - var(--film-w))/2 * var(--gs,1)),
     var(--film-hole) calc((var(--film-per) - var(--film-w))/2 * var(--gs,1)) calc((var(--film-per) + var(--film-w))/2 * var(--gs,1)),
     transparent calc((var(--film-per) + var(--film-w))/2 * var(--gs,1)) calc(var(--film-per) * var(--gs,1))),
    linear-gradient(to right,
     transparent 0 calc((var(--film-per) - var(--film-w))/2 * var(--gs,1)),
     var(--film-hole) calc((var(--film-per) - var(--film-w))/2 * var(--gs,1)) calc((var(--film-per) + var(--film-w))/2 * var(--gs,1)),
     transparent calc((var(--film-per) + var(--film-w))/2 * var(--gs,1)) calc(var(--film-per) * var(--gs,1)));
  background-size:calc(var(--film-per) * var(--gs,1)) calc(var(--film-h) * var(--gs,1)), calc(var(--film-per) * var(--gs,1)) calc(var(--film-h) * var(--gs,1));
  background-position:center calc(var(--film-in) * var(--gs,1)), center calc(100% - var(--film-in) * var(--gs,1));
  background-repeat:repeat-x, repeat-x;}
/* ⭐ AND THE COIN-TOSS FRAME'S LINE — "<NAME> SKATES FIRST", the other thing the rink says on the
   way in. Its box is height-reserved for two lines (see .rkc-say above) and this must not change
   that: no padding that would grow it, only the skin and the colour. */
/* ⚠⚠ AND IT GETS NO BORDER, WHICH THE PRE-FLIGHT CAUGHT ON THE FIRST RUN. .inkfilm's top and bottom
   borders are the same colour as its own background — they exist only to make the leader thicker —
   but this box reserves EXACTLY two lines of height and nothing more, so 2px each way pushed the
   second line out and the longest message ("ODAROOOOOO SKATES FIRST") lost the words that say who
   won. The sprockets are a background-IMAGE, so they land in the right place without it: same look,
   4px cheaper, and the reserved height is left exactly as it was. */
.rk-pick .rkc-say{color:#fdf6e3; text-shadow:none; background:#0d0a08;
  /* v0.567 - the same holes, now CENTRED and MIRRORED. The recipe is --film-tile in css/base.css
     and it is pulled in by var rather than copied, so this strip can never drift from the reel. */
  background-image:linear-gradient(to right,
     transparent 0 calc((var(--film-per) - var(--film-w))/2 * var(--gs,1)),
     var(--film-hole) calc((var(--film-per) - var(--film-w))/2 * var(--gs,1)) calc((var(--film-per) + var(--film-w))/2 * var(--gs,1)),
     transparent calc((var(--film-per) + var(--film-w))/2 * var(--gs,1)) calc(var(--film-per) * var(--gs,1))),
    linear-gradient(to right,
     transparent 0 calc((var(--film-per) - var(--film-w))/2 * var(--gs,1)),
     var(--film-hole) calc((var(--film-per) - var(--film-w))/2 * var(--gs,1)) calc((var(--film-per) + var(--film-w))/2 * var(--gs,1)),
     transparent calc((var(--film-per) + var(--film-w))/2 * var(--gs,1)) calc(var(--film-per) * var(--gs,1)));
  background-size:calc(var(--film-per) * var(--gs,1)) calc(var(--film-h) * var(--gs,1)), calc(var(--film-per) * var(--gs,1)) calc(var(--film-h) * var(--gs,1));
  background-position:center calc(var(--film-in) * var(--gs,1)), center calc(100% - var(--film-in) * var(--gs,1));
  background-repeat:repeat-x, repeat-x;}
