/* Figma UI rebuild (2026-11-03): the kit every rebuilt screen uses.
   --m   = CSS px per mock px (the Figma frames are 1440 x 2560), set by chrome.js measure()
   art   = PNG exports from Figma (src/figkit.js, assets/ui/fig/), never re-drawn in CSS
   text  = Futura Bold (Apple devices) / Jost Bold, white with the mock's black outside stroke */
:root { --font-ui: "UI", "Futura", "Jost", "Arial Black", sans-serif; }

/* outlined text: --sw = the mock's outside stroke weight (mock px), --fs = font size (mock px) */
.fx {
  font-family: var(--font-ui); font-weight: 700; color: #fff; line-height: 1; white-space: nowrap;
  font-size: calc(var(--m) * var(--fs, 32)); letter-spacing: 0;
  -webkit-text-stroke: calc(var(--m) * var(--sw, 6) * 2) #000; paint-order: stroke fill;
}
.fx.nostroke { -webkit-text-stroke: 0; }

/* an exported image as an element's whole background (fixed-size art) */
.fimg { background: var(--img) 0 0 / 100% 100% no-repeat; }
.fabs { position: absolute; }

/* a button made of exported art; the mock has no pressed state, so it sinks and darkens a little */
.fbtn {
  position: absolute; display: grid; place-items: center; padding: 0; margin: 0; border: 0; cursor: pointer;
  background: var(--img) 0 0 / 100% 100% no-repeat; font: inherit; color: inherit; touch-action: manipulation;
  transition: transform .06s, filter .06s;
}
.fbtn:active:not(:disabled) { transform: translateY(calc(var(--m) * 4)); filter: brightness(.92); }
.fbtn:focus-visible { outline: calc(var(--m) * 8) solid #fff; outline-offset: calc(var(--m) * 4); }
.fbtn:disabled { cursor: default; filter: grayscale(.6) brightness(.9); }

/* 9-slice: art that stretches (--img, --sl = slice insets in image px, --bw = their on-screen size) */
.f9 {
  border-style: solid; border-color: transparent; background: none;
  border-image: var(--img) var(--sl) fill / var(--bw) stretch;
}

/* ---- chrome: top bar + nav (src/chrome.js; mock Home 265:156) ---- */
.fc-top { position: absolute; z-index: 9; left: var(--colx); top: var(--sat, 0px); width: var(--colw); height: 0; pointer-events: none; }
.fc-top > *, .fc-world > * { pointer-events: auto; }
.fc-top[hidden], .fc-nav[hidden], .fc-top [hidden], .fc-nav [hidden] { display: none !important; }
.fc-world { position: absolute; left: 0; top: 0; width: 0; height: 0; }
.fc-top button, .fc-nav button { background-color: transparent; border: 0; padding: 0; margin: 0; cursor: pointer; font: inherit; touch-action: manipulation; }
.fc-top button:not(.fbtn):active, .fc-nav .fc-tab:active { filter: brightness(.93); }
.fc-txt { display: flex; align-items: center; justify-content: center; text-align: center; overflow: visible; }
.fc-pbird canvas, .fc-tabbird canvas { display: block; image-rendering: pixelated; }
.fc-pill.pump { animation: hudPump .25s; }
.fc-pill.shield { cursor: pointer; }
.fc-dot { position: absolute; right: calc(var(--m) * -6); top: calc(var(--m) * -6); width: calc(var(--m) * 34); height: calc(var(--m) * 34); border-radius: 50%; background: #e8322e; border: calc(var(--m) * 5) solid #000; }
.fc-badge { display: grid; place-items: center; box-sizing: border-box; border-radius: 999px; background: #e8322e; border: calc(var(--m) * 5) solid #000;
  font: 700 calc(var(--m) * 28)/1 var(--font-ui); color: #fff; pointer-events: none; }
.fc-badge.care { background: #fff; }
/* 5 Nov: a nav badge is a circle for one digit, a pill for more (style.css's old .tab-badge min-width made every one an
   oval, and the care emoji a pill that ran under the next tab); the care badge is its icon in a circle */
.fc-nav .fc-badge.tab-badge { width: auto !important; min-width: calc(var(--m) * 52); padding: 0 calc(var(--m) * 9); }
.fc-nav .fc-badge.tab-badge.care { width: calc(var(--m) * 52) !important; min-width: 0; padding: 0; }
.fc-badge.care img { display: block; width: 80%; height: 80%; object-fit: contain; }
.fc-nav { position: absolute; z-index: 9; left: var(--colx); width: var(--colw); bottom: var(--sab, 0px); height: calc(var(--m) * 239); pointer-events: none; }
.fc-nav > * { pointer-events: auto; }
.fc-navfill { position: absolute; left: calc(var(--m) * 64); width: calc(var(--m) * 1312); top: 100%; height: var(--sab, 0px); background: #71c5ff; }
.fc-tab .fc-tabon { display: none; }
.fc-tab.on .fc-tabon { display: block; }
/* 5 Nov (Basil): the active art is 5 mock px wider than its slot on each side; above its neighbours (as in the
   mock) so the next tab no longer covers its right outline */
.fc-nav .fc-tab.on { z-index: 1; }
.fc-pill .cp-ico { margin: 0; filter: none; animation: none; }   /* (style.css's old .cp-ico sizing; the class stays as the fly-to target) */

/* ---- mock-frame layers (src/figscreen.js) ---- */
.fs-layer { position: absolute; left: var(--colx); width: var(--colw); height: calc(var(--m) * 2560); pointer-events: none; }
.fs-layer > * { pointer-events: auto; }
.fs-top { top: var(--sat, 0px); }
.fs-bottom { bottom: var(--sab, 0px); }
.fs-backdrop { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.fs-blur { display: none; position: absolute; inset: -24px; background: center / cover no-repeat; filter: blur(14px) brightness(.85); }
body[data-wide="1"] .fs-blur { display: block; }
/* 4 Nov: the exported backdrops overhang the mock frame (home_bg: 111 mock px a side, opaque sea in its lower
   half); Figma clips them to the frame, so on a column narrower than the window the sides show the blur only */
body[data-wide="1"] .fs-backdrop > .fs-layer { clip-path: inset(-100vh 0); }
.fs-bgimg { position: absolute; background: 0 0 / 100% 100% no-repeat; }
.fs-layer button { background-color: transparent; padding: 0; margin: 0; cursor: pointer; font: inherit; touch-action: manipulation; }
/* (5 Nov: the border reset skips kit buttons: `border: 0` here outranked .btn's 9-slice (its slice fell back to 100 %), so a .btn on a
   Figma screen, the Base bar's TRAVEL / CLAIM, drew only the art's four corners) */
.fs-layer button:not(.btn) { border: 0; }
.fs-layer [hidden] { display: none !important; }

/* ---- Home (src/home.js; mock 265:156) ---- */
#s-home { overflow: hidden; }
.fh-tile { cursor: pointer; }
.fh-tile:active { transform: scale(.96); }
.fh-tile canvas { position: absolute; inset: 8%; width: 84% !important; height: auto !important; image-rendering: pixelated; }
.fh-tname { white-space: pre-line; line-height: 1.05; }
.fh-badge { left: calc(var(--m) * 120); top: calc(var(--m) * -8); width: calc(var(--m) * 46); height: calc(var(--m) * 46); }
.fh-bird { pointer-events: none !important; }
.fh-bird .hb-bob, .fh-bird .hb-wing { position: absolute; inset: 0; }
.fh-bird canvas { image-rendering: pixelated; }
.fh-hero { z-index: 1; }
.fh-play .fh-dots { position: absolute; inset: 0; pointer-events: none; }
.fh-sub { letter-spacing: 0; }
.fh-slot { cursor: pointer; }
.fh-slot.incoming .fh-sart { visibility: hidden; }
.fh-slot.landed .fh-sart { animation: fhLand .35s cubic-bezier(.2, 1.6, .4, 1); }
@keyframes fhLand { from { transform: scale(1.15, .85); } }
.fh-slot.opening .fh-sart, .fh-slot.ready .fh-sart { animation: none; }
.fh-slot.ready .fh-sart { animation: fhBob 1.2s ease-in-out infinite; }
@keyframes fhBob { 50% { transform: translateY(calc(var(--m) * -10)); } }
.fh-plus, .fh-lock { color: #7ed4ff; }
/* 5 Nov (mock Rectangle 102): a waiting chest's unlock-time tab, hanging from the slot's top edge */
.fh-tab { background: #0061a9; border-radius: 0 0 calc(var(--m) * 15) calc(var(--m) * 15); }
.fh-tabtime { justify-content: flex-start; text-align: left; }
.fh-lock { white-space: normal; line-height: 1.15; }
.fh-notice { --fs: 26; --sw: 3; display: flex; align-items: center; justify-content: center; border-radius: 999px; background: #000c; padding: 0 calc(var(--m) * 20); font-size: calc(var(--m) * 26); }
.fh-dot { pointer-events: none; }
@media (prefers-reduced-motion: reduce) { .fh-slot.ready .fh-sart { animation: none; } }

/* ---- Build / Base (src/base.js; mock 269:445): the stage is the bottom-anchored mock frame in island px (--u) ---- */
#s-base { overflow: hidden; background: linear-gradient(#5fbaf5, #8fd0f7 40%, #c5dffb); }
#s-base .base-stage { position: absolute; left: var(--colx); width: var(--colw); bottom: var(--sab, 0px); top: auto; height: calc(var(--m) * 2560);
  -webkit-mask-image: none; mask-image: none;
  background: url("assets/ui/fig/base_fade.5ac39a68.webp") 0 calc(var(--m) * 2095) / 100% calc(var(--m) * 655) no-repeat, url("assets/ui/fig/base_bg.422da06f.webp") 0 calc(var(--m) * -201) / 100% auto no-repeat, transparent; }
#s-base .base-stage[data-world="2"] { background: url("assets/base/w2/bg.a40c4614.webp") 0 calc(var(--u) * 70) / 100% auto no-repeat, transparent; }
#s-base .base-stage[data-world="3"] { background: url("assets/base/w3/bg.659f7e06.webp") 0 calc(var(--u) * 70) / 100% auto no-repeat, transparent; }
#s-base .base-bottom { --u: calc(var(--m) * 1440 / 853); z-index: 2; }
.fb-card { cursor: pointer; transition: transform .15s; }
.fb-card.sel { transform: translateY(calc(var(--m) * -14)); }
.fb-card.sel > .fimg:first-child { filter: drop-shadow(0 0 calc(var(--m) * 10) #ffd23a) drop-shadow(0 0 calc(var(--m) * 4) #ffd23a); }
.fb-card.shake { animation: shake .4s; }
/* 5 Nov (mock Build, ARENA): a damaged landmark shows at 30 % under the wrench, DAMAGED! in red where its stage dots were */
.fb-card.damaged .fb-thumb { opacity: .3; }
.fb-dmg { color: #ff7272; }
.fb-wrench, .fb-logtile { pointer-events: none; }
/* 5 Nov (mock Build, Group 17 / Rectangle 24): ACTIVITY LOG on the rail's navy tile (#223052 at 20 %) */
.fb-logtile { border-radius: calc(var(--m) * 20); background: rgba(34, 48, 82, .2); }
.fb-log { cursor: pointer; }
.fb-log:active { transform: scale(.96); }
.fb-log:focus-visible { outline: calc(var(--m) * 8) solid #fff; outline-offset: calc(var(--m) * 2); border-radius: calc(var(--m) * 20); }
.fb-thumb { width: calc(var(--m) * 200); height: calc(var(--m) * 190); object-fit: contain; }
.fb-maxed { color: #4ac3ff; }
.fb-price.poor { filter: saturate(.35) brightness(.95); }
.fb-price .ico-svg { display: block; }
.fb-price .ico-svg svg { width: 100%; height: 100%; }
#s-base .bp-head { display: flex; align-items: center; justify-content: space-between; gap: calc(var(--m) * 20); padding: 0 calc(var(--m) * 16) 0 calc(var(--m) * 34); border-radius: 999px; background: #0b2350e6; border: calc(var(--m) * 5) solid #000; }
#s-base .bp-head .wb-foot { display: flex; align-items: center; justify-content: space-between; gap: calc(var(--m) * 20); width: 100%; }
#s-base .bp-head .wb-goal { font: 700 calc(var(--m) * 30)/1.1 var(--font-ui); color: #fff; white-space: normal; }
#s-base .bp-head .btn { font-family: var(--font-ui); font-weight: 700; font-size: calc(var(--m) * 34); padding: calc(var(--m) * 10) calc(var(--m) * 30); }
/* 5 Nov (Basil): the bar's TRAVEL / CLAIM is the cards' green price button (src/base.js), a flex item at the bar's right end */
#s-base .bp-head .wb-travel { position: relative; flex: none; }

/* ---- Pinball (src/pinball.js, render.js; mock 270:683): the machine is canvas, these sit on it ---- */
#hits .pin-rail { position: absolute; pointer-events: none; --bw: calc(var(--m) * 24); }
#hits .pin-tile { position: absolute; pointer-events: auto; background: transparent; border: 0; padding: 0; cursor: pointer; color: #fff; font-size: inherit; }
#hits .pin-tile .pt-ico { position: absolute; left: 0; top: 0; width: 100%; height: 87%; }
#hits .pin-tile b { position: absolute; left: -12%; right: -12%; top: 75%; text-align: center; line-height: 1.05; font-size: 1em; -webkit-text-stroke: .32em #000; paint-order: stroke fill; }
#hits .pin-tile:active { transform: scale(.96); }
#hits .fig-x2 { border: 0; border-radius: 0; box-shadow: none; padding: 0; background: var(--img) 0 0 / 100% 100% no-repeat !important; color: #fff; }
#hits .fig-x2::before, #hits .fig-x2::after { content: none; }
#hits .fig-x2 b { position: absolute; inset: 0; opacity: 0; pointer-events: none; }   /* 5 Nov: the label is in the dial's art */
#hits .fig-x2 .x-prev { position: absolute; inset: 0; background: var(--img) 0 0 / 100% 100% no-repeat; animation: xPrevOut .22s ease-out forwards; pointer-events: none; }
@keyframes xPrevOut { from { opacity: 1; } to { opacity: 0; } }
#hits .fig-x2:active { transform: translateY(2px); filter: brightness(.95); }
#hits .fig-x2.bump { animation: hudPump .25s; }

/* ---- Birds: one page (src/birdspage.js; mock 281:409) ---- */
#s-birds { overflow: hidden; }
.fbr-scroll { position: absolute; left: var(--colx); width: var(--colw); top: calc(var(--sat, 0px) + var(--m) * 153); bottom: calc(var(--sab, 0px) + var(--m) * 222);
  overflow-x: hidden; overflow-y: auto; -webkit-overflow-scrolling: touch; touch-action: pan-y; overscroll-behavior: contain; scrollbar-width: none; }
.fbr-scroll::-webkit-scrollbar { display: none; }
.fbr-page { position: relative; width: 100%; }
.fbr-page button { background-color: transparent; border: 0; padding: 0; margin: 0; font: inherit; cursor: pointer; touch-action: pan-y; }
.fbr-page .fbtn { background: var(--img) 0 0 / 100% 100% no-repeat; }
.fbr-page .fbtn:disabled { filter: grayscale(.75) brightness(.92); }
.fbr-equip.done:disabled { filter: none; opacity: .85; }
.fbr-arc { position: absolute; inset: 0; }
.fbr-arc svg { width: 100%; height: 100%; display: block; transform: rotate(-90deg); }
.fbr-arc circle { fill: none; stroke: #3ec41e; stroke-width: 9; stroke-linecap: round; stroke-dasharray: 0 100; transition: stroke-dasharray .4s; }
.fbr-hero canvas { image-rendering: pixelated; }
.fbr-bird { cursor: pointer; transition: transform .12s; }
.fbr-bird:active { transform: scale(.97); }
.fbr-bird.sel > .fimg:first-child { filter: drop-shadow(0 0 calc(var(--m) * 8) #ffd23a) drop-shadow(0 0 calc(var(--m) * 4) #ffd23a); }
.fbr-bird canvas { image-rendering: pixelated; }
.fbr-bird.locked canvas { opacity: .9; }
.fbr-pill.r2 { filter: hue-rotate(-75deg) saturate(1.2); }   /* Rare: the Epic pill turned blue (the mock shows Common and Epic) */
.fbr-rar[data-r="2"] .fimg { filter: hue-rotate(-75deg) saturate(1.2); }
.fbr-task { cursor: pointer; }
.fbr-task:disabled { cursor: default; }
.fbr-task .fbr-tick[hidden] { display: none; }
.fbr-ttxt { white-space: pre-line; line-height: 1.1; }
.fbr-chest.locked .fbr-task { filter: saturate(.4); }
.fbr-mbadge[hidden] { display: none; }

/* ---- Race HUD (src/race/race.js; mock 289:436): in the race stage's design px (--u = mock px × 1125/1440) ---- */
/* 5 Nov: the race world is clipped to the portrait column (race.js fitRace); black bars outside it on wide windows */
#s-race { background: #000; }
/* 5 Nov (Basil: the top UI not aligned): on tall phones the HUD rises with the stage's lift to the screen's top (30 Oct), under the notch */
.race-stage .race-top { left: 0; right: 0; top: calc(env(safe-area-inset-top, 0px) - var(--race-lift, 0px)); height: 0; }
.race-stage .race-pause { position: absolute; left: calc(var(--u) * 33.6); top: calc(var(--u) * 33.6); width: calc(var(--u) * 87.5); height: calc(var(--u) * 87.5);
  border: 0; padding: 0; border-radius: 50%; box-shadow: none; font-size: 0; color: transparent; pointer-events: auto; cursor: pointer;
  background: url("assets/ui/fig/tb_round.eea037d6.webp") 0 0 / 100% 100% no-repeat; }
.race-stage .race-pause::before, .race-stage .race-pause::after { content: ""; position: absolute; top: calc(var(--u) * 21); width: calc(var(--u) * 10.8); height: calc(var(--u) * 41); border-radius: calc(var(--u) * 3); background: #fff; box-shadow: 0 0 0 calc(var(--u) * 1.6) #000; }
.race-stage .race-pause::before { left: calc(var(--u) * 28); }
.race-stage .race-pause::after { left: calc(var(--u) * 43.6); }
.race-stage .race-score { position: absolute; left: 0; right: 0; top: calc(var(--u) * 39); text-align: center; font: 700 calc(var(--u) * 100)/1 var(--font-ui); color: #fff;   /* (mock '12': 29, 170 tall line, centre 114) */
  -webkit-text-stroke: calc(var(--u) * 15.6) #000; paint-order: stroke fill; text-shadow: none; }
/* 5 Nov (Basil: the count overlapping the racer strip): the placement HUD's viewport size (arcade.css v0.20, #s-race.placehud, up
   to 66 px) outranked the mock's 100 on every real race, so on a wide window (a small --u) the count ran into the strip */
#s-race.placehud .race-stage .race-score { font-size: calc(var(--u) * 100); }
.race-stage .race-left { position: absolute; left: 0; right: 0; top: calc(var(--u) * 292); text-align: center;   /* 5 Nov (Basil): clear of the strip, which ends at 273 (was 268, its top inside the strip) */ font: 700 calc(var(--u) * 31.25)/1 var(--font-ui); color: #fff;
  -webkit-text-stroke: calc(var(--u) * 6.25) #000; paint-order: stroke fill; background: none; border: 0; padding: 0;
  z-index: 1; pointer-events: none; }   /* 5 Nov: over the racer strip, as in the mock (the strip comes later in the HUD and covered the count's top) */
.race-stage .race-roster { transform: none; right: auto; margin: 0; left: calc(var(--u) * 152.3); top: calc(var(--u) * 195.3 + env(safe-area-inset-top, 0px) - var(--race-lift, 0px)); width: calc(var(--u) * 820.3); height: calc(var(--u) * 78.1); padding: 0 calc(var(--u) * 20);
  display: flex; align-items: center; justify-content: space-between; gap: 0; border-radius: calc(var(--u) * 15.6); background: url("assets/ui/fig/race_strip.9c327601.webp") 0 0 / 100% 100% no-repeat; border: 0; box-shadow: none; }
.race-stage .race-roster .rr { width: calc(var(--u) * 71); height: calc(var(--u) * 48.4); position: relative; overflow: visible; }
/* 5 Nov: the slot is the mock's bird body (92 x 63); the sprite cell (28 x 26, body 22 x 15 at 2, 10) is placed so the body fills it, as birdInBox does */
.race-stage .race-roster .rr canvas { position: absolute; left: 50%; top: 50%; width: calc(100% * 28 / 22) !important; height: auto !important; max-width: none; transform: translate(-46.43%, -67.31%); }
.race-stage .race-roster .rr.you { outline: none; }
.race-stage .race-feed { left: 0; right: 0; top: calc(var(--u) * 1821); bottom: auto; gap: calc(var(--u) * 10); }
.race-stage .race-feed .fe { min-width: calc(var(--u) * 463.3); height: calc(var(--u) * 78.1); padding: 0 calc(var(--u) * 26); border-radius: calc(var(--u) * 15.6); justify-content: center;
  background: url("assets/ui/fig/race_pill.8fdd9d36.webp") 0 0 / 100% 100% no-repeat; font: 700 calc(var(--u) * 28.1)/1 var(--font-ui); color: #fff; -webkit-text-stroke: calc(var(--u) * 6.25) #000; paint-order: stroke fill; gap: calc(var(--u) * 12); }
.race-stage .race-feed .fe b { color: #fff; }
.race-stage .race-feed .fe canvas { width: calc(var(--u) * 50) !important; }

/* ---- Race results (src/race/resultview.js; mock 289:634 / 289:1229): mock px on the race stage ---- */
@font-face { font-family: "Changa One"; font-style: italic; font-weight: 400; font-display: swap; src: url(/fonts/changa-one-latin-400-italic.woff2) format("woff2"); }
.race-stage .race-result { position: absolute; inset: 0; z-index: 5; background: none; display: block; padding: 0; }
.race-stage .race-result[hidden] { display: none; }
.fres { position: absolute; left: 0; top: 0; width: calc(var(--u) * 1125); height: calc(var(--u) * 2000); --m: calc(var(--u) * 1125 / 1440); color: #fff; overflow: visible;
  animation: fresIn .35s cubic-bezier(.2, 1.3, .4, 1); }
@keyframes fresIn { from { opacity: 0; transform: scale(1.04); } }
/* 5 Nov: the parts build up one by one (resultview.js enter(): --d is each part's delay): the balances, the place stamping
   down from large (the 'stamp' sound lands with it), the sub line, the nest and the winnings, the reward cards left to
   right, the note, the mastery card, the Bond / Shine pill, then the buttons rising from below; ~1.4 s in all */
.fres .fres-in { animation: fresPop .45s cubic-bezier(.2, 1.4, .4, 1) both; animation-delay: var(--d, 0ms); }
@keyframes fresPop { from { opacity: 0; transform: scale(.6); } }
.fres .fres-in.fres-drop { animation-name: fresDrop; animation-duration: .4s; animation-timing-function: cubic-bezier(.3, 0, .2, 1); }
@keyframes fresDrop { from { opacity: 0; transform: scale(2.2); } 70% { opacity: 1; transform: scale(.94); } }
.fres .fres-in.fres-rise { animation-name: fresRise; }
@keyframes fresRise { from { opacity: 0; transform: translateY(calc(var(--m) * 160)); } }
@media (prefers-reduced-motion: reduce) { .fres .fres-in { animation: none; } }
.fres-bg { box-shadow: 0 0 0 100vmax #ffbe46; }
.fres button { background-color: transparent; border: 0; padding: 0; margin: 0; font: inherit; cursor: pointer; }
.fres .fbtn { background: var(--img) 0 0 / 100% 100% no-repeat; }
.fres-place .fp { position: absolute; inset: 0; display: flex; justify-content: center; align-items: flex-start; font: italic 400 calc(var(--m) * 318)/1 "Changa One", var(--font-ui); letter-spacing: 0; }
.fres-place .fp b { font-weight: 400; }
.fres-place .fp i { font-style: italic; font-size: calc(var(--m) * 136.4); margin: calc(var(--m) * 25) 0 0 calc(var(--m) * -4); }
.fres-place .fp.edge { color: #0d47c8; -webkit-text-stroke: calc(var(--m) * 16) #062d6e; paint-order: stroke fill; transform: translate(calc(var(--m) * 5), calc(var(--m) * 9)); }
.fres-place .fp.face b, .fres-place .fp.face i { background: linear-gradient(0deg, #ffffff 29%, #8fb3f5 50%, #ffffff 70%); -webkit-background-clip: text; background-clip: text; color: transparent; }
.fres-subrow { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; gap: calc(var(--m) * 12); --fs: 32; --sw: 4; font-size: calc(var(--m) * 32); }
.fres-pipe { display: inline-block; width: calc(var(--m) * 34); height: calc(var(--m) * 44); background: var(--img) 0 0 / 100% 100% no-repeat; -webkit-text-stroke: 0; }
.fres-note { color: #fff; }
.fres-bird canvas { image-rendering: pixelated; }
.fres-rv .btn { width: 100%; height: 100%; font-family: var(--font-ui); font-weight: 700; font-size: calc(var(--m) * 34); }
.fres .rs-actions .rs-decide { position: absolute; left: calc(var(--m) * 120); right: calc(var(--m) * 120); bottom: 0; display: flex; flex-direction: column; gap: calc(var(--m) * 14); align-items: center;
  padding: calc(var(--m) * 24); border-radius: calc(var(--m) * 30); background: #0b2350f0; border: calc(var(--m) * 5) solid #000; font-family: var(--font-ui); }
/* (the old results card's .rs / .rs-actions rules in style.css and arcade.css don't apply to the rebuilt view) */
.race-stage .race-result .rs.fres { width: calc(var(--u) * 1125); height: calc(var(--u) * 2000); max-height: none; padding: 0; margin: 0; background: none; border: 0; border-radius: 0; box-shadow: none;
  display: block; overflow: visible; text-align: left; gap: 0; }
.race-stage .race-result .fres .rs-actions { position: absolute; display: block; margin: 0; padding: 0; background: none; border: 0; border-radius: 0; width: calc(var(--m) * 1440); bottom: auto; flex: none; gap: 0; }
.race-stage .race-result .fres .rs-actions .fbtn { position: absolute; width: auto; }

/* ---- Chest opening (src/chestfx.js; mock 289:1328) ---- */
.chestfx.fchest { position: fixed; inset: 0; z-index: 60; background: #6a2fd0; overflow: hidden; display: block; padding: 0; animation: fcxIn .25s ease-out; }
@keyframes fcxIn { from { opacity: 0; } }
.chestfx.fchest.out { opacity: 0; transition: opacity .2s; }
.fcx-bg { position: absolute; inset: 0; background: var(--img) center / cover no-repeat; }
.fcx-frame { position: absolute; left: var(--colx); width: var(--colw); bottom: var(--sab, 0px); height: calc(var(--m) * 2560); }
.fcx-frame button { background-color: transparent; border: 0; padding: 0; margin: 0; font: inherit; cursor: pointer; color: #fff; }
.fcx-frame .fbtn { background: var(--img) 0 0 / 100% 100% no-repeat; }
.fcx-open { opacity: 0; transform: scale(.7); transition: opacity .25s, transform .35s cubic-bezier(.2, 1.6, .4, 1); }
.fchest.opened .fcx-open { opacity: 1; transform: none; }
.fchest.opened .fcx-closed { opacity: 0; transform: scale(1.2); transition: opacity .2s, transform .25s; }
.fchest.shake .fcx-closed { animation: fcxShake .56s; }
@keyframes fcxShake { 15% { transform: rotate(-6deg) scale(1.03); } 35% { transform: rotate(6deg) scale(1.06); } 55% { transform: rotate(-5deg) scale(1.08); } 75% { transform: rotate(4deg) scale(1.1); } }
.fchest[data-tier="silver"] .fcx-open { filter: hue-rotate(185deg) saturate(.75); }   /* (the mock's open chest is gold) */
.fchest[data-tier="bronze"] .fcx-open { filter: sepia(.5) saturate(.8) brightness(.85); }
.fcx-card { animation: fcxCard .35s cubic-bezier(.2, 1.6, .4, 1); }
.fcx-card.still { animation: none; }
@keyframes fcxCard { from { transform: translateY(calc(var(--m) * 380)) scale(.4); opacity: 0; } }
.fcx-skip { --fs: 30; --sw: 4; display: flex; align-items: center; justify-content: center; font-size: calc(var(--m) * 30); opacity: .85; }
.fcx-continue[hidden], .fcx-skip[hidden] { display: none; }

/* ---- the kit on every other screen (Figma UI rebuild): Store, sheets, modals, tutorial, arcade ---- */
:root { --font: var(--font-ui); }   /* one face everywhere (was Lilita One) */
/* buttons: the four kit buttons of the Figma Components page (Buttons 3:32), 9-sliced */
.btn { font-family: var(--font-ui); font-weight: 700; color: #fff; background: none !important; box-shadow: none !important; border-radius: 0 !important;
  border-style: solid !important; border-color: transparent !important; border-width: 4px !important; border-image: url("assets/ui/fig/btn_k_green.1b399746.webp") 64 64 70 64 fill / 15px 16px 17px 16px stretch;
  -webkit-text-stroke: 4px #000; paint-order: stroke fill; text-shadow: none; }
.btn.gold { border-image-source: url("assets/ui/fig/btn_k_yellow.52de94f7.webp"); }
.btn.blue, .btn.navy { border-image-source: url("assets/ui/fig/btn_k_blue.45e1bc88.webp"); }
.btn.grey { border-image-source: url("assets/ui/fig/btn_k_gray.8fe66287.webp"); }
/* 5 Nov: .red too (Settings RESET, the raid's ATTACK!): the kit has no red button, so .red fell back to green */
.btn.danger, .btn.red { border-image-source: url("assets/ui/fig/btn_k_yellow.52de94f7.webp"); filter: hue-rotate(-38deg) saturate(1.4); }
.btn.sm { border-image-width: 11px 12px 13px 12px; -webkit-text-stroke-width: 3px; }
.btn:active:not(:disabled) { transform: translateY(2px); filter: brightness(.93); box-shadow: none; }
.btn:disabled { filter: grayscale(.65) brightness(.92); }
/* modals: the mock's popup (Frame 14: the blue panel 289:1543 around a light panel 289:1545), the title white on top */
.card { background: none !important; box-shadow: none; border-radius: 0; border-style: solid !important; border-color: transparent !important; border-width: 18px !important;
  border-image: url("assets/ui/fig/pop_panel.ea159202.webp") 40 40 60 40 fill / 14px 14px 20px 14px stretch; }
.card header { background: none !important; border: 0 !important; border-radius: 0; padding: 2px 8px 8px; }
.card h2 { font-family: var(--font-ui); font-weight: 700; color: #fff; -webkit-text-stroke: 6px #000; paint-order: stroke fill; text-shadow: none; letter-spacing: 0; font-size: clamp(22px, 6vmin, 34px); }
.card:not(.navy) .body { border-style: solid; border-color: transparent; border-width: 10px; border-image: url("assets/ui/fig/pop_inner.5a84a9f8.webp") 30 fill / 12px stretch; margin: 0 2px 2px; }
.card.navy .body { background: #0b2350eb; border-radius: 14px; margin: 0 2px 2px; }
/* 5 Nov: the chest card, Frames 14 / 15 (289:1538 / 324:463), in mock px (--m): the blue card 850 wide (#01a7f9, a 6 px
   outline, the darker foot), the title, the light panel with the chest, then 750 x 130 rows 30 apart (src/chestui.js).
   How the mock draws its kit (measured on the Figma render, 5 Nov): an inner shadow is cast from the outline's outer edge,
   so the outline hides that much of it (the panel's 30 px foot under a 6 px outline shows 24; a Base Button's 10 px light
   top and 15 px dark foot under its 5 px outline show 5 and 10), and every Base Button layer is turned 180°, so its
   gradient reads bottom to top (the yellow button is yellow on top, orange at the foot). */
.card.chest-card { width: calc(var(--m) * 850); max-width: none; max-height: none; overflow: visible; position: relative; box-sizing: border-box;
  padding: calc(var(--m) * 28) calc(var(--m) * 50) calc(var(--m) * 68); background: #01a7f9 !important; border: 0 !important; border-image: none !important;
  border-radius: calc(var(--m) * 20) !important; box-shadow: 0 0 0 calc(var(--m) * 6) #000, inset 0 calc(var(--m) * -24) 0 #0158bc !important; }
.card.chest-card header { position: static !important; padding: 0 !important; margin: 0 0 calc(var(--m) * 27); }
.card.chest-card h2 { padding: 0; font-size: calc(var(--m) * 48); line-height: calc(var(--m) * 45); -webkit-text-stroke-width: calc(var(--m) * 12); }
.card.chest-card .xbtn, .card.attack-card .xbtn { right: calc(var(--m) * -25); top: calc(var(--m) * -50); transform: none; width: calc(var(--m) * 100); height: calc(var(--m) * 100); border: 0; border-radius: calc(var(--m) * 15);
  color: transparent; font-size: 0; filter: none;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 56.69 56.69'%3E%3Cpath d='M7.55 7.55 41.14 41.14M41.14 7.55 7.55 41.14' stroke='%23000' stroke-width='23.1' stroke-linecap='round'/%3E%3Cpath d='M7.55 7.55 41.14 41.14M41.14 7.55 7.55 41.14' stroke='%23fff' stroke-width='15.1' stroke-linecap='round'/%3E%3C/svg%3E") center / 56.69% no-repeat, linear-gradient(#ff5f5f, #c40000) !important;
  box-shadow: 0 0 0 calc(var(--m) * 5) #000, inset 0 calc(var(--m) * -10) 0 #780000, inset 0 calc(var(--m) * 5) 0 #fff !important; }
/* (the X: the mock's Union, two 15 px bars with round ends corner to corner of a 48.69 px square, a 4 px outline) */
.card.chest-card .body, .card.attack-card .body { display: block; padding: 0; margin: 0 !important; border: 0 !important; border-image: none !important; background: none !important; }
/* 5 Nov: the return summary, "Your base was attacked!" (Frame 16, 328:990), in mock px (--m) from the card's top-left: the
   blue card 940 wide (#01a7f9, a 6 px outline, the darker foot) over the swords (405 x 394 at (268, -319)), the X at
   (860, -20), the yellow title in its 539 x 127 box at (201, 25), the SHIELDS USED pill 537 x 100 at (207, 170), then
   838 x 167 rows 20 apart from (51, 310): five show, more scroll. The backdrop is the mock's 60 % black. */
.modal:has(> .card.attack-card), .modal:has(> .card.flappy-card) { background: rgba(0, 0, 0, .6); }
.card.attack-card, .card.flappy-card { width: calc(var(--m) * 940); max-width: none; max-height: none; overflow: visible; position: relative; box-sizing: border-box; isolation: isolate;
  padding: calc(var(--m) * 25) calc(var(--m) * 51) calc(var(--m) * 79); margin-bottom: calc(var(--m) * 90);
  background: none !important; border: 0 !important; border-image: none !important; border-radius: calc(var(--m) * 20) !important; box-shadow: none !important; }
.card.attack-card::before, .card.flappy-card::before { content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit;
  background: #01a7f9; box-shadow: 0 0 0 calc(var(--m) * 6) #000, inset 0 calc(var(--m) * -24) 0 #0259bc; }
.card.attack-card .xbtn { right: calc(var(--m) * -20); top: calc(var(--m) * -20); }
/* 5 Nov: the new Flappy card, "New Flappy unlocked!" (Frame 17, 328:1115): the same blue card, 940 x 930, its parts placed
   in mock px by src/pinball.js showFlappies (title, COLLECTED, the light panel with the name, the Flappy, the rarity pill, CONTINUE) */
.card.flappy-card { height: calc(var(--m) * 930); padding: 0; }
.fl-title { color: #fffb0c; }
.fl-panel { border-radius: calc(var(--m) * 20); background: linear-gradient(#fff, #9de4fd); }
.fl-bird, .fl-coin, .flappy-card .fbr-pill { pointer-events: none; }
.fl-bird canvas { image-rendering: pixelated; }
.fl-coin { object-fit: contain; }
.fl-go { padding: 0; border: 0; font: inherit; cursor: pointer; }
.card.attack-card:focus { outline: none; }
.card.attack-card header { position: static !important; padding: 0 !important; margin: 0; }
.card.attack-card h2 { box-sizing: border-box; display: flex; align-items: center; justify-content: center; width: calc(var(--m) * 539); height: calc(var(--m) * 127); margin: 0 auto; padding: 0;
  color: #fffb0c; font-size: calc(var(--m) * 48); line-height: calc(var(--m) * 64); -webkit-text-stroke-width: calc(var(--m) * 12); }
.ac-swords { position: absolute; z-index: -2; left: calc(var(--m) * 268); top: calc(var(--m) * -319); width: calc(var(--m) * 405); height: calc(var(--m) * 394); pointer-events: none; user-select: none; }
.ac-pill { position: relative; width: calc(var(--m) * 537); height: calc(var(--m) * 100); margin: calc(var(--m) * 18) 0 0 calc(var(--m) * 156); border-radius: calc(var(--m) * 20); background: #006dba; }
.ac-shield { position: absolute; left: calc(var(--m) * 50); top: calc(var(--m) * 10); width: calc(var(--m) * 71); height: calc(var(--m) * 80); }
.ac-used { position: absolute; left: calc(var(--m) * 133); top: calc(var(--m) * 35); width: calc(var(--m) * 342); height: calc(var(--m) * 30); display: flex; align-items: center; justify-content: center; --fs: 40; --sw: 4; }
/* the list: 32 px wider than the rows, so a scrollbar sits in the card's right margin, not on the rows */
.ac-list { display: flex; flex-direction: column; gap: calc(var(--m) * 20); width: calc(var(--m) * 870); max-height: calc(var(--m) * 915); margin-top: calc(var(--m) * 40);
  overflow-x: hidden; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; scrollbar-color: #006dba transparent; }
.ac-row { position: relative; flex: none; width: calc(var(--m) * 838); height: calc(var(--m) * 167); border-radius: calc(var(--m) * 20); background: linear-gradient(#fff, #9de4fd); text-align: left; }
.ac-av { position: absolute; left: calc(var(--m) * 34); top: calc(var(--m) * 34); width: calc(var(--m) * 100); height: calc(var(--m) * 100); border-radius: 50%; overflow: hidden;
  background: #000; box-shadow: 0 0 0 calc(var(--m) * 6) #5ac2e6; }
.ac-av canvas { display: block; width: 100%; height: 100%; }
.ac-t { position: absolute; left: calc(var(--m) * 166); display: flex; align-items: center; }
.ac-name { top: calc(var(--m) * 32); height: calc(var(--m) * 30); --fs: 40; --sw: 4; }
.ac-what { top: calc(var(--m) * 82); height: calc(var(--m) * 18); --fs: 24; --sw: 4; color: #ff7272; }
.ac-row.blocked .ac-what { color: #01a7f9; }
.ac-when { top: calc(var(--m) * 117); height: calc(var(--m) * 18); --fs: 24; color: #006dba; }
.ac-rv { position: absolute; left: calc(var(--m) * 553); top: calc(var(--m) * 36); width: calc(var(--m) * 266); height: calc(var(--m) * 96); padding: 0; border: 0; font: inherit; }
.ac-rvt { position: absolute; left: calc(var(--m) * 19); top: 0; width: calc(var(--m) * 231); height: calc(var(--m) * 88); display: flex; align-items: center; justify-content: center; --fs: 32; --sw: 4; }
.cc-art { height: calc(var(--m) * 460); box-sizing: border-box; padding-top: calc(var(--m) * 60); border-radius: calc(var(--m) * 20); background: linear-gradient(#fff, #9de4fd); }
.cc-art img { display: block; margin: 0 auto; width: calc(var(--m) * 375); height: calc(var(--m) * 341); object-fit: contain; }
.cc-list { display: flex; flex-direction: column; gap: calc(var(--m) * 30); margin-top: calc(var(--m) * 42); }
.cc-row { position: relative; display: block; width: 100%; height: calc(var(--m) * 130); padding: 0; border: 0; border-radius: calc(var(--m) * 15); cursor: pointer;
  font: 700 calc(var(--m) * 40) / 1 var(--font-ui); color: #fff; -webkit-text-stroke: calc(var(--m) * 10) #000; paint-order: stroke fill; }
.cc-row.green { background: linear-gradient(#50de06, #0ec12a); box-shadow: 0 0 0 calc(var(--m) * 5) #000, inset 0 calc(var(--m) * -10) 0 #038623, inset 0 calc(var(--m) * 5) 0 #fff; }
.cc-row.yellow { background: linear-gradient(#f9e51a, #fc9407); box-shadow: 0 0 0 calc(var(--m) * 5) #000, inset 0 calc(var(--m) * -10) 0 #af3f01, inset 0 calc(var(--m) * 5) 0 #fff; }
.cc-row:active:not(:disabled) { transform: translateY(calc(var(--m) * 4)); filter: brightness(.93); }
.cc-row:disabled, .cc-row.poor { filter: grayscale(.75) brightness(.92); }
.cc-row:disabled { cursor: default; }
.cc-pill { position: absolute; left: calc(var(--m) * 20); top: calc(var(--m) * 22); width: calc(var(--m) * 280); height: calc(var(--m) * 80); border-radius: calc(var(--m) * 45); background: #12a435; }
.cc-row.yellow .cc-pill { background: #db8325; }
.cc-ico { position: absolute; left: calc(var(--m) * 25); top: calc(var(--m) * 6); width: calc(var(--m) * 66); height: calc(var(--m) * 66); }
.cc-ico.coin { left: calc(var(--m) * 24); top: calc(var(--m) * 5); width: calc(var(--m) * 68); height: calc(var(--m) * 69); }
.cc-ico.ad { top: calc(var(--m) * 13); width: calc(var(--m) * 68); height: calc(var(--m) * 55); }
.cc-val { position: absolute; left: calc(var(--m) * 93); top: calc(var(--m) * 19); width: calc(var(--m) * 152); height: calc(var(--m) * 43); display: grid; place-items: center; font: inherit; }
.cc-lbl { position: absolute; left: calc(var(--m) * 278); top: calc(var(--m) * 21); width: calc(var(--m) * 407); height: calc(var(--m) * 88); display: grid; place-items: center; }
.cc-row.cc-timer { display: flex; align-items: center; justify-content: center; gap: calc(var(--m) * 12); background: #0072bf; cursor: default; }
.cc-timer .cc-ico { position: static; }
.cc-timer b { font: inherit; }
/* sheet titles (Store, Trophy Road, World Map, Daily, Events …): the mock's white outlined titles */
.sheet-head h1 { font-family: var(--font-ui); font-weight: 700; color: #fff; text-shadow: none; -webkit-text-stroke-color: #000; }
/* the tutorial bubble: the kit's light panel with an outline */
.guide-bubble { background: #fff; border: 4px solid #000; border-radius: 18px; box-shadow: 0 6px 0 #0006; }
.gb-step { font-family: var(--font-ui); font-weight: 700; }

/* ---- 5 Nov: the mock's yellow button (Base Button): yellow → orange, a dark foot, a light top edge, a 5 px outline ---- */
.fy-btn { border-radius: calc(var(--m) * 15); background-image: linear-gradient(#f9e51a, #fc9407);
  box-shadow: 0 0 0 calc(var(--m) * 5) #000, inset 0 calc(var(--m) * -10) 0 #af3f01, inset 0 calc(var(--m) * 5) 0 #fff; }
.fy-btn:focus-visible { outline: calc(var(--m) * 8) solid #fff; outline-offset: calc(var(--m) * 6); }
button.fy-btn { cursor: pointer; }
button.fy-btn:active:not(:disabled) { filter: brightness(.93); transform: translateY(calc(var(--m) * 3)); }
button.fy-btn:disabled { filter: grayscale(.7) brightness(.92); cursor: default; }

/* ---- 5 Nov: the Store (mock frame 'Store' 324:608) ---- */
.fst-starter, .fst-sec, .fst-card { pointer-events: none; }
.fst-starter > button, .fst-card > button { pointer-events: auto; }
.fst-panel { border-radius: calc(var(--m) * 35);
  background: linear-gradient(rgba(0, 0, 0, .37), rgba(0, 0, 0, 0) 25.6%), linear-gradient(rgba(0, 0, 0, .2), rgba(0, 0, 0, .2)), var(--img) center / cover no-repeat; }
.fst-once { background: rgba(0, 0, 0, .3); border-radius: calc(var(--m) * 10); }
.fst-item { background: rgba(0, 0, 0, .4); border-radius: calc(var(--m) * 13.57); box-shadow: 0 0 0 calc(var(--m) * 4.8) #000; }
.fst-epic { background: #c248fa; border-radius: calc(var(--m) * 19); box-shadow: 0 0 0 calc(var(--m) * 4) #8108ba; }
.fst-bird { image-rendering: pixelated; }
.fst-art, .fst-frame, .fst-bird { object-fit: contain; }
/* STARTER PACK: Changa One italic, two layers as in the mock (Group 607): the blue one's outside stroke and
   shadow under the light one */
.fst-title { font: italic 400 calc(var(--m) * 111.74)/calc(var(--m) * 118.67) "Changa One", var(--font-ui); letter-spacing: calc(var(--m) * -7.82);
  text-align: center; white-space: nowrap; }
.fst-title > span { position: absolute; inset: 0; color: transparent; -webkit-background-clip: text; background-clip: text; }
.fst-title .a { background-image: linear-gradient(to top, #003dbe 28.8%, #4f8cff 60%, #007bff 69.5%); -webkit-text-stroke: calc(var(--m) * 7.24) #0425ca;
  filter: drop-shadow(0 calc(var(--m) * 3.1) calc(var(--m) * 2.25) rgba(0, 0, 0, .5)); }
.fst-title .b { background-image: linear-gradient(to top, #fff 28.8%, #8eb2f5 60%, #fff 69.5%); filter: drop-shadow(0 0 calc(var(--m) * 3.58) rgba(0, 0, 0, .8)); }
.fst-sec { background: #01a7f9; border-radius: calc(var(--m) * 20); box-shadow: 0 0 0 calc(var(--m) * 6) #000, inset 0 calc(var(--m) * -24) 0 #0158bc; }
.fst-card { border-radius: calc(var(--m) * 20); background: linear-gradient(#fff, #9de4fd); }
.fst-head { background: #a3d9ff; border-radius: calc(var(--m) * 10); }
.fst-hrow { display: flex; align-items: center; justify-content: center; gap: calc(var(--m) * 12); pointer-events: none; }
.fst-hrow img { width: calc(var(--m) * 60); height: calc(var(--m) * 61); object-fit: contain; }
.fst-note { opacity: .9; }
.fst-starter.focus, .fst-sec.focus { animation: fstFocus .5s ease-out 2; }
@keyframes fstFocus { 40% { transform: scale(1.025); filter: brightness(1.12); } }
@media (prefers-reduced-motion: reduce) { .fst-starter.focus, .fst-sec.focus { animation: none; } }
