/* Motion: a one-shot load-in, images that settle into their frames as they scroll in, and the
   link's underline. Values are tokens (tokens.css, "Motion"). None of it runs for anyone who
   asks for reduced motion; the pinned text column (project.css) isn't motion, so it stays. */

@media (prefers-reduced-motion: no-preference) {
  /* Load-in. js/motion.js holds the page (data-intro="wait") until the fonts and the hero
     image are in, then plays it once (data-intro="play"): client, title and body fade up a
     beat apart while the hero image settles. Without JavaScript the page simply shows. */

  .media__img {
    transform-origin: 50% 100%; /* images keep their bottom edge as they settle */
  }

  [data-intro="wait"] :is(.project__intro > :not(.project__nav), .project__body > *, .media--hero .media__img) {
    opacity: 0;
  }

  [data-intro="play"] :is(.project__intro > :not(.project__nav), .project__body > *) {
    animation: intro-rise var(--intro-duration) var(--motion-ease) both;
    animation-delay: calc(var(--intro-step, 0) * var(--intro-stagger));
  }

  .project__title { --intro-step: 1; }
  .project__body > :nth-child(1) { --intro-step: 2; }
  .project__body > :nth-child(2) { --intro-step: 3; }
  .project__body > :nth-child(n + 3) { --intro-step: 4; }

  [data-intro="play"] .media--hero .media__img {
    animation: settle var(--hero-duration) var(--motion-ease) both;
  }

  /* Home: the load-in runs down the page, each piece a beat after the last (steps in
     home.css); the artwork behind it fades in slowly over the whole thing */
  [data-intro="wait"] .home__step {
    opacity: 0;
  }

  [data-intro="wait"] .home__art {
    opacity: 0;
  }

  [data-intro="play"] .home__art {
    animation: art-in calc(var(--hero-duration) * 2) ease-out both;
  }

  [data-intro="play"] .home__step {
    animation: intro-rise var(--intro-duration) var(--motion-ease) both;
    animation-delay: calc(var(--intro-step, 0) * var(--intro-stagger));
  }

  /* The projects strip: hovering a tile pushes its cover in slowly, from the bottom edge like
     the hero, and lets it go faster; the name under it comes up to full */
  @media (hover: hover) {
    .tile__img {
      transform-origin: 50% 100%;
      transition: transform var(--tile-release-ms) var(--motion-ease);
    }

    .tile:is(:hover, :focus-visible) .tile__img {
      transform: translateX(calc(-1 * var(--tile-drift))) scale(var(--tile-zoom));
      transition-duration: var(--tile-zoom-ms);
    }

    .tile__label {
      transition: opacity 300ms ease-out;
    }
  }

  /* Scrolling in, an image settles into its frame: from a little bigger and faded to 100%,
     tied to the scroll so it plays back going up. The frame never moves, so the grid holds;
     cut-outs rise into place instead. Browsers that can't tie animations to scrolling just
     show the images. */

  @supports (animation-timeline: view()) {
    .media:not(.media--hero) .media__frame {
      view-timeline: --frame block;
    }

    .media:not(.media--hero) .media__img {
      animation-name: settle;
      animation-timing-function: ease-out;
      animation-fill-mode: both;
      animation-timeline: --frame;
      animation-range: entry 0% entry var(--settle-range);
    }

    .media--inset:not(.media--hero) .media__img {
      animation-name: settle-rise;
    }

    /* Ken Burns: over the first screen of scrolling, the hero pushes in slowly and drifts,
       from its bottom edge. It's a transform, so it adds to the load-in's scale instead of
       replacing it; during the load-in both run. */
    .media--hero .media__img {
      animation: ken-burns linear both;
      animation-timeline: scroll(root);
      animation-range: 0 100vh;
    }

    [data-intro="play"] .media--hero .media__img {
      animation: settle var(--hero-duration) var(--motion-ease) both, ken-burns linear both;
      animation-timeline: auto, scroll(root);
      animation-range: normal, 0 100vh;
    }
  }

  /* The project nav: arrows nudge the way they point */
  .nav__arrow svg {
    transition: translate 300ms var(--motion-ease);
  }

  .nav__arrow--prev:is(:hover, :focus-visible) svg {
    translate: -2px 0;
  }

  .nav__arrow--next:is(:hover, :focus-visible) svg {
    translate: 2px 0;
  }

  /* Link: hovered or focused, the underline pulls away to the right, then draws back in from
     the left. Drawn as a background so it can be animated; sits where the underline did. */

  :is(.t-body, .t-caption) a {
    text-decoration-line: none;
    background: linear-gradient(currentColor 0 0) 100% 100% / 100% 1px no-repeat;
  }

  :is(.t-body, .t-caption) a:is(:hover, :focus-visible) {
    animation: underline-redraw 700ms var(--motion-ease);
  }

  /* The arrow waits down and to the left, slides up into place a beat after the underline
     starts, and slips back quickly when the pointer leaves */
  :is(.t-body, .t-caption) a[href^="http"]::after {
    translate: -0.35em 0.35em;
    transition: opacity 150ms ease-out, translate 150ms ease-out;
  }

  /* The camera and globe icons don't slide; they're already there */
  :is(.t-body, .t-caption) a:is(.link--video, .link--web)::after,
  :is(.t-body, .t-caption) a:is(.link--video, .link--web):is(:hover, :focus-visible)::after {
    translate: 0 0;
    transition: none;
  }

  :is(.t-body, .t-caption) a[href^="http"]:is(:hover, :focus-visible)::after {
    translate: 0 0;
    transition: opacity 300ms ease-out 120ms, translate 550ms var(--motion-ease) 120ms;
  }
}

@keyframes art-in {
  from {
    opacity: 0;
  }
}

@keyframes intro-rise {
  from {
    opacity: 0;
    translate: 0 var(--intro-rise);
  }
}

@keyframes settle {
  from {
    opacity: var(--settle-fade);
    scale: var(--settle-scale);
  }
}

@keyframes ken-burns {
  to {
    transform: translateX(calc(-1 * var(--hero-drift))) scale(var(--hero-zoom));
  }
}

@keyframes settle-rise {
  from {
    opacity: var(--settle-fade);
    translate: 0 var(--settle-rise);
  }
}

@keyframes underline-redraw {
  0% {
    background-position-x: 100%;
    background-size: 100% 1px;
  }
  45% {
    background-position-x: 100%;
    background-size: 0% 1px;
  }
  45.1% {
    background-position-x: 0%;
    background-size: 0% 1px;
  }
  100% {
    background-position-x: 0%;
    background-size: 100% 1px;
  }
}
