/* public/css/card3d.css — give every card real depth: a pointer-tracked tilt, a
   specular sheen that follows the cursor, and a lift with a shadow that agrees with it.
 *
 * HOW THIS AVOIDS FIGHTING THE REVEAL
 * ---------------------------------------------------------------------------
 * /css/anim.css animates entrances with `transform: translateY(20px)` on .reveal and
 * `transform: none` on .reveal.in. A tilt written to `transform` would stomp on that and
 * cards would arrive already settled, or not arrive at all.
 *
 * So every 3D rule here is scoped to `.in` — the class anim.js adds at the END of the
 * entrance. Before it lands, .reveal owns the transform and the card flies up as it
 * always did; after it lands, .reveal.in wants `transform:none` and these rules (equal
 * specificity, later stylesheet) take over. The two never apply at once.
 *
 * The tilt itself is driven by four custom properties set from /js/card3d.js:
 *   --rx / --ry  the rotation in degrees, from the pointer's position over the card
 *   --mx / --my  the pointer position as a percentage, for the sheen
 * A custom property costs nothing to animate through and, crucially, does not
 * invalidate layout — only the compositor's transform is touched, so this stays at
 * 60fps with thirty cards on screen.
 */

.card, .cx-card, .tier, .tcard, .feature-card, .suite-card, .ind-card, .aw-panel{
  transform-style:preserve-3d;
}

/* The settled state. `translateZ(0)` is not cargo cult here: it promotes the card to its
   own compositor layer so the tilt never triggers a repaint of the text inside it. */
.card.in, .cx-card.in, .tier.in, .tcard.in, .feature-card.in, .suite-card.in, .ind-card.in{
  transform:
    perspective(1000px)
    rotateX(var(--rx,0deg))
    rotateY(var(--ry,0deg))
    translateY(var(--lift,0px))
    scale(var(--pop,1))
    translateZ(0);
  transition:transform .34s cubic-bezier(.2,.7,.2,1), box-shadow .34s cubic-bezier(.2,.7,.2,1);
}

/* While the pointer is actually over a card the tilt must track it immediately —
   a third of a second of easing on every mousemove reads as lag, not smoothness. */
.card.in.is-tilting, .cx-card.in.is-tilting, .tier.in.is-tilting,
.tcard.in.is-tilting, .feature-card.in.is-tilting,
.suite-card.in.is-tilting, .ind-card.in.is-tilting{
  transition:box-shadow .34s cubic-bezier(.2,.7,.2,1);
}

/* Lift and shadow. The shadow is offset AGAINST the tilt so the card looks like it is
   leaning over a surface rather than having a shadow painted on its back. */
.card.in:hover, .cx-card.in:hover, .tier.in:hover,
.tcard.in:hover, .feature-card.in:hover,
.suite-card.in:hover, .ind-card.in:hover{
  --lift:-6px; --pop:1.012;
  box-shadow:
    0 2px 6px rgba(8,12,24,.06),
    0 18px 40px -12px rgba(8,12,24,.22),
    0 34px 70px -30px rgba(62,130,240,.28);
}
.dark .card.in:hover, .dark .tcard.in:hover, .suite-card.in:hover, .ind-card.in:hover{
  box-shadow:
    0 2px 6px rgba(0,0,0,.35),
    0 20px 46px -14px rgba(0,0,0,.55),
    0 36px 80px -34px rgba(154,72,198,.42);
}

/* A press should feel like the card takes the weight. */
.card.in:active, .cx-card.in:active, .tier.in:active,
.suite-card.in:active, .ind-card.in:active{ --lift:-2px; --pop:.997; }

/* --- the specular sheen ---------------------------------------------------
   One extra layer per card, painted only while the pointer is on it. It is a
   pseudo-element rather than a real node so no markup anywhere has to change, and
   `mix-blend-mode` lets one rule read correctly on both the light and dark sections. */
.card.in::after, .cx-card.in::after, .tier.in::after,
.tcard.in::after, .suite-card.in::after, .ind-card.in::after{
  content:'';position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  opacity:0;transition:opacity .3s ease;
  background:radial-gradient(420px circle at var(--mx,50%) var(--my,50%),
             rgba(255,255,255,.16), rgba(255,255,255,.05) 38%, transparent 62%);
  mix-blend-mode:soft-light;z-index:3;
}
.card.in:hover::after, .cx-card.in:hover::after, .tier.in:hover::after,
.tcard.in:hover::after, .suite-card.in:hover::after, .ind-card.in:hover::after{opacity:1}

/* ::after is only positionable if the card is a containing block. Most already are;
   these two are asserted because their own rules do not say so. */
.cx-card, .tcard, .tier{position:relative}

/* Content sits above the sheen and slightly proud of the card face, which is what
   actually sells the depth — a flat card that merely rotates reads as a photograph of
   a card. Only the leading elements are lifted; lifting everything costs layers for no
   visible gain. */
.card.in > h3, .card.in > .ic, .suite-card.in > .suite-head,
.ind-card.in .ind-badge, .tier.in > .name, .tier.in > .price{
  transform:translateZ(26px);
}
.cx-card.in > .cx-ico{transform:translateZ(18px)}

/* --- entrance ------------------------------------------------------------
   A card that merely fades up is flat. Starting it rotated back a few degrees and
   letting it come square gives the arrival the same depth as the hover, so the two
   read as one material. Runs once; --entry is cleared by the animation ending. */
@keyframes card3dIn{
  from{opacity:0;transform:perspective(1000px) rotateX(7deg) translateY(22px) scale(.985)}
  to  {opacity:1;transform:perspective(1000px) rotateX(0)    translateY(0)    scale(1)}
}
.c3d-entry.in{animation:card3dIn .62s cubic-bezier(.2,.7,.2,1) both;animation-delay:calc(var(--d,0) * 70ms)}

/* --- nobody who asked for stillness gets any of this ---------------------- */
@media (prefers-reduced-motion: reduce){
  .card.in, .cx-card.in, .tier.in, .tcard.in, .feature-card.in, .suite-card.in, .ind-card.in,
  .card.in:hover, .cx-card.in:hover, .tier.in:hover, .tcard.in:hover,
  .feature-card.in:hover, .suite-card.in:hover, .ind-card.in:hover{
    transform:none!important;transition:none!important;
  }
  .card.in > h3, .card.in > .ic, .suite-card.in > .suite-head, .ind-card.in .ind-badge,
  .tier.in > .name, .tier.in > .price, .cx-card.in > .cx-ico{transform:none!important}
  .card.in::after, .cx-card.in::after, .tier.in::after,
  .tcard.in::after, .suite-card.in::after, .ind-card.in::after{display:none!important}
  .c3d-entry.in{animation:none!important;opacity:1!important}
}

/* A coarse pointer cannot hover, so the tilt is meaningless and the sheen would stick
   wherever the last tap was. The JS never binds on touch; this makes the CSS agree. */
@media (hover:none),(pointer:coarse){
  .card.in::after, .cx-card.in::after, .tier.in::after,
  .tcard.in::after, .suite-card.in::after, .ind-card.in::after{display:none}
}
