/* Motion, in the brand's shapes: straight wipes and the diagonal of the
   fold, no circles. On load the hero photo wipes open from the right
   along its cut edge, the accent band follows it, and the text settles
   in. On scroll, titles rise out of their lines, text settles, photos
   wipe open upwards and the fold's band draws itself down its diagonal.
   Only for visitors without reduced motion; the scroll parts only where
   scroll-driven animations are supported (main.js covers the rest). The
   page reads the same without any of it. */

@media (prefers-reduced-motion: no-preference) {
  /* The accent leads, the photo follows on top of it. */
  .hero::after {
    animation: theme-band-wipe 1.2s var(--theme-ease-signature) 0.05s both;
  }

  .hero__media {
    animation: theme-hero-wipe 1.2s var(--theme-ease-signature) 0.3s both;
  }

  .hero__text > * {
    animation: theme-settle 0.9s var(--theme-ease-signature) both;
  }

  .hero__text > :nth-child(1) {
    animation-delay: 0.3s;
  }

  .hero__text > :nth-child(2) {
    animation-delay: 0.38s;
  }

  .hero__text > :nth-child(3) {
    animation-delay: 0.5s;
  }

  .hero__tag {
    animation: theme-settle 0.8s var(--theme-ease-signature) 1s both;
  }

  .hero__tag--start {
    animation-delay: 0.9s;
  }

  .hero__tag--floors {
    animation-delay: 1s;
  }

  .hero__tag--price {
    animation-delay: 1.1s;
  }

  .hero__tag--door {
    animation-delay: 1.2s;
  }

  .hero__tag--size {
    animation-delay: 1.3s;
  }

  .availability {
    animation: theme-settle 0.8s var(--theme-ease-signature) 0.3s both;
  }

  @keyframes theme-hero-wipe {
    from {
      clip-path: polygon(100% 0, 100% 0, 100% 100%, 100% 100%);
    }
  }

  @keyframes theme-band-wipe {
    from {
      clip-path: polygon(100% 0, 100% 0, 100% 100%, 100% 100%);
    }
  }

  @keyframes theme-settle {
    from {
      opacity: 0;
      translate: 0 16px;
    }
  }

  /* Narrow screens: the photo sits under the text with a slanted top. */
  @media (width <= 800px) {
    @keyframes theme-hero-wipe {
      from {
        clip-path: polygon(0 100%, 100% 100%, 100% 100%, 0 100%);
      }
    }
  }
}

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    [data-reveal] {
      animation: theme-settle-far cubic-bezier(0.3, 0.4, 0.4, 1) both;
      animation-timeline: view();
      animation-range: entry 0% cover 35%;
    }

    /* Photos wipe open upwards, a straight edge like the blocks. */
    [data-reveal='image'] {
      animation-name: theme-reveal-image;
      animation-range: entry 0% cover 45%;
    }

    /* The blueprint grid fades in as the section scrolls in (on the
       section's timeline: a pseudo-element cannot drive its own). */
    .feature {
      view-timeline: --theme-feature block;
    }

    .feature::before {
      animation: theme-grid-in linear both;
      animation-timeline: --theme-feature;
      animation-range: entry 0% cover 45%;
    }

    @keyframes theme-grid-in {
      from {
        opacity: 0;
        scale: 1.06;
      }
    }

    /* The fold's band draws down its diagonal from the dark block. */
    .fold__band {
      animation: theme-fold-draw linear both;
      animation-timeline: view();
      animation-range: entry 20% cover 55%;
    }

    @keyframes theme-settle-far {
      from {
        opacity: 0;
        translate: 0 32px;
      }
    }

    @keyframes theme-reveal-image {
      from {
        clip-path: inset(100% 0 0);
      }

      to {
        clip-path: inset(0);
      }
    }

    @keyframes theme-fold-draw {
      from {
        clip-path: polygon(
          var(--theme-fold-split) 0,
          var(--theme-fold-split) 0,
          var(--theme-fold-split) var(--theme-fold-step),
          var(--theme-fold-split) var(--theme-fold-step)
        );
      }
    }
  }
}

/* Call to action: the photos come in from their own edge as the section
   scrolls in, sit still while it fills the screen, and drift on a little
   further as it leaves. The image inside floats gently all the time,
   each at its own pace. */
@media (prefers-reduced-motion: no-preference) {
  .cta__image img {
    animation: theme-float 7s ease-in-out infinite alternate;
  }

  .cta__image--top img {
    animation-duration: 9s;
    animation-delay: -3s;
  }

  .cta__image--bottom img {
    animation-duration: 8s;
    animation-delay: -5s;
  }

  .cta__image--right img {
    animation-duration: 10s;
    animation-delay: -2s;
  }

  .cta__image--centre img {
    animation-duration: 6s;
    animation-delay: -4s;
  }

  @keyframes theme-float {
    from {
      translate: 0 -8px;
      rotate: -0.6deg;
    }

    to {
      translate: 0 8px;
      rotate: 0.6deg;
    }
  }
}

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .cta {
      view-timeline: --theme-cta block;
    }

    .cta__image {
      animation: theme-cta-drift linear both;
      animation-timeline: --theme-cta;
      animation-range: cover;
    }

    @keyframes theme-cta-drift {
      0% {
        opacity: 0;
        translate: var(--theme-cta-dx) var(--theme-cta-dy);
        scale: 0.7;
      }

      35%,
      55% {
        opacity: 1;
        translate: 0 0;
        scale: 1;
      }

      100% {
        opacity: 1;
        translate: calc(var(--theme-cta-dx) * -0.4) calc(var(--theme-cta-dy) * -0.4);
        scale: 1.05;
      }
    }
  }
}

/* Where scroll-driven animations are missing, main.js marks each
   [data-reveal] element once it is on screen. */
@media (prefers-reduced-motion: no-preference) {
  [data-reveal-mode='observer'] [data-reveal] {
    opacity: 0;
    translate: 0 32px;
    transition:
      opacity 0.8s var(--theme-ease-signature),
      translate 0.8s var(--theme-ease-signature);
  }

  [data-reveal-mode='observer'] [data-reveal][data-revealed] {
    opacity: 1;
    translate: 0 0;
  }
}

/* Titles: each rendered line is clipped (main.js wraps them), and its
   text rises up out of it, one line after the other. Without
   JavaScript the title is plain text. */
.reveal-line {
  display: block;
  overflow: clip;

  /* Room for descenders inside the clip, without changing the spacing. */
  padding-bottom: 0.12em;
  margin-bottom: -0.12em;
}

.reveal-line__inner {
  display: block;
}

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    [data-reveal-lines] {
      view-timeline: --theme-title block;
    }

    [data-reveal-lines] .reveal-line__inner {
      animation: theme-line-up cubic-bezier(0.3, 0.4, 0.4, 1) both;
      animation-timeline: --theme-title;
      animation-range: entry calc(var(--theme-line-index) * 25%) cover
        calc(30% + var(--theme-line-index) * 6%);
    }

    @keyframes theme-line-up {
      from {
        translate: 0 110%;
      }
    }
  }
}
