/* ============================================================
   HSPTAce — Coach Brady raid FX + the FX Lab (2026-10-08)
   js/cb-fx.js draws the beats, js/view-fxlab.js is the lab.
   Loaded after css/styles.css (index.html), so a rule here wins over
   the first-pass raid block there ("The Coach Brady event") when both
   set the same thing.
   Rules: transform + opacity in keyframes (school Chromebooks); every
   size in % of the stage or in --u (1% of its width) so a phone and a
   Chromebook see the same picture; prefers-reduced-motion at the end.
   ============================================================ */

/* ============================================================
   THE FX LAB (Tools → FX Lab)
   ============================================================ */
.fxl { display: flex; flex-direction: column; gap: 16px; }
.fxl-main { min-width: 0; }
.fxl-note { margin: 6px 0 10px; }
.fxl-moves { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 330px), 1fr)); gap: 14px 18px; padding-top: 14px; border-top: 1px solid var(--line); }
.fxl select.input { padding: 5px 8px; font-size: .78rem; min-height: 0; height: auto; border-radius: 8px; }
.fxl-group h4 { margin: 0 0 8px; font-size: .86rem; letter-spacing: .02em; }
.fxl-boss { margin-bottom: 8px; }
.fxl-boss-h { display: flex; align-items: center; gap: 5px; font-size: .74rem; font-weight: 700; color: var(--mut); margin-bottom: 4px; }
.fxl-row { display: flex; flex-wrap: wrap; gap: 6px; }
.fxl-btn { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; padding: 7px 10px; border-radius: 10px; cursor: pointer; font: inherit; color: var(--text);
  background: rgba(148,163,216,.07); border: 1px solid var(--line2); text-align: left; min-width: 0; }
.fxl-btn:hover { border-color: rgba(75,156,211,.7); background: rgba(75,156,211,.12); }
.fxl-btn:active { transform: translateY(1px); }
.fxl-btn b { font-size: .8rem; }
.fxl-btn small { font-size: .64rem; color: var(--mut); }
.fxl-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; padding: 8px 10px; border-radius: 12px; background: rgba(148,163,216,.05); border: 1px solid var(--line); margin-bottom: 8px; }
.fxl-ctl { display: inline-flex; align-items: center; gap: 4px; }
.fxl-ctl .tiny { margin-right: 2px; }
.fxl-seg { font: inherit; font-size: .74rem; font-weight: 700; padding: 4px 9px; border-radius: 8px; cursor: pointer; color: var(--mut); background: transparent; border: 1px solid var(--line2); }
.fxl-seg.on { color: #06101f; background: var(--cb-bolt, #bff4ff); border-color: var(--cb-bolt, #bff4ff); }
.fxl-chk { display: inline-flex; align-items: center; gap: 5px; font-size: .76rem; color: var(--mut); cursor: pointer; }
.fxl-team { gap: 8px; }
.fxl-pet { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 180px; }
.fxl-pet select { width: 100%; }
.input-sm { padding: 5px 8px; font-size: .78rem; border-radius: 8px; }
.fxl-snd .aud-toggle { padding: 4px 8px; }
.fxl-frame { width: min(100%, var(--fw, 642px)); margin: 6px 0 0; transition: width .3s ease; }
.fxl-shell .cb-box { min-height: 0; margin-top: 10px; padding: 10px 14px; }
.fxl-say-line { min-height: 2.6em; }
.fxl-time { margin-top: 10px; width: min(100%, var(--fw, 642px)); }
.fxl-frame + .fxl-time { width: 100%; }
.fxl-tl { position: relative; display: flex; gap: 2px; height: 40px; border-radius: 8px; overflow: hidden; background: rgba(148,163,216,.06); }
.fxl-tl-b { position: relative; display: flex; flex-direction: column; justify-content: center; padding: 0 6px; min-width: 0; background: rgba(75,156,211,.14); border-right: 1px solid rgba(5,8,20,.6); }
.fxl-tl-b.on { background: rgba(75,156,211,.36); }
.fxl-tl-b b { font-size: .66rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fxl-tl-b small { font-size: .6rem; color: var(--mut); white-space: nowrap; }
.fxl-tl-head { position: absolute; left: 0; top: 0; bottom: 0; width: 2px; background: #fff; box-shadow: 0 0 8px #fff; pointer-events: none; }

/* ============================================================
   THE RAID STAGE, made deterministic (2026-10-08)
   Every position below is a share of the stage, so js/cb-fx.js can aim
   a projectile at a pet with the same numbers on a phone and on a
   Chromebook. KEEP IN STEP with SEAT / BOX in js/cb-fx.js.
   ============================================================ */
.cb-stage { container-type: inline-size; --u: 6.4px; }
@supports (width: 1cqw) { .cb-stage { --u: 1cqw; } }
.cb-stage::before { display: none; }                       /* the vignette moved into the world */
.cb-world { position: absolute; inset: 0; z-index: 1; transform-origin: 55% 60%; }
.cb-world::before { content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(180deg, rgba(5,8,20,.55) 0%, rgba(5,8,20,0) 26%, rgba(5,8,20,0) 70%, rgba(5,8,20,.35) 100%); }
.cb-world > .cb-stage-bg { inset: -3%; width: 106%; height: 106%; }   /* bleed, so a shake never shows an edge */
.cb-stage .cb-topbar { z-index: 6; }
.cb-stage .cb-boss { right: 4%; bottom: 8%; width: 37%; height: 72%; }
.cb-stage.cb-vs-mini .cb-boss { right: -2%; bottom: 7%; width: 50%; height: 64%; }
.cb-stage .cb-team { left: 0; bottom: 0; width: 100%; height: 100%; }
.cb-stage .cb-pet-slot { display: block; left: var(--sl); bottom: var(--sb); width: var(--sw); }
.cb-stage .cb-slot-0 { --sl: 19%; --sb: 40%; --sw: 16%; }
.cb-stage .cb-slot-1 { --sl: 2.5%; --sb: 16%; --sw: 17%; }
.cb-stage .cb-slot-2 { --sl: 35%; --sb: 13%; --sw: 17%; }
.cb-pet-box { position: relative; width: 100%; aspect-ratio: 1; }
.cb-pet-box > .cb-pet-art, .cb-pet-box > .cbr { position: absolute; inset: 0; }
.cb-pet-box .cb-pet-art svg { width: 100%; height: 100%; }
.cb-stage .cb-pet-hud { position: absolute; left: 50%; top: 94%; margin: 0; transform: translateX(-50%); z-index: 2; white-space: nowrap; }
.cb-stage .cb-teamshield { inset: auto; left: 1%; bottom: 9%; width: 53%; height: 64%; border-radius: 46%; }
.cb-stage .hp-mini .hp-fill { transition-delay: var(--hpd, 0s); transition-duration: var(--hpt, .6s); }
.cb-stage .cb-bar-fill { transition: width var(--hpt, .55s) cubic-bezier(.2,1,.3,1) var(--hpd, 0s); }
.cb-bar-chip { position: absolute; inset: 0 auto 0 0; border-radius: inherit; background: rgba(255,240,220,.85); transition: width .7s ease calc(var(--hpd, 0s) + .45s); }

/* ---------- layers ---------- */
.cb-back { position: absolute; inset: 0; z-index: 1; pointer-events: none; }
.cb-world .cb-fx { z-index: 5; }
.cb-over { position: absolute; inset: 0; z-index: 7; pointer-events: none; }
.cbx-at { position: absolute; width: 0; height: 0; }
.cbx { position: absolute; left: 0; bottom: 0; display: block; opacity: 0; pointer-events: none; animation-fill-mode: both;
  --sz: calc(var(--s, 6) * var(--u));
  width: var(--sz); height: calc(var(--sz) * var(--ar, 1));
  margin-left: calc(var(--sz) * -.5); margin-bottom: calc(var(--sz) * var(--ar, 1) * -.5); }
.cbx > b { display: block; width: 100%; height: 100%; }
.cbx svg { display: block; width: 100%; height: 100%; overflow: visible; }
.cbx > b > img { display: block; width: 100%; height: 100%; object-fit: contain; }
.cbx-floor { margin-bottom: 0; transform-origin: 50% 100%; }

/* a pop: something bursts into view on a point and is gone */
.cbx-pop { animation: cbxPop var(--t, .5s) cubic-bezier(.2,1.4,.4,1) var(--d, 0s) both; }
@keyframes cbxPop { 0% { opacity: 0; transform: scale(.25) rotate(var(--r0, 0deg)); } 18% { opacity: 1; transform: scale(1.18) rotate(var(--r1, 0deg)); }
  34% { transform: scale(1) rotate(var(--r1, 0deg)); } 72% { opacity: 1; } 100% { opacity: 0; transform: scale(1.06) rotate(var(--r1, 0deg)); } }
/* a burst: an impact flash that blooms and fades */
.cbx-burst { animation: cbxBurst var(--t, .42s) ease-out var(--d, 0s) both; }
@keyframes cbxBurst { 0% { opacity: 0; transform: scale(.2) rotate(var(--r0, 0deg)); } 12% { opacity: 1; transform: scale(.95) rotate(var(--r0, 0deg)); } 100% { opacity: 0; transform: scale(1.5) rotate(calc(var(--r0, 0deg) + 25deg)); } }
/* a ring: a shockwave */
.cbx-ring { animation: cbxRing var(--t, .5s) cubic-bezier(.1,.7,.3,1) var(--d, 0s) both; }
@keyframes cbxRing { 0% { opacity: 0; transform: scale(.12); } 1% { opacity: .95; } 100% { opacity: 0; transform: scale(var(--k, 1.6)); } }   /* 0 → .95 at 1%: a delayed ring must not show early */
/* a spark: a particle thrown from a point */
.cbx-spark { animation: cbxSpark var(--t, .6s) cubic-bezier(.15,.8,.35,1) var(--d, 0s) both; }
@keyframes cbxSpark { 0% { opacity: 0; transform: translate(0, 0) scale(1) rotate(0); } 8% { opacity: 1; }
  70% { opacity: 1; } 100% { opacity: 0; transform: translate(calc(var(--dx) * var(--u)), calc(var(--dy) * var(--u))) scale(var(--k, .45)) rotate(var(--r1, 180deg)); } }
/* a drift: a feather or a page that floats down after the hit */
.cbx-drift { animation: cbxDrift var(--t, 1.1s) ease-in-out var(--d, 0s) both; }
@keyframes cbxDrift { 0% { opacity: 0; transform: translate(0, 0) rotate(0); } 12% { opacity: 1; }
  40% { transform: translate(calc(var(--dx) * .5 * var(--u)), calc(var(--dy) * .3 * var(--u))) rotate(calc(var(--r1, 90deg) * .5)); }
  80% { opacity: .9; } 100% { opacity: 0; transform: translate(calc(var(--dx) * var(--u)), calc(var(--dy) * var(--u))) rotate(var(--r1, 90deg)); } }
/* a throw: across in x (outer, linear) and up-and-over in y (inner, the arc) */
.cbx-fly { animation: cbxFlyX var(--t, .4s) linear var(--d, 0s) both; }
.cbx-fly > b { animation: cbxFlyY var(--t, .4s) linear var(--d, 0s) both; }
.cbx-fly > b > svg { animation: cbxSpin var(--t, .4s) linear var(--d, 0s) both; }
@keyframes cbxFlyX { 0% { opacity: 0; transform: translateX(0); } 5% { opacity: 1; } 96% { opacity: 1; } 100% { opacity: 0; transform: translateX(calc(var(--dx) * var(--u))); } }
@keyframes cbxFlyY { 0% { transform: translateY(0); animation-timing-function: cubic-bezier(.3,.6,.6,1); }
  50% { transform: translateY(calc((var(--dy) * .5 - var(--arc, 0)) * var(--u))); animation-timing-function: cubic-bezier(.4,0,.7,.4); }
  100% { transform: translateY(calc(var(--dy) * var(--u))); } }
@keyframes cbxSpin { from { transform: rotate(0); } to { transform: rotate(var(--spin, 0deg)); } }
/* a fall: from the sky onto a point */
.cbx-fall { animation: cbxFall var(--t, .45s) cubic-bezier(.5,0,.9,.5) var(--d, 0s) both; }
@keyframes cbxFall { 0% { opacity: 0; transform: translateY(calc(var(--h, 60) * -1 * var(--u))) rotate(var(--r0, 0deg)); } 12% { opacity: 1; }
  96% { opacity: 1; transform: translateY(0) rotate(var(--r1, 0deg)); } 100% { opacity: 0; transform: translateY(0) rotate(var(--r1, 0deg)) scale(1.2); } }
/* a rise: up off a point (punctuation leaving the ball) */
.cbx-rise { animation: cbxRise var(--t, .6s) cubic-bezier(.2,.7,.4,1) var(--d, 0s) both; }
@keyframes cbxRise { 0% { opacity: 0; transform: translate(0, 0) scale(.5); } 15% { opacity: 1; transform: translate(calc(var(--dx) * .15 * var(--u)), calc(var(--h, 50) * -.15 * var(--u))) scale(1); }
  85% { opacity: 1; } 100% { opacity: 0; transform: translate(calc(var(--dx) * var(--u)), calc(var(--h, 50) * -1 * var(--u))) rotate(var(--r1, 0deg)); } }
/* a slash: a streak drawn across in one stroke */
.cbx-slash { width: calc(var(--L, 22) * var(--u)); height: calc(var(--th, 1.6) * var(--u)); margin: 0; left: calc(var(--L, 22) * var(--u) * -.5);
  border-radius: 99px; transform-origin: 0 50%; background: linear-gradient(90deg, rgba(255,255,255,0), var(--a, #fff) 30%, #fff 70%, rgba(255,255,255,0));
  box-shadow: 0 0 calc(var(--u) * 1.2) var(--b, #ffd24d); animation: cbxSlash var(--t, .32s) cubic-bezier(.2,.9,.3,1) var(--d, 0s) both; }
@keyframes cbxSlash { 0% { opacity: 0; transform: rotate(var(--r, -35deg)) scaleX(0); } 12% { opacity: 1; } 45% { opacity: 1; transform: rotate(var(--r, -35deg)) scaleX(1); } 100% { opacity: 0; transform: rotate(var(--r, -35deg)) scaleX(1) scaleY(.2); } }
/* speed lines behind a dash */
.cbx-lines { position: absolute; left: var(--x0); bottom: var(--y0); width: var(--w); height: var(--hh); opacity: 0; pointer-events: none;
  background: repeating-linear-gradient(180deg, rgba(255,255,255,0) 0 9%, rgba(255,255,255,.75) 9% 11%, rgba(255,255,255,0) 11% 23%);
  -webkit-mask: linear-gradient(90deg, transparent, #000 25%, #000 75%, transparent); mask: linear-gradient(90deg, transparent, #000 25%, #000 75%, transparent);
  animation: cbxLines var(--t, .4s) ease-out var(--d, 0s) both; }
@keyframes cbxLines { 0% { opacity: 0; transform: translateX(10%) scaleX(.4); } 25% { opacity: .9; } 100% { opacity: 0; transform: translateX(-12%) scaleX(1.2); } }
/* the telegraph: lock-on brackets close in on the pet about to be hit
   (a ring on the floor hid behind the pet's name tag) */
.cbx-tel { position: absolute; left: -6%; right: -6%; top: -4%; bottom: 8%; z-index: 3; opacity: 0; pointer-events: none;
  --tcol: var(--tc, #ff5d76); --tl: 24%; --tw: calc(var(--u) * .5);
  background:
    linear-gradient(var(--tcol), var(--tcol)) left top / var(--tl) var(--tw) no-repeat, linear-gradient(var(--tcol), var(--tcol)) left top / var(--tw) var(--tl) no-repeat,
    linear-gradient(var(--tcol), var(--tcol)) right top / var(--tl) var(--tw) no-repeat, linear-gradient(var(--tcol), var(--tcol)) right top / var(--tw) var(--tl) no-repeat,
    linear-gradient(var(--tcol), var(--tcol)) left bottom / var(--tl) var(--tw) no-repeat, linear-gradient(var(--tcol), var(--tcol)) left bottom / var(--tw) var(--tl) no-repeat,
    linear-gradient(var(--tcol), var(--tcol)) right bottom / var(--tl) var(--tw) no-repeat, linear-gradient(var(--tcol), var(--tcol)) right bottom / var(--tw) var(--tl) no-repeat;
  filter: drop-shadow(0 0 calc(var(--u) * .45) var(--tcol)) drop-shadow(0 0 1px #000);
  animation: cbxTel var(--t, .5s) ease-out var(--d, 0s) both; }
@keyframes cbxTel { 0% { opacity: 0; transform: scale(1.6) rotate(-10deg); } 28% { opacity: 1; transform: none; } 46% { opacity: .35; } 60% { opacity: 1; } 74% { opacity: .4; }
  86% { opacity: 1; transform: scale(.94); } 100% { opacity: 0; transform: scale(.88); } }
/* a flash over everything */
.cbx-flash { position: absolute; inset: 0; opacity: 0; pointer-events: none; background: var(--fc, #fff); mix-blend-mode: screen;
  animation: cbxFlash var(--t, .35s) ease-out var(--d, 0s) both; }
@keyframes cbxFlash { 0% { opacity: 0; } 15% { opacity: var(--fo, .7); } 100% { opacity: 0; } }
/* comic text: CHOMP! BONK! */
.cbx-word { position: absolute; left: 0; bottom: 0; transform: translate(-50%, 50%); opacity: 0; pointer-events: none; white-space: nowrap;
  font-family: var(--font-d, 'Sora', sans-serif); font-weight: 800; font-size: calc(var(--fs, 5) * var(--u)); letter-spacing: .02em; line-height: 1;
  color: var(--wc, #fff); -webkit-text-stroke: calc(var(--u) * .35) var(--ws, #13294b); paint-order: stroke fill; text-shadow: calc(var(--u) * .4) calc(var(--u) * .4) 0 var(--ws, #13294b);
  animation: cbxWord var(--t, .7s) cubic-bezier(.2,1.5,.4,1) var(--d, 0s) both; }
@keyframes cbxWord { 0% { opacity: 0; transform: translate(-50%, 50%) scale(.2) rotate(var(--r, -8deg)); } 20% { opacity: 1; transform: translate(-50%, 50%) scale(1.15) rotate(var(--r, -8deg)); }
  35% { transform: translate(-50%, 50%) scale(1) rotate(var(--r, -8deg)); } 78% { opacity: 1; } 100% { opacity: 0; transform: translate(-50%, 20%) scale(1) rotate(var(--r, -8deg)); } }
/* a wave along the floor (the rhino's stomp) */
.cbx-quake { position: absolute; bottom: var(--y, 10%); left: var(--x, 70%); width: calc(var(--u) * 14); height: calc(var(--u) * 4); margin-left: calc(var(--u) * -7); margin-bottom: calc(var(--u) * -2);
  border-radius: 50%; border: calc(var(--u) * .8) solid rgba(255,236,200,.95); box-shadow: 0 0 calc(var(--u) * 2) rgba(255,200,120,.9), inset 0 0 calc(var(--u) * 1.2) rgba(255,220,160,.8); opacity: 0; pointer-events: none;
  animation: cbxQuake var(--t, .5s) cubic-bezier(.2,.6,.4,1) var(--d, 0s) both; }
@keyframes cbxQuake { 0% { opacity: 0; transform: translateX(0) scale(.4); } 10% { opacity: 1; } 85% { opacity: .8; } 100% { opacity: 0; transform: translateX(calc(var(--dx) * var(--u))) scale(var(--k, 3), calc(var(--k, 3) * .55)); } }

/* ---------- the pet that gets hit (a wrapper per hit: js seatWrap) ---------- */
.cbr { display: block; transform-origin: 50% 88%; }
.cbr-jab    { animation: cbrJab .26s ease-out var(--hd, 0s) both; }
.cbr-knock  { animation: cbrKnock .62s cubic-bezier(.2,.9,.3,1) var(--hd, 0s) both; }
.cbr-big    { animation: cbrBig .95s cubic-bezier(.2,.9,.3,1) var(--hd, 0s) both; }
.cbr-launch { animation: cbrLaunch .8s cubic-bezier(.3,.7,.4,1) var(--hd, 0s) both; }
.cbr-squash { animation: cbrSquash .55s ease-out var(--hd, 0s) both; }
.cbr-blast  { animation: cbrBlast .7s cubic-bezier(.2,.9,.3,1) var(--hd, 0s) both; }
.cbr-shiver { animation: cbrShiver .55s linear var(--hd, 0s) both; }
.cbr-dizzy  { animation: cbrDizzy .95s ease-in-out var(--hd, 0s) both; }
.cbr-shock  { animation: cbrShock .6s steps(1) var(--hd, 0s) both; }
.cbr-flash  { animation: cbrFlash .3s steps(1) var(--hd, 0s) both; }
@keyframes cbrJab { 0% { transform: none; } 30% { transform: translateX(-5%) rotate(-4deg); } 100% { transform: none; } }
@keyframes cbrKnock { 0% { transform: none; } 12% { transform: translateX(-13%) rotate(-10deg) scale(.96, 1.04); } 22% { transform: translateX(-13%) rotate(-10deg); }
  60% { transform: translateX(3%) rotate(2deg); } 100% { transform: none; } }
@keyframes cbrBig { 0% { transform: none; } 10% { transform: translate(-22%, -6%) rotate(-24deg) scale(.92, 1.08); } 22% { transform: translate(-24%, -8%) rotate(-28deg); }
  55% { transform: translate(-6%, 0) rotate(8deg) scale(1.06, .94); } 75% { transform: translateX(2%) rotate(-3deg); } 100% { transform: none; } }
@keyframes cbrLaunch { 0% { transform: none; } 10% { transform: scale(1.1, .85); } 40% { transform: translateY(-26%) rotate(-10deg); } 72% { transform: translateY(0) scale(1.08, .9); } 86% { transform: translateY(-4%); } 100% { transform: none; } }
@keyframes cbrSquash { 0% { transform: none; } 15% { transform: scale(1.22, .7); } 40% { transform: scale(.92, 1.1); } 70% { transform: scale(1.04, .97); } 100% { transform: none; } }
@keyframes cbrBlast { 0% { transform: none; } 15% { transform: translateX(-14%) skewX(10deg) scale(.9, 1.05); } 30% { transform: translateX(-16%) skewX(-6deg); } 70% { transform: translateX(2%) skewX(2deg); } 100% { transform: none; } }
@keyframes cbrShiver { 0%, 100% { transform: none; } 10% { transform: translateX(-4%); } 20% { transform: translateX(4%); } 30% { transform: translateX(-3%); } 40% { transform: translateX(3%); } 50% { transform: translateX(-2%); } 60% { transform: translateX(2%); } 75% { transform: translateX(-1%); } }
@keyframes cbrDizzy { 0% { transform: none; } 12% { transform: scale(1.2, .72); } 30% { transform: rotate(-9deg); } 50% { transform: rotate(8deg); } 70% { transform: rotate(-5deg); } 85% { transform: rotate(3deg); } 100% { transform: none; } }
@keyframes cbrShock { 0% { transform: none; } 10% { transform: translate(-3%, 1%); } 20% { transform: translate(3%, -1%); } 30% { transform: translate(-2%, 0); } 45% { transform: translate(2%, 1%); } 60% { transform: translate(-1%, 0); } 100% { transform: none; } }
/* the white flash of a hit, without filter(): an overlay of the pet's own art does not exist, so a bright bloom sits on it */
.cbx-hitglow { position: absolute; left: 50%; top: 52%; width: 70%; aspect-ratio: 1; margin: -35% 0 0 -35%; border-radius: 50%; pointer-events: none; opacity: 0;
  background: radial-gradient(circle, rgba(255,255,255,.95) 0 18%, var(--gc, rgba(255,210,120,.75)) 38%, rgba(255,255,255,0) 68%); mix-blend-mode: screen;
  animation: cbxBurst var(--t, .35s) ease-out var(--d, 0s) both; }

/* ---------- the boss's body (js bossCls + bossStyle: --lx/--ly are % of the boss box) ---------- */
.cbm-lunge  { animation: cbmLunge var(--bt, 1.1s) cubic-bezier(.3,.9,.3,1) var(--bd, 0s) both; }
@keyframes cbmLunge { 0% { transform: none; } 22% { transform: translate(6%, -1%) rotate(5deg) scale(1.03); } 34% { transform: translate(var(--lx), var(--ly)) rotate(-7deg) scale(1.06, .97); }
  46% { transform: translate(var(--lx), var(--ly)) rotate(-7deg); } 54% { transform: translate(calc(var(--lx) * .96), var(--ly)) rotate(-4deg); }
  78% { transform: translate(calc(var(--lx) * .1), 0) rotate(2deg); } 100% { transform: none; } }
.cbm-peck   { animation: cbmPeck var(--bt, 1.15s) cubic-bezier(.3,.9,.3,1) var(--bd, 0s) both; }
@keyframes cbmPeck { 0% { transform: none; } 18% { transform: translate(5%, -1%) rotate(7deg) scale(1.03); } 28% { transform: translate(var(--lx), var(--ly)) rotate(-8deg); }
  33% { transform: translate(calc(var(--lx) * .92), var(--ly)) rotate(-3deg); } 38% { transform: translate(var(--lx), var(--ly)) rotate(-9deg); }
  43% { transform: translate(calc(var(--lx) * .92), var(--ly)) rotate(-3deg); } 49% { transform: translate(calc(var(--lx) * 1.02), var(--ly)) rotate(-11deg) scale(1.05, .96); }
  57% { transform: translate(calc(var(--lx) * 1.02), var(--ly)) rotate(-11deg); } 80% { transform: translate(calc(var(--lx) * .08), 0) rotate(2deg); } 100% { transform: none; } }
.cbm-rear   { animation: cbmRear var(--bt, 1.6s) ease-out var(--bd, 0s) both; }
@keyframes cbmRear { 0% { transform: none; } 22% { transform: translate(4%, -2%) rotate(6deg) scale(1.04, 1.07); } 30% { transform: translate(-5%, 0) rotate(-5deg) scale(1.08, .95); }
  40% { transform: translate(-3%, 0) rotate(-3deg) scale(1.02); } 44% { transform: translate(-4%, 0) rotate(-4deg); } 48% { transform: translate(-2%, 0) rotate(-2deg); }
  52% { transform: translate(-4%, 0) rotate(-4deg); } 75% { transform: translate(-1%, 0); } 100% { transform: none; } }
.cbm-jump   { animation: cbmJump var(--bt, 1.6s) ease-in-out var(--bd, 0s) both; }
@keyframes cbmJump { 0% { transform: none; } 12% { transform: scale(1.06, .9); } 24% { transform: translateY(-14%) scale(.97, 1.04); } 70% { transform: translateY(-16%); }
  86% { transform: translateY(0) scale(1.05, .93); } 100% { transform: none; } }
.cbm-swoop  { animation: cbmSwoop var(--bt, 1.2s) cubic-bezier(.45,.05,.4,1) var(--bd, 0s) both; }
@keyframes cbmSwoop { 0% { transform: none; } 22% { transform: translate(4%, -20%) rotate(8deg) scale(.95); } 44% { transform: translate(var(--lx), var(--ly)) rotate(-16deg) scale(1.02); }
  52% { transform: translate(var(--lx), var(--ly)) rotate(-18deg); } 74% { transform: translate(calc(var(--lx) * .35), -24%) rotate(6deg) scale(.96); } 100% { transform: none; } }
.cbm-stomp  { animation: cbmStomp var(--bt, 1.1s) cubic-bezier(.3,.8,.3,1) var(--bd, 0s) both; }
@keyframes cbmStomp { 0% { transform: none; } 30% { transform: translateY(-9%) rotate(-5deg) scale(.97, 1.05); } 38% { transform: translateY(1%) scale(1.09, .9); }
  46% { transform: translateY(0) scale(1.09, .9); } 60% { transform: scale(.98, 1.03); } 100% { transform: none; } }
.cbm-charge { animation: cbmCharge var(--bt, 1.3s) cubic-bezier(.35,.9,.3,1) var(--bd, 0s) both; }
@keyframes cbmCharge { 0% { transform: none; } 8% { transform: translateX(2%) scale(1.02, .98); } 12% { transform: translateX(-1%); } 16% { transform: translateX(3%) rotate(2deg); }
  22% { transform: translateX(-1%); } 30% { transform: translateX(5%) rotate(3deg) scale(1.03, .97); }
  44% { transform: translate(var(--lx), var(--ly)) rotate(-5deg) scale(1.08, .95); } 54% { transform: translate(var(--lx), var(--ly)) rotate(-5deg) scale(1.08, .95); }
  64% { transform: translate(calc(var(--lx) * .82), var(--ly)) rotate(3deg); } 86% { transform: translate(calc(var(--lx) * .05), 0) rotate(-1deg); } 100% { transform: none; } }
.cbm-whip   { animation: cbmWhip var(--bt, 1.2s) cubic-bezier(.3,.9,.3,1) var(--bd, 0s) both; transform-origin: 54% 99%; }
@keyframes cbmWhip { 0% { transform: none; } 30% { transform: translateX(4%) rotate(12deg); } 44% { transform: translate(var(--lx), 0) rotate(-30deg); } 52% { transform: translate(var(--lx), 0) rotate(-30deg); }
  66% { transform: translate(calc(var(--lx) * .4), 0) rotate(10deg); } 80% { transform: translateX(0) rotate(-5deg); } 90% { transform: rotate(2deg); } 100% { transform: none; } }
.cbm-dribble { animation: cbmDribble var(--bt, 1.6s) ease-in-out var(--bd, 0s) both; }
@keyframes cbmDribble { 0% { transform: none; } 10% { transform: translateY(2%) scale(1.02, .97); } 20% { transform: translateY(-2%); } 30% { transform: translateY(3%) scale(1.04, .95); }
  42% { transform: translateY(-5%) scale(.98, 1.04); } 60% { transform: translateY(0); } 100% { transform: none; } }
.cbm-hop    { animation: cbmHop .5s ease-out var(--bd, 0s) both; }
@keyframes cbmHop { 0% { transform: none; } 30% { transform: translateY(-4%) scale(.98, 1.03); } 60% { transform: translateY(0) scale(1.03, .97); } 100% { transform: none; } }

/* a pose sequence: stacked frames, each shown in its own window (js seq) */
.cbq { position: relative; display: block; width: 100%; height: 100%; }
.cbq > .cb-art-img { position: absolute; inset: 0; opacity: 0; animation: cbqOn 1ms linear var(--on) both, cbqOff 1ms linear var(--off) forwards; }
.cbq > .cb-art-img.cbq-first { animation: cbqOff 1ms linear var(--off) forwards; opacity: 1; }
.cbq > .cb-art-img.cbq-last { animation: cbqOn 1ms linear var(--on) both; }
@keyframes cbqOn { from { opacity: 0; } to { opacity: 1; } }
@keyframes cbqOff { from { opacity: 1; } to { opacity: 0; } }

/* ---------- the whole world on impact: a punch-in and a shake sized to the damage ---------- */
.cbw-hit { animation: cbwHit var(--wt, .5s) linear var(--wd, 0s) both; }
@keyframes cbwHit {
  0% { transform: none; } 6% { transform: scale(1.025) translate(calc(var(--shk, 1) * -.6 * var(--u)), calc(var(--shk, 1) * .4 * var(--u))); }
  18% { transform: scale(1.018) translate(calc(var(--shk, 1) * .55 * var(--u)), calc(var(--shk, 1) * -.45 * var(--u))); }
  32% { transform: scale(1.01) translate(calc(var(--shk, 1) * -.4 * var(--u)), calc(var(--shk, 1) * .25 * var(--u))); }
  48% { transform: translate(calc(var(--shk, 1) * .25 * var(--u)), calc(var(--shk, 1) * -.15 * var(--u))); }
  66% { transform: translate(calc(var(--shk, 1) * -.12 * var(--u)), 0); } 100% { transform: none; } }
.cbw-rumble { animation: cbwRumble var(--wt, .7s) linear var(--wd, 0s) both; }
@keyframes cbwRumble { 0%, 100% { transform: none; } 10% { transform: translate(calc(var(--shk, 1) * -.3 * var(--u)), calc(var(--shk, 1) * .5 * var(--u))); }
  20% { transform: translate(calc(var(--shk, 1) * .3 * var(--u)), calc(var(--shk, 1) * -.4 * var(--u))); } 30% { transform: translate(calc(var(--shk, 1) * -.25 * var(--u)), calc(var(--shk, 1) * .4 * var(--u))); }
  40% { transform: translate(calc(var(--shk, 1) * .25 * var(--u)), calc(var(--shk, 1) * -.3 * var(--u))); } 55% { transform: translate(calc(var(--shk, 1) * -.15 * var(--u)), calc(var(--shk, 1) * .2 * var(--u))); }
  70% { transform: translate(calc(var(--shk, 1) * .1 * var(--u)), calc(var(--shk, 1) * -.1 * var(--u))); } }
.cbw-sway { animation: cbwSway var(--wt, .8s) ease-in-out var(--wd, 0s) both; }
@keyframes cbwSway { 0%, 100% { transform: none; } 20% { transform: translateX(calc(var(--shk, 1) * -.6 * var(--u))) skewX(-1deg); } 40% { transform: translateX(calc(var(--shk, 1) * .5 * var(--u))) skewX(.8deg); }
  60% { transform: translateX(calc(var(--shk, 1) * -.35 * var(--u))); } 80% { transform: translateX(calc(var(--shk, 1) * .15 * var(--u))); } }

/* ---------- numbers ---------- */
.cbn { position: absolute; z-index: 6; transform: translate(-50%, 50%); pointer-events: none; opacity: 0; display: flex; flex-direction: column; align-items: center;
  font-family: var(--font-d, 'Sora', sans-serif); font-weight: 800; font-size: calc(var(--fs, 4.4) * var(--u)); line-height: 1; color: #fff;
  -webkit-text-stroke: calc(var(--u) * .3) #2a0a12; paint-order: stroke fill; text-shadow: 0 calc(var(--u) * .45) 0 rgba(0,0,0,.6);
  animation: cbnUp var(--t, 1.05s) cubic-bezier(.2,1.2,.4,1) var(--d, 0s) both; }
.cbn i { font-style: normal; font-size: .42em; letter-spacing: .06em; -webkit-text-stroke: 0; color: var(--cb-gold, #ffd24d); text-shadow: 0 1px 2px #000; }
.cbn-ouch { color: #ff8095; }
.cbn-big { --fs: 6.4; color: #ffd0d8; }
.cbn-heal { color: #59f0a5; -webkit-text-stroke-color: #062b1b; }
.cbn-boss { --fs: 5.6; }
.cbn-word { --fs: 3.2; color: #dfe7ff; }
@keyframes cbnUp { 0% { opacity: 0; transform: translate(-50%, 50%) translateY(calc(var(--u) * 2)) scale(.5); } 16% { opacity: 1; transform: translate(-50%, 50%) translateY(0) scale(1.25); }
  30% { transform: translate(-50%, 50%) scale(1); } 74% { opacity: 1; } 100% { opacity: 0; transform: translate(-50%, 50%) translateY(calc(var(--u) * -4)) scale(1); } }

/* ---------- a mini boss going down ---------- */
.cbd-banner { position: absolute; left: 50%; top: 40%; z-index: 8; transform: translate(-50%, -50%); pointer-events: none; text-align: center; opacity: 0;
  animation: cbdBanner 2.6s cubic-bezier(.2,1.3,.4,1) var(--d, .7s) both; }
.cbd-banner b { display: block; font-family: var(--font-d, 'Sora', sans-serif); font-weight: 800; font-size: calc(var(--u) * 6.2); letter-spacing: .04em; color: #fff; white-space: nowrap;
  -webkit-text-stroke: calc(var(--u) * .35) var(--sc, #13294b); paint-order: stroke fill; text-shadow: 0 0 calc(var(--u) * 2) var(--sc, #4b9cd3), calc(var(--u) * .5) calc(var(--u) * .5) 0 #0a1020; }
.cbd-banner small { display: inline-block; margin-top: calc(var(--u) * 1); padding: calc(var(--u) * .5) calc(var(--u) * 1.6); border-radius: 99px; font-weight: 800; font-size: calc(var(--u) * 2.2); letter-spacing: .14em;
  color: #0a1020; background: var(--cb-gold, #ffd24d); }
@keyframes cbdBanner { 0% { opacity: 0; transform: translate(-50%, -50%) scale(2.2); } 14% { opacity: 1; transform: translate(-50%, -50%) scale(.95); } 22% { transform: translate(-50%, -50%) scale(1.03); }
  30% { transform: translate(-50%, -50%) scale(1); } 85% { opacity: 1; } 100% { opacity: 0; transform: translate(-50%, -50%) scale(1); } }
.cbd-stamp { position: absolute; left: 50%; top: 52%; z-index: 3; padding: 4% 9%; border: calc(var(--u) * .7) solid #ff5d76; border-radius: 10%; color: #ff5d76; font-family: var(--font-d, 'Sora', sans-serif);
  font-weight: 800; font-size: calc(var(--u) * 5); letter-spacing: .1em; background: rgba(5,8,20,.55); opacity: 0; transform: translate(-50%, -50%) rotate(-14deg);
  animation: cbdStamp .5s cubic-bezier(.2,1.6,.4,1) var(--d, 1.4s) both; }
@keyframes cbdStamp { 0% { opacity: 0; transform: translate(-50%, -50%) rotate(-14deg) scale(3); } 100% { opacity: 1; transform: translate(-50%, -50%) rotate(-14deg) scale(1); } }
.cbd-fall { animation: cbdFall 1.2s cubic-bezier(.3,.8,.3,1) var(--d, .2s) both; }
@keyframes cbdFall { 0% { transform: none; } 12% { transform: translateX(6%) rotate(5deg) scale(1.04); } 20% { transform: translateX(6%) rotate(5deg); } 60% { transform: translateY(3%) rotate(-2deg) scale(1.02, .97); } 100% { transform: translateY(2%); } }
.cbx-confetti { position: absolute; top: -4%; width: calc(var(--u) * 1.1); height: calc(var(--u) * 1.8); border-radius: 2px; opacity: 0; background: var(--c, #ffd24d);
  animation: cbxConf var(--t, 1.6s) cubic-bezier(.3,.4,.6,1) var(--d, .8s) both; }
@keyframes cbxConf { 0% { opacity: 0; transform: translateY(0) rotate(0); } 8% { opacity: 1; } 85% { opacity: 1; } 100% { opacity: 0; transform: translate(calc(var(--dx, 0) * var(--u)), calc(var(--u) * 66)) rotate(var(--r1, 540deg)); } }

/* the shark's jaws: open around the pet, then CHOMP shut (--o = how far each opens, in u) */
.cbx-jaw { animation: cbxJaw var(--t, .56s) linear var(--d, 0s) both; }
@keyframes cbxJaw { 0% { opacity: 0; transform: translateY(calc(var(--o) * 2.2 * var(--u))) scale(.6); } 20% { opacity: 1; transform: translateY(calc(var(--o) * 1.6 * var(--u))) scale(1); }
  50% { transform: translateY(calc(var(--o) * 1.9 * var(--u))) scale(1.04); } 56% { transform: translateY(0) scale(1.06); } 62% { transform: translateY(calc(var(--o) * .15 * var(--u))) rotate(2deg); }
  70% { transform: translateY(0) rotate(-3deg); } 80% { opacity: 1; transform: rotate(2deg); } 100% { opacity: 0; transform: scale(.94); } }
/* birds round a dizzy pet's head */
.cbx-orbit { animation: cbxOrbit var(--t, .9s) linear var(--d, 0s) both; }
.cbx-orbit > b { width: 34%; height: 34%; margin: 0 auto; }
@keyframes cbxOrbit { 0% { opacity: 0; transform: rotate(var(--o, 0deg)) scale(.5); } 12% { opacity: 1; transform: rotate(calc(var(--o, 0deg) + 60deg)) scale(1); } 85% { opacity: 1; } 100% { opacity: 0; transform: rotate(calc(var(--o, 0deg) + 560deg)) scale(.8); } }

/* ---------- reduced motion: the numbers, the words and a soft flash stay; nothing flies, shakes or lunges ---------- */
@media (prefers-reduced-motion: reduce) {
  .cb-world, .cb-boss, .cbr, .cbq > .cb-art-img { animation: none !important; }
  .cbq > .cb-art-img:not(.cbq-first) { opacity: 0 !important; }
  .cbq > .cb-art-img.cbq-first { opacity: 1 !important; }
  .cbx-fly, .cbx-spark, .cbx-drift, .cbx-fall, .cbx-rise, .cbx-lines, .cbx-quake, .cbx-jaw, .cbx-orbit, .cbx-confetti, .cbx-slash, .cbx-ring { display: none !important; }
  .cbx-burst, .cbx-pop, .cbx-hitglow, .cbx-tel { animation-name: cbxFade !important; }
  .cbn, .cbx-word, .cbd-banner, .cbd-stamp { animation-name: cbxFade !important; transform: translate(-50%, 50%); }
  .cbd-banner { transform: translate(-50%, -50%); }
  .cbd-stamp { transform: translate(-50%, -50%) rotate(-14deg); }
  .cbx-flash { animation-duration: .5s !important; --fo: .25; }
}
@keyframes cbxFade { 0% { opacity: 0; } 15% { opacity: 1; } 80% { opacity: 1; } 100% { opacity: 0; } }

/* a phone-sized stage: the pets' name tags shrink so they fit under the pets */
@container (max-width: 460px) {
  .cb-pet-slot .cb-pet-hud { transform: translateX(-50%) scale(.78); transform-origin: 50% 0; top: 92%; }
  .cbn { -webkit-text-stroke-width: calc(var(--u) * .45); }
}

/* the first-pass effects (styles.css) re-aimed at the seats above, for the beats js/cb-fx.js doesn't draw yet */
.cb-stage .cb-to-0 { left: 24%; } .cb-stage .cb-to-1 { left: 8%; } .cb-stage .cb-to-2 { left: 40.5%; }
.cb-stage .cb-at-0 { left: 25%; } .cb-stage .cb-at-1 { left: 9%; } .cb-stage .cb-at-2 { left: 41%; }
.cb-stage .cb-bolt-p { bottom: 50%; left: 30%; } .cb-stage .cb-from-1 { bottom: 27%; left: 14%; } .cb-stage .cb-from-2 { bottom: 24%; left: 46%; }

/* ============================================================
   A KID'S PET IN THE RAID (js/cb-fx.js petBeat)
   ============================================================ */
/* the spotlight: an Arena stage over the raid stage, lifted (--lift) so the Arena's monster spot is the boss's chest */
.cb-cast-wrap { position: absolute; left: 0; right: 0; bottom: var(--lift, 8%); height: 100%; z-index: 4; pointer-events: none;
  animation: cbCastIn .22s ease-out both, cbCastOut .3s ease-in var(--out, 1.75s) forwards; }
.cb-stage .arena-stage.cb-cast { position: absolute; inset: 0; aspect-ratio: auto; min-height: 0; max-height: none; border: 0; border-radius: 0; background: none; box-shadow: none; overflow: visible; }
.cb-cast .cb-cast-mon { visibility: hidden; }
.cb-cast-wrap .sx-sky { bottom: -14%; }
.cb-cast .combatant-pet { filter: drop-shadow(0 10px 12px rgba(0,0,0,.45)); }
@keyframes cbCastIn { 0% { opacity: 0; transform: translateX(-3%) scale(.94); } 100% { opacity: 1; transform: none; } }
@keyframes cbCastOut { to { opacity: 0; transform: translateX(-2%) scale(.97); } }
/* the caster's seat empties while it's in the spotlight; the other two step back */
.cb-pet-slot.cb-spot-src .cb-pet-box { animation: cbSpotSrc 2.1s ease both; }
.cb-pet-slot.cb-dim .cb-pet-box { animation: cbDim 2.1s ease both; }
@keyframes cbSpotSrc { 0% { opacity: 1; } 10% { opacity: .12; } 82% { opacity: .12; } 100% { opacity: 1; } }
@keyframes cbDim { 0% { opacity: 1; } 10% { opacity: .45; } 82% { opacity: .45; } 100% { opacity: 1; } }
/* quick / power from the seat */
.cbr-hop    { animation: cbrHop .42s ease-out var(--hd, 0s) both; }
.cbr-windup { animation: cbrWindup .7s cubic-bezier(.3,1.3,.5,1) var(--hd, 0s) both; }
@keyframes cbrHop { 0% { transform: none; } 35% { transform: translate(6%, -8%) rotate(4deg); } 70% { transform: translate(2%, 0) scale(1.04, .96); } 100% { transform: none; } }
@keyframes cbrWindup { 0% { transform: none; } 30% { transform: translateX(-6%) scale(.94, 1.06) rotate(-4deg); } 48% { transform: translateX(-7%) scale(.94, 1.06) rotate(-5deg); } 60% { transform: translateX(10%) scale(1.08, .94) rotate(5deg); } 100% { transform: none; } }
.cbx-charge { position: absolute; left: 50%; top: 50%; width: 90%; aspect-ratio: 1; margin: -45% 0 0 -45%; border-radius: 50%; pointer-events: none; opacity: 0;
  background: radial-gradient(circle, color-mix(in srgb, var(--c, #ffd24d) 70%, #fff) 0 12%, color-mix(in srgb, var(--c, #ffd24d) 55%, transparent) 35%, transparent 66%);
  mix-blend-mode: screen; animation: cbxCharge .4s ease-in var(--d, 0s) both; }
@keyframes cbxCharge { 0% { opacity: 0; transform: scale(1.5); } 70% { opacity: .9; transform: scale(.8); } 100% { opacity: 0; transform: scale(.4); } }
/* focus: a pink aura and a crosshair */
.cbx-focus { position: absolute; inset: 5%; border-radius: 50%; pointer-events: none; opacity: 0; background: radial-gradient(circle, rgba(255,158,203,.55), rgba(255,158,203,0) 65%);
  mix-blend-mode: screen; animation: cbxFocus 1.3s ease var(--d, 0s) both; }
@keyframes cbxFocus { 0% { opacity: 0; transform: scale(.6); } 25% { opacity: 1; transform: scale(1.1); } 80% { opacity: .8; } 100% { opacity: 0; transform: scale(1); } }
.cbx-stamp-focus { top: 30%; color: #ffd6ea; border-color: #ff9ecb; background: rgba(60,10,40,.8); }
/* a healed pet: green light up its body */
.cbx-heal { position: absolute; left: 15%; right: 15%; bottom: 8%; height: 80%; border-radius: 40% 40% 20% 20%; pointer-events: none; opacity: 0;
  background: linear-gradient(0deg, rgba(90,240,165,.6), rgba(90,240,165,0)); mix-blend-mode: screen; animation: cbxHeal .9s ease-out var(--d, 0s) both; }
@keyframes cbxHeal { 0% { opacity: 0; transform: translateY(20%) scaleY(.5); } 35% { opacity: 1; } 100% { opacity: 0; transform: translateY(-18%) scaleY(1.1); } }
/* the team shield goes up when the Guardian's plate does, not at the start of the beat */
.cb-shield-new .cb-teamshield { animation: cbShieldIn .45s cubic-bezier(.2,1.4,.4,1) .62s both, cbShield 1.6s ease-in-out 1.1s infinite; }
@keyframes cbShieldIn { 0% { opacity: 0; transform: scale(.85); } 100% { opacity: .85; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .cb-cast-wrap { animation: none; }
  .cb-pet-slot.cb-spot-src .cb-pet-box, .cb-pet-slot.cb-dim .cb-pet-box { animation: none; }
}

/* ============================================================
   COACH BRADY'S MOVES (js/cb-fx.js COACH)
   ============================================================ */
/* his body: anchored on his feet */
.cb-vs-coach .cb-boss.cbm { transform-origin: 50% 96%; }
.cbm-blow   { animation: cbmBlow var(--bt, .95s) cubic-bezier(.3,.9,.3,1) var(--bd, 0s) both; }
@keyframes cbmBlow { 0% { transform: none; } 26% { transform: translate(2.5%, -1%) rotate(3deg) scale(1.01, 1.02); } 36% { transform: translate(-3%, 0) rotate(-2.5deg) scale(1.03, .98); }
  44% { transform: translate(-2.2%, 0) rotate(-2deg); } 52% { transform: translate(-2.8%, 0) rotate(-2.4deg); } 100% { transform: none; } }
.cbm-throw  { animation: cbmThrow var(--bt, 1.5s) cubic-bezier(.3,.8,.3,1) var(--bd, 0s) both; }
@keyframes cbmThrow { 0% { transform: none; } 9% { transform: translate(1%, 0); } 40% { transform: translate(3%, -1.5%) rotate(3deg) scale(.99, 1.02); }
  46% { transform: translate(-4%, 0) rotate(-4deg) scale(1.04, .97); } 56% { transform: translate(-4.5%, 0) rotate(-4.5deg); } 75% { transform: translate(-1%, 0) rotate(-1deg); } 100% { transform: none; } }
.cbm-thrust { animation: cbmThrust var(--bt, 2s) ease-out var(--bd, 0s) both; }
@keyframes cbmThrust { 0% { transform: none; } 25% { transform: translate(1.5%, .5%) scale(1.01, .99); } 31% { transform: translate(-1%, 0); } 38% { transform: translate(-3.5%, 0) scale(1.03, .98); }
  44% { transform: translate(-2.6%, 0); } 52% { transform: translate(-3.3%, 0); } 58% { transform: translate(-2.6%, 0); } 64% { transform: translate(-3.2%, 0); } 74% { transform: translate(-2%, 0); } 100% { transform: none; } }
.cbm-crouch { animation: cbmCrouch var(--bt, 1.6s) ease-out var(--bd, 0s) both; }
@keyframes cbmCrouch { 0% { transform: none; } 12% { transform: translateY(1.5%) scale(1.02, .98); } 25% { transform: translate(-1%, 1%); } 42% { transform: translate(-2.4%, 1%); } 70% { transform: translate(-1%, .6%); } 100% { transform: none; } }
.cbm-slap   { animation: cbmSlap var(--bt, .52s) ease-out var(--bd, 0s) both; }
@keyframes cbmSlap { 0% { transform: none; } 40% { transform: translate(1%, -1%) rotate(1deg); } 52% { transform: translate(-1.6%, .4%) scale(1.02, .98); } 100% { transform: none; } }
.cbm-laugh  { animation: cbmLaugh var(--bt, .7s) ease-in-out var(--bd, 0s) both; }
@keyframes cbmLaugh { 0% { transform: none; } 15% { transform: translateY(-1%) rotate(-1deg); } 30% { transform: translateY(.5%); } 45% { transform: translateY(-1%) rotate(1deg); } 60% { transform: translateY(.5%); } 78% { transform: translateY(-.6%); } 100% { transform: none; } }

/* his lightning: two jagged copies of each bolt flicker in turn */
.cbx-bolt { position: absolute; inset: 0; opacity: 0; pointer-events: none; animation: cbxBoltA var(--t, .5s) steps(1) var(--d, 0s) both; }
.cbx-bolt-b { animation-name: cbxBoltB; }
.cbx-bolt svg { display: block; width: 100%; height: 100%; overflow: visible; }
@keyframes cbxBoltA { 0% { opacity: 0; } 1% { opacity: 1; } 12% { opacity: .15; } 20% { opacity: 1; } 34% { opacity: 0; } 42% { opacity: 1; } 58% { opacity: .3; } 66% { opacity: 1; } 84% { opacity: .15; } 92% { opacity: .8; } 99% { opacity: 0; } }
@keyframes cbxBoltB { 0% { opacity: 0; } 12% { opacity: 1; } 20% { opacity: 0; } 34% { opacity: 1; } 42% { opacity: 0; } 58% { opacity: 1; } 66% { opacity: .2; } 84% { opacity: 1; } 92% { opacity: 0; } }
/* a charge: sparks pulled in, a humming glow */
.cbx-suck { animation: cbxSuck var(--t, .42s) cubic-bezier(.5,0,.9,.5) var(--d, 0s) both; }
@keyframes cbxSuck { 0% { opacity: 0; transform: translate(calc(var(--dx) * var(--u)), calc(var(--dy) * var(--u))) scale(1.1); } 25% { opacity: 1; } 100% { opacity: 0; transform: translate(0, 0) scale(.3); } }
.cbx-hum { animation: cbxHum var(--t, .6s) linear var(--d, 0s) both; }
@keyframes cbxHum { 0% { opacity: 0; transform: scale(.3); } 12% { opacity: .9; transform: scale(.8); } 30% { opacity: .6; transform: scale(.7); } 48% { opacity: 1; transform: scale(.95); } 66% { opacity: .7; transform: scale(.85); } 86% { opacity: 1; transform: scale(1.1); } 100% { opacity: 0; transform: scale(1.4); } }
/* the gym goes dark behind the fighters */
.cbx-dim { position: absolute; inset: -3%; z-index: 1; pointer-events: none; opacity: 0;
  background: radial-gradient(ellipse at 72% 42%, rgba(12,26,72,.25), var(--dc, rgba(3,7,24,.66)) 70%); animation: cbxDim var(--t, 1.4s) ease var(--d, 0s) both; }
@keyframes cbxDim { 0% { opacity: 0; } 18% { opacity: 1; } 78% { opacity: 1; } 100% { opacity: 0; } }

/* a pet with his lightning running through it */
.cbr-zap { animation: cbrZap .56s steps(1) var(--hd, 0s) both; }
@keyframes cbrZap { 0% { transform: none; } 8% { transform: translate(-4%, 1%) scale(1.05, .95); } 16% { transform: translate(4%, -1%) scale(.96, 1.04); } 24% { transform: translate(-3%, 0); }
  32% { transform: translate(3%, 1%); } 42% { transform: translate(-2%, -1%); } 54% { transform: translate(2%, 0); } 66% { transform: translate(-1%, 0); } 80%, 100% { transform: none; } }
.cbx-elec { position: absolute; left: 0; right: 0; top: 2%; bottom: 0; border-radius: 50%; pointer-events: none; opacity: 0; mix-blend-mode: screen;
  background: radial-gradient(circle, rgba(232,251,255,.9) 0 14%, rgba(75,211,255,.7) 34%, rgba(75,211,255,0) 66%); animation: cbxElec var(--t, .7s) steps(1) var(--d, 0s) both; }
@keyframes cbxElec { 0% { opacity: 0; } 1% { opacity: 1; } 10% { opacity: .2; } 18% { opacity: .9; } 28% { opacity: .1; } 38% { opacity: .7; } 50% { opacity: .15; } 62% { opacity: .55; } 76% { opacity: .1; } 88% { opacity: .35; } 99% { opacity: 0; } }

/* the team shield, drawn by the beat (the stage shows it already used up) */
.cbx-dome { position: absolute; left: 1%; bottom: 9%; width: 53%; height: 64%; border-radius: 46%; pointer-events: none; opacity: .85;
  border: calc(var(--u) * .4) solid rgba(36,211,238,.75); background: radial-gradient(closest-side, rgba(36,211,238,.08), rgba(36,211,238,.2)); box-shadow: 0 0 calc(var(--u) * 2.4) rgba(36,211,238,.5);
  animation: cbxDomeBreak .34s ease-out var(--d, .5s) forwards; }
.cbx-dome-crack { position: absolute; inset: 0; opacity: 0; animation: cbxOn 1ms linear calc(var(--d, .5s) - .07s) forwards; }
.cbx-dome-crack svg { width: 100%; height: 100%; display: block; overflow: visible; filter: drop-shadow(0 0 calc(var(--u) * .5) #4bd3ff); }
@keyframes cbxDomeBreak { 0% { opacity: .85; transform: none; } 18% { opacity: 1; transform: scale(1.03); } 100% { opacity: 0; transform: scale(1.1); } }
@keyframes cbxOn { from { opacity: 0; } to { opacity: 1; } }

/* the cut-in: a slanted banner in from his side, a held beat, gone */
.cbc { position: absolute; left: -8%; right: -8%; top: 7%; height: calc(var(--u) * 19); z-index: 8; pointer-events: none; opacity: 0;
  transform: skewY(-5deg) translateX(70%); animation: cbcIn var(--t, .65s) cubic-bezier(.2,1,.3,1) var(--d, 0s) both; }
@keyframes cbcIn { 0% { opacity: 0; transform: skewY(-5deg) translateX(70%); } 1% { opacity: 1; } 17% { transform: skewY(-5deg) translateX(0); } 78% { opacity: 1; transform: skewY(-5deg) translateX(-3%); } 100% { opacity: 0; transform: skewY(-5deg) translateX(-55%); } }
.cbc-band { position: absolute; inset: 0; overflow: hidden; background: #06122e;
  border-top: calc(var(--u) * .5) solid #bff4ff; border-bottom: calc(var(--u) * .5) solid #bff4ff; box-shadow: 0 0 calc(var(--u) * 2.6) rgba(75,211,255,.75); }
.cbc-storm .cbc-band { border-color: #c9a2ff; box-shadow: 0 0 calc(var(--u) * 2.6) rgba(170,110,255,.75); }
.cbc-band > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: var(--op, 50% 45%);
  transform: skewY(5deg) scale(1.16); animation: cbcPush var(--t, .65s) linear var(--d, 0s) both; user-select: none; }
@keyframes cbcPush { from { transform: skewY(5deg) scale(1.16); } to { transform: skewY(5deg) scale(1.26); } }
.cbc-sheen { position: absolute; top: 0; bottom: 0; left: 0; width: 18%; background: linear-gradient(90deg, rgba(255,255,255,0), rgba(255,255,255,.55), rgba(255,255,255,0));
  transform: translateX(-120%) skewX(-20deg); animation: cbcSheen calc(var(--t, .65s) * .55) ease-out calc(var(--d, 0s) + var(--t, .65s) * .12) both; }
@keyframes cbcSheen { from { transform: translateX(-120%) skewX(-20deg); } to { transform: translateX(640%) skewX(-20deg); } }
.cbc-txt { position: absolute; left: 13%; bottom: calc(var(--u) * -1.8); display: flex; flex-direction: column; align-items: flex-start; transform: skewY(5deg); }
.cbc-txt b { font-family: var(--font-d, 'Sora', sans-serif); font-weight: 800; font-size: calc(var(--u) * 5.4); line-height: 1; letter-spacing: .03em; color: #fff; white-space: nowrap;
  -webkit-text-stroke: calc(var(--u) * .35) #0b2f63; paint-order: stroke fill; text-shadow: 0 0 calc(var(--u) * 1.6) #4bd3ff, calc(var(--u) * .45) calc(var(--u) * .45) 0 #06122e; }
.cbc-txt small { margin-top: calc(var(--u) * .5); padding: calc(var(--u) * .35) calc(var(--u) * 1.2); border-radius: 99px; font-weight: 800; font-size: calc(var(--u) * 1.6); letter-spacing: .12em; color: #06122e; background: var(--cb-gold, #ffd24d); white-space: nowrap; }
.cbc-storm .cbc-txt b { text-shadow: 0 0 calc(var(--u) * 1.6) #b884ff, calc(var(--u) * .45) calc(var(--u) * .45) 0 #12062e; -webkit-text-stroke-color: #2a0b5e; }
/* Chain Lightning's banner, built from his chain-3 frame */
.cbc-proc { position: absolute; inset: 0; background: radial-gradient(ellipse at 82% 55%, #6fe0ff 0, #2563eb 26%, #0b1d5c 62%, #050c26 100%); }
.cbc-rays { position: absolute; inset: 0; opacity: .5; background: repeating-linear-gradient(180deg, rgba(255,255,255,0) 0 7%, rgba(200,240,255,.5) 7% 8%, rgba(255,255,255,0) 8% 17%);
  animation: cbcRays .35s linear infinite; }
@keyframes cbcRays { from { transform: translateX(0); } to { transform: translateX(-12%); } }
.cbc-arcs { position: absolute; inset: 0; width: 100%; height: 100%; }
.cbc-arc { opacity: 0; animation: cbxBoltA .5s steps(1) calc(var(--d, 0s) + .08s) infinite; }
.cbc-arc-b { animation-name: cbxBoltB; }
.cbc-fig { position: absolute; right: 2%; top: -4%; height: 210%; width: auto; transform: skewY(5deg); filter: drop-shadow(0 0 calc(var(--u) * 1) rgba(140,230,255,.8)); }

/* a hologram (his Starting Five, a copied pet) */
.cbx-holo { position: absolute; width: calc(var(--w, 12) * var(--u)); aspect-ratio: var(--har, 1); transform: translateX(-50%); pointer-events: none; }
.cbh-run, .cbh-img { position: absolute; inset: 0; display: block; }
.cbh-img { transform-origin: 50% 100%; opacity: 0;
  filter: grayscale(1) sepia(1) hue-rotate(158deg) saturate(3) brightness(1.6) drop-shadow(0 0 calc(var(--u) * .2) #fff) drop-shadow(0 0 calc(var(--u) * 1.1) rgba(75,211,255,.95));
  -webkit-mask-image: repeating-linear-gradient(180deg, #000 0 calc(var(--u) * .4), rgba(0,0,0,.5) calc(var(--u) * .4) calc(var(--u) * .65));
  mask-image: repeating-linear-gradient(180deg, #000 0 calc(var(--u) * .4), rgba(0,0,0,.5) calc(var(--u) * .4) calc(var(--u) * .65));
  animation: cbhIn .34s ease-out var(--din, 0s) both, cbhOut .28s ease-in var(--dout, 99s) forwards; }
.cbh-img img, .cbh-img > span, .cbh-img svg { display: block; width: 100%; height: 100%; object-fit: contain; }
.cbh-pet.pl-flip { transform: scaleX(-1); }
@keyframes cbhIn { 0% { opacity: 0; transform: scale(.6, 0); } 35% { opacity: 1; transform: scale(.92, 1.12); } 50% { opacity: .35; } 62% { opacity: .95; transform: none; } 78% { opacity: .55; } 100% { opacity: .88; transform: none; } }
@keyframes cbhOut { 0% { opacity: .88; transform: none; } 30% { opacity: .3; transform: scale(1.15, .9); } 55% { opacity: .8; } 100% { opacity: 0; transform: scale(1.6, .02); } }
.cbh-floor { position: absolute; left: 10%; right: 10%; bottom: -5%; height: 12%; border-radius: 50%; opacity: 0; pointer-events: none;
  background: radial-gradient(closest-side, rgba(150,235,255,.85), rgba(75,211,255,.25) 60%, rgba(75,211,255,0));
  animation: cbhFloor .3s ease-out var(--din, 0s) both, cbxOff .25s ease-in var(--dout, 99s) forwards; }
@keyframes cbhFloor { from { opacity: 0; transform: scaleX(.2); } to { opacity: .85; transform: none; } }
@keyframes cbxOff { to { opacity: 0; } }
.cbh-rush { animation: cbhRush var(--rt, .4s) cubic-bezier(.55,0,.85,.55) var(--rd, 0s) both; }
@keyframes cbhRush { 0% { transform: none; } 14% { transform: translateX(calc(var(--u) * 1.6)) scale(.95, 1.05); }
  90% { opacity: 1; transform: translate(calc(var(--dx) * var(--u)), calc(var(--dy) * var(--u))) scale(1.04, .96); } 100% { opacity: 0; transform: translate(calc(var(--dx) * 1.04 * var(--u)), calc(var(--dy) * var(--u))) scale(1.2, .85); } }
.cbh-dash { animation: cbhDash var(--rt, .7s) cubic-bezier(.3,.9,.3,1) var(--rd, 0s) both; }
@keyframes cbhDash { 0% { transform: none; } 22% { transform: translateX(calc(var(--u) * 2)) scale(.95, 1.05); } 46% { transform: translateX(calc(var(--dx) * var(--u))) scale(1.06, .95); }
  60% { transform: translateX(calc(var(--dx) * .9 * var(--u))); } 100% { transform: none; } }
.cbh-cast { animation: cbhCast var(--rt, .7s) ease-in-out var(--rd, 0s) both; }
@keyframes cbhCast { 0% { transform: none; } 40% { transform: translateY(calc(var(--u) * -2.6)) scale(1.04); } 70% { transform: translateY(calc(var(--u) * -2)); } 100% { transform: none; } }
/* a copied orb, in his colours */
.cbh-tint { display: block; width: 100%; height: 100%; filter: grayscale(1) sepia(1) hue-rotate(158deg) saturate(4.2) brightness(1.25); }
.cbh-tint svg { width: 100%; height: 100%; }
/* Copycat: a pet's own recipe, mirrored and aimed (js copyLayer) */
.cb-copy { position: absolute; inset: 0; pointer-events: none; }
.cb-copy-mir { position: absolute; inset: 0; transform: scaleX(-1); }
.cb-copy .sfx { position: absolute; inset: 0; z-index: auto; }

/* the yellow card */
.cbx-card { filter: drop-shadow(0 calc(var(--u) * .3) calc(var(--u) * .4) rgba(0,0,0,.45)); }

/* Timeout: his clipboard, out of his hand into the middle of the court */
.cbt { position: absolute; left: 42%; bottom: 25%; width: calc(var(--u) * 23); z-index: 7; pointer-events: none; opacity: 0;
  animation: cbtIn .32s cubic-bezier(.2,1.25,.4,1) var(--d, .6s) both, cbtOut .26s ease-in var(--out, 1.8s) forwards; }
@keyframes cbtIn { 0% { opacity: 0; transform: translate(calc(var(--u) * 20), calc(var(--u) * -3)) scale(.3) rotate(14deg); } 100% { opacity: 1; transform: rotate(-3deg); } }
@keyframes cbtOut { 0% { opacity: 1; transform: rotate(-3deg); } 100% { opacity: 0; transform: translate(calc(var(--u) * 20), calc(var(--u) * -3)) scale(.3) rotate(14deg); } }
.cbt-board { position: relative; padding: calc(var(--u) * 1.8) calc(var(--u) * 1.1) calc(var(--u) * 1.1); border-radius: calc(var(--u) * 1.2);
  background: linear-gradient(160deg, #c99251, #8c5629); box-shadow: 0 calc(var(--u) * .8) calc(var(--u) * 2.2) rgba(0,0,0,.55), inset 0 0 0 calc(var(--u) * .25) rgba(255,255,255,.14);
  animation: cbtSlap .34s ease-out var(--h, 1.4s) both; }
@keyframes cbtSlap { 0% { transform: none; } 30% { transform: scale(1.09) rotate(2.5deg); } 100% { transform: none; } }
.cbt-clip { position: absolute; left: 50%; top: calc(var(--u) * -.9); width: 42%; height: calc(var(--u) * 2.6); transform: translateX(-50%); border-radius: calc(var(--u) * .6);
  background: linear-gradient(180deg, #f1f5fa, #98a5b8); box-shadow: 0 calc(var(--u) * .2) calc(var(--u) * .4) rgba(0,0,0,.45); }
.cbt-paper { min-height: calc(var(--u) * 19); padding: calc(var(--u) * 1.5) calc(var(--u) * 1.2) calc(var(--u) * 1.1); border-radius: calc(var(--u) * .5); background-color: #fbfaf3;
  background-image: repeating-linear-gradient(180deg, transparent 0 calc(var(--u) * 2.9), rgba(75,156,211,.2) calc(var(--u) * 2.9) calc(var(--u) * 3.05)); }
.cbt-head { display: block; margin-bottom: calc(var(--u) * .9); font-family: var(--font-d, 'Sora', sans-serif); font-weight: 800; font-size: calc(var(--u) * 2.8); letter-spacing: .07em; color: #d22b3c; transform: rotate(-2deg); }
.cbt ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: calc(var(--u) * .9); }
.cbt-row { position: relative; display: flex; align-items: center; gap: calc(var(--u) * .8); font-weight: 800; font-size: calc(var(--u) * 1.75); line-height: 1.1; color: #13294b; }
.cbt-ic { position: relative; display: inline-grid; place-items: center; flex: none; width: calc(var(--u) * 2.9); height: calc(var(--u) * 2.9); border-radius: 50%; }
.cbt-ic svg { width: 66%; height: 66%; }
.cbt-focus .cbt-ic { background: #ffe1ef; color: #e0408a; }
.cbt-cross .cbt-ic { background: #fff1c2; color: #b07800; }
.cbt-shield .cbt-ic { background: #d6f6fc; color: #0aa0c0; }
.cbt-lb { animation: cbtDim .2s ease var(--x, 1s) both; }
@keyframes cbtDim { from { opacity: 1; } to { opacity: .42; } }
.cbt-strike { position: absolute; left: -3%; right: -3%; top: 50%; height: calc(var(--u) * .6); margin-top: calc(var(--u) * -.3); border-radius: 99px; background: #e0283c;
  transform-origin: 0 50%; transform: scaleX(0) rotate(-4deg); animation: cbtStrike .16s ease-out var(--x, 1s) forwards; }
@keyframes cbtStrike { to { transform: scaleX(1) rotate(-4deg); } }
.cbt-play svg { display: block; width: 100%; height: auto; }
.cbt-note { display: block; margin-top: calc(var(--u) * .8); font-weight: 700; font-size: calc(var(--u) * 1.5); color: #5b6b85; }
/* each buff on the court until he crosses it off */
.cbx.cbx-hold { opacity: 1; animation: cbxHoldOff .3s ease-in var(--x, 1s) forwards; }
.cbx-hold-sig { color: #ffd24d; filter: drop-shadow(0 0 calc(var(--u) * .4) #000); }
@keyframes cbxHoldOff { 0% { opacity: 1; transform: none; } 40% { opacity: 1; transform: scale(1.35) rotate(12deg); } 100% { opacity: 0; transform: scale(.2) rotate(-30deg); } }
.cbx-hold-aura { position: absolute; inset: 6%; border-radius: 50%; pointer-events: none; mix-blend-mode: screen; opacity: .75;
  background: radial-gradient(circle, rgba(255,158,203,.55), rgba(255,158,203,0) 66%); animation: cbxOff .25s ease-in var(--x, 1s) forwards; }

/* Double Overtime: a tag on both of his moves */
.cbx-dot { position: absolute; right: 3%; top: 15%; z-index: 8; display: flex; align-items: center; gap: calc(var(--u) * .8); padding: calc(var(--u) * .5) calc(var(--u) * 1.2);
  border-radius: 99px; background: rgba(30,8,70,.85); border: calc(var(--u) * .25) solid #c9a2ff; box-shadow: 0 0 calc(var(--u) * 1.6) rgba(170,110,255,.7); pointer-events: none;
  animation: cbxDotIn .4s cubic-bezier(.2,1.4,.4,1) .1s both; }
.cbx-dot b { font-family: var(--font-d, 'Sora', sans-serif); font-weight: 800; font-size: calc(var(--u) * 1.6); letter-spacing: .08em; color: #fff; }
.cbx-dot i { font-style: normal; font-weight: 800; font-size: calc(var(--u) * 1.4); color: #1a0640; background: #c9a2ff; border-radius: 99px; padding: 0 calc(var(--u) * .7); }
@keyframes cbxDotIn { from { opacity: 0; transform: scale(.4); } to { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: reduce) {
  .cbx-bolt, .cbc-arc { animation-name: cbxFade !important; animation-timing-function: ease !important; }
  .cbx-suck, .cbh-run, .cbr-zap { animation: none !important; }
  .cbc { animation-name: cbxFade !important; transform: none !important; }
  .cbt { animation: cbxFade calc(var(--out, 1.8s) - var(--d, .6s) + .26s) linear var(--d, .6s) both !important; transform: none !important; }
  .cbc-band > img, .cbc-rays, .cbc-sheen { animation: none !important; }
  .cbx-elec, .cbx-hum { animation-name: cbxFade !important; animation-timing-function: ease !important; }
}

/* ============================================================
   THE BIG MOMENTS (js/cb-fx.js coachPhase, coachDown, endBeat, koBeat, missBeat)
   ============================================================ */
.cbx-bg-in { opacity: 0; animation: cbxOn var(--t, .3s) ease-out var(--d, 1s) forwards; }
.cbm-power { animation: cbmPower var(--bt, 2.8s) linear var(--bd, 0s) both; }
@keyframes cbmPower { 0% { transform: none; } 6% { transform: translate(2%, 0) rotate(2deg); } 14% { transform: none; } 30% { transform: translateY(1.5%) scale(1.02, .98); }
  34% { transform: translate(.5%, 1.5%) scale(1.02, .98); } 38% { transform: translate(-.5%, 1.5%) scale(1.02, .98); } 42% { transform: translate(.6%, 1.8%) scale(1.03, .97); }
  45% { transform: translateY(-2.5%) scale(.97, 1.05); } 56% { transform: translateY(-.5%); } 70%, 100% { transform: none; } }
.cbm-rise { animation: cbmRise var(--bt, 2.8s) ease-in-out var(--bd, 0s) both; }
@keyframes cbmRise { 0% { transform: none; } 30% { transform: translateY(1%) scale(1.02, .98); } 40% { transform: translate(.5%, 1.2%) scale(1.03, .97); } 44% { transform: translate(-.5%, 1%) scale(1.03, .97); }
  47% { transform: translateY(-7%) scale(.97, 1.04); } 62% { transform: translateY(-4.5%); } 80% { transform: translateY(-2.5%); } 100% { transform: none; } }
.cbm-ko { animation: cbmKo var(--bt, 1.5s) cubic-bezier(.3,.8,.3,1) var(--bd, 0s) both; }
@keyframes cbmKo { 0% { transform: none; } 6% { transform: translate(6%, -2%) rotate(6deg) scale(1.04); } 22% { transform: translate(7%, -1%) rotate(7deg); } 45% { transform: translate(5%, 1%) rotate(3deg); }
  62% { transform: translate(2%, 2%) scale(1.02, .97); } 70% { transform: translateY(0) scale(1.03, .96); } 100% { transform: none; } }
.cbm-dodge { animation: cbmDodge var(--bt, .52s) ease-out var(--bd, 0s) both; }
@keyframes cbmDodge { 0% { transform: none; } 30% { transform: translateX(5%) rotate(4deg); } 60% { transform: translateX(4%) rotate(2deg); } 100% { transform: none; } }
.cbp-banner { animation-duration: 1.45s; }
.cbd-banner-coach { animation-duration: 2.1s; }
.cbd-banner-coach b { font-size: calc(var(--u) * 5.4); }
.cbv-banner, .cbw-banner { animation-duration: 1.6s; }
.cbv-banner b { font-size: calc(var(--u) * 8); color: #fff3c4; }
.cbw-banner b { color: #dfe7ff; }
.cbw-banner small { background: #c9d2ef; }
/* the team celebrates */
.cbr-cheer { animation: cbrCheer .9s ease-out var(--hd, 0s) both; }
@keyframes cbrCheer { 0% { transform: none; } 10% { transform: scale(1.08, .9); } 28% { transform: translateY(-16%) rotate(-5deg); } 44% { transform: translateY(0) scale(1.06, .93); }
  60% { transform: translateY(-10%) rotate(4deg); } 76% { transform: translateY(0) scale(1.04, .96); } 100% { transform: none; } }
/* Coach Brady, good sport */
.cbx-bubble { position: absolute; z-index: 6; transform: translate(-50%, 0); padding: calc(var(--u) * .7) calc(var(--u) * 1.3); border-radius: calc(var(--u) * 1.4); background: #fff; color: #13294b; white-space: nowrap;
  font-family: var(--font-d, 'Sora', sans-serif); font-weight: 800; font-size: calc(var(--u) * 2.2); box-shadow: 0 calc(var(--u) * .4) calc(var(--u) * 1) rgba(0,0,0,.4); pointer-events: none; opacity: 0;
  animation: cbxBubble .4s cubic-bezier(.2,1.5,.4,1) var(--d, .5s) both; }
.cbx-bubble::after { content: ''; position: absolute; right: 18%; bottom: calc(var(--u) * -1); border: calc(var(--u) * .6) solid transparent; border-top: calc(var(--u) * .9) solid #fff; border-bottom: 0; }
@keyframes cbxBubble { from { opacity: 0; transform: translate(-50%, 30%) scale(.4); } to { opacity: 1; transform: translate(-50%, 0); } }
/* a pet knocked out: it reels and sinks, then goes grey */
.cb-pet-slot.ko.cb-ko-now { animation: cbKoGray .5s ease .45s both; }
@keyframes cbKoGray { from { filter: none; opacity: 1; } to { filter: grayscale(1) brightness(.6); opacity: .55; } }
.cbr-ko { animation: cbrKo 1s ease-in-out var(--hd, 0s) both; }
@keyframes cbrKo { 0% { transform: none; } 14% { transform: translateY(-10%) rotate(-6deg); } 30% { transform: rotate(5deg); } 48% { transform: translateY(5%) rotate(-11deg) scale(1.12, .72); }
  78% { transform: translateY(4%) rotate(-8deg) scale(1.06, .8); } 100% { transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .cbx-bubble, .cbv-banner, .cbw-banner, .cbp-banner { animation-name: cbxFade !important; transform: translate(-50%, -50%); }
  .cbx-bubble { transform: translate(-50%, 0); }
  .cbr-ko { animation: none !important; }
}

/* ============================================================
   THE COMEBACK (js/cb-fx.js comebackBeats, 2026-10-11): "Oh no. I say
   when we're done." — the first time he wipes a team with a new kid in it
   ============================================================ */
/* THE FAKE DEFEAT: the real TEAM WIPED card slams in and STAYS (the real
   one fades), and the court goes grey and dark under it */
.cbk-hold { animation: cbkSlam .6s cubic-bezier(.2,1.3,.4,1) var(--d, .12s) both; }
@keyframes cbkSlam { 0% { opacity: 0; transform: translate(-50%, -50%) scale(2.2); } 45% { opacity: 1; transform: translate(-50%, -50%) scale(.95); }
  70% { transform: translate(-50%, -50%) scale(1.03); } 100% { opacity: 1; transform: translate(-50%, -50%) scale(1); } }
.cbk-defeat, .cbk-grey { position: absolute; inset: 0; z-index: 7; pointer-events: none; opacity: 0; animation: cbxOn .55s ease var(--d, .12s) forwards; }
.cbk-defeat { background: radial-gradient(ellipse at 50% 45%, rgba(10,14,30,.12), rgba(10,14,30,.7)); }
.cbk-grey { background: #8a8a8a; mix-blend-mode: saturation; --op: .85; animation-name: cbkGrey; }
@keyframes cbkGrey { to { opacity: var(--op, .85); } }
/* …until the record scratch: the grey lifts, the card is knocked off the court */
.cbk-defeat.cbk-lift { opacity: 1; animation: cbxOff .35s ease-out var(--x, .04s) forwards; }
.cbk-grey.cbk-lift { opacity: .85; animation: cbxOff .35s ease-out var(--x, .04s) forwards; }
.cbk-cut { opacity: 1; animation: cbkCut .55s cubic-bezier(.55,0,.85,.4) var(--x, .04s) forwards; }
@keyframes cbkCut { 0% { opacity: 1; transform: translate(-50%, -50%); } 16% { opacity: 1; transform: translate(-51%, -50%) rotate(-3deg) scale(1.05); }
  100% { opacity: 0; transform: translate(-22%, 30%) rotate(16deg) scale(.86); } }
/* the fake result card in the command box: the real one's look, buttons that do nothing */
.cbk-fake .btn { pointer-events: none; }
/* his lines: bigger than "Good game.", with a gold rim. Placed by its RIGHT
   edge, level with his mouth (js/cb-fx.js), so it sits beside his face,
   never on it; it pops out of its tail, which points straight in at him.
   "Oh no…" gives way to the rest. */
.cbk-bubble { z-index: 7; transform: none; transform-origin: 100% 50%; font-size: calc(var(--u) * 3.2); padding: calc(var(--u) * 1) calc(var(--u) * 1.8);
  border-radius: calc(var(--u) * 1.8);
  box-shadow: 0 0 0 calc(var(--u) * .35) var(--cb-gold, #ffd24d), 0 calc(var(--u) * .5) calc(var(--u) * 1.4) rgba(0,0,0,.5);
  animation: cbkBubble .4s cubic-bezier(.2,1.5,.4,1) var(--d, .2s) both; }
.cbk-bubble::after { right: calc(var(--u) * -1.2); top: 50%; bottom: auto; margin-top: calc(var(--u) * -.85);
  border-style: solid; border-width: calc(var(--u) * .85) 0 calc(var(--u) * .85) calc(var(--u) * 1.5); border-color: transparent transparent transparent #fff; }
@keyframes cbkBubble { from { opacity: 0; transform: translateX(8%) scale(.4); } to { opacity: 1; transform: none; } }
.cbk-bubble-out { animation: cbkBubble .4s cubic-bezier(.2,1.5,.4,1) var(--d, .2s) both, cbxOff .12s linear var(--o, 1s) forwards; }
/* the light gathering in a knocked-out pet while he gets the whistle up */
.cbk-gather { animation: cbkGather 1.1s ease-in var(--d, .7s) both; }
@keyframes cbkGather { 0% { opacity: 0; transform: scale(.4); } 70% { opacity: .9; } 100% { opacity: 1; transform: scale(1.05); } }
/* gold light up the pet as the bolt lands */
.cbx-heal.cbk-col { background: linear-gradient(0deg, rgba(255,214,90,.8), rgba(255,246,200,0)); animation-duration: 1.15s; }
/* back up: grey and flat → a jolt of gold → springs up off the floor → lands */
.cbr-revive { animation: cbrRevive 1.15s cubic-bezier(.2,.9,.3,1) var(--hd, 0s) both; }
@keyframes cbrRevive {
  0% { opacity: .55; filter: grayscale(1) brightness(.6); transform: translateY(4%) scale(1.06, .82); }
  12% { opacity: 1; filter: grayscale(0) brightness(2.4); transform: translateY(3%) scale(1.1, .78); }
  38% { filter: brightness(1.45); transform: translateY(-22%) scale(.9, 1.14); }
  60% { filter: brightness(1.1); transform: translateY(0) scale(1.1, .9); }
  78% { transform: translateY(-4%) scale(.98, 1.03); }
  100% { opacity: 1; filter: none; transform: none; } }
.cbk-num { --fs: 5.2; }
/* the bar refills gold (it would start red: its colour follows where it was) */
.cb-pet-slot.cbk-up .hpbar .hp-fill { background: linear-gradient(180deg, #ffe58a, #ffc21a); box-shadow: 0 0 calc(var(--u) * .8) rgba(255,214,90,.7); }
.cbk-banner { animation-duration: 1.95s; }
.cbk-banner b { font-size: calc(var(--u) * 7.4); color: #fff3c4; }
@media (prefers-reduced-motion: reduce) {
  .cbk-hold { animation: none !important; opacity: 1; transform: translate(-50%, -50%); }
  .cbk-cut { animation: cbxOff .3s linear var(--x, .04s) forwards !important; transform: translate(-50%, -50%); }
  .cbk-gather { animation-name: cbxFade !important; }
  .cbk-bubble { transform: none; }
  .cbk-banner { animation-name: cbxFade !important; transform: translate(-50%, -50%); }
}

/* ============================================================
   THE SCOUTING REVEAL (js/view-coachbrady.js revealArt): each stage's
   moment, played once the first time a kid sees it (tap him to replay)
   ============================================================ */
.cb-hero-art[data-cb-rvplay] { cursor: pointer; }
.cb-rvfx { position: absolute; inset: 0; pointer-events: none; }
.cb-rvfx i, .cb-rvfx b { position: absolute; display: block; }
.cb-rvfx-svg { position: absolute; inset: -4% -10%; width: 120%; height: 108%; overflow: visible; }
.cb-rvb { opacity: 0; animation: cbxBoltA .5s steps(1) var(--d, 0s) both; filter: drop-shadow(0 0 3px #4bd3ff); }
/* 0: out of the dark */
.cb-rv-play0 > img { animation: cbRvEmerge 1.6s ease-out both; }
@keyframes cbRvEmerge { 0% { opacity: 0; transform: scale(.96); } 60% { opacity: .9; } 100% { opacity: 1; transform: none; } }
.cb-rvfx-fog { inset: 40% -20% -6% -20%; border-radius: 50%; background: radial-gradient(closest-side, rgba(110,150,210,.4), rgba(110,150,210,0)); animation: cbRvFog 2.2s ease-out both; }
@keyframes cbRvFog { 0% { opacity: 0; transform: translateX(-12%) scaleX(.8); } 30% { opacity: 1; } 100% { opacity: 0; transform: translateX(10%) scaleX(1.2); } }
/* 1: the whistle flares */
.cb-rvfx-flare { width: 62%; aspect-ratio: 1; transform: translate(-50%, -50%) scale(0); opacity: 0;
  background: radial-gradient(circle, #fff 0 8%, rgba(255,214,90,.9) 18%, rgba(255,201,77,0) 52%),
    linear-gradient(90deg, transparent 48%, rgba(255,240,190,.9) 49.5% 50.5%, transparent 52%), linear-gradient(0deg, transparent 48%, rgba(255,240,190,.9) 49.5% 50.5%, transparent 52%);
  animation: cbRvFlare 1s cubic-bezier(.2,1.2,.4,1) .1s both; }
@keyframes cbRvFlare { 0% { opacity: 0; transform: translate(-50%, -50%) scale(0) rotate(0); } 25% { opacity: 1; transform: translate(-50%, -50%) scale(1.3) rotate(25deg); } 100% { opacity: 0; transform: translate(-50%, -50%) scale(.6) rotate(60deg); } }
/* 2: the eyes snap on */
.cb-rvfx-eye { width: 26%; background: radial-gradient(circle, #fff 0 10%, rgba(140,235,255,.95) 22%, rgba(75,211,255,0) 56%); animation-duration: .8s; }
.cb-rv-play2 .cb-rv-eye { animation: cbRvEyesOn .5s steps(1) both, cbEyes 1.4s ease-in-out .5s infinite; }
@keyframes cbRvEyesOn { 0% { opacity: 0; } 20% { opacity: 1; } 35% { opacity: 0; } 50% { opacity: 1; } 65% { opacity: .2; } 80%, 100% { opacity: 1; } }
/* 3 and 4: lightning, a white-out */
.cb-rvfx-flash { inset: -30%; border-radius: 50%; background: radial-gradient(closest-side, rgba(255,255,255,.95), rgba(190,240,255,.6) 45%, rgba(190,240,255,0)); opacity: 0;
  animation: cbxFlash .6s ease-out var(--d, .1s) both; --fo: 1; }
.cb-hero-jolt { animation: cbRvJolt .5s ease .12s both; }
@keyframes cbRvJolt { 0%, 100% { transform: none; } 20% { transform: translate(-4px, 2px); } 40% { transform: translate(4px, -2px); } 60% { transform: translate(-2px, 1px); } 80% { transform: translate(2px, 0); } }
/* 4: revealed — the silhouette, a bolt, white, and there he is */
.cb-rv-play4 { position: relative; }
.cb-rv-play4 .cb-rv-sil { animation: cbxOff .25s ease-in .62s forwards; }
.cb-rv-play4 .cb-rv-full { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; animation: cbxOn .5s ease-out .66s forwards; }
.cb-rvfx-name { left: 50%; bottom: 3%; transform: translate(-50%, 0) rotate(-4deg); padding: 4px 14px; border-radius: 10px; white-space: nowrap; opacity: 0;
  font-family: var(--font-d, 'Sora', sans-serif); font-weight: 800; font-size: 1.15rem; letter-spacing: .08em; color: #0a1020; background: var(--cb-gold, #ffd24d);
  box-shadow: 0 0 18px rgba(255,210,77,.6), 0 6px 14px rgba(0,0,0,.45); animation: cbRvName .5s cubic-bezier(.2,1.6,.4,1) 1.05s both, cbxOff .5s ease 3.4s forwards; }
@keyframes cbRvName { 0% { opacity: 0; transform: translate(-50%, 0) rotate(-4deg) scale(2.4); } 100% { opacity: 1; transform: translate(-50%, 0) rotate(-4deg) scale(1); } }
@media (prefers-reduced-motion: reduce) {
  .cb-rvb, .cb-rvfx-flare, .cb-rvfx-fog, .cb-hero-jolt { animation: none !important; opacity: 0; }
  .cb-rv-play0 > img, .cb-rv-play2 .cb-rv-eye { animation: none !important; }
  .cb-rvfx-name { animation: cbxFade 3s ease 1s both !important; transform: translate(-50%, 0) rotate(-4deg); }
}
