/* ==========================================================================
   MAROSI — marosilabs.com · v4 "LOUD QUIET"
   White/black/grey UI floating over the three.js vault flythrough.
   Same quiet palette, award-site confidence: Inter Tight display type at
   8-10vw (Aeonik-ready stacks), bold pills with label-roll hovers, giant
   closing wordmark. Static document layout is the default; html.film
   (JS + motion OK) turns sections into pinned, scroll-scrubbed stages.
   ========================================================================== */

/* ---------- Tokens ---------- */
:root {
  --bg: #f5f6f8;
  --fg: #0b0d10;

  /* neutral grey ramp — the only "colors" in the chrome */
  --grey-700: #3f444b;  /* secondary text — AA on the halls */
  --grey-600: #565d66;  /* muted text */
  --grey-400: #8a9098;
  --grey-300: #b4b9c0;

  --hairline: rgba(11, 13, 16, 0.08);
  --hairline-strong: rgba(11, 13, 16, 0.16);
  --panel: rgba(255, 255, 255, 0.58);
  --panel-hover: rgba(255, 255, 255, 0.74);
  --panel-border: rgba(11, 13, 16, 0.08);
  --nav-bg: rgba(245, 246, 248, 0.72);
  --btn-hover: #2a2e34;
  --shadow-panel: 0 1px 2px rgba(11, 13, 16, 0.05), 0 12px 32px rgba(11, 13, 16, 0.07);

  /* menu card stack: near-opaque paper cards */
  --menu-card: rgba(252, 253, 254, 0.92);

  /* Aeonik leads both stacks — drop licensed @font-face files in and it
     takes over; Inter (text) / Inter Tight (display) are the live webfonts */
  --font-sans: 'Aeonik', 'Inter', system-ui, -apple-system, 'Helvetica Neue', sans-serif;
  --font-display: 'Aeonik', 'Inter Tight', 'Inter', system-ui, sans-serif;
  --font-mono: 'Geist Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-io: cubic-bezier(0.65, 0, 0.35, 1);
  /* the menu's voice: fast launch, long soft landing (card toss + rolls) */
  --ease-menu: cubic-bezier(0.4, 0, 0.1, 1);

  /* ---- the grid: 12 columns, one shared outer margin, one gap unit.
     Every block on every page keys off these three — the margin is the
     page's left/right datum (nav, hero, sections, footer all sit on it),
     the gap is the only horizontal spacing unit inside the grid. ---- */
  --grid-margin: clamp(28px, 7vw, 140px);
  --col-gap: clamp(16px, 1.8vw, 32px);
  --gutter: var(--grid-margin); /* legacy alias — everything already keys off it */

  --nav-h: 84px;
  --nav-top: clamp(10px, 2vh, 24px);
  --container: 1520px;
  --edge-y: clamp(28px, 4.5vh, 52px);
}

/* the one inversion: the dark capabilities night track mid-film */
html.inverted {
  --bg: #08090b;
  --fg: #f4f5f7;
  --grey-700: #aab0b8;
  --grey-600: #9ba1a9;
  --grey-400: #6a7078;
  --grey-300: #4a5058;
  --hairline: rgba(244, 245, 247, 0.1);
  --hairline-strong: rgba(244, 245, 247, 0.2);
  --panel: rgba(12, 14, 17, 0.55);
  --panel-hover: rgba(12, 14, 17, 0.72);
  --panel-border: rgba(244, 245, 247, 0.1);
  --nav-bg: rgba(8, 9, 11, 0.6);
  --btn-hover: #d9dce1;
  --shadow-panel: 0 12px 32px rgba(0, 0, 0, 0.4);
  --menu-card: rgba(16, 18, 22, 0.92);
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-sans);
  font-size: 1.25rem;
  line-height: 1.6;
  letter-spacing: -0.01em;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
  min-height: 100svh;
  cursor: default;
  -webkit-user-select: none;
  user-select: none;
  /* the chrome flip rides inside the GL dusk (eclipse + iris dip) — a longer,
     eased fade sits in that envelope instead of snapping through it */
  transition: background-color 0.9s var(--ease-io), color 0.9s var(--ease-io);
}
img, svg, canvas { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; cursor: pointer; }
ul, ol { list-style: none; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
input, textarea { font: inherit; color: inherit; cursor: text; -webkit-user-select: text; user-select: text; }
sup { font-size: 0.42em; }
::selection { background: var(--fg); color: var(--bg); }

::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb { background: var(--grey-300); border-radius: 4px; }

/* js/scrollbar.js replaces the native bar with a Lusion-style overlay pill —
   it rides the film's damped scroll, fades out when idle, drags on fine
   pointers. The 8px native styling above stays as the no-JS fallback. */
html.csb { scrollbar-width: none; }
html.csb::-webkit-scrollbar { display: none; }

.csb-track {
  position: fixed; top: 6px; bottom: 6px; right: 0;
  width: 18px; z-index: 4000;
  opacity: 0; pointer-events: none;
  transition: opacity 0.5s var(--ease-out);
}
.csb-track.is-on { opacity: 1; }
.csb-track.csb-idle { display: none; }
/* touch keeps it as a pure indicator — the rail never intercepts a swipe */
@media (pointer: fine) { .csb-track.is-on { pointer-events: auto; } }

.csb-thumb {
  position: absolute; top: 0; right: 6px; width: 4px;
  border-radius: 999px;
  background: rgba(11, 13, 16, 0.34);
  background: color-mix(in srgb, var(--fg) 36%, transparent);
  transition: width 0.25s var(--ease-out), background-color 0.25s var(--ease-out);
  will-change: transform;
}
@media (pointer: fine) {
  .csb-track:hover .csb-thumb,
  .csb-track.is-dragging .csb-thumb {
    width: 7px;
    background: rgba(11, 13, 16, 0.55);
    background: color-mix(in srgb, var(--fg) 58%, transparent);
  }
}

:focus-visible { outline: 2px solid var(--fg); outline-offset: 2px; }

.skip-link {
  position: fixed; top: -60px; left: 16px; z-index: 5000;
  padding: 10px 18px; border-radius: 999px;
  background: var(--fg); color: var(--bg);
  font-size: 0.9375rem; font-weight: 600;
  transition: top 0.25s var(--ease-out);
}
.skip-link:focus { top: 16px; }

/* ---------- Utilities ---------- */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
/* microlabel — the only uppercase on the site */
.mono {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  word-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--grey-600);
}
/* weight accent for single emphasized words inside headlines — the word
   goes black (900) against the 700 line, nothing else changes */
.acc {
  font-style: normal;
  font-weight: 900;
}
.container { width: 100%; max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }
.container--narrow { max-width: 860px; }

/* every display voice speaks Inter Tight (or Aeonik when present) —
   body copy stays in Inter for text-size rendering */
.mega, .mega-s, .statement, .slide-title, .slide-index,
.proc-name, .manifesto p,
.menu-link, .menu-talk-row, .nav-burger, .brand, .btn {
  font-family: var(--font-display);
}

.mega {
  font-weight: 700;
  font-size: clamp(3.25rem, 8.5vw, 9rem);
  line-height: 1.0;
  letter-spacing: -0.03em;
  text-wrap: balance;
}
.mega-s {
  font-weight: 700;
  font-size: clamp(2.75rem, 6vw, 5.5rem);
  line-height: 1.03;
  letter-spacing: -0.026em;
  text-wrap: balance;
}

/* ---------- Brand (the MAROSI antelope mark + name) ---------- */
.brand {
  display: inline-flex; align-items: center; gap: 0.65em;
  font-weight: 700;
  font-size: 1.0625rem;
  letter-spacing: 0.05em;
  white-space: nowrap;
}
.brand [aria-hidden] { display: inline-flex; align-items: center; gap: 0.65em; }
.logo { width: 1.9em; height: 1.9em; object-fit: contain; }
.logo--light { display: none; }
html.inverted .logo--dark { display: none; }
html.inverted .logo--light { display: block; }

/* ---------- Buttons ---------- */
.btn {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  gap: 0.5em;
  height: 58px;
  padding: 0 34px;
  border-radius: 999px;
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: 0;
  white-space: nowrap;
  transition: background-color 0.35s var(--ease-out), border-color 0.35s var(--ease-out),
              color 0.35s var(--ease-out), transform 0.1s ease-out;
}
.btn:active { transform: scale(0.98); }
/* the arrow window: two stacked ↗ glyphs in a clipped 1em box — on hover the
   first exits up-right, its twin lands from down-left. One quiet, decisive move. */
.btn-arr {
  display: inline-grid; place-items: center;
  width: 1em; height: 1em;
  overflow: clip;
}
.btn-arr svg {
  grid-area: 1 / 1;
  width: 0.8em; height: 0.8em;
  fill: none; stroke: currentColor;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
  transition: transform 0.45s var(--ease-out);
}
.btn-arr svg:last-child { transform: translate(-150%, 150%); }
.btn:hover .btn-arr svg:first-child, .btn:focus-visible .btn-arr svg:first-child,
.cta-talk:hover .btn-arr svg:first-child, .cta-talk:focus-visible .btn-arr svg:first-child,
.menu-card--talk:hover .btn-arr svg:first-child, .menu-card--talk:focus-visible .btn-arr svg:first-child {
  transform: translate(150%, -150%);
}
.btn:hover .btn-arr svg:last-child, .btn:focus-visible .btn-arr svg:last-child,
.cta-talk:hover .btn-arr svg:last-child, .cta-talk:focus-visible .btn-arr svg:last-child,
.menu-card--talk:hover .btn-arr svg:last-child, .menu-card--talk:focus-visible .btn-arr svg:last-child {
  transform: translate(0, 0);
}
.btn--solid { background: var(--fg); color: var(--bg); }
.btn--solid:hover { background: var(--btn-hover); }
.btn--ghost {
  background: var(--panel);
  border: 1px solid var(--panel-border);
  color: var(--fg);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}
/* the ghost pill commits on hover: fills to full ink, text flips paper */
.btn--ghost:hover, .btn--ghost:focus-visible {
  background: var(--fg);
  border-color: var(--fg);
  color: var(--bg);
}

/* ---------- Nav — colorless, floating clear of the top edge ---------- */
.nav {
  position: fixed; top: var(--nav-top); left: 0; right: 0; z-index: 1000;
  height: var(--nav-h);
}
.nav-inner {
  height: 100%;
  max-width: var(--container);
  margin-inline: auto; padding-inline: var(--gutter);
  display: flex; align-items: center; justify-content: space-between; gap: 1.5rem;
}
/* the bar carries no surface — the brand floats directly over the scene */
.nav-brand {
  font-size: 1.32rem;
  font-weight: 700;
  letter-spacing: 0.055em;
  transition: opacity 0.45s var(--ease-out);
}
.nav-brand .logo { width: 2.35em; height: 2.35em; }
.nav-right { display: flex; align-items: center; gap: 1rem; }
.nav-cta {
  height: 52px; padding: 0 30px; font-size: 1.0625rem;
  /* restate the .btn transition + opacity so the end-of-page fade rides along */
  transition: background-color 0.35s var(--ease-out), border-color 0.35s var(--ease-out),
              color 0.35s var(--ease-out), transform 0.1s ease-out,
              opacity 0.45s var(--ease-out);
}
/* html.at-end (set by initNavEnd when the contact section arrives): the page's
   own Let's Talk owns the frame — the nav brand and CTA bow out until scroll-up */
html.at-end .nav-brand, html.at-end .nav-cta {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.45s var(--ease-out), visibility 0s linear 0.45s,
              transform 0.1s ease-out;
}
/* the menu button: a speaking pill. "Menu" rolls out, "Close" rolls in,
   and the two dots spin a quarter turn on hover and while open. */
.nav-burger {
  display: inline-flex; align-items: center; gap: 0.55em;
  height: 52px; padding: 0 22px 0 26px;
  border-radius: 999px;
  font-size: 1.0625rem; font-weight: 600;
  color: var(--fg);
  background: var(--panel);
  border: 1px solid var(--panel-border);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  transition: background-color 0.3s ease, border-color 0.3s ease,
              color 0.3s ease, transform 0.15s ease-out;
}
/* both words share one grid cell: the label keeps the wider word's width,
   so the pill never jumps when Menu swaps for Close */
.burger-label { display: inline-grid; justify-items: start; overflow: clip; line-height: 1.25; }
.burger-word {
  grid-area: 1 / 1;
  transition: transform 0.35s var(--ease-menu);
}
.burger-word--close { transform: translateY(115%); }
.nav-burger[aria-expanded="true"] .burger-word { transform: translateY(-115%); }
.nav-burger[aria-expanded="true"] .burger-word--close { transform: translateY(0); }
.burger-dots {
  position: relative; width: 1em; height: 1em;
  transition: transform 0.4s var(--ease-menu);
}
.burger-dots i {
  position: absolute; top: 50%; width: 0.29em; height: 0.29em; margin-top: -0.145em;
  border-radius: 50%; background: currentColor;
}
.burger-dots i:first-child { left: 0.04em; }
.burger-dots i:last-child { right: 0.04em; }
/* open state commits to full ink, same as the ghost pill next door */
.nav-burger[aria-expanded="true"] {
  background: var(--fg);
  border-color: var(--fg);
  color: var(--bg);
}
.nav-burger[aria-expanded="true"] .burger-dots { transform: rotate(90deg); }
/* hover-capable pointers only: touch taps would leave :hover stuck */
@media (hover: hover) {
  .nav-burger:hover {
    background: var(--panel-hover);
    border-color: var(--hairline-strong);
  }
  .nav-burger:hover .burger-dots { transform: rotate(90deg); }
  .nav-burger[aria-expanded="true"]:hover {
    background: var(--fg);
    border-color: var(--fg);
  }
}

/* ---------- Menu: a stack of cards tossed in under the nav ----------
   Desktop: an invisible click-catcher over the untouched page; the cards
   fly up from below with a slight rotation and settle straight, links card
   first, talk card behind it. Closing reverses the stagger. */
.menu {
  position: fixed; inset: 0; z-index: 900;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.5s var(--ease-menu), visibility 0s linear 0.6s;
}
.menu.is-open { opacity: 1; visibility: visible; transition-delay: 0s; }
.menu-cards {
  position: absolute;
  top: calc(var(--nav-top) + var(--nav-h) + 10px);
  right: var(--gutter);
  width: min(400px, calc(100vw - var(--gutter) * 2));
  display: flex; flex-direction: column; gap: 10px;
}
.menu-card {
  border-radius: 22px;
  background: var(--menu-card);
  border: 1px solid var(--panel-border);
  box-shadow: var(--shadow-panel);
  opacity: 0;
  transform: translate3d(0, 88px, 0) rotate(3.5deg);
  transition: transform 0.55s var(--ease-menu), opacity 0.4s ease-out;
  transition-delay: var(--close-d, 0s);
  will-change: transform;
}
.menu.is-open .menu-card {
  opacity: 1;
  transform: none;
  transition-delay: var(--open-d, 0s);
}
.menu-card--links { --open-d: 0.05s; --close-d: 0.12s; }
.menu-card--notes { --open-d: 0.09s; --close-d: 0.08s; transform: translate3d(0, 96px, 0) rotate(2.5deg); }
.menu-card--careers { --open-d: 0.13s; --close-d: 0.04s; transform: translate3d(0, 104px, 0) rotate(-2.5deg); }
.menu-card--talk { --open-d: 0.17s; --close-d: 0s; transform: translate3d(0, 120px, 0) rotate(-3.5deg); }

/* link rows: pill highlight scales in, text rolls up, arrow lands */
.menu-card--links { padding: 14px 8px; display: flex; flex-direction: column; }
.menu-link {
  position: relative;
  display: block;
  padding: 16px 26px;
  font-size: 1.5rem; font-weight: 600;
  line-height: 1.2; letter-spacing: -0.02em;
  color: var(--fg);
}
.menu-link-bg {
  position: absolute; inset: 0;
  border-radius: 999px;
  background: var(--fg);
  opacity: 0;
  transform: scale(0.85);
  transition: opacity 0.3s ease, transform 0.4s var(--ease-menu);
}
/* the roll window: word + clone share a clipped grid cell (see .burger-label);
   the padding/margin pair keeps descenders inside the clip */
.menu-link-inner {
  position: relative; display: inline-grid; vertical-align: top;
  overflow: clip;
  padding: 0.12em; margin: -0.12em;
}
.menu-link-text {
  grid-area: 1 / 1;
  transition: transform 0.4s var(--ease-menu);
}
.menu-link-text--clone { transform: translateY(115%); }
.menu-link-arr {
  position: absolute; right: 24px; top: 50%;
  width: 1em; height: 1em; margin-top: -0.5em;
  fill: none; stroke: currentColor;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
  transform: scale(0);
  transition: transform 0.2s var(--ease-menu);
}
.menu-link:hover .menu-link-bg, .menu-link:focus-visible .menu-link-bg { opacity: 0.06; transform: none; }
.menu-link:hover .menu-link-text, .menu-link:focus-visible .menu-link-text,
.menu-card--talk:hover .menu-link-text, .menu-card--talk:focus-visible .menu-link-text,
.menu-card--notes:hover .menu-link-text, .menu-card--notes:focus-visible .menu-link-text,
.menu-card--careers:hover .menu-link-text, .menu-card--careers:focus-visible .menu-link-text { transform: translateY(-115%); }
.menu-link:hover .menu-link-text--clone, .menu-link:focus-visible .menu-link-text--clone,
.menu-card--talk:hover .menu-link-text--clone, .menu-card--talk:focus-visible .menu-link-text--clone,
.menu-card--notes:hover .menu-link-text--clone, .menu-card--notes:focus-visible .menu-link-text--clone,
.menu-card--careers:hover .menu-link-text--clone, .menu-card--careers:focus-visible .menu-link-text--clone { transform: translateY(0); }
.menu-link:hover .menu-link-arr, .menu-link:focus-visible .menu-link-arr {
  transform: scale(1);
  transition-delay: 0.12s;
}
/* the ink pill needs more alpha to read on the dark night-track cards */
html.inverted .menu-link:hover .menu-link-bg, html.inverted .menu-link:focus-visible .menu-link-bg { opacity: 0.1; }

/* the page cards (field notes, careers): the talk card's shape in paper —
   page destinations, so they keep the card stock and carry the forward
   arrow, not the ↗ */
.menu-card--notes, .menu-card--careers {
  display: flex; flex-direction: column; gap: 2px;
  padding: 24px 28px;
}
.menu-card--notes .btn-arr svg, .menu-card--careers .btn-arr svg { stroke-width: 1.5; }
.menu-card--notes:hover .btn-arr--fwd svg:first-child,
.menu-card--notes:focus-visible .btn-arr--fwd svg:first-child,
.menu-card--careers:hover .btn-arr--fwd svg:first-child,
.menu-card--careers:focus-visible .btn-arr--fwd svg:first-child { transform: translate(150%, 0); }
.menu-card--notes:hover .btn-arr--fwd svg:last-child,
.menu-card--notes:focus-visible .btn-arr--fwd svg:last-child,
.menu-card--careers:hover .btn-arr--fwd svg:last-child,
.menu-card--careers:focus-visible .btn-arr--fwd svg:last-child { transform: translate(0, 0); }

/* the talk card: full ink, the site's Let's Talk voice with the email line */
.menu-card--talk {
  display: flex; flex-direction: column; gap: 2px;
  padding: 24px 28px;
  background: var(--fg);
  border-color: transparent;
  color: var(--bg);
}
.menu-talk-row {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  font-size: 1.5rem; font-weight: 600;
  line-height: 1.2; letter-spacing: -0.02em;
}
.menu-talk-mail {
  font-size: 0.9375rem;
  opacity: 0.62;
  transition: opacity 0.3s ease;
}
.menu-card--talk:hover .menu-talk-mail, .menu-card--talk:focus-visible .menu-talk-mail,
.menu-card--notes:hover .menu-talk-mail, .menu-card--notes:focus-visible .menu-talk-mail,
.menu-card--careers:hover .menu-talk-mail, .menu-card--careers:focus-visible .menu-talk-mail { opacity: 1; }

/* short viewports: tighten the rows, then allow the stack itself to scroll */
@media (max-height: 700px) {
  .menu-link { padding: 12px 24px; font-size: 1.35rem; }
  .menu-card--talk, .menu-card--notes, .menu-card--careers { padding: 18px 26px; }
  .menu-talk-row { font-size: 1.35rem; }
}
@media (max-height: 560px) {
  .menu-cards {
    bottom: var(--edge-y);
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}

/* ==========================================================================
   SCENES — static document by default; html.film pins them
   ========================================================================== */
.scene { position: relative; }
html.film .scene { height: calc(var(--len, 200) * 1svh); }
/* runway lengths — how much scroll each pinned chapter takes. Retuned at
   the 820px breakpoint (shorter swipe-throughs on phones); services is
   only a pre-measure fallback — scenes.js re-sizes it from the card count
   so every capability gets the same slot of scroll on every aspect */
html.film [data-scene="hero"] { --len: 130; }
html.film [data-scene="statement"] { --len: 200; }
html.film [data-scene="services"] { --len: 600; }
.stage { position: relative; padding: calc(var(--nav-h) + 3rem) 0 3rem; }
html.film .stage {
  position: sticky; top: 0;
  height: 100svh;
  overflow: clip;
  padding: 0;
  display: block;
}
.stage-inner {
  width: 100%; max-width: var(--container);
  margin-inline: auto; padding-inline: var(--gutter);
}
html.film .stage-inner {
  height: 100%;
  display: flex; flex-direction: column; justify-content: center;
  padding-top: calc(var(--nav-h) + var(--nav-top) + 8px);
  padding-bottom: 12px;
}
/* if stage content ever exceeds 100svh, clip only at the bottom — never
   center-overflow into unreachable space at both ends */
@supports (align-items: safe center) {
  html.film .stage-inner { justify-content: safe center; }
}
.flow-section { position: relative; padding: clamp(8rem, 16vh, 14rem) 0; }
.flow-section.contact { padding-block: clamp(10rem, 20vh, 18rem) clamp(8rem, 16vh, 14rem); }

/* ---------- 01 · hero ---------- */
.hero-stage { position: relative; z-index: 2; }
html.film .hero-stage {
  /* lower-third anchor — the vista owns the top of the frame */
  justify-content: flex-end;
  padding-top: calc(var(--nav-h) + var(--nav-top));
  padding-bottom: clamp(88px, 13svh, 150px);
}
/* on overflow (short viewports) fall back to top-aligned so the headline
   stays reachable — overflow: clip hides the start edge */
@supports (align-items: safe center) {
  html.film .hero-stage { justify-content: safe flex-end; }
}
/* procedural PCB etch (js/hero-circuit.js) — white traces on the paper,
   right half of the frame. The virtual board is wider than this crop, so
   pads and wires run off the screen edge; the left side dissolves into the
   page under a mask so the board never presents a hard boundary. */
.hero-circuit {
  position: absolute; top: 0; right: 0; z-index: 1;
  width: 50%; height: 100%;
  pointer-events: none;
  /* the sheen lives in-canvas (ctx.shadow*) — a CSS drop-shadow here makes
     Chrome rasterize the filtered layer at reduced resolution and the thin
     white wires wash out */
  -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 28%);
  mask-image: linear-gradient(to right, transparent 0%, #000 28%);
}
.hero-title {
  margin-bottom: 2.75rem;
  font-weight: 700;
  font-size: clamp(3rem, 10vw, 11rem);
  line-height: 0.98;
  letter-spacing: -0.034em;
}
.hero-line { display: block; }
.hero-line--deck {
  margin-top: 1.75rem;
  font-family: var(--font-sans); /* body voice inside the display h1 */
  font-size: clamp(1.25rem, 1.7vw, 1.5rem);
  font-weight: 500;
  letter-spacing: -0.005em;
  line-height: 1.45;
  color: var(--grey-700);
}
/* the hero foot sits on the grid: sub copy owns columns 1-6 */
.hero-foot {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--col-gap);
  align-items: end;
}
.hero-sub {
  grid-column: 1 / span 6;
  max-width: 36ch;
  color: var(--grey-700);
  font-size: clamp(1.25rem, 1.6vw, 1.5rem);
  line-height: 1.55;
}
/* mobile-only Let's Talk under the hero copy — stands in for the nav CTA,
   which is hidden below 820px (see the 820px media block) */
.hero-cta { display: none; }
.scroll-hint {
  position: absolute; bottom: var(--edge-y); left: 50%; transform: translateX(-50%);
  z-index: 3;
  display: flex; align-items: center; gap: 12px;
}
html:not(.film) .scroll-hint { display: none; }
.scroll-hint-line { width: 44px; height: 1px; background: var(--grey-400); }

/* ---------- 02 · statement ---------- */
/* four authored lines, each sized to run nearly the full container —
   the copy owns the frame instead of huddling in the left third */
.statement {
  font-weight: 700;
  font-size: clamp(2.5rem, 5.4vw, 5.5rem);
  line-height: 1.12;
  letter-spacing: -0.026em;
  text-wrap: balance;
}
.st-line { display: block; }
/* the film stages the lines as panels: scenes.js splits each into clipped
   word slots and scrubs three vars — --wp lifts a word through its slot
   (a brief >1 is the landing settle), --lp drifts the filling line up,
   --ap draws the accent's ink rule. Every default rests at the settled
   state, so no-JS and reduced-motion readers always get full ink. */
html.film .st-line { transform: translateY(calc((1 - var(--lp, 1)) * 0.45em)); }
/* the slot window is padded (with compensating negative margin) so the
   tight line-height doesn't crop descenders or the landing overshoot */
.st-w {
  display: inline-block; overflow: clip; vertical-align: top;
  padding: 0.22em 0.28em; margin: -0.22em -0.28em;
}
.st-m { display: inline-block; transform: translateY(calc((1 - var(--wp, 1)) * 122%)); }
.st-m .acc { position: relative; }
html.film .st-m .acc::after {
  content: ""; position: absolute; left: 0.03em; right: 0.05em; bottom: -0.06em;
  height: 0.055em; border-radius: 1px;
  background: currentColor;
  transform: scaleX(var(--ap, 1)); transform-origin: left;
}

/* ---------- 03 · services (vertical night drum) ---------- */
html:not(.film) .v-drum { display: block; }
/* the film mounts the six capabilities on a drum turning toward the reader:
   one card at a time crests over the top, flattens and holds at centre,
   then rolls away underneath. Scroll direction and card travel finally
   agree — the old horizontal strafe fought the wheel. */
html.film .v-drum {
  position: relative;
  height: 100%;
  perspective: 1500px;
  perspective-origin: 50% 50%;
}
.slide { position: relative; }
html:not(.film) .slide {
  max-width: var(--container); margin-inline: auto;
  padding: 3.5rem var(--gutter);
  border-top: 1px solid var(--hairline);
}
/* every card sits stacked on the drum's face — scenes.js gives each one its
   own angle. The -50%/-50% that centres it lives in the scrubbed transform,
   so nothing here can fight it. */
html.film .slide {
  position: absolute;
  top: 50%; left: 50%;
  width: min(900px, 84vw);
  transform: translate3d(-50%, -50%, 0);
  transform-origin: 50% 50%;
  backface-visibility: hidden;
  will-change: transform, opacity;
}
.slide-index {
  position: absolute; right: var(--gutter); bottom: 3vh;
  z-index: 1;
  font-weight: 700;
  font-size: clamp(9rem, 38vh, 26rem);
  line-height: 1;
  letter-spacing: -0.03em;
  color: rgba(11, 13, 16, 0.11);
  mix-blend-mode: multiply;
  pointer-events: none;
}
/* per-card ghost numeral, anchored to the card's lower right */
html.film .slide-index {
  right: 0; bottom: -0.14em;
  font-size: clamp(7rem, 26vh, 15rem);
}
/* the numerals flip with the night chrome — multiplied ink dies on black */
html.inverted .slide-index {
  color: rgba(244, 245, 247, 0.12);
  mix-blend-mode: screen;
}
html:not(.film) .slide-index { top: 2.5rem; bottom: auto; font-size: clamp(4rem, 10vw, 7rem); }
.slide-body { position: relative; z-index: 2; max-width: 1080px; }
.slide-title {
  font-weight: 700;
  font-size: clamp(3rem, 7.2vw, 7rem);
  line-height: 1.0;
  letter-spacing: -0.03em;
  margin-bottom: 1.75rem;
  text-wrap: balance;
}
/* full-bleed poster type is too big for a 68vw card — step down one notch */
html.film .slide-title { font-size: clamp(2.6rem, 5.2vw, 5rem); }
.slide-desc {
  color: var(--grey-700);
  font-size: clamp(1.25rem, 1.6vw, 1.5rem);
  font-weight: 500;
  line-height: 1.55;
  max-width: 46ch;
}
.slide-counter {
  position: absolute; z-index: 3;
  bottom: var(--edge-y); left: var(--gutter);
}
html:not(.film) .slide-counter { display: none; }

/* ---------- 04 · process — a plain static section ---------- */
.proc-title { margin-bottom: 2.2rem; }
.proc-line { background: var(--fg); margin-bottom: clamp(3rem, 6vh, 4.5rem); }
.proc-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr); /* 4 phases × 3 grid columns each */
  gap: var(--col-gap);
}
.proc-phase {
  border-left: 1px solid var(--hairline);
  padding-left: clamp(1.1rem, 1.8vw, 1.6rem);
}
.proc-index { margin-bottom: 1.1rem; }
.proc-name {
  font-weight: 700;
  font-size: clamp(1.5rem, 2.1vw, 2rem);
  letter-spacing: -0.016em;
  margin-bottom: 0.7rem;
}
.proc-desc { color: var(--grey-700); font-size: 1.1875rem; line-height: 1.55; }

/* ---------- 05 · manifesto — the wave tank ---------- */
/* a full-bleed, square-edged vessel; the cube-grid water renders on the canvas
   behind the text. The gradient is the stand-in until (or in case) GL boots. */
.lab-box {
  position: relative;
  display: flex;
  align-items: center;
  min-height: clamp(540px, 85svh, 920px);
  overflow: hidden;
  isolation: isolate;
  background: linear-gradient(180deg, #e9ecf0, #dde2e8);
  border-block: 1px solid var(--panel-border);
  box-shadow: var(--shadow-panel);
  /* touch: horizontal drags draw waves, vertical pans keep scrolling */
  touch-action: pan-y;
}
.lab-canvas {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%;
}
/* the copy floats above the water and lets the pointer through to it —
   it rides the same container rails as the nav and stage content */
.lab-copy {
  position: relative; z-index: 1;
  width: 100%; max-width: var(--container);
  margin-inline: auto; padding-inline: var(--gutter);
  padding-block: clamp(2.75rem, 6vw, 6rem);
  pointer-events: none;
}
.lab-kicker { margin-bottom: clamp(1.6rem, 3.5vh, 2.75rem); }

.manifesto { display: flex; flex-direction: column; gap: 1.8rem; max-width: 990px; }
/* the tank's interior is always light, whatever the chrome is doing — the ink
   is pinned (not themed) and haloed in paper so waves pass beneath it */
.manifesto p {
  font-weight: 650;
  font-size: clamp(2.25rem, 4.4vw, 3.9rem);
  line-height: 1.18;
  letter-spacing: -0.024em;
  color: #0b0d10;
  text-shadow: 0 0 16px rgba(245, 246, 248, 0.6), 0 0 44px rgba(245, 246, 248, 0.45);
  text-wrap: balance;
}
.lab-box .lab-kicker { color: #565d66; }

/* the door to the writing shelf — floats on the tank's lower right (lower
   left on phones, clear of the thumb's scroll edge). The tank interior is
   always light, so the pill's ink is pinned like the manifesto's. */
.lab-cta {
  position: absolute; z-index: 2;
  /* the tank is full-bleed, so the pill computes its own distance to the
     container rail the rest of the page aligns to */
  right: max(var(--gutter), calc((100% - var(--container)) / 2 + var(--gutter)));
  bottom: clamp(1.75rem, 4vh, 2.75rem);
  background: #0b0d10;
  color: #f5f6f8;
}
.lab-cta:hover, .lab-cta:focus-visible { background: #2a2e34; color: #f5f6f8; }
/* desktop: the pill reads bigger against the wide tank and lifts clear of
   the bottom edge; phones keep the standard .btn size */
@media (min-width: 821px) {
  .lab-cta {
    height: 68px;
    padding: 0 44px;
    font-size: 1.1875rem;
    bottom: calc(clamp(1.75rem, 4vh, 2.75rem) + 2rem);
  }
}
/* forward arrow swap: the → exits right, its twin lands from the left */
.btn-arr--fwd svg:last-child { transform: translate(-150%, 0); }
.btn:hover .btn-arr--fwd svg:first-child, .btn:focus-visible .btn-arr--fwd svg:first-child { transform: translate(150%, 0); }
.btn:hover .btn-arr--fwd svg:last-child, .btn:focus-visible .btn-arr--fwd svg:last-child { transform: translate(0, 0); }

/* ---------- 06 · contact — one headline, one giant invitation ---------- */
.contact { text-align: center; }
.contact-title {
  margin-bottom: 1.75rem;
  font-size: clamp(3rem, 7.4vw, 7.5rem);
  line-height: 1.0;
  letter-spacing: -0.028em;
}
.contact-sub {
  color: var(--grey-700);
  font-size: clamp(1.25rem, 1.6vw, 1.5rem);
  max-width: 44ch; margin: 0 auto clamp(3.5rem, 7vh, 5.5rem);
  text-wrap: balance;
}
/* the Let's Talk pill — the only object in the section, sized like one */
.cta-talk {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  gap: 0.55em;
  height: clamp(84px, 11vw, 124px);
  padding: 0 clamp(48px, 6vw, 84px);
  border-radius: 999px;
  background: var(--fg); color: var(--bg);
  font-family: var(--font-display);
  font-size: clamp(1.375rem, 2.4vw, 2.125rem);
  font-weight: 600;
  letter-spacing: -0.01em;
  white-space: nowrap;
  transition: background-color 0.35s var(--ease-out), transform 0.1s ease-out;
}
/* proactive idle: sound-wave echoes — three thin arcs peel off the pill's left
   and right flanks in step, drift outward and dissolve, then the surface rests
   for a beat. 1px lines, low opacity, decelerating ease: sonar-quiet, never
   frantic. Hidden while hovered (the pill already has your attention). */
.cta-echo {
  position: absolute; top: 50%;
  width: 0; height: 0;
  pointer-events: none;
  transition: opacity 0.25s var(--ease-out);
}
.cta-echo--l { left: 0; }
.cta-echo--r { right: 0; }
/* one arc = the outward border of a tall ellipse; travel + fade live in the
   keyframes, so before its delay expires an arc is simply not there */
.cta-echo i {
  position: absolute; top: 0;
  width: 0.75em; height: 2.4em;
  border: 1px solid transparent;
  border-radius: 50%;
  opacity: 0;
  animation: 3.4s cubic-bezier(0.3, 0.6, 0.4, 1) infinite;
}
.cta-echo--l i { right: -0.35em; border-left-color: var(--fg); animation-name: talk-echo-l; }
.cta-echo--r i { left: -0.35em; border-right-color: var(--fg); animation-name: talk-echo-r; }
.cta-echo i:nth-child(2) { animation-delay: 0.22s; }
.cta-echo i:nth-child(3) { animation-delay: 0.44s; }
.cta-talk:hover .cta-echo, .cta-talk:focus-visible .cta-echo { opacity: 0; }
@keyframes talk-echo-l {
  0%        { opacity: 0;    transform: translate(0, -50%) scale(0.75); }
  8%        { opacity: 0.35; }
  55%, 100% { opacity: 0;    transform: translate(-1.7em, -50%) scale(1); }
}
@keyframes talk-echo-r {
  0%        { opacity: 0;    transform: translate(0, -50%) scale(0.75); }
  8%        { opacity: 0.35; }
  55%, 100% { opacity: 0;    transform: translate(1.7em, -50%) scale(1); }
}
.cta-talk:hover, .cta-talk:focus-visible {
  background: var(--btn-hover);
}
.cta-talk:active { transform: scale(0.98); }
/* the quiet alternative under the loud one */
.contact-alt { margin-top: clamp(2rem, 4vh, 3rem); }
.contact-alt a {
  display: inline-block;
  padding: 12px 4px; margin: -12px 0; /* tap target without moving the text */
  transition: color 0.2s ease;
}
.contact-alt a:hover { color: var(--fg); }

/* ---------- 06 · questions — a quiet accordion before the ask ---------- */
.faq-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(2rem, 4.5vw, 3.25rem);
  letter-spacing: -0.03em;
  margin-bottom: clamp(2.5rem, 6vh, 4rem);
}
.faq-item { border-top: 1px solid var(--hairline-strong); }
.faq-item:last-child { border-bottom: 1px solid var(--hairline-strong); }
.faq-item summary {
  display: flex; align-items: baseline; gap: 1.4rem;
  padding: 1.35rem 0;
  cursor: pointer;
  list-style: none;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.15rem, 1.8vw, 1.5rem);
  letter-spacing: -0.015em;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-index { flex: none; width: 2.2rem; color: var(--grey-600); font-size: 0.75rem; }
/* plus that loses its vertical bar when the item opens */
.faq-mark { position: relative; flex: none; width: 14px; height: 14px; margin-left: auto; align-self: center; }
.faq-mark::before, .faq-mark::after {
  content: ""; position: absolute; inset: 0; margin: auto;
  background: currentColor;
}
.faq-mark::before { width: 14px; height: 1.5px; }
.faq-mark::after { width: 1.5px; height: 14px; transition: transform 0.3s var(--ease-out); }
.faq-item[open] .faq-mark::after { transform: scaleY(0); }
.faq-answer {
  padding: 0 0 1.6rem 3.6rem; /* clears the index column */
  color: var(--grey-700);
  font-size: 1.125rem;
  line-height: 1.55;
  max-width: 62ch;
}
.faq-answer a { border-bottom: 1px solid var(--hairline-strong); transition: border-color 0.15s ease-out; }
.faq-answer a:hover { border-bottom-color: var(--fg); }
@media (max-width: 640px) {
  .faq-index { display: none; }
  .faq-answer { padding-left: 0; }
}

/* ---------- footer — the mark signs off, links beside it, legal line ---------- */
.footer { padding: clamp(3.5rem, 8vh, 5.5rem) 0 2rem; position: relative; }
.footer-top {
  display: flex; justify-content: space-between; align-items: center;
  gap: 2rem 2.5rem; flex-wrap: wrap;
  margin-bottom: clamp(2.5rem, 6vh, 4rem);
}
/* the closing brand — same proportions as the nav brand, three times the size */
.brand--footer { font-size: clamp(2.65rem, 8vw, 4rem); }
.brand--footer .logo { width: 2.35em; height: 2.35em; }
.footer-nav {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 0.25rem 2.4rem;
}
.footer-nav a {
  position: relative;
  padding-block: 9px; /* 44px hit-area floor */
  color: var(--fg); font-size: 1.125rem;
}
.footer-nav a::after {
  content: ""; position: absolute; left: 0; bottom: 5px;
  width: 100%; height: 1px; background: var(--fg);
  transform: scaleX(0); transform-origin: right;
  transition: transform 0.4s var(--ease-out);
}
.footer-nav a:hover::after { transform: scaleX(1); transform-origin: left; }
.footer-legal {
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 1rem;
  padding-top: 1.4rem;
  font-size: 0.9375rem;
  color: var(--grey-600);
}
/* inline links: grow the tap target upward without moving the text */
.footer-legal a {
  display: inline-block;
  padding-top: 12px; margin-top: -12px;
}
.footer-legal a:hover { color: var(--fg); }

/* ==========================================================================
   TEXT ANIMATION STATES
   ========================================================================== */

/* the clip window is padded (with compensating negative margin) so tight
   line-heights don't crop descenders or the serif accent's overhang */
.split-w {
  display: inline-block; overflow: clip; vertical-align: top;
  padding: 0.22em 0.28em; margin: -0.22em -0.28em;
}
.split-c {
  display: inline-block;
  transform: translateY(150%);
  transition: transform 0.9s var(--ease-out);
  transition-delay: calc(min(var(--i, 0), 24) * 24ms);
}
.is-visible .split-c { transform: none; }

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */
@media (max-width: 1080px) {
  .proc-grid { grid-template-columns: 1fr 1fr; row-gap: 2.5rem; }
}
@media (max-width: 820px) {
  :root { --nav-h: 72px; }
  /* phones: the menu sits on a solid body-colored sheet, no blur */
  .menu { background: var(--bg); }
  .nav-cta { display: none; }
  .nav-burger { height: 48px; padding: 0 19px 0 22px; font-size: 1rem; }
  /* the grid stacks: full-width rows, same margins */
  .hero-foot { display: flex; flex-direction: column; align-items: flex-start; gap: 2rem; }
  /* the nav CTA is gone up here — the hero carries Let's Talk instead */
  .hero-cta { display: inline-flex; }
  html.film .slide { width: 86vw; }
  /* a phone card is too narrow for the numeral to sit beside the copy —
     drop it clear of the description instead of behind it */
  html.film .slide-index { font-size: clamp(5rem, 16vh, 8rem); bottom: -0.86em; }
  /* a thumb-flick covers far less ground than a wheel — shorter runways
     keep the hero exit and the statement read-out inside one swipe each */
  html.film [data-scene="hero"] { --len: 115; }
  html.film [data-scene="statement"] { --len: 170; }
  /* bottom-left, and the centered copy reserves the button's floor so the
     manifesto can never sink into it on short phones */
  .lab-cta { right: auto; left: var(--gutter); }
  .lab-copy { padding-bottom: calc(clamp(1.75rem, 4vh, 2.75rem) + 58px + 1.5rem); }
}
@media (max-width: 520px) {
  body { font-size: 1.125rem; }
  .proc-grid { grid-template-columns: 1fr; }
}

/* short viewports (landscape phones, small laptops at high zoom): compress
   the pinned frames so nothing clips out of the 100svh stages */
@media (max-height: 620px) {
  html.film .hero-stage { padding-bottom: clamp(32px, 6svh, 72px); }
  html.film .hero-title { font-size: clamp(2rem, 6vw, 4rem); margin-bottom: 1.25rem; }
  html.film .hero-line--deck { margin-top: 0.8rem; font-size: 1rem; }
  html.film .hero-sub { font-size: 1rem; }
  html.film .statement { font-size: clamp(1.5rem, 6.2vh, 3rem); }
  html.film .slide-title { font-size: clamp(2rem, 12vh, 3.5rem); }
}

/* no-JS: the burger can't do anything — drop the dead control, keep the CTA */
html.no-js .nav-burger { display: none; }
html.no-js .nav-cta { display: inline-flex; }

/* ==========================================================================
   REDUCED MOTION (film mode is never enabled under reduced motion)
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0s !important; /* the menu stagger is delay-built */
    scroll-behavior: auto !important;
  }
  html { scroll-behavior: auto; }
  .split-c { transform: none; }
}
