/* =============================================================================
   card-reveal.css - Face-down cards, CSS flip and rarity effects.

   Reference: `.docs/steps/4.md` point 3.
     - the flip itself is now a keyframe animation (`card-flip`): a half turn that overshoots
       before it settles, with a slight zoom on the way. It runs whatever the animation mode
       (`css/animations/epic.css` only adds decoration on top for "epic"), so the card always answers
       the tap the same way;
     - rarities 1 and 2: plain rendering, light inner reflection, a glint when revealed;
     - rarity 3 (super rare): the lightest foil (the fine diagonal weave of
       `css/components/card-shine.css`) over the same inner reflection and glint;
     - rarity 4 (legendary): animated glow (`--glow-rarity-4`), the light foil and a halo ring on
       reveal;
     - rarity 5 (mythic): stronger animated glow (`--glow-rarity-5`), the full foil and the same
       halo, held longer. The halo fades out and leaves nothing behind;
     - the two glows and the halo are the only rarity effects left here: the foil itself is its own
       component, `css/components/card-shine.css`, applied by `CardComponent` (`applyShine`) as a
       window laid over the artwork (shapes, light and the sweeping line, each moving back and forth,
       clipped to the illustration so the frame of the card keeps no gloss);
     - full art printings drift a hair, like a lenticular print.
   Every color comes from `css/themes.css`, so the three themes stay readable.

   Watch out: `transform` is reserved for the flip (read by `backface-visibility`), so anything
   that moves a card on hover uses the independent `translate` / `scale` properties. They compose
   with the transform instead of replacing it - a plain `transform` there would cancel the half
   turn and show the front face again.
   ============================================================================= */

.card-reveal {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
  margin-top: var(--space-4);
  perspective: 1200px;
}

@media (min-width: 768px) {
  .card-reveal {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

/* --- Summary thumbnails ------------------------------------------------------
   The summary reuses the card markup inside a button. The inner card must not capture
   clicks (the wrapper button opens the modal) and keeps its flip state as a thumbnail. */

.card-reveal--summary {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

@media (min-width: 768px) {
  .card-reveal--summary {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

.card-reveal__card {
  position: relative;
  /* The ratio of the assets themselves (`css/base.css`, `--card-ratio`): a card box matching its
     artwork exactly is what lets the foil window of `css/components/card-shine.css` land on the
     picture instead of on letterbox bands. */
  aspect-ratio: var(--card-ratio);
  padding: 0;
  border: 0;
  background-color: transparent;
  cursor: pointer;
  touch-action: manipulation;
  transform-style: preserve-3d;
  transition: transform var(--duration-base) var(--easing-standard),
    translate var(--duration-fast) var(--easing-standard),
    scale var(--duration-fast) var(--easing-standard);
  /* Step 7 point 4: targeted promotion. A card is the only element of the grid whose animation
     runs on every interaction, so only it asks for a compositor layer (never the whole grid). */
  will-change: transform;
}

/* The card lifts a little under the finger: it tells a clickable card from a decorative one
   without a single line of JavaScript. */
.card-reveal__card:not(:disabled):hover {
  translate: 0 -4px;
}

.card-reveal__card:not(:disabled):active {
  scale: 0.97;
}

/* The flip: the rotation keeps the `transform` property, the animation only fills it in with
   a cinematic curve. `both` holds the last keyframe, so the card stays at 180deg once the
   animation is over (and the plain `transform` below is what a reduced-motion player sees). */
.card-reveal__card.is-flipped {
  transform: rotateY(180deg);
  animation: card-flip var(--anim-flip-ms, 220ms) var(--easing-standard) both;
}

@keyframes card-flip {
  0% {
    transform: rotateY(0deg) scale(1);
  }
  55% {
    transform: rotateY(146deg) scale(1.1);
  }
  78% {
    transform: rotateY(196deg) scale(1.03);
  }
  100% {
    transform: rotateY(180deg) scale(1);
  }
}

.card-reveal__card:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
  border-radius: var(--radius-md);
}

.card-reveal__face {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface);
  box-shadow: var(--shadow-sm);
  backface-visibility: hidden;
}

/* The back shows the shared illustration (`assets/img/card_back.png`, see `CardComponent`).
   It is a fixed image like the card itself, so `cover` fills the frame without cropping.
   The themed surface colour stays as a fallback if the file cannot be loaded. */
.card-reveal__face--back {
  background-color: var(--color-surface-alt);
}

.card-reveal__back-image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.card-reveal__face--front {
  transform: rotateY(180deg);
  background-color: var(--color-surface-alt);
}

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

.card-reveal__fallback-name {
  position: absolute;
  inset: auto var(--space-2) var(--space-2) var(--space-2);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  background-color: var(--overlay);
  color: var(--color-text);
  font-size: var(--font-size-xs);
  text-align: center;
}

/* "NEW": a corner ribbon in the top right of the card, flush with the frame and on the artwork
   itself. It is deliberately small - the card is the thing being looked at, the badge only has to
   be caught in passing - and it keeps no margin, so the same rule works on the full-size card of
   the reveal and on the thumbnails of the summary. The face clips it (`overflow: hidden`), so the
   ribbon follows the rounded corner of the card instead of poking out of it. */
.card-reveal__badge {
  position: absolute;
  top: 0;
  right: 0;
  z-index: 2;
  padding: 1px 0.3rem 2px 0.35rem;
  border-radius: 0 0 0 var(--radius-sm);
  background-color: var(--color-accent);
  color: var(--color-accent-contrast);
  font-size: 0.625rem;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: 0.04em;
}

/* --- Rarity rendering ---------------------------------------------------- */

/* Rarities 1 to 3: plain printing with a light inner reflection. */
.card-reveal__card--r1 .card-reveal__face--front,
.card-reveal__card--r2 .card-reveal__face--front,
.card-reveal__card--r3 .card-reveal__face--front {
  box-shadow: inset 0 0 18px var(--overlay);
}

/* Rarity 4: animated glow (box-shadow only: a `filter` on the faces would flatten the 3D
   stacking context and break `backface-visibility`, hiding the card once flipped). */
.card-reveal__card--r4 .card-reveal__face--front {
  box-shadow: var(--glow-rarity-4), 0 0 6px var(--overlay);
  animation: card-glow-soft 2.4s ease-in-out infinite alternate;
}

/* Rarity 5: stronger glow and the same foil reflection as the legendary, only harder. */
.card-reveal__card--r5 .card-reveal__face--front {
  box-shadow: var(--glow-rarity-5), 0 0 8px var(--overlay);
  animation: card-glow-strong 2s ease-in-out infinite alternate;
}

/* A mythic breathes: the artwork drifts a hair while the reflection crosses over it. */
.card-reveal__card--r5 .card-reveal__face--front .card-reveal__image {
  animation: card-holo 5.2s ease-in-out infinite alternate;
}

/* The halo: a ring of light that leaves the card the moment it is revealed. Rarities 4 and 5
   only - a common card does not deserve fireworks. */
.card-reveal__card--r4.is-flipped::after,
.card-reveal__card--r5.is-flipped::after {
  content: '';
  position: absolute;
  inset: -8%;
  z-index: 1;
  border-radius: var(--radius-md);
  background-image: radial-gradient(circle at 50% 50%, var(--color-accent) 8%, transparent 68%);
  /* Invisible at rest. The keyframes already fade the ring back to `opacity: 0`, but with no
     fill mode the element falls back to its own styles once the animation ends: without this the
     blue disc would come back, frozen, and stay on the card. */
  opacity: 0;
  animation: card-halo 900ms var(--easing-standard) 140ms;
  pointer-events: none;
}

.card-reveal__card--r5.is-flipped::after {
  animation-duration: 1300ms;
}

@keyframes card-halo {
  0% {
    opacity: 0;
    scale: 0.7;
  }
  35% {
    opacity: 0.75;
  }
  100% {
    opacity: 0;
    scale: 1.25;
  }
}

/* A discreet glint on every other card: the reveal is always an event, never a plain swap. */
.card-reveal__card--r1.is-flipped .card-reveal__face--front,
.card-reveal__card--r2.is-flipped .card-reveal__face--front,
.card-reveal__card--r3.is-flipped .card-reveal__face--front {
  animation: card-glint 620ms var(--easing-standard);
}

@keyframes card-glint {
  0% {
    box-shadow: inset 0 0 18px var(--overlay), 0 0 0 var(--overlay);
  }
  40% {
    box-shadow: inset 0 0 18px var(--overlay), 0 0 18px var(--overlay);
  }
  100% {
    box-shadow: inset 0 0 18px var(--overlay), 0 0 0 var(--overlay);
  }
}

@keyframes card-glow-soft {
  from {
    box-shadow: var(--glow-rarity-4), 0 0 6px var(--overlay);
  }
  to {
    box-shadow: var(--glow-rarity-4), 0 0 26px var(--overlay);
  }
}

@keyframes card-glow-strong {
  from {
    box-shadow: var(--glow-rarity-5), 0 0 8px var(--overlay);
  }
  to {
    box-shadow: var(--glow-rarity-5), 0 0 32px var(--overlay);
  }
}

/* Full art: the artwork drifts a hair, like a lenticular print. */
.card-reveal__card--fullart .card-reveal__face--front .card-reveal__image {
  animation: card-float 7s ease-in-out infinite alternate;
}

@keyframes card-holo {
  from {
    scale: 1;
  }
  to {
    scale: 1.025;
  }
}

@keyframes card-float {
  from {
    translate: 0 -0.6%;
    scale: 1.01;
  }
  to {
    translate: 0 0.6%;
    scale: 1.03;
  }
}

/* The revealed card pops slightly, drawing the eye to the latest flip (outline, not filter:
   the filter would flatten the 3D stacking context, see above).

   The Mine Pick stage is EXCLUDED (`:not(.minepick__card)`): its cards are flipped to shuffle the
   pack, not to reveal it, and the state that matters there is the ring of `css/views/minepick.css`
   - the rarity colour first, then green for the card the player keeps. Without the exclusion this
   rule (same specificity, and card-reveal.css is loaded after minepick.css) painted every flipped
   legendary and mythic blue and hid the green of the kept card. The `:not()` also raises the
   specificity, so the exclusion is not a cascade accident. */
.card-reveal__card.is-flipped.card-reveal__card--r4:not(.minepick__card),
.card-reveal__card.is-flipped.card-reveal__card--r5:not(.minepick__card) {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
  border-radius: var(--radius-md);
}

@media (prefers-reduced-motion: reduce) {
  /* Everything that moves: the flip, the halo, the glint, the continuous glows of the high
     rarities (they pulsed before this block existed - a pulsing border is motion too), the
     drift of the artwork. */
  .card-reveal__card.is-flipped,
  .card-reveal__card--r4.is-flipped::after,
  .card-reveal__card--r5.is-flipped::after,
  .card-reveal__card.is-flipped .card-reveal__face--front,
  .card-reveal__card--r4 .card-reveal__face--front,
  .card-reveal__card--r5 .card-reveal__face--front,
  .card-reveal__card--r5 .card-reveal__face--front .card-reveal__image,
  .card-reveal__card--fullart .card-reveal__face--front .card-reveal__image {
    animation: none;
  }

  .card-reveal__card:not(:disabled):hover {
    translate: none;
  }
}
