/* ============================================================
   Nicety Machinery - shared motion layer. Restrained motion only:
   short opacity/transform transitions, no parallax, no scroll-jacking,
   no autoplay, no carousel. Hooks emitted by the PHP templates (fixed):
     data-nz-reveal        fade + rise; ="fade" behaves the same,
                           ="line" draws an eyebrow's ::before rule
     data-nz-reveal-from   "left" | "right" (default: below)
     data-nz-reveal-group  JS staggers its direct children
     data-nz-arrow         slides 3px inside a hovered/focused control
   Per-element values from PHP: --nz-nudge (offset), --nz-delay (stagger).
   The hidden state applies only while <html> carries .nz-motion, a class
   site-motion.js adds in the head: with JS off nothing is ever hidden.
   ============================================================ */

/* --- Reveal: hidden state. Never applied to the "line" variant, whose
   eyebrow text stays legible while only its green rule is drawn. --- */
html.nz-motion [data-nz-reveal]:not([data-nz-reveal="line"]):not(.is-in) {
  opacity: 0;
  transform: translateY(var(--nz-nudge, 14px));
}

/* Direction variants: a sideways nudge instead of the default below. */
html.nz-motion [data-nz-reveal][data-nz-reveal-from="right"]:not(.is-in):not([data-nz-reveal="line"]) {
  transform: translateX(var(--nz-nudge, 14px));
}
html.nz-motion [data-nz-reveal][data-nz-reveal-from="left"]:not(.is-in):not([data-nz-reveal="line"]) {
  transform: translateX(calc(-1 * var(--nz-nudge, 14px)));
}

/* --- Reveal: transition (~540ms, soft ease-out) and revealed state.
   The element returns to opacity 1 / transform none once .is-in is set,
   delayed by the stagger the script writes into --nz-delay. -------- */
html.nz-motion [data-nz-reveal]:not([data-nz-reveal="line"]) {
  transition:
    opacity 540ms cubic-bezier(0.22, 0.61, 0.36, 1) var(--nz-delay, 0ms),
    transform 540ms cubic-bezier(0.22, 0.61, 0.36, 1) var(--nz-delay, 0ms);
}

html.nz-motion [data-nz-reveal].is-in {
  opacity: 1;
  transform: none;
}

/* --- Reveal variant "line": an eyebrow label whose 48px x 3px green rule
   (see .eyebrow::before in site.css) grows from 0 to 48px over ~420ms.
   The label itself never fades, so the text is readable throughout. --- */
html.nz-motion [data-nz-reveal="line"]::before {
  flex: none;
  width: 0;
  height: 3px;
  content: "";
  background: var(--green);
  transition: width 420ms cubic-bezier(0.22, 0.61, 0.36, 1) var(--nz-delay, 0ms);
}

html.nz-motion [data-nz-reveal="line"].is-in::before {
  width: 48px;
}

/* --- Hover affordance: an arrow sitting inside a link or a button slides
   3px in the reading direction over 180ms. It is at rest otherwise:
   no scale, no colour change, and it is not tied to the reveal layer. --- */
[data-nz-arrow] {
  display: inline-block;
  transition: transform 180ms ease;
}

a:hover [data-nz-arrow],
a:focus-visible [data-nz-arrow],
button:hover [data-nz-arrow],
button:focus-visible [data-nz-arrow] {
  transform: translateX(3px);
}

/* --- Reduced motion: the page is readable with no entrance animation at
   all, even if another stylesheet loads later and overrides the rules
   above. Reveal targets are forced visible, the eyebrow rule is restored
   to its full width, and the arrow slide is disabled. ---------------- */
@media (prefers-reduced-motion: reduce) {
  html.nz-motion [data-nz-reveal],
  html.nz-motion [data-nz-reveal].is-in {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  html.nz-motion [data-nz-reveal="line"]::before {
    width: 48px !important;
    transition: none !important;
  }

  [data-nz-arrow],
  a:hover [data-nz-arrow],
  a:focus-visible [data-nz-arrow],
  button:hover [data-nz-arrow],
  button:focus-visible [data-nz-arrow] {
    transform: none !important;
    transition: none !important;
  }
}
