:root {
  --card-tilt-max: 10;
  --card-tilt-perspective: 600px;
  --card-tilt-scale: 1;
  --card-tilt-glare-intensity: 0.9;
  --card-tilt-glare-hue: 270;
}

.card {
  --card-base-transform: scale(1);
  --card-hover-transform: scale(1);
  --card-tilt-x: 0.5;
  --card-tilt-y: 0.5;
  --card-tilt-rotate-x: 0deg;
  --card-tilt-rotate-y: 0deg;
  --card-tilt-opacity: 0;
  /* Keep one function list in every state so pointer rotation composes with
     each surface's hover/fan transform without a discrete transform swap. */
  transform:
    perspective(var(--card-tilt-perspective))
    rotateX(var(--card-tilt-rotate-x))
    rotateY(var(--card-tilt-rotate-y))
    scale(var(--card-tilt-scale))
    var(--card-hover-transform)
    var(--card-base-transform);
  transform-style: flat;
  will-change: auto;
}

.card.card-tilt-active {
  transform-style: preserve-3d;
  will-change: transform, box-shadow, opacity;
}

/* THE RESIDUAL FIREFOX TEXT JITTER. With the ancestor filters gone (the big
   half of "title and mana costs ... jittering"), Gecko still re-rasterises
   glyphs each tilt frame and snaps them to whole device pixels. Giving the
   text nodes their own composited layers lets them ride the 3D transform as
   textures between rasterisations, and geometricPrecision positions glyphs
   by geometry instead of the hinting grid. Scoped to the actively tilting
   card, so resting text keeps its ordinary pixel-hinted sharpness; no
   `transform` is declared here — .card-cost owns its centring translate. */
.card.card-tilt-active .card-name,
.card.card-tilt-active .card-cost,
.card.card-tilt-active .card-desc {
  will-change: transform;
  text-rendering: geometricPrecision;
}

.card-glare {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  z-index: 2;
  background-image: radial-gradient(farthest-corner circle at calc(var(--card-tilt-x) * 100%) calc(var(--card-tilt-y) * 100%),
      lch(95% 2.7 var(--card-tilt-glare-hue) / calc(var(--card-tilt-glare-intensity) * 0.66)) 8%,
      lch(88% 5.5 var(--card-tilt-glare-hue) / calc(var(--card-tilt-glare-intensity) * 0.5)) 28%,
      lch(5% 3.5 var(--card-tilt-glare-hue) / calc(var(--card-tilt-glare-intensity) * 0.25)) 90%);
  mix-blend-mode: overlay;
  opacity: var(--card-tilt-opacity);
  transition: opacity 0.2s ease;
}

@media (prefers-reduced-motion: reduce) {
  .card {
    --card-tilt-rotate-x: 0deg;
    --card-tilt-rotate-y: 0deg;
    --card-tilt-opacity: 0;
  }
}
