/* ===========================
      HOMEPAGE HERO — AMBIENT MOTION

      The left of the hero already moves: text fades in, a word in the
      heading swaps, the bands drift along the foot. The right half went
      completely still once its entry animations finished, which is what
      made the whole thing read as a screenshot.

      Two rules kept this from fighting what is already there:

      - Motion is written as the standalone `translate` and `rotate`
        properties, never the `transform` shorthand. Both outline squares
        rest on transform:rotate(-65deg); a keyframe on `transform` would
        have replaced that and swung them upright. The standalone
        properties compose on top of it instead.

      - It only starts once the entry animations have finished, on a class
        js/hero-alive.js adds. Each of these elements already carries an
        `animation`, and a second declaration replaces rather than adds --
        harmless after the first has played out and settled on its natural
        state, wrong while it is still running.

      Everything drifts on its own duration and a negative delay, so the
      pieces are never in step and nothing swings on load.
=========================== */

@keyframes heroDrift{
    from{ translate:0 0; }
    to  { translate:0 -12px; }
}

@keyframes heroDriftTilt{
    from{ translate:0 0;    rotate:0deg; }
    to  { translate:0 -9px; rotate:1.6deg; }
}

/* The blob used to breathe: 7px up and 1.2% bigger, alternating. Straight up
   and back down is the one path the eye reads as no path at all, and the
   scale was doing nothing except softening a raster image on the way. This
   traces a slow loop instead -- out, up, back across, down -- so there is
   always a direction to notice. Four stops rather than alternate, because a
   loop has to come back round rather than reverse.

   No scale in it, so the photograph is never resampled mid-drift. */

@keyframes heroFloat{
    0%   { translate:0 0;         rotate:0deg;   }
    25%  { translate:-8px -11px;  rotate:-.6deg; }
    50%  { translate:0 -19px;     rotate:0deg;   }
    75%  { translate:8px -11px;   rotate:.6deg;  }
    100% { translate:0 0;         rotate:0deg;   }
}

.hero-alive .hero-blob{
    animation:heroFloat 11s ease-in-out infinite;
}

.hero-alive .hero-outline-square{
    animation:heroDriftTilt 9s ease-in-out -2s infinite alternate;
}

.hero-alive .hero-outline-square-back{
    animation:heroDriftTilt 11s ease-in-out -5s infinite alternate;
}

.hero-alive .hero-stats-card{
    animation:heroDrift 6s ease-in-out -1.5s infinite alternate;
}

/* Follows the card it sits behind, a touch slower so the gap between them
   opens and closes rather than staying fixed. */

.hero-alive .hero-stats-card-shadow{
    animation:heroDrift 6.6s ease-in-out -1.2s infinite alternate;
}

/* js/script.js counts these up on load; tabular figures stop the width
   twitching on every frame as the digits change. */

.hero-stats-card .stats-number{
    font-variant-numeric:tabular-nums;
}

@media (prefers-reduced-motion:reduce){

    .hero-alive .hero-blob,
    .hero-alive .hero-outline-square,
    .hero-alive .hero-outline-square-back,
    .hero-alive .hero-stats-card,
    .hero-alive .hero-stats-card-shadow{
        animation:none;
    }

}
