/* Veya Digital — motion layer. Homepage only.
   Additive to styles.css: nothing here is required for the page to render
   correctly if assets/js/motion.js never runs (GSAP blocked/offline/etc). */

/* motion.js writes --py on four whole <section> elements on every scroll
   frame. Declared like this it is a *non-inherited* property, so the write
   dirties only the section itself and its ::before/::after — not the entire
   subtree underneath it, which is what made the parallax cost a full style
   recalc per frame. Engines without @property simply ignore this block and
   the parallax still works, just at the old cost. */
@property --py {
  syntax: "<length>";
  inherits: false;
  initial-value: 0px;
}

.scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 3px;
  background: var(--acid);
  transform-origin: left center;
  transform: scaleX(0);
  z-index: 70;
  pointer-events: none;
  will-change: transform;
}

.site-header {
  will-change: transform;
}
/* The compact header is `position: fixed`, sits above the full-page
   scroll for as long as nav-compact is applied (from 40px down to back
   near the top), and is also transform-animated (motion.js hides/shows
   it on scroll direction). A backdrop-filter on a fixed element forces
   the browser to re-blur everything scrolling behind it on every single
   frame — not just during the hide/show tween, but for the entire time
   it's visible — which reads as scroll jank on desktop, not just a
   one-off animation cost. Desktop originally kept the blur on the
   (wrong) assumption it had headroom mobile didn't; it doesn't. Solid
   everywhere: at 0.72 alpha over blur the two were already almost
   indistinguishable, and the solid costs nothing per frame. */
.site-header.nav-compact {
  background: #121214;
  box-shadow: 0 1px 0 rgba(242, 240, 235, 0.08);
  transition: background-color 0.4s ease, box-shadow 0.4s ease;
}

/* Kinetic type: line/word masks. Default state is fully visible —
   motion.js sets the animated-from state at runtime so a JS/GSAP
   failure never hides content. */
.line-mask {
  display: block;
  overflow: hidden;
}
.line-inner {
  display: block;
  will-change: transform;
}
.word-mask {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
}
.word-inner {
  display: inline-block;
  will-change: transform;
}

/* Typewriter caret for the hero headline (see typeReveal in motion.js).
   Positioned against the heading itself, so the heading needs to be the
   caret's offset parent. Sized in `em` so it tracks the heading's fluid
   clamp() font size at every breakpoint without a second set of
   breakpoints here. */
.hero h1 {
  position: relative;
}
.type-caret {
  position: absolute;
  left: 0;
  top: 0;
  width: 0.055em;
  background: var(--acid);
  pointer-events: none;
  /* Placed per character from JS by translating from the heading's own
     top-left. Driven by `transform` rather than left/top so each hop is a
     compositor move, and deliberately not transitioned — easing it would
     make the caret lag behind the text it is supposed to be leading. */
  will-change: transform;
}
/* Solid while typing, blinking once the line is finished — the same
   distinction a real text cursor makes between moving and idle. */
.type-caret.is-done {
  animation: caret-blink 0.9s steps(1) infinite;
}
@keyframes caret-blink {
  0%, 49% {
    opacity: 1;
  }
  50%, 100% {
    opacity: 0;
  }
}

.magnetic {
  display: inline-flex;
}

/* Approach principles are plain .reveal/.reveal-right blocks (see
   MOTION.md) — no pin, no scrub. will-change stays since app.js still
   animates opacity/transform on entry. */
.approach .principles > div {
  will-change: transform, opacity;
}

.case-visual {
  will-change: transform;
}

/* Restrained scroll parallax on the decorative V-mark watermarks.
   motion.js writes --py; these compose it with each section's own
   existing centering/offset transform. */
.hero::after {
  transform: translate3d(0, var(--py, 0px), 0);
}
.intro::before {
  transform: translate3d(0, var(--py, 0px), 0);
}
.approach::before {
  transform: translate3d(0, var(--py, 0px), 0);
}
.statement::before {
  transform: translate(-50%, calc(-50% + var(--py, 0px)));
}

@media (prefers-reduced-motion: reduce) {
  .scroll-progress {
    display: none;
  }
  .type-caret {
    display: none;
  }
  .line-inner,
  .word-inner {
    transform: none !important;
  }
}
