/* motion.css: scroll and load motion for the home page (revamp, 2026-10-14).
 *
 * Progressive enhancement. Every rule is scoped under `html.motion`, a class an inline script in <head> sets only when the browser has
 * IntersectionObserver AND the visitor has not asked for reduced motion; if motion.js has not initialised within 4 s the class is removed
 * again, so content can never stay hidden. Only transform, opacity and clip-path are animated, so nothing here can move the layout.
 *
 * Lessons kept from the first motion pass (docs/design/BRIEF.md): the hero headline and intro paragraph are never faded (the paragraph is
 * a Largest Contentful Paint candidate: they rise by transform only); the hidden state has zero specificity so `.is-in` always wins;
 * whatever holds keyboard focus is always shown.
 *
 * The page's motion, in four parts (taste skill, step 9):
 *   1. The signature: the hero stage opens like a shutter while the screen inside settles from a slight scale.
 *   2. A different entrance for the parts of each section (rise, open, wipe, drop, grow), staggered 70ms.
 *   3. Feedback under the hand: buttons, tabs, tiles, the FAQ.
 *   4. One moving picture: the hero screen and the showcase screen drift slowly as you scroll (where supported).
 *   And the live thing: "Watch it follow the imam" animates the four Congregation Mode moments.
 */

/* ── 1. Hero on load ─────────────────────────────────────────────────────────────────────────── */
@keyframes mRise   { from { opacity: 0; transform: translate3d(0, 20px, 0); } to { opacity: 1; transform: none; } }
@keyframes mRiseT  { from { transform: translate3d(0, 18px, 0); } to { transform: none; } }          /* transform only: stays visible from the first paint */
@keyframes mShutter{ from { clip-path: inset(100% 0 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes mSettle { from { transform: scale(1.12); } to { transform: none; } }

html.motion .hero h1         { animation: mRiseT .8s var(--ease-out) .05s both; }
html.motion .hero .sub       { animation: mRiseT .8s var(--ease-out) .10s both; }
html.motion .hero #join      { animation: mRise  .7s var(--ease-out) .16s both; }
html.motion .hero .hero-link { animation: mRise  .7s var(--ease-out) .22s both; }
html.motion .hero__stage     { animation: mShutter .85s var(--ease-in-out) 0s both; }   /* the image is the Largest Contentful Paint: the shutter is kept short */
html.motion .hero__shot img  { animation: mSettle 1.3s var(--ease-soft) 0s both; }
/* inner pages: the band's title and lead rise by transform only (never faded: the lead can be the Largest Contentful Paint) */
html.motion .page-head h1     { animation: mRiseT .8s var(--ease-out) .05s both; }
html.motion .page-head .lede  { animation: mRiseT .8s var(--ease-out) .10s both; }
html.motion .live-actions     { animation: mRise  .7s var(--ease-out) .16s both; }

/* ── 2. Reveal on scroll: a different manner per section (motion.js sets data-reveal) ───────── */
html.motion :where([data-reveal]) {
  transition: opacity .55s var(--ease-out) var(--d, 0ms), transform .7s var(--ease-out) var(--d, 0ms), clip-path .75s var(--ease-in-out) var(--d, 0ms);
}
html.motion :where([data-reveal="rise"])   { opacity: 0; transform: translate3d(0, 26px, 0); }
html.motion :where([data-reveal="up"])     { opacity: 0; transform: translate3d(0, 54px, 0); }
html.motion :where([data-reveal="drop"])   { opacity: 0; transform: translate3d(0, -14px, 0); }
html.motion :where([data-reveal="open"])   { clip-path: inset(0 0 100% 0); }
html.motion :where([data-reveal="wipe-l"]) { clip-path: inset(0 100% 0 0); }
html.motion :where([data-reveal="wipe-r"]) { clip-path: inset(0 0 0 100%); }
html.motion :where([data-reveal="grow"])   { transform: scaleY(.02); transform-origin: bottom; }
/* the showcase screen settles from a slight scale as its field opens (one reveal, driven by the field) */
html.motion :where(.showcase__media[data-reveal]) .showcase__shot img { transform: scale(1.1); transition: transform 1.4s var(--ease-soft) var(--d, 0ms); }

html.motion [data-reveal].is-in { opacity: 1; transform: none; }
/* only the clip reveals reset the clip: elements that carry their own clip-path (the FAQ index-card tabs) keep it */
html.motion :is([data-reveal="open"], [data-reveal="wipe-l"], [data-reveal="wipe-r"]).is-in { clip-path: inset(0 0 0 0); }
html.motion .showcase__media[data-reveal].is-in .showcase__shot img { transform: none; }
/* Keyboard: whatever holds focus is always shown, even if it has not been scrolled far enough into view to be revealed. */
html.motion [data-reveal]:focus-within { opacity: 1; transform: none; }
html.motion :is([data-reveal="open"], [data-reveal="wipe-l"], [data-reveal="wipe-r"]):focus-within { clip-path: inset(0 0 0 0); }

/* ── 3. Feedback under the hand ─────────────────────────────────────────────────────────────── */
@media (hover: hover) and (pointer: fine) {
  /* the lift uses the separate `translate` property, so a padded image keeps its own centring transform and a full-width one only rises */
  html.motion .tile__media img { transition: translate .9s var(--ease-soft); }
  html.motion .tile:hover .tile__media img { translate: 0 -6px; }
}
@supports selector(::details-content) {
  html.motion .card { interpolate-size: allow-keywords; }
  html.motion .card::details-content { block-size: 0; overflow: clip; transition: block-size .4s var(--ease-out), content-visibility .4s allow-discrete; }
  html.motion .card[open]::details-content { block-size: auto; }
}

/* ── 4. One moving picture: slow drift while scrolling (Chrome 115+, Safari 26+) ────────────── */
@supports (animation-timeline: scroll()) {
  @keyframes mDriftA { to { scale: 1.07; } }
  @keyframes mDriftB { from { scale: 1; } to { scale: 1.06; } }
  html.motion .hero__shot img { transform-origin: 50% 100%; animation: mSettle 1.3s var(--ease-soft) 0s both, mDriftA linear both; animation-timeline: auto, scroll(root); animation-range: normal, 0 90vh; }
  html.motion .showcase__shot img { animation: mDriftB linear both; animation-timeline: view(); animation-range: entry 0% exit 100%; }
}

/* ── The live thing: the four Congregation Mode moments ─────────────────────────────────────── */
@keyframes cmBar  { from { transform: scaleY(.45); } to { transform: scaleY(1.25); } }
@keyframes cmText { from { opacity: 0; transform: translate3d(0, 8px, 0); } to { opacity: 1; transform: none; } }
html.motion .moment.is-now .cm__pulse span { animation: cmBar .55s ease-in-out infinite alternate; transform-origin: center; }
html.motion .moment.is-now .cm__pulse span:nth-child(2) { animation-delay: .09s; }
html.motion .moment.is-now .cm__pulse span:nth-child(3) { animation-delay: .18s; }
html.motion .moment.is-now .cm__pulse span:nth-child(4) { animation-delay: .27s; }
html.motion .moment.is-now .cm__pulse span:nth-child(5) { animation-delay: .36s; }
html.motion .moment.is-now :is(.cm__ar, .cm__en, .cm__found, .cm__end, .cm__endtext) { animation: cmText .8s var(--ease-out) both; }
html.motion .moment.is-now .cm__en { animation-delay: .35s; }
html.motion .moment.is-now .cm__endtext { animation-delay: .35s; }

/* Never leave content hidden on paper or in a PDF: undo only what motion itself sets (the hidden states and the animations), not the
   transforms and clip-paths that are part of the layout (the hero screen's centring, the arch shapes, the FAQ card tabs). */
@media print {
  html.motion [data-reveal] { opacity: 1 !important; transform: none !important; }
  html.motion :is([data-reveal="open"], [data-reveal="wipe-l"], [data-reveal="wipe-r"]) { clip-path: none !important; }
  html.motion .showcase__shot img { transform: none !important; }
  html.motion * { animation: none !important; }
}
