@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

@keyframes modalIn {
  from { opacity: 0; transform: translateY(12px) scale(0.98); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes toastIn {
  from { opacity: 0; transform: translateX(30px); }
  to { opacity: 1; transform: translateX(0); }
}

@keyframes shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

@keyframes spin { to { transform: rotate(360deg); } }

.spinner {
  width: 18px; height: 18px;
  border: 2.5px solid rgba(255,255,255,0.35);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
  display: inline-block;
}
.spinner.dark { border-color: var(--border-strong); border-top-color: var(--accent-text); }

.fade-up {
  animation: fadeUp var(--dur-slow) var(--ease-out) forwards;
  opacity: 0;
}
@keyframes fadeUp {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

.stagger > * { opacity: 0; animation: fadeUp var(--dur-slow) var(--ease-out) forwards; }
.stagger > *:nth-child(1) { animation-delay: 0.02s; }
.stagger > *:nth-child(2) { animation-delay: 0.06s; }
.stagger > *:nth-child(3) { animation-delay: 0.10s; }
.stagger > *:nth-child(4) { animation-delay: 0.14s; }
.stagger > *:nth-child(5) { animation-delay: 0.18s; }
.stagger > *:nth-child(6) { animation-delay: 0.22s; }
.stagger > *:nth-child(7) { animation-delay: 0.26s; }
.stagger > *:nth-child(8) { animation-delay: 0.30s; }

/* ---- Scroll-in reveal gates ----
   Elements marked [data-reveal] (or containers marked
   [data-reveal-stagger]) stay hidden until js/utils/reveal.js
   swaps the attribute for the existing .fade-up / .stagger class
   above, when the element scrolls into view. No new animations —
   just a trigger for the ones already defined here. */
[data-reveal],
[data-reveal-stagger] > * { opacity: 0; }

/* ---- Public-site additions ---- */
@keyframes floatSlow {
  0%, 100% { transform: translateY(0) rotate(var(--tilt, 0deg)); }
  50% { transform: translateY(-10px) rotate(var(--tilt, 0deg)); }
}
.float-card { animation: floatSlow 6s ease-in-out infinite; }

@keyframes marquee {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

/* ---- Premium pass additions ---- */
@keyframes meshDrift {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50% { transform: translate(-3%, 2%) scale(1.05); }
}

@keyframes glowPulse {
  0%, 100% { opacity: 0.55; }
  50% { opacity: 1; }
}

@keyframes scaleIn {
  from { opacity: 0; transform: scale(0.94); }
  to { opacity: 1; transform: scale(1); }
}

@keyframes gridDrift {
  from { background-position: 0 0; }
  to { background-position: 48px 48px; }
}

.hover-lift {
  transition: transform var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out);
}
.hover-lift:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
}
