/* ==========================================================================
   In-view choreography

   Modelled on the reference site, which drives it with GSAP + ScrollTrigger:

       about-text    x −50   opacity 0→1   0.8s  power2.out
       about-image   x +50   opacity 0→1   0.8s  delay 0.2
       product-card  y +50   opacity 0→1   0.6s  stagger 0.1
       toggleActions   play none none reverse

   The first version of this file used animation-timeline: view() and no
   script. That was the better idea on paper and the wrong one in practice:
   on an engine that has not shipped it there is no fallback, the page simply
   never moves, and a stylesheet cannot detect that and do something else.

   So the state comes from a class now — assets/js/inview.js adds `.is-in`
   when the element enters and takes it away when it leaves — and everything
   below is a plain transition. Transitions run everywhere.

   ── The rule that matters ──────────────────────────────────────────────────

   The resting state is never opacity 0.

   If the script fails to load, is blocked, or throws, `.is-in` is never
   added — and whatever the resting state is, that is what the visitor is left
   looking at forever. 0.12 keeps a section dim; 0 loses it. No animation is
   worth a page that can go blank.
   ========================================================================== */

/* ==========================================================================
   Two layers, two channels
   ==========================================================================

   Three things animate the same elements on this site.

     reveal.js   marks the section .fl-reveal; main.css fades its children up
     main.css    runs a scroll-linked parallax (fl-drift-copy / fl-drift-media)
                 through animation-timeline: view()
     inview.js   marks specific children [data-anim]; this file slides them in
                 from the sides so the copy and the picture converge

   The first collision was specificity: .fl-reveal .fl-story__media (0,2,0)
   outweighed [data-anim="right"] (0,1,0), so the picture never moved sideways.
   Repeating the attribute selector settles that — this file is enqueued after
   main.css, so equal weight is enough, and no markup or !important was needed.

   The second collision could not be settled that way at all. The STORY copy
   carries fl-drift-copy, and a CSS animation overrides every normal
   declaration no matter how specific — it even beats an inline style, which is
   how it was finally identified: assigning el.style.transform directly changed
   nothing. The picture escaped only because the parallax is attached to the
   <img> inside the figure while the converge is on the figure itself. That was
   luck, not design.

   So the two effects are given different channels:

       transform          the parallax drift, untouched
       translate / scale  the entrance, here

   translate and scale are separate properties from transform; both apply and
   compose, so neither can take the other's place. On an engine too old to
   support them the slide is dropped and the 0.12 -> 1 fade remains, which is
   this layer's standing rule: nothing here may leave a section invisible.
   ========================================================================== */

@media (prefers-reduced-motion: no-preference) {

  [data-anim][data-anim] {
    /* power2.out from the reference, written as a bezier. */
    transition:
      opacity 0.85s cubic-bezier(0.22, 0.61, 0.36, 1) var(--fl-anim-delay, 0s),
      translate 0.85s cubic-bezier(0.22, 0.61, 0.36, 1) var(--fl-anim-delay, 0s),
      scale 0.85s cubic-bezier(0.22, 0.61, 0.36, 1) var(--fl-anim-delay, 0s),
      clip-path 0.85s cubic-bezier(0.22, 0.61, 0.36, 1) var(--fl-anim-delay, 0s);
    clip-path: none;
    will-change: translate, opacity;
  }

  /* -------------------------------------------------------- resting states */

  [data-anim="up"][data-anim]    { opacity: 0.12; translate: 0 72px; }
  [data-anim="left"][data-anim]  { opacity: 0.12; translate: -18% 0; }
  [data-anim="right"][data-anim] { opacity: 0.12; translate: 18% 0; }
  [data-anim="scale"][data-anim] { opacity: 0.12; scale: 0.88; }
  [data-anim="wipe"][data-anim]  { opacity: 0.12; scale: 1.05; clip-path: inset(0 0 32% 0); }

  /* ------------------------------------------------------------ in view */

  [data-anim][data-anim].is-in {
    opacity: 1;
    translate: none;
    scale: none;
    clip-path: inset(0 0 0 0);
  }

  /*
   * The picture follows the sentence. The reference delays its image by 0.2s
   * for the same reason: the words land, then the image agrees with them.
   */
  .fl-story__media[data-anim][data-anim] {
    transition-delay: 0.18s;
  }

  /* Once it has arrived it should stop claiming a compositor layer. */
  [data-anim][data-anim].is-in {
    will-change: auto;
  }
}
