/* ============================================================
   Quintessentia Network — BASE layer (historical dark theme)
   ============================================================

   🔴 READ THIS BEFORE CHANGING ANYTHING HERE.

   This file is NOT the shipping design system. It is the original dark +
   cyan theme, and `light.css` loads AFTER it and overrides the parts someone
   remembered to override. Everything NOT overridden below is still dark-theme
   styling rendering on a white page — which is exactly how the site ended up
   with an invisible CTA (#1a1a1c on #1a1a1c), process numerals painted in a
   1.46:1 cyan hairline, and 55 contrast failures. See
   data/vault/Bugs/02-Dark-Theme-Leftovers.md.

   The header here used to describe "premium dark + cyan, Space Grotesk /
   Inter". None of that ships: the live palette is light with an indigo
   #585ece accent and Figtree throughout. A stale banner on a base file is
   worse than no banner, because it tells the next editor the wrong theme is
   authoritative.

   RULE: when you add or change a rule in this file, check whether light.css
   overrides it. If it does not, you are styling the live site with
   dark-theme values.
   ============================================================ */

:root {
  --bg: #0a0e12;
  --bg-2: #0e141a;
  --surface: rgba(255, 255, 255, 0.04);
  --surface-2: rgba(255, 255, 255, 0.07);
  --border: rgba(255, 255, 255, 0.09);
  --border-strong: rgba(255, 255, 255, 0.16);
  --text: #eef2f5;
  --muted: #9eb1bf;
  --accent: #22d3ee;
  --accent-deep: #0891b2;
  --accent-soft: rgba(34, 211, 238, 0.12);
  --grad-accent: linear-gradient(135deg, #7dd3fc 0%, #22d3ee 45%, #0e7490 100%);
  /* Aliases, kept because rules across both sheets still reference them. They now
     point INTO the 4-step scale below rather than carrying their own values, so
     there is one scale and not two competing ones. --radius-sm was 10px, which was
     the eleventh distinct radius on the page. */
  --radius: var(--r-lg);
  --radius-sm: var(--r-sm);
  /* 1140 -> 1376, measured off the reference. 19 blocks already cap their measure in
     `ch`, so those hold a readable line length regardless of how wide the band gets;
     the risk of widening is entirely in prose blocks that have NO cap. Those were
     measured after the change and capped individually - see the `ch` additions below.
     --container also drives the nav pill (light.css:619 repeats this same min() math),
     so any change here must be re-checked against nav wrapping. */
  --container: 1376px;
  /* Clash Display and Space Grotesk are NOT loaded — the Fontshare request was
     removed because document.fonts reported every Clash face as `unloaded`.
     light.css overrides this token to Figtree; the names are kept out of the
     stack so nothing implies a font the site never fetches. */
  --font-display: system-ui, sans-serif;
  --font-body: "Inter", system-ui, sans-serif;
  /* Defined here as well as in light.css: nine rules in this file now say
     `var(--font-mono)`, and the token only existed in light.css. If that
     sheet ever fails to load, an undefined custom property makes those rules
     fall back to the inherited sans face rather than to a monospace one. */
  --font-mono: "Space Mono", ui-monospace, Consolas, monospace;

  /* ---------- TYPE SCALE ----------------------------------------------------
     🔴 Before this existed, the rendered page carried 25 distinct font sizes, and
     SIXTEEN of them sat inside a single 7px band: 10.56, 10.88, 11.20, 11.52,
     12.16, 12.48, 13.12, 13.60, 14.40, 14.72, 15.20, 15.68, 16.00, 16.32, 16.80,
     17.60. Nobody can tell 15.20 from 15.68. That is not a scale, it is drift —
     rem values chosen one rule at a time and compounding against different parent
     sizes.

     Use a token. If a new size seems necessary, it almost certainly is not; pick
     the nearer step. The whole point is that the steps are far enough apart to
     read as deliberate. */
  --fs-2xs: 0.72rem;
  --fs-xs:  0.82rem;
  --fs-sm:  0.92rem;
  /* 🔴 --fs-md (16px) was REMOVED, not renamed. It sat 1px from the body size,
     so an element explicitly set to "md" rendered a pixel smaller than text that
     simply inherited — a distinction no reader can make and every audit can. Two
     steps one pixel apart are not a scale, they are the drift this block exists to
     end. Body copy is --fs-lg. */
  /* 1.0625rem = 17px = exactly the body size below. These were 17.92px and 17px,
     0.92px apart, which is a difference nobody can see and every measurement can.
     rem is ROOT-relative, so body-inherited text and token-sized text will always
     land a hair apart unless the token is pinned to the body value. */
  --fs-lg:  1.0625rem;
  --fs-xl:  1.35rem;
  --fs-2xl: 1.7rem;
  --fs-3xl: 2.1rem;
  /* Display sizes are fluid; five steps, not sixteen.
     d0 and d1 are NOT interchangeable and must not be collapsed: d0 is the single
     oversized editorial hero on the homepage, d1 is every other page's h1. An
     earlier pass mapped both onto one step and silently shrank the homepage
     headline from 108px to 70px — a 35% cut to the largest element on the site,
     invisible in a token diff and obvious on the page. */
  --fs-d0: clamp(3.2rem, 9vw, 6.75rem);
  --fs-d1: clamp(2.4rem, 5vw, 3.75rem);
  --fs-d2: clamp(1.9rem, 4vw, 3rem);
  --fs-d3: clamp(1.6rem, 3vw, 2.3rem);
  --fs-d4: clamp(1.35rem, 2.4vw, 1.9rem);

  /* ---------- TRACKING ------------------------------------------------------
     🔴 Twelve distinct positive values across 29 declarations, and NON-MONOTONIC:
     one rendered size carried four different trackings (13.12px shipped 0.06,
     0.07, 0.10 and 0.14), and buttons at 11.52px got LESS tracking than buttons
     at 14.72px - backwards, because smaller caps need more air, not less.
     Three role tokens, monotone decreasing as size increases. */
  --track-btn: 0.06em;        /* every button, every size */
  --track-label-md: 0.10em;   /* caps at --fs-xs  / 13.12px */
  --track-label-sm: 0.14em;   /* caps at --fs-2xs / 11.52px - smaller, so wider */

  /* ---------- LEADING -------------------------------------------------------
     Six values did the work of one inside the 1.4-1.8 body band, producing five
     different leadings at a SINGLE rendered size. 1.65 is kept as the body value
     because 44 of 71 elements already used it, so the collapse is near-zero
     visual churn and keeps the accessibility headroom. */
  --lh-body: 1.65;
  --lh-dense: 1.5;
  /* Third leading, added deliberately after collapsing six to two. The two-token set
     had no value for DISPLAY text, so .step-num (33.6px) and .proof-item b (27.2px)
     inherited --lh-body 1.65 and rendered single-line content in 55.4px and 44.9px
     line boxes - the "inverted ramp" finding. Leading is a function of ROLE before
     size: a one-line numeral and a paragraph want different leading at the SAME size,
     so this is not the six-way drift that was collapsed. */
  --lh-display: 1.15;

  /* ---------- GAP SCALE -----------------------------------------------------
     🔴 25 distinct rendered gap values across 160 flex/grid containers, SEVENTEEN
     of them fractional pixels - 5.44, 8.8, 9.6, 10.4, 11.2, 12.8, 13.6, 14.4,
     15.2, 17.6, 19.2, 22.4, 25.6, 27.2, 35.2, 38.4. They come from fractional rem
     multipliers chosen one rule at a time (1.4rem = 22.4px, 0.55rem = 8.8px), not
     from any scale. Nine steps on a 4px grid.
     A 1px gap is a hairline DIVIDER, not spacing - it is left alone. */
  --gap-1: 4px;
  --gap-2: 8px;
  --gap-3: 12px;
  --gap-4: 16px;
  --gap-6: 24px;
  --gap-8: 32px;
  --gap-10: 40px;
  --gap-12: 48px;
  --gap-14: 56px;

  /* ---------- SPACING SCALE -------------------------------------------------
     🔴 18 distinct padding/margin values above 24px, ELEVEN of them fractional -
     25.5, 25.6, 28.8, 30.4, 35.2, 38.4, 41.6, 43.2, 45.6, 54.4, 67.2. Same cause
     as the gaps: fractional rem multipliers (1.9rem = 30.4, 2.2rem = 35.2,
     2.7rem = 43.2) chosen per rule rather than from a scale.
     Values at or below 24px are left alone - they are component-internal detail,
     not page rhythm, and snapping them churns a lot for no visible gain. */
  --sp-3: 24px;
  --sp-4: 32px;
  --sp-5: 40px;
  --sp-6: 48px;
  --sp-7: 56px;
  --sp-8: 64px;
  --sp-12: 96px;
  --sp-15: 120px;   /* section rhythm; 15 x 8, keeping the scale's 8px base */
  --sp-20: 160px;

  /* ---------- RADIUS SCALE -------------------------------------------------
     🔴 The rendered page carried ELEVEN rectangular radii: 8, 9, 10, 12, 14, 15,
     16, 18, 20, 22, 24. Nobody distinguishes an 8px corner from a 9px one; the
     reference this was measured against uses six values total. Four steps, plus
     the pill and the circle, which are shapes rather than steps.
     If a fifth seems necessary, it is not. */
  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 16px;
  --r-xl: 24px;
  --r-pill: 999px;

  --z-nav: 50;
  --z-overlay: 40;
  --z-grain: 45;    /* above content, BELOW --z-nav so the nav stays the top layer */

  /* motion system — Emil-Kowalski-grade: ease-OUT on enters, no default ease */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);       /* easeOutQuint — hovers, default */
  --ease-out-soft: cubic-bezier(0.16, 1, 0.3, 1);   /* easeOutExpo — large reveals */
  --ease-spring: cubic-bezier(0.34, 1.42, 0.5, 1);  /* slight overshoot — lifts, use sparingly */
  --ease-cinematic: cubic-bezier(0.16, 0.84, 0.24, 1); /* long tail — hero only, settles rather than stops */
  --dur-1: 140ms;  /* color / border micro-interactions */
  --dur-2: 240ms;  /* transforms, cards, buttons */
  --dur-3: 640ms;  /* scroll reveals */
  /* A fourth tier, for the hero only. 640ms is right for a card arriving in the
     periphery; the first thing a visitor sees deserves to resolve rather than snap.
     Paired with --ease-cinematic below, which has a longer tail than easeOutExpo. */
  --dur-4: 1100ms; /* hero-scale entrance, used sparingly */
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  font-family: var(--font-body);
  font-size: var(--fs-lg);
  /* Measured on the reference: body and UI text run weight 500 on a light ground, not 400.
     On a warm stone ground a 400 sits slightly grey and reads unset; 500 holds its colour.
     Figtree ships 500 as a real weight, so this is not synthesised.
     Line-height stays 1.65 rather than the reference's 1.5: their body blocks are short,
     ours run to a 70ch measure across long prose pages, where 1.5 is tight. */
  font-weight: 500;
  line-height: var(--lh-body);
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

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

::selection { background: rgba(34, 211, 238, 0.35); }

/* ---------- typography ---------- */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.13;
  letter-spacing: -0.015em;
  text-wrap: balance;
}
h1 { font-size: var(--fs-d1); line-height: 1.04; letter-spacing: -0.03em; }
h2 { font-size: var(--fs-d2); line-height: 1.08; letter-spacing: -0.022em; }
h3 { font-size: var(--fs-xl); letter-spacing: -0.012em; }
/* Section titles that are top-level in the DOCUMENT but subordinate in SIZE.
   Five pages had their real content sections marked h3 with no h2 above them,
   so the outline read h1 -> h3 and a screen-reader user got no section level to
   navigate by. Promoting them to h2 fixes the outline, but a bare h2 is
   clamp(1.8rem, 3.4vw, 2.6rem) and would have visibly doubled them. This keeps
   the h3 size on a correct h2. Verified by ink comparison, not assumed. */
h2.h2-compact { font-size: var(--fs-xl); letter-spacing: -0.012em; line-height: 1.13; }
p  { color: var(--muted); text-wrap: pretty; }
.lead { font-size: var(--fs-lg); line-height: var(--lh-body); }

.accent-text {
  background: var(--grad-accent);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

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

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-2);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: var(--track-label-md);
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 1rem;
}
.eyebrow::before {
  content: "";
  width: 26px; height: 1px;
  background: var(--accent);
}

/* ---------- layout ---------- */
.container {
  width: min(var(--container), calc(100% - 3rem));
  margin-inline: auto;
}

section { padding: var(--sp-12) 0; }
.section-head { max-width: 680px; margin-bottom: var(--sp-7); }
.section-head p { font-size: var(--fs-lg); }

/* ---------- topbar ---------- */
.topbar {
  position: fixed;
  top: 1rem; left: 1rem; right: 1rem;
  z-index: var(--z-nav);
  display: flex;
  justify-content: center;
}
.topbar-inner {
  width: min(var(--container), 100%);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-4);
  padding: 0.65rem 1.1rem;
  border-radius: var(--r-pill);
  background: rgba(10, 14, 18, 0.74);
  border: 1px solid var(--border);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
}
.brand {
  display: flex;
  align-items: center;
  gap: var(--gap-3);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-lg);
  white-space: nowrap;
}
.brand img { border-radius: var(--r-sm); }
.brand small {
  display: block;
  font-size: var(--fs-2xs);
  font-weight: 500;
  letter-spacing: var(--track-label-sm);
  color: var(--muted);
  text-transform: uppercase;
}
.nav-links {
  display: flex;
  align-items: center;
  gap: var(--gap-1);
  list-style: none;
}

/* ---------- nav dropdowns ---------- */
.nav-links .has-menu { position: relative; }
.nav-links .has-menu > a { display: inline-flex; align-items: center; gap: var(--gap-1); }
.nav-caret {
  width: 12px; height: 12px; flex: none;
  transition: transform var(--dur-2) var(--ease-out);
}
.has-menu:hover > a .nav-caret,
.has-menu:focus-within > a .nav-caret { transform: rotate(180deg); }

.nav-menu {
  position: absolute;
  top: calc(100% + 0.85rem);
  left: 50%;
  transform: translateX(-50%) translateY(-8px);
  min-width: 360px;
  display: grid;
  gap: var(--gap-1);
  padding: 0.55rem;
  border-radius: var(--r-xl);
  background: rgba(10, 14, 18, 0.94);
  border: 1px solid var(--border);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  box-shadow: 0 26px 60px rgba(0, 0, 0, 0.55);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity var(--dur-2) var(--ease-out),
              transform var(--dur-2) var(--ease-out),
              visibility var(--dur-2) linear;
}
/* A hover bridge, so the pointer can cross the gap without the menu closing. */
.nav-menu::before {
  content: "";
  position: absolute;
  top: -0.9rem; left: 0; right: 0; height: 0.9rem;
}
.has-menu:hover > .nav-menu,
.has-menu:focus-within > .nav-menu {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translateX(-50%) translateY(0);
}
.nav-menu a {
  display: block;
  padding: 0.7rem 0.85rem;
  border-radius: var(--r-md);
  line-height: 1.3;
}
.nav-menu a b {
  display: block;
  font-weight: 600;
  font-size: var(--fs-sm);
  color: var(--text);
  margin-bottom: 0.12rem;
}
.nav-menu a span {
  display: block;
  font-size: var(--fs-xs);
  color: var(--muted);
}
.nav-menu a:hover b, .nav-menu a:focus-visible b { color: var(--accent); }
.nav-menu-sep {
  height: 1px;
  background: var(--border);
  margin: 0.35rem 0.85rem;
}
.nav-links a {
  display: block;
  padding: 0.5rem 0.85rem;
  border-radius: var(--r-pill);
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--muted);
  transition: color var(--dur-1) var(--ease-out), background-color var(--dur-1) var(--ease-out);
}
.nav-links a:hover { color: var(--text); background: var(--surface-2); }
.nav-links a.active { color: var(--text); background: var(--surface-2); }
/* ---------- focus ring -------------------------------------------------------
   🔴 This used to be a hand-maintained selector LIST. On the homepage that left
   36 of 65 focusable elements falling back to Chrome's own ring - every
   .work-card, both .practice-row links, and all 28 footer links - because
   nothing had thought to add them. A list of what to style is a list you have to
   remember to update; a broad :where() is not.

   :where() keeps specificity at 0, so any component that deliberately styles its
   own focus still wins. There is no `outline: none` anywhere in this codebase
   (checked), so nothing silently swallows it.

   The COLOUR is a token, not a fixed value, because --accent is #1a1a1c and the
   footer background is #000000: widening the selector list without this would
   have shipped a 1.21:1 ring on 28 links, which is worse than the browser
   default it replaced. Ground-aware below. */
:where(a[href], button, input, select, textarea, summary, [tabindex]):not([tabindex="-1"]):focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

.nav-cta { margin-left: 0.5rem; }
.nav-links a.btn-accent {
  color: #04252e;
  background: var(--grad-accent);
  font-weight: 600;
  padding: 0.55rem 1.25rem;
}
.nav-links a.btn-accent:hover {
  color: #04252e;
  background: var(--grad-accent);
  box-shadow: 0 4px 20px rgba(34, 211, 238, 0.35);
}

.nav-toggle {
  display: none;
  background: none;
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  width: 42px; height: 42px;
  align-items: center;
  justify-content: center;
  color: var(--text);
  cursor: pointer;
}

/* ---------- buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-2);
  padding: 0.78rem 1.5rem;
  border-radius: var(--r-pill);
  font-family: var(--font-body);
  font-size: var(--fs-lg);
  font-weight: 600;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background-color var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out),
              color var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out),
              transform var(--dur-2) var(--ease-spring);
}
.btn:active { transform: translateY(1px); }
.btn-accent {
  background: var(--grad-accent);
  color: #04252e;
}
.btn-accent:hover { box-shadow: 0 8px 30px rgba(34, 211, 238, 0.4); transform: translateY(-2px); }
.btn-ghost {
  border-color: var(--border-strong);
  color: var(--text);
  background: transparent;
}
.btn-ghost:hover { background: var(--surface-2); border-color: var(--accent-deep); transform: translateY(-2px); }
.btn svg { width: 18px; height: 18px; }
@media (prefers-reduced-motion: reduce) {
  .btn-accent:hover, .btn-ghost:hover, .btn:active { transform: none; }
}

/* ---------- scroll progress bar ---------- */
.scroll-progress {
  position: fixed;
  top: 0; left: 0;
  height: 2px;
  width: 0;
  background: var(--grad-accent);
  box-shadow: 0 0 12px rgba(34, 211, 238, 0.7);
  z-index: 60;
  pointer-events: none;
}

/* ---------- hero ---------- */
.hero {
  position: relative;
  min-height: 92vh;
  display: flex;
  align-items: center;
  padding: var(--sp-20) 0 var(--sp-12);
  overflow: hidden;
}
.hero-bg {
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(ellipse 60% 45% at 70% 8%, rgba(8, 145, 178, 0.16), transparent 60%),
    radial-gradient(ellipse 50% 40% at 12% 85%, rgba(14, 116, 144, 0.12), transparent 65%),
    var(--bg);
}
.hero-grid-lines {
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image:
    linear-gradient(rgba(255,255,255,0.035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.035) 1px, transparent 1px);
  background-size: 72px 72px;
  mask-image: radial-gradient(ellipse 75% 65% at 50% 35%, #000 30%, transparent 75%);
  -webkit-mask-image: radial-gradient(ellipse 75% 65% at 50% 35%, #000 30%, transparent 75%);
}
.hero-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-2);
  padding: 0.42rem 1rem;
  border-radius: var(--r-pill);
  border: 1px solid var(--border);
  background: var(--surface);
  font-size: var(--fs-sm);
  color: var(--muted);
  margin-bottom: var(--sp-3);
}
.hero-badge .dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--accent);
}
.hero h1 { max-width: 16ch; margin-bottom: 1.4rem; }
.hero .lead { max-width: 56ch; margin-bottom: var(--sp-5); }
.hero-actions { display: flex; flex-wrap: wrap; gap: var(--gap-4); }

.hero-verticals {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-2);
  margin-top: var(--sp-6);
}
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-2);
  padding: 0.5rem 1rem;
  border-radius: var(--r-pill);
  border: 1px solid var(--border);
  background: var(--surface);
  font-size: var(--fs-sm);
  color: var(--muted);
}
.chip svg { width: 15px; height: 15px; color: var(--accent); }

/* ---------- cards ---------- */
/* cards sit on a near-black bg — solid translucency reads identically
   to backdrop blur at a fraction of the compositor cost */
.glass {
  background: rgba(13, 20, 26, 0.6);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--gap-6); }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gap-6); }
.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--gap-6); }

.card {
  padding: var(--sp-4);
  display: flex;
  flex-direction: column;
  gap: var(--gap-3);
  transition: border-color var(--dur-2) var(--ease-out), background-color var(--dur-2) var(--ease-out),
              box-shadow var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out);
}
a.card { cursor: pointer; }
a.card:hover, .card.hoverable:hover {
  border-color: rgba(34, 211, 238, 0.45);
  background: var(--surface-2);
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.5);
  transform: translateY(-4px);
}
@media (prefers-reduced-motion: reduce) {
  a.card:hover, .card.hoverable:hover { transform: none; }
}
.card h3 { color: var(--text); }
.card p { font-size: var(--fs-lg); }

.icon-tile {
  /* 🔴 flex-shrink:0 is not decoration. .contact-line is display:flex, and a flex
     item defaults to flex-shrink:1 — so this 46px tile SQUASHES to a sliver as soon as
     the text beside it is long enough to want the room. Every existing contact card
     had one or two short lines, so the bug stayed hidden until a card with a real
     paragraph was added and its icon collapsed to about 10px wide. A fixed width on a
     flex child is a preference, not a guarantee. */
  flex-shrink: 0;
  width: 46px; height: 46px;
  border-radius: var(--r-md);
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--accent-soft);
  border: 1px solid rgba(34, 211, 238, 0.25);
  color: var(--accent);
}
.icon-tile svg { width: 22px; height: 22px; }

.card-link {
  margin-top: auto;
  display: inline-flex;
  align-items: center;
  gap: var(--gap-2);
  font-weight: 600;
  font-size: var(--fs-sm);
  color: var(--accent);
}
.card-link svg { width: 16px; height: 16px; transition: transform var(--dur-1) var(--ease-out); }
a.card:hover .card-link svg { transform: translateX(4px); }

.tag {
  display: inline-block;
  padding: 0.22rem 0.7rem;
  border-radius: var(--r-pill);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: var(--track-label-md);
  text-transform: uppercase;
  background: var(--accent-soft);
  border: 1px solid rgba(34, 211, 238, 0.25);
  color: var(--accent);
  width: fit-content;
}
.tag.neutral {
  background: var(--surface-2);
  border-color: var(--border);
  color: var(--muted);
}

/* flagship band */
.flagship {
  position: relative;
  border-radius: var(--r-xl);
  border: 1px solid var(--border);
  background:
    radial-gradient(ellipse 55% 70% at 85% 15%, rgba(8, 145, 178, 0.14), transparent 60%),
    var(--bg-2);
  padding: var(--sp-7);
  overflow: hidden;
}
.flagship-grid {
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  gap: var(--gap-12);
  align-items: center;
}
.feature-list { list-style: none; display: grid; gap: var(--gap-4); margin: var(--sp-3) 0 var(--sp-4); }
.feature-list li {
  display: flex;
  gap: var(--gap-3);
  align-items: flex-start;
  color: var(--muted);
  font-size: var(--fs-lg);
}
.feature-list svg {
  width: 20px; height: 20px;
  flex-shrink: 0;
  color: var(--accent);
  margin-top: 0.2rem;
}
.feature-list strong { color: var(--text); font-weight: 600; }

/* process steps */
.step-num {
  font-family: var(--font-display);
  font-size: var(--fs-3xl);
  font-weight: 700;
  color: transparent;
  -webkit-text-stroke: 1px rgba(34, 211, 238, 0.6);
}

/* ---------- CTA band ---------- */
.cta-band {
  text-align: center;
  border-radius: var(--r-xl);
  border: 1px solid rgba(34, 211, 238, 0.25);
  background:
    radial-gradient(ellipse 60% 90% at 50% -20%, rgba(8, 145, 178, 0.22), transparent 65%),
    var(--bg-2);
  padding: var(--sp-8) var(--sp-4);
}
.cta-band h2 { margin-bottom: 0.9rem; }
.cta-band p { max-width: 52ch; margin: 0 auto 2rem; font-size: var(--fs-lg); }

/* ---------- page hero (inner pages) — same atmosphere as the homepage ---------- */
.page-hero {
  position: relative;
  min-height: clamp(360px, 56vh, 560px);
  display: flex;
  align-items: center;
  padding: var(--sp-20) 0 var(--sp-8);
  overflow: hidden;
}
.page-hero .hero-bg { z-index: -1; }
.page-hero .container { position: relative; z-index: 1; }
.page-hero h1 { max-width: 20ch; margin-bottom: 1.1rem; }
.page-hero .lead { max-width: 60ch; }

/* ---------- forms ---------- */
.form-grid { display: grid; gap: var(--gap-4); }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--gap-4); }
.field { display: flex; flex-direction: column; gap: var(--gap-2); }
.field label { font-size: var(--fs-sm); font-weight: 600; color: var(--text); }
.field input, .field select, .field textarea {
  font-family: var(--font-body);
  font-size: var(--fs-lg);
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 0.8rem 1rem;
  transition: border-color var(--dur-1) var(--ease-out);
}
.field select { appearance: none; }
.field select option { background: var(--bg-2); color: var(--text); }
.field input:hover, .field select:hover, .field textarea:hover { border-color: rgba(255,255,255,0.3); }
.field textarea { resize: vertical; min-height: 140px; }
/* 68ch matches the cap .prose already uses, so no new number enters the system.
   Without it these notes set to 155ch - more than twice a comfortable measure, and
   wider than anything on the reference, whose widest prose line is 79ch. */
.form-note {
  max-width: 68ch; font-size: var(--fs-sm); }
.form-status {
  display: none;
  padding: 0.9rem 1.1rem;
  border-radius: var(--radius-sm);
  font-size: var(--fs-lg);
  font-weight: 500;
}
.form-status.ok {
  display: block;
  background: rgba(34, 197, 94, 0.12);
  border: 1px solid rgba(34, 197, 94, 0.4);
  color: #86efac;
}
.form-status.err {
  display: block;
  background: rgba(239, 68, 68, 0.12);
  border: 1px solid rgba(239, 68, 68, 0.4);
  color: #fca5a5;
}

.contact-aside { display: grid; gap: var(--gap-6); align-content: start; }
.contact-line {
  display: flex;
  gap: var(--gap-4);
  align-items: flex-start;
}
.contact-line p { font-size: var(--fs-lg); }
.contact-line a { color: var(--accent); font-weight: 600; }
.contact-line a:hover { text-decoration: underline; }

/* ---------- footer ---------- */
footer {
  border-top: 1px solid var(--border);
  background: var(--bg-2);
  padding: var(--sp-8) 0 var(--sp-5);
  margin-top: var(--sp-4);
}
.footer-grid {
  display: grid;
  /* 🔴 FIVE tracks, because the footer supplies five children: brand, Industries,
     Services, Company, Network. It declared four, so grid wrapped "Network" onto a
     second row where it sat alone under the brand blurb, on every page that had it.
     A grid whose track count disagrees with its child count does not error — it
     silently reflows, which is why this survived. Count the children before you
     count the columns. */
  grid-template-columns: 1.5fr 1fr 1fr 1fr 1fr;
  gap: var(--gap-8);
  margin-bottom: var(--sp-6);
}
.footer-grid h2 {
  font-size: var(--fs-xs);
  letter-spacing: var(--track-label-md);
  text-transform: uppercase;
  color: var(--text);
  margin-bottom: 1rem;
}
.footer-grid ul { list-style: none; display: grid; gap: var(--gap-2); }
.footer-grid ul a { color: var(--muted); font-size: var(--fs-lg); transition: color var(--dur-1) var(--ease-out); }
.footer-grid ul a:hover { color: var(--accent); }
.footer-blurb { max-width: 34ch; font-size: var(--fs-lg); margin-top: 1rem; }
.footer-bottom {
  border-top: 1px solid var(--border);
  padding-top: var(--sp-3);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--gap-3);
  color: var(--muted);
  font-size: var(--fs-sm);
}

/* ---------- hero atmosphere: cursor trails ---------- */
.hero-trails {
  position: absolute;
  inset: 0;
  /* Must sit ABOVE the atmosphere layers (all z-index:-1). Underneath them,
     the vignette and aurora crush the trail's soft accumulated edges and it
     collapses into one hard bright line. Below .hero-inner (z-index:1) so it
     never crosses the headline. */
  z-index: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  opacity: 0.7;
  /* Confine the trail to the right-hand column where the orbs live. Unmasked,
     it draws a bright stroke straight through the H1 and subhead, which is a
     legibility cost the effect does not earn. */
  -webkit-mask-image: linear-gradient(to right, transparent 38%, rgba(0,0,0,0.55) 58%, #000 76%);
          mask-image: linear-gradient(to right, transparent 38%, rgba(0,0,0,0.55) 58%, #000 76%);
}
/* The script bails out under reduced motion and on coarse pointers, so the
   canvas simply stays empty — hide it so it can never affect layout. */
@media (prefers-reduced-motion: reduce) {
  .hero-trails { display: none; }
}
@media (pointer: coarse) {
  .hero-trails { display: none; }
}

/* ---------- hero atmosphere: animated aurora + film grain ---------- */
.hero-aurora {
  position: absolute;
  inset: -12% -6%;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
  filter: blur(64px) saturate(1.15);
}
.hero-aurora span {
  position: absolute;
  border-radius: 50%;
  mix-blend-mode: screen;
  will-change: transform;
}
.aur-1 { width: 48vw; height: 48vw; top: -10%; right: 2%;
  background: radial-gradient(circle, rgba(34,211,238,0.55), transparent 66%); opacity: 0.6; }
.aur-2 { width: 40vw; height: 40vw; bottom: -16%; left: -6%;
  background: radial-gradient(circle, rgba(14,116,144,0.6), transparent 66%); opacity: 0.6; }
.aur-3 { width: 32vw; height: 32vw; top: 28%; left: 36%;
  background: radial-gradient(circle, rgba(124,92,232,0.34), transparent 62%); opacity: 0.5; }
@media (prefers-reduced-motion: no-preference) {
  .aur-1 { animation: aur-a 19s ease-in-out infinite alternate; }
  .aur-2 { animation: aur-b 23s ease-in-out infinite alternate; }
  .aur-3 { animation: aur-c 27s ease-in-out infinite alternate; }
  @keyframes aur-a { to { transform: translate(-7%, 9%) scale(1.18); } }
  @keyframes aur-b { to { transform: translate(9%, -7%) scale(1.12); } }
  @keyframes aur-c { to { transform: translate(-11%, -9%) scale(1.22); opacity: 0.42; } }
}
/* vignette pushes the field back → reads as depth-of-field for free */
.hero-vignette {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(120% 92% at 50% 40%, transparent 36%, rgba(3, 6, 12, 0.62));
}
.hero-grain {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.085;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---------- floating field (parallax container) ---------- */
.float-field {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}
.float-wrap {
  position: absolute;
  will-change: transform;
  transition: transform 0.5s var(--ease-out);
}

/* ---------- glass orbs (real depth, Clay-style spheres) ---------- */
.orb {
  display: block;
  border-radius: 50%;
  will-change: transform;
}
.orb-cyan {
  width: 98px; height: 98px;   /* was inline on all 18 pages, identical every time */
  background: radial-gradient(circle at 33% 27%, #eafdff 0%, #7dd3fc 16%, #22d3ee 42%, #0e7490 73%, #052b35 100%);
  box-shadow:
    inset -10px -14px 30px rgba(0,0,0,0.45),
    inset 9px 11px 22px rgba(255,255,255,0.5),
    0 36px 60px rgba(0,0,0,0.5),
    0 0 64px rgba(34,211,238,0.22);
}
.orb-violet {
  width: 40px; height: 40px;   /* was inline on all 18 pages, identical every time */
  background: radial-gradient(circle at 33% 27%, #f4ecff 0%, #c4b5fd 18%, #8b5cf6 46%, #5b21b6 77%, #2a1259 100%);
  box-shadow:
    inset -8px -12px 26px rgba(0,0,0,0.45),
    inset 6px 9px 18px rgba(255,255,255,0.42),
    0 28px 50px rgba(0,0,0,0.5),
    0 0 52px rgba(139,92,246,0.26);
}
.orb-warm {
  background: radial-gradient(circle at 35% 30%, #fff1e0 0%, #fbbf24 40%, #b45309 100%);
  box-shadow:
    inset -4px -6px 12px rgba(0,0,0,0.4),
    0 16px 28px rgba(0,0,0,0.45),
    0 0 32px rgba(251,191,36,0.32);
}
/* far/deep sphere — large, dim, blurred = atmospheric depth-of-field back layer */
.orb-far {
  background: radial-gradient(circle at 38% 32%, rgba(125,211,252,0.55), rgba(34,211,238,0.32) 48%, rgba(8,47,58,0.6) 100%);
  box-shadow: 0 40px 80px rgba(0,0,0,0.4);
  filter: blur(6px);
  opacity: 0.5;
}
/* organic, continuous (non-ping-pong) float paths — each sphere drifts differently */
@media (prefers-reduced-motion: no-preference) {
  .orb-cyan   { animation: orb-a 15s ease-in-out infinite; }
  .orb-violet { animation: orb-b 11s ease-in-out infinite; }
  .orb-warm   { animation: orb-c 8.5s ease-in-out infinite; }
  .orb-far    { animation: orb-a 24s ease-in-out infinite; }
  @keyframes orb-a {
    0%, 100% { transform: translate(0, 0) rotate(0deg); }
    25%  { transform: translate(7px, -13px) rotate(2deg); }
    50%  { transform: translate(3px, 9px) rotate(-1.5deg); }
    75%  { transform: translate(-6px, -5px) rotate(1deg); }
  }
  @keyframes orb-b {
    0%, 100% { transform: translate(0, 0) rotate(0deg); }
    30%  { transform: translate(-9px, -10px) rotate(-3deg); }
    60%  { transform: translate(6px, 12px) rotate(3deg); }
  }
  @keyframes orb-c {
    0%, 100% { transform: translate(0, 0); }
    25%  { transform: translate(6px, 11px); }
    50%  { transform: translate(-7px, 5px); }
    75%  { transform: translate(4px, -11px); }
  }
}

/* ---------- hero figure: the logo as a real 3D-ish object ---------- */
.hero-figure { position: relative; perspective: 950px; }
.hero-figure-inner {
  position: relative;
  transform-style: preserve-3d;
  transition: transform 0.35s var(--ease-out);
}
.hero-figure img {
  display: block;
  border-radius: 24%;
  transform: translateZ(42px);            /* genuine z-lift above the sphere plane */
  box-shadow: 0 34px 80px rgba(0,0,0,0.62), 0 8px 20px rgba(0,0,0,0.5),
              0 0 54px rgba(34,211,238,0.28);
}
.hero-figure .bloom {
  position: absolute;
  inset: -28%;
  z-index: -1;
  background: radial-gradient(circle, rgba(34,211,238,0.4), transparent 60%);
  filter: blur(22px);
}
/* contact shadow lives OUTSIDE the tilt-inner → behaves like a floor cast,
   not attached to the object. The single cue that kills the floating-sticker look. */
.hero-figure > .contact {
  position: absolute;
  left: 8%; right: 8%; bottom: -15%;
  height: 22%;
  z-index: -2;
  background: radial-gradient(ellipse at center, rgba(0,0,0,0.62), transparent 72%);
  filter: blur(10px);
}
@media (prefers-reduced-motion: no-preference) {
  .hero-figure { animation: fig-float 9s ease-in-out infinite alternate; }
  @keyframes fig-float {
    from { transform: translateY(-11px); }
    to   { transform: translateY(15px); }
  }
}

@media (max-width: 760px) {
  .float-field, .hero-grain { display: none; }
}

/* ---------- properties wordmark wall (honest proof strip) ---------- */
.proof-strip {
  padding: var(--sp-7) 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  background: var(--bg-2);
}
.proof-label {
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: var(--track-label-md);
  text-transform: uppercase;
  color: var(--muted);
  text-align: center;
  margin-bottom: var(--sp-4);
}
.wordmark-wall {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: baseline;
  gap: var(--gap-6) var(--gap-12);
}
.wordmark {
  font-family: var(--font-display);
  font-size: var(--fs-d4);
  font-weight: 600;
  letter-spacing: -0.015em;
  color: #56697a;
  transition: color var(--dur-1) var(--ease-out);
  white-space: nowrap;
}
.wordmark:hover { color: var(--text); }
.wordmark-link {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-2);
  font-size: var(--fs-lg);
  font-weight: 600;
  color: var(--accent);
}
.wordmark-link svg { width: 16px; height: 16px; transition: transform var(--dur-1) var(--ease-out); }
.wordmark-link:hover svg { transform: translateX(4px); }

/* ---------- oversized editorial hero ---------- */
.hero-inner { position: relative; z-index: 1; }
.hero-title {
  font-size: var(--fs-d0);
  line-height: 0.97;
  letter-spacing: -0.038em;
  max-width: 15ch;
  margin: 0.4rem 0 var(--sp-3);
}
.hero-sub {
  font-size: var(--fs-d4);
  line-height: var(--lh-body);
  color: var(--muted);
  max-width: 44ch;
  margin-bottom: var(--sp-5);
}
.hero-meta {
  position: absolute;
  left: 0; right: 0; bottom: 2.4rem;
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-2) var(--gap-6);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: var(--track-label-md);
  text-transform: uppercase;
  color: var(--muted);
  z-index: 1;
}
.hero-meta b { color: var(--accent); font-weight: 600; margin-right: 0.5rem; }
@media (max-width: 760px) {
  .hero-meta { position: static; margin-top: var(--sp-5); }
}

/* ---------- big editorial statement (deepens the type ladder) ---------- */
/* 🔴 `.statement` is the SECTION TITLE on most pages, and it used to be a <p>.
   That left whole sections with no heading at all, so their h3 cards followed the
   page h1 directly — an h1 -> h3 skip on six pages, and no outline for a screen
   reader to navigate by. Promoted to <h2 class="statement">.

   Visually inert by construction: every typographic property the shared
   `h1,h2,h3,h4` rule sets is also set here, and `.statement` at (0,1,0) outranks
   the bare `h2` element rule at (0,0,1). Verified by whole-page ink comparison
   before and after, not by assumption. */
.statement {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--fs-d2);
  line-height: 1.2;
  letter-spacing: -0.025em;
  color: var(--text);
  max-width: 20ch;
}
.statement .muted { color: var(--muted); }
.statement.wide { max-width: 26ch; }

/* ---------- practice rows (type-led, replaces card grid) ---------- */
.practice-rows { border-top: 1px solid var(--border); margin-top: var(--sp-7); }
.practice-row {
  display: grid;
  grid-template-columns: 4rem 1fr auto;
  align-items: center;
  gap: var(--gap-6);
  padding: var(--sp-5) 0;
  border-bottom: 1px solid var(--border);
  text-decoration: none;
  transition: border-color var(--dur-2) var(--ease-out), padding var(--dur-2) var(--ease-out);
}
a.practice-row:hover { border-bottom-color: var(--accent); }
.practice-index {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: 600;
  color: var(--accent);
  letter-spacing: 0.05em;
}
.practice-main { display: flex; flex-direction: column; gap: var(--gap-3); }
.practice-name {
  font-family: var(--font-display);
  font-size: var(--fs-d2);
  font-weight: 600;
  line-height: 1.02;
  letter-spacing: -0.028em;
  color: var(--text);
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--gap-4);
  transition: color var(--dur-2) var(--ease-out);
}
a.practice-row:hover .practice-name { color: var(--accent); }
.practice-flag {
  font-family: var(--font-body);
  font-size: var(--fs-2xs);
  font-weight: 600;
  letter-spacing: var(--track-label-sm);
  text-transform: uppercase;
  color: var(--accent);
  border: 1px solid rgba(34, 211, 238, 0.4);
  background: var(--accent-soft);
  border-radius: var(--r-pill);
  padding: 0.25rem 0.7rem;
  align-self: center;
}
.practice-flag.neutral {
  color: var(--muted);
  border-color: var(--border);
  background: var(--surface-2);
}
.practice-desc { font-size: var(--fs-lg); color: var(--muted); max-width: 54ch; }
.practice-arrow {
  width: 52px; height: 52px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 1px solid var(--border-strong);
  display: grid;
  place-items: center;
  color: var(--text);
  transition: background-color var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out),
              border-color var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-spring);
}
.practice-arrow svg { width: 22px; height: 22px; }
.practice-row:hover .practice-arrow {
  background: var(--accent);
  /* 🔴 #04252e is a DARK-THEME literal. On the light theme --accent resolves to
     #1a1a1c, so hover painted a near-black glyph on a near-black disc: 1.08:1, and the
     arrow simply vanished at the moment the user pointed at it. The one place the
     affordance matters most is the one place it disappeared. */
  color: var(--bg);
  border-color: var(--accent);
  transform: rotate(-45deg);
}
@media (prefers-reduced-motion: reduce) {
  .practice-row:hover .practice-arrow { transform: none; }
}
@media (max-width: 760px) {
  .practice-rows { margin-top: var(--sp-5); }
  .practice-row { grid-template-columns: 1fr; gap: var(--gap-3); padding: var(--sp-4) 0; }
  .practice-index { order: -1; }
  .practice-arrow { display: none; }
}

/* ---------- hero split (copy + terminal) ---------- */
.hero-split {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: var(--gap-12);
  align-items: center;
}

/* terminal window */
.term {
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--border-strong);
  background: rgba(7, 11, 15, 0.92);
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(34, 211, 238, 0.06);
  font-size: var(--fs-sm);
}
.term-bar {
  display: flex;
  align-items: center;
  gap: var(--gap-2);
  padding: 0.65rem 0.95rem;
  background: rgba(255, 255, 255, 0.04);
  border-bottom: 1px solid var(--border);
}
.t-dot { width: 11px; height: 11px; border-radius: 50%; }
.t-dot.red { background: #f87171; }
.t-dot.yellow { background: #fbbf24; }
.t-dot.green { background: #34d399; }
.term-title {
  margin-left: 0.6rem;
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: var(--fs-xs);
  color: var(--muted);
  letter-spacing: var(--track-label-md);
}
.term-body {
  margin: 0;
  padding: 1.1rem 1.2rem 1.3rem;
  min-height: 222px;
  font-family: var(--font-mono);
  line-height: var(--lh-body);
  color: #c8d6e0;
  white-space: pre-wrap;
  overflow: hidden;
}
.term-body .tl-prompt { color: var(--accent); }
.term-body .tl-ok { color: #34d399; }
.term-body .tl-dim { color: #7d8e9b; }
.term-caret {
  display: inline-block;
  width: 8px; height: 1.05em;
  vertical-align: text-bottom;
  background: var(--accent);
}
@media (prefers-reduced-motion: no-preference) {
  .term-caret { animation: caret-blink 1s steps(1) infinite; }
  @keyframes caret-blink { 50% { opacity: 0; } }
}

/* ---------- architecture diagram ---------- */
.arch-panel {
  position: relative;
  padding: var(--sp-5) var(--sp-4);
  overflow: hidden;
  background:
    radial-gradient(ellipse 70% 70% at 68% 50%, rgba(34,211,238,0.06), transparent 70%),
    var(--surface);
}
.arch-svg { width: 100%; height: auto; display: block; }
/* nodes = raised glossy chips (gradient fill + edge + drop shadow via SVG filter) */
.arch-svg .node {
  fill: url(#nodeGrad);
  stroke: rgba(255, 255, 255, 0.09);
  stroke-width: 1;
}
.arch-svg .node.hub {
  fill: url(#hubGrad);
  stroke: rgba(34, 211, 238, 0.5);
  stroke-width: 1.3;
}
.arch-svg .gloss { fill: url(#gloss); pointer-events: none; }
.arch-svg .node-label {
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 600;
  fill: #f3f7fa;
}
.arch-svg .node-sub {
  font-family: var(--font-body);
  font-size: 10.5px;
  fill: #9eb1bf;
}
.arch-svg .flow {
  fill: none;
  stroke: url(#flowGrad);
  stroke-width: 2.4;
  stroke-dasharray: 5 9;
  stroke-linecap: round;
}
.arch-svg .pulse { fill: var(--accent); }
.arch-svg .spark { fill: #d8fcff; }
/* flows stay static (glow computed once) — the traveling sparks carry the motion,
   so we never re-blur a moving dash every frame (cheap on weak GPUs). */
@media (prefers-reduced-motion: no-preference) {
  .arch-svg .pulse { animation: node-pulse 2.4s ease-in-out infinite; transform-origin: center; transform-box: fill-box; }
  @keyframes node-pulse { 0%, 100% { opacity: 0.4; transform: scale(0.8); } 50% { opacity: 1; transform: scale(1.3); } }
}

/* tech stack chips */
.stack-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-2);
  margin-top: var(--sp-3);
}
.stack-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-2);
  padding: 0.45rem 0.95rem;
  border-radius: var(--r-pill);
  border: 1px solid var(--border);
  background: var(--surface);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  color: var(--muted);
  transition: border-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out), transform var(--dur-1) var(--ease-out);
}
.stack-chip:hover { border-color: rgba(34, 211, 238, 0.5); color: var(--text); transform: translateY(-2px); }
.stack-chip::before {
  content: "";
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0.7;
}

/* ---------- productized offer cards (with real prices) ---------- */
.offer {
  display: flex;
  flex-direction: column;
  gap: var(--gap-4);
  padding: var(--sp-4) var(--sp-4);
}
.offer.featured {
  border-color: rgba(34, 211, 238, 0.42);
  background:
    radial-gradient(ellipse 90% 60% at 50% 0%, rgba(34, 211, 238, 0.09), transparent 70%),
    rgba(13, 20, 26, 0.6);
}
.offer-head { display: flex; flex-direction: column; gap: var(--gap-2); }
.offer h3 { font-size: var(--fs-xl); }
.offer-meta {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: var(--track-label-md);
  text-transform: uppercase;
  color: var(--muted);
}
.price {
  font-family: var(--font-display);
  /* Prices sit side by side across offer cards and are read as a column, so the
     digits must share one advance width. Without this, $4,500 / $12,500 /
     $22,000 set ragged and the cards look misaligned even though the boxes are
     not. `lining-nums` also stops any old-style/oldstyle figures in the display
     face from dropping below the baseline. */
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "tnum" 1, "lnum" 1;
  font-size: var(--fs-d3);
  font-weight: 600;
  letter-spacing: -0.025em;
  color: var(--text);
  line-height: 1.1;
}
.price small {
  display: block;
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: 0;
  color: var(--muted);
  margin-top: 0.3rem;
}
.offer-list { list-style: none; display: grid; gap: var(--gap-2); margin: 0.2rem 0 0; }
.offer-list li {
  display: flex;
  gap: var(--gap-2);
  align-items: flex-start;
  font-size: var(--fs-lg);
  color: var(--muted);
  line-height: var(--lh-dense);
}
.offer-list li::before {
  content: "";
  flex-shrink: 0;
  width: 16px; height: 16px;
  margin-top: 0.24rem;
  background: var(--accent);
  opacity: 0.85;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E") center/contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E") center/contain no-repeat;
}
.offer-list.excl li { color: #7d8e9b; }
.offer-list.excl li::before {
  background: #7d8e9b;
  opacity: 0.7;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'/%3E%3Cline x1='6' y1='6' x2='18' y2='18'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'/%3E%3Cline x1='6' y1='6' x2='18' y2='18'/%3E%3C/svg%3E");
}
.offer-sub {
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: var(--track-label-md);
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 0.4rem;
}
.offer .btn { margin-top: auto; align-self: flex-start; }

/* ---------- data-residency strip ---------- */
.residency {
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  background: var(--bg-2);
  /* 🔴 This was `padding: 3.2rem 0`, specificity (0,1,0), which OUTRANKS
     `main > section { padding: var(--sp-12) 0.75rem }` in light.css at (0,0,2). The
     declared 100px never landed here: this band rendered at 51.2px while its
     eight neighbours rendered at 100px, so one section sat at half the page's
     vertical rhythm for no stated reason. CLAUDE.md 5.1 firing in production
     again - a class beats an element-plus-child selector every time.
     Horizontal only now; the shell rule supplies the vertical. */
  padding-left: 0;
  padding-right: 0;
}
.residency-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--gap-4); margin-top: var(--sp-4); }
.res-item {
  padding: 1.3rem 1.2rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  transition: border-color var(--dur-2) var(--ease-out);
}
.res-item:hover { border-color: rgba(34, 211, 238, 0.4); }
.res-item b {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  color: var(--text);
  margin-bottom: 0.35rem;
}
.res-item span { font-size: var(--fs-sm); color: var(--muted); line-height: var(--lh-dense); }

/* ---------- build-vs-buy comparison ---------- */
.cmp-wrap { overflow-x: auto; margin-top: var(--sp-4); }
.cmp {
  width: 100%;
  min-width: 640px;
  border-collapse: collapse;
  font-size: var(--fs-lg);
}
.cmp th, .cmp td {
  text-align: left;
  padding: 1rem 1.1rem;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
.cmp th {
  font-family: var(--font-display);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: var(--track-label-md);
  text-transform: uppercase;
  color: var(--muted);
}
.cmp td:first-child { color: var(--text); font-weight: 600; white-space: nowrap; }
.cmp td { color: var(--muted); }
.cmp tr:last-child td { border-bottom: none; }
.cmp .us { color: var(--accent); }

/* ---------- honest callout ---------- */
.callout {
  border-left: 2px solid var(--accent);
  background: var(--accent-soft);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  padding: 1.3rem 1.5rem;
  margin-top: var(--sp-4);
}
.callout p { color: var(--text); font-size: var(--fs-lg); margin: 0; }
.callout p + p { margin-top: 0.7rem; color: var(--muted); }

/* ---------- trust / spec rows ---------- */
.spec { border-top: 1px solid var(--border); }
.spec-row {
  display: grid;
  grid-template-columns: 15rem 1fr;
  gap: var(--gap-6);
  padding: 1.5rem 0;
  border-bottom: 1px solid var(--border);
}
.spec-row dt {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-lg);
  color: var(--text);
}
.spec-row dd { margin: 0; color: var(--muted); font-size: var(--fs-lg); line-height: var(--lh-body); }
@media (max-width: 760px) {
  .residency-grid { grid-template-columns: 1fr; }
  .spec-row { grid-template-columns: 1fr; gap: var(--gap-2); }
}
@media (max-width: 1024px) {
  .residency-grid { grid-template-columns: repeat(2, 1fr); }
}

/* ---------- case studies (own products) ---------- */
.case {
  display: grid;
  grid-template-columns: 1fr 1.15fr;
  gap: var(--gap-12);
  align-items: center;
  padding: var(--sp-8) 0;
  border-bottom: 1px solid var(--border);
}
.case:last-child { border-bottom: none; }
.case.flip .case-body { order: 2; }
.case-tags { display: flex; flex-wrap: wrap; gap: var(--gap-2); margin-bottom: 1.1rem; }
.case-tag {
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
  letter-spacing: var(--track-label-sm);
  text-transform: uppercase;
  color: var(--muted);
  border: 1px solid var(--border);
  background: var(--surface);
  border-radius: var(--r-pill);
  padding: 0.28rem 0.75rem;
}
.case-tag.own { color: var(--accent); border-color: rgba(34,211,238,0.4); background: var(--accent-soft); }
.case h3 {
  font-size: var(--fs-d3);
  line-height: 1.1;
  letter-spacing: -0.025em;
  margin-bottom: 0.9rem;
}
.case-desc { font-size: var(--fs-lg); line-height: var(--lh-body); }
.case-list { list-style: none; display: grid; gap: var(--gap-2); margin: 1.4rem 0 0; }
.case-list li {
  display: flex; gap: var(--gap-2); align-items: flex-start;
  font-size: var(--fs-lg); color: var(--muted); line-height: var(--lh-dense);
}
.case-list li::before {
  content: ""; flex-shrink: 0;
  width: 15px; height: 15px; margin-top: 0.26rem;
  background: var(--accent); opacity: 0.8;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E") center/contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E") center/contain no-repeat;
}
.case-stats {
  display: flex; flex-wrap: wrap; gap: var(--gap-8);
  margin-top: var(--sp-4); padding-top: 1.5rem;
  border-top: 1px solid var(--border);
}
.case-stat b {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-d4);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--accent);
  line-height: 1.1;
}
.case-stat span { font-size: var(--fs-xs); color: var(--muted); }
.case-shot {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--border-strong);
  box-shadow: 0 30px 70px rgba(0,0,0,0.55), 0 0 50px rgba(34,211,238,0.07);
  transition: transform var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out);
}
.case-shot img { display: block; width: 100%; height: auto; }
.case-shot:hover { transform: translateY(-5px); box-shadow: 0 38px 84px rgba(0,0,0,0.62), 0 0 64px rgba(34,211,238,0.14); }
@media (prefers-reduced-motion: reduce) { .case-shot:hover { transform: none; } }
@media (max-width: 900px) {
  .case { grid-template-columns: 1fr; gap: var(--gap-8); padding: var(--sp-6) 0; }
  .case.flip .case-body { order: 0; }
  .case-stats { gap: var(--gap-6); }
}

/* ---------- work grid (homepage proof) ---------- */
/* .work-grid is retired — the homepage section is now .work-stack (see light.css).
   Kept as a 3-up grid for any future page that wants the old tile layout. */
.work-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gap-6); margin-top: var(--sp-6); }
.work-card {
  display: flex;
  flex-direction: column;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--border);
  background: rgba(13, 20, 26, 0.6);
  text-decoration: none;
  transition: border-color var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out),
              box-shadow var(--dur-2) var(--ease-out);
}
.work-card:hover {
  border-color: rgba(34, 211, 238, 0.45);
  transform: translateY(-5px);
  box-shadow: 0 22px 54px rgba(0,0,0,0.5), 0 0 44px rgba(34,211,238,0.1);
}
@media (prefers-reduced-motion: reduce) { .work-card:hover { transform: none; } }
.work-shot {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-bottom: 1px solid var(--border);
  background: var(--bg-2);
}
.work-shot img {
  width: 100%; height: 100%;
  object-fit: cover; object-position: top center;
  display: block;
  transition: transform 0.6s var(--ease-out);
}
.work-card:hover .work-shot img { transform: scale(1.04); }
@media (prefers-reduced-motion: reduce) { .work-card:hover .work-shot img { transform: none; } }
.work-body { padding: 1.4rem 1.5rem var(--sp-3); display: flex; flex-direction: column; gap: var(--gap-2); flex: 1; }
.work-kicker {
  font-family: var(--font-mono);
  font-size: var(--fs-2xs); letter-spacing: var(--track-label-sm); text-transform: uppercase;
  color: var(--accent);
}
.work-body h3 { font-size: var(--fs-lg); line-height: 1.25; color: var(--text); }
.work-body p { font-size: var(--fs-sm); line-height: var(--lh-body); }
.work-metric {
  margin-top: auto; padding-top: 1rem;
  border-top: 1px solid var(--border);
  font-size: var(--fs-sm); color: var(--muted);
}
.work-metric b { color: var(--text); font-family: var(--font-display); font-weight: 600; }
@media (max-width: 900px) { .work-grid { grid-template-columns: 1fr; } }

/* ---------- insights / articles ---------- */
.post-list { border-top: 1px solid var(--border); margin-top: var(--sp-6); }
.post {
  display: grid;
  grid-template-columns: 8.5rem 1fr auto;
  gap: var(--gap-8);
  align-items: baseline;
  padding: var(--sp-4) 0;
  border-bottom: 1px solid var(--border);
  text-decoration: none;
  transition: border-bottom-color var(--dur-2) var(--ease-out);
}
.post:hover { border-bottom-color: var(--accent); }
.post-date {
  font-family: var(--font-mono);
  font-size: var(--fs-xs); letter-spacing: var(--track-label-md); text-transform: uppercase;
  color: var(--muted);
}
.post-main { display: flex; flex-direction: column; gap: var(--gap-2); }
.post-title {
  font-family: var(--font-display);
  font-size: var(--fs-d4);
  font-weight: 600; line-height: 1.25; letter-spacing: -0.018em;
  color: var(--text);
  transition: color var(--dur-2) var(--ease-out);
}
.post:hover .post-title { color: var(--accent); }
.post-excerpt { font-size: var(--fs-lg); color: var(--muted); line-height: var(--lh-body); max-width: 62ch; }
.post-read { font-size: var(--fs-xs); color: var(--muted); white-space: nowrap; }
@media (max-width: 760px) {
  .post { grid-template-columns: 1fr; gap: var(--gap-2); padding: var(--sp-3) 0; }
  .post-read { display: none; }
}

/* ---------- article prose ---------- */
.prose { max-width: 68ch; }
.prose > * + * { margin-top: 1.35rem; }
.prose h2 {
  font-size: var(--fs-d4);
  margin-top: var(--sp-6);
  padding-top: 0.4rem;
  letter-spacing: -0.022em;
}
.prose h3 { font-size: var(--fs-lg); margin-top: var(--sp-4); }
.prose p, .prose li { font-size: var(--fs-lg); line-height: var(--lh-body); color: var(--muted); }
.prose strong { color: var(--text); font-weight: 600; }
/* :not(.btn) for the same reason as the light-theme rule — see light.css. */
.prose a:not(.btn) { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }
.prose ul, .prose ol { padding-left: 1.3rem; display: grid; gap: var(--gap-2); }
.prose li::marker { color: var(--accent); }
.prose blockquote {
  border-left: 2px solid var(--accent);
  background: var(--accent-soft);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  padding: 1.1rem 1.4rem;
  margin-left: 0;
}
.prose blockquote p { color: var(--text); margin: 0; }
.prose code {
  font-family: var(--font-mono);
  font-size: 0.92em;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  padding: 0.12em 0.42em;
  color: var(--text);
}
.prose table { width: 100%; border-collapse: collapse; font-size: var(--fs-lg); }
.prose th, .prose td { text-align: left; padding: 0.8rem 0.9rem; border-bottom: 1px solid var(--border); }
.prose th {
  font-family: var(--font-display); font-size: var(--fs-xs); font-weight: 600;
  letter-spacing: var(--track-label-md); text-transform: uppercase; color: var(--muted);
}
.prose td { color: var(--muted); }
.prose td:first-child { color: var(--text); }
/* #7d8e9b measured 3.38:1 on white — another blue-cast grey under the AA floor. */
.prose .tnote { font-size: var(--fs-sm); color: var(--muted); }
.article-meta {
  display: flex; flex-wrap: wrap; gap: var(--gap-2) var(--gap-6);
  font-family: var(--font-mono);
  font-size: var(--fs-xs); letter-spacing: var(--track-label-md); text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 1.4rem;
}
.article-nav {
  display: flex; justify-content: space-between; gap: var(--gap-4); flex-wrap: wrap;
  margin-top: var(--sp-7); padding-top: var(--sp-4);
  border-top: 1px solid var(--border);
}

/* ---------- reveal animation ----------
   Keyframe (not transition) so it never collides with hover transitions on
   elements that are both .reveal and .card. `backwards` fill holds the hidden
   start during the JS stagger delay; no `forwards`, so hover transform is free
   once the entrance finishes. */
/* 🔴 Gated on html.js, which main.js sets IMMEDIATELY BEFORE wiring the reveal
   observer — deliberately NOT as its first statement. On line 1, any later throw in
   that file left every block hidden forever, which is the failure this gate exists to
   prevent. Do not "tidy" it back to the top. Previously a bare
   `.reveal { opacity: 0 }`: with 21 .reveal blocks, no <noscript> anywhere, and
   main.js as a single IIFE, one thrown error served prices at 2.27:1 contrast
   and everything below at 1.00:1 — white on white, at HTTP 200, no console
   error. Gating on a class the script itself sets also covers "JS loaded but
   threw", which <noscript> does not. /trust.html commits to WCAG 2.0 AA. */
html.js .reveal:not(.visible) { opacity: 0; }
/* 🔴 `:not(.visible)` is load-bearing, not decoration. The first version of this
   fix was `html.js .reveal`, which is specificity (0,2,1) and OUTRANKS
   `.reveal.visible` (0,2,0) — so the observer added .visible and opacity stayed
   pinned at 0. The whole page below the hero went blank on production.
   Excluding .visible from the hide rule removes the race entirely rather than
   winning it. See CLAUDE.md §5.1: specificity decides, and `!important` would
   not have helped here either. */
.reveal.visible {
  opacity: 1;
  animation: reveal-rise var(--dur-3) var(--ease-out-soft) backwards;
}
@keyframes reveal-rise {
  from { opacity: 0; transform: translateY(26px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  /* 🔴 This escape hatch was itself out-specified. `.reveal` is (0,1,0) and could
     never beat the `html.js .reveal:not(.visible)` gate at (0,3,1), so a
     reduced-motion visitor whose JS died between setting the `js` class and wiring
     the observer still got a blank page — the exact scenario this line exists for.
     Matching the gate's selector and specificity, and sitting later in the file, is
     what actually makes it win. A fallback that cannot outrank the thing it is
     falling back from is decoration. */
  html.js .reveal:not(.visible) { opacity: 1; }
  .reveal { opacity: 1; }
  .reveal.visible { animation: none; }
}

/* ============================================================
   🔴 DEAD-CLASS AUDIT — 2026-08-23. NOT ACTED ON. READ BEFORE DELETING.

   A scan of both stylesheets against all 29 HTML files and both JS files listed
   65 classes as "defined in CSS, referenced nowhere". They were NOT removed,
   and the reason is worth keeping:

   The list included `.js` — the class that gates `html.js .reveal:not(.visible)`
   and therefore the visibility of every reveal block on the site. It is set at
   main.js:42 as `className += " js"`, and the scan missed it because it searched
   for the literal "js" while the string carries a leading space. Deleting from
   that list would have re-created the blackout fixed earlier the same day.

   Genuinely dead as of this date (their JS was removed in the same pass):
   `.term`, `.term-bar`, `.term-body`, `.term-title`, `.term-caret`, `.tl-prompt`,
   `.tl-ok`, `.tl-dim`, `.hero-figure`, `.hero-figure-inner`. Everything else in
   the list is unverified and may be applied by JS, by a class list this scan
   parsed badly, or by lab/.

   If you clean these up: verify each one against the RENDERED page, not the
   source, and delete in small batches with a screenshot diff between each.
   A dead-code scan that is wrong about one entry is wrong about an unknown
   number of them.
   ============================================================ */

/* ---------- responsive ---------- */
@media (max-width: 1024px) {
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
  .grid-3 { grid-template-columns: repeat(2, 1fr); }
  .flagship { padding: var(--sp-5); }
  .flagship-grid { grid-template-columns: 1fr; gap: var(--gap-8); }
  .footer-grid { grid-template-columns: 1fr 1fr; }   /* 5 -> 2 up, brand spans naturally */
  .hero-split { grid-template-columns: 1fr; gap: var(--gap-10); }
}

@media (max-width: 760px) {
  body { font-size: 16px; }
  section { padding: var(--sp-8) 0; }
  .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
  .form-row { grid-template-columns: 1fr; }
  .hero { min-height: 0; padding-top: var(--sp-12); }

  .nav-toggle { display: flex; }
  .nav-links {
    position: absolute;
    top: calc(100% + 0.6rem);
    left: 0; right: 0;
    flex-direction: column;
    align-items: stretch;
    padding: 0.8rem;
    border-radius: var(--r-xl);
    /* Fully opaque: the panel is tall now that it carries both dropdown
       groups, and at 0.96 the hero type read through it. */
    background: #0a0e12;
    border: 1px solid var(--border);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    display: none;
  }
  .nav-links.open { display: flex; }
  .nav-links a { padding: 0.85rem 1rem; border-radius: var(--r-md); }
  .nav-cta { margin: 0.4rem 0 0; }

  /* Below the breakpoint the panel is already a column, so the dropdowns
     simply become inline sections. No toggling, nothing to tap twice. */
  .nav-links .has-menu { position: static; }
  .nav-links .has-menu > a .nav-caret { display: none; }
  .nav-menu {
    position: static;
    transform: none;
    min-width: 0;
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    background: none;
    border: none;
    box-shadow: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    padding: 0 0 0.4rem 0.6rem;
    border-left: 1px solid var(--border);
    margin: 0.1rem 0 0.5rem 1rem;
  }
  .nav-menu::before { display: none; }
  .nav-menu a { padding: 0.6rem 0.7rem; }
  .nav-menu a span { display: none; }   /* descriptions would bloat the panel */
  .nav-menu-sep { display: none; }
}
