/* Reign Wala: the arrival system. Loaded last on every page; remove this file and js/motion.js and everything is
   simply there, still.

   Below the opening, things arrive once, as they come into view, in one language: headings and their first lines
   rise 12px and fade in, photographs develop (a fade and a slight settle), a section's hairline draws in from the
   left, and the two display lines rise word by word from a mask. Inside a [data-stagger] group each follows the last
   by 80ms. Nothing replays on the way back up and nothing is tied to the scroll position.

   Markup: data-reveal ("" rise, "draw", "words"), data-ph, data-stagger (see js/motion.js). motion.js adds .is-in
   when one arrives, .is-done once its arrival has finished (from then on the element's own transitions apply
   again), and .is-now for the moment it is shown without motion. Everything held back here waits on html.js (set by
   one line in the head), on a screen (a printed page shows everything), and on there being no wish for reduced
   motion: with JavaScript off, or reduced motion, every word and photograph is simply there. Arrivals move opacity, translate and scale, never transform, so whatever
   transform an element already has is left alone. */

[data-reveal="draw"]::after, [data-reveal="pen"]::after { transform-origin: 0 50%; }
.rw-w, .rw-w > span { display: inline-block; }

@media screen and (prefers-reduced-motion: no-preference) {
  /* rise, the default: 12px and a fade (--rise: 0px makes it a fade alone) */
  html.js :is([data-reveal=""], [data-reveal="rise"]):not(.is-in) { opacity: 0; translate: 0 var(--rise, 12px); }
  html.js :is([data-reveal=""], [data-reveal="rise"]).is-in:not(.is-done) { transition: opacity 800ms var(--ease) var(--d, 0ms), translate 1000ms var(--ease) var(--d, 0ms); }

  /* draw: the element's own ::after hairline grows from the left */
  html.js [data-reveal="draw"]:not(.is-in)::after { scale: 0 1; }
  html.js [data-reveal="draw"].is-in:not(.is-done)::after { transition: scale 1000ms var(--ease) var(--d, 0ms); }

  /* words: once the fonts are in, motion.js sets each word in a mask (.rw-w); until then the line waits unseen.
     The mask reaches past the line on every side, so descenders and quotation marks are never cut, and a waiting
     word sits wholly below it. Once the line has arrived it is plain text again. */
  html.js [data-reveal="words"]:not(.is-split):not(.is-in) { opacity: 0; }
  html.js [data-reveal="words"].is-in:not(.is-split):not(.is-done) { transition: opacity 800ms var(--ease) var(--d, 0ms); }
  html.js [data-reveal="words"] .rw-w { clip-path: inset(-0.4em -0.3em -0.34em); }
  html.js [data-reveal="words"]:not(.is-in) .rw-w > span { translate: 0 175%; }
  html.js [data-reveal="words"].is-in:not(.is-done) .rw-w > span { transition: translate 900ms var(--ease) calc(var(--d, 0ms) + var(--i, 0) * 40ms); }

  /* photographs develop: a soft fade and a slight settle, once the picture has loaded */
  html.js [data-ph]:not(.is-in) img { opacity: 0; scale: 1.05; }
  html.js [data-ph].is-in:not(.is-done) img { transition: opacity 1000ms var(--ease) var(--d, 0ms), scale 1600ms var(--ease) var(--d, 0ms); }

  /* the thread beneath the five steps sews itself through once, as the row arrives (.steps gets .is-in with its
     first photograph, and follows the photographs a beat behind, as a seam follows the needle): drawn left to right on a wide screen, down the photo column on a phone (--cut, in css/style.css) */
  html.js .steps:not(.is-in) + .thread { clip-path: inset(var(--cut)); }
  html.js .steps.is-in + .thread { transition: clip-path 1600ms cubic-bezier(0.45, 0, 0.3, 1) 450ms; }
  html.js .steps:has(.is-now) + .thread { transition: none; }

  /* (9 Nov) pen: a promise (the homepage) or a note in Good to know (the bag pages). Its hairline draws in as "draw" does, then its icon is drawn line by line, as if by a pen
     (each shape carries pathLength="1" in index.html), and its words follow. */
  html.js [data-reveal="pen"]:not(.is-in)::after { scale: 0 1; }
  html.js [data-reveal="pen"] .vi-svg :is(path, circle, ellipse) { stroke-dasharray: 1 1; }
  html.js [data-reveal="pen"]:not(.is-in) .vi-svg { opacity: 0; }
  html.js [data-reveal="pen"]:not(.is-in) .vi-svg :is(path, circle, ellipse) { stroke-dashoffset: 1; }
  html.js [data-reveal="pen"]:not(.is-in) :is(.vi-label, h3, p, .link) { opacity: 0; translate: 0 8px; }
  html.js [data-reveal="pen"].is-in:not(.is-done)::after { transition: scale 1000ms var(--ease) var(--d, 0ms); }
  html.js [data-reveal="pen"].is-in:not(.is-done) .vi-svg { transition: opacity 200ms var(--ease) calc(var(--d, 0ms) + 160ms), translate 320ms var(--ease); }
  html.js [data-reveal="pen"].is-in:not(.is-done) .vi-svg :is(path, circle, ellipse) { transition: stroke-dashoffset 1300ms var(--ease-pen) calc(var(--d, 0ms) + 160ms); }
  html.js [data-reveal="pen"].is-in:not(.is-done) :is(.vi-label, h3, p, .link) { transition: opacity 800ms var(--ease) calc(var(--d, 0ms) + 520ms), translate 1000ms var(--ease) calc(var(--d, 0ms) + 520ms); }


  /* (9 Nov) sign: the footer's reign_wala writes itself in from the left, as a signature */
  html.js [data-reveal="sign"] img { clip-path: inset(-30% -4% -30% 0); }
  html.js [data-reveal="sign"]:not(.is-in) img { clip-path: inset(-30% 100% -30% 0); }
  html.js [data-reveal="sign"].is-in:not(.is-done) img { transition: clip-path 1700ms var(--ease-pen) calc(var(--d, 0ms) + 200ms); }

  /* shown without motion (already passed, or a return to the page), whatever other transitions say */
  html.js .is-now, html.js .is-now::after, html.js .is-now img, html.js .is-now .rw-w > span,
  html.js .is-now .vi-svg, html.js .is-now .vi-svg *, html.js .is-now :is(.vi-label, h3, p, .link) { transition: none !important; }

}

/* ================================================================ interactions
   Alive under the hand, never busy. Hovers 200 to 320ms, on the same ease as the arrivals. The icons' float is in
   css/value-icons.css, the bag card, notes, photographs and sign-up in css/style.css. Photograph and card hovers use
   `transform`, which arrivals never touch (they use translate and scale), and wait for .is-done. */

/* page to page: a soft cross-fade instead of a white flash (a browser without it just loads) */
@view-transition { navigation: auto; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 280ms; animation-timing-function: ease; }
@media (prefers-reduced-motion: reduce) { @view-transition { navigation: none; } }

/* a button's words: js/motion.js still wraps them (.roll, two equal halves, so app.js can change the words in one
   place), but since 9 Nov they no longer roll: the words stay still and the button's stitch answers the hand
   (css/style.css, .btn::before). Only the first half shows. */
.roll { position: relative; display: block; line-height: 1.7; }
.roll > span { display: block; }
.roll > span + span { display: none; }

/* the cart count bumps when a bag goes in (app.js adds .is-bump for 600ms) */
[data-cart-count] { display: inline-block; }
@keyframes rw-bump { 0% { transform: none; } 35% { transform: scale(1.3); } 100% { transform: none; } }
@media (prefers-reduced-motion: no-preference) {
  [data-cart-count].is-bump { animation: rw-bump 600ms var(--ease); }
}
