/* ============================================
   ANIMATIONS (SCROLL-SYNCED)
   JS directly sets opacity/transform per frame.
   These classes define initial/fallback state only.
   ============================================ */
.reveal {
  opacity: 0;
}

#hero .reveal {
  opacity: 0;
}



/* ============================================
   KEYFRAME ANIMATIONS
   ============================================ */
@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateX(-50%) translateY(16px);
  }

  to {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
  }
}

@keyframes scrollPulse {

  0%,
  100% {
    opacity: 0.3;
  }

  50% {
    opacity: 1;
  }
}

@keyframes arrowPulse {

  0%,
  100% {
    opacity: 0.3;
  }

  50% {
    opacity: 0.8;
    color: var(--accent);
  }
}

@keyframes pulse {

  0%,
  100% {
    opacity: 0.4;
    box-shadow: 0 0 0 0 rgba(100, 255, 218, 0.3);
  }

  50% {
    opacity: 1;
    box-shadow: 0 0 0 6px rgba(100, 255, 218, 0);
  }
}

/* Animated gradient shimmer on hero keywords */
.text-shimmer {
  background: linear-gradient(120deg,
      var(--text-primary) 0%,
      var(--accent) 25%,
      var(--accent-hover) 50%,
      var(--accent) 75%,
      var(--text-primary) 100%);
  background-size: 250% 100%;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  animation: shimmerSlide 6s ease-in-out infinite;
}

@keyframes shimmerSlide {

  0%,
  100% {
    background-position: 100% 50%;
  }

  50% {
    background-position: 0% 50%;
  }
}

@keyframes cursorFadeIn {
  to {
    opacity: 1;
  }
}