/* Ohara motion layer (run 3, extended in run 5: anticipation beats, the odds
   meter, the layered foil, offset & delay in runs, compositor-only fixes -
   web/DESIGN.md "Motion" has the research and the pacing table). Three parts:
   1. Page motion - ambient, and every loop points at something real (the
      pack = the action, the ladder = the odds, the pool = what's left).
      Ambient loops animate transform/opacity only, so they run on the
      compositor and never repaint the page (the run-2 holo and sheen loops
      repainted every frame; see web/DESIGN.md section P0).
   2. The reveal theatre - a full-screen, timed sequence choreographed by
      theatre.js: enter -> anticipation -> tension -> tear -> rise (card back) ->
      climb (with the chase fake-out) -> flip -> impact -> settled, plus the
      multi-pack deal (r-card), the run rail, the end-of-run board and the
      in-theatre question. theatre.js sets data-stage for transient
      animations, cumulative classes (is-on, is-packed, is-ripped, is-out,
      is-flipped, is-burst, is-settled, is-run, is-board) for held states,
      data-glow for the colour climbing the ladder, data-tier for the pull.
   3. Reduced motion: .is-calm and prefers-reduced-motion get a real, working
      opacity-only path. Tokens live in app.css. */

/* =========================== 1. PAGE MOTION =========================== */
@keyframes float{0%,100%{transform:translateY(0) rotate(-2deg)}50%{transform:translateY(-12px) rotate(1.5deg)}}
@keyframes sheen{0%,58%{transform:translateX(0)}100%{transform:translateX(440px)}}
@keyframes halo{0%,100%{opacity:.65;transform:scale(1)}50%{opacity:1;transform:scale(1.1)}}
@keyframes ping{0%{transform:scale(1);opacity:.9}100%{transform:scale(3.4);opacity:0}}
@keyframes cta-shine{0%,62%{transform:translateX(-140%) skewX(-20deg)}100%{transform:translateX(420%) skewX(-20deg)}}
@keyframes cell-in{from{transform:scale(0);opacity:0}}
@keyframes bar-grow{from{transform:scaleX(0)}}
@keyframes rung-in{from{opacity:0;transform:translateY(10px)}}
@keyframes rung-shine{0%,55%{transform:translateX(-100%)}100%{transform:translateX(100%)}}
@keyframes ladder-ping{from{opacity:.9;transform:scale(1)}to{opacity:0;transform:scale(1.035)}}
@keyframes rise-in{from{opacity:0;transform:translateY(16px)}}
@keyframes feed-in{from{opacity:0;transform:translateX(-14px) scale(.96)}}
@keyframes holo{from{transform:translateX(-62%)}to{transform:translateX(62%)}}
@keyframes new-glow{0%,100%{opacity:.3}50%{opacity:1}}
@keyframes fan-in{from{opacity:0;transform:translateY(40px) rotate(0) scale(.8)}}
@keyframes marquee{to{transform:translateX(-50%)}}
@keyframes tile-in{from{opacity:0;transform:translateY(22px) scale(.97)}}

.pack-stage .pack-object,.hero-pack .pack-object{animation:float 6s var(--ease-io) infinite;transform-origin:50% 60%}
.pack-halo{animation:halo 4s ease-in-out infinite}
.storefront.is-armed .pack-stage .pack-object{animation-duration:2.6s}
.storefront.is-armed .pack-halo{background:radial-gradient(circle,rgba(255,154,31,.55),transparent 65%);animation-duration:1.6s}
.live-dot::after{animation:ping 1.8s ease-out infinite}
.open-button::before{content:'';position:absolute;top:0;bottom:0;left:0;width:28%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.5),transparent);transform:translateX(-140%) skewX(-20deg);pointer-events:none}
.open-button:not(:disabled)::before{animation:cta-shine 2.8s var(--ease-io) infinite}

.waffle i{animation:cell-in .5s var(--ease-spring) backwards;animation-delay:calc(var(--i,0) * 6ms)}
.rung{animation:rung-in .5s var(--ease-out) backwards;animation-delay:calc(var(--i,0) * 80ms)}
.rung .bar-fill{transform-origin:left;animation:bar-grow 1s var(--ease-out) backwards;animation-delay:calc(var(--i,0) * 80ms + 150ms)}
.rung[data-tier="chase"]::after{content:'';position:absolute;inset:0;background:linear-gradient(100deg,transparent 30%,rgba(255,230,160,.2) 50%,transparent 70%);transform:translateX(-100%);animation:rung-shine 3.6s ease-in-out infinite;pointer-events:none}
/* the ladder pings when the stock under it moves: a ring that scales and fades (no box-shadow repaint) */
.ladder{position:relative}
.ladder::after{content:'';position:absolute;inset:-2px;border-radius:inherit;border:2px solid rgba(53,208,255,.75);opacity:0;pointer-events:none}
.ladder.is-updated::after{animation:ladder-ping 1.2s var(--ease-out)}

/* holo: a wide gradient slid with transform (compositor only). In grids it is
   static until hovered; the showcase, hero and best-pull frames keep it live. */
.tcg-card .holo{position:absolute;inset:0;z-index:1;pointer-events:none;overflow:hidden;mix-blend-mode:color-dodge;opacity:.5}
.tcg-card .holo::before{content:'';position:absolute;top:0;bottom:0;left:-80%;width:260%;background:linear-gradient(115deg,transparent 25%,rgba(255,255,255,.42) 42%,rgba(140,230,255,.32) 50%,rgba(255,140,230,.28) 58%,transparent 75%);transform:translateX(0)}
.tcg-card[data-tier="hit"] .holo{opacity:.6}
.tcg-card[data-tier="chase"] .holo{opacity:.75}
.showcase-fan .holo::before,.hero-fan .holo::before,.rb-frame .holo::before,.tcg-card:hover .holo::before{animation:holo 5s linear infinite}
.showcase-fan [data-tier="hit"] .holo::before,.hero-fan [data-tier="hit"] .holo::before{animation-duration:4s}
.showcase-fan [data-tier="chase"] .holo::before,.hero-fan [data-tier="chase"] .holo::before,.rb-frame[data-tier="chase"] .holo::before{animation-duration:3.2s}
.tcg-card.is-tilting .holo::before{animation:none;transform:translateX(calc(var(--mx,50%) - 50%))}
/* foil (hit, chase): a spectral band instead of the plain sheen, a glare that
   follows the pointer, and on a chase two glitter layers drifting in opposite
   directions under a diagonal mask. The whole group is composited onto the
   art with color-dodge; every moving layer moves with transform only. */
.tcg-card .holo.foil::before{background:linear-gradient(115deg,transparent 16%,rgba(255,90,170,.36) 29%,rgba(255,214,90,.36) 37%,rgba(90,255,190,.34) 45%,rgba(90,180,255,.36) 53%,rgba(200,110,255,.34) 61%,transparent 76%)}
.foil-glare,.foil-glitter{position:absolute;inset:0;pointer-events:none}
.foil-glare{opacity:0;transition:opacity .3s}
.foil-glare::before,.t-glare::before{content:'';position:absolute;left:-50%;top:-50%;width:200%;height:200%;
  background:radial-gradient(closest-side,rgba(255,255,255,.85),rgba(255,255,255,.18) 45%,transparent 70%);transform:translate(calc((var(--mx,30%) - 50%) / 2),calc((var(--my,25%) - 50%) / 2))}
.tcg-card.is-tilting .foil-glare,.tcg-card:hover .foil-glare{opacity:.9}
.foil-glitter,.t-glitter{-webkit-mask-image:linear-gradient(115deg,transparent 14%,#000 38%,#000 62%,transparent 86%);mask-image:linear-gradient(115deg,transparent 14%,#000 38%,#000 62%,transparent 86%)}
.foil-glitter::before,.foil-glitter::after,.t-glitter::before,.t-glitter::after{content:'';position:absolute;inset:-25%;
  background:radial-gradient(circle,#fff 0 .7px,transparent 1.3px) 0 0/9px 11px,radial-gradient(circle,#fff3c4 0 .6px,transparent 1.2px) 4px 5px/13px 7px}
.foil-glitter::after,.t-glitter::after{background-size:11px 9px,7px 13px;background-position:2px 3px,6px 1px;opacity:.75}
@keyframes glitter-a{from{transform:translate(0,0)}to{transform:translate(8%,-5%)}}
@keyframes glitter-b{from{transform:translate(0,0)}to{transform:translate(-8%,5%)}}
.showcase-fan .foil-glitter::before,.hero-fan .foil-glitter::before,.rb-frame .foil-glitter::before,.tcg-card:hover .foil-glitter::before{animation:glitter-a 7s ease-in-out infinite alternate}
.showcase-fan .foil-glitter::after,.hero-fan .foil-glitter::after,.rb-frame .foil-glitter::after,.tcg-card:hover .foil-glitter::after{animation:glitter-b 7s ease-in-out infinite alternate}
.showcase-fan .tcg-card{animation:fan-in .8s var(--ease-out) backwards;transition:transform .5s var(--ease-out),filter .5s}
.showcase-fan .fan-1{animation-delay:.12s}.showcase-fan .fan-2{animation-delay:.2s}
.showcase-fan:hover .fan-1{transform:rotate(-22deg) translate(-34px,22px) scale(.86);filter:brightness(.9)}
.showcase-fan:hover .fan-2{transform:rotate(16deg) translate(34px,22px) scale(.86);filter:brightness(.9)}
.showcase-fan .fan-0.tilt{transform:rotate(-4deg) perspective(900px) rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg))}
.hero-fan .tcg-card{animation:fan-in .9s var(--ease-out) backwards}
.hero-fan .fan-1{animation-delay:.1s}.hero-fan .fan-2{animation-delay:.18s}
.pool-wall.is-first .pool-card{animation:rise-in .5s var(--ease-out) backwards;animation-delay:calc(var(--i,0) * 24ms)}
.feed li.is-new{animation:feed-in .55s var(--ease-spring) backwards}
.vault-card.is-new .tcg-card::after{content:'';position:absolute;inset:0;z-index:2;border-radius:inherit;pointer-events:none;box-shadow:inset 0 0 0 2px var(--tier-c,var(--ok)),inset 0 0 22px var(--tier-g,rgba(63,224,160,.45));opacity:0;animation:new-glow 1.4s ease-in-out 3}
.pack-tile{animation:tile-in .55s var(--ease-out) backwards;animation-delay:calc(var(--i,0) * 32ms)}
.rail-track{animation:marquee calc(var(--n,10) * 2.8s) linear infinite}
.rail-viewport:hover .rail-track,.rail-viewport:focus-within .rail-track{animation-play-state:paused}

/* Screens are real pages: cross-document view transitions make moving between
   them a crossfade, and morph a catalogue pack into the pack page's pack. */
@view-transition{navigation:auto}
::view-transition-old(root){animation:vt-out .2s var(--ease-in) both}
::view-transition-new(root){animation:vt-in .34s var(--ease-out) both}
@keyframes vt-out{to{opacity:0;transform:translateY(-6px)}}
@keyframes vt-in{from{opacity:0;transform:translateY(10px)}}
::view-transition-group(pack-hero){animation-duration:.5s;animation-timing-function:var(--ease-out)}

/* =========================== 2. THE THEATRE =========================== */
html.theatre-open{overflow:hidden}
.theatre{position:fixed;inset:0;z-index:100;display:flex;align-items:center;justify-content:center;padding:84px 24px 64px;overflow:hidden;color:var(--text);
  --card-w:min(330px,44vh,72vw);--glow-c:#ffffff;--glow-g:rgba(255,255,255,.22);--amp:1;--dim:.9}
.theatre:not([data-tier]){--tier-c:#fff;--tier-g:rgba(255,255,255,.22)}
.theatre[data-glow="base"]{--glow-c:var(--base);--glow-g:var(--base-g)}
.theatre[data-glow="plus"]{--glow-c:var(--plus);--glow-g:var(--plus-g)}
.theatre[data-glow="hit"]{--glow-c:var(--hit);--glow-g:var(--hit-g)}
.theatre[data-glow="chase"]{--glow-c:var(--chase);--glow-g:var(--chase-g)}

.t-backdrop{position:absolute;inset:0;background:#03040a;opacity:0;transition:opacity .45s ease}
.theatre.is-on .t-backdrop{opacity:var(--dim)}
.t-vignette{position:absolute;inset:0;pointer-events:none;opacity:0;background:radial-gradient(ellipse at center,transparent 38%,rgba(0,0,0,.8) 100%);transition:opacity .6s}
.theatre.is-on .t-vignette{opacity:.75}
.theatre.is-redline .t-vignette{background:radial-gradient(ellipse at center,transparent 30%,rgba(255,40,40,.5) 100%);animation:redline .46s ease-in-out infinite alternate}
@keyframes redline{from{opacity:.35}to{opacity:1}}
/* the spotlight: a cone of light from above, on the pack while it waits */
.t-spot{position:absolute;left:50%;top:-12vh;width:min(90vmin,760px);height:112vh;transform:translateX(-50%);pointer-events:none;opacity:0;transition:opacity .6s;
  background:linear-gradient(180deg,rgba(255,255,255,.2),var(--glow-g) 55%,transparent 92%);clip-path:polygon(42% 0,58% 0,100% 100%,0 100%);mix-blend-mode:screen}
.theatre[data-stage="anticipation"] .t-spot,.theatre[data-stage="tension"] .t-spot,.theatre[data-stage="windup"] .t-spot,.theatre[data-stage="tear"] .t-spot{opacity:.55}
.theatre[data-stage="windup"] .t-spot{opacity:.75}
.theatre[data-stage="climb"] .t-spot,.theatre[data-stage="fakeout"] .t-spot,.theatre[data-stage="cock"] .t-spot,.theatre[data-stage="flip"] .t-spot{opacity:.35}
.theatre.is-settled .t-spot,.theatre.is-board .t-spot{opacity:.12}
.t-flash{position:absolute;inset:0;z-index:6;pointer-events:none;opacity:0;background:radial-gradient(circle at 50% 50%,#fff 0,var(--glow-c) 35%,transparent 75%);mix-blend-mode:screen}

.t-top{position:absolute;top:0;left:0;right:0;z-index:10;display:flex;align-items:center;gap:12px;padding:16px clamp(16px,3vw,32px)}
/* O46 (U46-04, the owner's #414): one quiet mark, not a hazard pill - the theatre covers the page's footer */
.t-demo{font:600 11px/1 var(--sans);letter-spacing:.02em;color:rgba(236,232,222,.66);background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.14);border-radius:999px;padding:5px 9px}
.t-preview{font:700 10px/1 var(--display);letter-spacing:.2em;text-transform:uppercase;color:var(--hit);border:1px solid var(--hit);border-radius:999px;padding:5px 10px}
.t-count{position:absolute;left:50%;transform:translateX(-50%);font:700 13px/1 var(--display);letter-spacing:.24em;text-transform:uppercase;color:var(--text-2)}
.t-count b{font-size:26px;color:var(--text);letter-spacing:.02em;font-variant-numeric:tabular-nums}
.t-skip,.t-close,.t-results,.t-stop{background:rgba(255,255,255,.06);border:1px solid var(--line-2);color:var(--text);border-radius:999px;padding:9px 16px;font:600 13px/1 var(--sans);cursor:pointer}
.t-skip,.t-results{margin-left:auto}
.t-close{margin-left:auto}
.t-results{border-color:var(--plus);color:var(--plus)}
.t-stop{border-color:rgba(255,107,107,.5);color:var(--bad)}
.t-skip kbd{font-size:10px;color:var(--text-3);margin-left:6px}
.t-close{display:none}
.theatre.is-settled .t-skip,.theatre.is-board .t-skip{display:none}
.theatre.is-settled .t-close,.theatre.is-board .t-close{display:inline-block}
.theatre.is-board .t-results,.theatre.is-board .t-stop{display:none}

/* the ladder climb - the same four rungs the customer saw before buying */
.t-ladder{position:absolute;z-index:7;right:clamp(16px,4vw,56px);top:50%;transform:translateY(-50%);list-style:none;margin:0;padding:0;display:grid;gap:14px;opacity:0;transition:opacity .3s}
.t-ladder li{display:flex;align-items:center;justify-content:flex-end;gap:10px;font:700 12px/1 var(--display);letter-spacing:.22em;text-transform:uppercase;color:var(--text-3);transition:color .25s}
.t-ladder li::after{content:'';width:12px;height:12px;transform:rotate(45deg);border:2px solid currentColor;transition:background .25s,box-shadow .25s}
.t-ladder li.is-lit{color:var(--tier-c)}
.t-ladder li.is-lit::after{background:var(--tier-c);box-shadow:0 0 14px var(--tier-c)}
.t-ladder li small{min-width:8ch;font:600 11px/1 var(--mono);letter-spacing:0;text-transform:none;text-align:right;color:var(--text-3);font-variant-numeric:tabular-nums}
.t-ladder li small:empty{display:none}
.t-ladder li.is-lit small{color:var(--tier-c)}
.theatre[data-stage="climb"] .t-ladder,.theatre[data-stage="fakeout"] .t-ladder,.theatre[data-stage="cock"] .t-ladder,.theatre[data-stage="flip"] .t-ladder,.theatre[data-stage="tension"].is-run .t-ladder{opacity:1}

/* the odds meter: "1 in N" counts up the ladder, then names this card's own odds (text only; nothing moves) */
.t-meter{position:absolute;z-index:8;left:50%;bottom:calc(100% + 14px);margin:0;display:grid;justify-items:center;gap:3px;transform:translateX(-50%);opacity:0;pointer-events:none;white-space:nowrap;transition:opacity .25s var(--ease-out)}
.t-meter small{font:700 10px/1 var(--display);letter-spacing:.3em;color:var(--text-3)}
.t-meter b{min-width:9ch;text-align:center;font:700 clamp(26px,4.4vh,42px)/1 var(--display);letter-spacing:.02em;color:var(--glow-c);font-variant-numeric:tabular-nums;text-shadow:0 0 22px var(--glow-g)}
.t-meter span{font:600 11px/1 var(--mono);color:var(--text-2)}
.theatre.is-metered .t-meter{opacity:1}
.theatre.is-meter-card .t-meter small,.theatre.is-meter-card .t-meter b{color:var(--tier-c)}
.theatre.is-meter-card .t-meter b{text-shadow:0 0 30px var(--tier-g)}
.theatre.is-settled .t-meter,.theatre.is-board .t-meter{opacity:0}

/* the floor: pack and card share one card-sized slot */
.t-floor{position:relative;z-index:4;flex:none;width:var(--card-w);aspect-ratio:600/838;isolation:isolate;transform-origin:0 0}
.t-floor::before{content:'';position:absolute;z-index:-2;left:50%;top:50%;width:260%;height:200%;transform:translate(-50%,-50%);background:radial-gradient(closest-side,var(--glow-g),transparent);opacity:0;transition:opacity .5s}
.theatre[data-glow] .t-floor::before{opacity:1}
/* motes gather toward the pack before a big pull (hit, chase) */
.t-floor::after{content:'';position:absolute;z-index:-1;left:50%;top:50%;width:240%;height:180%;transform:translate(-50%,-50%) scale(1.6);opacity:0;pointer-events:none;
  background:radial-gradient(circle,var(--glow-c,#fff) 0 1.2px,transparent 2px) 0 0/38px 38px;-webkit-mask-image:radial-gradient(closest-side,transparent 30%,#000 55%,transparent 72%);mask-image:radial-gradient(closest-side,transparent 30%,#000 55%,transparent 72%)}
.theatre.is-gathering .t-floor::after,.theatre[data-stage="tension"] .t-floor::after{animation:gather 1.4s ease-in infinite}
@keyframes gather{0%{opacity:0;transform:translate(-50%,-50%) scale(1.7) rotate(0)}30%{opacity:.7}100%{opacity:0;transform:translate(-50%,-50%) scale(.55) rotate(40deg)}}
.t-rays{position:absolute;z-index:-1;left:50%;top:50%;width:170vmax;height:170vmax;margin:-85vmax 0 0 -85vmax;color:var(--glow-c);fill:currentColor;opacity:0;pointer-events:none;transition:opacity .6s;
  -webkit-mask-image:radial-gradient(closest-side,#000 6%,transparent 62%);mask-image:radial-gradient(closest-side,#000 6%,transparent 62%)}
.theatre:not([hidden]) .t-rays{animation:spin 22s linear infinite;will-change:transform}
.theatre[data-tier="chase"].is-burst .t-rays{animation-duration:9s}
@keyframes spin{to{transform:rotate(360deg)}}
.theatre.is-burst .t-rays{opacity:var(--rays,.5)}
.theatre.is-settled .t-rays,.theatre.is-board .t-rays{opacity:calc(var(--rays,.5) * .45)}
.t-ring{position:absolute;z-index:0;left:50%;top:50%;width:100%;aspect-ratio:1;border-radius:50%;border:3px solid var(--tier-c,#fff);box-shadow:0 0 30px var(--tier-g,rgba(255,255,255,.3)),inset 0 0 30px var(--tier-g,rgba(255,255,255,.3));opacity:0;pointer-events:none;transform:translate(-50%,-50%)}
.t-slam{position:absolute;z-index:0;left:50%;top:50%;margin:0;transform:translate(-50%,-50%);opacity:0;pointer-events:none;white-space:nowrap;
  font:700 clamp(72px,15vw,220px)/1 var(--display);letter-spacing:.12em;color:transparent;-webkit-text-stroke:2px var(--tier-c);text-shadow:0 0 40px var(--tier-g)}
.theatre[data-tier="chase"] .t-slam{color:rgba(255,197,58,.18);-webkit-text-stroke:3px var(--chase)}
.t-particles{position:absolute;z-index:5;left:50%;top:50%;width:0;height:0;pointer-events:none}
.t-particles i{position:absolute;left:0;top:0;width:var(--sz);height:calc(var(--sz) * .55);border-radius:2px;background:var(--pc);opacity:0;box-shadow:0 0 6px var(--pc);animation:particle var(--dur) cubic-bezier(.2,.7,.3,1) var(--delay) forwards}
.t-particles i.is-confetti{width:calc(var(--sz) * .6);height:calc(var(--sz) * 1.3);border-radius:1px;box-shadow:none}
@keyframes particle{
  0%{opacity:1;transform:translate(-50%,-50%) rotate(0) scale(.3)}
  60%{opacity:1;transform:translate(calc(-50% + var(--tx)),calc(-50% + var(--ty))) rotate(calc(var(--rot) * .6)) scale(1)}
  100%{opacity:0;transform:translate(calc(-50% + var(--tx) * 1.08),calc(-50% + var(--ty) + var(--fall))) rotate(var(--rot)) scale(.9)}
}

.t-pack{position:absolute;inset:0;z-index:2;opacity:0}
.t-pack .pack-svg{width:100%;height:100%;animation:none;overflow:visible;filter:drop-shadow(0 30px 40px rgba(0,0,0,.65))}
.t-pack .pk-soldout{display:none}
.t-pack .pack-leak{fill:var(--glow-c)}
.t-pack .pack-strip{transform-box:fill-box;transform-origin:0% 100%}
/* the light beam out of the torn top */
.t-pack::after{content:'';position:absolute;left:50%;top:8%;width:82%;height:150%;transform:translate(-50%,-100%) scaleY(0);transform-origin:50% 100%;opacity:0;pointer-events:none;
  background:linear-gradient(0deg,var(--glow-c),rgba(255,255,255,.35) 30%,transparent 85%);filter:blur(5px)}
.theatre.is-ripped:not(.is-out) .t-pack::after{animation:beam var(--d-tear,400ms) ease-out forwards}
@keyframes beam{0%{opacity:0;transform:translate(-50%,-100%) scaleY(0)}35%{opacity:.85}100%{opacity:.5;transform:translate(-50%,-100%) scaleY(1)}}
.theatre.is-packed .t-pack{opacity:1}
.theatre[data-stage="enter"] .t-pack{animation:pack-enter .42s var(--ease-spring) both}
@keyframes pack-enter{from{opacity:0;transform:translateY(45%) scale(.7) rotate(-7deg)}}
.theatre[data-stage="anticipation"] .t-pack{animation:breathe 1.8s var(--ease-io) infinite}
@keyframes breathe{0%,100%{transform:translateY(0) scale(1)}50%{transform:translateY(-8px) scale(1.015)}}
.theatre[data-stage="tension"] .t-pack{animation:pack-shake .38s ease-in-out infinite}
@keyframes pack-shake{
  0%,100%{transform:translate(0,0) rotate(0)}
  20%{transform:translate(calc(var(--amp) * -1px),calc(var(--amp) * .4px)) rotate(calc(var(--amp) * -.5deg))}
  40%{transform:translate(calc(var(--amp) * 1px),calc(var(--amp) * -.3px)) rotate(calc(var(--amp) * .5deg))}
  60%{transform:translate(calc(var(--amp) * -.7px),calc(var(--amp) * -.4px)) rotate(calc(var(--amp) * -.3deg))}
  80%{transform:translate(calc(var(--amp) * .6px),calc(var(--amp) * .3px)) rotate(calc(var(--amp) * .3deg))}
}
.theatre[data-stage="tension"] .pack-leak{animation:leak .45s ease-in-out infinite alternate}
@keyframes leak{from{opacity:.15}to{opacity:calc(.25 + var(--amp) * .06)}}
/* the strip tears from its notch: the right end lifts while the left end still holds, then it comes away */
.theatre.is-ripped .t-pack .pack-strip{transform:translate(-34px,-170px) rotate(-38deg);opacity:0;animation:strip-peel var(--d-tear,400ms) cubic-bezier(.3,0,.2,1) both}
@keyframes strip-peel{0%{transform:none;opacity:1}38%{transform:rotate(-11deg) translate(-2px,-4px);opacity:1}100%{transform:translate(-34px,-170px) rotate(-38deg);opacity:0}}
.theatre.is-ripped .t-pack .pack-leak{opacity:1;transition:opacity .15s}
.theatre[data-stage="rise"] .t-pack{animation:pack-drop var(--d-rise,500ms) var(--ease-in) both}
@keyframes pack-drop{0%,42%{transform:none;opacity:1}100%{transform:translateY(85%) rotate(7deg) scale(.95);opacity:0}}
.theatre.is-out .t-pack{opacity:0;visibility:hidden}

.t-card{position:absolute;inset:0;z-index:1;opacity:0}
.theatre[data-stage="rise"] .t-card{opacity:1;animation:card-rise var(--d-rise,500ms) var(--ease-out) both}
@keyframes card-rise{
  0%{transform:translateY(10%) scale(.94);z-index:1}
  45%{transform:translateY(-64%) scale(.97);z-index:1}
  46%{z-index:3}
  100%{transform:none;z-index:3}
}
.theatre.is-out .t-card{opacity:1;z-index:3}
.theatre.is-run .t-card{display:none}
.t-card-tilt{width:100%;height:100%;transform:perspective(1100px) rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg));transition:transform .25s var(--ease-out)}
.t-card-inner{position:relative;width:100%;height:100%;transform-style:preserve-3d;transition:transform var(--d-flip,500ms) var(--flip-ease,var(--ease-out))}
.theatre.is-flipped .t-card-inner{transform:rotateY(var(--flip-turn,180deg))}
.t-face,.r-face{position:absolute;inset:0;border-radius:var(--r-card);overflow:hidden;-webkit-backface-visibility:hidden;backface-visibility:hidden}
.t-back,.r-back{display:grid;place-content:center;justify-items:center;gap:10px;color:#fff3c4;
  background:radial-gradient(circle at 50% 46%,rgba(255,197,58,.22),transparent 42%),repeating-linear-gradient(45deg,rgba(255,255,255,.045) 0 2px,transparent 2px 13px),repeating-linear-gradient(-45deg,rgba(255,255,255,.045) 0 2px,transparent 2px 13px),linear-gradient(160deg,#1d2142,#0a0c1b);
  border:7px solid #090a14;box-shadow:0 0 0 2px var(--glow-c),0 0 34px var(--glow-g),0 30px 60px rgba(0,0,0,.6)}
.t-back::after,.r-back::after{content:'';position:absolute;inset:0;background:rgba(3,4,10,.55);opacity:0;transition:opacity .3s;pointer-events:none}
/* the card-back ladder (Theatre.setBack): the pack's price band's back art over the drawn back */
.theatre.has-back .t-back,.theatre.has-back .r-back{background:var(--card-back) center/cover no-repeat,#0a0c1b;border-color:#06070d}
.theatre.has-back .t-back>*,.theatre.has-back .r-back>*{visibility:hidden}
.t-card::before,.r-card::before{content:'';position:absolute;inset:0;z-index:-1;border-radius:var(--r-card);pointer-events:none;opacity:0;transition:opacity .3s;
  box-shadow:0 0 0 3px var(--glow-c),0 0 60px var(--glow-g),0 0 140px var(--glow-g)}
.t-back-ring{width:46%;aspect-ratio:1;border-radius:50%;border:3px solid var(--chase);box-shadow:inset 0 0 0 9px rgba(0,0,0,.35),inset 0 0 0 11px rgba(255,197,58,.35),0 0 24px rgba(255,197,58,.25);background:radial-gradient(circle,#2b0b1d 0 12%,transparent 13%)}
.t-back b,.r-back b{font:700 clamp(16px,3vh,26px)/1 var(--display);letter-spacing:.34em;margin-right:-.34em}
.t-back small{font:700 10px/1 var(--display);letter-spacing:.3em;color:var(--chase);max-width:90%;text-align:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.theatre[data-stage="climb"] .t-card::before,.theatre[data-stage="cock"] .t-card::before,.theatre[data-stage="climb"] .r-card::before,.theatre[data-stage="tension"] .r-card::before,.theatre[data-stage="cock"] .r-card:last-of-type::before{opacity:1}
.theatre[data-stage="fakeout"] .t-back::after,.theatre[data-stage="fakeout"] .r-back::after{opacity:1}
.t-front{transform:rotateY(180deg);background:linear-gradient(160deg,var(--ink-3),var(--ink-1));box-shadow:0 30px 60px rgba(0,0,0,.6)}
.theatre.is-flipped .t-front{box-shadow:0 0 0 2px var(--tier-c),0 0 60px var(--tier-g),0 30px 60px rgba(0,0,0,.6)}
.theatre.is-flipped[data-tier="base"] .t-front{box-shadow:0 0 0 1px rgba(255,255,255,.25),0 30px 60px rgba(0,0,0,.6)}
.reveal-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.reveal-card{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:space-between;padding:18px;background:radial-gradient(circle at 50% 35%,var(--tier-g),transparent 60%),linear-gradient(160deg,var(--ink-3),var(--ink-1))}
.reveal-card span{font:700 12px/1 var(--display);letter-spacing:.24em;color:var(--tier-c)}
.reveal-card b{font:700 clamp(24px,4vh,36px)/1 var(--display);text-transform:uppercase}
.reveal-card small{font:600 11px/1.4 var(--sans);color:var(--text-2)}
.t-holo{position:absolute;inset:0;pointer-events:none;opacity:0;overflow:hidden;mix-blend-mode:color-dodge;transition:opacity .6s}
.t-holo::before{content:'';position:absolute;top:0;bottom:0;left:-80%;width:260%;background:linear-gradient(115deg,transparent 22%,rgba(255,255,255,.45) 40%,rgba(140,230,255,.35) 48%,rgba(255,140,230,.3) 56%,transparent 72%)}
.theatre.is-flipped:not([data-tier="base"]) .t-holo{opacity:.55}
.theatre.is-flipped:not([data-tier="base"]) .t-holo::before{animation:holo 4.5s linear infinite}
.theatre.is-flipped[data-tier="chase"] .t-holo{opacity:.8}
.theatre.is-flipped[data-tier="chase"] .t-holo::before{animation-duration:2.8s}
.theatre.is-tilting .t-holo::before{animation:none;transform:translateX(calc(var(--mx,50%) - 50%))}
.theatre[data-tier="hit"] .t-holo::before,.theatre[data-tier="chase"] .t-holo::before{background:linear-gradient(115deg,transparent 16%,rgba(255,90,170,.4) 29%,rgba(255,214,90,.4) 37%,rgba(90,255,190,.38) 45%,rgba(90,180,255,.4) 53%,rgba(200,110,255,.38) 61%,transparent 76%)}
.t-glare,.t-glitter{position:absolute;inset:0;pointer-events:none;opacity:0;transition:opacity .4s}
.theatre.is-flipped[data-tier="hit"] .t-glare,.theatre.is-flipped[data-tier="chase"] .t-glare{opacity:.4}
.theatre.is-tilting[data-tier="hit"] .t-glare,.theatre.is-tilting[data-tier="chase"] .t-glare{opacity:.95}
.theatre.is-flipped[data-tier="chase"] .t-glitter{opacity:1}
.theatre.is-flipped[data-tier="chase"] .t-glitter::before{animation:glitter-a 7s ease-in-out infinite alternate}
.theatre.is-flipped[data-tier="chase"] .t-glitter::after{animation:glitter-b 7s ease-in-out infinite alternate}

.t-status{position:absolute;left:50%;top:calc(100% + 22px);transform:translateX(-50%);margin:0;white-space:nowrap;font:700 13px/1 var(--display);letter-spacing:.3em;text-transform:uppercase;color:var(--glow-c);transition:color .25s}
.theatre[data-stage="climb"] .t-status{font-size:18px;text-shadow:0 0 18px var(--glow-g)}
.theatre.is-settled .t-status{display:none}

/* settled: identity panel slides in beside the card (below it on narrow screens) */
.t-info{display:none;position:relative;z-index:7;width:min(460px,100%);max-height:calc(100vh - 150px);overflow:auto;padding:4px 6px 4px 0}
.theatre.is-settled{gap:clamp(28px,6vw,96px);overflow-x:hidden}
.theatre.is-settled .t-info{display:block;animation:info-in .6s var(--ease-out) backwards}
@keyframes info-in{from{opacity:0;transform:translateY(24px)}}
.t-badge{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin:0 0 14px}
.t-badge-tier{font:700 14px/1 var(--display);letter-spacing:.26em;text-transform:uppercase;color:var(--ink-0);background:var(--tier-c);border-radius:999px;padding:8px 14px;box-shadow:0 0 24px var(--tier-g)}
.theatre[data-tier="chase"] .t-badge-tier{background:linear-gradient(90deg,#fff3c4,var(--chase),var(--chase-2))}
.t-badge-odds{font:600 13px/1.3 var(--sans);color:var(--text-2)}
.t-info h2{font-size:clamp(34px,4.6vw,60px);line-height:.95;text-transform:uppercase;margin:0 0 10px}
.theatre[data-tier="chase"] .t-info h2{background:linear-gradient(180deg,#fff3c4,var(--chase) 60%,var(--chase-2));-webkit-background-clip:text;background-clip:text;color:transparent}
.t-printing{font:600 15px/1.4 var(--display);letter-spacing:.06em;color:var(--text);margin:0 0 8px}
.t-sub{font-size:13px;color:var(--text-2);margin:0 0 18px;line-height:1.55}
.t-actions{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.t-actions .open-button{grid-column:1/-1}
.theatre.is-settled #reveal-share{animation:nudge 1.1s ease-in-out .9s 2}
@keyframes nudge{0%,100%{transform:none}30%{transform:translateY(-3px) scale(1.04)}}
.t-share-note{min-height:1.2em;font-size:12px;color:var(--ok);margin:8px 0 0}
.t-receipt{margin-top:10px;border-top:1px solid var(--line);padding-top:10px;font-size:12px}
.t-receipt summary{cursor:pointer;color:var(--text-2)}
.t-receipt .kv{font-size:11px}
.theatre.is-preview .t-receipt,.theatre.is-preview #reveal-share,.theatre.is-preview #reveal-vault{display:none}

/* --- multi-pack run: dealt cards, the rail, the board, the question --- */
.theatre.is-run{--card-w:min(300px,38vh,64vw);padding-bottom:clamp(170px,24vh,240px)}
.r-card{position:absolute;inset:0;z-index:4;perspective:1100px}
.r-inner{position:relative;width:100%;height:100%;transform-style:preserve-3d}
.r-front{transform:rotateY(180deg);background:linear-gradient(160deg,var(--ink-3),var(--ink-1));box-shadow:0 30px 60px rgba(0,0,0,.6)}
.r-card.is-up .r-front{box-shadow:0 0 0 2px var(--tier-c),0 0 50px var(--tier-g),0 30px 60px rgba(0,0,0,.6)}
.r-card[data-tier="base"].is-up .r-front{box-shadow:0 0 0 1px rgba(255,255,255,.25),0 30px 60px rgba(0,0,0,.6)}
.r-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.r-cap{position:absolute;left:0;right:0;bottom:0;padding:10px;font:700 14px/1.1 var(--display);text-transform:uppercase;background:linear-gradient(0deg,rgba(0,0,0,.8),transparent)}
.r-img~.r-cap{display:none}
.t-rail{position:absolute;left:50%;bottom:clamp(14px,3vh,28px);transform:translateX(-50%);z-index:8;width:min(1040px,94vw);margin:0;padding:0;list-style:none;
  display:grid;grid-template-columns:repeat(auto-fit,minmax(40px,58px));justify-content:center;gap:6px}
.t-rail.is-dense{grid-template-columns:repeat(var(--cols,18),minmax(0,1fr));gap:5px}
.t-rail li{position:relative;aspect-ratio:600/838;border-radius:5px;border:1px dashed var(--line-2);background:rgba(255,255,255,.03);display:grid;place-items:center;overflow:hidden;font:700 11px var(--display);color:var(--text-3)}
.t-rail li img{width:100%;height:100%;object-fit:cover;display:block}
.t-rail li.is-in{border:1px solid var(--tier-c);box-shadow:0 0 10px var(--tier-g)}
.t-rail li.is-in::after{content:'';position:absolute;inset:0;background:var(--tier-c);opacity:0;pointer-events:none;animation:slot-flash .5s ease-out}
.t-rail li.is-in[data-tier="hit"],.t-rail li.is-in[data-tier="chase"]{box-shadow:0 0 0 1px var(--tier-c),0 0 22px var(--tier-c)}
@keyframes slot-flash{from{opacity:.6}}
.t-board{position:relative;z-index:9;width:min(1120px,96vw);max-height:calc(100vh - 88px);overflow:auto;display:grid;gap:14px;padding:clamp(18px,3vw,30px);
  background:linear-gradient(160deg,var(--tier-g,rgba(255,255,255,.06)),transparent 45%),rgba(8,9,18,.94);border:1px solid var(--line-2);border-radius:var(--r-l);box-shadow:0 40px 100px rgba(0,0,0,.6)}
.theatre.is-board .t-floor,.theatre.is-board .t-ladder{display:none}
.rb-head h2{font-size:clamp(34px,4.6vw,60px);line-height:.95;text-transform:uppercase;margin:0 0 6px}
.rb-head .kicker{color:var(--tier-c)}
.rb-head .muted{margin:0}
.theatre.is-run.is-board{padding-top:68px;padding-bottom:20px}
.rb-body{display:grid;grid-template-columns:minmax(150px,min(230px,30vh)) minmax(0,1fr);gap:clamp(16px,3vw,32px);align-items:start}
.rb-best{margin:0;display:grid;gap:10px}
.rb-frame{display:block;box-shadow:0 0 0 2px var(--tier-c),0 0 60px var(--tier-g),0 30px 60px rgba(0,0,0,.6)}
.rb-frame img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.rb-best figcaption{display:grid;gap:4px;font-size:12px;color:var(--text-2)}
.rb-best figcaption b{font:700 22px/1.05 var(--display);text-transform:uppercase;color:var(--text)}
.rb-best figcaption .tier-chip{justify-self:start}
.t-board .rb-grid{grid-template-columns:repeat(auto-fill,minmax(84px,1fr));gap:8px}
.t-board .rb-grid li{aspect-ratio:600/838;border-radius:4px;overflow:hidden;border:1px solid var(--tier-c);background:var(--ink-2)}
.t-board .rb-grid li[data-tier="base"]{border-color:rgba(147,161,187,.35)}
.t-board .rb-grid li[data-tier="hit"],.t-board .rb-grid li[data-tier="chase"]{box-shadow:0 0 14px var(--tier-g)}
.t-board .rb-grid img{width:100%;height:100%;object-fit:cover;display:block}
.t-board .rb-grid li{animation:rise-in .42s var(--ease-out) backwards;animation-delay:calc(var(--i,0) * 14ms + 180ms)}
.t-board .rb-tiers li{animation:rise-in .45s var(--ease-out) backwards;animation-delay:calc(var(--i,0) * 70ms + 80ms)}
.rb-actions{display:flex;flex-wrap:wrap;gap:10px;align-items:center}
.rb-actions .open-button{width:auto;min-width:280px}
.t-ask{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:12;width:min(460px,90vw);display:grid;gap:10px;padding:22px;border-radius:var(--r-l);
  background:var(--ink-1);border:1px solid var(--warn);box-shadow:0 0 0 6px rgba(255,179,64,.12),0 40px 90px rgba(0,0,0,.75);animation:info-in .35s var(--ease-out)}
.t-ask h3{margin:0;color:var(--warn);text-transform:uppercase;letter-spacing:.04em}
.t-ask p{margin:0;font-size:13px;line-height:1.5;color:var(--text-2)}
.t-ask-actions{display:flex;flex-wrap:wrap;gap:10px;margin-top:6px}
.t-ask-actions .open-button{width:auto}

@media(max-width:820px){
  .theatre{padding:72px 16px 48px;--card-w:min(300px,46vh,74vw)}
  .theatre.is-settled{flex-direction:column;justify-content:flex-start;overflow-y:auto;gap:28px;--card-w:min(220px,32vh,58vw)}
  .theatre.is-run{--card-w:min(220px,34vh,60vw)}
  .t-info{max-height:none;overflow:visible;padding-bottom:24px}
  .t-top{flex-wrap:wrap;gap:8px;padding:12px 12px 12px 12px}
  .t-count{position:static;transform:none}
  .t-demo{white-space:nowrap}
  .t-preview{white-space:nowrap;font-size:9px;letter-spacing:.12em}
  .t-ladder{right:auto;left:50%;top:auto;bottom:18px;transform:translateX(-50%);display:flex;flex-direction:row-reverse;gap:14px}
  .theatre.is-run .t-ladder{bottom:auto;top:110px}
  .t-ladder li{flex-direction:column-reverse;gap:6px;font-size:10px;letter-spacing:.14em}
  .rb-body{grid-template-columns:1fr}
  .rb-best{grid-template-columns:120px 1fr;align-items:center}
}

/* O45-24 (owner: "deeper UI work and design"): on a phone the reveal is a stage of its own. The backdrop covers the
   screen however far the reveal scrolls (it was the scroll box's first screen only, so the page behind - its pack
   art, its sticky buy bar - showed through below it) and is solid once the card has landed; the page's buy bar is
   put away while the theatre is up; Close stays at the top and "Open another" at the bottom while the card's
   details scroll between them. */
html.theatre-open .mbb{visibility:hidden}
.t-backdrop,.t-vignette{position:fixed}
/* once the card has landed its words are read: the room stays dark enough that the page behind never competes */
.theatre.is-settled:not(.is-run) .t-backdrop{opacity:max(var(--dim),.95)}
/* O46 (U46-12): at 95% the page behind stayed readable on a desktop and ran into the reveal's own lines ("Half of
   all pulls are worth ..." beside the postage line, the ladder's figures at the right). A landed card and a run's
   board are read: the room behind them is solid, as it already was on a phone. */
.theatre.is-settled:not(.is-run) .t-backdrop,.theatre.is-board .t-backdrop{opacity:1}
@media(max-width:820px){
  .theatre.is-settled:not(.is-run) .t-backdrop{opacity:1}
  .theatre.is-settled:not(.is-run) .t-top{position:fixed;padding-bottom:22px;background:linear-gradient(180deg,#03040a 62%,rgba(3,4,10,0))}
  .theatre.is-settled:not(.is-run) .t-info{padding-bottom:0}
  .theatre.is-settled:not(.is-run) .t-actions{position:sticky;bottom:0;z-index:3;grid-template-columns:minmax(0,1fr) auto;align-items:stretch;
    margin:14px -16px 0;padding:18px 16px calc(14px + env(safe-area-inset-bottom,0px));background:linear-gradient(180deg,rgba(3,4,10,0),#03040a 26%)}
  .theatre.is-settled:not(.is-run) .t-actions .open-button{grid-column:auto;min-width:0}
  .theatre.is-settled:not(.is-run) .t-actions .cta-sub{font-size:11px}
  .theatre.is-settled:not(.is-run) #reveal-share{align-self:center;white-space:nowrap;padding-inline:14px}
  .theatre.is-settled:not(.is-run) .t-receipt{margin-top:14px}
  .theatre.is-settled:not(.is-run) .fine-print:last-child{margin-bottom:28px}
}

/* =========================== 3. REDUCED MOTION =========================== */
/* .is-calm is set by theatre.js when prefers-reduced-motion matches: the same
   stages run, but only as short opacity crossfades - no rip, flip, shake,
   rays, rings, slam, beam or particles. A run deals cards straight into the
   rail. Tier still reads through colour, glow and the badge. */
.theatre.is-calm *,.theatre.is-calm *::before,.theatre.is-calm *::after{animation:none!important}
.theatre.is-calm .t-pack,.theatre.is-calm .t-card,.theatre.is-calm .t-face,.theatre.is-calm .pack-strip,.theatre.is-calm .t-info{transition:opacity .25s linear!important;transform:none!important}
.theatre.is-calm .t-card-inner,.theatre.is-calm .t-card-tilt{transform:none!important;transition:none!important}
.theatre.is-calm .t-front{opacity:0}
.theatre.is-calm.is-flipped .t-front{opacity:1}
.theatre.is-calm.is-flipped .t-back{opacity:0}
.theatre.is-calm .t-rays,.theatre.is-calm .t-particles,.theatre.is-calm .t-flash,.theatre.is-calm .t-ring,.theatre.is-calm .t-slam,.theatre.is-calm .t-spot,.theatre.is-calm .t-floor::after,.theatre.is-calm .t-pack::after{display:none}
.theatre.is-calm.is-out .t-pack{opacity:0}

@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto}
  @view-transition{navigation:none}
  .pack-object,.pack-gloss::after,.pack-halo,.live-dot::after,.open-button::before,.waffle i,.rung,.rung .bar-fill,.rung::after,.ladder.is-updated,
  .tcg-card .holo::before,.foil-glitter::before,.foil-glitter::after,.showcase-fan .tcg-card,.hero-fan .tcg-card,.pool-wall.is-first .pool-card,.feed li.is-new,.vault-card.is-new .tcg-card::after,.pack-tile,.rail-track,.ladder.is-updated::after{animation:none!important}
  .rail-viewport{overflow-x:auto}
  .tilt,.showcase-fan .tcg-card,.vault-card .tcg-card,.open-button,.pack-tile,.pt-chase,.pt-pack{transition:none!important}
  .open-button:hover:not(:disabled),.pack-tile:hover{transform:none}
}

/* ==================== BOARD: what you pulled is worth something ====================
   The end-of-run board shows every card's value today and lets you pick the
   ones you don't want and sell them back on the spot. Values only - never a
   ratio, a margin or a return (design/tokenomics_policy.md section 3). */

.t-board .rb-grid li{position:relative}
.t-board .rb-grid li.is-pickable{cursor:pointer}
.t-board .rb-grid li.is-pickable:hover{transform:translateY(-2px)}
.t-board .rb-grid li.is-pickable:focus-visible{outline:2px solid var(--plus);outline-offset:2px}
.t-board .rb-grid li .rb-val{position:absolute;left:0;right:0;bottom:0;z-index:2;padding:16px 2px 5px;font:700 13px/1 var(--mono);letter-spacing:.01em;text-align:center;color:#fff;
  font-variant-numeric:tabular-nums;text-shadow:0 1px 4px rgba(0,0,0,.95);background:linear-gradient(180deg,transparent,rgba(4,5,12,.95) 46%)}
.t-board .rb-grid li.is-picked{border-color:var(--ok);box-shadow:0 0 0 2px var(--ok),0 0 20px rgba(63,224,160,.45)}
.t-board .rb-grid li.is-picked .rb-val{color:var(--ok)}
.t-board .rb-grid li.is-sold{opacity:.5;filter:saturate(.3)}
.t-board .rb-grid li.is-sold .rb-val{color:var(--ok);background:linear-gradient(180deg,transparent,rgba(4,5,12,.95) 45%)}
.rb-total{margin:10px 0 0;font-size:var(--fs-s);color:var(--text-2);line-height:1.6}
.rb-sellbar{display:grid;gap:12px;margin-top:14px;padding:14px 16px;border:1px solid var(--line-2);border-radius:var(--r-m);background:rgba(255,197,58,.05)}
.rb-quick{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.rb-sellbar .rb-sell-copy{margin:0;font-size:var(--fs-s);color:var(--text-2)}
.rb-sellbar .rb-sell-copy b{color:var(--text)}
.rb-sell-value{margin:0;min-height:24px;font:700 clamp(22px,2.4vw,30px)/1 var(--display);color:var(--chase);font-variant-numeric:tabular-nums}
.rb-sellbar .open-button{width:auto;min-width:280px}
/* The run's own headline number - every card this run pulled, priced today,
   live. Values only, never a ratio, a margin or a return (tokenomics section 3). */
.rb-head{display:flex;flex-wrap:wrap;gap:var(--s4);align-items:flex-end;justify-content:space-between}
.rb-head-copy{display:grid;gap:8px}
.rb-worth{display:grid;gap:2px;justify-items:end;text-align:right;padding:14px 18px;border:1px solid var(--line-2);border-radius:var(--r-m);
  background:linear-gradient(160deg,rgba(255,197,58,.12),transparent 70%),var(--ink-1)}
.rb-worth-k{margin:0;font:700 10px/1 var(--display);letter-spacing:.2em;text-transform:uppercase;color:var(--text-3)}
.rb-worth-v{margin:4px 0 0;display:flex;align-items:baseline;gap:10px;justify-content:flex-end}
.rb-worth-v b{font:700 clamp(34px,4.6vw,58px)/1 var(--display);color:var(--chase);font-variant-numeric:tabular-nums;letter-spacing:-.01em}
.rb-worth-v small{font:700 14px/1 var(--display);color:var(--text-2);letter-spacing:.04em}
.rb-worth-n{margin:2px 0 0;font-size:var(--fs-xs);color:var(--text-2)}
/* The pull's value, right under the card in the reveal. */
.t-worth{margin:0 0 14px;display:grid;gap:3px}
.t-worth b{font:700 clamp(30px,3.4vw,44px)/1 var(--display);color:var(--chase);font-variant-numeric:tabular-nums}
.t-worth span{font:600 12px/1.35 var(--sans);color:var(--text-2)}
@media(max-width:820px){.rb-worth{justify-items:start;text-align:left}.rb-worth-v{justify-content:flex-start}}
.t-share-note{margin:0}

/* ============ RUN WORTH: what this run has actually pulled, live ============
   While a multi-pack run deals, the top of the theatre answers the only
   question that matters: what is this worth? The last card's value and the
   run's running total. Every card that lands also carries its own price tag
   on the rail (hidden in dense runs, always in the hover title).
   Realised values only - never a ratio, a margin or a return
   (design/tokenomics_policy.md section 3). */

.t-runworth{position:absolute;top:100%;left:50%;transform:translateX(-50%);z-index:11;margin:0;pointer-events:none;
  display:flex;align-items:baseline;gap:10px;padding:6px 15px;border-radius:999px;white-space:nowrap;
  background:rgba(8,10,18,.74);border:1px solid var(--line-2);backdrop-filter:blur(6px);font-variant-numeric:tabular-nums}
.t-runworth small{font:700 9px/1 var(--display);letter-spacing:.22em;text-transform:uppercase;color:var(--text-3)}
.t-runworth b{font:700 clamp(16px,1.9vw,22px)/1 var(--display);color:var(--chase);letter-spacing:.01em}
.t-runworth span{font:600 12px/1 var(--sans);color:var(--text-2)}
.t-runworth.is-bump b{animation:runworth-bump .55s cubic-bezier(.16,1,.3,1)}
@keyframes runworth-bump{0%{transform:scale(.7);filter:brightness(1.8)}100%{transform:none;filter:none}}
.theatre.is-preview .t-runworth{display:none}
.t-rail li .r-worth{position:absolute;left:0;right:0;bottom:0;z-index:2;padding:2px 0;text-align:center;
  font:700 9px/1.3 var(--mono);color:#fff;letter-spacing:.01em;font-variant-numeric:tabular-nums;
  background:linear-gradient(0deg,rgba(0,0,0,.86),rgba(0,0,0,.3))}
@media(max-width:820px){.t-runworth{gap:8px;padding:5px 12px}.t-runworth span{font-size:11px}}

/* ---- run 8: every card on the rail keeps its value; the run total is handed to the board ----
   The rail deals a run of more than 20 cards into two rows (--cols = half the
   run, set by theatre.js), so a 36-pack run still gives each slot room for its
   berry chip - the berry mark and the exact count, the same integer the board shows.
   On a phone the dense rail is one row that scrolls with the deal. Every
   landed slot opens the card view. The readout's big number is the run total;
   at the end of the run it flies into the board's headline (handOver). */
.t-rail li .r-worth{font:700 10px/1.3 var(--mono);padding:2px 0 1px;color:#ffe9a8;text-shadow:0 1px 2px #000}
.t-rail li[data-tier="base"] .r-worth{color:#e8ecf5}
.t-rail.is-dense li .r-worth{font-size:9.5px;letter-spacing:-.02em}
.t-rail li[role="button"]{cursor:zoom-in}
.t-rail li[role="button"]:hover{border-color:var(--text);transform:translateY(-2px)}
.t-rail li[role="button"]:focus-visible{outline:2px solid var(--plus);outline-offset:2px}
@media(max-width:820px){
  .t-rail.is-dense{grid-template-columns:none;grid-auto-flow:column;grid-auto-columns:46px;justify-content:start;overflow-x:auto;overscroll-behavior-x:contain;scrollbar-width:thin;padding-bottom:4px}
}

.t-runworth{gap:9px;padding:7px 16px}
.t-runworth b{font:700 clamp(20px,2.3vw,28px)/1 var(--display);color:var(--chase);letter-spacing:-.01em}
.t-runworth .rw-last{font:600 11px/1 var(--sans);color:var(--text-3);padding-left:10px;border-left:1px solid var(--line-2)}
.t-runworth .rw-last i{font-style:normal;color:var(--text-2)}
.t-runworth.is-leaving b{visibility:hidden}
.t-runworth.is-leaving{transition:opacity .5s ease .25s;opacity:.0}
.rw-fly{position:fixed;z-index:40;margin:0;transform-origin:0 0;pointer-events:none;white-space:nowrap;
  font-family:var(--display);font-weight:700;line-height:1;letter-spacing:-.01em;color:var(--chase);font-variant-numeric:tabular-nums;
  text-shadow:0 0 22px rgba(255,197,58,.6),0 0 2px rgba(0,0,0,.8);will-change:transform}
.rb-worth.is-received{animation:rb-received 1.1s cubic-bezier(.16,1,.3,1)}
.rb-worth.is-received .rb-worth-v b{animation:rb-received-n .9s cubic-bezier(.16,1,.3,1)}
@keyframes rb-received{0%{box-shadow:0 0 0 0 rgba(255,197,58,.0)}25%{box-shadow:0 0 0 3px rgba(255,197,58,.55),0 0 60px rgba(255,197,58,.35)}100%{box-shadow:0 0 0 0 rgba(255,197,58,0)}}
@keyframes rb-received-n{0%{filter:brightness(1.9)}100%{filter:none}}
@media(max-width:820px){.t-runworth .rw-last{display:none}}

/* the board's sell quick-picks and the look-closer button on each card */
.rb-quick .chip-btn{display:inline-flex;align-items:baseline;gap:6px}
.chip-btn.tier-pick{border-color:color-mix(in srgb,var(--tier-c) 55%,transparent);color:var(--text)}
.chip-btn.tier-pick b{font:700 12px/1 var(--display);letter-spacing:.06em;text-transform:uppercase;color:var(--tier-c)}
.chip-btn .tp-n{font:700 12px/1 var(--mono);color:var(--text)}
.chip-btn.tier-pick small{font:600 11px/1 var(--mono);color:var(--text-2)}
.chip-btn[aria-pressed="true"]{border-color:var(--ok);background:rgba(63,224,160,.12);box-shadow:inset 0 0 0 1px rgba(63,224,160,.35)}
.chip-btn[aria-pressed="true"] small{color:var(--ok)}
.t-board .rb-grid li .rb-look{position:absolute;top:4px;right:4px;z-index:3;width:26px;height:26px;border-radius:50%;border:1px solid rgba(255,255,255,.35);
  background:rgba(6,7,13,.72);color:#fff;font:700 14px/1 var(--sans);display:grid;place-items:center;cursor:zoom-in;opacity:.55;transition:opacity .15s}
.t-board .rb-grid li:hover .rb-look,.t-board .rb-grid li .rb-look:focus-visible{opacity:1}
.t-board .rb-grid li .rb-look:focus-visible{outline:2px solid var(--plus);outline-offset:1px}
@media(hover:none){.t-board .rb-grid li .rb-look{opacity:.85}}
.rb-frame[role="button"]{cursor:zoom-in}
.rb-frame[role="button"]:focus-visible{outline:2px solid var(--plus);outline-offset:3px}
/* in a run the readout sits top-left, clear of the odds meter above the card */
.theatre.is-run .t-runworth{left:clamp(16px,3vw,32px);transform:none}

/* ---- run 8: slower, and more to look at ----
   The camera leans in rung by rung as the glow climbs (--push, set by
   theatre.js, a few percent per rung) and settles back on the flip. Just
   before a plus-or-better card turns, a light sweeps across its back. When a
   hit or chase lands, the card and the sparks hold still for a beat
   (.is-hitstop) - the frame the eye remembers. Reduced motion: none of it
   (.is-calm stops animations; the push is pinned to 1). */
.t-card,.r-card{scale:var(--push,1);transition:scale .6s cubic-bezier(.16,1,.3,1)}
.theatre.is-calm .t-card,.theatre.is-calm .r-card{scale:1;transition:none}
.t-back::before,.r-back::before{content:'';position:absolute;inset:0;z-index:2;pointer-events:none;opacity:0;border-radius:inherit;
  background:linear-gradient(115deg,transparent 32%,rgba(255,255,255,.08) 42%,rgba(255,246,214,.62) 50%,rgba(255,255,255,.08) 58%,transparent 68%);
  background-size:260% 100%;background-position:130% 0;mix-blend-mode:screen}
.theatre[data-stage="cock"] .t-back::before,.theatre[data-stage="cock"] .r-card:not(.is-up) .r-back::before{animation:back-sweep .6s cubic-bezier(.4,0,.2,1) both}
@keyframes back-sweep{0%{opacity:0;background-position:130% 0}25%{opacity:1}100%{opacity:0;background-position:-30% 0}}
.theatre.is-hitstop .t-particles>*,.theatre.is-hitstop .t-rays,.theatre.is-hitstop .t-ring{animation-play-state:paused!important}
.theatre.is-hitstop .t-flash{filter:brightness(1.25)}
@media (prefers-reduced-motion:reduce){.t-card,.r-card{scale:1;transition:none}}

/* Run 10 (J25, the owner's pick, 2 Oct): the chase lands as ONE motion. The push carries the card toward
   the camera while the vignette closes in and the light blooms; at the push's peak the gold fires and
   travels INWARD (.is-converge: from a ring outside the card to its edge), then gathers into a soft halo
   on the card as it eases back. Driven from theatre.js (chaseLanding) on the stage's own clock. */
.theatre.is-chase-push .t-vignette{opacity:.95;background:radial-gradient(ellipse at center,transparent 24%,rgba(0,0,0,.86) 100%);transition:opacity .42s ease-out}
.theatre.is-chase-push .t-spot{opacity:.8;filter:brightness(1.35) saturate(1.2);transition:opacity .42s ease-out,filter .42s ease-out}
.t-particles i.is-converge{width:var(--sz);height:var(--sz);border-radius:50%;box-shadow:0 0 10px 2px var(--pc);animation:converge var(--dur) cubic-bezier(.3,.7,.2,1) var(--delay) forwards}
@keyframes converge{
  0%{opacity:0;transform:translate(calc(-50% + var(--sx)),calc(-50% + var(--sy))) scale(1.25)}
  18%{opacity:1}
  78%{opacity:1;transform:translate(calc(-50% + var(--ex)),calc(-50% + var(--ey))) scale(.8)}
  100%{opacity:0;transform:translate(calc(-50% + var(--ex)),calc(-50% + var(--ey))) scale(.45)}
}
@media (prefers-reduced-motion:reduce){.t-particles i.is-converge{animation:none;opacity:0}.theatre.is-chase-push .t-vignette,.theatre.is-chase-push .t-spot{transition:none}}
/* Run 17 (B6, owner ruling Q7): the reveal and the run board lead with keeping and shipping; selling comes after, quiet. */
.t-keep,.rb-keep{display:grid;gap:10px;padding:12px 14px;border:1px solid var(--line-2);border-radius:var(--r-m);background:rgba(255,255,255,.03)}
.t-keep{margin:0 0 12px}
.rb-keep{margin-top:14px}
.t-keep[hidden],.rb-keep[hidden]{display:none}
.t-kept,.rb-kept{margin:0;font-size:var(--fs-s);color:var(--text-2)}
.t-kept b,.rb-kept b{color:var(--text)}
.t-keep-actions,.rb-keep-actions{display:flex;flex-wrap:wrap;gap:10px}
/* O45-21: what posting costs, under "Ship it to me" on a card worth less than its postage */
.t-post-hint{margin:0;font-size:var(--fs-xs,12px);line-height:1.45;color:var(--text-3)}
.t-post-hint[hidden]{display:none}
.rb-sellbar.is-quiet{background:transparent;border-style:dashed}
.rb-sellbar.is-quiet .rb-sell-value{font-size:var(--fs-m);color:var(--text-2)}
#rb-sell.sell-btn{justify-self:start;display:inline-flex;flex-wrap:wrap;gap:4px 8px;align-items:center}
#rb-sell.sell-btn .cta-sub{font-weight:500;color:var(--text-2)}
#rb-sell.sell-btn .cta-arrow{display:none}
/* Run 19 (owner, issue 2: "the sell button disappears when I open multiple packs"):
   the run board's sell bar is pinned to the foot of the board while its cards
   scroll - always in view at every width - and every card that can be sold
   carries a pick circle. Keeping stays the default: nothing sells without a
   pick and one confirmation. With nothing left to sell the bar steps back. */
.t-board .rb-sellbar,.t-board .rb-sellbar.is-quiet{position:sticky;bottom:0;z-index:5;margin-top:0;
  grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"copy btn" "quick btn" "note note";align-items:center;gap:8px 16px;padding:12px 14px;
  background:rgba(10,12,22,.97);border:1px solid var(--line-2);border-style:solid;border-radius:var(--r-m);box-shadow:0 -16px 34px rgba(0,0,0,.6)}
.t-board .rb-sellbar.is-idle{position:static;box-shadow:none;background:transparent;border-style:dashed}
.t-board .rb-sellbar .rb-sell-copy{grid-area:copy}
.t-board .rb-sellbar .rb-quick{grid-area:quick}
.t-board .rb-sellbar .rb-sell-value{display:none}
.t-board .rb-sellbar .rb-sale-note{grid-area:note;margin:0;font-size:var(--fs-s);color:var(--text-2)}
.t-board .rb-sellbar .rb-sale-note:empty{display:none}
.t-board #rb-sell.sell-btn{grid-area:btn;justify-self:end;align-self:center;padding:11px 18px;font-size:var(--fs-s);border-color:var(--chase);color:var(--text);background:rgba(255,197,58,.1)}
.t-board #rb-sell.sell-btn:disabled{opacity:1;border-color:var(--line-2);background:transparent;color:var(--text-2)}
.t-board #rb-sell.sell-btn[hidden]{display:none}
.t-board .rb-grid li.is-pickable::before{content:'';position:absolute;top:5px;left:5px;z-index:3;width:18px;height:18px;border-radius:50%;
  border:2px solid rgba(255,255,255,.9);background:rgba(4,5,12,.55);box-shadow:0 1px 4px rgba(0,0,0,.7);pointer-events:none}
.t-board .rb-grid li.is-picked::before{background:var(--ok);border-color:var(--ok)}
.t-board .rb-grid li.is-picked::after{content:'';position:absolute;top:9px;left:12px;z-index:4;width:5px;height:9px;border:solid #04120c;border-width:0 2px 2px 0;transform:rotate(45deg);pointer-events:none}
.t-board .rb-grid li.is-sold::before,.t-board .rb-grid li.is-sold::after{display:none}
@media(max-width:620px){
  .t-board .rb-sellbar,.t-board .rb-sellbar.is-quiet{grid-template-columns:1fr;grid-template-areas:"copy" "quick" "btn" "note";padding:10px 12px;gap:8px}
  .t-board #rb-sell.sell-btn{justify-self:stretch;justify-content:center}
  .t-board .rb-sellbar .rb-sell-copy{font-size:12px}
}

/* O24 E1: a pull replaced by its listed value in berries (out of stock when drawn) */
.t-rail li.is-replaced img{filter:saturate(.35) brightness(.75)}
.t-rail li .r-repl{position:absolute;left:0;right:0;top:0;font:700 8px/1.6 var(--display);letter-spacing:.08em;text-align:center;color:var(--ink-0);background:var(--chase);pointer-events:none}
.t-board .rb-grid li.is-replaced img{filter:saturate(.35) brightness(.75)}
.t-board .rb-grid li .rb-repl{position:absolute;left:0;right:0;top:0;font:700 9px/1.7 var(--display);letter-spacing:.08em;text-align:center;color:var(--ink-0);background:var(--chase);pointer-events:none;z-index:2}
.t-board .rb-grid li{position:relative}

/* O46 (U46-11): on a wide screen the board's sell bar, pinned to its foot, sat over the best pull's name on the first
   view ("DR.KUREHA" under the bar, "(PARALLEL)" peeking below). The name and its tier lead the column there; the
   card follows. A phone keeps the name beside the card. */
@media (min-width:821px){.t-board .rb-best figcaption{order:-1}}
