/* =========================================================================
   Birthday pack -- premium collectible feel: dark, lit from within, calm.
   ========================================================================= */

:root {
  color-scheme: dark;

  --ink:        #0a0718;
  --ink-2:      #130c2c;
  --gold:       #d6a41a;
  --gold-soft:  #f0cd72;
  --violet:     #7b4ae0;
  --magenta:    #e0568f;
  --cyan:       #58e5da;
  --text:       #efe9ff;
  --muted:      #a99fc8;

  --card-aspect: 0.7136;          /* overwritten from border.png at runtime */
  --pack-aspect: 0.7111;

  --card-h: min(70vh, 660px, calc(88vw / var(--card-aspect)));
  --card-w: calc(var(--card-h) * var(--card-aspect));
  --pack-h: min(62vh, 580px, calc(78vw / var(--pack-aspect)));
  --pack-w: calc(var(--pack-h) * var(--pack-aspect));

  --ease: cubic-bezier(.22, .68, .3, 1);
  --sans: 'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --display: 'Cinzel', 'Iowan Old Style', Georgia, serif;
}

@supports (height: 100dvh) {
  :root {
    --card-h: min(70dvh, 660px, calc(88vw / var(--card-aspect)));
    --pack-h: min(62dvh, 580px, calc(78vw / var(--pack-aspect)));
  }
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--ink);
  color: var(--text);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
  overscroll-behavior: none;
}

body {
  overflow: hidden;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

img { max-width: 100%; display: block; user-select: none; -webkit-user-drag: none; }

/* ----------------------------------------------------------- ambient bg -- */

#fx {
  position: fixed; inset: 0;
  width: 100%; height: 100%;
  z-index: 1; pointer-events: none;
}

.ambient { position: fixed; inset: 0; z-index: 0; overflow: hidden; }

.ambient::after {                       /* deep vignette keeps focus centred */
  content: '';
  position: absolute; inset: -20%;
  background: radial-gradient(ellipse at 50% 45%, transparent 28%, rgba(5, 3, 15, .78) 78%);
}

.orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(70px);
  opacity: .5;
  animation: drift 26s ease-in-out infinite;
}
.orb--a { width: 54vmax; height: 54vmax; left: -18vmax; top: -16vmax;
          background: radial-gradient(circle, rgba(123, 74, 224, .55), transparent 68%); }
.orb--b { width: 46vmax; height: 46vmax; right: -14vmax; top: 18vmax;
          background: radial-gradient(circle, rgba(224, 86, 143, .45), transparent 68%);
          animation-duration: 34s; animation-direction: reverse; }
.orb--c { width: 40vmax; height: 40vmax; left: 22vmax; bottom: -18vmax;
          background: radial-gradient(circle, rgba(88, 229, 218, .28), transparent 68%);
          animation-duration: 42s; }

@keyframes drift {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  33%      { transform: translate3d(6vmax, -4vmax, 0) scale(1.12); }
  66%      { transform: translate3d(-5vmax, 5vmax, 0) scale(.94); }
}

.grid {
  position: absolute; inset: 0;
  background-image:
    linear-gradient(rgba(255, 255, 255, .028) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, .028) 1px, transparent 1px);
  background-size: 62px 62px;
  mask-image: radial-gradient(ellipse at 50% 45%, #000 20%, transparent 72%);
  -webkit-mask-image: radial-gradient(ellipse at 50% 45%, #000 20%, transparent 72%);
}

/* --------------------------------------------------------------- screens -- */

#app { position: relative; z-index: 2; height: 100%; }

.screen {
  position: fixed; inset: 0;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: clamp(18px, 3.4vh, 34px);
  padding: max(20px, env(safe-area-inset-top)) 20px max(20px, env(safe-area-inset-bottom));
  opacity: 0;
  transform: translateY(14px) scale(.985);
  pointer-events: none;
  transition: opacity .55s var(--ease), transform .55s var(--ease);
}
.screen[hidden] { display: none; }
.screen.is-active { opacity: 1; transform: none; pointer-events: auto; }
.screen.is-leaving { opacity: 0; transform: translateY(-20px) scale(.97); }

/* ------------------------------------------------------------------ gate -- */

.gate {
  width: min(330px, 100%);
  text-align: center;
}

.gate__mark {
  display: block;
  width: 23px; height: 25px;
  margin: 0 auto 32px;
  filter: drop-shadow(0 3px 16px rgba(214, 164, 26, .5));
}

.gate__title {
  margin: 0 0 46px;
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(22px, 5.4vw, 29px);
  line-height: 1.3;
  letter-spacing: .015em;
  color: #f4f0ff;
  text-wrap: balance;
}

.gate__form {
  display: grid;
  gap: 32px;
  justify-items: center;
}

.field { width: 100%; }

/* A ruled line rather than a box -- it reads as an engraved field instead
   of a web form, which is the whole character of this screen. */
.field__input {
  width: 100%;
  padding: 10px 0 14px;
  border: 0;
  border-bottom: 1px solid rgba(255, 255, 255, .2);
  border-radius: 0;
  background: none;
  color: var(--text);
  font-family: var(--sans);
  font-size: 16px;                      /* 16px stops iOS zooming on focus */
  font-weight: 400;
  letter-spacing: .3em;
  text-align: center;
  text-indent: .3em;                    /* offsets the trailing letter-space */
  text-transform: uppercase;
  outline: none;
  transition: border-color .35s, box-shadow .35s;
}
.field__input::placeholder {
  font-size: 12.5px;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: rgba(169, 159, 200, .38);
}
.field__input:focus {
  border-bottom-color: rgba(240, 205, 114, .85);
  box-shadow: 0 1px 0 rgba(240, 205, 114, .3);
}

.field.is-wrong { animation: shakeX .4s var(--ease); }
.field.is-wrong .field__input { border-bottom-color: rgba(255, 122, 132, .8); }
@keyframes shakeX {
  20%, 60% { transform: translateX(-5px); }
  40%, 80% { transform: translateX(5px); }
}

.gate__error {
  min-height: 18px;
  margin: 22px 0 0;
  font-size: 12px;
  letter-spacing: .04em;
  line-height: 1.45;
  color: #ff97a3;
  opacity: 0;
  transition: opacity .25s;
}
.gate__error.is-shown { opacity: 1; }

/* --------------------------------------------------------------- buttons -- */

.btn {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  gap: 10px;
  padding: 15px 30px;
  border: 0; border-radius: 10px;
  font-family: var(--sans);
  font-size: 12px; font-weight: 600;
  letter-spacing: .2em; text-transform: uppercase;
  cursor: pointer;
  overflow: hidden;
  transition: transform .22s var(--ease), box-shadow .3s, opacity .3s;
}
.btn:active { transform: scale(.975); }
.btn:disabled { cursor: default; opacity: .6; }

.btn--primary {
  min-width: 172px;
  color: #241806;
  background: linear-gradient(180deg, #f4d484, var(--gold));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .45), 0 4px 16px rgba(214, 164, 26, .14);
}
.btn--primary:hover { background: linear-gradient(180deg, #f8dc96, #e0ae22); }

.btn--ghost {
  color: var(--text);
  background: rgba(255, 255, 255, .05);
  border: 1px solid rgba(255, 255, 255, .16);
  backdrop-filter: blur(10px);
}
.btn--ghost:hover { background: rgba(255, 255, 255, .1); border-color: rgba(240, 205, 114, .45); }

.btn__spin {
  width: 15px; height: 15px;
  border: 2px solid rgba(37, 24, 3, .3);
  border-top-color: #251803;
  border-radius: 50%;
  display: none;
  animation: spin .7s linear infinite;
}
.btn.is-busy .btn__spin { display: block; }
.btn.is-busy .btn__label { opacity: .55; }
@keyframes spin { to { transform: rotate(360deg); } }

.hint {
  margin: 0;
  font-size: 12px; letter-spacing: .22em; text-transform: uppercase;
  color: var(--muted); opacity: .7;
  text-align: center;
  animation: breathe 3.4s ease-in-out infinite;
  transition: opacity .4s;
}
.hint.is-hidden { opacity: 0; }
@keyframes breathe { 50% { opacity: .32; } }

/* ------------------------------------------------------------------ pack -- */

.pack-scene {
  position: relative;
  width: var(--pack-w); height: var(--pack-h);
  perspective: 1100px;
  transform-style: preserve-3d;
}

.pack-shadow {
  position: absolute;
  left: 50%; bottom: -7%;
  width: 66%; height: 7%;
  transform: translateX(-50%);
  background: radial-gradient(ellipse, rgba(0, 0, 0, .62), transparent 72%);
  filter: blur(9px);
  transition: opacity .5s;
}

.pack {
  position: absolute; inset: 0;
  transform-style: preserve-3d;
  cursor: grab;
  will-change: transform;
  touch-action: none;          /* a drag here is ours, never a page gesture */
}
.pack:active { cursor: grabbing; }
.pack:focus-visible { outline: 2px solid var(--gold-soft); outline-offset: 14px; border-radius: 20px; }

.pack__piece {
  position: absolute; inset: 0;
  will-change: transform, opacity;
  filter: drop-shadow(0 22px 42px rgba(0, 0, 0, .55));
}
.pack__piece--top    { clip-path: var(--clip-top,    inset(0 0 78% 0)); }
.pack.is-pulling .pack__piece--top { z-index: 3; }
.pack__piece--bottom { clip-path: var(--clip-bottom, inset(22% 0 0 0)); }

.pack__art { width: 100%; height: 100%; object-fit: contain; }

.pack__gloss {
  position: absolute; inset: 0;
  pointer-events: none;
  border-radius: 22px;
  background: linear-gradient(112deg,
      transparent 30%, rgba(255, 255, 255, .16) 44%,
      rgba(255, 255, 255, .34) 50%, rgba(255, 255, 255, .16) 56%, transparent 70%);
  background-size: 260% 100%;
  mix-blend-mode: overlay;
  animation: sweep 5.2s linear infinite;
}

.pack__leak {
  position: absolute; inset: 0;
  pointer-events: none;
  background: linear-gradient(to bottom,
      transparent calc(var(--tear, 22%) - 6%),
      rgba(255, 243, 212, .78) var(--tear, 22%),
      transparent calc(var(--tear, 22%) + 6%));
  mix-blend-mode: screen;
  opacity: var(--seam-op, 0);
  transition: opacity .12s linear;
}
.pack.is-tearing .pack__leak { animation: seamFlash .55s ease-out forwards; }
@keyframes seamFlash {
  0%   { opacity: var(--seam-op, 0); }
  22%  { opacity: 1; }
  100% { opacity: 0; }
}

.pack.is-torn .pack__piece {
  transition: transform 1.15s cubic-bezier(.16, .74, .28, 1), opacity .9s ease-in .25s;
  opacity: 0;
}
.pack.is-torn .pack__piece--top    { transform: translate3d(-16%, -122%, 0) rotate(-19deg); }
.pack.is-torn .pack__piece--bottom { transform: translate3d(14%, 116%, 0) rotate(13deg); }
.pack.is-torn .pack__gloss { opacity: 0; transition: opacity .3s; }

/* ------------------------------------------------------------------ card -- */

.card-scene {
  position: relative;
  width: var(--card-w); height: var(--card-h);
  perspective: 1400px;
}

.rays {
  position: absolute;
  left: 50%; top: 50%;
  width: 200%; aspect-ratio: 1;
  transform: translate(-50%, -50%) scale(.2);
  opacity: 0;
  pointer-events: none;
  background: conic-gradient(from 0deg,
      transparent 0 4deg, rgba(255, 226, 160, .5) 5deg 6deg, transparent 7deg 14deg,
      rgba(200, 170, 255, .4) 15deg 16deg, transparent 17deg 26deg,
      rgba(255, 226, 160, .34) 27deg 28deg, transparent 29deg 40deg);
  mask-image: radial-gradient(circle, #000 8%, transparent 58%);
  -webkit-mask-image: radial-gradient(circle, #000 8%, transparent 58%);
}
.card-scene.is-revealing .rays { animation: raysBurst 1.5s ease-out forwards; }
@keyframes raysBurst {
  0%   { opacity: 0;  transform: translate(-50%, -50%) scale(.2) rotate(0deg); }
  22%  { opacity: .95; }
  100% { opacity: 0;  transform: translate(-50%, -50%) scale(1.1) rotate(42deg); }
}

.bloom {
  position: absolute;
  left: 50%; top: 50%;
  width: 168%; aspect-ratio: 1;
  max-width: none;
  transform: translate(-50%, -50%);
  pointer-events: none;
  opacity: 0;
  background:
    radial-gradient(circle,
      rgba(255, 214, 140, calc(.06 + var(--pfc, 0) * .12)) 0%,
      rgba(168, 96, 255, calc(.05 + var(--pfc, 0) * .1)) 34%,
      transparent 66%);
  transition: opacity 1.2s ease .4s;
}
.screen--card.is-ready .bloom { opacity: 1; }

.card {
  position: absolute; inset: 0;
  transform-style: preserve-3d;
  cursor: pointer;
  will-change: transform;
  touch-action: none;
  transform:
    rotateX(calc(var(--ty, 0) * var(--tilt, 16deg) * -1))
    rotateY(calc(var(--tx, 0) * var(--tilt, 16deg)))
    scale(var(--sc, 1))
    translateZ(0);
}
.card:focus-visible { outline: 2px solid var(--gold-soft); outline-offset: 16px; border-radius: 18px; }

.card__inner {
  position: absolute; inset: 0;
  transform-style: preserve-3d;
  transform: rotateY(var(--flip, 0deg));
  transition: transform .95s cubic-bezier(.3, .9, .25, 1);
}

.face {
  position: absolute; inset: 0;
  border-radius: 14px;
  overflow: hidden;
  isolation: isolate;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  background: #07050f;
  box-shadow:
    calc(var(--tx, 0) * -22px) calc(var(--ty, 0) * -22px + 30px) 60px rgba(0, 0, 0, .7),
    calc(var(--tx, 0) * -8px) calc(var(--ty, 0) * -8px + 10px) 22px rgba(0, 0, 0, .45),
    0 0 0 1px rgba(255, 255, 255, .08),
    inset 0 0 0 1px rgba(255, 255, 255, .06);
}
.face--back { transform: rotateY(180deg); }
.face__art { width: 100%; height: 100%; object-fit: cover; }

/* -- parallax layers -- */

.layers { position: absolute; inset: 0; }

.layer {
  position: absolute; inset: 0;
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  will-change: transform;
  transform:
    translate3d(calc(var(--tx, 0) * var(--depth, 0) * 1px),
                calc(var(--ty, 0) * var(--depth, 0) * 1px), 0)
    scale(var(--layer-scale, 1));
}
.layer--background { --layer-scale: 1.07; }
.layer--character  { --layer-scale: 1.02; }
.layer--secondary  { --layer-scale: 1.03; }
.layer--border     { --layer-scale: 1; transform: none; }

/* -- holographic foil ----------------------------------------------------

   Generated entirely here; never baked into the artwork. The trick that
   makes foil read as foil rather than a colour wash: stack a few gradients,
   blend them together with background-blend-mode, then crush the result
   with a high contrast() before compositing in color-dodge. Contrast is
   what produces bright specular streaks with dark gaps between them --
   tinting alone just muddies the art underneath.

   --px/--py   pointer over the card, 0-100
   --bgx/--bgy pointer remapped to a wider travel for the foil
   --pfc       0 at the centre, 1 at the edges; drives intensity
   ------------------------------------------------------------------- */

.holo { position: absolute; inset: 0; pointer-events: none; }
.holo > span { position: absolute; inset: -1px; display: block; }

.holo-bg {
  position: absolute; inset: 0;
  pointer-events: none;
  /* sits in the background plane, so it travels with the scenery the way a
     laminated foil does -- the reflection moves across it, not the foil */
  transform: translate3d(calc(var(--tx, 0) * var(--depth-bg, -5) * 1px),
                         calc(var(--ty, 0) * var(--depth-bg, -5) * 1px), 0)
             scale(1.07);
  opacity: calc(var(--holo, .5) * (1.4 + var(--pfc, 0) * .5));
}

/* Gold foil confined to the frame's own lines, masked by border.png, so it
   follows whatever frame is dropped in. */
.holo-border {
  position: absolute; inset: 0;
  pointer-events: none;
  mask-size: 100% 100%;
  -webkit-mask-size: 100% 100%;
  mask-repeat: no-repeat;
  -webkit-mask-repeat: no-repeat;
  opacity: calc(var(--border-holo, 1) * (.85 + var(--pfc, 0) * .35));
}

/* The frame's own gold has to stay gold. A coloured source pushes its hue --
   hard-light turned it orange -- so the source here is GREYSCALE and rides on
   overlay: only the value moves, the hue underneath is left alone. That is
   what metallic ink does when it catches the light. */
[data-holo-border="gold"] .holo-border {
  background-image:
    repeating-linear-gradient(104deg,
      rgba(0, 0, 0, .5) 0%, rgba(70, 70, 70, .45) 2%,
      rgba(200, 196, 186, .8) 4%, rgba(255, 252, 242, .98) 5.4%,
      rgba(200, 196, 186, .8) 6.8%, rgba(70, 70, 70, .45) 9%,
      rgba(0, 0, 0, .5) 13%, rgba(0, 0, 0, .55) 18%),
    radial-gradient(farthest-corner circle at calc(var(--px, 50) * 1%) calc(var(--py, 50) * 1%),
      rgba(255, 255, 255, .5) 3%, rgba(128, 128, 128, .5) 40%, rgba(0, 0, 0, .5) 105%);
  background-blend-mode: overlay;
  background-size: 240% 240%, 250% 250%;
  background-position:
    calc(var(--bgx, 50) * 1%) calc(var(--bgy, 50) * 1%),
    calc(var(--px, 50) * 1%) calc(var(--py, 50) * 1%);
  filter: contrast(1.25);
  mix-blend-mode: overlay;
}

/* Same idea, but the highlight carries a little colour, so the frame reads
   as an iridescent foil rather than plain metal. Kept low-saturation on
   purpose -- more than this and the gold stops looking like gold. */
[data-holo-border="rainbow"] .holo-border {
  background-image:
    repeating-linear-gradient(104deg,
      rgba(0, 0, 0, .5) 0%, rgba(255, 150, 180, .55) 2.4%,
      rgba(255, 240, 190, .85) 4.4%, rgba(190, 255, 230, .85) 6.4%,
      rgba(170, 200, 255, .6) 8.6%, rgba(0, 0, 0, .5) 12.5%,
      rgba(0, 0, 0, .55) 17%),
    radial-gradient(farthest-corner circle at calc(var(--px, 50) * 1%) calc(var(--py, 50) * 1%),
      rgba(255, 255, 255, .5) 3%, rgba(128, 128, 128, .5) 40%, rgba(0, 0, 0, .5) 105%);
  background-blend-mode: overlay;
  background-size: 240% 240%, 250% 250%;
  background-position:
    calc(var(--bgx, 50) * 1%) calc(var(--bgy, 50) * 1%),
    calc(var(--px, 50) * 1%) calc(var(--py, 50) * 1%);
  filter: contrast(1.3) saturate(1.15);
  mix-blend-mode: overlay;
}

/* Each recipe is a bright, STRUCTURED band rather than an even wash. The
   mask is narrow and travels a long way for a small tilt, so the highlight
   races across the art the way foil does; outside the band there is nothing,
   which is what keeps dark artwork dark. */

.holo-bg {
  mask-image: linear-gradient(
      calc(101deg + var(--tx, 0) * 16deg),
      transparent 12%, rgba(0, 0, 0, .45) 32%, #000 46%, #000 54%,
      rgba(0, 0, 0, .45) 68%, transparent 88%);
  -webkit-mask-image: linear-gradient(
      calc(101deg + var(--tx, 0) * 16deg),
      transparent 12%, rgba(0, 0, 0, .45) 32%, #000 46%, #000 54%,
      rgba(0, 0, 0, .45) 68%, transparent 88%);
  mask-size: 300% 300%;
  -webkit-mask-size: 300% 300%;
  mask-position: calc(50% - var(--tx, 0) * 46%) calc(50% - var(--ty, 0) * 46%);
  -webkit-mask-position: calc(50% - var(--tx, 0) * 46%) calc(50% - var(--ty, 0) * 46%);
  mask-repeat: no-repeat;
  -webkit-mask-repeat: no-repeat;
}

[data-holo-bg="rainbow"] .holo-bg {
  background-image:
    repeating-linear-gradient(99deg,
      #ff3d7f 0px, #ff9d3d 11px, #ffe94d 22px, #46e08a 33px,
      #3dc8ff 44px, #9b6bff 55px, #ff54cf 66px, #ff3d7f 77px),
    repeating-linear-gradient(99deg,
      rgba(255, 255, 255, .85) 0px, rgba(255, 255, 255, .85) 1.5px,
      rgba(0, 0, 0, .7) 1.5px, rgba(0, 0, 0, .7) 4.5px);
  background-blend-mode: overlay;
  background-size: auto, auto;
  background-position:
    calc(var(--tx, 0) * -150px) calc(var(--ty, 0) * -150px),
    calc(var(--tx, 0) * -84px) calc(var(--ty, 0) * -84px);
  filter: brightness(1.15) contrast(1.35) saturate(1.45);
  mix-blend-mode: overlay;
}

/* Cosmos: cracked-ice flecks catching the light, the classic galaxy holo. */
[data-holo-bg="galaxy"] .holo-bg {
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='c'%3E%3CfeTurbulence type='turbulence' baseFrequency='0.055' numOctaves='3' seed='9' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 -3.2 -3.2 -3.2 0 2.1'/%3E%3C/filter%3E%3Crect width='300' height='300' filter='url(%23c)'/%3E%3C/svg%3E"),
    repeating-linear-gradient(99deg,
      #ff4fa8 0px, #ffc24d 16px, #5ff0b4 32px,
      #4fc4ff 48px, #a86bff 64px, #ff4fa8 80px);
  background-blend-mode: overlay;
  background-size: 115% auto, auto;
  background-position:
    calc(var(--tx, 0) * -60px) calc(var(--ty, 0) * -60px),
    calc(var(--tx, 0) * -140px) calc(var(--ty, 0) * -140px);
  filter: brightness(1.3) contrast(1.75) saturate(1.4);
  mix-blend-mode: overlay;
}

/* Fine sparkle dust suspended in the foil. */
[data-holo-bg="glitter"] .holo-bg {
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.62' numOctaves='2' seed='8' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 5 5 5 0 -3.4'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23g)'/%3E%3C/svg%3E"),
    repeating-linear-gradient(99deg,
      #ff6b9d 0px, #ffd76b 14px, #6bffb0 28px,
      #6bd4ff 42px, #b88bff 56px, #ff6b9d 70px);
  background-blend-mode: overlay;
  background-size: 30% auto, auto;
  background-position:
    calc(var(--tx, 0) * -40px) calc(var(--ty, 0) * -40px),
    calc(var(--tx, 0) * -130px) calc(var(--ty, 0) * -130px);
  filter: brightness(1.25) contrast(1.6) saturate(1.25);
  mix-blend-mode: overlay;
}

/* Brushed metal: tight ribs, little colour. */
[data-holo-bg="linear"] .holo-bg {
  background-image:
    repeating-linear-gradient(99deg,
      #ff8fae 0px, #ffe2a8 18px, #a8ffd4 36px, #a8d8ff 54px, #d0b0ff 72px, #ff8fae 90px),
    repeating-linear-gradient(99deg,
      rgba(255, 255, 255, .9) 0px, rgba(255, 255, 255, .9) 1px,
      rgba(0, 0, 0, .75) 1px, rgba(0, 0, 0, .75) 3px);
  background-blend-mode: overlay;
  background-position:
    calc(var(--tx, 0) * -120px) calc(var(--ty, 0) * -120px),
    calc(var(--tx, 0) * -60px) calc(var(--ty, 0) * -60px);
  filter: brightness(1.15) contrast(1.3) saturate(.9);
  mix-blend-mode: overlay;
}

/* ---------- shared secondary layers ---------- */

/* Glitter grains that only light up near the pointer. */
.holo__sparkle {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='260' height='260'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' seed='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 .34 .34 .34 0 0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='gamma' exponent='4' amplitude='1.5'/%3E%3C/feComponentTransfer%3E%3CfeGaussianBlur stdDeviation='.45'/%3E%3C/filter%3E%3Crect width='260' height='260' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 30% auto;
  background-position: calc(50% + var(--tx, 0) * 5%) calc(50% + var(--ty, 0) * 5%);
  mix-blend-mode: color-dodge;
  filter: brightness(.8);
  opacity: calc(var(--holo, .5) * (.06 + var(--pfc, 0) * .22));
  mask-image: radial-gradient(52% 52% at calc(var(--px, 50) * 1%) calc(var(--py, 50) * 1%),
      #000 0%, rgba(0, 0, 0, .3) 40%, transparent 78%);
  -webkit-mask-image: radial-gradient(52% 52% at calc(var(--px, 50) * 1%) calc(var(--py, 50) * 1%),
      #000 0%, rgba(0, 0, 0, .3) 40%, transparent 78%);
  mask-repeat: no-repeat;
  -webkit-mask-repeat: no-repeat;
}

/* The bright reflection travelling across the surface. */
[data-holo-surface="none"] .holo__band { display: none; }
.holo__band {
  background-image: linear-gradient(
      calc(100deg + var(--tx, 0) * 20deg),
      transparent 28%, rgba(255, 255, 255, .12) 42%,
      rgba(255, 255, 255, .5) 50%, rgba(255, 255, 255, .12) 58%, transparent 72%);
  background-size: 260% 260%;
  background-repeat: no-repeat;
  background-position: calc(50% - var(--tx, 0) * 45%) calc(50% - var(--ty, 0) * 45%);
  mix-blend-mode: screen;
  opacity: calc(var(--holo, .5) * .9);
}

/* Soft specular right under the pointer. */
[data-holo-surface="none"] .holo__glare { display: none; }
.holo__glare {
  background-image: radial-gradient(
      farthest-corner circle at calc(var(--px, 50) * 1%) calc(var(--py, 50) * 1%),
      rgba(255, 255, 255, .5) 6%, rgba(255, 255, 255, .12) 24%, rgba(0, 0, 0, .5) 90%);
  background-repeat: no-repeat;
  mix-blend-mode: overlay;
  opacity: calc(var(--glare, .6) * (.5 + var(--pfc, 0) * .5));
}

.holo--back .holo__foil { opacity: calc(var(--holo, .5) * .38); }
.holo--back .holo__glare { opacity: calc(var(--glare, .6) * .4); }


/* -- discrete effect layers -----------------------------------------------

   A foil wash alone reads as weak. Real premium cards stack separate,
   individually visible effects -- a glittering mirror-ball field behind the
   art, prismatic rays, sharp little sparkles that pop in and out, and a
   flare that sweeps across the surface. Each is its own layer here, in the
   same order those cards use, and each can be switched off in config.js.
   ---------------------------------------------------------------------- */

.fx { position: absolute; inset: 0; pointer-events: none; }
.fx[hidden] { display: none; }

/* Mirror-ball field: sits behind the character, drifts opposite the tilt so
   it reads as depth, and twinkles as the card turns. */
.fx-mirror {
  position: absolute; inset: -14%;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cg fill='%23ffffff'%3E%3Ccircle cx='33.0' cy='138.0' r='1.7' opacity='0.53'/%3E%3Ccircle cx='168.7' cy='197.9' r='1.0' opacity='0.88'/%3E%3Ccircle cx='102.5' cy='101.0' r='0.6' opacity='0.86'/%3E%3Ccircle cx='2.8' cy='186.6' r='1.0' opacity='0.4'/%3E%3Ccircle cx='158.8' cy='46.5' r='0.6' opacity='0.8'/%3E%3Ccircle cx='87.4' cy='199.1' r='1.0' opacity='0.75'/%3E%3Ccircle cx='6.8' cy='65.8' r='1.0' opacity='0.8'/%3E%3Ccircle cx='129.8' cy='187.6' r='0.5' opacity='0.45'/%3E%3Ccircle cx='163.5' cy='25.0' r='0.5' opacity='0.64'/%3E%3Ccircle cx='110.4' cy='68.6' r='1.0' opacity='0.45'/%3E%3Ccircle cx='133.0' cy='94.0' r='0.6' opacity='0.4'/%3E%3Ccircle cx='39.5' cy='134.8' r='1.7' opacity='0.84'/%3E%3Ccircle cx='152.6' cy='116.2' r='1.7' opacity='0.4'/%3E%3Ccircle cx='112.0' cy='111.8' r='1.0' opacity='0.48'/%3E%3Ccircle cx='184.6' cy='177.5' r='1.0' opacity='0.54'/%3E%3Ccircle cx='190.9' cy='100.3' r='0.8' opacity='1.0'/%3E%3Ccircle cx='77.3' cy='5.4' r='0.5' opacity='0.45'/%3E%3Ccircle cx='143.2' cy='196.5' r='0.5' opacity='0.67'/%3E%3Ccircle cx='110.1' cy='149.6' r='0.6' opacity='0.72'/%3E%3Ccircle cx='63.7' cy='196.0' r='0.5' opacity='0.47'/%3E%3Ccircle cx='34.0' cy='69.6' r='0.8' opacity='0.58'/%3E%3Ccircle cx='119.4' cy='61.3' r='0.5' opacity='0.46'/%3E%3Ccircle cx='184.6' cy='34.8' r='1.0' opacity='0.59'/%3E%3Ccircle cx='136.7' cy='135.2' r='1.7' opacity='0.97'/%3E%3Ccircle cx='81.4' cy='197.8' r='1.7' opacity='0.73'/%3E%3Ccircle cx='176.6' cy='98.2' r='1.0' opacity='0.78'/%3E%3Ccircle cx='187.3' cy='49.2' r='1.3' opacity='0.4'/%3E%3Ccircle cx='161.1' cy='154.8' r='1.0' opacity='0.39'/%3E%3Ccircle cx='57.6' cy='170.7' r='1.7' opacity='0.54'/%3E%3Ccircle cx='83.9' cy='34.1' r='0.5' opacity='0.92'/%3E%3Ccircle cx='129.1' cy='29.2' r='0.6' opacity='0.83'/%3E%3Ccircle cx='95.8' cy='50.4' r='1.7' opacity='0.69'/%3E%3Ccircle cx='145.7' cy='5.7' r='0.6' opacity='0.93'/%3E%3Ccircle cx='73.1' cy='30.8' r='0.8' opacity='0.74'/%3E%3Ccircle cx='85.2' cy='116.2' r='1.0' opacity='0.55'/%3E%3Ccircle cx='106.9' cy='55.2' r='1.7' opacity='0.36'/%3E%3Ccircle cx='137.1' cy='190.8' r='0.5' opacity='0.52'/%3E%3Ccircle cx='65.2' cy='50.0' r='1.3' opacity='0.62'/%3E%3Ccircle cx='136.6' cy='150.3' r='0.6' opacity='0.44'/%3E%3Ccircle cx='19.0' cy='18.8' r='0.5' opacity='0.77'/%3E%3Ccircle cx='157.2' cy='14.4' r='0.5' opacity='0.78'/%3E%3Ccircle cx='25.3' cy='107.7' r='0.8' opacity='0.61'/%3E%3Ccircle cx='177.6' cy='124.2' r='0.6' opacity='0.47'/%3E%3Ccircle cx='75.6' cy='142.0' r='1.3' opacity='0.84'/%3E%3Ccircle cx='120.8' cy='101.0' r='1.7' opacity='0.85'/%3E%3Ccircle cx='158.1' cy='1.6' r='1.0' opacity='0.91'/%3E%3Ccircle cx='79.6' cy='113.4' r='1.7' opacity='0.5'/%3E%3Ccircle cx='192.8' cy='121.0' r='1.7' opacity='0.38'/%3E%3Ccircle cx='77.8' cy='61.9' r='0.8' opacity='0.88'/%3E%3Ccircle cx='160.6' cy='98.0' r='1.3' opacity='0.41'/%3E%3Ccircle cx='120.2' cy='101.6' r='1.7' opacity='0.56'/%3E%3Ccircle cx='103.4' cy='58.3' r='1.3' opacity='0.69'/%3E%3Ccircle cx='112.1' cy='12.7' r='0.8' opacity='0.98'/%3E%3Ccircle cx='71.0' cy='63.6' r='1.0' opacity='0.42'/%3E%3Ccircle cx='15.2' cy='14.7' r='1.0' opacity='0.68'/%3E%3Ccircle cx='189.4' cy='136.0' r='1.7' opacity='0.64'/%3E%3Ccircle cx='103.5' cy='77.9' r='1.0' opacity='0.4'/%3E%3Ccircle cx='5.0' cy='132.3' r='0.5' opacity='0.51'/%3E%3Ccircle cx='140.8' cy='163.5' r='1.7' opacity='0.63'/%3E%3Ccircle cx='159.5' cy='79.8' r='0.8' opacity='0.67'/%3E%3Ccircle cx='126.4' cy='192.6' r='0.5' opacity='0.37'/%3E%3Ccircle cx='34.6' cy='74.6' r='1.3' opacity='0.93'/%3E%3Ccircle cx='155.9' cy='125.4' r='1.3' opacity='0.78'/%3E%3Ccircle cx='171.8' cy='139.8' r='1.7' opacity='0.52'/%3E%3Ccircle cx='96.2' cy='99.7' r='0.8' opacity='0.75'/%3E%3Ccircle cx='165.0' cy='192.7' r='0.5' opacity='0.46'/%3E%3Ccircle cx='40.4' cy='175.1' r='1.7' opacity='0.44'/%3E%3Ccircle cx='110.6' cy='15.9' r='0.8' opacity='0.75'/%3E%3Ccircle cx='75.1' cy='148.6' r='0.5' opacity='0.99'/%3E%3Ccircle cx='33.3' cy='86.7' r='1.7' opacity='0.57'/%3E%3Ccircle cx='128.3' cy='136.3' r='0.8' opacity='0.4'/%3E%3Ccircle cx='5.7' cy='102.9' r='0.6' opacity='0.93'/%3E%3Ccircle cx='101.4' cy='47.7' r='1.7' opacity='0.53'/%3E%3Ccircle cx='75.8' cy='188.1' r='1.0' opacity='0.61'/%3E%3Ccircle cx='92.1' cy='133.2' r='1.7' opacity='0.46'/%3E%3Ccircle cx='76.9' cy='54.5' r='0.6' opacity='0.98'/%3E%3Ccircle cx='43.0' cy='70.1' r='1.7' opacity='0.96'/%3E%3Ccircle cx='140.9' cy='3.8' r='1.3' opacity='0.73'/%3E%3Ccircle cx='79.6' cy='88.2' r='1.0' opacity='0.51'/%3E%3Ccircle cx='1.5' cy='108.9' r='0.5' opacity='0.98'/%3E%3Ccircle cx='38.1' cy='74.1' r='0.5' opacity='0.59'/%3E%3Ccircle cx='27.0' cy='158.3' r='1.0' opacity='0.69'/%3E%3Ccircle cx='9.8' cy='37.5' r='1.0' opacity='0.92'/%3E%3Ccircle cx='48.9' cy='115.0' r='1.3' opacity='0.95'/%3E%3Ccircle cx='176.7' cy='3.5' r='1.3' opacity='0.4'/%3E%3Ccircle cx='87.2' cy='166.5' r='1.7' opacity='0.47'/%3E%3Ccircle cx='11.9' cy='163.0' r='1.3' opacity='0.7'/%3E%3Ccircle cx='98.3' cy='135.8' r='1.7' opacity='0.57'/%3E%3Ccircle cx='53.9' cy='70.6' r='0.8' opacity='0.77'/%3E%3Ccircle cx='1.8' cy='161.4' r='1.7' opacity='0.39'/%3E%3Ccircle cx='102.4' cy='135.6' r='0.6' opacity='0.58'/%3E%3Ccircle cx='70.5' cy='32.4' r='1.3' opacity='0.67'/%3E%3Ccircle cx='136.2' cy='130.6' r='0.6' opacity='0.37'/%3E%3Ccircle cx='46.5' cy='71.7' r='0.8' opacity='0.62'/%3E%3Ccircle cx='138.2' cy='145.6' r='1.3' opacity='0.63'/%3E%3Ccircle cx='64.9' cy='43.8' r='1.3' opacity='0.38'/%3E%3Ccircle cx='70.5' cy='106.5' r='1.7' opacity='0.77'/%3E%3Ccircle cx='4.2' cy='73.7' r='1.0' opacity='0.46'/%3E%3Ccircle cx='170.2' cy='161.3' r='0.8' opacity='0.79'/%3E%3Ccircle cx='43.5' cy='155.5' r='1.3' opacity='0.7'/%3E%3Ccircle cx='181.7' cy='194.0' r='1.0' opacity='0.49'/%3E%3Ccircle cx='92.8' cy='139.4' r='0.8' opacity='0.36'/%3E%3Ccircle cx='70.4' cy='122.7' r='1.3' opacity='0.37'/%3E%3Ccircle cx='75.2' cy='149.7' r='0.6' opacity='0.96'/%3E%3Ccircle cx='107.2' cy='176.3' r='0.6' opacity='0.5'/%3E%3Ccircle cx='102.9' cy='57.2' r='1.0' opacity='0.83'/%3E%3Ccircle cx='176.6' cy='72.5' r='0.5' opacity='0.51'/%3E%3Ccircle cx='119.9' cy='70.4' r='1.7' opacity='0.88'/%3E%3Ccircle cx='72.4' cy='26.2' r='0.5' opacity='0.94'/%3E%3Ccircle cx='190.9' cy='151.0' r='1.7' opacity='0.83'/%3E%3Ccircle cx='148.3' cy='42.5' r='1.3' opacity='0.69'/%3E%3Ccircle cx='179.0' cy='102.8' r='0.5' opacity='0.45'/%3E%3Ccircle cx='132.4' cy='122.7' r='1.0' opacity='0.85'/%3E%3Ccircle cx='150.3' cy='130.2' r='0.8' opacity='0.47'/%3E%3Ccircle cx='165.4' cy='44.5' r='1.0' opacity='0.52'/%3E%3Ccircle cx='107.6' cy='91.8' r='0.5' opacity='0.86'/%3E%3Ccircle cx='67.2' cy='88.1' r='0.8' opacity='0.83'/%3E%3Ccircle cx='146.2' cy='198.7' r='1.0' opacity='0.44'/%3E%3Ccircle cx='6.5' cy='155.5' r='1.3' opacity='0.54'/%3E%3Ccircle cx='166.5' cy='91.6' r='1.0' opacity='0.5'/%3E%3Ccircle cx='146.8' cy='162.5' r='1.0' opacity='0.79'/%3E%3Ccircle cx='5.4' cy='183.3' r='0.6' opacity='0.67'/%3E%3Ccircle cx='92.3' cy='77.9' r='1.7' opacity='0.64'/%3E%3Ccircle cx='143.7' cy='14.1' r='0.8' opacity='0.84'/%3E%3Ccircle cx='75.0' cy='50.1' r='1.0' opacity='0.87'/%3E%3Ccircle cx='185.6' cy='39.8' r='0.8' opacity='0.93'/%3E%3Ccircle cx='15.4' cy='61.6' r='1.7' opacity='0.43'/%3E%3Ccircle cx='150.3' cy='187.0' r='0.5' opacity='0.79'/%3E%3Ccircle cx='59.2' cy='43.6' r='0.6' opacity='0.44'/%3E%3Ccircle cx='154.2' cy='99.0' r='0.5' opacity='0.8'/%3E%3Ccircle cx='67.0' cy='129.9' r='0.8' opacity='0.36'/%3E%3Ccircle cx='168.6' cy='56.7' r='0.8' opacity='0.8'/%3E%3Ccircle cx='82.7' cy='24.6' r='1.3' opacity='0.78'/%3E%3Ccircle cx='4.2' cy='144.9' r='1.3' opacity='0.81'/%3E%3Ccircle cx='97.6' cy='107.5' r='1.3' opacity='0.59'/%3E%3Ccircle cx='127.2' cy='127.1' r='0.8' opacity='0.44'/%3E%3Ccircle cx='80.4' cy='88.7' r='1.7' opacity='0.65'/%3E%3Ccircle cx='102.8' cy='44.7' r='0.6' opacity='0.36'/%3E%3Ccircle cx='128.6' cy='91.0' r='0.6' opacity='0.85'/%3E%3Ccircle cx='180.4' cy='149.8' r='0.8' opacity='0.67'/%3E%3Ccircle cx='33.0' cy='159.8' r='0.8' opacity='0.8'/%3E%3Ccircle cx='59.9' cy='192.9' r='1.0' opacity='0.47'/%3E%3Ccircle cx='30.3' cy='124.8' r='0.6' opacity='0.49'/%3E%3Ccircle cx='22.4' cy='106.9' r='0.5' opacity='0.76'/%3E%3Ccircle cx='24.5' cy='24.8' r='1.7' opacity='0.8'/%3E%3Ccircle cx='107.7' cy='17.0' r='0.6' opacity='0.49'/%3E%3Ccircle cx='113.6' cy='48.9' r='1.0' opacity='0.72'/%3E%3Ccircle cx='163.6' cy='104.1' r='1.7' opacity='0.88'/%3E%3Ccircle cx='79.9' cy='191.9' r='1.7' opacity='0.58'/%3E%3Ccircle cx='157.0' cy='6.9' r='1.0' opacity='0.38'/%3E%3Ccircle cx='80.8' cy='161.3' r='1.0' opacity='0.47'/%3E%3Ccircle cx='185.2' cy='16.0' r='0.8' opacity='0.85'/%3E%3Ccircle cx='143.9' cy='106.1' r='0.6' opacity='0.54'/%3E%3Ccircle cx='74.2' cy='98.2' r='0.8' opacity='0.6'/%3E%3Ccircle cx='160.2' cy='10.7' r='0.8' opacity='0.73'/%3E%3Ccircle cx='97.3' cy='164.1' r='0.6' opacity='0.84'/%3E%3Ccircle cx='29.9' cy='61.7' r='0.5' opacity='0.53'/%3E%3Ccircle cx='135.4' cy='181.3' r='0.5' opacity='0.59'/%3E%3Ccircle cx='173.0' cy='85.0' r='1.7' opacity='0.42'/%3E%3Ccircle cx='194.4' cy='43.6' r='0.8' opacity='0.82'/%3E%3Ccircle cx='9.3' cy='125.2' r='1.3' opacity='0.56'/%3E%3Ccircle cx='37.3' cy='182.7' r='1.0' opacity='0.68'/%3E%3Ccircle cx='32.5' cy='43.5' r='0.6' opacity='0.91'/%3E%3Ccircle cx='67.4' cy='133.4' r='0.6' opacity='0.9'/%3E%3Ccircle cx='192.8' cy='49.7' r='0.8' opacity='0.69'/%3E%3Ccircle cx='75.1' cy='56.0' r='1.3' opacity='0.93'/%3E%3Ccircle cx='36.3' cy='73.7' r='0.6' opacity='0.56'/%3E%3Ccircle cx='178.3' cy='169.2' r='0.6' opacity='0.54'/%3E%3Ccircle cx='150.0' cy='139.3' r='1.7' opacity='0.98'/%3E%3Ccircle cx='175.8' cy='49.2' r='0.8' opacity='0.56'/%3E%3Ccircle cx='76.0' cy='195.3' r='0.6' opacity='0.82'/%3E%3Ccircle cx='5.6' cy='115.6' r='0.8' opacity='0.49'/%3E%3Ccircle cx='196.9' cy='153.3' r='0.6' opacity='0.86'/%3E%3Ccircle cx='174.4' cy='178.7' r='1.0' opacity='0.99'/%3E%3Ccircle cx='99.9' cy='140.3' r='1.3' opacity='0.49'/%3E%3Ccircle cx='33.4' cy='180.4' r='1.0' opacity='0.78'/%3E%3Ccircle cx='59.0' cy='25.9' r='1.0' opacity='0.38'/%3E%3Ccircle cx='142.6' cy='150.9' r='0.6' opacity='0.65'/%3E%3Ccircle cx='152.7' cy='9.7' r='1.7' opacity='0.56'/%3E%3Ccircle cx='35.3' cy='116.6' r='1.7' opacity='0.64'/%3E%3Ccircle cx='142.4' cy='82.7' r='1.0' opacity='0.97'/%3E%3Ccircle cx='110.8' cy='55.9' r='0.5' opacity='0.81'/%3E%3Ccircle cx='167.0' cy='195.9' r='0.8' opacity='0.65'/%3E%3Ccircle cx='181.5' cy='176.3' r='0.8' opacity='0.9'/%3E%3Ccircle cx='27.0' cy='69.0' r='1.7' opacity='0.58'/%3E%3Ccircle cx='126.4' cy='163.7' r='0.8' opacity='0.87'/%3E%3Ccircle cx='32.3' cy='193.7' r='0.5' opacity='0.46'/%3E%3Ccircle cx='69.2' cy='42.6' r='0.5' opacity='0.38'/%3E%3Ccircle cx='5.8' cy='65.0' r='1.7' opacity='0.71'/%3E%3Ccircle cx='169.9' cy='169.4' r='1.3' opacity='0.82'/%3E%3Ccircle cx='121.5' cy='39.7' r='0.6' opacity='0.95'/%3E%3Ccircle cx='61.7' cy='50.6' r='0.6' opacity='0.82'/%3E%3Ccircle cx='76.8' cy='159.0' r='0.8' opacity='0.83'/%3E%3Ccircle cx='145.9' cy='48.8' r='0.8' opacity='0.5'/%3E%3Ccircle cx='164.3' cy='154.0' r='0.6' opacity='1.0'/%3E%3Ccircle cx='16.8' cy='192.9' r='1.0' opacity='0.65'/%3E%3Ccircle cx='138.6' cy='156.9' r='0.6' opacity='0.82'/%3E%3Ccircle cx='87.7' cy='10.0' r='1.0' opacity='0.94'/%3E%3Ccircle cx='16.9' cy='142.9' r='1.0' opacity='0.94'/%3E%3Ccircle cx='186.6' cy='163.4' r='0.5' opacity='0.75'/%3E%3Ccircle cx='1.8' cy='153.3' r='0.8' opacity='0.69'/%3E%3Ccircle cx='144.4' cy='0.4' r='0.5' opacity='0.92'/%3E%3Ccircle cx='197.2' cy='191.9' r='0.5' opacity='0.72'/%3E%3Ccircle cx='72.7' cy='121.2' r='1.0' opacity='0.86'/%3E%3Ccircle cx='97.7' cy='53.1' r='1.3' opacity='0.54'/%3E%3Ccircle cx='152.7' cy='45.0' r='0.5' opacity='0.95'/%3E%3Ccircle cx='28.4' cy='183.7' r='1.7' opacity='0.55'/%3E%3Ccircle cx='52.3' cy='70.5' r='1.3' opacity='0.83'/%3E%3Ccircle cx='73.6' cy='102.1' r='0.5' opacity='0.77'/%3E%3Ccircle cx='177.7' cy='92.0' r='1.0' opacity='0.54'/%3E%3Ccircle cx='167.4' cy='131.6' r='2.5' fill='%23d8f0ff' opacity='0.90'/%3E%3Ccircle cx='137.2' cy='63.1' r='2.6' fill='%23d8f0ff' opacity='0.89'/%3E%3Ccircle cx='106.9' cy='150.5' r='2.6' fill='%23d8f0ff' opacity='0.97'/%3E%3Ccircle cx='52.8' cy='134.3' r='3.0' fill='%23d8f0ff' opacity='0.79'/%3E%3Ccircle cx='181.0' cy='18.9' r='2.7' fill='%23d8f0ff' opacity='0.67'/%3E%3Ccircle cx='150.1' cy='84.7' r='2.5' fill='%23d8f0ff' opacity='0.66'/%3E%3Ccircle cx='51.4' cy='173.1' r='2.6' fill='%23d8f0ff' opacity='0.83'/%3E%3Ccircle cx='23.1' cy='58.6' r='3.0' fill='%23d8f0ff' opacity='0.64'/%3E%3Ccircle cx='107.6' cy='139.3' r='2.5' fill='%23d8f0ff' opacity='0.80'/%3E%3Ccircle cx='194.0' cy='156.3' r='2.2' fill='%23d8f0ff' opacity='0.74'/%3E%3Ccircle cx='83.9' cy='136.8' r='2.7' fill='%23d8f0ff' opacity='0.67'/%3E%3Ccircle cx='138.5' cy='86.2' r='2.0' fill='%23d8f0ff' opacity='0.68'/%3E%3Ccircle cx='75.4' cy='39.4' r='2.7' fill='%23d8f0ff' opacity='1.00'/%3E%3Ccircle cx='186.3' cy='125.9' r='2.9' fill='%23d8f0ff' opacity='0.77'/%3E%3Ccircle cx='117.3' cy='178.7' r='2.1' fill='%23d8f0ff' opacity='0.71'/%3E%3Ccircle cx='74.8' cy='68.2' r='2.4' fill='%23d8f0ff' opacity='0.58'/%3E%3Ccircle cx='135.8' cy='191.4' r='2.2' fill='%23d8f0ff' opacity='0.63'/%3E%3Ccircle cx='66.9' cy='159.3' r='2.2' fill='%23d8f0ff' opacity='0.90'/%3E%3Ccircle cx='34.5' cy='119.0' r='2.7' fill='%23d8f0ff' opacity='0.85'/%3E%3Ccircle cx='16.9' cy='191.3' r='2.8' fill='%23d8f0ff' opacity='0.77'/%3E%3Ccircle cx='171.9' cy='120.2' r='2.2' fill='%23d8f0ff' opacity='0.73'/%3E%3Ccircle cx='164.2' cy='92.7' r='2.0' fill='%23d8f0ff' opacity='0.62'/%3E%3Ccircle cx='37.2' cy='117.2' r='2.6' fill='%23d8f0ff' opacity='0.75'/%3E%3Ccircle cx='80.8' cy='192.6' r='2.3' fill='%23d8f0ff' opacity='0.85'/%3E%3Ccircle cx='40.9' cy='102.8' r='2.2' fill='%23d8f0ff' opacity='0.60'/%3E%3Ccircle cx='67.3' cy='23.0' r='2.4' fill='%23d8f0ff' opacity='0.84'/%3E%3C/g%3E%3C/svg%3E");
  background-size: 30% auto;
  background-position: calc(50% - var(--tx, 0) * 9%) calc(50% - var(--ty, 0) * 9%);
  mix-blend-mode: screen;
  opacity: calc(var(--fx-mirror, 1) * (.34 + var(--pfc, 0) * .5));
  filter: brightness(1.35) contrast(1.3);
}
.fx-mirror::after {
  content: '';
  position: absolute; inset: 0;
  background-image: inherit;
  background-size: 47% auto;
  background-position: calc(50% + var(--tx, 0) * 5%) calc(50% + var(--ty, 0) * 5%);
  opacity: .5;
}

/* Prism: rainbow rays fanning from the middle, turning with the card. */
.fx-prism {
  position: absolute; inset: -30%;
  background-image: repeating-conic-gradient(
      from calc(var(--tx, 0) * 26deg) at 50% 52%,
      transparent 0deg 5deg,
      rgba(255, 120, 190, .55) 6deg 7.4deg,
      transparent 8.4deg 13deg,
      rgba(120, 210, 255, .5) 14deg 15.4deg,
      transparent 16.4deg 21deg,
      rgba(180, 255, 190, .42) 22deg 23.2deg,
      transparent 24.2deg 30deg);
  mix-blend-mode: screen;
  opacity: calc(var(--fx-prism, 1) * (.14 + var(--pfc, 0) * .4));
  mask-image: radial-gradient(circle at 50% 52%, #000 4%, rgba(0, 0, 0, .55) 30%, transparent 62%);
  -webkit-mask-image: radial-gradient(circle at 50% 52%, #000 4%, rgba(0, 0, 0, .55) 30%, transparent 62%);
}

/* Puyo-kira: sharp four-point sparkles that pop in and out over the card. */
.fx-sparks {
  position: absolute; inset: 0;
  transform: translate3d(calc(var(--tx, 0) * 9px), calc(var(--ty, 0) * 9px), 0);
}
.spark {
  position: absolute;
  width: var(--s, 22px); aspect-ratio: 1;
  margin: calc(var(--s, 22px) / -2);
  background: radial-gradient(circle,
      #fff 0%, #fff 20%, rgba(206, 240, 255, .95) 42%,
      rgba(255, 176, 240, .7) 66%, transparent 100%);
  clip-path: polygon(50% 0%, 56% 44%, 100% 50%, 56% 56%,
                     50% 100%, 44% 56%, 0% 50%, 44% 44%);
  opacity: 0;
  mix-blend-mode: screen;
  filter: drop-shadow(0 0 5px rgba(190, 230, 255, .9));
  animation: twinkle var(--dur, 3.4s) ease-in-out var(--delay, 0s) infinite;
}
@keyframes twinkle {
  0%, 68%, 100% { opacity: 0; transform: scale(.1) rotate(0deg); }
  12%           { opacity: 1; transform: scale(1) rotate(22deg); }
  30%           { opacity: .85; transform: scale(.78) rotate(38deg); }
  48%           { opacity: 0; transform: scale(.2) rotate(56deg); }
}

/* Trail-kira: a bright flare that sweeps the surface, trailing light. */
.fx-trail { position: absolute; inset: 0; overflow: hidden; }
.fx-trail i {
  position: absolute;
  left: -14%; top: 72%;
  width: 30%; aspect-ratio: 1;
  background: radial-gradient(circle,
      rgba(255, 255, 255, .95) 0%, rgba(255, 255, 255, .45) 12%,
      rgba(175, 220, 255, .22) 32%, transparent 64%);
  mix-blend-mode: screen;
  opacity: 0;
  animation: sweepFlare var(--trail-dur, 7.5s) ease-in-out infinite;
}
.fx-trail i::before,
.fx-trail i::after {           /* the crossed star spikes */
  content: '';
  position: absolute; left: 50%; top: 50%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .95), transparent);
  transform: translate(-50%, -50%);
}
.fx-trail i::before { width: 230%; height: 2px; }
.fx-trail i::after  { width: 2px; height: 150%;
  background: linear-gradient(180deg, transparent, rgba(255, 255, 255, .9), transparent); }

@keyframes sweepFlare {
  0%, 6%   { opacity: 0; transform: translate(0, 0) scale(.35); }
  16%      { opacity: 1; }
  55%      { opacity: 1; transform: translate(250%, -195%) scale(1.1); }
  82%, 100%{ opacity: 0; transform: translate(400%, -310%) scale(.4); }
}

@media (prefers-reduced-motion: reduce) {
  .spark, .fx-trail i { animation: none; }
  .spark { opacity: .55; transform: scale(.8); }
}

/* -- card stock -----------------------------------------------------------

   The single biggest thing that makes this read as a printed object rather
   than a screen: a fine paper tooth over the whole face, and a crisp cut
   edge catching the light along the top while the bottom falls into shadow.
   ---------------------------------------------------------------------- */

.stock {
  position: absolute; inset: 0;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23g)'/%3E%3C/svg%3E");
  background-size: 120px 120px;
  mix-blend-mode: overlay;
  opacity: calc(var(--stock, 1) * .17);
}

.face::after {                 /* the cut edge of the card itself */
  content: '';
  position: absolute; inset: 0;
  border-radius: inherit;
  pointer-events: none;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, calc(var(--stock, 1) * .3)),
    inset 1px 0 0 rgba(255, 255, 255, calc(var(--stock, 1) * .1)),
    inset -1px 0 0 rgba(0, 0, 0, calc(var(--stock, 1) * .3)),
    inset 0 -1px 0 rgba(0, 0, 0, calc(var(--stock, 1) * .45));
}

/* -- name plate over the artwork -- */

.nameplate {
  position: absolute;
  left: 0; right: 0;
  top: var(--name-top, 79%);
  text-align: center;
  padding: 0 14%;
  pointer-events: none;
  text-shadow: 0 2px 14px rgba(0, 0, 0, .85), 0 0 34px rgba(0, 0, 0, .6);
}
.nameplate[hidden] { display: none; }
.nameplate__name {
  margin: 0;
  font-family: var(--display); font-weight: 600;
  font-size: clamp(13px, calc(var(--card-w) * .062), 27px);
  letter-spacing: .04em;
  background: linear-gradient(180deg, #fff8e2, var(--gold-soft) 58%, #b98a1f);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.nameplate__sub {
  margin: 5px 0 0;
  font-size: clamp(7px, calc(var(--card-w) * .027), 12px);
  letter-spacing: .3em; text-transform: uppercase;
  color: rgba(255, 246, 223, .74);
}

/* -- invitation on the back -- */

.invitation {
  position: absolute;
  inset: 12% 11%;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: calc(var(--card-h) * .022);
  text-align: center;
  pointer-events: none;
}
.invitation[hidden] { display: none; }

.inv__eyebrow {
  margin: 0;
  font-size: clamp(7px, calc(var(--card-w) * .027), 12px);
  letter-spacing: .34em; text-transform: uppercase;
  color: var(--gold-soft);
}
.inv__title {
  margin: 0;
  font-family: var(--display); font-weight: 700;
  font-size: clamp(19px, calc(var(--card-w) * .097), 42px);
  line-height: 1.1;
  background: linear-gradient(180deg, #fffaf0, #f0cd72 62%, #c08e15);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  text-shadow: 0 0 40px rgba(240, 205, 114, .22);
}
.inv__rule {
  width: 52%; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(240, 205, 114, .8), transparent);
}
.inv__message {
  margin: 0;
  font-size: clamp(8.5px, calc(var(--card-w) * .0335), 14px);
  line-height: 1.62; font-weight: 300;
  color: rgba(239, 233, 255, .9);
}
.inv__details {
  display: grid;
  gap: calc(var(--card-h) * .022);
  width: 100%;
}
.inv__row {
  display: grid;
  gap: 3px;
}
.inv__label {
  font-size: clamp(6.5px, calc(var(--card-w) * .0235), 10px);
  letter-spacing: .28em; text-transform: uppercase;
  color: rgba(240, 205, 114, .72);
}
.inv__value {
  font-size: clamp(8.5px, calc(var(--card-w) * .0335), 14px);
  font-weight: 500;
  color: #fff;
}
.inv__footer {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(8px, calc(var(--card-w) * .031), 13px);
  letter-spacing: .1em;
  color: rgba(255, 246, 223, .82);
}

/* -- reveal flight: the card coming out of the torn pack -- */

.card-scene.is-revealing .card { animation: cardEmerge 1.45s cubic-bezier(.18, .78, .26, 1) both; }
@keyframes cardEmerge {
  0%   { opacity: 0; transform: translate3d(0, 18%, -420px) rotateZ(-18deg) rotateX(34deg) scale(.34); }
  30%  { opacity: 1; }
  58%  { transform: translate3d(0, -6%, 90px) rotateZ(6deg) rotateX(-9deg) scale(1.12); }
  78%  { transform: translate3d(0, 1%, 0) rotateZ(-2deg) scale(.985); }
  100% { opacity: 1; transform: none; }
}


/* ----------------------------------------------------------------- flash -- */

.flash {
  position: fixed; inset: 0;
  z-index: 50; pointer-events: none;
  background: radial-gradient(circle at 50% 46%, #fff 0%, rgba(255, 236, 200, .9) 26%, rgba(255, 190, 240, .35) 52%, transparent 72%);
  opacity: 0;
}
.flash.is-firing { animation: flashOut .78s ease-out forwards; }
@keyframes flashOut {
  0%   { opacity: 0; }
  9%   { opacity: 1; }
  100% { opacity: 0; }
}

/* ------------------------------------------------------------ responsive -- */

@media (max-height: 660px) {
  :root { --card-h: min(64vh, 520px, calc(84vw / var(--card-aspect))); }
  .gate__mark { margin-bottom: 22px; }
  .gate__title { margin-bottom: 32px; }
  .gate__form { gap: 24px; }
}

@media (max-width: 430px) {
  .screen { gap: 16px; }
  .btn { padding: 15px 24px; font-size: 12px; }
  .hint { font-size: 10.5px; letter-spacing: .18em; }
}

@media (hover: none) {
  .pack { cursor: default; }
}

@media (prefers-reduced-motion: reduce) {
  .orb, .pack__gloss, .hint { animation: none !important; }
  .card-scene.is-revealing .card { animation-duration: .5s; }
  .card__inner { transition-duration: .45s; }
}
