/* ==========================================================================
   animations.css — keyframes + animation utility classes
   Only transform/opacity animate on anything continuous or scroll-linked.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Keyframes
   -------------------------------------------------------------------------- */

/* Hero Ken Burns — slow push on the active slide */
@keyframes ken-burns {
  from {
    transform: scale(1.02) translate3d(0, 0, 0);
  }
  to {
    transform: scale(1.14) translate3d(-1.2%, -1.4%, 0);
  }
}

/* Slide-control progress sweep */
@keyframes dot-progress {
  from {
    transform: scaleX(0);
  }
  to {
    transform: scaleX(1);
  }
}

/* Grass blades: each blade gets an offset delay so none move in sync */
@keyframes sway {
  0%,
  100% {
    transform: rotate(-1.6deg);
  }
  50% {
    transform: rotate(1.9deg);
  }
}

/* Scroll cue bob */
@keyframes cue-bob {
  0%,
  100% {
    transform: translateY(0);
    opacity: 0.65;
  }
  50% {
    transform: translateY(6px);
    opacity: 1;
  }
}

/* Reveal on scroll */
@keyframes reveal-up {
  from {
    opacity: 0;
    transform: translateY(2rem);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Icon line draw-in */
@keyframes draw-in {
  from {
    stroke-dashoffset: 120;
  }
  to {
    stroke-dashoffset: 0;
  }
}

/* Soft pulse behind the primary CTA */
@keyframes pulse-ring {
  0% {
    box-shadow: 0 0 0 0 rgba(245, 166, 35, 0.45);
  }
  70% {
    box-shadow: 0 0 0 14px rgba(245, 166, 35, 0);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(245, 166, 35, 0);
  }
}

/* Wedge intro — the diagonal cut sweeps in on first paint */
@keyframes wedge-in {
  from {
    opacity: 0;
    transform: skewX(var(--diagonal-angle)) translateX(-14%);
  }
  to {
    opacity: 1;
    transform: skewX(var(--diagonal-angle)) translateX(0);
  }
}


/* --------------------------------------------------------------------------
   Hero motion
   -------------------------------------------------------------------------- */
.hero__wedge {
  animation: wedge-in var(--duration-slower) var(--ease-out-expo) both;
}

/* Ken Burns runs only on the visible slide, and pauses when the hero is
   scrolled out of view (class toggled from animations.js). */
.hero__slide img {
  will-change: transform;
}

.hero__slide.is-active img {
  animation: ken-burns var(--loop-kenburns) var(--ease-in-out-soft) forwards;
}

.hero.is-offscreen .hero__slide img {
  animation-play-state: paused;
}

/* Delays are offset past --duration-base (400ms) because .hero__copy.is-active
   waits that long before fading in, so the outgoing slide's copy is gone first. */
.hero__copy.is-active .hero__eyebrow {
  animation: reveal-up var(--duration-slow) var(--ease-out-expo) 520ms both;
}

.hero__copy.is-active .hero__title {
  animation: reveal-up var(--duration-slow) var(--ease-out-expo) 620ms both;
}

.hero__copy.is-active .hero__lead {
  animation: reveal-up var(--duration-slow) var(--ease-out-expo) 740ms both;
}

.hero__copy.is-active .hero__actions {
  animation: reveal-up var(--duration-slow) var(--ease-out-expo) 860ms both;
}

.hero__cue .icon {
  animation: cue-bob 2.4s var(--ease-in-out-soft) infinite;
}


/* --------------------------------------------------------------------------
   Grass blade sway — offset per blade so the band never marches in step
   -------------------------------------------------------------------------- */
.divider--grass .grass__blade {
  transform-box: fill-box;
  transform-origin: bottom center;
  animation: sway var(--loop-sway) var(--ease-in-out-soft) infinite;
}

/* A randomly chosen share of blades is baked static in the markup. With ~190
   paths per band, animating all of them burns main-thread time for no visual
   gain — real grass does not move as one. */
.divider--grass .grass__blade--still {
  animation: none;
}

/* The flipped band at the top of the contact section points up into flat black,
   where the sway is invisible; skipping it halves the page's animated paths. */
.divider--flip .grass__blade {
  animation: none;
}

/* An 11-step cycle over jittered blade shapes: long enough that no travelling
   wave is visible, where the old 6-step cycle on evenly spaced blades read as a
   pattern. Durations are deliberately non-multiples of each other. */
.divider--grass .grass__blade:nth-child(11n + 1) {
  animation-duration: 7.7s;
  animation-delay: -0.4s;
}
.divider--grass .grass__blade:nth-child(11n + 2) {
  animation-duration: 11.3s;
  animation-delay: -4.9s;
}
.divider--grass .grass__blade:nth-child(11n + 3) {
  animation-duration: 9.1s;
  animation-delay: -2.2s;
}
.divider--grass .grass__blade:nth-child(11n + 4) {
  animation-duration: 13.4s;
  animation-delay: -7.6s;
}
.divider--grass .grass__blade:nth-child(11n + 5) {
  animation-duration: 8.6s;
  animation-delay: -1.1s;
}
.divider--grass .grass__blade:nth-child(11n + 6) {
  animation-duration: 12.1s;
  animation-delay: -5.8s;
}
.divider--grass .grass__blade:nth-child(11n + 7) {
  animation-duration: 10.4s;
  animation-delay: -9.3s;
}
.divider--grass .grass__blade:nth-child(11n + 8) {
  animation-duration: 14.2s;
  animation-delay: -3.1s;
}
.divider--grass .grass__blade:nth-child(11n + 9) {
  animation-duration: 8.1s;
  animation-delay: -6.4s;
}
.divider--grass .grass__blade:nth-child(11n + 10) {
  animation-duration: 11.9s;
  animation-delay: -0.9s;
}
.divider--grass .grass__blade:nth-child(11n) {
  animation-duration: 9.7s;
  animation-delay: -8.2s;
}

/* Taller back blades move a little more, like grass further from the mower */
.divider--grass .grass__blades--back .grass__blade {
  animation-duration: 15.5s;
}


/* --------------------------------------------------------------------------
   Scroll reveals — driven by a single IntersectionObserver in animations.js
   -------------------------------------------------------------------------- */
[data-reveal] {
  opacity: 0;
  transform: translateY(2rem);
  transition: opacity var(--duration-slow) var(--ease-out-soft),
    transform var(--duration-slow) var(--ease-out-expo);
  transition-delay: calc(var(--reveal-delay, 0) * var(--stagger-step));
}

[data-reveal].is-revealed {
  opacity: 1;
  transform: translateY(0);
}

/* If JS never runs, nothing should stay invisible */
.no-js [data-reveal] {
  opacity: 1;
  transform: none;
}


/* --------------------------------------------------------------------------
   Icon draw-in on reveal
   -------------------------------------------------------------------------- */
.pillar__icon .icon path,
.pillar__icon .icon circle {
  stroke-dasharray: 120;
}

[data-reveal].is-revealed .pillar__icon .icon path,
[data-reveal].is-revealed .pillar__icon .icon circle {
  animation: draw-in var(--duration-slower) var(--ease-out-soft) 200ms both;
}


/* --------------------------------------------------------------------------
   CTA pulse — the hero's primary phone button only, so it stays a signal
   -------------------------------------------------------------------------- */
.hero__actions .btn--primary {
  animation: pulse-ring 3.6s var(--ease-out-soft) 1.6s infinite;
}

.hero__actions .btn--primary:hover {
  animation-play-state: paused;
}


/* --------------------------------------------------------------------------
   Parallax hook — transform is written by rAF in animations.js
   -------------------------------------------------------------------------- */
[data-parallax] {
  will-change: transform;
}


/* --------------------------------------------------------------------------
   Reduced-motion tier: kill ambient loops and parallax, keep reveals as
   instant opacity fades (CLAUDE.md §6).
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .hero__slide.is-active img,
  .hero__cue .icon,
  .divider--grass .grass__blade,
  .hero__actions .btn--primary,
  .hero__wedge {
    animation: none !important;
  }

  .hero__slide img {
    transform: none;
    will-change: auto;
  }

  .hero__copy.is-active .hero__eyebrow,
  .hero__copy.is-active .hero__title,
  .hero__copy.is-active .hero__lead,
  .hero__copy.is-active .hero__actions {
    animation: none;
  }

  .hero__copy {
    transform: none;
    transition: opacity var(--duration-base) linear;
  }

  [data-reveal] {
    transform: none;
    transition: opacity var(--duration-base) linear;
    transition-delay: 0ms;
  }

  [data-reveal].is-revealed {
    transform: none;
  }

  [data-parallax] {
    transform: none !important;
    will-change: auto;
  }

  .hero__dot.is-active .hero__dot-fill {
    animation: none;
    transform: scaleX(1);
  }

  .card:hover,
  .tile:hover,
  .btn:hover {
    transform: none;
  }
}
