/* ==========================================================================
   ZTE SECURITY - Animations Stylesheet  |  css/animations.css
   All keyframe animations, transition classes, and hero stagger timing.
   ========================================================================== */

/* ==========================================================================
   01. HERO ENTRY ANIMATION SEQUENCE
   Failure-safe CSS-only staggered entry. Elements visible by default.
   ========================================================================== */

/* Elements are fully visible and in normal position by default. */
.hero-eyebrow,
.hero-title,
.hero-desc,
.hero-actions,
.hero-floating-cards {
  opacity: 1;
  transform: none;
}

/* Animations applied immediately on load using 'both' fill-mode to prevent FOUC 
   while ensuring they remain visible if CSS animations fail. Added 0.2s delay for loader. */
.hero-eyebrow {
  animation: fadeSlideUp 0.55s cubic-bezier(0.22, 1, 0.36, 1) 0.30s both;
}

.hero-title {
  animation: fadeSlideUp 0.65s cubic-bezier(0.22, 1, 0.36, 1) 0.42s both;
}

.hero-desc {
  animation: fadeSlideUp 0.60s cubic-bezier(0.22, 1, 0.36, 1) 0.58s both;
}

.hero-actions {
  animation: fadeSlideUp 0.60s cubic-bezier(0.22, 1, 0.36, 1) 0.72s both;
}

.hero-floating-cards {
  animation: fadeSlideScale 0.80s cubic-bezier(0.22, 1, 0.36, 1) 0.40s both;
}

/* ==========================================================================
   02. KEYFRAME DEFINITIONS
   ========================================================================== */

/* Slide up + fade in */
@keyframes fadeSlideUp {
  from {
    opacity: 0;
    transform: translateY(20px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Slide from left + fade in */
@keyframes fadeSlideLeft {
  from {
    opacity: 0;
    transform: translateX(-20px);
  }

  to {
    opacity: 1;
    transform: translateX(0);
  }
}

/* Slide from right + fade in */
@keyframes fadeSlideRight {
  from {
    opacity: 0;
    transform: translateX(20px);
  }

  to {
    opacity: 1;
    transform: translateX(0);
  }
}

/* Scale up + fade in (for visual panels) */
@keyframes fadeSlideScale {
  from {
    opacity: 0;
    transform: translateY(16px) scale(0.97);
  }

  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

/* Fade in only */
@keyframes fadeIn {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

/* Gentle float for decorative elements */
@keyframes float {

  0%,
  100% {
    transform: translateY(0px);
  }

  50% {
    transform: translateY(-8px);
  }
}

/* Reusable Corporate Floating Animations */
@keyframes floatSlow {

  0%,
  100% {
    transform: translateY(0px);
  }

  50% {
    transform: translateY(-8px);
  }
}

@keyframes floatMedium {

  0%,
  100% {
    transform: translateY(0px);
  }

  50% {
    transform: translateY(-6px);
  }
}

@keyframes floatFast {

  0%,
  100% {
    transform: translateY(0px);
  }

  50% {
    transform: translateY(-4px);
  }
}

.float-slow {
  animation: floatSlow 6s ease-in-out infinite;
  will-change: transform;
}

.float-medium {
  animation: floatMedium 4.8s ease-in-out infinite;
  animation-delay: 0.8s;
  will-change: transform;
}

.float-fast {
  animation: floatFast 3.6s ease-in-out infinite;
  animation-delay: 1.4s;
  will-change: transform;
}

.float-delayed {
  animation: floatSlow 6.5s ease-in-out infinite;
  animation-delay: 2s;
  will-change: transform;
}

/* Shimmer loading skeleton */
@keyframes shimmer {
  0% {
    background-position: -400px 0;
  }

  100% {
    background-position: 400px 0;
  }
}

/* Spin for loaders */
@keyframes spin {
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(360deg);
  }
}

/* Branded ZTE Security Loader Animations */
@keyframes brandOrbitSpin {
  0% {
    transform: rotate(0deg);
  }

  100% {
    transform: rotate(360deg);
  }
}

@keyframes networkDotPulse {

  0%,
  100% {
    transform: scale(1);
    opacity: 0.8;
  }

  50% {
    transform: scale(1.35);
    opacity: 1;
  }
}

@keyframes brandBreathing {

  0%,
  100% {
    transform: scale(1);
    filter: drop-shadow(0 0 4px rgba(71, 132, 249, 0.3));
  }

  50% {
    transform: scale(1.04);
    filter: drop-shadow(0 0 10px rgba(71, 132, 249, 0.6));
  }
}

/* Pulsing ring (for accent dots) */
@keyframes pulseRing {
  0% {
    box-shadow: 0 0 0 0 rgba(71, 132, 249, 0.4);
  }

  70% {
    box-shadow: 0 0 0 12px rgba(71, 132, 249, 0);
  }

  100% {
    box-shadow: 0 0 0 0 rgba(71, 132, 249, 0);
  }
}

/* ==========================================================================
   03. SCROLL REVEAL SYSTEM
   Applied by IntersectionObserver in animations.js (animates only once).
   ========================================================================== */
.js-animations-ready .reveal {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.55s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.55s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}

.js-animations-ready .reveal-left {
  opacity: 0;
  transform: translateX(-24px);
  transition: opacity 0.55s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.55s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}

.js-animations-ready .reveal-right {
  opacity: 0;
  transform: translateX(24px);
  transition: opacity 0.55s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.55s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}

.js-animations-ready .reveal-scale {
  opacity: 0;
  transform: translateY(16px) scale(0.96);
  transition: opacity 0.55s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.55s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}

.js-animations-ready .reveal-down {
  opacity: 0;
  transform: translateY(-20px);
  transition: opacity 0.55s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.55s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}

/* Active revealed state — set once by observer */
.js-animations-ready .reveal.is-revealed,
.js-animations-ready .reveal-left.is-revealed,
.js-animations-ready .reveal-right.is-revealed,
.js-animations-ready .reveal-scale.is-revealed,
.js-animations-ready .reveal-down.is-revealed {
  opacity: 1;
  transform: translate(0, 0) scale(1);
}

/* Stagger groups — children reveal with delay */
.stagger-group .reveal:nth-child(1) {
  transition-delay: 0ms;
}

.stagger-group .reveal:nth-child(2) {
  transition-delay: 80ms;
}

.stagger-group .reveal:nth-child(3) {
  transition-delay: 160ms;
}

.stagger-group .reveal:nth-child(4) {
  transition-delay: 240ms;
}

.stagger-group .reveal:nth-child(5) {
  transition-delay: 320ms;
}

.stagger-group .reveal:nth-child(6) {
  transition-delay: 400ms;
}

.stagger-group .reveal:nth-child(7) {
  transition-delay: 480ms;
}

.stagger-group .reveal:nth-child(8) {
  transition-delay: 560ms;
}

.stagger-group .reveal:nth-child(9) {
  transition-delay: 640ms;
}

.stagger-group .reveal:nth-child(10) {
  transition-delay: 720ms;
}

/* ==========================================================================
   04. CARD HOVER MICRO-ANIMATIONS
   ========================================================================== */

/* Service card: icon lifts slightly on hover */
.service-card:hover .service-card-icon {
  animation: cardIconPop 0.25s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

@keyframes cardIconPop {
  0% {
    transform: scale(1);
  }

  50% {
    transform: scale(1.15);
  }

  100% {
    transform: scale(1.05);
  }
}

/* Solution card: header gradient shift */
.solution-card-header {
  background-size: 200% 200%;
  background-position: 0% 0%;
  transition: background-position 0.5s ease;
}

.solution-card:hover .solution-card-header {
  background-position: 100% 100%;
}

/* ==========================================================================
   05. NAVBAR SCROLL EFFECT
   .is-scrolled class added by navbar.js â€” shadow already in style.css.
   Additional backdrop blur ramp on scroll.
   ========================================================================== */
.site-header {
  transition:
    box-shadow 250ms cubic-bezier(0.22, 1, 0.36, 1),
    border-color 250ms cubic-bezier(0.22, 1, 0.36, 1),
    background-color 250ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* ==========================================================================
   06. DROPDOWN SMOOTH ENTRY
   ========================================================================== */
.dropdown {
  transform-origin: top center;
}

.dropdown--wide {
  transform-origin: top left;
}

/* ==========================================================================
   07. BUTTON RIPPLE EFFECT
   Add .btn-ripple class to enable.
   The ripple span is injected by JS when clicked.
   ========================================================================== */
.btn-ripple {
  position: relative;
  overflow: hidden;
}

.btn-ripple .ripple {
  position: absolute;
  border-radius: 50%;
  background-color: rgba(255, 255, 255, 0.35);
  transform: scale(0);
  animation: rippleEffect 0.55s linear;
  pointer-events: none;
}

@keyframes rippleEffect {
  to {
    transform: scale(4);
    opacity: 0;
  }
}

/* ==========================================================================
   08. FLOATING HERO BADGE
   The badge on the hero visual gently floats.
   ========================================================================== */
.hero-badge {
  animation: float 4s ease-in-out infinite;
  animation-delay: 1s;
}

/* ==========================================================================
   Storytelling & Telemetry Micro-Animations
   ========================================================================== */

/* Telemetry radar ripple */
@keyframes radar-ripple {
  0% {
    transform: scale(0.85);
    opacity: 1;
  }

  100% {
    transform: scale(2.6);
    opacity: 0;
  }
}

/* Panel Active Glowing Accent Animation */
.video-story-panel {
  position: relative;
  transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1),
    box-shadow 0.35s cubic-bezier(0.16, 1, 0.3, 1),
    border-color 0.35s ease,
    background 0.35s ease;
}

.video-story-panel::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: 4px;
  background: linear-gradient(180deg, #2F6FE6, #1E4FB8);
  border-radius: 4px 0 0 4px;
  opacity: 0;
  transform: scaleY(0.4);
  transition: all 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.video-story-panel.is-active::before {
  opacity: 1;
  transform: scaleY(1);
}

.video-story-panel:hover {
  transform: translateY(-4px) scale(1.012);
  border-color: rgba(47, 111, 230, 0.45);
  box-shadow: 0 14px 28px -6px rgba(30, 79, 184, 0.12);
}

.video-story-panel.is-active {
  transform: scale(1.02);
  box-shadow: 0 16px 36px -6px rgba(30, 79, 184, 0.18);
}

/* Video Frame Hover Depth & HUD Corner Expansion */
.story-video-display {
  transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1),
    box-shadow 0.4s cubic-bezier(0.16, 1, 0.3, 1),
    border-color 0.4s ease;
}

.story-video-display:hover {
  transform: translateY(-4px) scale(1.01);
  box-shadow: 0 24px 50px -10px rgba(47, 111, 230, 0.25), 0 0 20px rgba(47, 111, 230, 0.2);
  border-color: rgba(47, 111, 230, 0.6);
}

.story-video-display:hover .hud-bracket--tl {
  top: 6px;
  left: 6px;
}

.story-video-display:hover .hud-bracket--br {
  bottom: 6px;
  right: 6px;
}

/* ==========================================================================
   Responsive Mobile & Tablet Adjustments (Single Column Layout)
   ========================================================================== */

@media (max-width: 992px) {

  /* Flatten parent grid layout */
  .video-story-inner {
    grid-template-columns: 1fr;
    min-height: unset;
    gap: 1.5rem;
  }

  /* Reset sticky positioning for mobile flow */
  .video-story-sticky {
    position: static;
    height: auto;
    padding: 0;
    top: auto;
  }

  /* Constrain video display height for smaller screens */
  .story-video-display {
    max-height: 320px;
    width: 100%;
    aspect-ratio: 16 / 9;
  }

  /* Mobile panels wrapper padding */
  .video-story-panels {
    padding: 0;
    gap: 1rem;
  }

  /* Keep all panels fully visible and interactive on touch devices */
  .video-story-panel {
    opacity: 1;
    transform: none;
    min-height: auto;
  }

  .video-story-panel:hover {
    transform: none;
  }
}

/* ==========================================================================
   10. SCROLL PROGRESS BAR ANIMATION
   Width is updated via JS â€” the transition is defined in style.css.
   ========================================================================== */

/* ==========================================================================
   11. LOADING SKELETON (for lazy-loaded content placeholder)
   ========================================================================== */
.skeleton {
  background: linear-gradient(90deg,
      var(--clr-surface) 0%,
      var(--clr-surface-2) 50%,
      var(--clr-surface) 100%);
  background-size: 800px 100%;
  animation: shimmer 1.5s infinite linear;
  border-radius: var(--radius-md);
}

/* ==========================================================================
   12. REDUCED MOTION â€” Override everything
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {

  /* Disable all animations and transitions for accessibility */
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  /* Hero: show immediately without animation */
  .hero-eyebrow,
  .hero-title,
  .hero-desc,
  .hero-actions,
  .hero-floating-cards {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
  }

  /* Reveal elements: show without animation */
  .reveal,
  .reveal-left,
  .reveal-right,
  .reveal-scale,
  .reveal-down {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  /* Floating elements and badge: no floating */
  .hero-badge,
  .float-slow,
  .float-medium,
  .float-fast,
  .float-delayed {
    animation: none !important;
    transform: none !important;
  }

  /* Loader animations: static */
  .loader-ring,
  .loader-logo {
    animation: none !important;
  }

  /* No scroll progress animation */
  .scroll-progress {
    transition: none !important;
  }
}

/* ==========================================================================
   20. BRAND MOTION LAYER
   Extra entrance, ambient and hover motion on top of the base animations.
   Everything here is transform/opacity/background-position only and is
   disabled for visitors who prefer reduced motion.
   ========================================================================== */
@media (prefers-reduced-motion: no-preference) {

  /* --- Navbar logo: drop in on load, lift on hover --- */
  .site-header .nav-brand-logo {
    animation: brandLogoDrop 0.7s cubic-bezier(0.22, 1, 0.36, 1) 0.15s both;
    transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1), filter 0.35s ease;
  }

  .site-header .nav-brand:hover .nav-brand-logo {
    transform: translateY(-2px) scale(1.06);
    filter: drop-shadow(0 6px 12px rgba(0, 0, 0, 0.18));
  }

  /* --- Hero: slow cinematic zoom on the video / poster --- */
  .brand-single-video.mode-hero {
    animation: heroKenBurns 24s ease-in-out infinite alternate;
    transform-origin: 60% 40%;
  }

  /* --- Hero: drifting brand glow orbs --- */
  .hero-glow-orb--1 {
    animation: orbDriftA 16s ease-in-out infinite alternate;
  }

  .hero-glow-orb--2 {
    animation: orbDriftB 20s ease-in-out infinite alternate;
  }

  /* --- Hero: highlight words get a travelling shine --- */
  .hero .hero-title .highlight {
    background-image: linear-gradient(105deg, rgba(255, 255, 255, 0) 42%, rgba(255, 255, 255, 0.9) 50%, rgba(255, 255, 255, 0) 58%), var(--brand-text-gradient);
    background-size: 300% 100%, 100% 100%;
    background-repeat: no-repeat;
    background-position: 150% 0, 0 0;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: brandTextShine 6s ease-in-out 1.6s infinite;
  }

  /* --- Hero: blur-to-sharp title focus (runs with the base slide-up) --- */
  .hero-title {
    animation: fadeSlideUp 0.65s cubic-bezier(0.22, 1, 0.36, 1) 0.42s both,
      brandFocusIn 0.9s ease-out 0.42s both;
  }

  /* --- Hero: primary CTA sends a shine every few seconds --- */
  .hero-actions .btn-primary::after,
  .cta-banner-actions .btn-primary::after {
    animation: btnAutoShine 5s ease-in-out 2.2s infinite;
  }

  /* --- Hero: content eases up and fades as you scroll past (set by JS) --- */
  .hero-content-center {
    transform: translate3d(0, var(--hero-shift, 0px), 0);
    opacity: var(--hero-fade, 1);
    will-change: transform, opacity;
  }

  /* --- Buttons: shine sweep on hover --- */
  .btn-primary,
  .btn--primary {
    position: relative;
    overflow: hidden;
    isolation: isolate;
  }

  .btn-primary::after,
  .btn--primary::after {
    content: '';
    position: absolute;
    top: 0;
    left: -60%;
    width: 45%;
    height: 100%;
    background: linear-gradient(105deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.45) 50%, rgba(255, 255, 255, 0) 100%);
    transform: skewX(-20deg) translateX(0);
    pointer-events: none;
    z-index: 1;
  }

  .btn-primary:hover::after,
  .btn--primary:hover::after {
    animation: btnHoverShine 0.75s ease-out;
  }

  /* --- Section headings: accent words get an underline that draws in --- */
  .section-title span {
    background-image: linear-gradient(color-mix(in srgb, currentColor 30%, transparent), color-mix(in srgb, currentColor 30%, transparent));
    background-repeat: no-repeat;
    background-position: 0 92%;
    background-size: 0% 0.16em;
    -webkit-box-decoration-break: clone;
    box-decoration-break: clone;
    transition: background-size 1s cubic-bezier(0.22, 1, 0.36, 1) 0.35s;
  }

  .is-revealed .section-title span,
  .section-header.is-revealed .section-title span {
    background-size: 100% 0.16em;
  }

  /* --- Eyebrow labels: soft letter-spacing settle --- */
  .is-revealed > .eyebrow,
  .is-revealed > .section-badge {
    animation: eyebrowSettle 0.8s cubic-bezier(0.22, 1, 0.36, 1) both;
  }

  /* --- Cards: icon pops and tilts on hover --- */
  .service-card:hover .service-card-icon svg,
  .trust-item:hover .trust-item-icon svg,
  .dropdown-item:hover .dropdown-item-icon svg {
    animation: iconPopTilt 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
  }

  .service-card-icon,
  .trust-item-icon {
    transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1), background-color 0.25s ease, color 0.25s ease;
  }

  .service-card:hover .service-card-icon,
  .trust-item:hover .trust-item-icon {
    transform: translateY(-3px) scale(1.06);
  }

  /* --- "Why" numbers glide in when their card reveals --- */
  .why-item.is-revealed .why-number {
    animation: numberRise 0.9s cubic-bezier(0.22, 1, 0.36, 1) 0.15s both;
  }

  /* --- Testimonials: stars pop in one by one (stars wrapped by JS) --- */
  .testimonial-stars .star {
    display: inline-block;
    transform-origin: 50% 60%;
  }

  .testimonial-card.is-revealed .testimonial-stars .star {
    animation: starPop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) both;
  }

  .testimonial-card.is-revealed .testimonial-stars .star:nth-child(1) { animation-delay: 0.20s; }
  .testimonial-card.is-revealed .testimonial-stars .star:nth-child(2) { animation-delay: 0.30s; }
  .testimonial-card.is-revealed .testimonial-stars .star:nth-child(3) { animation-delay: 0.40s; }
  .testimonial-card.is-revealed .testimonial-stars .star:nth-child(4) { animation-delay: 0.50s; }
  .testimonial-card.is-revealed .testimonial-stars .star:nth-child(5) { animation-delay: 0.60s; }

  /* --- CTA banner: slowly shifting gradient and drifting glows --- */
  .cta-banner {
    background-size: 180% 180%;
    animation: ctaGradientShift 16s ease-in-out infinite alternate;
  }

  .cta-banner::before {
    animation: orbDriftA 14s ease-in-out infinite alternate;
  }

  .cta-banner::after {
    animation: orbDriftB 18s ease-in-out infinite alternate;
  }

  /* --- Inner pages: header content arrives in sequence --- */
  .page-hero-content > * {
    animation: fadeSlideUp 0.7s cubic-bezier(0.22, 1, 0.36, 1) both;
  }

  .page-hero-content > *:nth-child(1) { animation-delay: 0.20s; }
  .page-hero-content > *:nth-child(2) { animation-delay: 0.32s; }
  .page-hero-content > *:nth-child(3) { animation-delay: 0.44s; }
  .page-hero-content > *:nth-child(4) { animation-delay: 0.56s; }
  .page-hero-content > *:nth-child(5) { animation-delay: 0.68s; }

  /* --- Footer: columns rise in when the footer scrolls into view --- */
  .footer-motion .footer-brand,
  .footer-motion .footer-col {
    opacity: 0;
    transform: translateY(18px);
    transition: opacity 0.7s ease, transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
  }

  .footer-motion.is-in .footer-brand,
  .footer-motion.is-in .footer-col {
    opacity: 1;
    transform: none;
  }

  .footer-motion.is-in .footer-col:nth-child(2) { transition-delay: 0.08s; }
  .footer-motion.is-in .footer-col:nth-child(3) { transition-delay: 0.16s; }
  .footer-motion.is-in .footer-col:nth-child(4) { transition-delay: 0.24s; }
  .footer-motion.is-in .footer-col:nth-child(5) { transition-delay: 0.32s; }

  /* --- Footer logo: gentle breathing --- */
  .footer-brand-logo {
    animation: logoBreath 5s ease-in-out infinite;
  }
}

/* ---------------- Brand motion keyframes ---------------- */
@keyframes brandLogoDrop {
  from { opacity: 0; transform: translateY(-14px) scale(0.92); }
  to { opacity: 1; transform: none; }
}

@keyframes heroKenBurns {
  from { transform: scale(1) translate3d(0, 0, 0); }
  to { transform: scale(1.09) translate3d(-1.2%, -1%, 0); }
}

@keyframes orbDriftA {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to { transform: translate3d(60px, 40px, 0) scale(1.12); }
}

@keyframes orbDriftB {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to { transform: translate3d(-70px, -30px, 0) scale(1.08); }
}

@keyframes brandTextShine {
  0% { background-position: 150% 0, 0 0; }
  40%, 100% { background-position: -50% 0, 0 0; }
}

@keyframes brandFocusIn {
  from { filter: blur(8px); }
  to { filter: blur(0); }
}

@keyframes btnHoverShine {
  from { left: -60%; }
  to { left: 130%; }
}

@keyframes btnAutoShine {
  0%, 70% { left: -60%; }
  90%, 100% { left: 130%; }
}

@keyframes eyebrowSettle {
  from { letter-spacing: 0.32em; opacity: 0; }
  to { opacity: 1; }
}

@keyframes iconPopTilt {
  0% { transform: scale(1) rotate(0); }
  40% { transform: scale(1.22) rotate(-10deg); }
  70% { transform: scale(0.96) rotate(6deg); }
  100% { transform: scale(1) rotate(0); }
}

@keyframes numberRise {
  from { opacity: 0; transform: translateY(14px) scale(0.9); letter-spacing: 0.2em; }
  to { opacity: 1; transform: none; }
}

@keyframes starPop {
  from { opacity: 0; transform: scale(0.2) rotate(-40deg); }
  to { opacity: 1; transform: none; }
}

@keyframes ctaGradientShift {
  from { background-position: 0% 30%; }
  to { background-position: 100% 70%; }
}

@keyframes logoBreath {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-3px); }
}
