/* ══════════════════════════════════════════════════
   Motion layer — bidirectional, scroll-linked
   Every effect is driven by a per-element progress value --p (0 → 1) that JS
   recomputes from scroll position, so animations play forward on the way down
   and reverse on the way back up.
   ══════════════════════════════════════════════════ */

/* inherits:true is required — the blur is applied to the child <img>, which
   must receive --p from its .fx-img parent. With inherits:false it always read
   the initial value and stayed permanently blurred. */
@property --p  { syntax: '<number>'; initial-value: 1;   inherits: true; }
@property --px { syntax: '<length>'; initial-value: 0px; inherits: true; }

/* cross-document navigation */
@view-transition { navigation: auto; }
@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root) { animation: vtOut .26s cubic-bezier(.4,0,1,1) both; }
  ::view-transition-new(root) { animation: vtIn  .40s cubic-bezier(0,0,.2,1) both; }
}
@keyframes vtOut { to   { opacity:0; transform:translateY(-8px) } }
@keyframes vtIn  { from { opacity:0; transform:translateY(16px) } }

/* Everything below is gated on `motion-ready`, which JS adds at startup.
   If the script never runs, no element is ever hidden. */
@media (prefers-reduced-motion: no-preference) {

  /* ── 1. line-mask text reveal ── */
  .motion-ready .fx-line { display:block; overflow:hidden; padding-bottom:.04em }
  .motion-ready .fx-line > .fx-in {
    transition: --p .22s linear, --px .22s linear;
    display:block;
    transform: translateY(calc((1 - var(--p)) * 112%));
    opacity: calc(.15 + var(--p) * .85);
  }

  /* ── 2. focus-pull on photographs (blur + scale + drift) ── */
  .motion-ready .fx-img { overflow:hidden }
  .motion-ready .fx-img img {
    transition: --p .22s linear, --px .22s linear;
    filter: blur(calc((1 - var(--p)) * 8px));
    transform: translate3d(0, var(--px, 0px), 0) scale(calc(1.05 - var(--p) * .05));
    will-change: transform, filter;
  }

  /* ── 3. swivel — cards and thumbnails only, never body text ── */
  .motion-ready .fx-card {
    transition: --p .22s linear, --px .22s linear;
    opacity: calc(.08 + var(--p) * .92);
    transform:
      perspective(1200px)
      rotateX(calc((1 - var(--p)) * 9deg))
      translateY(calc((1 - var(--p)) * 30px))
      scale(calc(.97 + var(--p) * .03));
    transform-origin: 50% 100%;
    will-change: transform, opacity;
  }

  /* ── plain fade-rise for the rest ── */
  .motion-ready .fx-fade {
    transition: --p .22s linear, --px .22s linear;
    opacity: calc(.06 + var(--p) * .94);
    transform: translateY(calc((1 - var(--p)) * 34px));
  }
}

@media (prefers-reduced-motion: reduce) {
  .fx-line > .fx-in, .fx-card, .fx-fade, .fx-img img { opacity:1; transform:none; filter:none }
}

/* ── scroll progress ── */
.mo-bar { position:fixed; inset:0 0 auto; height:2px; z-index:120; pointer-events:none }
.mo-bar i { display:block; height:100%; width:0; background:var(--primary,#ff791b) }

/* ── back to top ── */
.mo-top {
  position:fixed; right:clamp(1rem,3vw,2.2rem); bottom:clamp(1rem,3vw,2.2rem);
  z-index:130; width:52px; height:52px; border-radius:50%;
  display:grid; place-items:center; cursor:pointer;
  background:var(--primary,#ff791b); color:#101010; border:0;
  box-shadow:0 10px 30px -8px rgba(0,0,0,.6);
  opacity:0; transform:translateY(14px) scale(.9); pointer-events:none;
  transition:opacity .4s ease, transform .4s cubic-bezier(.2,.7,.2,1), filter .25s;
}
.mo-top.on { opacity:1; transform:none; pointer-events:auto }
.mo-top:hover { filter:brightness(1.12) }
.mo-top:focus-visible { outline:2px solid #fff; outline-offset:3px }
.mo-top svg { width:20px; height:20px; display:block }
