/* ==========================================================================
   SHVA LEADERSHIP — shvaleadership.com
   assets/style.css  —  ONE stylesheet for index.html, the-work.html,
                        communique.html
   Stack:  pure CSS. No framework, no @import, no build step.

   THE HORIZON
   -----------
   One antique-gold hairline is the structural spine of the site. The sun
   crests it in the hero. It becomes the boundary between sections as you
   scroll. At the call to action it is the line the road arrives on, and the
   one gold object on the site sits on it.

   It replaces four devices that used to decorate rather than encode: the
   per-section rule, the vertical edge rails, the tile diagonals and the
   tile numerals.

   COLOUR DISCIPLINE
   -----------------
   --color-gold-primary  the action button and its border. Nothing else.
   --color-gold-antique  the horizon, and links.
   --color-text-primary  headlines and body copy.
   --color-text-secondary labels, numerals, bylines, notes.

   TYPE
   ----
   Display  Cormorant Garamond. Roman for headlines. Italic is reserved
            for Dr. G's first-person conviction statements: that is his
            voice, and it does not get spent anywhere else.
   Body     Inter.
   Utility  Inter, differentiated by weight, tracking and tabular figures.
            Labels, numerals and bylines live here.

   Every size is one fluid clamp() built from a 375px to 1440px ramp, so
   the breakpoint blocks carry layout only and never re-declare the scale.

   MOTION
   ------
   Transform and opacity only, with three documented paint-only exceptions
   that never touch layout:
     * stroke-dashoffset on the convergence threads
     * clip-path on the hero road unroll
     * background-color on button hover
   All scroll triggering is IntersectionObserver in main.js. There is no
   scroll listener anywhere.

   REQUIRED IN EVERY PAGE <head>:
       <script>document.documentElement.className+=' js';</script>
   Without it the animated start states never apply and the page renders in
   its final resting state. That is the intended no-JS fallback, not a bug.
   ========================================================================== */


/* ==========================================================================
   1. TOKENS
   ========================================================================== */

:root {

  /* --- Brand colour field (CLAUDE.md, locked) --- */
  --color-field-primary: #1C1C1E;
  --color-field-deep:    #0D0D0F;
  --color-field-mid:     #161618;
  --color-field-tile:    #222224;
  --color-gold-primary:  #E6B800;
  --color-gold-antique:  #E0BC84;
  --color-text-primary:  #D4D0C8;
  --color-text-secondary:#8A8680;

  /* --- Derived translucent values (no literal hex used elsewhere) --- */
  --color-gold-wash:      rgba(230, 184, 0, 0.08);   /* gold button hover fill    */
  --color-antique-wash:   rgba(224, 188, 132, 0.08); /* antique button hover fill */
  --color-antique-sel:    rgba(224, 188, 132, 0.16); /* text selection            */
  --color-nav-field:      rgba(28, 28, 30, 0.95);    /* nav bg once scrolled      */
  --color-thread-head:    #FFE9C2;                   /* comet core, arrival only  */
  --color-rail-soft:      rgba(224, 188, 132, 0.35); /* phase timeline connectors */
  --color-field-primary-0: rgba(28, 28, 30, 0);      /* #1C1C1E at zero alpha     */
  --color-overlay-field:  rgba(13, 13, 15, 0.98);    /* mobile menu overlay       */

  /* --- Type roles --- */
  --font-display: 'Cormorant Garamond', Georgia, serif;
  --font-body:    'Inter', system-ui, sans-serif;
  --font-util:    var(--font-body);

  /* Utility role. Labels, numerals and bylines. Differentiated from body by
     weight, tracking and tabular figures, not by family. */
  --util-weight:  500;
  --util-track:   0.22em;

  /* --- Fluid type scale ---------------------------------------------------
     Every value is clamp(min, <intercept>rem + <slope>vw, max) solved across
     a 375px to 1440px viewport ramp. One declaration, no breakpoint copies. */
  --fs-fine:          clamp(11px, 0.666rem + 0.094vw, 12px);
  --fs-label:         clamp(10px, 0.603rem + 0.094vw, 11px);
  --fs-micro:         clamp(12px, 0.728rem + 0.094vw, 13px);
  --fs-body-sm:       clamp(14px, 0.853rem + 0.094vw, 15px);
  --fs-body:          clamp(15px, 0.916rem + 0.094vw, 16px);
  --fs-tile-title:    clamp(19px, 1.122rem + 0.282vw, 22px);
  --fs-duo-lead:      var(--fs-tile-title);
  --fs-phase-title:   var(--fs-tile-title);
  --fs-hero-sub:      clamp(16px, 0.912rem + 0.376vw, 20px);
  --fs-page-sub:      clamp(16px, 0.956rem + 0.188vw, 18px);
  --fs-cta-sub:       var(--fs-page-sub);
  --fs-conviction:    clamp(21px, 1.159rem + 0.657vw, 28px);
  --fs-serves:        clamp(24px, 1.324rem + 0.751vw, 32px);
  --fs-focus-title:   var(--fs-serves);
  --fs-cta-headline:  clamp(30px, 1.391rem + 2.066vw, 52px);
  --fs-page-headline: clamp(32px, 1.472rem + 2.254vw, 56px);
  --fs-hero-headline: clamp(32px, 1.350rem + 2.620vw, 58px);

  /* --- Thread system -------------------------------------------------------
     Three layers per thread, all sharing one curved path:
       .thread-dust   long, heavily blurred, faint. The dust in the wake.
       .thread-comet  short, bright, blurred. The head.
       .thread        the hairline that stays behind. CLAUDE.md: 1px, hair-thin.
     The head and dust exist only while the thread travels; they fade out on
     arrival, leaving the hairline. */
  --thread-weight-primary:   1px;
  --thread-weight-secondary: 1px;   /* the horizon */
  --thread-opacity:      0.5;       /* at rest: hair-thin but legible          */
  --thread-comet-weight: 2.6px;
  --thread-dust-weight:  6px;

  /* --- Layout --- */
  --content-max-width: 1200px;
  --content-padding:   80px;
  --gutter:      var(--content-padding);
  --section-pad: 120px;
  /* Absolute x of the content column's left edge, for elements that sit
     outside .container but must share its axis. */
  --content-left: max(var(--gutter),
                      calc(50% - var(--content-max-width) / 2 + var(--gutter)));

  /* --- Hero composition ---------------------------------------------------
     The centre axis is deliberately broken. The sun sits on the left third,
     at the 22.7% x the mark occupies in the brand video. */
  /* Height of the sky band, i.e. where the line sits. A viewport length, not
     a percentage: the ground below it is in normal flow, so the hero can
     grow on a short screen instead of clipping the copy. */
  --hero-horizon:  50svh;
  /* The hero mark is now the FULL lockup: sun, road and wordmark on one
     1600x744 canvas re-derived from _source/SHVA_full_logo_no_background_V3.png.
     All three layers register exactly, so they stack with inset:0. */
  --mark-size:     clamp(320px, 36vw, 520px);
  --mark-aspect:   1600 / 744;
  /* Sun centre inside assets/hero-sun.png, measured. */
  --mark-sun-cx:   22.719%;
  --mark-sun-cy:   49.933%;
  /* Rotation that puts the road's own axis upright, so the unroll sweep runs
     from the wide near end toward the narrow far tip. Measured. */
  --road-sweep:    -23.85deg;

  /* --- Hero motion --------------------------------------------------------
     Timings derived from LogoAnimation.mxf and compressed for web. The
     perceptible sequence completes at 4.10s.

     The spin is a flywheel, not an ease. Measured from the video:
       constant 111.5 deg/s, then linear deceleration at 19.0 deg/s^2.

     Both measured constants are held exactly. The only free variable is how
     long the constant phase runs, and it is solved so the mark comes to rest
     in its authored orientation rather than part-way round: a registered
     trademark should not settle at an angle.

     Decay phase    5.868s  =  327.16 deg   (111.5/19.0 and 111.5^2/(2*19.0))
     Constant phase 0.2945s =   32.84 deg   ((360 - 327.16) / 111.5)
     Total          6.163s  =  360.00 deg   exactly one turn
     Constant phase is 0.2945/6.163 = 4.779% of the animation.

     Linear velocity decay makes the angle a quadratic, and the exact cubic
     Bezier for 1-(1-t)^2 is cubic-bezier(0.33333, 0.66667, 0.66667, 1). So
     the deceleration is exact, not approximated. */
  --spin-duration:   6.163s;
  --spin-hold-deg:   32.84deg;
  --spin-total-deg:  360deg;
  --ease-flywheel:   cubic-bezier(0.33333, 0.66667, 0.66667, 1);

  /* Order matters: the road does NOT start while the sun is still climbing.
     The sun reaches its resting position at 1.75s; the road begins at 2.05s,
     a clear beat later, by which point the flywheel is 25% through its decay
     and visibly slowing. The wordmark resolves only once the road is complete. */
  --t-horizon:   0.10s;   /* horizon draws                      */
  --d-horizon:   0.70s;
  --t-thread:    0.25s;   /* threads arrive from off-screen     */
  --d-thread:    1.30s;
  --t-sun:       0.50s;   /* sun crests the horizon, spinning   */
  --d-sun:       1.25s;   /*   ... at rest 1.75s                */
  --t-road:      2.05s;   /* road unrolls toward the sun        */
  --d-road:      0.85s;   /*   ... complete 2.90s               */
  --t-word:      2.95s;   /* wordmark resolves                  */
  --d-word:      0.50s;
  --t-headline:  3.50s;
  --d-headline:  0.55s;
  --t-subhead:   3.90s;
  --d-subhead:   0.45s;
  --t-chevron:   4.30s;
  --d-chevron:   0.35s;

  /* --- Nav mark, inner pages only. See "NAV MARK FORMATION" below. --------
     Sweeps 180deg in 1.35s and rests at 0deg, matching the static mark. */
  --nav-mark-size: clamp(38px, 3.2vw, 46px);
  --nav-sun-cx:    49.863%;
  --nav-sun-cy:    49.933%;
  --nav-spin-from: -180deg;
  --d-nav-spin:    1.35s;
  --t-nav-sun:     0.05s;
  --d-nav-sun:     0.60s;
  --t-nav-road:    0.62s;   /* begins while the flywheel is still shedding */
  --d-nav-road:    0.70s;

  /* --- Easing --- */
  /* Sun rise. Measured from the video: cubic ease-out, RMS 0.032. */
  --ease-rise:   cubic-bezier(0.215, 0.61, 0.355, 1);
  --ease-thread: cubic-bezier(0.25, 0.46, 0.45, 0.94);
  --ease-road:   cubic-bezier(0.16, 1, 0.30, 1);
  --ease-out:    cubic-bezier(0, 0, 0.2, 1);
  --reveal-base-delay: 0s;

  /* --- Stacking --- */
  --z-threads: 1;
  --z-content: 2;
  --z-salesiq: 90;
  --z-nav:     100;
  --z-menu:    110;

  color-scheme: dark;
}


/* ==========================================================================
   2. RESET + BASE
   ========================================================================== */

*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background-color: var(--color-field-deep);
  color: var(--color-text-primary);
  font-family: var(--font-body);
  font-weight: 400;
  font-size: var(--fs-body);
  line-height: 1.6;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body.is-menu-open { overflow: hidden; }

img, svg { display: block; max-width: 100%; }
img { height: auto; }

h1, h2, h3, h4, p, figure, blockquote { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }

a { color: inherit; text-decoration: none; }

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

:focus-visible {
  outline: 1px solid var(--color-gold-antique);
  outline-offset: 3px;
}

::selection {
  background-color: var(--color-antique-sel);
  color: var(--color-text-primary);
}


/* ==========================================================================
   3. UTILITIES
   ========================================================================== */

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.u-center { text-align: center; }
.u-mt-sm  { margin-top: 16px; }
.u-mt-md  { margin-top: 24px; }
.u-mt-lg  { margin-top: 40px; }

.skip-link {
  position: absolute;
  top: 0; left: 0;
  z-index: calc(var(--z-nav) + 10);
  transform: translateY(-120%);
  padding: 12px 20px;
  background-color: var(--color-field-primary);
  color: var(--color-gold-antique);
  font-family: var(--font-util);
  font-size: var(--fs-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  transition: transform 0.2s var(--ease-out);
}
.skip-link:focus { transform: translateY(0); }


/* ==========================================================================
   4. LAYOUT PRIMITIVES
   ========================================================================== */

.container {
  width: 100%;
  max-width: var(--content-max-width);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section {
  position: relative;
  padding-block: var(--section-pad);
  --reveal-base-delay: 0.6s;  /* 0.5s horizon draw + 0.1s hold */
}

/* A section whose horizon is not at its top edge reveals at once. */
.section--no-rule { --reveal-base-delay: 0s; }

.section--field { background-color: var(--color-field-primary); }
.section--mid   { background-color: var(--color-field-mid); }
.section--deep  { background-color: var(--color-field-deep); }
.section--tight { padding-block: calc(var(--section-pad) * 0.66); }


/* --------------------------------------------------------------------------
   THE HORIZON
   Full-bleed antique hairline at the top edge of a section, drawn left to
   right as the section arrives. `.section__rule` is the legacy class name
   still carried by the-work.html and communique.html; both resolve here.
   -------------------------------------------------------------------------- */
.horizon,
.section__rule {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: var(--thread-weight-secondary);
  background-color: var(--color-gold-antique);
  transform: scaleX(0);
  transform-origin: left center;
  pointer-events: none;
}
.js .horizon,
.js .section__rule { transition: transform 0.5s var(--ease-thread); }

.section.is-inview .horizon,
.section.is-inview .section__rule { transform: scaleX(1); }


/* Section accent label — the utility type role -------------------------- */
.section__label {
  font-family: var(--font-util);
  font-weight: var(--util-weight);
  font-size: var(--fs-label);
  letter-spacing: var(--util-track);
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  color: var(--color-text-secondary);
  margin-bottom: 32px;
}


/* ==========================================================================
   5. GOLD THREAD SVG SYSTEM
   --------------------------------------------------------------------------
   Every thread starts OUTSIDE the viewport and ends 12px past the
   convergence point, per CLAUDE.md. It travels on a bent path and
   straightens as it falls in, so its resting state is a straight line aimed
   squarely at the sun's centre, not a curve sweeping across the page.
   Curved in travel, straight at rest.
   ========================================================================== */

.thread-field {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: var(--z-threads);
  overflow: visible;
}

/* Held transparent until main.js begins that field's arrival, which it does by
   setting opacity directly. Belt and braces on top of the dash offset below:
   the dash alone hides the authored paths before the script runs, but it
   cannot protect against the script itself painting a settled state at the
   wrong moment. Scoped to .js so the no-script fallback still shows them. */
.js .thread-field { opacity: 0; }

/* The hairline that remains. */
.thread {
  fill: none;
  stroke: var(--color-gold-antique);
  stroke-width: var(--thread-weight-primary);
  stroke-opacity: var(--thread-opacity);
  stroke-linecap: round;
  /* Needed only for the no-JS fallback, where the viewBox is still the
     anisotropic 0 0 100 100. Once main.js rewrites the viewBox to CSS pixels
     the user space is 1:1 with the screen. */
  vector-effect: non-scaling-stroke;
}

.js .thread { vector-effect: none; }

/* The travelling head and its dust. Both are built by main.js from the same
   path data, so they follow the identical curve. */
.thread-comet,
.thread-dust {
  fill: none;
  stroke-linecap: round;
  opacity: 0;
  pointer-events: none;
}
.thread-comet {
  stroke: var(--color-thread-head);
  stroke-width: var(--thread-comet-weight);
  filter: url(#threadGlow);
}
.thread-dust {
  stroke: var(--color-gold-antique);
  stroke-width: var(--thread-dust-weight);
  filter: url(#threadDust);
}

/* The threads are driven frame by frame in main.js, not by keyframes.
   They have to CHANGE SHAPE: bent while they travel, dead straight by the
   time they come to rest, aimed at the convergence point. A keyframe cannot
   morph path data, so the whole arrival is a single one-shot rAF pass that
   writes `d`, the dash geometry and the head opacity together.

   All this rule does is hold them offstage until that pass takes over, so
   they never flash in fully drawn before the script runs. 4000px comfortably
   exceeds any thread on any viewport, so the dash hides the whole path until
   the first rendered frame replaces both values. */
.js .thread {
  stroke-dasharray:  4000px;
  stroke-dashoffset: 4000px;
}


/* ==========================================================================
   6. SCROLL REVEAL SYSTEM
   --------------------------------------------------------------------------
   main.js adds .is-inview to .section, .tile and .focus. Descendants
   carrying .reveal then transition to their resting state.
   data-stagger="0..5" adds n * 0.15s of extra delay.
   ========================================================================== */

.js .reveal {
  opacity: 0;
  transform: translateY(12px);
  transition:
    opacity   0.5s var(--ease-out),
    transform 0.5s var(--ease-out);
  transition-delay: calc(var(--reveal-base-delay) + var(--stagger, 0s));
  will-change: opacity, transform;
}

.js .reveal--left  { transform: translateX(-20px); }
.js .reveal--right { transform: translateX(20px); }
.js .reveal--up    { transform: translateY(8px); }
.js .reveal--still { transform: none; }

.is-inview .reveal,
.reveal.is-inview {
  opacity: 1;
  transform: none;
}

[data-stagger="0"] { --stagger: 0s; }
[data-stagger="1"] { --stagger: 0.15s; }
[data-stagger="2"] { --stagger: 0.30s; }
[data-stagger="3"] { --stagger: 0.45s; }
[data-stagger="4"] { --stagger: 0.60s; }
[data-stagger="5"] { --stagger: 0.75s; }


/* ==========================================================================
   7. BUTTONS + LINKS
   --------------------------------------------------------------------------
   --color-gold-primary appears here and nowhere else on the site.
   ========================================================================== */

.btn-gold {
  display: inline-block;
  font-family: var(--font-util);
  font-weight: var(--util-weight);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-gold-primary);
  background-color: transparent;
  border: 1px solid var(--color-gold-primary);
  line-height: 1;
  white-space: nowrap;
  transition: background-color 0.2s var(--ease-out);
}
.btn-gold:hover,
.btn-gold:focus-visible { background-color: var(--color-gold-wash); }

.btn-gold--nav { font-size: var(--fs-micro); padding: 10px 24px; }
.btn-gold--cta { font-size: var(--fs-body-sm); padding: 16px 40px; }

.btn-gold--antique {
  color: var(--color-gold-antique);
  border-color: var(--color-gold-antique);
  font-size: var(--fs-body-sm);
  letter-spacing: 0.08em;
  padding: 14px 36px;
}
.btn-gold--antique:hover,
.btn-gold--antique:focus-visible { background-color: var(--color-antique-wash); }

/* Inline "→ See the full engagement structure" style link */
.link-arrow {
  display: inline-block;
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--color-gold-antique);
  border-bottom: 1px solid transparent;
  transition: border-color 0.2s var(--ease-out);
}
.link-arrow:hover,
.link-arrow:focus-visible { border-bottom-color: var(--color-gold-antique); }


/* ==========================================================================
   8. NAVIGATION
   ========================================================================== */

.site-nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: var(--z-nav);
  padding: 20px var(--gutter);
  background-color: transparent;
  transition: background-color 0.3s ease;
}
.site-nav.is-scrolled { background-color: var(--color-nav-field); }

.site-nav__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}

.site-nav__logo { display: block; line-height: 0; }
.site-nav__logo-img {
  width: var(--nav-mark-size);
  height: auto;
}


/* --------------------------------------------------------------------------
   NAV MARK FORMATION — the-work.html and communique.html only
   --------------------------------------------------------------------------
   Those pages have no hero sequence, so the mark forms in the corner instead:
   the sun fades in already spinning, rises into place, and the road unrolls
   along its own axis as the spin decays. The home page nav stays static
   because its hero already carries the full sequence.

   Same flywheel LAW as the hero: velocity decays linearly, which makes the
   angle a quadratic, and the exact cubic Bezier for 1-(1-t)^2 is
   cubic-bezier(0.33333, 0.66667, 0.66667, 1). Not an approximation.

   The hero's own constants do not survive the compression, and cannot: a
   flywheel starting at 111.5 deg/s and shedding 19.0 deg/s^2 needs 5.87s to
   stop and sweeps 327 deg getting there. Held to ~1.35s and ~180 deg, the law
   fixes the rest, so the constants are re-derived rather than borrowed:

     sweep  = w0 * T / 2   ->  w0 = 2 * 180 / 1.35 = 266.7 deg/s
     decel  = w0 / T       ->       266.7 / 1.35   = 197.5 deg/s^2

   It starts at -180deg and ends at 0deg, so it sweeps half a turn and comes
   to rest in exactly the orientation the static mark uses.
   -------------------------------------------------------------------------- */

.nav-mark {
  position: relative;
  display: block;
  width: var(--nav-mark-size);
  aspect-ratio: 512 / 523;
}

.nav-mark__sun,
.nav-mark__road {
  position: absolute;
  inset: 0;
}

.nav-mark__sun-img,
.nav-mark__road-img {
  position: absolute;
  width: 100%;
}

/* Riser carries translateY only, so the spin below never fights it. */
.nav-mark__sun-img {
  inset: 0;
  transform-origin: var(--nav-sun-cx) var(--nav-sun-cy);
}

/* Same unroll mechanic as the hero, scaled: an oversized wrapper rotated so
   the road's axis runs upright, swept by a plain inset() clip, with the image
   counter-rotated about the same centre. 150% is enough here because the nav
   box is nearly square; the hero needed 190% for its 2.15:1 lockup. */
.nav-mark__road {
  inset: -25%;
  transform: rotate(var(--road-sweep));
  clip-path: inset(0 0 0 0);
}
.nav-mark__road-img {
  left: 16.6667%;
  top:  16.6667%;
  width: 66.6667%;
  transform: rotate(calc(-1 * var(--road-sweep)));
}

@keyframes navSunRise {
  from { opacity: 0; transform: translateY(48%); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes navSunSpin {
  from { transform: rotate(var(--nav-spin-from)); }
  to   { transform: rotate(0deg); }
}

@keyframes navRoadUnroll {
  from { clip-path: inset(100% 0 0 0); }
  to   { clip-path: inset(0 0 0 0); }
}

.js .nav-mark--forming .nav-mark__sun {
  animation: navSunRise var(--d-nav-sun) var(--ease-rise) var(--t-nav-sun) both;
}
.js .nav-mark--forming .nav-mark__sun-img {
  animation: navSunSpin var(--d-nav-spin) var(--ease-flywheel) var(--t-nav-sun) both;
}
.js .nav-mark--forming .nav-mark__road {
  animation: navRoadUnroll var(--d-nav-road) var(--ease-road) var(--t-nav-road) both;
}

.site-nav__links {
  display: flex;
  align-items: center;
  gap: clamp(24px, 2.6vw, 40px);
}

.site-nav__link {
  font-family: var(--font-util);
  font-weight: var(--util-weight);
  font-size: var(--fs-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-text-primary);
  transition: color 0.2s var(--ease-out);
}
.site-nav__link:hover,
.site-nav__link:focus-visible { color: var(--color-gold-antique); }
.site-nav__link.is-current { color: var(--color-gold-antique); }

/* Hamburger — hidden above 768px */
.site-nav__toggle {
  display: none;
  width: 32px;
  height: 24px;
  position: relative;
  margin-left: auto;
}
.site-nav__toggle-bar {
  position: absolute;
  left: 0;
  width: 100%;
  height: 1px;
  background-color: var(--color-gold-antique);
}
.site-nav__toggle-bar:nth-child(1) { top: 4px; }
.site-nav__toggle-bar:nth-child(2) { top: 11px; }
.site-nav__toggle-bar:nth-child(3) { top: 18px; }


/* ==========================================================================
   9. MOBILE MENU OVERLAY
   ========================================================================== */

.mobile-menu {
  position: fixed;
  inset: 0;
  z-index: var(--z-menu);
  background-color: var(--color-overlay-field);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  visibility: hidden; /* removes contents from the tab order when closed */
  transition: opacity 0.3s var(--ease-out), visibility 0s linear 0.3s;
}
.mobile-menu.is-open {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.3s var(--ease-out), visibility 0s linear 0s;
}

.mobile-menu__close {
  position: absolute;
  top: 20px;
  right: var(--gutter);
  width: 32px;
  height: 32px;
}
.mobile-menu__close::before,
.mobile-menu__close::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  height: 1px;
  background-color: var(--color-gold-antique);
}
.mobile-menu__close::before { transform: rotate(45deg); }
.mobile-menu__close::after  { transform: rotate(-45deg); }

.mobile-menu__list {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 48px;
  text-align: center;
  padding: 0 24px;
}

.mobile-menu__link {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(28px, 7vw, 32px);
  line-height: 1.2;
  color: var(--color-text-primary);
  transition: color 0.2s var(--ease-out);
}
.mobile-menu__link:hover,
.mobile-menu__link:focus-visible { color: var(--color-gold-antique); }
.mobile-menu__link--accent { color: var(--color-gold-primary); }


/* ==========================================================================
   10. HERO — index.html only
   --------------------------------------------------------------------------
   Composition:

       .hero__sky      top of the hero down to the horizon. overflow:hidden,
                       so its bottom edge IS the horizon the sun crests.
       .hero__mark     the sun and road lockup, resting on that bottom edge,
                       positioned so the sun's centre lands on --hero-sun-x.
       .hero__horizon  the hairline itself.
       .hero__ground   everything below the line. Headline left-aligned.

   The wordmark is not in the hero. The nav and the footer carry it, and the
   brand video has no wordmark to take timing from.
   ========================================================================== */

.hero {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background-color: var(--color-field-deep);
}

.hero__threads { z-index: var(--z-threads); }

/* --- Sky: the clipping band. Its bottom edge is the horizon. ------------ */
.hero__sky {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: var(--hero-horizon);
  overflow: hidden;
  z-index: var(--z-content);
  pointer-events: none;
}

/* --- The mark. Bottom sits on the horizon; the road meets the line. ----- */
/* The mark shares the headline's left axis, so the two read as one
   composition rather than two things that happen to be near each other.
   At the 1440px design width that axis is also the 22.7% x the mark
   occupies in the brand video; anchoring it here holds the relationship at
   every width instead of only that one. */
.hero__mark {
  position: absolute;
  bottom: 0;
  left: var(--content-left);
  width: var(--mark-size);
  aspect-ratio: var(--mark-aspect);
}

.hero__sun,
.hero__road-img,
.hero__wordmark { position: absolute; }

/* Riser. Carries translateY only, so the spin below never fights it. */
.hero__sun {
  inset: 0;
  will-change: transform;
}
.hero__sun-img {
  position: absolute;
  inset: 0;
  width: 100%;
  transform-origin: var(--mark-sun-cx) var(--mark-sun-cy);
  will-change: transform;
}

/* Road unroll ------------------------------------------------------------
   The wrapper is oversized and rotated so the road's own axis runs upright
   inside it. A plain inset() clip then sweeps bottom to top in that rotated
   space, which on screen travels from the wide near end toward the narrow far
   tip. The image counter-rotates about the same centre, so it renders upright.

   190%, not 150%: the lockup box is 2.15:1, and rotating a box that wide by
   23.85deg makes it 1.78x its own height. At 150% the road was clipped.
   Oversizing keeps every clip value inside 0%..100%, so no negative insets. */
.hero__road {
  position: absolute;
  inset: -45%;
  transform: rotate(var(--road-sweep));
  clip-path: inset(0 0 0 0);
}
.hero__road-img {
  left: 23.6842%;   /* 45 / 190 */
  top:  23.6842%;
  width: 52.6316%;  /* 100 / 190 */
  transform: rotate(calc(-1 * var(--road-sweep)));
}

/* Wordmark. Opacity only, no movement, once the road has completed. */
.hero__wordmark {
  inset: 0;
  width: 100%;
}

/* --- The horizon line --------------------------------------------------- */
.hero__horizon {
  position: absolute;
  top: var(--hero-horizon);
  left: 0;
  right: 0;
  height: var(--thread-weight-secondary);
  background-color: var(--color-gold-antique);
  transform-origin: left center;
  z-index: var(--z-content);
  pointer-events: none;
}

/* --- Ground: the copy. Left-aligned on the same axis as the mark. -------
   In normal flow, pushed clear of the horizon by its own top margin. If the
   copy runs taller than the space beneath the line the hero grows rather
   than cropping it. */
.hero__ground {
  position: relative;
  margin-top: var(--hero-horizon);
  padding-top: clamp(24px, 4.5svh, 56px);
  padding-bottom: clamp(72px, 11svh, 110px);  /* room for the chevron below */
  z-index: var(--z-content);
}

.hero__headline {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-hero-headline);
  line-height: 1.08;
  letter-spacing: -0.015em;
  color: var(--color-text-primary);
  max-width: 20ch;
  text-wrap: balance;
}

.hero__subhead {
  font-family: var(--font-body);
  font-size: var(--fs-hero-sub);
  line-height: 1.6;
  color: var(--color-text-secondary);
  max-width: 46ch;
  margin-top: clamp(16px, 2.4svh, 28px);
}

/* Pinned to the foot of the hero on the content axis, so it is always the
   last thing above the fold and never rides on the stack above it. */
.hero__scroll {
  position: absolute;
  left: var(--content-left);
  bottom: clamp(24px, 4.5svh, 52px);
  width: 24px;
  height: 24px;
  color: var(--color-text-secondary);
  stroke: currentColor;
  stroke-width: 1;
  fill: none;
  z-index: var(--z-content);
}

/* --- Hero keyframes ----------------------------------------------------- */

/* Sun crests the horizon. Cubic ease-out, measured from the video. */
@keyframes heroSunRise {
  from { transform: translateY(102%); }
  to   { transform: translateY(0); }
}

/* Flywheel. Constant angular velocity, then linear deceleration.
   The 4.779% stop must stay in step with --spin-duration and
   --spin-hold-deg above: a keyframe selector cannot take a custom property. */
@keyframes heroSunSpin {
  0% {
    transform: rotate(0deg);
    animation-timing-function: linear;
  }
  4.779% {
    transform: rotate(var(--spin-hold-deg));
    animation-timing-function: var(--ease-flywheel);
  }
  100% { transform: rotate(var(--spin-total-deg)); }
}

/* Road unrolls along its own axis, near end first. */
@keyframes heroRoadUnroll {
  from { clip-path: inset(100% 0 0 0); }
  to   { clip-path: inset(0 0 0 0); }
}

@keyframes heroLineDraw {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

@keyframes heroCopyRise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes heroFadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes heroChevronPulse {
  0%, 100% { opacity: 0.4; }
  50%      { opacity: 1; }
}

.js .hero__horizon {
  transform: scaleX(0);
  animation: heroLineDraw var(--d-horizon) var(--ease-thread) var(--t-horizon) both;
}
.js .hero__sun {
  animation: heroSunRise var(--d-sun) var(--ease-rise) var(--t-sun) both;
}
.js .hero__sun-img {
  animation: heroSunSpin var(--spin-duration) linear var(--t-sun) both;
}
.js .hero__road {
  animation: heroRoadUnroll var(--d-road) var(--ease-road) var(--t-road) both;
}
.js .hero__wordmark {
  opacity: 0;
  animation: heroFadeIn var(--d-word) var(--ease-out) var(--t-word) both;
}
.js .hero__headline {
  opacity: 0;
  animation: heroCopyRise var(--d-headline) var(--ease-out) var(--t-headline) both;
}
.js .hero__subhead {
  opacity: 0;
  animation: heroCopyRise var(--d-subhead) var(--ease-out) var(--t-subhead) both;
}
.js .hero__scroll {
  opacity: 0;
  animation:
    heroFadeIn       var(--d-chevron) var(--ease-out) var(--t-chevron) both,
    heroChevronPulse 1.5s ease-in-out calc(var(--t-chevron) + var(--d-chevron)) infinite;
}

/* Zero-height marker used by main.js to flip the nav background. */
.scroll-sentinel {
  display: block;
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  visibility: hidden;
  pointer-events: none;
}


/* ==========================================================================
   11. PAGE HERO — the-work.html / communique.html (static, no animation)
   ========================================================================== */

.page-hero {
  position: relative;
  display: flex;
  align-items: center;
  background-color: var(--color-field-deep);
  padding-block: calc(var(--section-pad) * 0.8);
}
.page-hero--work       { min-height: 60vh; min-height: 60svh; }
.page-hero--communique { min-height: 50vh; min-height: 50svh; }

/* 26ch, not 18: the page headlines are full sentences rather than two short
   stacked phrases, and at 18ch they broke to four cramped lines. Balanced so
   the wrap is even rather than leaving a widow. */
.page-hero__headline {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-page-headline);
  line-height: 1.12;
  letter-spacing: -0.015em;
  color: var(--color-text-primary);
  max-width: 26ch;
  text-wrap: balance;
}

.page-hero__subhead {
  font-family: var(--font-body);
  font-size: var(--fs-page-sub);
  line-height: 1.7;
  color: var(--color-text-secondary);
  max-width: 58ch;
  margin-top: 20px;
}


/* ==========================================================================
   12. CONVICTION SECTION — index.html section 2
   --------------------------------------------------------------------------
   .conviction__statement is the one place italic is spent. It is Dr. G
   speaking in the first person.
   ========================================================================== */

.conviction { position: relative; }

.conviction__copy { min-width: 0; }

.conviction__grid {
  display: grid;
  grid-template-columns: 58fr 42fr;
  gap: 64px;
  align-items: start;
}

.conviction__statement {
  font-family: var(--font-display);
  font-weight: 400;
  font-style: italic;
  font-size: var(--fs-conviction);
  line-height: 1.55;
  color: var(--color-text-primary);
  margin-top: 24px;
}
.conviction__statement p + p { margin-top: 1em; }

.conviction__body {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.8;
  color: var(--color-text-secondary);
  max-width: 62ch;
  margin-top: 32px;
}
.conviction__body p + p { margin-top: 1.2em; }

/* Portrait column — desktop and tablet only, hidden on mobile. */
.conviction__portrait { position: relative; }

.portrait-frame {
  position: relative;
  overflow: hidden;
}
.portrait-frame__img {
  width: 100%;
  max-height: 600px;
  object-fit: cover;
  object-position: center top;
}
.portrait-frame__fade {
  position: absolute;
  inset: 0;
  pointer-events: none;
  /* Ramp from the field colour at zero alpha, not from `transparent`: the
     latter is rgba(0,0,0,0), so the midpoint greys out. */
  background-image: linear-gradient(
    to bottom,
    var(--color-field-primary-0) 45%,
    var(--color-field-primary) 92%
  );
}


/* ==========================================================================
   13. WHO WE SERVE — index.html section 3
   ========================================================================== */

.serves { position: relative; }

.serves__lines {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.serves__line {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-serves);
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: var(--color-text-primary);
}
.serves__line:nth-child(1) { --stagger: 0s; }
.serves__line:nth-child(2) { --stagger: 0.2s; }
.serves__line:nth-child(3) { --stagger: 0.4s; }

.serves__note {
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  line-height: 1.7;
  color: var(--color-text-secondary);
  max-width: 58ch;
  margin-top: 28px;
}


/* ==========================================================================
   14. WORK PREVIEW TILES — index.html section 4
   --------------------------------------------------------------------------
   No numerals: these are three parallel offerings, not a sequence. Numbering
   lives on the-work.html, where the phases really are ordered.
   Each tile carries what is different afterward, which is the thing a reader
   actually needs.
   ========================================================================== */

.tiles {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}

/* --color-field-tile (#222224) drops --color-text-secondary to 4.38:1, under
   AA. On --color-field-primary the same muted grey is 4.70:1 and passes, so
   the tiles sit on that and the section beneath them carries --section--mid. */
.tile {
  position: relative;
  display: flex;
  flex-direction: column;
  background-color: var(--color-field-primary);
  padding: clamp(28px, 2.6vw, 40px);
}

.tile__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-tile-title);
  line-height: 1.25;
  color: var(--color-text-primary);
}

.tile__body {
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  line-height: 1.7;
  color: var(--color-text-secondary);
  margin-top: 16px;
}

.tile__change {
  margin-top: auto;
  padding-top: 28px;
}

.tile__change-label {
  display: block;
  font-family: var(--font-util);
  font-weight: var(--util-weight);
  font-size: var(--fs-label);
  letter-spacing: var(--util-track);
  text-transform: uppercase;
  color: var(--color-text-secondary);
  margin-bottom: 10px;
}

.tile__change-text {
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  line-height: 1.65;
  color: var(--color-text-primary);
}

.tiles__footer {
  margin-top: 40px;
}


/* ==========================================================================
   15. TWO-COLUMN PROSE ("duo")
   the-work.html section 2, communique.html section 2
   ========================================================================== */

.duo {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 64px;
  align-items: start;
}

.duo__lead {
  font-family: var(--font-display);
  font-weight: 400;
  font-style: italic;
  font-size: var(--fs-duo-lead);
  line-height: 1.6;
  color: var(--color-text-primary);
}
.duo__lead p + p { margin-top: 1em; }

.duo__body {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.8;
  color: var(--color-text-secondary);
}
.duo__body p + p { margin-top: 1.2em; }

.duo__note {
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  line-height: 1.7;
  color: var(--color-text-secondary);
  margin-top: 48px;
}


/* ==========================================================================
   16. FOCUS AREAS — the-work.html section 3
   ========================================================================== */

.focus-list {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

/* Same reason as .tile: --color-field-tile (#222224) drops
   --color-text-secondary to 4.38:1, under AA. On --color-field-primary it is
   4.70:1 and passes, and the block still reads as raised off --section--mid. */
.focus {
  position: relative;
  background-color: var(--color-field-primary);
  padding: clamp(28px, 3.2vw, 48px);
  display: grid;
  grid-template-columns: 60fr 40fr;
  gap: 48px;
  align-items: start;
}

.focus__title {
  grid-column: 1 / -1;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-focus-title);
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: var(--color-text-primary);
}

.focus__body {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.8;
  color: var(--color-text-secondary);
}
.focus__body p + p { margin-top: 1.2em; }

.focus__aside {
  border-left: 1px solid var(--color-rail-soft);
  padding-left: 24px;
}

.focus__change-label {
  display: block;
  font-family: var(--font-util);
  font-weight: var(--util-weight);
  font-size: var(--fs-label);
  letter-spacing: var(--util-track);
  text-transform: uppercase;
  color: var(--color-text-secondary);
  margin-bottom: 12px;
}

.focus__change {
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  line-height: 1.7;
  color: var(--color-text-primary);
}


/* ==========================================================================
   17. ENGAGEMENT STRUCTURE TIMELINE — the-work.html section 4
   --------------------------------------------------------------------------
   This IS a sequence, so this is where numbering belongs.
   ========================================================================== */

.phases {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 32px;
}

.phase {
  position: relative;
  padding-top: 28px;
}
.phase::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background-color: var(--color-rail-soft);
}

.phase__marker {
  position: absolute;
  top: -3px;
  left: 0;
  width: 7px;
  height: 7px;
  background-color: var(--color-gold-antique);
}

.phase__num {
  display: block;
  font-family: var(--font-util);
  font-weight: var(--util-weight);
  font-size: var(--fs-label);
  letter-spacing: var(--util-track);
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  color: var(--color-text-secondary);
  margin-bottom: 12px;
}

.phase__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-phase-title);
  line-height: 1.25;
  color: var(--color-text-primary);
}

.phase__body {
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  line-height: 1.7;
  color: var(--color-text-secondary);
  margin-top: 12px;
}


/* ==========================================================================
   18. NEWSLETTER CTA — communique.html section 3
   ========================================================================== */

.newsletter { text-align: center; }

.newsletter__text {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.8;
  color: var(--color-text-primary);
  max-width: 62ch;
  margin-inline: auto;
}

.newsletter__button { margin-top: 32px; }

.newsletter__note {
  font-family: var(--font-body);
  font-size: var(--fs-micro);
  line-height: 1.6;
  color: var(--color-text-secondary);
  margin-top: 16px;
}


/* ==========================================================================
   19. CTA CONVERGENCE SECTION — all three pages
   --------------------------------------------------------------------------
   The horizon arrives here. It runs full bleed, and the one gold object on
   the site sits on it. The threads converge above the headline, so nothing
   crosses type.
   ========================================================================== */

.cta {
  position: relative;
  overflow: hidden;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  align-items: center;
  background-color: var(--color-field-deep);
}

.cta__threads { z-index: var(--z-threads); }

.cta__inner {
  position: relative;
  z-index: var(--z-content);
  text-align: center;
  width: 100%;
}

.cta__headline {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-cta-headline);
  line-height: 1.16;
  letter-spacing: -0.015em;
  color: var(--color-text-primary);
  max-width: 20ch;
  margin-inline: auto;
  text-wrap: balance;
}

.cta__subhead {
  font-family: var(--font-body);
  font-size: var(--fs-cta-sub);
  line-height: 1.7;
  color: var(--color-text-secondary);
  max-width: 52ch;
  margin: 20px auto 0;
}

/* The horizon, and the button standing on it. Full bleed by design: this
   element sits outside .container. */
.cta__act {
  display: flex;
  align-items: center;
  gap: clamp(20px, 4vw, 56px);
  margin-top: clamp(40px, 6vh, 64px);
  padding-inline: 0;
}

.cta__act-line {
  flex: 1 1 0;
  height: var(--thread-weight-secondary);
  background-color: var(--color-gold-antique);
  transform: scaleX(0);
}
.cta__act-line:first-child { transform-origin: right center; }
.cta__act-line:last-child  { transform-origin: left center; }

.js .cta__act-line {
  transition: transform 0.7s var(--ease-thread);
  transition-delay: 1.2s;
}
.cta.is-inview .cta__act-line { transform: scaleX(1); }

/* Button arrives at convergence: threads finish at 1.4s. */
.cta__button {
  flex: 0 0 auto;
  --stagger: 1.4s;
}
.js .cta__button {
  transition:
    opacity          0.4s var(--ease-out),
    transform        0.4s var(--ease-out),
    background-color 0.2s var(--ease-out);
  /* the shorthand above resets transition-delay, so restate it */
  transition-delay: calc(var(--reveal-base-delay) + var(--stagger, 0s)),
                    calc(var(--reveal-base-delay) + var(--stagger, 0s)),
                    0s;
}

.cta__byline {
  font-family: var(--font-util);
  font-weight: var(--util-weight);
  font-size: var(--fs-micro);
  letter-spacing: 0.08em;
  line-height: 1.7;
  color: var(--color-text-secondary);
  margin-top: 28px;
  --stagger: 1.7s;
}


/* ==========================================================================
   20. FOOTER — identical on all three pages
   ========================================================================== */

.site-footer {
  background-color: var(--color-field-deep);
  border-top: 1px solid var(--color-gold-antique);
  padding-block: 64px;
}

.site-footer__inner {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 40px;
  align-items: start;
}

.site-footer__brand { min-width: 0; }

.site-footer__logo {
  width: clamp(140px, 12vw, 150px);
  height: auto;
}

.site-footer__copyright {
  font-family: var(--font-util);
  font-size: var(--fs-fine);
  letter-spacing: 0.04em;
  line-height: 1.6;
  color: var(--color-text-secondary);
  margin-top: 20px;
}

/* Legacy third column on the-work.html and communique.html. The footer is a
   two-column layout; this keeps those pages correct until they are rebuilt. */
.site-footer__spacer { display: none; }

.site-footer__links {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 12px;
  text-align: right;
}

.site-footer__link {
  font-family: var(--font-body);
  font-size: var(--fs-micro);
  color: var(--color-gold-antique);
  border-bottom: 1px solid transparent;
  transition: border-color 0.2s var(--ease-out);
}
.site-footer__link:hover,
.site-footer__link:focus-visible { border-bottom-color: var(--color-gold-antique); }


/* ==========================================================================
   21. ELENA SALESIQ — keep the widget under the navigation
   ========================================================================== */

#zsiqwidget,
.zsiq_floatmain,
.zsiq_flt_rel,
div[id^="zsiq"] {
  z-index: var(--z-salesiq) !important;
}


/* ==========================================================================
   22. BREAKPOINT — TABLET  (768px to 1199px)
   Layout only. The type scale is fluid and never re-declared.
   ========================================================================== */

@media (max-width: 1199px) {
  :root {
    --gutter:      48px;
    --section-pad: 88px;
  }

  .conviction__grid { grid-template-columns: 62fr 38fr; gap: 40px; }
  .duo              { gap: 40px; }
  .tiles            { gap: 16px; }
  .focus            { gap: 32px; }
  .phases           { grid-template-columns: repeat(2, 1fr); gap: 32px 24px; }
}


/* ==========================================================================
   23. BREAKPOINT — MOBILE  (below 768px)
   Single column, portrait HIDDEN, hamburger nav.
   ========================================================================== */

@media (max-width: 767px) {
  :root {
    --gutter:        24px;
    --section-pad:   64px;
    --hero-horizon:  42svh;
    /* The lockup is 2.15:1 with a small second line, so on a phone it takes
       the whole content column or the wordmark stops being readable. */
    --mark-size:     min(calc(100vw - 2 * var(--gutter)), 360px);
  }

  /* Nav: links out, hamburger in */
  .site-nav          { padding: 16px var(--gutter); }
  .site-nav__links   { display: none; }
  .site-nav__toggle  { display: block; }

  /* Layout collapses to one column */
  .conviction__grid  { grid-template-columns: 1fr; gap: 32px; }
  .conviction__portrait { display: none; }
  .duo               { grid-template-columns: 1fr; gap: 32px; }
  .tiles             { grid-template-columns: 1fr; gap: 16px; }
  .focus             { grid-template-columns: 1fr; gap: 24px; }
  .focus__aside      { border-left: 0; border-top: 1px solid var(--color-rail-soft);
                       padding-left: 0; padding-top: 20px; }

  /* Timeline becomes vertical */
  .phases            { grid-template-columns: 1fr; gap: 32px; }
  .phase             { padding-top: 0; padding-left: 28px; }
  .phase::before     { top: 0; bottom: 0; left: 0; right: auto;
                       width: 1px; height: auto; }
  .phase__marker     { top: 0; left: -3px; }

  /* Footer stacks */
  .site-footer__inner { grid-template-columns: 1fr; gap: 32px; }
  .site-footer__links { align-items: flex-start; text-align: left; }

  .section__label    { margin-bottom: 24px; }
  .tile__change      { padding-top: 20px; }

  /* The CTA horizon needs the button to stay readable at 375px. */
  .cta__act          { gap: 16px; }
}


/* ==========================================================================
   24. SHORT-VIEWPORT GUARD
   The hero has to resolve above the fold on short laptop screens and small
   phones. Only the horizon height and the mark scale need to move: the type
   is already fluid.
   ========================================================================== */

@media (max-width: 767px) and (max-height: 720px) {
  :root {
    --hero-horizon: 38svh;
    --mark-size:    min(calc(100vw - 2 * var(--gutter)), 300px);
  }
}

@media (min-width: 768px) and (max-height: 860px) {
  :root {
    --hero-horizon: 46svh;
    --mark-size:    clamp(300px, 32vw, 430px);
  }
}

@media (min-width: 768px) and (max-height: 700px) {
  :root {
    --hero-horizon: 42svh;
    --mark-size:    clamp(280px, 28vw, 380px);
  }
  .hero__scroll { display: none; }
}


/* ==========================================================================
   25. REDUCED MOTION
   Everything resolves instantly in its final resting state.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {

  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    transition-delay: 0s !important;
  }

  .js .hero__sun,
  .js .hero__sun-img,
  .js .hero__wordmark,
  .js .hero__headline,
  .js .hero__subhead,
  .js .hero__scroll {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }

  /* The travelling head and its dust are motion for its own sake. Drop them.
     main.js also checks prefers-reduced-motion and settles the threads
     straight and fully drawn without running the arrival. */
  .thread-comet,
  .thread-dust { display: none !important; }

  .js .thread { stroke-dashoffset: 0 !important; }

  /* The nav mark simply appears, already formed. */
  .js .nav-mark--forming .nav-mark__sun,
  .js .nav-mark--forming .nav-mark__sun-img {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  .js .nav-mark--forming .nav-mark__road {
    animation: none !important;
    clip-path: inset(0 0 0 0) !important;
    transform: rotate(var(--road-sweep)) !important;
  }

  .js .hero__road {
    animation: none !important;
    clip-path: inset(0 0 0 0) !important;
    transform: rotate(var(--road-sweep)) !important;
  }

  .js .hero__horizon {
    animation: none !important;
    transform: scaleX(1) !important;
  }

  .js .reveal {
    opacity: 1 !important;
    transform: none !important;
  }

  .horizon,
  .section__rule,
  .cta__act-line { transform: scaleX(1) !important; }

  .js .hero__threads .thread,
  .js .cta__threads .thread,
  .js .cta.is-inview .cta__threads .thread {
    animation: none !important;
    stroke-dasharray: none !important;
    stroke-dashoffset: 0 !important;
  }
}


/* ==========================================================================
   26. PRINT — minimal courtesy sheet
   ========================================================================== */

@media print {
  .site-nav,
  .mobile-menu,
  .thread-field,
  .hero__horizon,
  .cta__act-line,
  .hero__scroll { display: none !important; }

  .js .reveal { opacity: 1 !important; transform: none !important; }
}
