/* ==========================================================================
   Latx Technologies — Motion
   --------------------------------------------------------------------------
   All motion in one file so its cost is visible and it can be removed in one
   line if it ever stops earning its place.

   Three rules this file follows without exception:

   1. Every animation is wrapped in `prefers-reduced-motion: no-preference`.
      Motion is opt-out at the operating-system level, and a visitor who has
      asked for less gets a completely static site — not a faster one.
   2. Only `transform` and `opacity` are animated. Both are composited by the
      GPU; animating `width`, `height`, `top` or `left` forces layout on every
      frame and is the usual cause of janky scrolling.
   3. Nothing is hidden by default unless JavaScript is running. The reveal
      classes only take effect under `.has-javascript`, which functions.php
      prints in the head, so a no-script visitor sees the whole page.

   Requires variables.css, reset.css, global.css.
   ========================================================================== */

@media (prefers-reduced-motion: no-preference) {
  /* ------------------------------------------------- 1. Reveal on scroll */

  .has-javascript .reveal {
    opacity: 0;
    transform: translateY(1rem);
    transition:
      opacity var(--duration-slow) var(--easing-out),
      transform var(--duration-slow) var(--easing-out);
    transition-delay: var(--reveal-delay, 0ms);
  }

  .has-javascript .reveal.is-visible {
    opacity: 1;
    transform: none;
  }

  /* Variants for elements that read better arriving from the side. */
  .has-javascript .reveal--from-left {
    transform: translateX(-1.5rem);
  }

  .has-javascript .reveal--from-right {
    transform: translateX(1.5rem);
  }

  .has-javascript .reveal--zoom-in {
    transform: scale(0.96);
  }

  .has-javascript .reveal--from-left.is-visible,
  .has-javascript .reveal--from-right.is-visible,
  .has-javascript .reveal--zoom-in.is-visible {
    transform: none;
  }

  /* A group whose children arrive in sequence. reveal.js sets the index, so
     the delay is computed rather than hand-written into the markup. Capped at
     four steps by the script, so a twelve-card grid does not take a second and
     a half to finish arriving. */
  .has-javascript .reveal[style*="--stagger-index"] {
    transition-delay: calc(var(--stagger-index, 0) * 90ms);
  }

  /* ------------------------------------------------- 2. Entrance on load */

  /* Above-the-fold content is visible immediately and so cannot wait for a
     scroll trigger. The delay is set per element with --entrance-delay, so a
     group arrives in sequence rather than all at once. */
  .has-javascript .entrance {
    animation: entrance-rise 700ms var(--easing-out) backwards;
    animation-delay: var(--entrance-delay, 0ms);
  }

  @keyframes entrance-rise {
    from {
      opacity: 0;
      transform: translateY(1.25rem);
    }

    to {
      opacity: 1;
      transform: none;
    }
  }

  /* --------------------------------------------------- 3. Image reveal */

  /* The image scales down to its natural size as it arrives, which reads as
     the photograph settling into place rather than appearing abruptly. */
  .has-javascript .image-reveal {
    overflow: hidden;
  }

  .has-javascript .image-reveal img {
    transform: scale(1.08);
    transition: transform 900ms var(--easing-out);
  }

  .has-javascript .image-reveal.is-visible img {
    transform: scale(1);
  }

  /* ------------------------------------------------- 4. Hover responses */

  /* Cards with a photograph: the image lifts slightly under the pointer.
     Scoped to hover-capable devices so it never fires on a tap. */
  @media (hover: hover) {
    .work-card__thumbnail,
    .post-card__thumbnail {
      transition: transform var(--duration-slow) var(--easing-out);
    }

    .work-card:hover .work-card__thumbnail,
    .post-card:hover .post-card__thumbnail {
      transform: scale(1.04);
    }
  }

  /* ------------------------------------------------ 5. Continuous motion */

  /* A slow drift on the hero's light sources. Long duration and small
     displacement on purpose: it should register as depth, not as an animation
     demanding attention. */
  .hero__glow--blue {
    animation: glow-drift 22s var(--easing-in-out) infinite alternate;
  }

  .hero__glow--violet {
    animation: glow-drift 28s var(--easing-in-out) infinite alternate-reverse;
  }

  @keyframes glow-drift {
    from {
      transform: translate3d(0, 0, 0) scale(1);
    }

    to {
      transform: translate3d(-3%, 4%, 0) scale(1.12);
    }
  }

  /* ------------------------------------------------- 6. Numeric counting */

  /* The trust-strip figures count up once, when first scrolled into view. The
     markup carries the final value as text, so the number is correct and
     readable before and after the animation, and without JavaScript. Tabular
     figures stop the digits jittering while it runs. */
  [data-count-up] {
    font-variant-numeric: tabular-nums;
  }
}
