/* ═══════════════════════════════════════════════════════════════════════
   VEYDROS GROUP — veydros.com
   ═══════════════════════════════════════════════════════════════════════

   THE GRAMMAR. This is not a palette, it is a semantics. Every rule below
   is downstream of these four sentences, and a change to any of them is a
   change to the argument the site is making:

       NAVY  is a judgement that is still standing.
       GREY  is everything set down — the material you brought us,
             and the branches we ruled out.
       INK   is the firm speaking in its own voice.
       WHITE is what has not been decided yet.

   The visitor learns this in the first two seconds of the trace without
   being told, and it then holds for the whole site. It is why hover draws
   a rule rather than lifting a card: a mark is a decision, an elevation is
   a mood. It is why the footer is the one filled navy field — that is
   where the firm signs.

   NAVY BUDGET: under 4% of painted pixels above the footer, on every page.
   This is the design, not a preference. At ~10% it stops being a white
   sheet with a line drawn through it and becomes a corporate blue website.

   DARK SURFACE BUDGET: exactly one, the footer. One temperature: daylight.

   BANNED, WITHOUT EXCEPTION: teal, amber, warm greys, purple, gradients of
   any kind (including navy→navy — a gradient implies interpolation, which
   is precisely what this firm's engine does not do), glow, atmospheric
   wash, filter: blur(), and box-shadow. Elevation is expressed as rule
   weight (--rule → --navy). border-radius is 0 everywhere. The only
   permitted box-shadow on this site is the focus ring.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── Fonts — THE VEYDROS TYPE SYSTEM ──────────────────────────────────
   Satoshi (editorial display) + Manrope (primary / body / apparatus),
   self-hosted. This is the Veydros Group brand typography, distinct from
   the Axis Meridi Helvetica-only rule — veydros.com is the parent brand
   and carries the parent's face.

   WEIGHTS ARE THIN, by brand law: display 300, body 300–400, labels 500.
   NEVER 600+ anywhere. Emphasis is carried by size, colour and eyebrows,
   not by bold. (This inverts the earlier Helvetica build, whose weights
   were the wrong way round.) */
@font-face {
  font-family: 'Satoshi';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('/assets/fonts/satoshi-300.woff2') format('woff2');
}
@font-face {
  font-family: 'Satoshi';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/satoshi-500.woff2') format('woff2');
}
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 200 700;          /* variable; we use 300 / 400 / 500 */
  font-display: swap;
  src: url('/assets/fonts/manrope-var-latin.woff2') format('woff2');
}

:root {
  /* Surfaces */
  --paper:       #FFFFFF;  /* ~85% of painted pixels */
  --bone:        #F4F5F7;  /* cool off-white, zero warmth. Never > 1 field per viewport */

  /* Lines and set-down material */
  --rule:        #D3D7DE;  /* every hairline at rest, and every ruled-out stroke */
  --grey-600:    #5F6874;  /* 5.65:1 — all apparatus labels and every ruled-out reason */
  --graphite:    #39404B;  /* 10.45:1 — body copy */

  /* The firm's voice, and the mark */
  --ink:         #0D1B2A;  /* 17:1 — headings, ROOT, register numerals, the footer plate */
  --navy:        #1A2B4A;  /* 14.0:1 — THE MARK */
  --navy-active: #2E5A9A;  /* 6.65:1 — INTERACTION ONLY. Never a resting colour. */

  /* Type — Satoshi display, Manrope everything else. */
  --display: 'Satoshi', 'Manrope', 'Helvetica Neue', Arial, sans-serif;
  --sans:    'Manrope', 'Helvetica Neue', Helvetica, Arial, sans-serif;

  --maxw: 1280px;
  --gutter: 32px;
  --section: 128px;

  color-scheme: light;   /* so native form controls never invert */
}

/* ── Reset ───────────────────────────────────────────────────────────── */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
/* NO scroll-behavior: smooth. Motion on this site is authored, not ambient. */

body {
  background: var(--paper);
  color: var(--graphite);
  font-family: var(--sans);
  font-weight: 400;
  font-size: 1.0625rem;   /* 17px */
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-feature-settings: 'kern' 1, 'liga' 1;
}

img, svg { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
::selection { background: var(--ink); color: #FFFFFF; }

/* THE VEYDROS DISPLAY VOICE — Satoshi, thin.
   Headings are Satoshi 300 (Light). This is the parent brand's editorial
   face, and thinness is the point: on a bright page, hierarchy comes from
   SIZE, TRACKING and RULE, never from weight. The brand law is explicit —
   display 300, body 300–400, labels 500, NEVER 600+. Do not "fix" a heading
   by making it heavier; make it larger or add an eyebrow. */

h1, h2, h3, h4 { color: var(--ink); }

.h1 {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(2.5rem, 1.4rem + 4.4vw, 4.5rem);
  line-height: 1.03;
  letter-spacing: -0.03em;
}
.h2 {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.75rem, 1.1rem + 2.4vw, 2.75rem);
  line-height: 1.12;
  letter-spacing: -0.025em;
}
.h3 {
  font-family: var(--display); font-weight: 500;
  font-size: 1.125rem; line-height: 1.30; letter-spacing: -0.01em;
}

.lead {
  font-weight: 300;
  font-size: clamp(1.125rem, 1rem + 0.5vw, 1.375rem);
  line-height: 1.52;
  color: var(--graphite);
  max-width: 58ch;
}
.body, p { max-width: 62ch; }
.pull {
  font-family: var(--display); font-weight: 300;
  font-size: 1.5rem; line-height: 1.32; letter-spacing: -0.02em;
  color: var(--ink);
  max-width: 52ch;
}

/* Apparatus — eyebrows, indices, tags, captions, buttons. Manrope Medium
   (500), uppercase, wide-tracked: the brand's label treatment. Visibly a
   different register from the prose without a third typeface. */
.eyebrow, .tag, .index, .cap, .btn, .ex-label, .foot-meta {
  font-family: var(--sans);
  font-variant-numeric: tabular-nums;
}
.eyebrow, .index, .cap, .tag {
  font-size: 0.6875rem;   /* 11px */
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--grey-600);
}

/* Inline mention of a group brand — Manrope Medium + ink colour. Brand law:
   emphasis is never 600+, so the lift is one step to 500, not to bold. */
.brand { font-weight: 500; color: var(--ink); }

/* ── Layout ──────────────────────────────────────────────────────────── */
.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 var(--gutter); }

/* 12 columns. Content occupies 1–8; 10–12 are margin and carry only mono
   apparatus. Everything is left-aligned. No centred hero, no centred
   section heading, ever. */
.grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: var(--gutter); }
.col-main { grid-column: 1 / span 8; }
.col-side { grid-column: 10 / span 3; }

.section { padding: var(--section) 0; border-top: 1px solid var(--rule); }
.section:first-of-type { border-top: 0; }
.section-head { margin-bottom: 48px; }
.section-head .index { display: block; margin-bottom: 20px; }
.section-head .h2 { max-width: 20ch; }
.stack > * + * { margin-top: 24px; }
.stack-lg > * + * { margin-top: 40px; }

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

/* The skip link is .vh until focused, then it must become VISIBLE — a
   skip link you cannot see when it is focused is not a skip link. Tabbing
   into it un-clips it and drops it into the top-left corner as a real,
   navy-on-white control. WCAG 2.4.7. */
.skip:focus {
  position: fixed !important; top: 12px; left: 12px;
  width: auto; height: auto; margin: 0;
  clip: auto; clip-path: none; overflow: visible;
  padding: 12px 20px; background: var(--ink); color: #FFFFFF; z-index: 100;
  font-family: var(--sans); font-size: 0.6875rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.16em;
}

/* ── Focus. The ring is navy because it marks where the keyboard is. ──── */
:focus { outline: none; }
:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--navy-active);   /* the ONLY box-shadow on this site */
  outline-offset: 2px;
}

/* ── Masthead. One hairline. That is the entire navigation. ───────────── */
.masthead { padding: 28px 0 20px; border-bottom: 1px solid var(--rule); }
.masthead .wrap {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 24px; flex-wrap: wrap;
}
/* The Veydros wordmark logo (real vector, recoloured to --ink). */
.wordmark { display: inline-flex; align-items: center; line-height: 0; }
.wordmark img { height: 19px; width: auto; display: block; }
.nav { display: flex; flex-wrap: wrap; gap: 4px 28px; align-items: baseline; }
.nav a {
  font-family: var(--sans); font-size: 0.6875rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.16em; color: var(--grey-600);
  padding-bottom: 2px; border-bottom: 1px solid transparent;
}
/* Hover draws a mark. It does not lift, tint or glow. */
.nav a:hover { color: var(--ink); border-bottom-color: var(--navy); }
.nav a[aria-current='page'] { color: var(--ink); border-bottom-color: var(--navy); }

/* ── Links in prose ──────────────────────────────────────────────────── */
.link {
  color: var(--ink);
  border-bottom: 1px solid var(--rule);
  padding-bottom: 1px;
}
.link:hover { border-bottom-color: var(--navy); }
.link-mono {
  font-family: var(--sans); font-size: 0.6875rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.16em; color: var(--ink);
  border-bottom: 1px solid var(--rule); padding-bottom: 3px;
  display: inline-block;
}
.link-mono:hover { border-bottom-color: var(--navy); }

/* ── Buttons ─────────────────────────────────────────────────────────── */
.btn {
  display: inline-block;
  font-family: var(--sans); font-size: 0.6875rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.16em;
  padding: 15px 26px; border: 1px solid var(--ink);
  background: var(--ink); color: #FFFFFF;
  transition: background-color 160ms ease, border-color 160ms ease;
}
.btn:hover { background: var(--navy-active); border-color: var(--navy-active); }
.btn-ghost { background: none; color: var(--ink); border-color: var(--rule); }
.btn-ghost:hover { background: none; color: var(--ink); border-color: var(--navy); }
.btn-row { display: flex; flex-wrap: wrap; gap: 16px 28px; align-items: center; }

/* ── THE MARK ─────────────────────────────────────────────────────────
   A 1px navy rule draws left→right. It is the firm standing behind what
   sits above it. The register's numerals are NOT counted up — counting a
   number up is asking for applause; printing it is stating a fact. The
   numeral is already at its final value; only the mark draws.

   PROGRESSIVE-ENHANCEMENT INVERSION (non-negotiable, a review gate):
   CSS ships the FINISHED state. JS adds .is-armed, which UN-draws it, then
   .is-drawn on the next frame, which re-draws it with a transition. No-JS,
   a CSP block, an old browser and reduced-motion therefore all land on the
   identical correct composition, with no second code path to maintain and
   no chance of divergence. Do not flip this. */
.rule-mark { display: block; height: 1px; background: var(--navy); transform-origin: left; }
.rule-mark.is-armed { transform: scaleX(0); transition: none; }
.rule-mark.is-armed.is-drawn {
  transform: scaleX(1);
  transition: transform 320ms cubic-bezier(0.22, 0.65, 0.2, 1);
}

/* ── Hero ────────────────────────────────────────────────────────────── */
.hero { padding: 96px 0 var(--section); }
.hero-grid { display: grid; grid-template-columns: 1fr 1.05fr; gap: 72px; align-items: start; }
.hero .h1 { margin: 20px 0 0; max-width: 14ch; }
.hero .lead { margin-top: 28px; }
.hero .btn-row { margin-top: 40px; }
.trace-intro { margin-top: 56px; color: var(--graphite); max-width: 52ch; }

/* ── The example selector. Native radios: real radiogroup semantics and
      arrow-key traversal for free. Never hand-roll role="radio".

      The .ex-block fieldset wraps the radios AND the traces so that the
      radios are direct siblings of both .ex-select and .traces — a sibling
      combinator cannot climb out of a wrapper, and the whole switch is
      CSS-only. See the structure note in tools/gen-trace.mjs. */
.ex-block { border: 0; margin: 0; padding: 0; min-width: 0; }
.ex-select { margin: 0 0 28px; display: flex; flex-direction: column; }
.ex-label {
  display: block;
  font-size: 0.6875rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.14em;
  color: var(--grey-600);
  padding: 12px 0; border-top: 1px solid var(--rule);
  cursor: pointer;
  transition: color 160ms ease;
}
.ex-select .ex-label:last-child { border-bottom: 1px solid var(--rule); }
.ex-num { color: var(--rule); margin-right: 2px; transition: color 160ms ease; }
.ex-label:hover { color: var(--ink); }

/* The set-down, at low volume: while we are following this one, the others
   are set down. Same grammar as the trace, one step quieter. */
#ex1:checked ~ .ex-select .ex-label[for='ex1'],
#ex2:checked ~ .ex-select .ex-label[for='ex2'],
#ex3:checked ~ .ex-select .ex-label[for='ex3'] {
  color: var(--ink); border-top-color: var(--navy);
}
#ex1:checked ~ .ex-select .ex-label[for='ex1'] .ex-num,
#ex2:checked ~ .ex-select .ex-label[for='ex2'] .ex-num,
#ex3:checked ~ .ex-select .ex-label[for='ex3'] .ex-num { color: var(--navy); }

#ex1:focus-visible ~ .ex-select .ex-label[for='ex1'],
#ex2:focus-visible ~ .ex-select .ex-label[for='ex2'],
#ex3:focus-visible ~ .ex-select .ex-label[for='ex3'] {
  box-shadow: 0 0 0 2px var(--navy-active); color: var(--ink);
}

/* Example switching is CSS-only and works with JavaScript disabled. */
.traces .trace { display: none; }
#ex1:checked ~ .traces [data-ex='1'],
#ex2:checked ~ .traces [data-ex='2'],
#ex3:checked ~ .traces [data-ex='3'] { display: block; }

.tr-cap { margin-top: 20px; }
.tr-cap {
  font-family: var(--sans); font-size: 0.6875rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.14em; color: var(--grey-600);
}

/* ═══ THE TRACE ═══════════════════════════════════════════════════════
   Rest state = FINISHED. See the inversion note above. */

.tr-svg { width: 100%; height: auto; overflow: visible; }

/* The outline renderer is OFF above 760px. Both parts of it must be named
   here: .tr-o-payoff is a SIBLING of .tr-outline, not a child, so hiding
   only .tr-outline left the payoff line rendering on desktop underneath the
   SVG's own payoff — the same sentence printed twice. */
.tr-outline, .tr-o-payoff { display: none; }

.tr-given-box { fill: none; stroke: var(--rule); stroke-width: 1; }
.tr-given-t { font: 400 15px var(--sans); fill: var(--ink); }

.tr-q {
  font-family: var(--sans); font-size: 11.5px; font-weight: 500;
  letter-spacing: 0.13em; fill: var(--grey-600);
}
.tr-tag {
  font-family: var(--sans); font-size: 11px; font-weight: 500;
  letter-spacing: 0.15em; fill: var(--grey-600);
}
.tr-reason {
  font-family: var(--sans); font-size: 12px; font-weight: 400;
  letter-spacing: 0.01em; fill: var(--grey-600);
}
.tr-lbl { font: 400 16px var(--sans); fill: var(--ink); }
.tr-root-box { fill: var(--ink); }
.tr-root-t { font: 400 15px var(--sans); fill: #FFFFFF; }
/* The payoff is the punchline — Satoshi, thin, a touch larger. */
.tr-payoff { font: 300 23px var(--display); fill: var(--ink); letter-spacing: -0.015em; }

/* Marks. pathLength="1" on every path means dasharray/dashoffset are always
   exactly 1/0 and JS never measures a path. */
.tr-mark { fill: none; stroke: var(--navy); stroke-width: 1; stroke-dasharray: 1; stroke-dashoffset: 0; }
.tr-surv { stroke-width: 1.5; }
.tr-dotted { fill: none; stroke: var(--rule); stroke-width: 1; opacity: 1; }

/* THE SET-DOWN. You cannot transition border-style, and you cannot reliably
   interpolate stroke-dasharray: none → 2 3. So every branch that can be
   ruled out is authored as TWO coincident paths, and the set-down is an
   opacity cross-fade between them — composited, cheap and exact.
   Do not attempt it any other way. */
.tr-ruled { opacity: 0; }          /* at rest the branch is already set down */
.tr-lbl-ruled { fill: var(--grey-600); }

/* ARMED — un-draw. No transitions here, or the un-draw animates backwards. */
.trace.is-armed .tr-mark { stroke-dashoffset: 1; transition: none; }
.trace.is-armed .tr-surv { stroke-width: 1; }
.trace.is-armed .tr-ruled { opacity: 1; }
.trace.is-armed .tr-dotted { opacity: 0; }
.trace.is-armed .tr-lbl-ruled { fill: var(--ink); }
.trace.is-armed .tr-lbl,
.trace.is-armed .fade-d,
.trace.is-armed .fade-u { opacity: 0; transition: none; }

/* DRAWN — replay. Order matters: .tr-surv and .tr-ruled must follow
   .tr-mark, they carry equal specificity and override by source order. */
.trace.is-armed.is-drawn .tr-mark {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 200ms linear var(--d, 0ms);
}
.trace.is-armed.is-drawn .tr-surv {
  stroke-width: 1.5;
  transition: stroke-dashoffset 200ms linear var(--d, 0ms),
              stroke-width 160ms ease var(--d2, 0ms);
}
.trace.is-armed.is-drawn .tr-ruled {
  opacity: 0;
  transition: stroke-dashoffset 200ms linear var(--d, 0ms),
              opacity 160ms ease var(--d2, 0ms);
}
.trace.is-armed.is-drawn .tr-dotted {
  opacity: 1;
  transition: opacity 160ms ease var(--d2, 0ms);
}
/* Child labels are already present in ink at the fork — they never fade in.
   0ms duration, delayed: present, not animated. */
.trace.is-armed.is-drawn .tr-lbl {
  opacity: 1;
  transition: opacity 0ms linear var(--d, 0ms);
}
.trace.is-armed.is-drawn .tr-lbl-ruled {
  fill: var(--grey-600);
  transition: opacity 0ms linear var(--d, 0ms),
              fill 160ms ease var(--d2, 0ms);
}
.trace.is-armed.is-drawn .fade-d { opacity: 1; transition: opacity 160ms ease var(--d, 0ms); }
.trace.is-armed.is-drawn .fade-u { opacity: 1; transition: opacity 160ms ease var(--d2, 0ms); }

/* Delay classes. Strict CSP forbids inline style attributes, so per-node
   delays are numbered utility classes. Never write delays into markup.
     .tN → --d  (draw)      .uN → --d2 (set-down)
   Beats: stem 0 · hold 200–400 · Q 400 · fork 560 · set-down 780 · … ·
   root 2000 · payoff 2200. Total 2.2s. Runs once. No loop, no replay. */
.t0  { --d: 0ms; }     .u0  { --d2: 0ms; }
.t1  { --d: 200ms; }   .u1  { --d2: 200ms; }
.t2  { --d: 400ms; }   .u2  { --d2: 400ms; }
.t3  { --d: 560ms; }   .u3  { --d2: 560ms; }
.t4  { --d: 780ms; }   .u4  { --d2: 780ms; }
.t5  { --d: 940ms; }   .u5  { --d2: 940ms; }
.t6  { --d: 1100ms; }  .u6  { --d2: 1100ms; }
.t7  { --d: 1300ms; }  .u7  { --d2: 1300ms; }
.t8  { --d: 1460ms; }  .u8  { --d2: 1460ms; }
.t9  { --d: 1620ms; }  .u9  { --d2: 1620ms; }
.t10 { --d: 1820ms; }  .u10 { --d2: 1820ms; }
.t11 { --d: 1980ms; }  .u11 { --d2: 1980ms; }
.t12 { --d: 2000ms; }  .u12 { --d2: 2000ms; }
.t13 { --d: 2100ms; }  .u13 { --d2: 2100ms; }
.t14 { --d: 2200ms; }  .u14 { --d2: 2200ms; }

/* ── §01 The Standard ────────────────────────────────────────────────── */
.standard-q {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.5rem, 1rem + 2vw, 2.25rem);
  line-height: 1.22; letter-spacing: -0.022em; color: var(--ink);
  max-width: 24ch; padding-left: 24px; border-left: 1px solid var(--navy);
}

/* ── §04 The register ────────────────────────────────────────────────── */
.register { background: var(--bone); padding: 72px 0; }
.reg-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: var(--gutter); margin-top: 48px; }
.reg-item .reg-num {
  display: block;
  font-family: var(--display); font-weight: 300;
  font-size: clamp(2.25rem, 4.4vw, 3.75rem);
  line-height: 1; letter-spacing: -0.02em; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.reg-item .rule-mark { margin: 16px 0 14px; }
.reg-item .reg-key { font-size: 0.9375rem; color: var(--graphite); line-height: 1.45; }

/* ── §03 The one span ────────────────────────────────────────────────
   Every consulting site ships five separated capability cards, and the
   gaps between those cards are literally where the firm ends and a vendor
   begins. This is one 100%-wide bar, five segments, 1px navy seams, zero
   gaps. The total is invariant and the seams never open BY CONSTRUCTION
   rather than by transition — a stronger version of the same argument.
   Interaction is a proper APG tablist: click and arrow keys, never hover. */
.span-bar { display: flex; width: 100%; border: 1px solid var(--navy); background: var(--bone); }
.span-tab {
  flex: 1 1 0; min-width: 0;
  padding: 20px 18px; text-align: left;
  border: 0; border-left: 1px solid var(--navy);
  font-family: var(--sans); font-size: 0.6875rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.12em;
  color: var(--grey-600);
  transition: color 160ms ease, background-color 160ms ease;
}
.span-tab:first-child { border-left: 0; }
.span-tab .span-num { display: block; color: var(--rule); margin-bottom: 8px; }
.span-tab:hover { color: var(--ink); }
.span-tab[aria-selected='true'] { color: #FFFFFF; background: var(--ink); }
.span-tab[aria-selected='true'] .span-num { color: var(--rule); }
.span-panel { padding-top: 40px; }
.span-panel[hidden] { display: none; }
.span-panel .h3 { margin-bottom: 16px; }
.span-note { margin-top: 40px; }

/* Capability entries on /capabilities — the refusals are the credibility. */
.cap-def { display: grid; grid-template-columns: 120px 1fr; gap: 24px; }
.cap-def + .cap-def { margin-top: 28px; }
.cap-def dt {
  font-family: var(--sans); font-size: 0.6875rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.14em; color: var(--grey-600);
  padding-top: 4px;
}
.cap-def dd { max-width: 62ch; }

/* ── §05 The terms. No motion whatsoever. On a page where everything else
      is measured and converging, stillness reads as the firm not selling.
      That is a consultant's instinct, and it is the section a partner reads
      twice. Do not add a reveal here. ───────────────────────────────── */
.terms { }

/* ── Specification table (/technology) ───────────────────────────────── */
.spec-table { width: 100%; border-collapse: collapse; margin-top: 32px; max-width: 720px; }
.spec-table th, .spec-table td {
  text-align: left; padding: 14px 0; border-bottom: 1px solid var(--rule);
  font-family: var(--sans); font-size: 0.8125rem; font-weight: 400;
  color: var(--graphite);
}
.spec-table th {
  font-weight: 500; font-size: 0.6875rem; text-transform: uppercase;
  letter-spacing: 0.14em; color: var(--grey-600); width: 220px;
}
.spec-table td { color: var(--ink); }

/* ── Platform roster ─────────────────────────────────────────────────── */
.roster { border-top: 1px solid var(--rule); margin-top: 40px; }
.roster-item {
  display: grid; grid-template-columns: 200px 1fr;
  gap: 24px; padding: 22px 0; border-bottom: 1px solid var(--rule);
  align-items: baseline;
}
.roster-item:hover { border-bottom-color: var(--navy); }
.roster-name { color: var(--ink); font-size: 1.0625rem; }
.roster-desc { color: var(--graphite); max-width: 62ch; }

/* ── Services: "what we do" at-a-glance grid ──────────────────────────
   The plain-language answer to "do you make websites / do SEO / run ads?".
   Concrete service names, scannable, above the interpretive detail. */
.svc-glance { padding-top: 72px; padding-bottom: 72px; }
.svc-grid {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 48px 56px;
}
.svc-group-name {
  display: block;
  font-family: var(--sans); font-size: 0.75rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.14em; color: var(--ink);
  padding-bottom: 14px; border-bottom: 1px solid var(--navy);
}
.svc-group-name:hover { color: var(--navy-active); }
.svc-group-num { color: var(--rule); margin-right: 10px; }
.svc-list { list-style: none; margin-top: 4px; }
.svc-list li {
  padding: 11px 0; border-bottom: 1px solid var(--rule);
  font-size: 0.9688rem; color: var(--graphite); line-height: 1.35;
}

/* The same concrete services, leading each detailed section as bordered
   chips — so the plain answer sits above the interpretive prose there too. */
.svc-inline {
  display: flex; flex-wrap: wrap; gap: 8px;
  list-style: none; margin: 4px 0 32px;
}
.svc-inline li {
  border: 1px solid var(--rule); padding: 8px 13px;
  font-size: 0.8125rem; color: var(--ink); line-height: 1.2;
}

/* ── Form. Hairline underlines, labels above the fields.
      Never placeholder-as-label. ──────────────────────────────────────── */
.form { max-width: 640px; margin-top: 40px; }
.field + .field { margin-top: 32px; }
.field label {
  display: block;
  font-family: var(--sans); font-size: 0.6875rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.14em; color: var(--grey-600);
  margin-bottom: 10px;
}
.field input, .field textarea {
  width: 100%; font: inherit; color: var(--ink);
  background: none; border: 0; border-bottom: 1px solid var(--rule);
  padding: 8px 0; border-radius: 0;
  transition: border-color 160ms ease;
}
.field textarea { resize: vertical; min-height: 140px; }
.field input:hover, .field textarea:hover { border-bottom-color: var(--grey-600); }
.field input:focus, .field textarea:focus {
  border-bottom-color: var(--navy); box-shadow: none; outline: none;
}
.field input:focus-visible, .field textarea:focus-visible {
  box-shadow: 0 0 0 2px var(--navy-active); outline-offset: 2px;
}
.form .btn { margin-top: 40px; }
.form-note { margin-top: 20px; color: var(--grey-600); font-size: 0.9375rem; }
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.form-msg { padding: 16px 20px; border: 1px solid var(--rule); border-left: 2px solid var(--navy); margin-bottom: 32px; }
.form-msg.is-error { border-left-color: var(--ink); }

/* ── Footer. The one dark plate. It means the document is closed. ─────── */
.footer { background: var(--ink); color: #FFFFFF; padding: 72px 0 40px; margin-top: 0; }
.footer a { color: #FFFFFF; }
.footer-grid { display: grid; grid-template-columns: 2fr 1fr 1fr; gap: 48px; }
.footer-mark { line-height: 0; }
.footer-mark img { height: 24px; width: auto; display: block; }
.footer-div { margin-top: 20px; color: rgba(255, 255, 255, 0.6); font-size: 0.9375rem; max-width: 44ch; }
/* Footer column labels are <h2 class="foot-h"> — real headings so the
   footer landmark is navigable, kept at h2 so no page skips a level
   (inner pages end on an h2; the home page's h3s can always step back up). */
.footer .foot-h {
  font-family: var(--sans); font-size: 0.6875rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.14em;
  color: rgba(255, 255, 255, 0.6); margin-bottom: 18px;
}
.footer-list li { list-style: none; margin-bottom: 10px; }
.footer-list a { border-bottom: 1px solid transparent; padding-bottom: 2px; }
.footer-list a:hover { border-bottom-color: rgba(255, 255, 255, 0.6); }
.footer-contact { list-style: none; }
.footer-contact li { margin-bottom: 10px; color: rgba(255, 255, 255, 0.6); }
.footer-contact a:hover { border-bottom: 1px solid rgba(255, 255, 255, 0.6); }
.footer-base {
  margin-top: 64px; padding-top: 24px;
  border-top: 1px solid rgba(255, 255, 255, 0.14);
  display: flex; justify-content: space-between; gap: 24px; flex-wrap: wrap;
}
.foot-meta { font-size: 0.6875rem; letter-spacing: 0.1em; color: rgba(255, 255, 255, 0.6); text-transform: uppercase; }
.footer :focus-visible { box-shadow: 0 0 0 2px #FFFFFF; }

/* ═══ Responsive ══════════════════════════════════════════════════════
   Breakpoints: 1280 max content · 1000 hero single column · 900 span
   stacks (gapless) · 760 trace switches renderer · 375 floor. */

@media (max-width: 1000px) {
  .hero-grid { grid-template-columns: 1fr; gap: 56px; }
  .hero .h1 { max-width: 18ch; }
  .col-main { grid-column: 1 / span 12; }
  .col-side { grid-column: 1 / span 12; }
  .reg-grid { grid-template-columns: repeat(2, 1fr); gap: 40px var(--gutter); }
}

@media (max-width: 900px) {
  /* The span stacks — and stays gapless. The seams become horizontal.
     The argument survives the breakpoint; that is the whole point of it
     being a bar and not five cards. */
  .span-bar { flex-direction: column; }
  .span-tab { border-left: 0; border-top: 1px solid var(--navy); }
  .span-tab:first-child { border-top: 0; }
  .span-tab .span-num { display: inline; margin-right: 10px; margin-bottom: 0; }
  .footer-grid { grid-template-columns: 1fr 1fr; }
  .roster-item { grid-template-columns: 1fr; gap: 6px; }
  .cap-def { grid-template-columns: 1fr; gap: 8px; }
  .svc-grid { grid-template-columns: repeat(2, 1fr); gap: 40px 40px; }
}

/* ── The outline renderer. A second COMPONENT, not a media query.
      Same data, same tags, same beats. No forking geometry to break, no
      label collision, no viewBox scaling. Ship both or ship neither. ──── */
@media (max-width: 760px) {
  .tr-svg { display: none; }
  .tr-outline { display: block; list-style: none; }
  .tr-o-payoff { display: block; }

  /* THE SPINE, on mobile.
     top:0/bottom:0 (not top:6px) so adjacent items' rules TOUCH and the spine
     reads as one continuous line, exactly as the SVG does. A segmented spine
     says the reasoning stopped and restarted. */
  .tr-outline li {
    position: relative; padding-left: 22px; padding-bottom: 18px;
  }
  .tr-outline li::before {
    content: ''; position: absolute; left: 0; top: 0; bottom: 0;
    width: 2px; background: var(--navy);
    transform-origin: top; transform: scaleY(1);
  }
  /* SPECIFICITY, deliberately: these overrides must be written as
     `.tr-outline .tr-o-*::before`, not `.tr-o-*::before`. The base rule above
     is `.tr-outline li::before` = (0,1,2); a bare `.tr-o-given::before` is
     (0,1,1) and LOSES, which shipped a stray navy tick beside GIVEN and a
     rule down the ROOT plate. Do not "simplify" these selectors. */
  /* These padding overrides MUST carry the .tr-outline prefix too. The base
     rule `.tr-outline li { padding: … }` is (0,1,1); a bare `.tr-o-ruled`
     is (0,1,0) and loses, so the ruled item kept the 22px indent and the
     dotted branch struck through its label. Same specificity trap the
     ::before overrides above already dodge. */
  .tr-outline .tr-o-given { padding-bottom: 24px; color: var(--ink); font-size: 1.0625rem; }
  .tr-outline .tr-o-given::before { background: none; border: 0; }
  .tr-o-tag {
    display: block; font-family: var(--sans); font-size: 0.6875rem;
    font-weight: 500; text-transform: uppercase; letter-spacing: 0.14em;
    color: var(--grey-600); margin-bottom: 8px;
  }
  .tr-outline .tr-o-q {
    font-family: var(--sans); font-size: 0.75rem; font-weight: 500;
    letter-spacing: 0.12em; color: var(--grey-600); padding-bottom: 14px;
  }
  /* THE FORK, on mobile. A ruled-out item keeps the navy spine at left:0 —
     because the trace SURVIVED this junction — and carries its own dotted
     BRANCH, indented, alongside. Putting the dotted rule in the spine's own
     position (the obvious shortcut) inverts the argument: it reads as the
     line itself being set down, when what was set down is the branch. */
  .tr-outline .tr-o-ruled { padding-left: 46px; }
  .tr-outline .tr-o-ruled::after {
    content: ''; position: absolute; left: 24px; top: 0; bottom: 18px;
    border-left: 1px dotted var(--rule);
    transform-origin: top; transform: scaleY(1);
  }
  .tr-o-ruled .tr-o-lbl { color: var(--grey-600); }
  .tr-o-ruled .tr-o-tag { display: inline-block; margin: 0 0 0 10px; }
  .tr-o-reason {
    display: block; font-family: var(--sans); font-size: 0.75rem;
    letter-spacing: 0.02em; color: var(--grey-600); margin-top: 4px;
  }
  .tr-o-live .tr-o-lbl { color: var(--ink); font-size: 1.0625rem; }
  .tr-outline .tr-o-root { color: #FFFFFF; background: var(--ink); padding: 20px; margin-top: 8px; }
  .tr-outline .tr-o-root::before { display: none; }
  .tr-o-root .tr-o-tag { color: rgba(255, 255, 255, 0.6); }
  .tr-o-payoff { font-size: 1.375rem; color: var(--ink); margin-top: 28px; }

  /* Same inversion, same beats. The spine draws on the fork beat (--d); the
     dotted branch appears on the set-down beat (--d2), matching the SVG.
     Rules draw; text never moves and never wraps mid-transition. */
  .trace.is-armed .tr-outline li::before,
  .trace.is-armed .tr-outline .tr-o-ruled::after { transform: scaleY(0); transition: none; }
  .trace.is-armed.is-drawn .tr-outline li::before {
    transform: scaleY(1);
    transition: transform 200ms linear var(--d, 0ms);
  }
  .trace.is-armed.is-drawn .tr-outline .tr-o-ruled::after {
    transform: scaleY(1);
    transition: transform 160ms linear var(--d2, 0ms);
  }
}

@media (max-width: 720px) {
  :root { --gutter: 20px; --section: 72px; }
  .hero { padding: 56px 0 var(--section); }
  .masthead .wrap { gap: 14px; }
  .nav { gap: 4px 18px; }
  .reg-grid { grid-template-columns: 1fr; gap: 36px; }
  .footer-grid { grid-template-columns: 1fr; gap: 36px; }
  .cap-def { grid-template-columns: 1fr; }
  .svc-grid { grid-template-columns: 1fr; gap: 36px; }
}

/* ── Reduced motion ──────────────────────────────────────────────────
   Belt and braces: site.js already refuses to arm anything when this is
   set, so nothing here should ever fire. It exists because a stylesheet
   that only looks right when a script ran is a stylesheet with a bug. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }
  .trace.is-armed .tr-mark { stroke-dashoffset: 0; }
  .trace.is-armed .tr-surv { stroke-width: 1.5; }
  .trace.is-armed .tr-ruled { opacity: 0; }
  .trace.is-armed .tr-dotted { opacity: 1; }
  .trace.is-armed .tr-lbl-ruled { fill: var(--grey-600); }
  .trace.is-armed .tr-lbl,
  .trace.is-armed .fade-d,
  .trace.is-armed .fade-u { opacity: 1; }
  .trace.is-armed .tr-outline li::before { transform: scaleY(1); }
  .rule-mark.is-armed { transform: scaleX(1); }
}

/* ── Print ───────────────────────────────────────────────────────────── */
@media print {
  .masthead, .footer, .btn-row { display: none; }
  body { color: #000; }
  .trace { break-inside: avoid; }
}
