/* ============================================================
   SYNODEV — Motion
   CSS handles the cheap states; GSAP handles the choreography.
   ============================================================ */

/* Pre-JS: content is visible and complete (progressive enhancement).
   JS opts into the animated state by adding .js to <html>. */
.reveal,
[data-mask] .line > span,
[data-reveal] {
  will-change: transform, opacity;
}

/* Mask Rise — a single line of a heading --------------------- */
[data-mask] .line { display: block; overflow: hidden; padding-bottom: 0.06em; }
[data-mask] .line > span { display: block; }

/* The no-JS / reduced-motion baseline: fully visible. -------- */
html:not(.js) [data-mask] .line > span,
html.reduced-motion [data-mask] .line > span,
html:not(.js) [data-reveal],
html.reduced-motion [data-reveal] {
  transform: none !important;
  opacity: 1 !important;
}

/* Fade-up utility -------------------------------------------- */
.fade-up {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity var(--dur-3) var(--ease-out), transform var(--dur-3) var(--ease-out);
}
.fade-up.is-inview { opacity: 1; transform: none; }

.fade-in { opacity: 0; transition: opacity var(--dur-3) var(--ease-out); }
.fade-in.is-inview { opacity: 1; }

/* Node draw-in for SVG visuals ------------------------------- */
.draw path,
.draw line,
.draw circle {
  stroke-dasharray: var(--len, 400);
  stroke-dashoffset: var(--len, 400);
  transition: stroke-dashoffset 1.6s var(--ease-inout);
}
.draw.is-inview path,
.draw.is-inview line,
.draw.is-inview circle { stroke-dashoffset: 0; }

/* Sticky/scroll-driven elements are hidden until JS wires them,
   but must remain fully readable without JS. */
html.js [data-scrub] { opacity: 1; }

/* Focus containment while the mobile menu is open ------------- */
body.nav-open { overflow: hidden; }

/* Cross-document View Transitions (progressive enhancement).
   The JS overlay is the fallback where this is unsupported. --- */
@view-transition { navigation: auto; }
::view-transition-old(root) { animation: vt-out 0.4s var(--ease-inout) both; }
::view-transition-new(root) { animation: vt-in 0.5s var(--ease-inout) both; }
@keyframes vt-out { to { opacity: 0; transform: translateY(-1.5%); } }
@keyframes vt-in { from { opacity: 0; transform: translateY(1.5%); } }
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) { animation: none; }
}

/* Print — show everything, drop the chrome. ------------------ */
@media print {
  .relay, .cursor, .site-header, .mobile-menu, .preloader, .hero__signal { display: none !important; }
  [data-reveal], [data-mask] .line > span { opacity: 1 !important; transform: none !important; }
  .section { padding-block: 2.5rem; }
  a[href]::after { content: ""; }
}

/* Phone overrides — last in cascade so they win. -------------- */
@media (max-width: 640px) {
  .eyebrow { font-size: 0.66rem; letter-spacing: 0.1em; }
  .eyebrow::before { width: 1em; }
  .hero__title { max-width: 100%; }
  .hero__lead { font-size: 0.95rem; }
  .hero__sub { gap: var(--space-md); }
}
