/*
 * Auspicious Journeys website motion (F4, SPEC 6): the start and end states for motion.js.
 * Every hidden start state sits under html.mo, which motion.js adds only after it has marked what is already on screen,
 * so the page is complete with JavaScript off, before the late scripts load, and under reduced motion.
 *
 *   data-reveal="up | lines | image | draw | fade"   data-reveal-group on a parent   data-delay="ms"
 *   data-speed="-0.15 ... 0.3" (parallax, --py)       .mo-frame around a parallax image
 *   data-magnetic (fine pointers)                     data-preview on index rows
 * motion.js sets --rd (delay), --ri (index in a group), --li (line index), --py, --stage-p, --mx, --my.
 */
:root {
  --mo-ease: var(--ease-out, cubic-bezier(.16, 1, .3, 1));
  --mo-ease-io: var(--ease-in-out, cubic-bezier(.65, 0, .35, 1));
  --mo-ease-mask: var(--ease-mask, cubic-bezier(.77, 0, .18, 1));
  --mo-stagger: var(--stagger, 80ms);
}

/* ---------- Lenis (1.1.20 stylesheet, plus no CSS smooth scrolling while Lenis runs) ---------- */
html.lenis, html.lenis body { height: auto; }
html.lenis { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: clip; }
.lenis.lenis-smooth iframe { pointer-events: none; }

/* ---------- up: rises 28px and fades in, 900ms ---------- */
html.mo [data-reveal="up"]:not(.is-in) { opacity: 0; translate: 0 calc(var(--py, 0px) + 28px); }
html.mo [data-reveal="up"].is-in:not(.no-anim):not(.is-done) {
  transition: opacity 900ms var(--mo-ease) var(--rd, 0ms), translate 900ms var(--mo-ease) var(--rd, 0ms);
}

/* ---------- fade: opacity only, 800ms ---------- */
html.mo [data-reveal="fade"]:not(.is-in) { opacity: 0; }
html.mo [data-reveal="fade"].is-in:not(.no-anim):not(.is-done) { transition: opacity 800ms var(--mo-ease) var(--rd, 0ms); }

/* ---------- lines: every word sits in a mask; the words of one line rise together, 1000ms, 80ms per line ---------- */
html.mo [data-reveal="lines"]:not(.is-split):not(.is-in) { opacity: 0; }
.mo-w {
  display: inline-block;
  vertical-align: top;
  overflow: clip;
  /* room for descenders, accents and italic overhang; the negative margins keep the line box unchanged */
  padding: 0.06em 0.04em 0.14em;
  margin: -0.06em -0.04em -0.14em;
}
.mo-w > span { display: inline-block; }
html.mo [data-reveal="lines"].is-split:not(.is-in) :is(.mo-w, .w) > span { translate: 0 calc(105% + 0.2em); }
html.mo [data-reveal="lines"].is-in:not(.no-anim):not(.is-done) :is(.mo-w, .w) > span {
  transition: translate 1000ms var(--mo-ease-mask) calc(var(--rd, 0ms) + var(--li, 0) * var(--mo-stagger));
}

/* ---------- image (reference analysis 5.6): portrait and square frames open through a centred window (inset 20% to 0,
 * the photo 1.1 to 1, 900ms); wide bands (motion.js adds .mo-wide when the frame is 1.4 times wider than tall) wipe
 * open upwards in 1000ms, the photo settling from 1.1 in 1200ms. Both on the mask curve. ---------- */
html.mo [data-reveal="image"]:not(.is-in) { clip-path: inset(20%); }
html.mo [data-reveal="image"].mo-wide:not(.is-in) { clip-path: inset(100% 0 0 0); }
html.mo [data-reveal="image"]:not(.is-in) img { scale: 1.1; }
html.mo [data-reveal="image"].is-in:not(.no-anim):not(.is-done) { transition: clip-path 900ms var(--mo-ease-mask) var(--rd, 0ms); }
html.mo [data-reveal="image"].is-in:not(.no-anim):not(.is-done) img { transition: scale 900ms var(--mo-ease-mask) var(--rd, 0ms); }
html.mo [data-reveal="image"].mo-wide.is-in:not(.no-anim):not(.is-done) { transition-duration: 1000ms; }
html.mo [data-reveal="image"].mo-wide.is-in:not(.no-anim):not(.is-done) img { transition: scale 1200ms var(--mo-ease) var(--rd, 0ms); }

/* ---------- draw: a hairline grows from the left (data-draw="y": from the top), an SVG path strokes in, 1100ms ---------- */
html.mo [data-reveal="draw"]:not(.is-in):not(svg, svg *) { scale: 0 1; transform-origin: 0 50%; }
html.mo [data-reveal="draw"][data-draw="y"]:not(.is-in):not(svg, svg *) { scale: 1 0; transform-origin: 50% 0; }
html.mo [data-reveal="draw"].is-in:not(.no-anim):not(.is-done):not(svg, svg *) { transition: scale 1100ms var(--mo-ease) var(--rd, 0ms); }
html.mo .mo-path { stroke-dasharray: 1 1; }
html.mo [data-reveal="draw"]:not(.is-in) .mo-path, html.mo .mo-path[data-reveal="draw"]:not(.is-in) { stroke-dashoffset: 1; }
html.mo [data-reveal="draw"].is-in:not(.no-anim) .mo-path, html.mo .mo-path[data-reveal="draw"].is-in:not(.no-anim) {
  transition: stroke-dashoffset 1100ms var(--mo-ease-io) var(--rd, 0ms);
}

/* ---------- route maps (BLOCKS.routemap): the route draws and the pins land once the map is in view ---------- */
html.mo .routemap .rm-route { stroke-dasharray: 1 1; }
html.mo .routemap:not(.is-drawn) .rm-route { stroke-dashoffset: 1; }
html.mo .routemap.is-drawn:not(.no-anim) .rm-route { transition: stroke-dashoffset 1800ms var(--mo-ease-io) 150ms; }
html.mo .routemap:not(.is-drawn) .rm-pin { opacity: 0; scale: 0.6; }
html.mo .routemap.is-drawn:not(.no-anim) .rm-pin { transition: opacity 600ms var(--mo-ease) 900ms, scale 600ms var(--mo-ease) 900ms; }

/* ---------- parallax: motion.js writes --py on [data-speed]; a frame keeps a taller photo's edges hidden (15% overscan
 * top and bottom: a 600px frame at speed -0.1 drifts up to about 70px, more than the old 7.5%) ---------- */
html.mo [data-speed] { translate: 0 var(--py, 0px); }
html.mo-fine [data-speed] { will-change: translate; }
.mo-frame { position: relative; overflow: clip; }
.mo-frame > img[data-speed], .mo-frame > picture[data-speed] {
  position: absolute; left: 0; top: -15%; width: 100%; height: 130%; max-width: none; object-fit: cover; object-position: var(--pos, 50% 50%);
}
.mo-frame > picture[data-speed] img { width: 100%; height: 100%; object-fit: cover; object-position: inherit; }

/* ---------- magnetic (fine pointers): motion.js eases --mx/--my towards the pointer and back ---------- */
html.mo-fine [data-magnetic] { translate: var(--mx, 0px) var(--my, 0px); }

/* ---------- image preview on index rows (fine pointers) ---------- */
.mo-preview {
  position: fixed; left: 0; top: 0; z-index: 45; width: 280px; height: 200px; overflow: clip;
  pointer-events: none; opacity: 0; scale: 0.9; background: var(--green-raised);
  transition: opacity 300ms var(--mo-ease), scale 300ms var(--mo-ease);
}
.mo-preview.is-on { opacity: 1; scale: 1; }
.mo-preview img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* ---------- reduced motion and print: nothing waits, nothing drifts (motion.js also never adds html.mo) ---------- */
@media (prefers-reduced-motion: reduce) {
  html.mo [data-reveal], html.mo [data-reveal] img, html.mo [data-reveal] :is(.mo-w, .w) > span {
    opacity: 1 !important; translate: none !important; scale: none !important; clip-path: none !important; transition: none !important;
  }
  html.mo .mo-path, html.mo .routemap .rm-route { stroke-dashoffset: 0 !important; transition: none !important; }
  html.mo .routemap .rm-pin { opacity: 1 !important; scale: none !important; transition: none !important; }
  [data-speed], [data-magnetic] { translate: none !important; }
  .mo-preview { display: none; }
}
@media print {
  html.mo [data-reveal], html.mo [data-reveal] img, html.mo [data-reveal] :is(.mo-w, .w) > span { opacity: 1 !important; translate: none !important; scale: none !important; clip-path: none !important; }
  .mo-preview { display: none; }
}
