/* poke-pack.rip — the pack opening: on the counter, on the playmat, under
   the pendant light (DESIGN.md). The overlay is the counter top, warm
   laminate lit from above. The pack, the cards and the end-of-pack spread
   all lie on one neoprene mat with a stitched edge; when the pack is done the
   till prints a receipt beside it. Light comes from the pendant: a still
   pool on the counter and the mat, the wrapper's colour in it before the
   tear, the turned card's type colour spilling onto the mat under it.

   Card faces and foils are not touched here; only what holds them. The tear
   itself is css/tear.css and js/tear.js.

   Every moving piece is a transform, opacity or filter animation on a small
   layer that is pre-rendered before it moves. Nothing loops behind a turned
   card. Everything decorative stops under body.no-motion and
   prefers-reduced-motion; the hit's build-up, flash, glints and kick are only
   switched on by JS when hit effects are enabled, and body.no-flash hides
   them outright. */

#overlay {
  --pack-glow: 150 176 232;
  --aura: transparent;
  --charge-ms: 620ms;
  --op-ease: cubic-bezier(0.2, 0.85, 0.25, 1);
  --op-spring: cubic-bezier(0.2, 0.9, 0.3, 1.18);
  --op-snap: cubic-bezier(0.15, 0.8, 0.3, 1);
  --pendant: 255 224 178;
  /* The card on the mat: as tall as the screen allows once the bar, the slot
     strip and the controls have their room (at least 55% of a desktop). */
  --card-h: clamp(340px, calc(100svh - 310px), 640px);
  --card-w: calc(var(--card-h) * 0.716);
  --strip-h: 70px;
  --gutter-x: 32px;
}

/* ---- The counter ----------------------------------------------------------
   The overlay is the counter top: laminate, a pool of warm light where the
   pendant hangs over the mat, the edges falling off into the dark shop. */
#overlay,
#overlay.dealing {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  padding: 0;
  background:
    radial-gradient(ellipse 900px 640px at 46% 44%, rgb(var(--pendant) / 0.16), rgb(var(--pendant) / 0) 70%),
    radial-gradient(ellipse 130% 110% at 46% 40%, transparent 55%, rgba(0, 0, 0, 0.32)),
    url("../assets/textures/laminate.png"),
    var(--counter);
  color: var(--ink);
}
#overlay .rip-stage,
#overlay.dealing .rip-stage {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  flex: 1 0 auto;
  width: 100%;
  max-width: 1440px;
  min-height: 0;
  margin: 0 auto;
  text-align: left;
  align-items: stretch;
  justify-content: flex-start;
}

/* ---- The bar: Leave, which pack, how far into the box -------------------- */
#overlay .op-bar {
  display: flex;
  align-items: center;
  gap: 18px;
  min-height: 64px;
  padding: max(0px, env(safe-area-inset-top)) var(--gutter-x) 0;
}
#overlay .overlay-leave,
#overlay .overlay-leave:hover {
  position: static;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: none;
  min-width: 0;
  min-height: 44px;
  margin: 0 0 0 -10px;
  padding: 0 14px 0 10px;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--ink);
  font-size: 15px;
  font-weight: 600;
  transition: background-color 0.15s ease;
}
#overlay .overlay-leave:hover { background: rgba(0, 0, 0, 0.22); }
#overlay .overlay-leave svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
}
#overlay .op-where {
  min-width: 0;
  margin: 0;
  overflow: hidden;
  color: var(--ink-2);
  font-size: 15px;
  white-space: nowrap;
  text-overflow: ellipsis;
}
#overlay .box-progress {
  display: flex;
  align-items: center;
  gap: 6px 12px;
  flex-wrap: wrap;
  justify-content: flex-end;
  margin: 0 0 0 auto;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink-2);
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}
#overlay .box-progress b { color: var(--ink); font-weight: 600; }
.box-pips { display: inline-flex; flex-wrap: wrap; gap: 3px; max-width: 176px; }
.box-pips i { width: 6px; height: 6px; border-radius: 50%; background: rgb(var(--hl) / 0.22); }
.box-pips i.done { background: var(--ink-2); }
.box-pips i.now { background: var(--ink); }
.box-progress-bar {
  display: inline-block;
  width: 120px;
  height: 4px;
  border-radius: 2px;
  background: rgb(var(--hl) / 0.18);
  overflow: hidden;
}
.box-progress-bar span { display: block; height: 100%; background: var(--ink); }

/* ---- The table: the mat, and beside it the receipt once it has printed ---- */
#overlay .op-table {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 18px;
  align-items: start;
  width: 100%;
  max-width: 1240px;
  margin: 0 auto;
  padding: 4px var(--gutter-x) 28px;
}
#overlay.with-receipt .op-table {
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: 30px;
  max-width: none;
}
#overlay .op-side { display: flex; flex-direction: column; gap: 18px; min-width: 0; }

/* The playmat: charcoal neoprene, a stitched edge, lit from above. */
#overlay .op-mat {
  position: relative;
  isolation: isolate;
  overflow: clip; /* the light and the glints stay on the mat */
  min-width: 0;
  padding: 28px 30px 20px;
  border-radius: 18px;
  background: url("../assets/textures/neoprene.png"), var(--mat);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    0 3px 4px rgba(0, 0, 0, 0.35),
    0 18px 40px rgba(0, 0, 0, 0.3);
}
#overlay .op-mat::after {
  content: "";
  position: absolute;
  inset: 5px;
  border: 1px dashed rgba(220, 220, 214, 0.22);
  border-radius: 14px;
  pointer-events: none;
}
/* The pendant's pool on the mat; before the tear it carries a little of the wrapper. */
#overlay .op-mat::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background:
    radial-gradient(ellipse 52% 62% at 50% 46%, rgb(var(--pendant) / 0.08), transparent 72%),
    radial-gradient(ellipse 30% 44% at 50% 48%, rgb(var(--pack-glow) / 0.1), transparent 70%);
  pointer-events: none;
  transition: opacity 0.6s ease;
}
#overlay.dealing .op-mat::before,
#overlay.is-spread .op-mat::before {
  background: radial-gradient(ellipse 56% 64% at 50% 46%, rgb(var(--pendant) / 0.07), transparent 72%);
}

/* ---- Ambient: the shop dims for a hit, and the flashes ------------------- */
.op-ambient {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}
.op-ambient > * { position: absolute; display: block; }
.op-flash { will-change: opacity; }

/* The lights go down while a hit gathers itself, and come back at the flash. */
.op-dim {
  inset: 0;
  background: rgba(8, 6, 4, 0.62);
  opacity: 0;
  transition: opacity 0.35s ease;
}
#overlay.charging .op-dim,
#overlay.charged .op-dim { opacity: 1; transition-duration: 0.5s; }
#overlay.hit-flash .op-dim { opacity: 0; transition: opacity 0.55s ease-out; }

/* Tear flash: the pendant catching the foil as the top comes off. A disc
   painted once and slid to the torn edge by transform. */
.op-flash {
  left: 0;
  top: 0;
  width: 640px;
  height: 640px;
  opacity: 0;
  translate: calc(var(--burst-x, 50vw) - 50%) calc(var(--burst-y, 30vh) - 50%);
  background: radial-gradient(
    circle closest-side,
    rgb(255 248 236 / 0.8),
    rgb(var(--pack-glow) / 0.28) 70px,
    rgb(var(--pendant) / 0.08) 170px,
    transparent 296px
  );
}
#overlay.tear-burst .op-flash { animation: opFlash 0.75s ease-out both; }
@keyframes opFlash {
  0% { opacity: 0; }
  14% { opacity: 1; }
  100% { opacity: 0; }
}

/* The hit flash on the counter around the mat: white light, the card's colour in it. */
.op-hit {
  inset: 0;
  opacity: 0;
  background: radial-gradient(
    ellipse 60% 52% at 46% 46%,
    rgb(255 250 240 / 0.7),
    rgb(var(--pendant) / 0.32) 26%,
    var(--aura, rgb(var(--pendant) / 0.2)) 46%,
    transparent 72%
  );
}
#overlay.charging .op-hit,
#overlay.charged .op-hit { will-change: opacity; }
#overlay.hit-flash .op-hit { animation: opHitFlash 0.9s ease-out both; }
#overlay.hit-flash.hit-t1 .op-hit { animation-duration: 0.5s; animation-name: opHitFlashSm; }
@keyframes opHitFlash {
  0% { opacity: 0; }
  9% { opacity: 1; }
  40% { opacity: 0.35; }
  100% { opacity: 0; }
}
@keyframes opHitFlashSm {
  0% { opacity: 0; }
  20% { opacity: 0.45; }
  100% { opacity: 0; }
}

/* ---- The sealed pack ----------------------------------------------------- */
#overlay .rip-hint {
  min-height: 24px;
  margin: 0 0 14px;
  color: var(--ink-2);
  font-size: 15px;
  font-weight: 500;
  text-align: center;
}
#overlay .booster {
  width: clamp(200px, calc((100svh - 300px) * 0.55), 330px);
  margin: 0 auto 26px;
}
#overlay[data-phase="ready"] .booster { animation: opPackIn 0.6s var(--op-ease) both; }
#overlay .booster.tearing,
#overlay .booster.dragging,
#overlay .booster.torn { animation-play-state: paused; }
@keyframes opPackIn {
  from { opacity: 0; translate: 0 24px; }
  to { opacity: 1; translate: 0 0; }
}
/* Contact shadow: the wrapper lies on the mat. */
#overlay .booster::after {
  content: "";
  position: absolute;
  left: 6%;
  right: 6%;
  bottom: -16px;
  height: 22px;
  z-index: 0;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(0, 0, 0, 0.6), transparent);
  pointer-events: none;
}
#overlay .booster.spill::after { opacity: 0; transition: opacity 0.3s ease; }

/* A light sweep across the wrapper, masked to its outline: the pendant moving
   over the foil. The band is three wrappers wide and slides by transform, and
   it sits beside the art rather than inside it, so the art's drop-shadow is
   never re-run. It fades out once a tear starts. */
#pack-rest-art { position: relative; }
.pack-sheen {
  position: absolute;
  inset: 0;
  z-index: 2;
  overflow: hidden;
  pointer-events: none;
  -webkit-mask: var(--pack-mask) center / 100% 100% no-repeat;
  mask: var(--pack-mask) center / 100% 100% no-repeat;
  opacity: 0;
  transition: opacity 0.2s ease;
}
.pack-sheen::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 300%;
  background: linear-gradient(
    105deg,
    transparent 36%,
    rgba(255, 255, 255, 0) 42%,
    rgba(255, 250, 240, 0.3) 50%,
    rgba(255, 255, 255, 0) 58%,
    transparent 64%
  );
  transform: translateX(-80%);
}
#overlay[data-phase="ready"] .booster:not(.tearing):not(.torn) .pack-sheen { opacity: 1; }
#overlay[data-phase="ready"] .booster:not(.tearing):not(.torn) .pack-sheen::after {
  animation: opSheen 5.4s ease-in-out 1s infinite;
}
@keyframes opSheen {
  0% { transform: translateX(-80%); }
  32%, 100% { transform: translateX(13.333%); }
}

/* "Tear here": a dashed line along the crimp with a light running across it. */
.tear-guide {
  position: absolute;
  left: 3%;
  right: 3%;
  top: 6.4%;
  height: 0;
  z-index: 8;
  border-top: 1.5px dashed rgba(255, 255, 255, 0.6);
  filter: drop-shadow(0 0 2px rgba(0, 0, 0, 0.9));
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}
#overlay[data-phase="ready"] .booster:not(.tearing):not(.torn) .tear-guide {
  animation: opGuideIn 0.5s ease 0.8s both;
}
.tear-guide i { position: absolute; inset: 0; display: block; }
.tear-guide i::before {
  content: "";
  position: absolute;
  left: 0;
  top: -5px;
  width: 9px;
  height: 9px;
  margin-left: -4.5px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.16);
}
#overlay[data-phase="ready"] .tear-guide i { animation: opGuide 2.6s cubic-bezier(0.5, 0, 0.2, 1) 1s infinite; }
@keyframes opGuideIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes opGuide {
  0% { transform: translateX(0); opacity: 0; }
  12% { transform: translateX(0); opacity: 1; }
  72% { transform: translateX(100%); opacity: 1; }
  86%, 100% { transform: translateX(100%); opacity: 0; }
}

/* Card backs inside the wrapper; they rise out once the top is gone. */
.pack-peek {
  position: absolute;
  left: 10%;
  right: 10%;
  top: 8.6%;
  z-index: 0;
  aspect-ratio: 63 / 88;
  pointer-events: none;
}
.pack-peek i {
  position: absolute;
  inset: 0;
  border-radius: 4.5% / 3.3%;
  background: #1b1e22 var(--card-back) center / cover no-repeat;
  opacity: 0;
}
#overlay .booster.tearing .pack-peek i,
#overlay .booster.torn .pack-peek i { opacity: 1; }
#overlay .booster.spill .pack-peek i {
  box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.45);
  animation: opPeek 0.6s var(--op-ease) both;
}
#overlay .booster.spill .pack-peek i:nth-child(1) { --r: -5deg; --x: -6%; animation-delay: 70ms; }
#overlay .booster.spill .pack-peek i:nth-child(2) { --r: 4deg; --x: 5%; animation-delay: 30ms; }
#overlay .booster.spill .pack-peek i:nth-child(3) { --r: 0deg; --x: 0%; }
@keyframes opPeek {
  from { opacity: 1; transform: translate(0, 4%) rotate(0deg); }
  to { opacity: 1; transform: translate(var(--x), -40%) rotate(var(--r)); }
}
/* The empty wrapper drops away under the rising cards (css/tear.css drops the torn edge with it). */
#overlay .booster.spill .pack-rest {
  animation: opPackDrop 0.55s cubic-bezier(0.55, 0, 0.8, 0.3) 0.12s both;
}
@keyframes opPackDrop {
  from { transform: none; opacity: 1; }
  to { transform: translateY(42%) rotate(2deg); opacity: 0; }
}

/* ---- The reveal -----------------------------------------------------------
   The card is the star. Prev and next flank it, the slot strip runs under it
   along the mat, and the card's name sits beside it, level with its foot. */
#overlay .focus-wrap {
  --aura: transparent;
  display: grid;
  grid-template-columns: auto minmax(0, 360px);
  grid-template-areas: "stage meta";
  align-items: end;
  justify-content: center;
  justify-items: stretch;
  column-gap: clamp(24px, 3.4vw, 52px);
  width: 100%;
  margin: 0;
}
#overlay .focus-stage {
  grid-area: stage;
  position: relative;
  display: grid;
  grid-template-columns: 44px var(--card-w) 44px;
  grid-template-rows: var(--card-h) auto;
  align-items: center;
  justify-content: center;
  gap: 16px 14px;
  width: auto;
  min-height: 0;
  perspective: 1400px;
  perspective-origin: 50% 42%;
}
#overlay .focus-nav.prev { grid-column: 1; grid-row: 1; }
#overlay .focus-card { grid-column: 2; grid-row: 1; }
#overlay .focus-nav.next { grid-column: 3; grid-row: 1; }
#overlay .focus-card {
  width: var(--card-w);
  height: auto;
  max-height: none;
  justify-self: center;
  align-self: center;
}
#overlay .focus-nav {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--ink-2);
  justify-self: center;
  align-self: center;
  transition: color 0.15s ease, opacity 0.2s ease;
}
#overlay .focus-nav svg {
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
#overlay .focus-nav:hover:not(:disabled) { color: var(--ink); background: transparent; }
#overlay .focus-nav:disabled { opacity: 0.3; }
#overlay .focus-nav:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

.focus-card.deal { animation: opDealIn 0.46s var(--op-spring) both; }
.focus-card.deal.from-pack { animation: opFromPack 0.66s var(--op-spring) both; }
@keyframes opDealIn {
  from { opacity: 0; transform: translate3d(56px, 20px, 0) rotateY(-30deg) rotateZ(5deg) scale(0.86); }
  to { opacity: 1; transform: none; }
}
@keyframes opFromPack {
  from { opacity: 0; transform: translate3d(0, 110px, 0) rotateX(26deg) scale(0.62); }
  45% { opacity: 1; }
  to { opacity: 1; transform: none; }
}
.face-front { border-radius: 4.5% / 3.3%; }
/* The card lies on the mat: a contact shadow under it, on the holder, never on .tcg. */
#overlay .face-front::before,
#overlay .face-back::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 4.5% / 3.2%;
  box-shadow: 0 2px 3px rgba(0, 0, 0, 0.5), 0 16px 34px rgba(0, 0, 0, 0.45);
  pointer-events: none;
}

/* The name, level with the foot of the card. */
#overlay .focus-meta {
  grid-area: meta;
  min-height: 0;
  margin: 0;
  padding: 0 0 calc(var(--strip-h) + 16px);
  text-align: left;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.38s ease, transform 0.42s var(--op-ease);
  pointer-events: none;
}
#overlay .focus-meta.in { opacity: 1; transform: none; }
#overlay .focus-kicker {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: flex-start;
  gap: 4px 8px;
  margin: 0 0 8px;
  color: var(--ink-2);
  font-family: var(--font);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  font-variant-numeric: tabular-nums;
}
#overlay .focus-mark {
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
  color: var(--ink);
  font-size: 14px;
}
#overlay .focus-title {
  margin: 0;
  color: var(--ink);
  font-family: var(--font);
  font-weight: 700;
  font-variation-settings: "opsz" 48;
  font-size: clamp(30px, 2.8vw, 40px);
  line-height: 1.02;
  letter-spacing: -0.02em;
  text-wrap: balance;
  overflow-wrap: anywhere;
}
/* A hit's name is the shop's signage. */
#overlay .focus-title.sign,
#overlay .end-name.sign {
  font-weight: 800;
  font-stretch: 80%;
  font-variation-settings: "opsz" 96, "wdth" 80;
  font-size: clamp(52px, 5.2vw, 76px);
  line-height: 0.9;
  letter-spacing: -0.02em;
}
#overlay .focus-data {
  margin: 12px 0 0;
  color: var(--ink);
  font-size: 17px;
  line-height: 1.4;
  font-variant-numeric: tabular-nums;
}
#overlay .focus-new { color: var(--ink-2); }

/* ---- The slot strip: which card of the pack, and where the rare slots are.
   Face-down cards are their backs; turned ones their faces. The current one
   carries an ink line, the way a chosen word does. */
#overlay .thumbs,
#overlay .thumbs.hidden {
  grid-column: 1 / -1;
  grid-row: 2;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: 6px;
  width: auto;
  max-width: none;
  min-height: var(--strip-h);
  margin: 0;
  padding: 0;
  overflow: visible;
  border: 0;
  border-radius: 0;
  background: none;
}
#overlay .thumbs.hidden { visibility: hidden; pointer-events: none; }
#overlay .thumb,
#overlay .thumb.empty {
  position: relative;
  display: grid;
  justify-items: center;
  gap: 4px;
  flex: none;
  width: 36px;
  min-height: 44px;
  padding: 0 0 8px;
  border: 0;
  border-radius: 0;
  background: none;
  color: var(--muted);
  opacity: 1;
  aspect-ratio: auto;
  font: 600 11px/1 var(--font);
  letter-spacing: 0;
  transform: none;
  translate: none;
  transition: color 0.15s ease;
}
#overlay .thumb .tcg,
#overlay .thumb-back {
  display: block;
  width: 36px;
  aspect-ratio: 63 / 88;
  border-radius: 4.5% / 3.2%;
}
#overlay .thumb-back { background: #1b1e22 var(--card-back) center / cover no-repeat; opacity: 0.5; }
#overlay .thumb.current .thumb-back { opacity: 0.9; }
#overlay .thumb > span { pointer-events: none; }
#overlay .thumb.hit,
#overlay .thumb.empty.hit { color: var(--ink-2); }
#overlay .thumb:hover,
#overlay .thumb.current { color: var(--ink); }
#overlay .thumb:hover { transform: none; translate: none; opacity: 1; }
#overlay .thumb.current::after {
  content: "";
  position: absolute;
  left: 6px;
  right: 6px;
  bottom: 0;
  height: 2px;
  background: var(--ink);
}
#overlay .thumb:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
#overlay .thumb.pop .tcg { animation: opThumbIn 0.3s ease-out both; }
@keyframes opThumbIn { from { opacity: 0; } }

/* ---- The hit ---------------------------------------------------------------
   The pendant's light gathers on the card and the shop goes dark around it;
   the card turns, the light flashes off the foil and its colour spills onto
   the mat. Every layer is sized to the card, painted once, then only moved
   or faded. */
.focus-stage > .hit-halo,
.focus-stage > .focus-aura {
  position: absolute;
  grid-column: 1 / -1;
  grid-row: 1;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  pointer-events: none;
  opacity: 0;
}
.hit-halo { z-index: 1; }
.focus-aura { z-index: 0; }

/* Build-up: the card trembles harder and harder while the light gathers; the
   rest of the table steps back. */
.focus-card.charging .pull-lift { animation: opChargeT2 var(--charge-ms) ease-in both; }
#overlay.charge-t3 .focus-card.charging .pull-lift { animation-name: opChargeT3; }
/* The tremble ends lifted and swollen, and the turn starts from that pose:
   .charged holds the last keyframe as a plain value, then .flipped eases it
   down over the flip, so the turn never starts from a snap back to rest. */
.focus-card.charged .pull-lift { transform: translateY(-8px) scale(1.05); }
#overlay.charge-t3 .focus-card.charged .pull-lift { transform: translate(0, -10px) scale(1.08); }
.focus-card.flipped .pull-lift {
  transform: none;
  transition: transform var(--flip-ms) cubic-bezier(0.2, 0.6, 0.25, 1);
}
/* A charged card turns with momentum; the tremble was the anticipation. */
.focus-card.t2 .pull-inner,
.focus-card.t3 .pull-inner { transition-timing-function: cubic-bezier(0.25, 0.1, 0.2, 1); }
@keyframes opChargeT2 {
  0% { transform: none; }
  20% { transform: translateY(-4px) rotate(-1deg) scale(1.01); }
  40% { transform: translateY(-5px) rotate(1.2deg) scale(1.02); }
  60% { transform: translateY(-6px) rotate(-1.6deg) scale(1.03); }
  80% { transform: translateY(-7px) rotate(2deg) scale(1.04); }
  100% { transform: translateY(-8px) rotate(0deg) scale(1.05); }
}
@keyframes opChargeT3 {
  0% { transform: none; }
  10% { transform: translateY(-2px) rotate(-0.6deg); }
  20% { transform: translateY(-3px) rotate(0.8deg) scale(1.01); }
  30% { transform: translateY(-4px) rotate(-1deg) scale(1.015); }
  40% { transform: translateY(-5px) rotate(1.3deg) scale(1.02); }
  50% { transform: translate(-2px, -6px) rotate(-1.6deg) scale(1.03); }
  60% { transform: translate(2px, -7px) rotate(1.9deg) scale(1.04); }
  70% { transform: translate(-3px, -8px) rotate(-2.2deg) scale(1.05); }
  80% { transform: translate(3px, -9px) rotate(2.5deg) scale(1.06); }
  90% { transform: translate(-3px, -10px) rotate(-2.8deg) scale(1.07); }
  100% { transform: translate(0, -10px) rotate(0deg) scale(1.08); }
}
#overlay.charging .focus-nav,
#overlay.charging .thumbs,
#overlay.charging .overlay-actions,
#overlay.charging .focus-meta,
#overlay.charged .focus-nav,
#overlay.charged .thumbs,
#overlay.charged .overlay-actions,
#overlay.charged .focus-meta { opacity: 0.25; transition: opacity 0.35s ease; }

/* The pendant's light on the card: warm white, gathering over the charge,
   blown out at the flash. */
.hit-halo {
  width: calc(var(--card-w) * 1.9);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(closest-side,
    rgb(255 250 240 / 0.55), rgb(var(--pendant) / 0.26) 38%, rgb(var(--pendant) / 0.08) 60%, transparent 76%);
  scale: 0.55;
}
#overlay.charging .hit-halo,
#overlay.charged .hit-halo { will-change: transform, opacity; }
#overlay.charging .hit-halo { animation: opHaloGather var(--charge-ms) cubic-bezier(0.5, 0, 0.8, 0.4) both; }
#overlay.charged .hit-halo { opacity: 0.9; scale: 1; }
#overlay.hit-flash .hit-halo { animation: opHaloBurst 0.75s var(--op-snap) both; }
/* A plain rare never charged, so its halo is a short pop rather than a blow-out. */
#overlay.hit-flash.hit-t1 .hit-halo { animation: opHaloPop 0.6s var(--op-snap) both; }
@keyframes opHaloGather {
  from { opacity: 0; scale: 0.55; }
  to { opacity: 0.9; scale: 1; }
}
@keyframes opHaloBurst {
  0% { opacity: 1; scale: 1; }
  100% { opacity: 0; scale: 1.5; }
}
@keyframes opHaloPop {
  0% { opacity: 0.5; scale: 0.7; }
  100% { opacity: 0; scale: 1.15; }
}

/* Once the card has turned, its type colour lies on the mat around it: a
   wide, low pool, the way coloured light falls on a table. A legend throws a
   few still pools of prism colour instead. No blur and no loop. */
.focus-aura {
  width: calc(var(--card-w) * 2.7);
  height: calc(var(--card-h) * 1.2);
  border-radius: 50%;
  background: radial-gradient(closest-side, var(--aura), transparent);
  transition: opacity 0.42s ease;
}
#overlay .focus-wrap.revealed .focus-aura { opacity: 0.42; }
#overlay .focus-wrap.revealed.is-hit .focus-aura { opacity: 0.62; }
#overlay .focus-wrap.rainbow .focus-aura {
  background:
    radial-gradient(closest-side at 30% 40%, rgba(255, 150, 96, 0.55), transparent),
    radial-gradient(closest-side at 70% 38%, rgba(96, 178, 255, 0.55), transparent),
    radial-gradient(closest-side at 62% 70%, rgba(255, 112, 200, 0.45), transparent),
    radial-gradient(closest-side at 38% 68%, rgba(110, 235, 170, 0.4), transparent);
}
#overlay .focus-wrap.revealed.rainbow .focus-aura { opacity: 0.7; }

/* Glints off the foil as it turns: a fixed handful of small discs and one or
   two rings, no shadows. Pieces wait out their delay unseen (fill-mode
   forwards, never both: a backwards fill would paint the first keyframe on
   the card back through the whole delay). */
.hit-fx { z-index: 4; }
.hit-spark {
  position: absolute;
  left: 50%;
  top: 48%;
  width: 8px;
  height: 8px;
  margin: -4px;
  border-radius: 50%;
  background: radial-gradient(closest-side, #fff 30%, rgba(255, 238, 200, 0.9) 55%, rgba(255, 228, 180, 0) 100%);
  opacity: 0;
  pointer-events: none;
  animation: opSpark 0.95s cubic-bezier(0.16, 0.84, 0.3, 1) var(--dly, 0ms) forwards;
}
.hit-spark.t3 { width: 10px; height: 10px; margin: -5px; }
.hit-spark.streak {
  width: 3px;
  height: 22px;
  margin: -11px -1.5px;
  border-radius: 2px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0), #fff 40%, #fff 60%, rgba(255, 255, 255, 0));
  animation-name: opStreak;
}
@keyframes opSpark {
  0% { opacity: 1; transform: translate(0, 0) scale(0.6); }
  25% { opacity: 1; transform: translate(calc(var(--sx) * 0.45), calc(var(--sy) * 0.45)) scale(1.15); }
  100% { opacity: 0; transform: translate(var(--sx), var(--sy)) scale(0.2); }
}
/* The rotation sits after the translate so the streak points along its path. */
@keyframes opStreak {
  0% { opacity: 1; transform: translate(0, 0) rotate(calc(var(--ang, 0deg) + 90deg)) scaleY(1.5); }
  100% { opacity: 0; transform: translate(var(--sx), var(--sy)) rotate(calc(var(--ang, 0deg) + 90deg)) scaleY(0.2); }
}
.hit-ring {
  position: absolute;
  left: 50%;
  top: 48%;
  width: 120px;
  height: 120px;
  margin: -60px 0 0 -60px;
  border-radius: 50%;
  border: 2px solid rgba(255, 250, 240, 0.8);
  opacity: 0;
  pointer-events: none;
  animation: opHitRing 0.72s cubic-bezier(0.1, 0.7, 0.3, 1) var(--dly, 0ms) forwards;
}
.hit-ring.t3 { border-width: 3px; }
@keyframes opHitRing {
  0% { opacity: 1; transform: scale(0.5); }
  55% { opacity: 0.5; }
  100% { opacity: 0; transform: scale(4.2); }
}

/* The kick: the card stage jolts and settles. Only the stage moves. */
#overlay.hit-shake-sm .focus-stage { animation: opKickSm 0.42s ease-out; }
#overlay.hit-shake .focus-stage { animation: opKick 0.6s ease-out; }
@keyframes opKickSm {
  0% { transform: none; }
  20% { transform: translate(-3px, 1px) scale(1.015); }
  45% { transform: translate(3px, -1px) scale(1.01); }
  70% { transform: translate(-2px, 0); }
  100% { transform: none; }
}
@keyframes opKick {
  0% { transform: none; }
  14% { transform: translate(-7px, 2px) rotate(-0.4deg) scale(1.03); }
  30% { transform: translate(6px, -2px) rotate(0.35deg) scale(1.025); }
  48% { transform: translate(-4px, 1px) scale(1.012); }
  66% { transform: translate(3px, 0); }
  84% { transform: translate(-1px, 0); }
  100% { transform: none; }
}

/* The light sliding over a rare or better once it has turned: a masked window
   and a band three cards wide, moved by transform, once. */
.reveal-sweep {
  position: absolute;
  inset: 0;
  z-index: 3;
  border-radius: 4.5% / 3.3%;
  overflow: hidden;
  pointer-events: none;
  opacity: 0;
  transform: translateZ(2px);
}
.reveal-sweep::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 300%;
  background: linear-gradient(
    112deg,
    transparent 40%,
    rgba(255, 255, 255, 0) 45%,
    rgba(255, 252, 244, 0.38) 50%,
    rgba(255, 255, 255, 0) 55%,
    transparent 60%
  );
  transform: translateX(-66.7%);
}
.focus-card.swept .reveal-sweep { animation: opSweepShow 0.95s ease-out both; }
.focus-card.swept .reveal-sweep::after { animation: opSweep 0.95s ease-out both; }
@keyframes opSweepShow {
  0%, 85% { opacity: 1; }
  100% { opacity: 0; }
}
@keyframes opSweep {
  from { transform: translateX(-66.7%); }
  to { transform: translateX(0); }
}

/* ---- Controls --------------------------------------------------------------
   Plain, on the counter under the mat: one orange action, outlines for the
   rest, underlined words for the ways out. */
#overlay .overlay-actions {
  position: static;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 10px 12px;
  width: auto;
  min-height: 0;
  margin: 0;
  padding: 0;
  background: none;
}
#overlay .overlay-actions .solid,
#overlay .overlay-actions .ghost {
  flex: none;
  width: auto;
  min-width: 0;
  min-height: 52px;
  margin: 0;
  padding: 0 24px;
  border-radius: var(--r-sm);
  font-size: 16px;
  font-weight: 650;
  box-shadow: none;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease, opacity 0.2s ease;
}
#overlay .overlay-actions .solid {
  border: 1px solid transparent;
  background: var(--orange);
  color: var(--on-orange);
}
#overlay .overlay-actions .solid:hover:not(:disabled) { background: var(--orange-hover); }
#overlay .overlay-actions .solid:disabled { opacity: 0.45; cursor: default; }
/* On the laminate a line-2 outline disappears; the outline is the ink, thinned. */
#overlay .overlay-actions .ghost {
  border: 1px solid rgb(var(--hl) / 0.38);
  background: transparent;
  color: var(--ink);
}
#overlay .overlay-actions .ghost:hover:not(:disabled) { border-color: var(--ink); background: transparent; }
#overlay .overlay-actions .link-btn {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink);
  font-size: 15px;
  font-weight: 600;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
  text-decoration-color: rgb(var(--hl) / 0.5);
}
#overlay .overlay-actions .link-btn:hover { text-decoration-color: var(--ink); }
#overlay .overlay-actions .link-btn:disabled { opacity: 0.5; }
#overlay #again-btn { display: inline-flex; align-items: center; justify-content: center; }
#overlay #again-btn.hidden { display: none; }
#overlay .op-price {
  display: inline-flex;
  align-items: center;
  margin-left: 10px;
  font-size: 15px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
#overlay .op-price .coin-i { width: 18px; height: 18px; margin-right: 4px; vertical-align: 0; }

/* Once the receipt has printed, the ways on stack under it. */
#overlay.with-receipt .overlay-actions {
  flex-direction: column;
  align-items: stretch;
  gap: 2px;
}
#overlay.with-receipt .overlay-actions .solid { min-height: 56px; margin-bottom: 10px; font-size: 18px; }
#overlay.with-receipt .overlay-actions .ghost { margin-bottom: 10px; }
#overlay.with-receipt .overlay-actions .link-btn { align-self: flex-start; }

/* ---- The end of the pack: the cards laid out on the mat ------------------
   The best pull large on the left, the rest in pack order beside it, its
   name under them. Each card opens the inspector. */
#overlay .spread { display: block; margin: 0; }
#overlay .end-mat {
  --lead-w: clamp(240px, calc((100svh - 220px) * 0.716), 440px);
  display: grid;
  grid-template-columns: var(--lead-w) minmax(0, 1fr);
  grid-template-rows: auto 1fr;
  grid-template-areas: "lead rest" "lead about";
  gap: 26px 34px;
  padding: 4px 0 6px;
}
#overlay .end-lead { grid-area: lead; align-self: start; }
#overlay .end-lead .spread-card { width: var(--lead-w); }
#overlay .end-rest {
  grid-area: rest;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 14px 11px;
  align-content: start;
}
#overlay .end-rest .spread-card { width: 100%; }
#overlay .end-mat .spread-card {
  position: relative;
  display: block;
  padding: 0;
  border: 0;
  border-radius: 4.5% / 3.2%;
  background: none;
  animation: none;
  cursor: pointer;
}
/* Cards lying on the mat: a contact shadow on the holder, never on .tcg. */
#overlay .end-mat .spread-card::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 4.5% / 3.2%;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.5), 0 6px 12px rgba(0, 0, 0, 0.35);
  pointer-events: none;
}
#overlay .end-lead .spread-card::before { box-shadow: 0 2px 3px rgba(0, 0, 0, 0.5), 0 16px 34px rgba(0, 0, 0, 0.45); }
#overlay .spread-card:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }
#overlay .spread-card.top-pull .tcg img { filter: none; }
#overlay .end-about { grid-area: about; align-self: end; min-width: 0; padding-bottom: 6px; }
#overlay .end-kicker { margin: 0 0 6px; color: var(--ink-2); font-size: 15px; }
#overlay .end-name {
  margin: 0;
  color: var(--ink);
  font-size: clamp(30px, 2.8vw, 40px);
  font-weight: 700;
  font-variation-settings: "opsz" 48;
  line-height: 1.02;
  letter-spacing: -0.02em;
  text-wrap: balance;
  overflow-wrap: anywhere;
  outline: none;
}
#overlay .end-data { margin: 10px 0 0; color: var(--ink); font-size: 17px; font-variant-numeric: tabular-nums; }
#overlay .spread-tip { margin: 18px 0 0; color: var(--ink-2); font-size: 14px; text-align: left; }

/* ---- The till receipt (also used by the order results, css/pages/batch.css).
   Thermal paper, Share Tech Mono, uppercase: the one place either is used.
   A hit's row prints inverted. The bottom edge is torn off the roll. */
.receipt {
  position: relative;
  margin: 0 0 8px;
  padding: 20px 16px 24px;
  background: var(--thermal);
  color: var(--print);
  font-family: var(--receipt-font);
  font-size: 13px;
  font-weight: 400;
  line-height: 1.38;
  letter-spacing: 0.02em;
  text-align: left;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 12px 24px rgba(0, 0, 0, 0.3);
  transform: rotate(0.6deg);
}
.receipt::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -7px;
  height: 8px;
  background:
    linear-gradient(135deg, var(--thermal) 50%, transparent 50%) 0 0 / 8px 8px repeat-x,
    linear-gradient(225deg, var(--thermal) 50%, transparent 50%) 0 0 / 8px 8px repeat-x;
}
.receipt p { margin: 0; }
.receipt-shop { font-size: 22px; line-height: 1.1; letter-spacing: 0.06em; text-align: center; }
.receipt-head { margin-top: 6px !important; text-align: center; }
.receipt hr { margin: 10px 0; border: 0; border-top: 1px dashed #77736c; }
.receipt-rows { margin: 0; padding: 0; list-style: none; }
.receipt-rows li,
.receipt-line {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: 10px;
}
.receipt .r-name { display: flex; min-width: 0; white-space: nowrap; }
.receipt .r-nm { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.receipt .r-code { flex: none; white-space: pre; }
.receipt .r-name i { flex: none; margin-left: 0.6em; font-style: normal; }
.receipt .r-val { text-align: right; white-space: nowrap; }
.receipt-rows li.sub { padding-left: 2ch; }
.receipt-rows li.hit { margin: 2px -6px; padding: 1px 6px; background: var(--print); color: var(--thermal); }
.receipt-rows li.sub2 { padding-left: 4ch; }
.receipt-rows li.hit.sub { padding-left: calc(2ch + 6px); }
.receipt-rows li.hit.sub2 { padding-left: calc(4ch + 6px); }
.receipt-total { margin-top: 4px !important; font-size: 20px; line-height: 1.2; }
.receipt-foot { font-size: 12px; text-align: center; }

/* ---- A box's promos before its first pack, and the rest of the box -------- */
#overlay .spread-head { margin: 0 0 22px; text-align: center; }
#overlay .spread-head h2 {
  margin: 0;
  font-family: var(--font);
  font-weight: 700;
  font-variation-settings: "opsz" 48;
  font-size: clamp(28px, 3vw, 40px);
  line-height: 1.05;
  letter-spacing: -0.02em;
}
#overlay .spread-facts { margin: 10px 0 0; color: var(--ink-2); font-size: 15px; }
#overlay .spread-facts .coin-i { width: 16px; height: 16px; vertical-align: -3px; margin-right: 3px; }
#overlay .spread-grid { display: flex; flex-wrap: wrap; justify-content: center; gap: 18px; max-width: 980px; margin: 0 auto; }
#overlay .promo-spread .spread-card {
  width: min(240px, 40vw);
  padding: 0;
  border: 0;
  background: none;
  animation: none;
}
#overlay .box-cards { width: min(980px, 100%); margin: 28px auto 0; padding: 0; }
#overlay .box-cards-title {
  margin: 0 0 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid rgb(var(--hl) / 0.16);
  font: 650 15px/1.2 var(--font);
}
#overlay .box-cards-group + .box-cards-group { margin-top: 16px; }
#overlay .box-cards-group h4 { margin: 0 0 8px; color: var(--ink-2); font: 600 14px/1.2 var(--font); }
#overlay .box-cards-group h4 span { margin-left: 6px; font-variant-numeric: tabular-nums; }
#overlay .box-cards-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 10px; }
#overlay .box-card {
  position: relative;
  display: block;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}
#overlay .box-card .tcg { width: 100%; }
#overlay .box-count,
#overlay .box-new {
  position: absolute;
  z-index: 3;
  padding: 2px 6px;
  border-radius: 2px;
  font: 700 11px/1.2 var(--font);
  background: var(--ink);
  color: var(--black);
  pointer-events: none;
}
#overlay .box-count { right: 0; bottom: 0; font-variant-numeric: tabular-nums; }
#overlay .box-new { left: 0; top: 0; }

/* ---- Narrower desktops: the receipt drops under the mat ------------------- */
@media (max-width: 1180px) {
  #overlay.with-receipt .op-table { grid-template-columns: minmax(0, 1fr); max-width: 980px; }
  #overlay.with-receipt .op-side { display: grid; grid-template-columns: minmax(0, 330px) minmax(0, 1fr); gap: 28px; align-items: start; }
}
@media (max-width: 960px) {
  #overlay .focus-wrap { grid-template-columns: auto minmax(0, 260px); column-gap: 20px; }
  #overlay .focus-title.sign,
  #overlay .end-name.sign { font-size: clamp(40px, 6vw, 56px); }
}

/* ---- Phone ----------------------------------------------------------------
   The card as large as the screen allows, the strip and prev/next under it,
   its name under those, and the controls in a bar along the bottom. The end
   of the pack stacks: the best pull, its name, the other ten five wide, the
   receipt, the ways out; Open another stays in reach at the bottom. */
@media (max-width: 720px) {
  #overlay {
    --gutter-x: 12px;
    --bottom-bar: calc(130px + env(safe-area-inset-bottom));
    --card-w: min(calc(100vw - 52px), calc((100svh - 254px - var(--bottom-bar)) * 0.716));
    --card-h: calc(var(--card-w) / 0.716);
    --strip-h: 40px;
  }
  #overlay,
  #overlay.dealing { display: flex; padding: 0; overflow-y: auto; }
  #overlay .op-bar { min-height: 52px; gap: 10px; padding: max(0px, env(safe-area-inset-top)) var(--gutter-x) 0; }
  #overlay .overlay-leave,
  #overlay .overlay-leave:hover { margin-left: -6px; padding: 0 10px 0 6px; align-self: center; }
  #overlay .op-where { font-size: 14px; }
  #overlay .box-progress { flex: none; font-size: 13px; white-space: nowrap; }
  #overlay .box-progress b,
  #overlay .box-pips { display: none; }
  #overlay .op-table,
  #overlay.with-receipt .op-table {
    grid-template-columns: minmax(0, 1fr);
    gap: 26px;
    max-width: none;
    padding: 2px 10px calc(var(--bottom-bar) + 14px);
  }
  #overlay .op-mat { padding: 16px 10px 14px; border-radius: 14px; }
  #overlay .op-mat::after { inset: 4px; border-radius: 10px; }
  #overlay .rip-hint { margin: 0 0 12px; font-size: 14px; }
  #overlay .booster { width: min(64vw, calc((100svh - 330px) * 0.55)); margin-bottom: 22px; }

  /* Reveal: the card, then [prev, strip, next], then the name. */
  #overlay .focus-wrap { display: flex; flex-direction: column; align-items: stretch; gap: 12px; }
  #overlay .focus-stage {
    grid-template-columns: 40px minmax(0, 1fr) 40px;
    grid-template-rows: auto auto;
    gap: 12px 4px;
    width: 100%;
  }
  #overlay .focus-card { grid-column: 1 / -1; grid-row: 1; width: var(--card-w); }
  #overlay .focus-nav { width: 40px; height: 44px; }
  #overlay .focus-nav.prev { grid-column: 1; grid-row: 2; }
  #overlay .focus-nav.next { grid-column: 3; grid-row: 2; }
  #overlay .thumbs,
  #overlay .thumbs.hidden {
    grid-column: 2;
    grid-row: 2;
    display: flex !important;
    gap: 3px;
    min-height: var(--strip-h);
    align-items: center;
  }
  #overlay .thumb,
  #overlay .thumb.empty { width: 21px; min-height: 40px; padding: 0 0 7px; align-content: start; }
  #overlay .thumb .tcg,
  #overlay .thumb-back { width: 21px; }
  #overlay .thumb > span { display: none; }
  #overlay .thumb.current::after { left: 3px; right: 3px; }
  #overlay .focus-meta {
    order: 2;
    min-height: 84px;
    padding: 0 4px;
  }
  #overlay .focus-kicker { margin-bottom: 4px; font-size: 14px; }
  #overlay .focus-title { font-size: 26px; display: block; min-height: 0; overflow: visible; -webkit-line-clamp: none; }
  #overlay .focus-title.sign { font-size: 42px; }
  #overlay .focus-data { margin-top: 6px; font-size: 15px; }
  .hit-halo { width: calc(var(--card-w) * 1.6); }
  .focus-aura { width: calc(var(--card-w) * 1.8); height: calc(var(--card-h) * 1.1); }

  /* The controls live in a bar along the bottom of the screen. */
  #overlay .overlay-actions {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 8;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    padding: 10px 12px max(12px, env(safe-area-inset-bottom));
    border-top: 1px solid var(--line-2);
    background: var(--wall-dark);
  }
  #overlay .overlay-actions .solid { grid-column: 1 / -1; min-height: 52px; }
  #overlay .overlay-actions .ghost { min-height: 48px; padding: 0 12px; font-size: 15px; border-color: var(--line-2); }
  #overlay .overlay-actions:not(:has(#skip-hits-btn:not(.hidden))) #skip-btn { grid-column: 1 / -1; }
  #overlay .overlay-actions .link-btn { grid-column: 1 / -1; }
  /* Mid-box the way out is the box summary, a plain word under the buttons. */
  #overlay:has(#box-summary-btn:not(.hidden)) { --bottom-bar: calc(182px + env(safe-area-inset-bottom)); }
  #overlay:not(.is-spread) #box-summary-btn {
    grid-column: 1 / -1;
    min-height: 44px;
    border: 0;
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 4px;
    text-decoration-color: rgb(var(--hl) / 0.5);
  }

  /* The end: everything in the page's flow except Open another. */
  #overlay.with-receipt .op-side,
  #overlay.is-spread .op-side { display: flex; flex-direction: column; align-items: stretch; gap: 22px; }
  #overlay.is-spread .overlay-actions {
    position: static;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    padding: 0 6px;
    border: 0;
    background: none;
  }
  #overlay.is-spread .overlay-actions .link-btn { align-self: flex-start; }
  #overlay.is-spread .overlay-actions .ghost { margin: 0 0 10px; }
  /* Open another rides in a bar along the bottom; the bar is the button's
     own spread shadow, with the hairline peeking out above it. */
  #overlay.is-spread #again-btn:not(.hidden) {
    position: fixed;
    left: 12px;
    right: 12px;
    bottom: max(12px, env(safe-area-inset-bottom));
    z-index: 9;
    margin: 0;
    box-shadow: 0 0 0 12px var(--wall-dark), 0 -1px 0 12px var(--line-2), 0 24px 0 12px var(--wall-dark);
  }
  #overlay.is-spread .op-table { padding-bottom: 28px; }
  #overlay.is-spread:has(#again-btn:not(.hidden)) .op-table { padding-bottom: calc(96px + env(safe-area-inset-bottom)); }

  #overlay .end-mat {
    --lead-w: min(330px, 100%);
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto;
    grid-template-areas: "lead" "about" "rest";
    gap: 18px;
    padding: 6px 2px 4px;
  }
  #overlay .end-lead { display: flex; justify-content: center; }
  #overlay .end-rest { gap: 10px 7px; }
  #overlay .end-about { padding: 0 4px; }
  #overlay .end-name { font-size: 28px; }
  #overlay .end-name.sign { font-size: 46px; }
  #overlay .end-data { font-size: 16px; }
  #overlay .receipt { width: 100%; max-width: 340px; margin: 0 auto 8px; }
  #overlay .spread-head h2 { font-size: 26px; }
  #overlay .promo-spread .spread-card { width: min(200px, 42vw); }
  #overlay .box-cards-grid { grid-template-columns: repeat(auto-fill, minmax(64px, 1fr)); gap: 8px; }
}

/* ---- Kill-switches ------------------------------------------------------- */
body.no-flash .hit-fx,
body.no-flash .hit-halo,
body.no-flash .op-hit,
body.no-flash .op-dim { display: none; }
body.no-flash #overlay.hit-shake .focus-stage,
body.no-flash #overlay.hit-shake-sm .focus-stage,
body.no-flash #overlay .focus-card.charging .pull-lift { animation: none; }

body.no-motion .reveal-sweep { display: none; }
body.no-motion #overlay .booster,
body.no-motion .pack-sheen::after,
body.no-motion .tear-guide i,
body.no-motion #overlay .focus-card .pull-lift,
body.no-motion #overlay .hit-halo,
body.no-motion #overlay .focus-aura,
body.no-motion #overlay .hit-spark,
body.no-motion #overlay .hit-ring,
body.no-motion #overlay .focus-stage,
body.no-motion #overlay .thumb.pop .tcg,
body.no-motion .op-flash,
body.no-motion .op-hit { animation: none !important; }
body.no-motion #overlay[data-phase="ready"] .tear-guide { opacity: 1; }
body.no-motion #overlay .booster.tearing .tear-guide,
body.no-motion #overlay .booster.torn .tear-guide { opacity: 0; }
body.no-motion #overlay .focus-card.deal { animation: none; }
body.no-motion #overlay .focus-meta { transform: none; }
body.no-motion #overlay .hit-halo { opacity: 0 !important; }
body.no-motion .op-dim,
body.no-motion .op-mat::before,
body.no-motion .focus-aura { transition: none; }

@media (prefers-reduced-motion: reduce) {
  .reveal-sweep { display: none; }
  #overlay .booster,
  .pack-sheen::after,
  .tear-guide i,
  #overlay .focus-card .pull-lift,
  #overlay .hit-halo,
  #overlay .focus-aura,
  #overlay .hit-spark,
  #overlay .hit-ring,
  #overlay .focus-stage,
  #overlay .thumb.pop .tcg,
  .op-flash,
  .op-hit { animation: none !important; }
  #overlay[data-phase="ready"] .tear-guide { opacity: 1; }
  #overlay .booster.tearing .tear-guide,
  #overlay .booster.torn .tear-guide { opacity: 0; }
  #overlay .focus-meta { transform: none; }
  #overlay .hit-halo { opacity: 0 !important; }
  .op-dim, .op-mat::before, .focus-aura { transition: none; }
}
