/* ============================================================
   TM ADVISORS / Design System v2 "Meridian"
   One stylesheet. Every page. No inline <style> blocks.
   ============================================================ */

/* ---------- 1. TOKENS ---------- */
:root {
  /* Ink scale: mid slate-navy. Light enough to read comfortably, dark enough
     to stay premium. Every surface derives from these. */
  --ink-950: #16232f;
  --ink-900: #1b2a38;
  --ink-850: #203141;
  --ink-800: #26394b;
  --ink-700: #2f4457;
  --ink-600: #3a5069;

  /* Translucent veil used by grid tiles, so they track the background gradient
     instead of sitting on it as flat blocks. */
  --tile: rgba(14, 24, 35, 0.45);

  /* Brand */
  --navy: #16283d;
  --gold: #c5a47e;
  --gold-lt: #e8d7b8;
  --gold-dk: #96754d;
  --grad-gold: linear-gradient(115deg, #e8d7b8 0%, #c5a47e 46%, #9c7f5c 100%);

  /* Foreground alphas measured against the COMPOSITED field, not a flat stop.
     The field was lifted a step lighter per client feedback; its lightest painted
     point is the top-left blue glow, which at ::before opacity 0.64 composites to
     about rgb(58,81,105). Because .bg-field is fixed, everything scrolls through
     that band, so it is the worst case. Over it this ramp measures 4.63 / 5.49 /
     6.25 (fg-4 / fg-3 / fg-2), higher on the darker panels and inputs. The alphas
     were raised together with the lift so brightening did not cost contrast:
     every muted tier still clears AA and the three steps still read apart. */
  --fg: #f2f5f8;
  --fg-2: rgba(242, 245, 248, 0.88);
  --fg-3: rgba(242, 245, 248, 0.80);
  --fg-4: rgba(242, 245, 248, 0.70);

  /* Lines & surfaces */
  --line: rgba(255, 255, 255, 0.10);
  --line-2: rgba(255, 255, 255, 0.18);
  --surface: rgba(255, 255, 255, 0.04);
  --surface-2: rgba(255, 255, 255, 0.075);

  /* Type */
  --serif: "Instrument Serif", "Playfair Display", Georgia, "Times New Roman", serif;
  --sans: "Inter", "Montserrat", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

  /* Rhythm */
  --gutter: clamp(1.5rem, 4vw, 4.5rem);   /* 24px floor, was 20px */
  --max: 1440px;
  --max-narrow: 980px;
  /* Vertical rhythm, tightened per client feedback (padding between elements
     was too large across the site). Roughly 35-40% less than before. */
  --section-y: clamp(3.25rem, 6.5vw, 6rem);

  /* Spacing scale + shared gaps/tile padding, so gaps stop being ad hoc */
  --space-2xs: 0.5rem; --space-xs: 0.7rem; --space-sm: 0.9rem;
  --space-md: 1.3rem; --space-lg: 1.7rem; --space-xl: 2.4rem;
  --gap-grid: clamp(1.1rem, 2vw, 1.8rem);
  --gap-flow: clamp(1.5rem, 3vw, 2.6rem);
  --pad-tile: clamp(1.7rem, 2.9vw, 2.5rem);
  --pad-tile-sm: clamp(1.25rem, 2.2vw, 1.8rem);

  /* Type: one mid-heading step + a size-keyed uppercase tracking ramp
     (tighter as caps grow), so every label reads typeset by one hand. */
  --h4: clamp(1.72rem, 2.15vw, 2rem);
  --track-cap-lg: 0.14em;   /* ~0.76-0.85rem caps */
  --track-cap-md: 0.2em;    /* ~0.68-0.72rem caps */
  --track-cap-sm: 0.24em;   /* ~0.6-0.63rem caps */

  /* Body / narrative / box text scale. Raised ~40% per client feedback; the
     display and heading sizes stay as they were. Change these to retune the
     whole reading size of the site in one place. */
  --lead: clamp(1.35rem, 1.7vw, 1.62rem);
  --body: 1.24rem;       /* card + section body copy */
  --body-sm: 1.12rem;    /* dense lists / secondary copy */
  --body-lh: 1.6;

  /* Depth: one ambient elevation tier between the flat field and the deep
     overlay shadows on the dialog/dropdown. */
  --elev-1: 0 26px 60px -34px rgba(0, 0, 0, 0.66);

  /* Motion */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-io: cubic-bezier(0.65, 0, 0.35, 1);
  --dur-fast: 0.35s; --dur: 0.6s; --dur-slow: 0.9s; --stagger: 70ms;

  --header-h: 84px;
  color-scheme: dark;
}

/* ---------- 2. RESET ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.65;
  color: var(--fg);
  background: var(--ink-950);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-synthesis-weight: none;
}

img, svg, picture, video { display: block; max-width: 100%; }
img { height: auto; }
button, input, textarea, select { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; }

:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
  border-radius: 2px;
}

::selection { background: var(--gold); color: var(--ink-950); }

.skip-link {
  position: absolute; top: -100px; left: var(--gutter); z-index: 9999;
  background: var(--gold); color: var(--ink-950);
  padding: 0.85rem 1.5rem; font-weight: 600; font-size: 0.85rem;
  letter-spacing: 0.04em; border-radius: 0 0 4px 4px;
  transition: top 0.25s var(--ease);
}
.skip-link:focus { top: 0; }

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

/* ---------- 3. AMBIENT BACKGROUND ---------- */
.bg-field { position: fixed; inset: 0; z-index: -2; pointer-events: none; background: var(--ink-950); }
.bg-field::before {
  content: ""; position: absolute; inset: 0;
  /* Slate-navy field, lifted one step lighter per client feedback while keeping
     muted copy over AA (see the --fg tokens for the measured ratios). .bg-field
     paints --ink-950 beneath, so this opacity seats the layers into the navy; at
     0.64 the lightest point (top-left blue glow) composites to ~rgb(58,81,105).
     Hue and layer relationships are unchanged, everything is just a shade
     brighter and a touch more saturated. */
  opacity: 0.64;
  background:
    radial-gradient(90rem 55rem at 12% -12%, rgba(116, 154, 192, 0.40) 0%, transparent 62%),
    radial-gradient(70rem 45rem at 96% 6%, rgba(197, 164, 126, 0.16) 0%, transparent 58%),
    radial-gradient(80rem 60rem at 50% 108%, rgba(48, 72, 98, 0.62) 0%, transparent 65%),
    linear-gradient(180deg, #344c65 0%, #2c3f54 45%, #24384c 100%);
}
/* Film grain: kills gradient banding, adds a printed-paper quality.
   No mix-blend-mode. A blend mode on a fixed, full-viewport layer makes the
   compositor run a blend pass over the whole screen on every composited frame,
   which is every frame of every scroll. At 3.5% opacity the overlay maths was
   doing almost nothing visible for that price, so this is a plain alpha wash at
   a slightly higher opacity to match the old density. */
.bg-field::after {
  content: ""; position: absolute; inset: 0; opacity: 0.05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 220 220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
#contour { position: fixed; inset: 0; z-index: -1; width: 100%; height: 100%; pointer-events: none; opacity: 0.55; }

/* ---------- 3b. INTRO CURTAIN (home first-load only) ----------
   A brand-navy curtain with the logo and a gold hairline that fills, then
   lifts to reveal the hero. Gated by an inline <head> script that adds
   .intro-done to <html> to skip it (repeat session visit, deep link, or
   reduced-motion), so there is no flash-then-hide. */
.intro {
  position: fixed; inset: 0; z-index: 4000; display: grid; place-items: center;
  background:
    radial-gradient(60rem 60rem at 50% 42%, #24384c 0%, #101d29 70%),
    #101d29;
  animation: intro-lift 0.85s var(--ease) forwards;
  animation-delay: 1.15s;
}
.intro-mark { display: flex; flex-direction: column; align-items: center; gap: 1.7rem; padding: 0 2rem; }
.intro-logo {
  height: clamp(40px, 6vw, 54px); width: auto; filter: brightness(0) invert(1);
  opacity: 0; transform: translateY(12px);
  animation: intro-logo 0.9s var(--ease) forwards 0.12s;
}
.intro-bar { width: min(210px, 55vw); height: 1px; background: rgba(255, 255, 255, 0.14); overflow: hidden; }
.intro-bar > span {
  display: block; height: 100%; width: 100%; background: var(--grad-gold);
  transform: scaleX(0); transform-origin: left;
  animation: intro-fill 1.02s var(--ease) forwards 0.18s;
}
@keyframes intro-logo { to { opacity: 1; transform: none; } }
@keyframes intro-fill { to { transform: scaleX(1); } }
@keyframes intro-lift { to { opacity: 0; visibility: hidden; transform: translateY(-100%); } }
.intro-done .intro { display: none; }
@media (prefers-reduced-motion: reduce) { .intro { display: none; } }

/* ---------- 4. LAYOUT ---------- */
.shell { width: 100%; max-width: var(--max); margin-inline: auto; padding-inline: var(--gutter); }
.shell--narrow { max-width: var(--max-narrow); }
.section { padding-block: var(--section-y); position: relative; }
/* Stacked sections collapse to one rhythm at the seam, so every gap is one
   --section-y instead of a doubled void. Replaces the per-page inline padding
   hacks. */
.section + .section { padding-top: 0; }
.section--intro { padding-top: clamp(1rem, 3vw, 2.5rem); }  /* first section after a page-hero */
/* The CTA band stays a distinct destination with symmetric internal padding;
   pull the doubled gap by dropping the preceding section's bottom pad instead. */
.section:has(+ .cta-band) { padding-bottom: 0; }
/* Must out-specify `.section + .section` (0,2,0) so the CTA keeps symmetric
   internal padding while the preceding section's bottom pad is pulled above. */
.section.cta-band { padding-top: var(--section-y); }
.rule { height: 1px; background: var(--line); border: 0; }

/* ---------- 5. TYPOGRAPHY ---------- */
.display {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(3.4rem, 8.8vw, 8rem);
  line-height: 0.96; letter-spacing: -0.025em;
}
.h2 {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(2.6rem, 5.4vw, 4.5rem);
  line-height: 1.04; letter-spacing: -0.02em;
}
.h3 { font-family: var(--serif); font-weight: 400; font-size: clamp(1.78rem, 2.5vw, 2.35rem); line-height: 1.16; letter-spacing: -0.015em; }
/* Serif optical rendering + balanced rag: heads are judged on their line breaks. */
.display, .h2, .h3, .strategy-aside h2, .bio-side h2, .svc-card h2 {
  text-rendering: optimizeLegibility; font-feature-settings: "kern" 1, "liga" 1;
  text-wrap: balance;
}
.gold-text {
  font-style: italic;
  background: var(--grad-gold);
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
  /* background-clip:text fills the glyphs from the gradient, but the gradient is
     only painted within the element's box. With the display line-height (0.94)
     the box stops above the italic descender, so the tail of a "p" or "g" gets
     no gradient and renders transparent (visible only when you select the text,
     which repaints it normally). Bottom padding extends the paint box below the
     baseline; inline vertical padding does not affect layout, so nothing moves. */
  padding-bottom: 0.2em;
}
.eyebrow {
  display: inline-flex; align-items: center; gap: 0.7rem;
  font-size: 0.8rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: var(--track-cap-md); color: var(--gold);
}
.eyebrow::before { content: ""; width: 1.9rem; height: 1px; background: var(--gold); opacity: 0.65; }
/* Weight 300 is reserved for the display-sized lead only. All body-sized running
   text sits at 400 so it holds its ink over the moving field. */
.lead { font-size: var(--lead); line-height: 1.5; color: var(--fg-2); font-weight: 300; max-width: 48ch; text-wrap: pretty; }
.body-sm { font-size: var(--body-sm); line-height: 1.55; color: var(--fg-2); font-weight: 400; text-wrap: pretty; }

.section-head { margin-bottom: calc(var(--section-y) * 0.5); }
.section-head .h2 { margin-top: 1.4rem; max-width: 20ch; }
.section-head--center { text-align: center; }
.section-head--center .eyebrow::before { display: none; }
.section-head--center .h2 { margin-inline: auto; }

/* ---------- 6. ICONS ---------- */
.icon { width: 1.25em; height: 1.25em; flex: none; stroke: currentColor; fill: none; stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; }
.icon--lg { width: 1.9rem; height: 1.9rem; stroke-width: 1.1; }

/* ---------- 7. BUTTONS ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.65rem;
  padding: 0.95rem 1.9rem; border-radius: 999px;
  font-size: 0.83rem; font-weight: 600; letter-spacing: 0.075em; text-transform: uppercase;
  white-space: nowrap; transition: all var(--dur-fast) var(--ease); position: relative; overflow: hidden;
}
.btn .icon { transition: transform 0.4s var(--ease); }
.btn:hover .icon { transform: translateX(4px); }
.btn:active { transform: scale(0.985); transition-duration: 0.09s; }

.btn--primary { background: var(--fg); color: var(--ink-950); }
.btn--primary:hover { background: var(--gold-lt); box-shadow: 0 0 0 1px var(--gold-lt), 0 14px 40px -12px rgba(197, 164, 126, 0.55); }

.btn--ghost { color: var(--fg); box-shadow: inset 0 0 0 1px var(--line-2); }
.btn--ghost:hover { box-shadow: inset 0 0 0 1px var(--gold); color: var(--gold-lt); background: rgba(197, 164, 126, 0.06); }

.btn--gold { background: var(--gold); color: var(--ink-950); }
.btn--gold:hover { background: var(--gold-lt); transform: translateY(-2px); box-shadow: 0 18px 45px -14px rgba(197, 164, 126, 0.6); }
.btn--gold:active { transform: scale(0.985); box-shadow: 0 6px 16px -10px rgba(197, 164, 126, 0.55); }
/* One restrained gleam sweeps across the primary CTA on hover (uses .btn overflow:hidden). */
.btn--gold::before {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(115deg, transparent 38%, rgba(255, 255, 255, 0.38) 50%, transparent 62%);
  transform: translateX(-130%); transition: transform 0.75s var(--ease);
}
.btn--gold:hover::before { transform: translateX(130%); }

.link-arrow {
  display: inline-flex; align-items: center; gap: 0.6rem;
  font-size: 0.85rem; font-weight: 600; letter-spacing: var(--track-cap-lg); text-transform: uppercase;
  color: var(--fg-3); transition: color 0.35s var(--ease);
}
.link-arrow .icon { transition: transform 0.4s var(--ease); }
.link-arrow:hover { color: var(--gold); }
.link-arrow:hover .icon { transform: translateX(5px); }

/* ---------- 8. HEADER ---------- */
.site-header {
  position: fixed; inset: 0 0 auto; z-index: 1000; height: var(--header-h);
  display: flex; align-items: center;
  transition: height 0.45s var(--ease), background 0.45s var(--ease), box-shadow 0.45s var(--ease);
}
.site-header::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  /* The blur is re-sampled every scroll frame the header is stuck. Blur cost
     scales with the radius, so the radius comes down and the fill goes up a
     little to keep the same density behind the type. */
  background: rgba(26, 40, 56, 0.88);
  backdrop-filter: blur(12px) saturate(1.3); -webkit-backdrop-filter: blur(12px) saturate(1.3);
  border-bottom: 1px solid var(--line);
  opacity: 0; transition: opacity 0.45s var(--ease);
}
.site-header.is-stuck { height: 68px; }
.site-header.is-stuck::before { opacity: 1; }

.header-inner { width: 100%; max-width: var(--max); margin-inline: auto; padding-inline: var(--gutter); display: flex; align-items: center; justify-content: space-between; gap: 2rem; }
/* Logo and award travel together, so header-inner still has three children and
   its space-between distribution is unchanged. */
.header-brand { display: flex; align-items: center; gap: clamp(0.7rem, 1.3vw, 1.15rem); flex: none; min-width: 0; }
.brand { display: block; flex: none; }
.brand img { height: 42px; width: auto; filter: brightness(0) invert(1); transition: height 0.45s var(--ease); }
.site-header.is-stuck .brand img { height: 34px; }

/* The award, moved out of the hero on Brett's note. The hero sizing (81px to
   117px, with a heavy drop shadow to lift it off the band) is wrong at header
   scale, so both are reset here rather than loosened there. */
.header-accolade { flex: none; padding-left: clamp(0.7rem, 1.3vw, 1.15rem); border-left: 1px solid var(--line); }
/* Sized up: 38px was timid next to a 42px logo, and the award is the point.
   At 54px it clears the logo and still leaves 15px of air top and bottom in
   the 84px bar, 11px in the 68px stuck bar. */
.header-accolade .accolade-badge {
  height: 54px; filter: none;
  transition: height 0.45s var(--ease);
}
.site-header.is-stuck .header-accolade .accolade-badge { height: 44px; }
/* If the artwork 404s, the text fallback has to fit a header, not a hero. */
.header-accolade.no-badge [data-badge-fallback] { padding-left: 0; border-left: 0; gap: 0.1rem; }
.header-accolade .accolade-pub { font-size: 0.54rem; }
.header-accolade .accolade-award { font-size: 0.8rem; }

.nav { display: flex; align-items: center; gap: clamp(1.1rem, 2vw, 2.1rem); }
.nav-link {
  position: relative; font-size: 0.94rem; font-weight: 400; letter-spacing: 0.015em;
  color: var(--fg-2); padding-block: 0.4rem; transition: color 0.3s var(--ease); white-space: nowrap;
}
.nav-link::after {
  content: ""; position: absolute; left: 0; bottom: 0; height: 1px; width: 100%;
  background: var(--gold); transform: scaleX(0); transform-origin: right;
  transition: transform 0.45s var(--ease);
}
.nav-link:hover { color: var(--fg); }
.nav-link:hover::after, .nav-link[aria-current]::after { transform: scaleX(1); transform-origin: left; }
.nav-link[aria-current] { color: var(--fg); }

.nav-divider { width: 1px; height: 18px; background: var(--line-2); }

.dropdown { position: relative; }
.dropdown-trigger { display: inline-flex; align-items: center; gap: 0.45rem; }
.dropdown-trigger .icon { width: 0.85em; height: 0.85em; transition: transform 0.35s var(--ease); }
.dropdown[data-open="true"] .dropdown-trigger .icon { transform: rotate(180deg); }
.dropdown-menu {
  position: absolute; top: calc(100% + 1.1rem); right: 0; width: 250px;
  /* 97% opaque, so the blur it used to carry was not visible through it. */
  background: rgba(28, 43, 60, 0.97);
  border: 1px solid var(--line-2); border-radius: 6px;
  box-shadow: 0 30px 70px -20px rgba(0, 0, 0, 0.8);
  padding: 0.4rem; overflow: hidden;
  opacity: 0; visibility: hidden; transform: translateY(-8px) scale(0.98);
  transition: opacity 0.3s var(--ease), transform 0.3s var(--ease), visibility 0.3s;
}
.dropdown[data-open="true"] .dropdown-menu { opacity: 1; visibility: visible; transform: none; }
.dropdown-menu a {
  position: relative;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 0.95rem 1.1rem; font-size: 0.86rem; color: var(--fg-2);
  border-radius: 4px; transition: background 0.25s, color 0.25s;
}
.dropdown-menu a::before {
  content: ""; position: absolute; left: 0; top: 50%; width: 2px; height: 0;
  background: var(--grad-gold); border-radius: 2px; transform: translateY(-50%);
  transition: height 0.3s var(--ease);
}
.dropdown-menu a:hover::before { height: 58%; }
.dropdown-menu a .icon { opacity: 0.4; transition: opacity 0.25s, transform 0.35s var(--ease); }
.dropdown-menu a:hover { background: var(--surface-2); color: var(--fg); }
.dropdown-menu a:hover .icon { opacity: 1; color: var(--gold); transform: translate(2px, -2px); }
/* The portal trigger stays lit (colour + underline) while its menu is open. */
.dropdown[data-open="true"] .dropdown-trigger { color: var(--fg); }
.dropdown[data-open="true"] .dropdown-trigger::after { transform: scaleX(1); transform-origin: left; }
/* Every chrome link flashes gold on press. */
.nav-link:active, .dropdown-menu a:active, .footer-bottom a:active,
.footer-bottom nav a:active, .loc a:active, .footer-contact a:active, .direct-line:active { color: var(--gold); }
/* Contact 'you are here' marker on the header CTA. */
.header-actions .btn[aria-current="page"] { box-shadow: inset 0 0 0 1px var(--gold); }

.header-actions { display: flex; align-items: center; gap: 1rem; flex: none; }
.header-actions .btn { padding: 0.78rem 1.6rem; font-size: 0.75rem; }

.burger { display: none; width: 44px; height: 44px; align-items: center; justify-content: center; color: var(--fg); margin-right: -10px; }
.burger .icon { width: 24px; height: 24px; }

/* ---------- 9. MOBILE DRAWER ---------- */
.drawer {
  position: fixed; inset: 0; z-index: 1200;
  /* No backdrop-filter here. At 98.5% opaque only 1.5% of the page shows
     through, so a blur on it is invisible, yet it still forces the compositor
     to snapshot and blur the whole screen every frame the drawer animates.
     That is the entire cost with none of the effect. */
  background: rgba(24, 37, 52, 0.985);
  /* The nav needs about 578px of height. Centred with no overflow, and with body
     scroll locked while it is open, anything shorter than that silently cut the
     top links off and pushed the Contact CTA entirely below the screen with no
     way to reach it. That is every phone in landscape. flex-start plus auto
     margins on the nav keeps it optically centred when it fits and falls back to
     top aligned and scrollable when it does not. */
  display: flex; flex-direction: column; justify-content: flex-start;
  padding: clamp(5rem, 12vh, 6rem) var(--gutter) clamp(2rem, 6vh, 3rem);
  overflow-y: auto; overscroll-behavior: contain;
  /* No transform on the drawer itself. Any transformed ancestor becomes the
     containing block for position:fixed descendants, which would pin the close
     button to the drawer rather than the viewport and let it scroll away with
     the content. The staggered link rise below already carries the entrance. */
  opacity: 0; visibility: hidden;
  transition: opacity 0.5s var(--ease), visibility 0.5s;
}
.drawer.is-open { opacity: 1; visibility: visible; }
/* Fixed, not absolute: an absolutely positioned child of a scroll container
   scrolls away with the content, taking the only close affordance with it. */
.drawer-close { position: fixed; z-index: 1; top: 1.6rem; right: calc(var(--gutter) - 10px); width: 44px; height: 44px; display: flex; align-items: center; justify-content: center; color: var(--fg-2); }
.drawer-nav { display: flex; flex-direction: column; gap: 0.15rem; flex: none; margin-block: auto; }
.drawer-nav a {
  font-family: var(--serif); font-size: clamp(2rem, 8vw, 2.9rem); line-height: 1.25;
  color: var(--fg); padding-block: 0.35rem;
  opacity: 0; transform: translateY(18px);
  transition: opacity 0.55s var(--ease), transform 0.55s var(--ease), color 0.3s;
}
.drawer.is-open .drawer-nav a { opacity: 1; transform: none; transition-delay: calc(var(--i) * 55ms + 90ms); }
.drawer-nav a:active { color: var(--gold); }
.drawer-group { display: block; font-size: 0.68rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.26em; color: var(--gold); margin-top: 2rem; margin-bottom: 0.75rem; }
.drawer-sub { font-family: var(--sans) !important; font-size: 1.02rem !important; color: var(--fg-2) !important; display: flex; align-items: center; gap: 0.55rem; }
/* Selector must out-specify `.drawer-nav a`, which would otherwise impose the
   serif display face and 2.9rem size on the pill button. */
.drawer-nav a.drawer-cta {
  margin-top: 2.4rem; align-self: flex-start;
  font-family: var(--sans); font-size: 0.83rem; line-height: 1;
  padding: 1.1rem 2.2rem;
}

/* ---------- 10. HERO ---------- */
.hero {
  /* vh first as a fallback: a browser without svh support drops the whole
     declaration, and the hero would collapse to content height. */
  min-height: min(100vh, 900px);
  min-height: min(100svh, 900px);
  display: flex; align-items: flex-end;
  padding-top: calc(var(--header-h) + 4rem); padding-bottom: clamp(2.5rem, 5vw, 4.5rem);
  position: relative; isolation: isolate;
}
/* Scrim seats the hero type on the moving field so the headline never floats. */
.hero::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: radial-gradient(70rem 46rem at 18% 92%, rgba(9, 16, 24, 0.6), transparent 58%);
}
.hero-inner { width: 100%; }
.hero .eyebrow { margin-bottom: clamp(1.5rem, 3vw, 2.4rem); opacity: 0; transform: translateY(16px); transition: opacity 0.9s var(--ease), transform 0.9s var(--ease); }
.is-ready .hero .eyebrow { opacity: 1; transform: none; transition-delay: 0.12s; }
 /* Three lines of six words, where there were two lines of two. The old
    clamp(3.4rem, 8.8vw, 8rem) would have set "Strategic Wealth Management"
    at a size no viewport could hold, and .line clips its overflow, so a
    wrapped line would not have wrapped, it would have vanished. Sized so the
    longest of the three fits on one line at every width above the breakpoint
    below, where the clip is released and wrapping is allowed. */
.hero .display { max-width: 30ch; font-size: clamp(1.75rem, 4.4vw, 3.9rem); }
/* The clip box for the entrance IS the line box, and line-height 0.94 makes that
   box shorter than the type is tall: at 49.6px the ink runs 37px up and 11px
   down, 48px of it, inside a 46.6px box. So every descender was sliced off, the
   g in Engineered and the p in Optimized most visibly. Pad the clip box down far
   enough to hold the ink, then pull exactly the same amount back with a negative
   margin, so the leading between the two lines and below the h1 is unchanged. */
/* overflow:hidden powers the slide-up reveal; the padding/negative-margin pair
   keeps plain (non-gold) descenders clear of the clip without shifting layout.
   The italic gold descender is handled on .gold-text (background-clip paint box),
   not here. */
.hero .display .line { display: block; overflow: hidden; padding-bottom: 0.2em; margin-bottom: -0.2em; }
/* Each line slides up from below its own clip box. That box is now 0.18em
   taller, so the old 105% would leave the type peeking into the new padding
   before it animates. 125% clears the taller box. */
.hero .display .line > span { display: block; transform: translateY(125%); transition: transform 1.15s var(--ease); }
.is-ready .hero .display .line > span { transform: none; }
.hero .display .line:nth-child(2) > span { transition-delay: 0.13s; }
.hero .display .line:nth-child(3) > span { transition-delay: 0.26s; }

.hero-lead { margin-top: clamp(1.75rem, 3vw, 2.5rem); max-width: 52ch; opacity: 0; transform: translateY(16px); transition: opacity 0.9s var(--ease) 0.42s, transform 0.9s var(--ease) 0.42s; }
.hero-actions { display: flex; flex-wrap: wrap; gap: 0.85rem; margin-top: clamp(2rem, 3.5vw, 2.9rem); opacity: 0; transform: translateY(16px); transition: opacity 0.9s var(--ease) 0.56s, transform 0.9s var(--ease) 0.56s; }
.is-ready .hero-lead, .is-ready .hero-actions { opacity: 1; transform: none; }

.hero-scroll { position: absolute; right: var(--gutter); bottom: clamp(2.5rem, 5vw, 4.5rem); display: flex; align-items: center; gap: 0.8rem; font-size: 0.66rem; letter-spacing: 0.24em; text-transform: uppercase; color: var(--fg-4); }
.hero-scroll::after { content: ""; width: 60px; height: 1px; background: linear-gradient(90deg, var(--fg-4), transparent); animation: scroll-cue 2.8s var(--ease-io) infinite; }
@keyframes scroll-cue { 0%, 100% { opacity: 0.35; transform: translateX(0); } 50% { opacity: 1; transform: translateX(6px); } }

/* ---------- 10b. HERO ATMOSPHERE ----------
   Round 6b. The first pass read as "a bunch of circles in different shades of
   blue", which was fair: a 60px blur on a 46vw disc leaves 91% of the disc
   edge intact, and three discs at three lightnesses is three readable circles.

   Rebuilt on different principles.

   No blur filter and no border-radius. The softness comes from the gradient
   itself, which fades across its whole radius, so there is no edge to find.
   That is also far cheaper than blurring a 660px element every frame.

   Ellipses, not circles, at wildly different aspect ratios, sized past the
   viewport on at least one axis so no shape can be read whole.

   One light source, not three. Everything is lit warm from the upper right
   and falls to deep navy at the lower left. Random blobs look random; a
   consistent direction of light looks intentional.

   A sheen crosses on a 24s loop. That is the part you actually notice, and it
   reads as light moving over a surface rather than as shapes drifting, which
   is what fixes "too subtle" without making anything hectic.

   Grain over the top. Gradients alone render plastic; a fine noise is what
   separates an expensive dark surface from a CSS demo. */
.hero-aurora {
  position: absolute; inset: 0; z-index: -2;
  overflow: hidden; pointer-events: none;
}

/* hero.js adds .gl-on once a WebGL context is live and drawing. Everything
   below it in this section is then dead weight, so it comes out of the
   compositor entirely. Without WebGL, or after a lost context, .gl-on is
   absent or removed and the CSS fields carry the hero on their own. */
.hero-canvas { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }
.hero-aurora.gl-on > span,
.hero-aurora.gl-on > .hero-grain { display: none; }
.hero-aurora.gl-on::before,
.hero-aurora.gl-on::after { content: none; }

/* The lit surface. Static: this is the light source, and light sources that
   wander are what made the first pass look accidental. */
.hero-aurora::before {
  content: ""; position: absolute; inset: -15%;
  background:
    radial-gradient(85% 65% at 82% 8%, rgba(104, 141, 182, 0.50), rgba(104, 141, 182, 0) 64%),
    radial-gradient(60% 70% at 96% 34%, rgba(197, 164, 126, 0.15), rgba(197, 164, 126, 0) 60%),
    radial-gradient(95% 80% at 8% 104%, rgba(8, 14, 22, 0.82), rgba(8, 14, 22, 0) 62%);
}

/* The sheen. A wide, very soft diagonal band crossing the whole hero. */
.hero-aurora::after {
  content: ""; position: absolute; top: -30%; bottom: -30%; left: -60%; width: 75%;
  background: linear-gradient(100deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, 0.028) 38%,
    rgba(214, 231, 250, 0.065) 50%,
    rgba(255, 255, 255, 0.028) 62%,
    rgba(255, 255, 255, 0) 100%);
  transform: skewX(-12deg);
  will-change: transform;
  animation: hero-sheen 24s var(--ease-io) infinite;
}

.hero-aurora span {
  position: absolute; display: block;
  will-change: transform;
}
/* Wider than the viewport, so its ends are always off screen. */
.hero-aurora span:nth-child(1) {
  top: -45%; left: -30%; width: 150%; height: 115%;
  background: radial-gradient(52% 46% at 42% 50%, rgba(101, 137, 178, 0.42), rgba(101, 137, 178, 0) 72%);
  animation: atmos-a 38s var(--ease-io) infinite;
}
/* The one warm field, kept near the light source so the warmth has a reason. */
.hero-aurora span:nth-child(2) {
  top: -25%; right: -40%; width: 115%; height: 95%;
  background: radial-gradient(46% 52% at 60% 42%, rgba(197, 164, 126, 0.17), rgba(197, 164, 126, 0) 70%);
  animation: atmos-b 47s var(--ease-io) infinite;
}
/* Deep shadow field, anchoring the lower left away from the light. */
.hero-aurora span:nth-child(3) {
  bottom: -55%; left: -25%; width: 140%; height: 120%;
  background: radial-gradient(48% 44% at 38% 55%, rgba(13, 22, 33, 0.60), rgba(13, 22, 33, 0) 70%);
  animation: atmos-c 61s var(--ease-io) infinite;
}

@keyframes hero-sheen {
  0%       { transform: translateX(0) skewX(-12deg); }
  100%     { transform: translateX(260%) skewX(-12deg); }
}
@keyframes atmos-a {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  38%      { transform: translate3d(9%, 12%, 0) scale(1.18); }
  70%      { transform: translate3d(-5%, 5%, 0) scale(0.94); }
}
@keyframes atmos-b {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  45%      { transform: translate3d(-12%, 14%, 0) scale(1.22); }
  75%      { transform: translate3d(-4%, -7%, 0) scale(0.9); }
}
@keyframes atmos-c {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  42%      { transform: translate3d(11%, -13%, 0) scale(1.15); }
  78%      { transform: translate3d(-7%, -4%, 0) scale(0.93); }
}

/* Film grain. It lives inside .hero-aurora rather than on .hero::after,
   because the bands redesign kills .hero::before and .hero::after with
   !important to keep the hero flat, and that rule is still doing its job for
   the gradient and texture pass it was written against. Same reason the scrim
   that main.css puts on .hero::before has never actually painted.

   Last child, so it sits over every field below it. One repeating 180px tile,
   rasterised once. */
.hero-grain {
  position: absolute; inset: 0; display: block; pointer-events: none;
  opacity: 0.16;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* Asked not to move: the lit surface, the fields and the grain all stay, the
   drift and the sheen stop. The band is still a lit surface, which was the
   actual note, and nothing travels. */
@media (prefers-reduced-motion: reduce) {
  .hero-aurora span, .hero-aurora::after { animation: none; }
  .hero-aurora::after { opacity: 0.5; transform: translateX(120%) skewX(-12deg); }
}

/* ---------- 11. CREDENTIAL STRIP ---------- */
.creds { border-block: 1px solid var(--line); padding-block: 1.5rem; }
.creds-inner { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1rem 2.5rem; }
.creds-label { font-size: 0.74rem; letter-spacing: 0.2em; text-transform: uppercase; color: var(--fg-4); }
.creds-list { display: flex; flex-wrap: wrap; gap: 0.55rem 1.9rem; }
.creds-list li { font-size: 0.88rem; letter-spacing: var(--track-cap-lg); text-transform: uppercase; color: var(--fg-2); font-weight: 500; }
.creds-list li + li { position: relative; }
.creds-list li + li::before { content: ""; position: absolute; left: -0.95rem; top: 50%; width: 3px; height: 3px; border-radius: 50%; background: var(--gold); opacity: 0.55; transform: translateY(-50%); }

/* ---------- 12. CAPABILITIES (editorial index) ---------- */
.cap-list { border-top: 1px solid var(--line); }
.cap {
  display: grid; grid-template-columns: 5.5rem minmax(0, 22rem) minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 4rem); align-items: start;
  padding-block: clamp(1.5rem, 3vw, 2.4rem);
  border-bottom: 1px solid var(--line);
  position: relative; transition: background 0.5s var(--ease);
}
.cap::after {
  content: ""; position: absolute; left: 0; bottom: -1px; height: 1px; width: 100%;
  background: var(--grad-gold); transform: scaleX(0); transform-origin: left;
  transition: transform 0.7s var(--ease);
}
.cap:hover { background: linear-gradient(90deg, rgba(255, 255, 255, 0.028), transparent 70%); }
.cap:hover::after { transform: scaleX(1); }
.cap-num { font-family: var(--serif); font-size: clamp(1.7rem, 2.6vw, 2.4rem); color: var(--fg-4); letter-spacing: 0.02em; padding-top: 0.1rem; font-variant-numeric: tabular-nums lining-nums; transition: color 0.5s var(--ease); }
.cap:hover .cap-num { color: var(--gold); }
.cap-title { display: flex; align-items: flex-start; gap: 1.1rem; }
.cap-title .icon { color: var(--gold); margin-top: 0.15rem; opacity: 0.85; transition: transform 0.6s var(--ease); }
.cap:hover .cap-title .icon { transform: translateY(-3px) rotate(-4deg); }
.cap-body { color: var(--fg-2); font-weight: 400; font-size: var(--body); line-height: var(--body-lh); max-width: 48ch; }

/* ---------- 13. SERVICES (home) ----------
   Light blue-gray cards (#b2bdc7) that lift out of the dark field to break the
   section up (client request). Every element flips to dark for contrast on the
   light card; measured on #b2bdc7 (lum .50): heading 8.4, body 5.2, link 4.7,
   deep-gold icon 4.0. The .svc component is used only on the home page. */
.svc-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: rgba(22, 35, 47, 0.35); border: 1px solid rgba(22, 35, 47, 0.30); box-shadow: var(--elev-1); }
.svc {
  background: #c7cfd6;
  padding: var(--pad-tile);
  display: flex; flex-direction: column; gap: 0.85rem;
  min-height: 16rem; position: relative; isolation: isolate;
  transition: background 0.45s var(--ease);
}
.svc:hover, .svc:focus-visible { background: #d2d8de; }
.svc .icon--lg { color: #6a4e26; transition: transform 0.55s var(--ease); }
.svc:hover .icon--lg, .svc:focus-visible .icon--lg { transform: translateY(-4px); }
.svc h3 { font-family: var(--serif); font-weight: 400; font-size: var(--h4); letter-spacing: -0.015em; line-height: 1.12; color: #16232f; }
.svc p { font-size: var(--body); line-height: var(--body-lh); color: rgba(22, 35, 47, 0.78); font-weight: 400; flex: 1; }
.svc .link-arrow { margin-top: 0.35rem; color: rgba(22, 35, 47, 0.74); }
.svc:hover .link-arrow, .svc:focus-visible .link-arrow { color: #16232f; }
.svc:hover .link-arrow .icon, .svc:focus-visible .link-arrow .icon { transform: translateX(5px); }

/* ---------- 14. TEAM ---------- */
.team-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(1.25rem, 2.4vw, 2.2rem); }
.member {
  display: block; border: 1px solid var(--line); border-radius: 4px; overflow: hidden;
  /* Same glass as the service tiles so adjacent grids read as one material. */
  background: var(--tile); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06), 0 16px 36px -26px rgba(0, 0, 0, 0.6);
  position: relative; cursor: pointer;
  transition: border-color 0.5s var(--ease), transform 0.5s var(--ease), background 0.5s var(--ease);
}
/* Keyboard focus lands on the inner trigger. Ideally the ring wraps the whole
   card, but :has() only landed in Firefox 121, so ring the button by default and
   upgrade to the full-card ring only where :has() is actually supported.
   Without this split, pre-121 Firefox shows no focus indicator at all. */
.member-trigger:focus-visible { outline: 2px solid var(--gold); outline-offset: -3px; }
@supports selector(:has(*)) {
  .member:has(.member-trigger:focus-visible) { outline: 2px solid var(--gold); outline-offset: 3px; }
  .member-trigger:focus-visible { outline: none; }
  /* Keyboard focus mirrors the hover lift + photo colour so tabbing feels alive. */
  .member:has(.member-trigger:focus-visible) { border-color: var(--line-2); transform: translateY(-5px); }
  .member:has(.member-trigger:focus-visible) .member-photo img { filter: grayscale(0) contrast(1.02) brightness(1); transform: scale(1.045); }
  .member:has(.member-trigger:focus-visible) .member-photo::after { opacity: 0.82; }
}
.member:hover { border-color: var(--line-2); transform: translateY(-5px); background: var(--surface-2); }
.member-photo { position: relative; aspect-ratio: 4 / 5; overflow: hidden; background: linear-gradient(150deg, var(--ink-700), var(--ink-900)); }
.member-photo img {
  width: 100%; height: 100%; object-fit: cover; object-position: center 18%;
  /* Source portraits are shot on a light studio grey. Knocking brightness down
     and desaturating lets that background sit inside the dark card instead of
     punching a bright hole in it. Colour returns on hover. */
  filter: grayscale(1) contrast(1.08) brightness(0.88);
  transform: scale(1.01);
  transition: filter 0.7s var(--ease), transform 0.9s var(--ease);
}
.member:hover .member-photo img { filter: grayscale(0) contrast(1.02) brightness(1); transform: scale(1.045); }
.member-photo::after {
  content: ""; position: absolute; inset: 0; transition: opacity 0.7s var(--ease);
  background:
    linear-gradient(to top, rgba(16, 27, 39, 0.94) 0%, rgba(16, 27, 39, 0.38) 38%, rgba(16, 27, 39, 0.04) 68%),
    linear-gradient(150deg, rgba(36, 58, 84, 0.32), rgba(20, 34, 48, 0.18));
}
.member:hover .member-photo::after { opacity: 0.82; }
.member-meta { position: absolute; inset: auto 0 0; padding: 1.4rem clamp(1.1rem, 1.8vw, 1.6rem); z-index: 2; }
.member-meta h3 { font-family: var(--serif); font-weight: 400; font-size: var(--h4); line-height: 1.12; letter-spacing: -0.015em; }
.member-meta .role { font-size: 0.78rem; letter-spacing: var(--track-cap-md); text-transform: uppercase; color: var(--gold); margin-top: 0.5rem; font-weight: 500; }
.member-trigger {
  /* position:static so ::after resolves against .member and covers the whole card,
     making the entire tile clickable while the real hit target stays a <button>. */
  position: static;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  width: 100%; text-align: left;
  /* No top border: the portrait's bottom gradient already separates the strip. */
  padding: 0.9rem clamp(1.1rem, 1.8vw, 1.6rem);
  font-size: 0.78rem; letter-spacing: var(--track-cap-md); text-transform: uppercase; color: var(--fg-3);
  transition: color 0.4s var(--ease);
}
.member-trigger::after { content: ""; position: absolute; inset: 0; z-index: 3; }
.member-trigger .icon { transition: transform 0.45s var(--ease); }
.member:hover .member-trigger { color: var(--gold); }
.member:hover .member-trigger .icon { transform: translateX(5px); }

/* ---------- 15. BIO DIALOG ---------- */
.bio[open] { display: flex; }
.bio {
  border: 1px solid var(--line-2); border-radius: 6px; padding: 0;
  /* The global `* { margin: 0 }` reset wipes the UA's `margin: auto`, which is
     what centres a modal <dialog>. Put it back explicitly. */
  margin: auto;
  width: min(1000px, calc(100vw - 2rem)); max-width: none;
  max-height: min(88vh, 820px);
  max-height: min(88svh, 820px);
  /* Same reasoning as .drawer: 98.5% opaque, so the blur behind it was
     imperceptible and cost a full-screen composite on open. */
  background: rgba(28, 43, 60, 0.985);
  color: var(--fg); overflow: hidden;
  box-shadow: 0 45px 110px -30px rgba(0, 0, 0, 0.9);
}
.bio::backdrop { background: rgba(12, 20, 29, 0.85); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); }
/* The dialog eases in rather than snapping open. */
@keyframes bio-in { from { opacity: 0; transform: translateY(10px) scale(0.985); } to { opacity: 1; transform: none; } }
@keyframes bio-backdrop-in { from { opacity: 0; } to { opacity: 1; } }
.bio[open] { animation: bio-in 0.4s var(--ease); }
.bio[open]::backdrop { animation: bio-backdrop-in 0.4s var(--ease); }
.bio-grid { display: grid; grid-template-columns: 290px minmax(0, 1fr); width: 100%; min-height: 0; }
.bio-side { background: rgba(0, 0, 0, 0.28); border-right: 1px solid var(--line); padding: 2.6rem 1.9rem; display: flex; flex-direction: column; align-items: center; text-align: center; justify-content: center; }
.bio-photo { width: 148px; aspect-ratio: 1; border-radius: 50%; overflow: hidden; border: 1px solid var(--line-2); background: var(--ink-800); margin-bottom: 1.5rem; }
.bio-photo img { width: 100%; height: 100%; object-fit: cover; object-position: center 18%; }
.bio-side h2 { font-family: var(--serif); font-weight: 400; font-size: 1.9rem; line-height: 1.14; letter-spacing: -0.01em; }
.bio-side .role { font-size: 0.76rem; letter-spacing: var(--track-cap-md); text-transform: uppercase; color: var(--gold); margin-top: 0.7rem; }
/* overscroll-behavior stops a flick that reaches the end of the bio from
   chaining through to the page underneath and scrolling it away. */
.bio-main { padding: 3rem clamp(1.75rem, 3.5vw, 3.4rem); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; scrollbar-color: var(--line-2) transparent; }
.bio-main p { font-size: var(--body); line-height: 1.68; color: var(--fg-2); font-weight: 400; }
.bio-main p + p { margin-top: 1.15rem; }
.bio-close { position: absolute; top: 0.9rem; right: 0.9rem; width: 42px; height: 42px; display: flex; align-items: center; justify-content: center; color: var(--fg-3); border-radius: 50%; z-index: 5; transition: color 0.3s, background 0.3s; }
.bio-close:hover { color: var(--fg); background: var(--surface-2); }
.bio-nav { position: absolute; bottom: 1.1rem; right: 1.2rem; display: flex; gap: 0.5rem; z-index: 5; }
.bio-nav button { width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: var(--fg-2); background: rgba(255, 255, 255, 0.05); border: 1px solid var(--line); transition: all 0.3s var(--ease); }
.bio-nav button:hover:not(:disabled) { background: var(--gold); color: var(--ink-950); border-color: var(--gold); }
.bio-nav button:disabled { opacity: 0.22; cursor: not-allowed; }

/* ---------- 16. CTA BAND ---------- */
.cta-band { position: relative; overflow: hidden; border-top: 1px solid var(--line); }
.cta-band::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: radial-gradient(60rem 30rem at 50% 118%, rgba(197, 164, 126, 0.18), transparent 68%);
}
.cta-inner { text-align: center; display: flex; flex-direction: column; align-items: center; gap: var(--space-md); }
.cta-inner .h2 { max-width: 18ch; }
/* Centered eyebrow drops its left-only hairline so it sits symmetric. */
.cta-inner .eyebrow::before { display: none; }
.cta-actions { display: flex; flex-wrap: wrap; gap: var(--space-sm); justify-content: center; margin-top: 0.9rem; }

/* ---------- 17. FOOTER ---------- */
.site-footer { background: var(--ink-950); border-top: 1px solid var(--line); position: relative; z-index: 1; }
.footer-top { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 2.5rem; padding-block: clamp(1.9rem, 3.5vw, 3rem); border-bottom: 1px solid var(--line); }
.footer-logo { height: 40px; width: auto; filter: brightness(0) invert(1); opacity: 0.9; }
.footer-contacts { display: flex; flex-wrap: wrap; gap: 1.5rem 3.5rem; }
.footer-contact { display: flex; align-items: center; gap: 1rem; }
.footer-contact .icon--lg { color: var(--gold); width: 1.35rem; height: 1.35rem; }
.footer-contact .label { display: block; font-size: 0.72rem; letter-spacing: var(--track-cap-sm); text-transform: uppercase; color: var(--fg-4); margin-bottom: 0.28rem; }
/* Sans so the serif stays reserved for true headings. */
.footer-contact a { font-family: var(--sans); font-weight: 500; font-size: 1.16rem; transition: color 0.3s; }
.footer-contact a:hover { color: var(--gold); }

.footer-locations { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(2rem, 4vw, 3.5rem); padding-block: clamp(1.9rem, 3.5vw, 3rem); border-bottom: 1px solid var(--line); }
.loc .eyebrow { font-size: 0.72rem; letter-spacing: var(--track-cap-sm); }
.loc .eyebrow::before { width: 1.2rem; }
.loc h3 { font-family: var(--serif); font-weight: 400; font-size: 1.55rem; margin: 0.9rem 0 0.75rem; letter-spacing: -0.01em; }
.loc address { font-style: normal; font-size: var(--body-sm); line-height: 1.55; color: var(--fg-3); font-weight: 400; }
.loc a { transition: color 0.3s; }
.loc a:hover { color: var(--gold); }

.legal { padding-block: 2.2rem; }
.legal summary {
  cursor: pointer; list-style: none; display: flex; align-items: center; gap: 0.7rem;
  font-size: 0.68rem; letter-spacing: 0.2em; text-transform: uppercase; color: var(--fg-4);
  transition: color 0.3s; padding-block: 0.4rem;
}
.legal summary::-webkit-details-marker { display: none; }
.legal summary:hover { color: var(--fg-2); }
.legal summary .icon { width: 0.95em; height: 0.95em; transition: transform 0.35s var(--ease); }
.legal[open] summary .icon { transform: rotate(180deg); }
.legal-body { padding-top: 1.5rem; max-width: 100ch; }
.legal-body p { font-size: 0.84rem; line-height: 1.8; color: var(--fg-4); }
.legal-body p + p { margin-top: 1rem; }

.footer-bottom { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1rem; padding-block: 1.8rem; border-top: 1px solid var(--line); }
.footer-bottom p, .footer-bottom a { font-size: 0.82rem; color: var(--fg-4); }
.footer-bottom a:hover { color: var(--fg-2); }
.footer-bottom nav { display: flex; gap: 1.6rem; }

/* ---------- 17b. ACCOLADE (Accounting Today / third-party recognition) ----------
   The official artwork already carries the publication wordmark, the year and the
   award name, so it is shown on its own: no border, no plate, no repeated text.
   Height is fixed and width is auto, so the box the browser reserves is stable
   whatever the artwork's aspect ratio turns out to be, and there is no layout
   shift when it decodes. */
.accolade { display: inline-flex; align-items: center; }
.accolade-badge {
  /* ~50% larger per client feedback (was clamp(54px, 7.2vw, 78px)). */
  height: clamp(81px, 10.8vw, 117px); width: auto; flex: none;
  transition: transform 0.5s var(--ease);
}
/* The artwork is dark navy and the field behind it is dark slate. A whisper of
   ambient separation lets its own edge register without drawing a box around it.
   If the supplied file is a knockout (white or transparent) version, this costs
   nothing visually. */
.accolade-badge { filter: drop-shadow(0 10px 24px rgba(0, 0, 0, 0.42)); }
@media (hover: hover) and (pointer: fine) {
  .accolade:hover .accolade-badge { transform: translateY(-2px); }
}
.hero-accolade {
  margin-top: clamp(2rem, 3.5vw, 2.8rem);
  opacity: 0; transform: translateY(16px);
  transition: opacity 0.9s var(--ease) 0.7s, transform 0.9s var(--ease) 0.7s;
}
.is-ready .hero-accolade { opacity: 1; transform: none; }

/* Fallback: only if the artwork fails to load does the text lockup stand in. */
.accolade [data-badge-fallback] { display: none; }
.accolade.no-badge .accolade-badge { display: none; }
.accolade.no-badge [data-badge-fallback] {
  display: flex; flex-direction: column; gap: 0.32rem;
  border-left: 2px solid var(--gold); padding-left: 1.05rem;
}
.accolade-pub { font-size: 0.62rem; font-weight: 600; letter-spacing: var(--track-cap-sm); text-transform: uppercase; color: var(--fg-3); }
.accolade-award { font-family: var(--serif); font-size: 1.05rem; line-height: 1.12; letter-spacing: -0.01em; }
.accolade-award .yr { color: var(--gold); }

/* ---------- 17c. ALLOCATION STACK (Investment Strategies) ---------- */
.stack { border: 1px solid var(--line); border-radius: 6px; overflow: hidden; background: var(--surface); box-shadow: var(--elev-1); }
.layer {
  display: grid; grid-template-columns: 2.6rem minmax(0, 1fr) auto;
  gap: clamp(1rem, 2.5vw, 2rem); align-items: center;
  padding: clamp(1.35rem, 2.4vw, 1.85rem) clamp(1.25rem, 2.4vw, 2rem);
  position: relative; transition: background 0.5s var(--ease); color: inherit;
}
.layer + .layer { border-top: 1px solid var(--line); }
.layer::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 2px;
  background: var(--grad-gold); transform: scaleY(0); transform-origin: top;
  transition: transform 0.6s var(--ease);
}
.layer:hover { background: rgba(255, 255, 255, 0.03); }
.layer:hover::before { transform: scaleY(1); }
.layer-idx { font-family: var(--serif); font-size: 1rem; color: var(--fg-4); font-variant-numeric: tabular-nums lining-nums; }
.layer-name { font-family: var(--serif); font-size: var(--h4); line-height: 1.12; letter-spacing: -0.015em; }
.layer-desc { font-size: var(--body-sm); color: var(--fg-3); font-weight: 400; margin-top: 0.32rem; line-height: 1.5; }
.layer-tag {
  font-size: 0.6rem; font-weight: 600; letter-spacing: 0.19em; text-transform: uppercase;
  color: var(--gold); border: 1px solid rgba(197, 164, 126, 0.35); border-radius: 999px;
  padding: 0.42rem 0.85rem; white-space: nowrap;
}

/* ---------- 17d. STRATEGY SECTIONS ---------- */
.strategy {
  display: grid; grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
  gap: clamp(2rem, 5vw, 5rem);
  padding-block: clamp(1.9rem, 3.5vw, 3.2rem);
  border-top: 1px solid var(--line);
}
.strategy { scroll-margin-top: calc(var(--header-h) + 1.5rem); }
.strategy-aside { position: sticky; top: calc(var(--header-h) + 2.5rem); align-self: start; }
.strategy-aside .icon--lg { color: var(--gold); margin-bottom: 1.3rem; }
.strategy-num { font-family: var(--serif); font-size: 0.95rem; color: var(--fg-4); letter-spacing: 0.06em; display: block; margin-bottom: 0.9rem; font-variant-numeric: tabular-nums lining-nums; }
.strategy-aside h2 { font-family: var(--serif); font-weight: 400; font-size: clamp(2.15rem, 3.4vw, 3.15rem); line-height: 1.06; letter-spacing: -0.02em; }
.strategy-role { display: block; margin-top: 1rem; font-size: 0.76rem; letter-spacing: 0.2em; text-transform: uppercase; color: var(--fg-3); }

.cap-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px; background: var(--line-2); border: 1px solid var(--line); margin-top: 2rem; }
.cap-grid li { background: var(--tile); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06); padding: 1.05rem 1.2rem; font-size: var(--body-sm); line-height: 1.5; color: var(--fg-2); font-weight: 400; display: flex; gap: 0.7rem; align-items: flex-start; }
.cap-grid .icon { color: var(--gold); width: 1.05em; height: 1.05em; margin-top: 0.28em; }

.designed-to { margin-top: 2rem; border-left: 2px solid var(--gold); padding: 0.4rem 0 0.4rem clamp(1.2rem, 2vw, 1.8rem); }
.designed-to .label { display: block; font-size: 0.61rem; font-weight: 600; letter-spacing: 0.24em; text-transform: uppercase; color: var(--gold); margin-bottom: 0.7rem; }
.designed-to p { font-family: var(--serif); font-style: italic; font-size: clamp(1.35rem, 1.9vw, 1.6rem); line-height: 1.45; color: var(--fg-2); }

/* ---------- 17e. PROCESS ---------- */
.process-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: var(--line-2); border: 1px solid var(--line); box-shadow: var(--elev-1); }
.step {
  background: var(--tile); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
  padding: var(--pad-tile-sm); position: relative; overflow: hidden;
  transition: background 0.5s var(--ease);
}
.step::after {
  content: ""; position: absolute; left: 0; top: -1px; width: 100%; height: 2px;
  background: var(--grad-gold); transform: scaleX(0); transform-origin: left;
  transition: transform 0.6s var(--ease);
}
.step:hover { background: rgba(255, 255, 255, 0.03); }
.step:hover::after { transform: scaleX(1); }
.step-num { font-family: var(--serif); font-size: 0.92rem; color: var(--fg-4); font-variant-numeric: tabular-nums lining-nums; }
.step h3 { font-family: var(--serif); font-weight: 400; font-size: 1.55rem; line-height: 1.2; margin: 0.85rem 0 0.6rem; letter-spacing: -0.01em; }
.step p { font-size: var(--body); line-height: var(--body-lh); color: var(--fg-2); font-weight: 400; }

/* ---------- 17f. NOTE / DISCLOSURE INLINE ---------- */
/* Dark wash, not white: a raised surface should deepen against the field rather
   than lighten it, or it eats the contrast budget of the muted copy it holds. */
.note { border: 1px solid var(--line); border-radius: 5px; padding: var(--pad-tile-sm); background: var(--tile); box-shadow: var(--elev-1); }
.note p { font-size: 0.86rem; line-height: 1.75; color: var(--fg-4); }

/* ---------- 17g. SERVICES: CARD GRID (services.html) ----------
   One light blue-gray card per discipline, matching the home services boxes, so
   the whole "services" idea reads as one card/box system (client request). All
   content is dark for contrast on the light card: heading ~10:1, hook/features
   ~6:1, deep-gold icons ~4.8:1 on #c7cfd6. */
.svc-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: rgba(22, 35, 47, 0.35); border: 1px solid rgba(22, 35, 47, 0.30); box-shadow: var(--elev-1); }
.svc-card {
  background: #c7cfd6; padding: var(--pad-tile);
  display: flex; flex-direction: column;
  scroll-margin-top: calc(var(--header-h) + 1.5rem);
  transition: background 0.45s var(--ease);
}
.svc-card:hover, .svc-card:focus-within { background: #d2d8de; }
.svc-card .icon--lg { color: #6a4e26; margin-bottom: 1rem; transition: transform 0.55s var(--ease); }
.svc-card:hover .icon--lg { transform: translateY(-4px); }
.svc-card h2 { font-family: var(--serif); font-weight: 400; font-size: clamp(1.8rem, 2.4vw, 2.2rem); line-height: 1.1; letter-spacing: -0.015em; color: #16232f; }
.svc-card-hook { color: rgba(22, 35, 47, 0.82); font-size: var(--body); line-height: var(--body-lh); margin: 0.85rem 0 1.3rem; }
.svc-card-list { margin-bottom: 1.5rem; }
.svc-card-list li { display: flex; gap: 0.7rem; align-items: flex-start; padding-block: 0.62rem; border-top: 1px solid rgba(22, 35, 47, 0.15); font-size: var(--body-sm); line-height: 1.45; color: rgba(22, 35, 47, 0.82); }
.svc-card-list .icon { color: #6a4e26; width: 1.05em; height: 1.05em; margin-top: 0.22em; flex: none; }
.svc-card .link-arrow { margin-top: auto; color: rgba(22, 35, 47, 0.74); }
.svc-card:hover .link-arrow, .svc-card:focus-within .link-arrow { color: #16232f; }
.svc-card:hover .link-arrow .icon, .svc-card:focus-within .link-arrow .icon { transform: translateX(5px); }

@media (max-width: 1024px) { .svc-cards { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .svc-cards { grid-template-columns: 1fr; } }

/* ---------- 17h. FORMS (contact.html) ---------- */
/* Dark wash for the same reason as .note: this panel holds the form, whose
   placeholder and disclaimer copy were the worst contrast cases on the site. */
.panel { border: 1px solid var(--line); border-radius: 6px; background: var(--tile); padding: clamp(1.6rem, 3vw, 2.75rem); backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px); box-shadow: var(--elev-1); }
.contact-layout { display: grid; grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); gap: var(--gap-grid); align-items: start; }
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(1.1rem, 2vw, var(--space-md)); }
.field { display: flex; flex-direction: column; gap: 0.55rem; }
.field--full { grid-column: 1 / -1; }
.field label { font-size: 0.78rem; font-weight: 500; letter-spacing: var(--track-cap-md); text-transform: uppercase; color: var(--fg-3); transition: color 0.3s var(--ease); }
/* The label lights gold with its field. */
.field:focus-within label { color: var(--gold); }
.field .req { color: var(--gold); }
.input, .textarea {
  /* background-COLOR, not the shorthand. The shorthand would wipe the caret
     background-image that select.input relies on. */
  width: 100%; background-color: rgba(10, 18, 27, 0.30);
  border: 1px solid var(--line); border-radius: 4px;
  /* 16px is a hard floor, not a preference. iOS Safari zooms the whole page in
     when you focus a control whose text is smaller than that, and it does not
     zoom back out. Every field was 15.2px, so tapping any of them threw the
     layout sideways. Weight matches body copy at 400 rather than a thin 300. */
  padding: 0.92rem 1.1rem; color: var(--fg); font-size: 1rem; font-weight: 400;
  font-family: inherit; transition: border-color 0.3s, background-color 0.3s, box-shadow 0.3s;
}
.input::placeholder, .textarea::placeholder { color: var(--fg-4); }
.input:focus, .textarea:focus { outline: none; border-color: var(--gold); background-color: rgba(10, 18, 27, 0.20); box-shadow: 0 0 0 3px rgba(197, 164, 126, 0.13); }
.textarea { min-height: 150px; resize: vertical; }
select.input {
  appearance: none; cursor: pointer; padding-right: 2.6rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23c5a47e' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9.5 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 1rem center; background-size: 1.05rem;
}
select.input:invalid { color: var(--fg-4); }
.form-note { font-size: 0.82rem; color: var(--fg-4); line-height: 1.65; margin-top: 1.1rem; }
/* Honeypot: bots fill it, humans never see it */
.hp { position: absolute !important; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.office { border-left: 2px solid var(--line); padding-left: 1.35rem; transition: border-color 0.4s var(--ease); }
.office + .office { margin-top: 1.6rem; }
.office:hover { border-color: var(--gold); }
.office h3 { font-family: var(--serif); font-weight: 400; font-size: 1.55rem; margin-bottom: 0.5rem; }
.office address { font-style: normal; font-size: var(--body-sm); line-height: 1.55; color: var(--fg-3); font-weight: 400; }
.office address a { color: inherit; transition: color 0.3s var(--ease); }
.office:hover address a, .office address a:hover { color: var(--gold); }
.direct-line { display: flex; align-items: center; gap: 0.85rem; padding-block: 0.7rem; font-size: 1.28rem; transition: color 0.3s; }
.direct-line .icon { color: var(--gold); }
.direct-line:hover { color: var(--gold); }
.panel-label { display: block; font-size: 0.74rem; font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase; color: var(--gold); margin-bottom: 1.1rem; }
.panel-label + .panel-label, .direct-line + .panel-label { margin-top: 2.2rem; }

/* ---------- 18. REVEAL ---------- */
.reveal { opacity: 0; transform: translateY(26px); transition: opacity var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease); transition-delay: calc(var(--i, 0) * var(--stagger)); }
.reveal.is-in { opacity: 1; transform: none; }

/* ---------- 19. INTERIOR PAGE HELPERS ---------- */
.page-hero { position: relative; isolation: isolate; padding-top: calc(var(--header-h) + clamp(4rem, 9vw, 8rem)); padding-bottom: clamp(2.5rem, 5vw, 4.5rem); }
.page-hero .display { font-size: clamp(3rem, 6.8vw, 5.9rem); max-width: 18ch; }
.page-hero .lead { margin-top: 1.75rem; }
/* Interior heroes and the aux (404 / thank-you) centred pages arrive with the
   same unhurried rise as the home hero. main.js adds .is-ready on every page. */
.page-hero .eyebrow, .page-hero .display, .page-hero .lead, .hero--full .cta-inner > * {
  opacity: 0; transform: translateY(16px);
  transition: opacity var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease);
}
.page-hero .display { transition-delay: 0.08s; }
.page-hero .lead { transition-delay: 0.18s; }
.is-ready .page-hero .eyebrow, .is-ready .page-hero .display, .is-ready .page-hero .lead,
.is-ready .hero--full .cta-inner > * { opacity: 1; transform: none; }

/* ---------- 20. RESPONSIVE ---------- */
/* Logo plus badge plus burger is one thing too many on a phone, and the logo
   is the one that has to stay. */
@media (max-width: 560px) {
  .header-accolade { display: none; }
}

@media (max-width: 1180px) {
  .svc-grid { grid-template-columns: repeat(2, 1fr); }
  .cap { grid-template-columns: 3.5rem minmax(0, 18rem) minmax(0, 1fr); }
  .process-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 1024px) {
  .nav, .header-actions .btn { display: none; }
  .burger { display: flex; }
  .team-grid { grid-template-columns: repeat(2, 1fr); }
  .contact-layout { grid-template-columns: 1fr; }
  .strategy { grid-template-columns: 1fr; gap: 2rem; }
  .strategy-aside { position: static; }
  .bio-side { border-right: 0; border-bottom: 1px solid var(--line); padding: 2.2rem 1.5rem; }
  .bio-photo { width: 108px; margin-bottom: 1.1rem; }
  .bio-main { padding: 2rem 1.6rem 4.5rem; }
  .bio { max-height: 92vh; max-height: 92svh; }
  .bio-grid { display: block; overflow-y: auto; overscroll-behavior: contain; max-height: 92vh; max-height: 92svh; }
  .bio-main { overflow: visible; }
}

@media (max-width: 820px) {
  :root { --header-h: 72px; }
  .cap { grid-template-columns: 1fr; gap: 1rem; }
  .cap-num { padding-top: 0; }
  .svc-detail-grid { grid-template-columns: 1fr; }
  .footer-locations { grid-template-columns: 1fr; gap: 2.5rem; }
  .footer-top { flex-direction: column; align-items: flex-start; }
  .hero-scroll { display: none; }
  .hero { align-items: center; min-height: 92vh; min-height: 92svh; }
  .creds-inner { flex-direction: column; align-items: flex-start; gap: 1rem; }
}

@media (max-width: 640px) {
  /* Below here the three title lines are allowed to wrap, so the clip that
     powers the slide-up reveal has to come off: a wrapped second row would be
     clipped out of existence rather than shown. The reveal falls back to the
     translate alone, which still reads. */
  .hero .display .line { overflow: visible; padding-bottom: 0; margin-bottom: 0; }
  .hero .display .line > span { transform: translateY(22px); opacity: 0; transition: transform 1.15s var(--ease), opacity 1.15s var(--ease); }
  .is-ready .hero .display .line > span { transform: none; opacity: 1; }
  .svc-grid, .team-grid, .cap-grid, .process-grid, .svc-detail-grid, .form-grid { grid-template-columns: 1fr; }
  .svc { min-height: 0; }
  .footer-bottom { flex-direction: column; align-items: flex-start; }
  .btn { width: 100%; }
  .hero-actions .btn { width: auto; flex: 1 1 auto; }
  .layer { grid-template-columns: 2rem minmax(0, 1fr); row-gap: 0.9rem; }
  .layer-tag { grid-column: 2; justify-self: start; }
}

/* ---------- 20b. TOUCH TARGETS ----------
   Measured on a 360px viewport, the footer links came in between 14px and 20px
   tall. WCAG 2.5.8 sets the floor at 24px and Apple's guidance at 44px, so these
   were a genuine thumb problem on the two things people most want to tap: the
   phone number and the email address. The padding below expands the hit area
   into gaps that already existed, so nothing moves visually.
   Both halves of the query are needed: a real phone reports `pointer: coarse`,
   but some touch laptops report `fine`, and a narrow viewport is a phone anyway. */
@media (pointer: coarse), (max-width: 820px) {
  .footer-contact a, .footer-bottom a, .loc address a {
    display: inline-block; padding-block: 0.78rem;
  }
  .footer-bottom nav { gap: 1.9rem; flex-wrap: wrap; }
  .legal summary { padding-block: 0.85rem; }
  /* The brand mark is the tap target back to home. */
  .brand { padding-block: 0.3rem; }
  /* The six "Start a conversation" links on services are 0.76rem type on a 1.65
     line height, so their box was about 20px: the smallest touch target on the
     site, on that page's primary conversion path. The negative top margin
     cancels the new top padding so the text does not move, and the extra height
     below is absorbed by the row's own padding. */
  .svc-card .link-arrow { padding-block: 0.5rem; }
}

/* ---------- 20c. RENDER BUDGET ----------
   backdrop-filter makes the compositor snapshot everything behind an element and
   blur it, and it redoes that work every frame the backdrop moves. On a sticky
   header that is the full width of the screen on every single scroll frame.

   This was scoped to phones, on the theory that a desktop GPU could absorb it.
   That held while the hero was flat. It stopped holding the moment the hero
   became a moving field: the header now re-snapshots and re-blurs a surface
   that changes every frame, at full desktop width, forever. Brandon reported
   scrolling as "rigid and laggy" and this is the first thing to go.

   What is lost is a 12px blur behind a fill that was already 88% opaque. The
   fill goes to 94% and carries the same density behind the type. */
.site-header::before {
  background: rgba(26, 40, 56, 0.94);
  backdrop-filter: none; -webkit-backdrop-filter: none;
}

@media (max-width: 820px) {
  .site-header::before { background: rgba(26, 40, 56, 0.96); }
  .panel {
    background: var(--tile);
    backdrop-filter: none; -webkit-backdrop-filter: none;
  }
  .bio::backdrop {
    background: rgba(12, 20, 29, 0.94);
    backdrop-filter: none; -webkit-backdrop-filter: none;
  }
  /* The film grain is a fixed full-viewport layer in overlay blend mode. Blend
     modes cost an extra compositing pass, and the turbulence tile behind it has
     to be rasterised first. At 3.5% opacity on a high density phone screen none
     of that is perceptible, so it comes off entirely. */
  .bg-field::after { display: none; }
}

/* ---------- 20d. NO-JS FLOOR ----------
   Everything listed here starts at opacity 0 and is lifted only when main.js adds
   .is-ready or .is-in. If scripting is disabled, or main.js is blocked, 404s or
   throws a parse error, that class never arrives and the hero plus every scroll
   revealed section stays invisible permanently, with no way to recover. The
   html.no-js class ships in the markup and is removed by an inline head script,
   so this block applies exactly when scripting did not run. The `.line > span`
   rule matters most: the home H1 is clipped by an overflow:hidden parent rather
   than faded, so opacity alone would not bring it back. */
html.no-js .reveal, html.no-js .hero-lead, html.no-js .hero-actions,
html.no-js .hero-accolade, html.no-js .hero .eyebrow,
html.no-js .page-hero .eyebrow, html.no-js .page-hero .display,
html.no-js .page-hero .lead, html.no-js .hero--full .cta-inner > *,
html.no-js .ledger-cta { opacity: 1 !important; transform: none !important; }
html.no-js .hero .display .line > span { transform: none !important; }
html.no-js .intro { display: none !important; }

/* ---------- 21. MOTION / PRINT ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important; animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important; scroll-behavior: auto !important;
    animation-delay: 0ms !important; transition-delay: 0ms !important;
  }
  /* Every entrance that starts at opacity:0 MUST reset here or opted-out users
     get stuck on invisible content. */
  .reveal, .hero-lead, .hero-actions, .hero-accolade,
  .hero .eyebrow, .page-hero .eyebrow, .page-hero .display, .page-hero .lead,
  .hero--full .cta-inner > * { opacity: 1 !important; transform: none !important; }
  .hero .display .line > span { transform: none !important; }
  #contour { display: none; }
}

@media print {
  .site-header, .drawer, #contour, .bg-field, .hero-scroll, .cta-band { display: none !important; }
  body { background: #fff; color: #000; }
  a { color: #000; }
  /* Nothing has been scrolled when a page is sent to the printer, so every
     entrance is still sitting at opacity 0 and those sections came out blank.
     Same selector list as the reduced-motion reset, for the same reason. */
  .reveal, .hero-lead, .hero-actions, .hero-accolade,
  .hero .eyebrow, .page-hero .eyebrow, .page-hero .display, .page-hero .lead,
  .hero--full .cta-inner > *, .ledger-cta { opacity: 1 !important; transform: none !important; }
  .hero .display .line > span { transform: none !important; }
  /* `body { color }` only reaches text that inherits it. Anything carrying an
     explicit token stayed near white and printed invisibly on white paper. */
  *, *::before, *::after { color: #000 !important; }
  /* .gold-text is transparent text over a clipped gradient, and print drops the
     gradient, so it printed as nothing at all. */
  .gold-text { background: none !important; -webkit-text-fill-color: #000 !important; }
}

/* Full-viewport centred page used by 404 and thank-you */
.hero--full { min-height: 100vh; min-height: 100svh; align-items: center; }
.confirm-mark { width: 56px; height: 56px; margin: 0 auto 0.4rem; border-radius: 50%; display: grid; place-items: center; border: 1px solid var(--line-2); background: rgba(197, 164, 126, 0.08); color: var(--gold); }
.confirm-mark .icon { width: 1.5rem; height: 1.5rem; stroke-width: 1.4; }
