/* board-packs.css: the pack theatre (quick-board.js openPackUI). Owned by the cards lane: tftsolid's learning pass
   (2026-10-07), tftcards' rarity lane (2026-10-08), the AV pass (2026-10-09). The cards themselves are board-cards.css
   (card-ui.js); the pack image, its tear halves and the rays behind it start in board.css. 2026-10-09 (Eric: "refine
   draft showdown with vfx and animations from this clip"): the screen goes dark so the pack and the cards own it; the
   pack breathes and tears in a burst of inked white puffs; the cards come out as a stack; each is drawn to the middle
   large and turned; a special card waits, glowing, then turns into rays, a ring, sparks and its word; a skin gets the
   screen to itself; at the end every card sits in a clean grid with its bar. Reduced motion: the block at the end.
   2026-10-15 (the apps; a 5-card pack took about 20 s left alone): the wind-up, the rise, a card's draw-in and its flight
   to the row are quicker, and their lengths come from quick-board.js PT on the overlay (--pt-wind, --pt-rise,
   --pt-drawin, --pt-fly; the fallbacks here are the same numbers), so the animation and the sound cued with it land
   together. */

.bd .bd-packov.pt { --sy: 46.5%; --sky: 85%; --stw: 290px; background: radial-gradient(circle at 50% 46%, #3b2d70 0%, #1f1840 48%, #100b20 100%); }
.bd.wide .bd-packov.pt { --sy: 56%; --stw: 250px; }
/* the stack rises out of the pouch: the pouch's lower half stays in front of it as it falls away */
.bd-packov.pt .bd-tear.bot { z-index: 4; }
.bd-packov.pt:focus, .bd-packov.pt:focus-visible { outline: none; }
.pt-bg { position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.07) 0 1.5px, rgba(255, 255, 255, 0) 2.5px) 0 0 / 34px 34px,
    radial-gradient(circle, rgba(255, 255, 255, 0.05) 0 1px, rgba(255, 255, 255, 0) 2px) 17px 17px / 34px 34px; }
.bd-packov.pt .bd-packrays { transition: opacity 0.4s ease; }
.bd-packov.pt .bd-packrays.pt-dim { opacity: 0.18; }
.bd-packov.pt-jolt { animation: ptJolt 0.34s linear; }
@keyframes ptJolt { 0%, 100% { transform: none; } 20% { transform: translate(-6px, 3px); } 40% { transform: translate(5px, -4px); } 60% { transform: translate(-4px, -2px); } 80% { transform: translate(3px, 2px); } }

/* ---- the pack: it tilts and breathes; a tap squeezes and crinkles it, brighter, then it tears ---- */
.bd .bd-packov.pt .bd-pack3d { animation: bdPackIn 0.6s cubic-bezier(.2, 1.5, .4, 1) both, ptPackIdle 3.4s ease-in-out 0.6s infinite; transform-origin: 50% 60%; }
@keyframes ptPackIdle { 0%, 100% { transform: perspective(900px) rotateY(-11deg) rotateZ(-2deg) translateY(0) scale(1); }
  50% { transform: perspective(900px) rotateY(11deg) rotateZ(2deg) translateY(-12px) scale(1.035); } }
.bd .bd-packov.pt .bd-pack3d.charge { animation: ptPackWind var(--pt-wind, 0.42s) ease-in both;
  filter: drop-shadow(0 0 26px rgba(255, 240, 180, 0.9)) drop-shadow(0 0 60px rgba(255, 200, 110, 0.75)); }
@keyframes ptPackWind {
  0% { transform: scale(1); } 12% { transform: scale(1.06, 0.95) rotate(-3deg); } 24% { transform: scale(0.95, 1.06) rotate(3deg); }
  38% { transform: scale(1.09, 0.93) rotate(-5deg); } 52% { transform: scale(0.94, 1.08) rotate(5deg); } 66% { transform: scale(1.12, 0.92) rotate(-7deg); }
  80% { transform: scale(0.93, 1.1) rotate(7deg); filter: brightness(1.5); } 100% { transform: scale(1.16); filter: brightness(2.1); } }
/* the tear's burst: inked white puffs, paper bits and sparks */
.pt-bit { position: absolute; z-index: 6; pointer-events: none; }
.pt-puff { width: 36px; height: 36px; margin: -18px 0 0 -18px; border-radius: 50%; background: #fff; box-shadow: 0 0 0 3.5px var(--ol), inset -4px -5px 0 #e3e0ef;
  animation: ptPuff 0.85s cubic-bezier(.15, .8, .3, 1) both; }
.pt-shred { width: 12px; height: 18px; margin: -9px 0 0 -6px; border-radius: 2px; background: #fffaf0; box-shadow: 0 0 0 2.5px var(--ol);
  animation: ptShred 0.95s cubic-bezier(.2, .7, .5, 1) both; }
.pt-spk { width: 32px; height: 32px; margin: -16px 0 0 -16px; animation: ptPuff 0.7s cubic-bezier(.15, .8, .3, 1) both; }
.pt-spk svg, .pt-glint svg { display: block; width: 100%; height: 100%; overflow: visible; }
.pt-spk path, .pt-glint path { fill: #fff; stroke: var(--ol); stroke-width: 2.4; stroke-linejoin: round; }
@keyframes ptPuff { 0% { transform: translate(0, 0) scale(0.2); } 35% { transform: translate(calc(var(--dx) * 0.62), calc(var(--dy) * 0.62)) scale(var(--z)); }
  100% { transform: translate(var(--dx), var(--dy)) scale(0); } }
@keyframes ptShred { 0% { transform: translate(0, 0) rotate(0) scale(0.4); } 30% { transform: translate(calc(var(--dx) * 0.6), calc(var(--dy) * 0.6)) rotate(calc(var(--r) * 0.5)) scale(var(--z)); }
  100% { transform: translate(var(--dx), calc(var(--dy) + 150px)) rotate(var(--r)) scale(var(--z)); opacity: 0; } }

/* ---- the stack of backs and the row of drawn cards ---- */
.pt-stack { position: absolute; z-index: 3; left: 50%; top: var(--sky); width: 124px; height: 174px; margin: -87px 0 0 -62px; pointer-events: none; }
.bd.wide .pt-stack { left: 21%; top: var(--sy); }
/* a deck: each card under the top one a little lower and turned a little, its edge showing (--d: depth from the top) */
.pt-stack .cu-card { position: absolute; left: 0; top: 0; transform: translate(calc(var(--d) * 1.2px), calc(var(--d) * 4px)) rotate(calc(var(--d) * 0.6deg)); }
.pt-stack .cu-card:nth-child(odd) { rotate: -1.6deg; }
.pt-stack .cu-card:last-child { rotate: 0deg; }
.pt-stack.pt-rise { animation: ptStackIn var(--pt-rise, 0.7s) cubic-bezier(.25, .8, .3, 1) both; }
@keyframes ptStackIn { 0% { transform: translate(var(--fx), calc(var(--fy) + 40px)) scale(var(--fs)); opacity: 0; } 14% { opacity: 1; }
  45% { transform: translate(var(--fx), calc(var(--fy) - 90px)) scale(calc(var(--fs) * 1.08)) rotate(-5deg); } 100% { transform: none; } }
.pt-strip { position: absolute; z-index: 4; left: 0; right: 0; top: 78px; height: 126px; pointer-events: none; }
.bd.wide .pt-strip { top: 54px; }
.pt-slot { position: absolute; top: 0; visibility: hidden; transition: left 0.25s ease; }
.pt-slot.in { visibility: visible; animation: ptLand 0.3s cubic-bezier(.2, 1.5, .4, 1) both; }
@keyframes ptLand { from { transform: scale(0.75); } to { transform: none; } }
.bd .bd-packov .pt-skip { position: absolute; z-index: 7; right: 16px; bottom: 22px; height: 46px; padding: 0 18px; border: 3px solid var(--ol); border-radius: 23px;
  background: #3b3350; color: #fff; font-size: 20px; font-weight: 800; box-shadow: 0 4px 0 rgba(8, 4, 20, 0.5); cursor: pointer; }
.bd .bd-packov .pt-skip:active { transform: translateY(2px); box-shadow: 0 2px 0 rgba(8, 4, 20, 0.5); }

/* ---- the drawn card: off the stack to the middle, a shake while it waits, then to the row ---- */
.pt-stage { position: absolute; z-index: 5; left: 50%; top: var(--sy); width: var(--stw); height: calc(var(--stw) * 1.4); margin: calc(var(--stw) * -0.7) 0 0 calc(var(--stw) * -0.5); pointer-events: none; }
.pt-stage .cu-flip { position: absolute; left: 0; top: 0; }
.pt-stage.pt-drawin { animation: ptDrawIn var(--pt-drawin, 0.2s) cubic-bezier(.2, .9, .3, 1) both; }
@keyframes ptDrawIn { from { transform: translate(var(--fx), var(--fy)) scale(var(--fs)) rotate(-9deg); } to { transform: none; } }
.pt-stage.pt-shake { animation: ptShake var(--wait, 0.6s) linear both; }
@keyframes ptShake { 0% { transform: none; } 15% { transform: translate(-2px, -2px) rotate(-1deg) scale(1.01); } 30% { transform: translate(3px, -3px) rotate(1.4deg) scale(1.02); }
  45% { transform: translate(-4px, -5px) rotate(-2deg) scale(1.03); } 60% { transform: translate(5px, -6px) rotate(2.6deg) scale(1.04); } 72% { transform: translate(-6px, -7px) rotate(-3.2deg) scale(1.05); }
  84% { transform: translate(7px, -8px) rotate(3.6deg) scale(1.06); } 94% { transform: translate(-3px, -9px) rotate(-1.5deg) scale(1.07); } 100% { transform: translate(0, -8px) scale(1.06); } }
.pt-stage.pt-admire { animation: ptAdmire 2.4s ease-in-out infinite; }
@keyframes ptAdmire { 0%, 100% { transform: none; } 30% { transform: perspective(1000px) rotateY(11deg) rotateX(-3deg) translateY(-4px); }
  70% { transform: perspective(1000px) rotateY(-9deg) rotateX(2deg) translateY(-2px); } }
.pt-stage.pt-fly { animation: ptFly var(--pt-fly, 0.22s) cubic-bezier(.55, 0, .8, .45) both; }
@keyframes ptFly { from { transform: none; } to { transform: translate(var(--tx), var(--ty)) scale(var(--ts)) rotate(4deg); } }

/* ---- a special card's moment: rays in its colour (faint while it waits), a ring, sparks, its word ---- */
.pt-r-rare { --ray: rgba(205, 222, 255, 0.5); --rs: #d8e6ff; --wc: #dfeaff; }
.pt-r-new { --ray: rgba(255, 232, 150, 0.55); --rs: #ffe27a; --wc: #ffe27a; }
.pt-r-holo { --ray: rgba(255, 170, 236, 0.5); --rs: #ffb3ec; --wc: #ffb6ec; }
.pt-r-ultra { --ray: rgba(255, 214, 90, 0.6); --rs: #ffd34d; --wc: #ffd34d; }
.pt-r-ghost { --ray: rgba(160, 240, 255, 0.5); --rs: #bff3ff; --wc: #c8f7ff; }
.pt-rays { position: absolute; z-index: 2; left: 50%; top: var(--sy); width: 1100px; height: 1100px; margin: -550px 0 0 -550px; border-radius: 50%; pointer-events: none;
  background: repeating-conic-gradient(from 0deg, var(--ray) 0deg 7deg, rgba(255, 255, 255, 0) 7deg 18deg);
  -webkit-mask: radial-gradient(circle, #000 0 12%, transparent 56%); mask: radial-gradient(circle, #000 0 12%, transparent 56%);
  opacity: 0; transition: opacity 0.3s ease; animation: ptSpin 11s linear infinite; }
.pt-rays.pt-r-holo { background: repeating-conic-gradient(from 0deg, rgba(255, 160, 230, 0.5) 0deg 6deg, rgba(255, 255, 255, 0) 6deg 15deg, rgba(140, 225, 255, 0.5) 15deg 21deg, rgba(255, 255, 255, 0) 21deg 30deg); }
.pt-rays.pt-pre { opacity: 0.4; }
.pt-rays.pt-on { opacity: 1; }
@keyframes ptSpin { to { transform: rotate(360deg); } }
.pt-ring { position: absolute; z-index: 4; left: 50%; top: var(--sy); width: 170px; height: 170px; margin: -85px 0 0 -85px; border-radius: 50%; pointer-events: none;
  border: 11px solid var(--rs); box-shadow: 0 0 0 3px var(--ol), inset 0 0 0 3px var(--ol); animation: ptRing 0.7s cubic-bezier(.1, .7, .3, 1) both; }
@keyframes ptRing { from { transform: scale(0.5); opacity: 1; } to { transform: scale(3.4); opacity: 0; } }
.pt-glint { position: absolute; z-index: 6; left: 50%; top: var(--sy); width: 30px; height: 30px; margin: -15px 0 0 -15px; pointer-events: none;
  transform: translate(var(--gx), var(--gy)) scale(0); animation: ptGlint 1s ease-out both; }
@keyframes ptGlint { 0% { transform: translate(var(--gx), var(--gy)) scale(0) rotate(0deg); } 30% { transform: translate(var(--gx), var(--gy)) scale(var(--z)) rotate(25deg); }
  100% { transform: translate(var(--gx), calc(var(--gy) - 14px)) scale(0) rotate(80deg); } }
.pt-word { position: absolute; z-index: 6; left: 50%; top: calc(var(--sy) + var(--stw) * 0.7 + 18px); transform: translateX(-50%); text-align: center; white-space: nowrap; pointer-events: none;
  animation: ptWord 0.45s cubic-bezier(.2, 1.6, .4, 1) both; }
.pt-word b { display: block; font-size: 46px; font-weight: 800; line-height: 1; letter-spacing: 0.04em; color: var(--wc); -webkit-text-stroke: 10px var(--ol); }
.pt-word small { display: block; margin-top: 6px; font-size: 19px; font-weight: 800; color: #fff; -webkit-text-stroke: 5px var(--ol); }
.pt-word.pt-r-holo b { animation: ptHue 1.8s linear infinite; }
@keyframes ptHue { to { filter: hue-rotate(360deg); } }
@keyframes ptWord { from { transform: translateX(-50%) scale(0.3); opacity: 0; } to { transform: translateX(-50%); opacity: 1; } }

/* ---- a new skin: the unit in it, large, on its own ---- */
.pt-skin { position: absolute; inset: 0; z-index: 8; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; overflow: hidden;
  background: rgba(12, 8, 28, 0.84); --sk: #ffd34d; --skd: #8a5a16; animation: ptSkinIn 0.3s ease-out both; }
.pt-skin.out { animation: ptSkinOut 0.25s ease-in both; }
.pt-sk-frost { --sk: #9fe6ff; --skd: #2c5f93; } .pt-sk-shadow { --sk: #c9a6ff; --skd: #8a78c4; } .pt-sk-ghost { --sk: #c9f7ff; --skd: #2f4f86; }
.pt-skinrays { position: absolute; left: 50%; top: 50%; width: 1100px; height: 1100px; margin: -550px 0 0 -550px; border-radius: 50%; pointer-events: none; opacity: 0.6;
  background: repeating-conic-gradient(from 0deg, var(--sk) 0deg 6deg, rgba(255, 255, 255, 0) 6deg 17deg);
  -webkit-mask: radial-gradient(circle, #000 0 10%, transparent 52%); mask: radial-gradient(circle, #000 0 10%, transparent 52%); animation: ptSpin 14s linear infinite; }
.pt-skinlbl { position: relative; padding: 2px 16px; border-radius: 14px; background: #ff5a5f; box-shadow: 0 0 0 4px var(--ol), 0 4px 0 4px rgba(8, 4, 20, 0.45);
  font-size: 24px; font-weight: 800; letter-spacing: 0.08em; -webkit-text-stroke: 6px var(--ol); animation: ptWordPlain 0.4s cubic-bezier(.2, 1.6, .4, 1) 0.1s both; }
.pt-skinfig { position: relative; width: 340px; height: 340px; animation: ptSkinFig 0.55s cubic-bezier(.2, 1.5, .4, 1) both; }
/* a lit disc behind the unit in the skin's colour, so a pale skin (frost, ghost) reads against the dark */
.pt-skinfig::before { content: ""; position: absolute; left: 4%; right: 4%; top: 4%; bottom: 4%; border-radius: 50%;
  background: radial-gradient(closest-side, var(--skd) 0%, var(--skd) 62%, rgba(0, 0, 0, 0) 100%); box-shadow: 0 0 0 5px var(--ol), 0 0 0 11px var(--sk), 0 0 0 15px var(--ol); }
.pt-skinfig::after { content: ""; position: absolute; left: 22%; right: 22%; bottom: 9%; height: 12%; border-radius: 50%; background: radial-gradient(closest-side, rgba(10, 6, 24, 0.45), rgba(10, 6, 24, 0)); }
.pt-skinfig canvas { position: relative; z-index: 1; display: block; width: 100% !important; height: 100% !important; }
.pt-skinname { position: relative; max-width: calc(100% - 24px); font-size: 40px; font-weight: 800; line-height: 1.05; text-align: center; color: #fff; -webkit-text-stroke: 9px var(--ol);
  animation: ptWordPlain 0.4s cubic-bezier(.2, 1.6, .4, 1) 0.2s both; }
@keyframes ptSkinIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes ptSkinOut { to { opacity: 0; } }
@keyframes ptSkinFig { from { transform: scale(0.3) translateY(60px); } to { transform: none; } }
@keyframes ptWordPlain { from { transform: scale(0.3); opacity: 0; } to { transform: none; opacity: 1; } }

/* ---- the end: every card in a clean grid, its next level under it; the ready line; UPGRADES and CLAIM ---- */
.pt-end { position: absolute; inset: 0; z-index: 6; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 20px; padding: 70px 12px 36px; pointer-events: none; }
.bd.wide .pt-end { padding: 46px 12px 22px; gap: 16px; }
.pt-end > * { pointer-events: auto; }
.pt-grid { display: grid; grid-template-columns: repeat(var(--cols, 3), var(--gw, 124px)); column-gap: 26px; row-gap: 24px; justify-content: center; }
.pt-cell { position: relative; display: flex; flex-direction: column; align-items: center; gap: 20px; width: var(--gw, 124px); }
.pt-cell.pt-from { animation: ptFrom 0.42s cubic-bezier(.2, 1.1, .4, 1) both; }
@keyframes ptFrom { from { transform: translate(var(--fx), var(--fy)) scale(var(--fs)); } to { transform: none; } }
/* the claimed cards' own layer over the next screen (the pack has closed): the grid as it stood, sweeping away */
.pt-sweepov { position: absolute; inset: 0; z-index: 46; pointer-events: none; }
.pt-sweepov .pt-end, .pt-sweepov .pt-end > * { pointer-events: none; }
.pt-sweepov .pt-total { opacity: 0; transition: opacity 0.2s ease; }
.pt-cell.pt-sweep { animation: ptSweep 0.4s cubic-bezier(.5, 0, .8, .45) both; }
@keyframes ptSweep { from { transform: none; opacity: 1; } 30% { transform: translateY(14px) scale(1.04); opacity: 1; } to { transform: translateY(-120vh) scale(0.55) rotate(-8deg); opacity: 0.4; } }
/* the next level under the card: two lines at most, always the same height, so rows never overlap */
.pt-next { width: calc(var(--gw, 124px) + 22px); height: 2.4em; margin-top: -6px; overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  font-size: 15px; font-weight: 800; line-height: 1.2; text-align: center; color: #fff; -webkit-text-stroke: 4px var(--ol); paint-order: stroke fill; }
.pt-next.ready { color: #b8f59a; }
/* a card with a skin pill on its foot: the line goes below the pill */
.pt-cell.pt-hasskin .pt-next { margin-top: calc(var(--gw, 124px) * 0.08); }
.pt-next b { display: inline-block; margin-right: 3px; padding: 0 5px; border-radius: 6px; background: #5cc23a; box-shadow: 0 0 0 2px var(--ol); vertical-align: 1px;
  font-size: 11px; line-height: 16px; letter-spacing: 0.04em; color: #fff; -webkit-text-stroke: 2.6px var(--ol); }
.bd .bd-packov.pt .pt-foot { position: static; left: auto; right: auto; bottom: auto; }
.pt-foot.pt-gone { opacity: 0; transition: opacity 0.25s ease; pointer-events: none; }
/* CLAIM pops in as the grid lands (2026-10-15: after 0.3 s, was 0.5) */
.bd .bd-packov .pt-claim { animation: ptClaimIn 0.35s cubic-bezier(.2, 1.5, .4, 1) 0.3s both; }
@keyframes ptClaimIn { from { transform: scale(0.5); opacity: 0; } to { transform: none; opacity: 1; } }

/* ---- the end's line and buttons, the ⓘ (from the 2026-10-07 pass) ---- */
.bd-p-foot { position: absolute; left: 12px; right: 12px; bottom: 5%; display: flex; flex-direction: column; align-items: center; gap: 10px; }
.pt-total { font-size: 30px; font-weight: 800; line-height: 1; color: #ffd34d; -webkit-text-stroke: 7px var(--ol); animation: ptWordPlain 0.4s cubic-bezier(.2, 1.6, .4, 1) 0.2s both; }
.bd-p-readyline { max-width: 100%; text-wrap: balance; font-size: 19px; font-weight: 800; line-height: 1.15; color: #b8f59a; text-align: center; -webkit-text-stroke: 4px var(--ol); paint-order: stroke fill;
  animation: bdPReadyIn 0.3s cubic-bezier(.2, 1.6, .4, 1) 0.6s both; }
@keyframes bdPReadyIn { from { transform: scale(0.4); opacity: 0; } to { transform: none; opacity: 1; } }
.bd-p-btns { display: flex; justify-content: center; gap: 12px; }
.bd .bd-p-foot .bd-packok { position: static; width: 200px; }
.bd .bd-p-foot .bd-p-up { width: 200px; min-width: 0; height: 66px; font-size: 26px; }
.bd .bd-packov .bd-p-i { position: absolute; top: 14px; right: 14px; z-index: 9; width: 40px; height: 40px; padding: 0; border: 3px solid var(--ol); border-radius: 50%;
  background: #3b3350; font-size: 22px; font-weight: 800; font-style: italic; line-height: 1; box-shadow: 0 3px 0 rgba(20, 14, 34, 0.45); cursor: pointer; }
.bd .bd-packov .bd-p-i[aria-expanded="true"] { background: #6474f2; }
.bd-p-note { position: absolute; top: 62px; right: 14px; z-index: 9; max-width: min(340px, calc(100% - 28px)); padding: 8px 12px; border: 3px solid var(--ol); border-radius: 12px;
  background: #fff6d6; color: #3b3350; font-size: 15px; font-weight: 700; line-height: 1.3; text-align: left; box-shadow: 0 4px 0 rgba(20, 14, 34, 0.45); }
.bd-p-note[hidden] { display: none; }

/* the overlay opened under reduced motion (quick-board.js reads it once, CardUI.still): its rays stand still too if
   the setting changes while it is up */
.bd-packov.pt-still .pt-rays, .bd-packov.pt-still .pt-skinrays { animation: none; }

/* reduced motion: no breathing, wind-up, tear, burst, flight, shake, turn, ring, sparks or sweep. Each card appears face
   up in turn with its word (quick-board.js snaps the turn); the rays stand still; a bar shows where it ends. */
@media (prefers-reduced-motion: reduce) {
  .bd .bd-packov.pt .bd-pack3d, .bd .bd-packov.pt .bd-pack3d.charge, .pt-stack.pt-rise, .pt-slot.in, .pt-stage.pt-drawin, .pt-stage.pt-shake, .pt-stage.pt-fly, .pt-stage.pt-admire,
  .pt-rays, .pt-word, .pt-word.pt-r-holo b, .bd-packov.pt-jolt, .pt-skin, .pt-skin.out, .pt-skinrays, .pt-skinlbl, .pt-skinfig, .pt-skinname,
  .pt-cell.pt-from, .pt-cell.pt-sweep, .pt-claim, .bd-p-readyline, .pt-total { animation: none !important; }
  .pt-ring, .pt-glint, .pt-bit { display: none; }
  .pt-rays { transition: none; }
  .pt-word { transform: translateX(-50%); }
  .pt-foot.pt-gone { transition: none; }
}
