/* ============================================================================
   OpenPok :: 3D Pack Opening & Animation Engine
   ============================================================================ */

.pack-opening-overlay {
  position: fixed;
  inset: 0;
  z-index: 2000;
  background: radial-gradient(circle at 50% 20%, #1c1c33 0%, #05050a 75%);
  display: flex;
  flex-direction: column;
  align-items: center;
  /* `safe center` centers when content fits but falls back to start-alignment
     when it doesn't — without it, a tall spread (10 cards + Continue button on
     a short/landscape phone) overflows the top of a centered flex container
     and becomes unreachable even with scrolling. Pair with overflow-y:auto. */
  justify-content: safe center;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  padding: 24px;
}

.pack-opening-close {
  position: absolute;
  top: 20px;
  right: 24px;
  background: rgba(255, 255, 255, 0.08);
  border: none;
  color: var(--text-primary);
  width: 38px;
  height: 38px;
  border-radius: 50%;
  font-size: 1.2rem;
  z-index: 10;
}

/* ---------------------------------------------------------------------------
   Stage 1: sealed wrapper + tear interaction
   --------------------------------------------------------------------------- */

.pack-stage {
  perspective: 1400px;
  width: 260px;
  height: 360px;
  position: relative;
}

.pack-wrapper {
  width: 100%;
  height: 100%;
  border-radius: 16px;
  background: linear-gradient(150deg, #3a2a70, #7c5cff 45%, #ff5cad 100%);
  box-shadow: 0 20px 60px rgba(124, 92, 255, 0.4), inset 0 0 0 1px rgba(255, 255, 255, 0.15);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transform-style: preserve-3d;
  transition: box-shadow 0.4s ease, filter 0.4s ease;
  animation: pack-idle-float 3.2s ease-in-out infinite;
  overflow: hidden;
  position: relative;
  will-change: transform;
}

.pack-wrapper img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* (1a) Hover shake/bounce. This MUST be an animation, not a static transform:
   the base rule already runs pack-idle-float on `transform`, and a running
   animation wins over a plain `:hover { transform }` on every frame — so a
   static hover transform would silently never appear. Swapping the animation
   on hover hands transform control cleanly to the bounce keyframes. */
.pack-wrapper:hover {
  animation: pack-hover-bounce 0.7s ease-in-out infinite;
  box-shadow: 0 26px 70px rgba(124, 92, 255, 0.6), inset 0 0 0 1px rgba(255, 255, 255, 0.25);
  filter: brightness(1.08);
}

@keyframes pack-hover-bounce {
  0%, 100% { transform: translateY(0) rotateZ(0deg) scale(1.04); }
  20% { transform: translateY(-7px) rotateZ(-2.2deg) scale(1.06); }
  60% { transform: translateY(-3px) rotateZ(2.2deg) scale(1.05); }
}

.pack-wrapper .tear-hint {
  position: absolute;
  bottom: 14px;
  left: 0;
  right: 0;
  text-align: center;
  color: rgba(255, 255, 255, 0.85);
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  text-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);
}

@keyframes pack-idle-float {
  0%, 100% { transform: translateY(0) rotateZ(0deg); }
  50% { transform: translateY(-8px) rotateZ(-1deg); }
}

.pack-wrapper.is-tearing {
  animation: pack-tear-shake 0.4s ease;
}

@keyframes pack-tear-shake {
  0% { transform: translateX(0); }
  20% { transform: translateX(-6px) rotateZ(-2deg); }
  40% { transform: translateX(6px) rotateZ(2deg); }
  60% { transform: translateX(-4px) rotateZ(-1deg); }
  80% { transform: translateX(4px) rotateZ(1deg); }
  100% { transform: translateX(0); }
}

.pack-wrapper.torn .pack-top,
.pack-wrapper.torn .pack-bottom {
  transition: transform 0.6s cubic-bezier(0.36, 0, 0.66, -0.56), opacity 0.6s ease 0.2s;
}

.pack-top,
.pack-bottom {
  position: absolute;
  left: 0;
  right: 0;
  height: 50%;
  background: inherit;
}

.pack-top { top: 0; border-radius: 16px 16px 0 0; }
.pack-bottom { bottom: 0; border-radius: 0 0 16px 16px; }

.pack-wrapper.torn .pack-top {
  transform: translateY(-140%) rotateX(60deg);
  opacity: 0;
}

.pack-wrapper.torn .pack-bottom {
  transform: translateY(140%) rotateX(-60deg);
  opacity: 0;
}

/* (1b) Glowing explosion burst injected by js/pack-opening.js at the instant
   the pack tears open. Absolutely centered on the .pack-stage. */
.pack-burst {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 40px;
  height: 40px;
  margin: -20px 0 0 -20px;
  border-radius: 50%;
  background: radial-gradient(circle, #ffffff 0%, #ffd76a 28%, rgba(124, 92, 255, 0.7) 55%, rgba(255, 92, 173, 0) 76%);
  pointer-events: none;
  z-index: 5;
  transform: scale(0.2);
  opacity: 0.95;
  animation: pack-burst-blast 0.7s cubic-bezier(0.16, 1, 0.3, 1) forwards;
  will-change: transform, opacity;
}

@keyframes pack-burst-blast {
  0% { transform: scale(0.2); opacity: 0.95; }
  60% { opacity: 0.85; }
  100% { transform: scale(14); opacity: 0; }
}

/* ---------------------------------------------------------------------------
   Stage 2: card spread + 3D flip reveal
   --------------------------------------------------------------------------- */

.card-spread {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 18px;
  max-width: 1100px;
  margin-top: 32px;
}

.tcg-card {
  width: 140px;
  height: 196px;
  perspective: 1000px;
  opacity: 0;
  transform: translateY(48px) rotateZ(-6deg) scale(0.82);
  animation: card-slide-in 0.55s cubic-bezier(0.22, 1, 0.36, 1) forwards;
  cursor: pointer;
  position: relative;
  will-change: transform, opacity;
}

/* (1c) Fan-out slide-in: cards ease up, straighten from a slight fan tilt, and
   settle. Staggered per-card via inline animation-delay set in JS. */
@keyframes card-slide-in {
  60% { opacity: 1; }
  to {
    opacity: 1;
    transform: translateY(0) rotateZ(0deg) scale(1);
  }
}

.tcg-card__inner {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transition: transform 0.7s cubic-bezier(0.34, 1.56, 0.64, 1);
  will-change: transform;
}

.tcg-card.is-flipped .tcg-card__inner {
  transform: rotateY(180deg);
}

/* Invite the click: face-down cards lift slightly on hover... */
.tcg-card:not(.is-flipped):hover .tcg-card__inner {
  transform: translateY(-6px) scale(1.04);
}

/* ...and a revealed card gets a subtle 3D tilt on hover (keeps it flipped). */
.tcg-card.is-flipped:hover .tcg-card__inner {
  transform: rotateY(180deg) rotateX(5deg) scale(1.05);
}

.tcg-card__face {
  position: absolute;
  inset: 0;
  border-radius: 12px;
  backface-visibility: hidden;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.5);
}

.tcg-card__face--back {
  background: linear-gradient(160deg, #262646 0%, #14141f 100%);
  border: 2px solid rgba(124, 92, 255, 0.4);
  animation: card-back-glow 2.4s ease-in-out infinite;
}

/* Gentle breathing ring on face-down cards to signal they're clickable. */
@keyframes card-back-glow {
  0%, 100% { box-shadow: 0 10px 24px rgba(0, 0, 0, 0.5), inset 0 0 0 2px rgba(124, 92, 255, 0.2); }
  50% { box-shadow: 0 10px 30px rgba(124, 92, 255, 0.45), inset 0 0 0 2px rgba(124, 92, 255, 0.6); }
}

.tcg-card__face--back::after {
  content: "?";
  font-size: 2.4rem;
  color: rgba(255, 255, 255, 0.25);
  font-weight: 800;
}

.tcg-card__face--front {
  transform: rotateY(180deg);
  background: linear-gradient(160deg, #2a2a4e 0%, #14141f 100%);
  border: 2px solid var(--border-subtle);
  flex-direction: column;
}

/* Placeholder card-back — ALWAYS rendered as the base layer behind the
   artwork. The image covers it when it loads; if the image is missing or
   fails (onerror removes it), this shows through, so a card is never a blank
   black frame. */
.tcg-card__placeholder {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 14px;
  text-align: center;
  background: linear-gradient(160deg, #2a2a4e 0%, #14141f 100%);
  color: rgba(255, 255, 255, 0.72);
}

.tcg-card__placeholder-icon {
  font-size: 2.4rem;
  opacity: 0.55;
}

.tcg-card__placeholder-name {
  font-size: 0.78rem;
  font-weight: 700;
  line-height: 1.25;
}

.tcg-card__face--front img,
.tcg-card__img {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Card-back tone while the image decodes — never a black flash. */
  background: linear-gradient(160deg, #2a2a4e 0%, #14141f 100%);
}

.tcg-card__meta {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 5; /* always above the holo shimmer so the details stay readable */
  padding: 6px 8px;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.9), transparent);
  font-size: 0.68rem;
  text-align: left;
}

.tcg-card__meta .name {
  font-weight: 700;
  display: block;
}

.tcg-card__meta .price {
  display: inline-block;
  margin-top: 4px;
  padding: 2px 10px;
  font-size: 20px;
  font-weight: 800;
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.12);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border: 1px solid rgba(255, 255, 255, 0.15);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
  color: #4ade80;
}

.tcg-card__meta .price[data-price-tier="blue"] {
  color: #60a5fa;
}

.tcg-card__meta .price[data-price-tier="gold"] {
  color: #fbbf24;
}

.tcg-card__meta .price[data-price-tier="legendary"] {
  color: #fb923c;
}

/* Holographic mouse-tracking shimmer, applied to ultra/secret rarity fronts.
   --mx / --my are set via JS on mousemove (0-100, percentage across card). */
.tcg-card.is-holo .tcg-card__face--front {
  --mx: 50;
  --my: 50;
}

.tcg-card.is-holo .tcg-card__face--front::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: radial-gradient(
    circle at calc(var(--mx) * 1%) calc(var(--my) * 1%),
    rgba(255, 255, 255, 0.55),
    rgba(255, 92, 173, 0.35) 25%,
    rgba(124, 92, 255, 0.35) 50%,
    transparent 70%
  );
  mix-blend-mode: color-dodge;
  opacity: 0.85;
}

.tcg-card.is-holo .tcg-card__face--front::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  background: repeating-linear-gradient(
    calc(var(--mx) * 0.6deg),
    rgba(255, 255, 255, 0.12) 0px,
    transparent 2px,
    transparent 6px
  );
  mix-blend-mode: overlay;
}

/* ---------------------------------------------------------------------------
   (1d) Rarity aura — a glowing halo behind the card, revealed only AFTER the
   flip (`.is-flipped`) so a face-down card never leaks its rarity. Rendered on
   a ::before layer sized larger than the card so the glow spills past the
   edges; pulse is animated via `opacity` (compositor-only) rather than
   box-shadow so it stays 60fps on mobile. Aura class is added per-card in JS.
   --------------------------------------------------------------------------- */

.tcg-card::before {
  content: "";
  position: absolute;
  inset: -8px;
  border-radius: 18px;
  z-index: -1;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.45s ease;
}

.tcg-card.is-flipped.aura-rare::before {
  opacity: 1;
  box-shadow: 0 0 26px 4px rgba(37, 99, 235, 0.55);
}

.tcg-card.is-flipped.aura-ultra::before {
  box-shadow: 0 0 40px 8px rgba(147, 51, 234, 0.7);
  animation: aura-pulse 1.8s ease-in-out infinite;
}

.tcg-card.is-flipped.aura-secret::before {
  /* Gold foil aura for the top-tier chase cards (Secret / Hyper Rare). */
  box-shadow: 0 0 44px 10px rgba(255, 199, 74, 0.8);
  animation: aura-pulse 1.6s ease-in-out infinite;
}

.tcg-card.is-flipped.aura-illustration::before {
  box-shadow: 0 0 42px 9px rgba(219, 39, 119, 0.75);
  animation: aura-pulse 1.6s ease-in-out infinite;
}

@keyframes aura-pulse {
  0%, 100% { opacity: 0.72; }
  50% { opacity: 1; }
}

/* Gold border sheen on the revealed front of the very top rarities. */
.tcg-card.is-flipped.aura-secret .tcg-card__face--front {
  border-color: rgba(255, 199, 74, 0.9);
}

/* ---------------------------------------------------------------------------
   Rare pull celebration (confetti)
   --------------------------------------------------------------------------- */

.confetti-layer {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 3000;
  overflow: hidden;
}

.confetti-piece {
  position: absolute;
  top: -20px;
  width: 9px;
  height: 14px;
  opacity: 0.9;
  animation-name: confetti-fall;
  animation-timing-function: linear;
  animation-fill-mode: forwards;
  will-change: transform, opacity;
}

@keyframes confetti-fall {
  0% {
    transform: translateY(0) rotate(0deg);
    opacity: 1;
  }
  100% {
    transform: translateY(110vh) rotate(720deg);
    opacity: 0.2;
  }
}

.rare-pull-banner {
  position: fixed;
  top: 18%;
  left: 50%;
  transform: translate(-50%, -20px);
  z-index: 3001;
  background: var(--accent-gradient);
  padding: 14px 28px;
  border-radius: 999px;
  font-weight: 800;
  letter-spacing: 0.02em;
  box-shadow: 0 12px 40px rgba(255, 92, 173, 0.4);
  opacity: 0;
  animation: rare-banner-in 0.5s ease forwards, rare-banner-out 0.5s ease 2.6s forwards;
}

@keyframes rare-banner-in {
  to { opacity: 1; transform: translate(-50%, 0); }
}

@keyframes rare-banner-out {
  to { opacity: 0; transform: translate(-50%, -20px); }
}

/* ---------------------------------------------------------------------------
   Continue button shown once all cards are revealed
   --------------------------------------------------------------------------- */

.pack-opening-continue {
  margin-top: 36px;
  opacity: 0;
  animation: fade-in 0.4s ease forwards;
}

@keyframes fade-in {
  to { opacity: 1; }
}

@media (max-width: 640px) {
  .tcg-card { width: 108px; height: 151px; }
  .pack-stage { width: 200px; height: 280px; }
  .card-spread { gap: 12px; margin-top: 20px; }
  .pack-opening-continue { margin-top: 24px; }
}

/* ---------------------------------------------------------------------------
   Accessibility / low-end performance: honor the OS "reduce motion" setting.
   Keeps the reveal fully usable (cards end visible & flippable) but strips the
   infinite float/pulse/shimmer loops and long transitions that cause motion
   discomfort and drain battery on weak GPUs.
   --------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .pack-wrapper,
  .pack-wrapper:hover,
  .pack-burst,
  .tcg-card,
  .tcg-card__inner,
  .tcg-card__face--back,
  .tcg-card.is-flipped.aura-ultra::before,
  .tcg-card.is-flipped.aura-secret::before,
  .tcg-card.is-flipped.aura-illustration::before,
  .confetti-piece,
  .rare-pull-banner,
  .pack-opening-continue,
  .collection-card,
  .collection-card__art::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }

  /* Guarantee cards land in their visible, upright resting state. */
  .tcg-card { opacity: 1 !important; transform: none !important; }
}
