/* ============================================================
   Animations — vanilla ports of reactbits.dev effects
   ============================================================ */

/* ---- Respect reduced-motion ---- */
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1 !important; translate: none !important; scale: none !important; }
  * { animation-duration: 0.001ms !important; }
}

/* ---- ScrollReveal / AnimatedContent ----
   Uses the independent `translate` property (not `transform`) so it
   composes with `.tilt` and card hover transforms instead of overriding them. */
.reveal {
  opacity: 0;
  translate: 0 28px;
  transition: opacity 0.7s cubic-bezier(0.22, 1, 0.36, 1),
              translate 0.7s cubic-bezier(0.22, 1, 0.36, 1),
              scale 0.7s cubic-bezier(0.22, 1, 0.36, 1);
  transition-delay: var(--reveal-delay, 0s);
  will-change: opacity, translate;
}
.reveal.in { opacity: 1; translate: 0 0; }

/* ---- SpotlightCard ---- */
/* A cursor-following radial glow. Driven by --mx / --my (px) set in JS. */
.spotlight { position: relative; }
.spotlight::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(
    220px circle at var(--mx, 50%) var(--my, 50%),
    rgba(120, 160, 255, 0.18),
    transparent 60%
  );
  opacity: 0;
  transition: opacity 0.3s;
  pointer-events: none;
  z-index: 1;
}
.spotlight:hover::before { opacity: 1; }
/* keep card text above the glow */
.spotlight > * { position: relative; z-index: 2; }

/* ---- TiltedCard ---- */
.tilt {
  transform: perspective(800px) rotateX(var(--ry, 0deg)) rotateY(var(--rx, 0deg));
  transition: transform 0.18s ease;
  transform-style: preserve-3d;
}

/* ---- StarBorder (animated traveling gradient border) ---- */
/* A rotating conic-gradient pseudo-element (transform animation = GPU-cheap,
   instead of repainting a conic-gradient angle every frame). */
.star-border {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  border: none !important;
  background: var(--accent);
}
.star-border::before {
  content: "";
  position: absolute;
  top: 50%; left: 50%;
  width: 250%; aspect-ratio: 1;
  margin: -125% 0 0 -125%;
  z-index: -2;
  background: conic-gradient(
    from 0deg,
    transparent 0% 35%,
    #8847ff 45%,
    #5b8cff 52%,
    #e4ae39 60%,
    transparent 70% 100%
  );
  animation: spin-border 5s linear infinite;
}
.star-border::after {
  content: "";
  position: absolute;
  inset: 2px;
  border-radius: inherit;
  background: var(--accent);
  z-index: -1;
}
@keyframes spin-border {
  to { transform: rotate(1turn); }
}

/* ---- ShinyText ---- */
.shiny {
  background: linear-gradient(
    110deg,
    currentColor 40%,
    #ffffff 50%,
    currentColor 60%
  );
  background-size: 220% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: shine 3.5s linear infinite;
}
@keyframes shine {
  0% { background-position: 220% 0; }
  100% { background-position: -120% 0; }
}

/* ---- ClickSpark ---- */
.spark {
  position: fixed;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #6f9bff;
  pointer-events: none;
  z-index: 9999;
  transform: translate(-50%, -50%);
  animation: spark-fly 0.5s ease-out forwards;
}
@keyframes spark-fly {
  to { transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(0.2); opacity: 0; }
}

/* ---- Catalog card entrance (stagger handled in JS via --reveal-delay) ---- */
.card.reveal { translate: 0 18px; scale: 0.98; }
.card.reveal.in { translate: 0 0; scale: 1; }

/* ---- Pause looping animations when the tab is hidden (set by animations.js) ---- */
html.anim-paused .blob,
html.anim-paused .orb,
html.anim-paused .star-border::before,
html.anim-paused .shiny,
html.anim-paused .eyebrow .pulse {
  animation-play-state: paused !important;
}
