/* === Scroll-triggered fade (fallback without GSAP) === */
.reveal {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}

.reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* Когда GSAP активен — не прячем через CSS (иначе риск «залипшей» прозрачности) */
.has-gsap .reveal {
  opacity: 1;
  transform: none;
  transition: none;
}

/* === Button glow pulse === */
@keyframes btnGlow {
  0%, 100% { box-shadow: 0 8px 20px rgba(37, 99, 235, 0.22); }
  50% { box-shadow: 0 10px 26px rgba(14, 165, 183, 0.28); }
}

.btn-primary:hover {
  animation: btnGlow 2s ease-in-out infinite;
}

/* === Card hover lift === */
.service-card,
.case-card {
  will-change: transform;
}

/* === Ripple (used by JS) === */
.ripple {
  position: absolute;
  width: 20px;
  height: 20px;
  margin-left: -10px;
  margin-top: -10px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.3);
  transform: translate(-50%, -50%) scale(0);
  animation: rippleExpand 0.5s ease-out;
  pointer-events: none;
}

@keyframes rippleExpand {
  to {
    transform: translate(-50%, -50%) scale(4);
    opacity: 0;
  }
}

/*
 * Hero: блик по иллюстрации.
 * Длительность анимации = период между повторами (например 10s).
 * Движение только в хвосте цикла: здесь 60%–100% = 40% периода на проход
 * → при 10s периоде проход за 4s (скорость как у animation: … 4s linear).
 */
@keyframes heroGlowSweep {
  0%,
  60% {
    transform: translateX(-100%);
  }
  100% {
    transform: translateX(100%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero-visual::after {
    animation: none;
    opacity: 0;
  }

}
