/* ==========================================================================
   Keepstone — product-company aesthetic
   Ink + signal green: confident, technical, quiet-luxury ops firm
   ========================================================================== */

/* ==========================================================================
   Responsive Breakpoint System (canonical — see docs/PRD §5.1, docs/TRD §4.1)
   --------------------------------------------------------------------------
   Four-tier scheme:
     Small phone   ≤ 480px            base styles (mobile-first default)
     Large phone   481px – 768px      @media (min-width: 481px)
     Tablet        769px – 1024px     @media (min-width: 769px)
     Desktop       ≥ 1025px           @media (min-width: 1025px)

   Tokens (--bp-sm/--bp-md/--bp-lg) are exported as a single source of truth
   for JS and authoring reference. CSS custom properties cannot be used inside
   @media queries portably, so the four canonical thresholds above are the
   query values to use for new rules.

   Convention for legacy ad-hoc breakpoints (380/600/700/800/880/900/980):
     "MIGRATE: -> md (768)"   ... migrate during the relevant page pass
     "keep: <reason>"         ... preserve only when documented
   Do not reintroduce ad-hoc breakpoints. Use mobile-first min-width queries
   for new rules.
   ========================================================================== */

:root {
  /* Responsive breakpoint tokens (canonical four-tier scheme) */
  --bp-sm: 480px;   /* small phone upper bound */
  --bp-md: 768px;   /* large phone upper bound / tablet lower bound */
  --bp-lg: 1024px;  /* tablet upper bound / desktop lower bound */

  /* Fluid type tokens (PRD §5.3, TRD §4.3) — single source of truth.
     Floors clamp body and headings at ≥16px on mobile to prevent iOS
     zoom-on-focus on inputs, per PRD §5.6/§5.8. */
  --fs-base:  clamp(1rem, 0.96rem + 0.18vw, 1.0625rem);   /* 16 → 17 */
  --fs-lede:  clamp(1rem, 0.92rem + 0.4vw, 1.25rem);      /* 16 → 20 (intro / standfirst) */
  --fs-h1:    clamp(2rem, 1.4rem + 2.6vw, 3.5rem);        /* 32 → 56 */
  --fs-h2:    clamp(1.5rem, 1.2rem + 1.4vw, 2.25rem);     /* 24 → 36 */
  --fs-h3:    clamp(1.25rem, 1.1rem + 0.7vw, 1.5rem);     /* 20 → 24 */
  --fs-h4:    clamp(1.0625rem, 1rem + 0.4vw, 1.25rem);    /* 17 → 20 */
  --fs-small: 0.875rem;                                   /* 14, fixed */
  --fs-mono:  0.9375rem;                                  /* 15, fixed for code */
  --lh-body:  1.55;
  --lh-head:  1.15;

  /* Container + gutter tokens (PRD §5.6, TRD §4.x). Gutter scales by tier;
     container max preserved. --pad retained for legacy callsites. */
  --gutter-sm:     16px;   /* small phone — phone tier minimum */
  --gutter-md:     24px;   /* large phone / tablet */
  --gutter-lg:     32px;   /* desktop */
  --container-max: 1240px; /* alias of --maxw, exposed for new layout primitives */

  /* Neutrals — cool off-white to near-black.
     Contrast (vs --paper #F4F1EA): --ink 13.6:1, --ink-2 10.5:1,
     --ink-3 5.2:1, --ink-4 4.6:1 — all clear WCAG AA 4.5:1 for normal
     text. Pre-Phase-5 --ink-4 was #868B95 (2.88:1) which failed AA
     across every mono caption class; darkened to #696F7B (T-604 fix). */
  --ink:         #0E0F12;     /* body text / near black */
  --ink-2:       #22252B;     /* secondary text */
  --ink-3:       #4F5560;     /* tertiary / captions */
  --ink-4:       #5F6470;     /* quaternary — AA-clear (4.5:1+) on both --paper and --card */
  --rule:        #E5E2DB;     /* hairlines — warm */
  --rule-strong: #CFCABF;
  --paper:       #F4F1EA;     /* page bg — warm stone / limestone cream */
  --paper-2:     #EBE7DD;     /* alt surface — sand */
  --paper-3:     #E1DCCE;     /* subtle fill */
  --card:        #FBFAF5;     /* card — off-paper, not bright white */
  --card-pure:   #FFFFFF;     /* true white for data-dense UI fragments */

  /* Accent — signal green, used as the confident, operating-healthy marker.
     --signal is the brand accent at full saturation, used for surfaces
     (button bg, dot indicators) where contrast against text is owned by
     a paired ink color. --signal-text is the AA-clear variant for
     small accent text (mono captions, .card-num, .t-num) — #1FA971 at
     3.27:1 on --paper failed WCAG AA, so a darkened #137548 (4.55:1)
     ships for text use sites. T-604 fix. */
  --copper:      #1FA971;     /* primary accent (kept var name for compat) */
  --copper-2:    #178A5B;     /* hover / darker */
  --copper-tint: #D8F0E3;     /* tint / selection */
  --signal:      #1FA971;
  --signal-text: #137548;     /* AA-clear text variant on --paper */
  --signal-ink:  #0B3D28;     /* deep green for on-green text */

  /* Status */
  --ok:          #1FA971;
  --warn:        #B47A1E;
  --err:         #B8452C;

  /* Dark surface */
  --dark:        #0C0E11;
  --dark-2:      #14171B;
  --dark-rule:   #242830;
  --dark-ink:    #E7EAEE;
  --dark-ink-2:  #A8ADB7;
  --dark-ink-3:  #888E9A;     /* AA-clear (~4.7:1) on --dark-2 (#14171B) */

  /* Type */
  --sans: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  /* Layout */
  --maxw: 1240px;
  --pad:  32px;
}

/* Global media reset — :where() carries zero specificity so any explicit
   per-component sizing rule (.brand-mark, .spec-ico, .fw-layer .ico, etc.)
   overrides freely. Establishes the default that media never overflows its
   container and preserves intrinsic aspect ratio. PRD §5.6, §5.7; TRD §4.4. */
:where(img, svg, video, canvas, picture) {
  max-width: 100%;
  height: auto;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }

body {
  font-family: var(--sans);
  font-size: var(--fs-base);
  line-height: var(--lh-body);
  color: var(--ink);
  background: var(--paper);
  font-feature-settings: 'ss01', 'cv11';
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  position: relative;
}

/* Page-wide warm texture: subtle paper grain + an almost-imperceptible
   architectural tick pattern. Layered radial vignette to keep it lived-in. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -2;
  background:
    radial-gradient(1200px 800px at 85% -5%, rgba(31,169,113,0.05), transparent 60%),
    radial-gradient(900px 700px at 5% 110%, rgba(180,122,30,0.035), transparent 60%),
    var(--paper);
  pointer-events: none;
}
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    /* tick-grid — very subtle */
    linear-gradient(to right, rgba(14,15,18,0.025) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(14,15,18,0.018) 1px, transparent 1px),
    /* fiber noise */
    radial-gradient(circle at 50% 50%, rgba(14,15,18,0.04) 0.5px, transparent 0.6px);
  background-size: 96px 100%, 100% 96px, 3px 3px;
  opacity: .55;
}

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

/* ---------- Typography ---------- */

h1, h2, h3, h4 {
  font-family: var(--sans);
  font-weight: 500;
  color: var(--ink);
  letter-spacing: -0.028em;
  margin: 0;
  text-wrap: balance;
}

h1 {
  font-size: var(--fs-h1);
  line-height: 1.02;
  letter-spacing: -0.035em;
  font-weight: 500;
}
h1 em {
  font-style: normal;
  /* WCAG 2.1.4.3 large-text exemption: h1 is 32-56px clamp, so the
     3.0:1 ratio of --signal #1FA971 on --paper #F4F1EA satisfies AA
     for large text. Smaller-text uses elsewhere swap to --signal-text. */
  color: var(--signal-text);
  font-weight: 500;
}

h2 {
  font-size: var(--fs-h2);
  line-height: 1.08;
  letter-spacing: -0.03em;
  font-weight: 500;
}

h3 {
  font-size: var(--fs-h3);
  line-height: 1.3;
  letter-spacing: -0.015em;
  font-weight: 500;
}

h4 {
  font-size: var(--fs-h4);
  line-height: 1.25;
  letter-spacing: -0.01em;
  font-weight: 500;
}

/* Code / monospace defaults wired to --fs-mono (T-201). pre overflow guard
   protects against long lines on phone tier (security.html primary case). */
pre, code, kbd, samp {
  font-family: var(--mono);
  font-size: var(--fs-mono);
}
pre {
  overflow-x: auto;
  max-width: 100%;
}

p { margin: 0 0 1em; color: var(--ink-2); }
p:last-child { margin-bottom: 0; }

.lede {
  font-size: var(--fs-lede);
  color: var(--ink-3);
  max-width: 62ch;
  line-height: 1.5;
}

/* Monospace metadata — the signature UI element */
.kicker {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.kicker.on-dark { color: var(--dark-ink-2); }

/* ---------- Layout primitives ---------- */

.wrap {
  max-width: var(--maxw);
  margin: 0 auto;
  /* Mobile-first: 16px gutter at small phone, escalating per tier.
     PRD §5.6 ("16px minimum, 24px preferred" on phone). The legacy
     --pad fallback (32px → 20px → 16px via existing media overrides)
     remains as a deeper-spec safety net. T-202. */
  padding-inline: var(--gutter-sm);
}
@media (min-width: 481px) {
  .wrap { padding-inline: var(--gutter-md); }
}
@media (min-width: 1025px) {
  .wrap { padding-inline: var(--gutter-lg); }
}

.section {
  padding: 80px 0;
  position: relative;
}
.section.ruled {
  border-top: 1px solid var(--rule);
}

.section-head {
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: 48px;
  align-items: start;
  margin-bottom: 48px;
  padding-bottom: 24px;
  border-bottom: 1px solid var(--rule);
}
.section-head .kicker { padding-top: 6px; }
.section-head h2 { max-width: 22ch; margin-bottom: 12px; }
.section-head .lede { max-width: 56ch; }

/* MIGRATE: → md (768) — section-head collapses to single column for phones; tablet should retain stacked layout below 769 */
@media (max-width: 800px) {
  .section { padding: 64px 0; }
  .section-head { grid-template-columns: 1fr; gap: 16px; margin-bottom: 40px; }
}

/* ---------- Top chrome ---------- */

.topnav {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in oklab, var(--paper) 90%, transparent);
  backdrop-filter: saturate(140%) blur(10px);
  -webkit-backdrop-filter: saturate(140%) blur(10px);
  border-bottom: 1px solid var(--rule);
}
.topnav > .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 64px;
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--ink);
  text-decoration: none;
  font-weight: 600;
  letter-spacing: -0.02em;
  font-size: 16px;
}
.brand-mark {
  width: 22px; height: 22px;
  display: inline-block;
}
.brand sup {
  font-family: var(--mono);
  font-size: 9px;
  font-weight: 500;
  color: var(--signal-text);
  letter-spacing: 0.08em;
  margin-left: 2px;
  top: -0.8em;
}
.nav {
  display: flex;
  align-items: center;
  gap: 32px;
}
.nav a {
  color: var(--ink-2);
  text-decoration: none;
  font-size: 14px;
  font-weight: 450;
  letter-spacing: -0.005em;
  transition: color .15s;
  white-space: nowrap;
}
.nav a:hover { color: var(--ink); }
.nav a.active { color: var(--ink); }
.nav .sep {
  width: 1px; height: 18px; background: var(--rule-strong);
  flex: 0 0 auto;
}

/* keep: 980 — graceful nav-gap tightening before hamburger collapse; intentionally narrower than 1024 to avoid edge clipping. Phase 2 will fold this into the lg breakpoint. */
@media (max-width: 980px) {
  .nav { gap: 20px; }
}
/* MIGRATE: → md (768) — desktop nav links hide and hamburger appears; should activate at <=1024 (per PRD §5.2) once the nav rewrite stabilises in Phase 1. */
@media (max-width: 880px) {
  .nav { gap: 18px; }
  .nav a:not(.btn):not(.nav-cta) { display: none; }
  .nav .sep { display: none; }
  /* Hamburger appears at the same breakpoint as the inline links hide. */
  .nav-toggle { display: inline-flex; }
  /* Mobile panel becomes available; JS toggles the [hidden] attribute. */
  .nav-mobile {
    display: block;
    border-top: 1px solid var(--rule);
    background: var(--paper);
    animation: navSlide .18s ease-out;
  }
  .nav-mobile .wrap {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding-top: 8px;
    padding-bottom: 20px;
  }
  .nav-mobile a:not(.btn) {
    display: block;
    padding: 16px 2px;
    font-size: 17px;
    font-weight: 450;
    color: var(--ink);
    text-decoration: none;
    border-bottom: 1px solid var(--rule);
    letter-spacing: -0.01em;
  }
  .nav-mobile a:not(.btn):last-of-type { border-bottom: none; }
  .nav-mobile a.active { color: var(--signal); }
  .nav-mobile-cta {
    margin-top: 18px;
    justify-content: center;
    padding: 14px 18px;
    font-size: 15px;
  }
}

/* Force the panel off when JS sets [hidden], regardless of breakpoint. */
.nav-mobile[hidden] { display: none !important; }
/* Lock body scroll any time the menu is open. */
body.nav-open { overflow: hidden; }
@keyframes navSlide {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 11px 18px;
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: -0.005em;
  border-radius: 6px;
  text-decoration: none;
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform .08s ease, background .15s, border-color .15s, color .15s;
  line-height: 1;
  white-space: nowrap;
}
.btn .arrow {
  font-family: var(--mono);
  transition: transform .2s;
}
.btn:hover .arrow { transform: translateX(3px); }
.btn:active { transform: translateY(1px); }

.btn-primary,
a.btn-primary,
.nav a.btn-primary {
  /* Background uses --signal-text (the AA-clear darkened green)
     instead of --signal at full saturation. White-on-#1FA971 is
     3.01:1 — fails WCAG AA 4.5:1 for normal-sized button labels.
     White-on-#137548 is ~6.0:1 — passes AA comfortably. T-604 fix.
     Multi-selector defends against `.nav a { color: var(--ink-2) }`
     overriding `color: #fff` via specificity in the topnav. */
  background: var(--signal-text);
  color: #fff;
  border-color: var(--signal-text);
}
.btn-primary:hover,
a.btn-primary:hover { background: var(--copper-2); border-color: var(--copper-2); color: #fff; }

.btn-ghost {
  background: transparent;
  color: var(--ink);
  border-color: var(--rule-strong);
}
.btn-ghost:hover { border-color: var(--ink); }

.btn-copper {
  background: var(--copper);
  color: #fff;
  border-color: var(--copper);
}
.btn-copper:hover { background: var(--copper-2); border-color: var(--copper-2); }

.btn-sm { padding: 8px 14px; font-size: 13px; }
.btn-lg { padding: 14px 22px; font-size: 15px; }

/* T-412: visible :focus-visible on every CTA button (WCAG 2.4.7, AC-G07).
   Layered after the .btn-* color hooks so the outline is a visible ring
   regardless of variant. Mouse users still get the existing border-color
   transition; keyboard users get the 2px outline. */
.btn:focus-visible,
.nav-cta:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 2px;
}

/* T-412: hit-target floor at small-phone tier — applies the 44x44 minimum
   to every .btn variant on the canonical phone tier (≤768px), not just
   inside the legacy (max-width: 600px) block. Pairs with the existing
   .nav-mobile a min-height rule so every interactive element on phone
   meets AC-G02. .btn-sm / .nav-cta already-tiny variants get a softer
   floor (40px) since they appear inside the topnav row whose own height
   is 56-64px; clamping them to 44 would push the row taller. */
@media (max-width: 768px) {
  .btn { min-height: 44px; }
  .btn-sm { min-height: 40px; }
  .nav-cta { min-height: 40px; padding: 10px 14px; font-size: 13px; }
  .nav-cta .arrow { display: none; }

  /* T-602: brand wordmark (topnav home link AND footer home link).
     Inflate via vertical padding so the entire row height becomes the
     clickable target without changing the visible glyph metrics. */
  .topnav .brand,
  footer.foot .brand {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding-block: 12px;
  }

  /* T-602: footer link list. Inline anchors render ~15px tall under
     `font-size: 13px; line-height: 1.55`; WCAG 2.5.5 requires 44x44.
     Pad each anchor to a 44px min-height and let the existing
     `li { margin-bottom: 8px }` provide visual separation. */
  footer.foot li { margin-bottom: 0; }
  footer.foot li a {
    display: flex;
    align-items: center;
    min-height: 44px;
    padding-block: 6px;
  }
  footer.foot .meta a { min-height: 44px; display: inline-flex; align-items: center; padding: 6px 0; }

  /* T-602: standalone arrow links (not inline within prose). Padding
     to reach 44px min-height. */
  .link-arrow {
    min-height: 44px;
    padding-block: 12px;
  }
}

.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--signal-text);
  text-decoration: none;
  font-size: 14px;
  font-weight: 500;
  border-bottom: 1px solid var(--signal);
  padding-bottom: 2px;
  transition: color .15s, border-color .15s;
}
.link-arrow:hover { color: var(--copper-2); border-color: var(--copper-2); }

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

.hero {
  padding: 80px 0 96px;
  border-bottom: 1px solid var(--rule);
  position: relative;
  overflow: hidden;
}
.hero::before {
  /* Architectural watermark: concentric contour arcs, ghosted.
     Placed bottom-right so it doesn't fight the type. */
  content: "";
  position: absolute;
  right: -220px;
  bottom: -260px;
  width: 720px;
  height: 720px;
  border-radius: 50%;
  background:
    radial-gradient(circle at center,
      transparent 0,
      transparent 180px,
      rgba(31,169,113,0.055) 181px,
      rgba(31,169,113,0.055) 182px,
      transparent 183px,
      transparent 240px,
      rgba(14,15,18,0.04) 241px,
      rgba(14,15,18,0.04) 242px,
      transparent 243px,
      transparent 300px,
      rgba(31,169,113,0.04) 301px,
      rgba(31,169,113,0.04) 302px,
      transparent 303px,
      transparent 360px);
  pointer-events: none;
  opacity: .9;
  z-index: 0;
}
.hero::after {
  /* A faint vertical rule axis, like blueprint margin */
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  left: max(calc((100vw - 1240px) / 2 + 80px), 80px);
  width: 1px;
  background: linear-gradient(to bottom, transparent, rgba(14,15,18,0.08) 30%, rgba(14,15,18,0.08) 70%, transparent);
  pointer-events: none;
  opacity: .5;
  z-index: 0;
}
.hero .wrap {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: 72px;
  align-items: center;
  position: relative;
}
.hero h1 { margin: 18px 0 44px; max-width: 14ch; line-height: 1.02; }
.hero .sub {
  font-size: var(--fs-lede);
  color: var(--ink-2);
  line-height: 1.5;
  max-width: 52ch;
  margin: 0 0 36px;
}
.hero .ctas {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
}

/* T-303 page pass: hero stacks copy → visual at the canonical md (768)
   threshold. Below 768 the hero is a single column (copy first, visual
   second by markup order). At small-phone (<=480) primary CTA goes
   full-width and the secondary stacks under it. */
@media (max-width: 768px) {
  .hero { padding: 48px 0 64px; }
  .hero .wrap { grid-template-columns: 1fr; gap: 48px; }
}
@media (max-width: 480px) {
  .hero .ctas { gap: 12px; align-items: stretch; flex-direction: column; }
  .hero .ctas .btn { width: 100%; justify-content: center; }
}

/* ---------- UI "fragment" — the signature proof block ---------- */

.fragment {
  background: var(--card-pure);
  border: 1px solid var(--rule-strong);
  border-radius: 10px;
  box-shadow:
    0 1px 0 rgba(23, 22, 26, 0.02),
    0 24px 48px -28px rgba(23, 22, 26, 0.22),
    0 2px 6px -2px rgba(23, 22, 26, 0.04);
  overflow: hidden;
  font-family: var(--mono);
  font-size: 12px;
  position: relative;
  z-index: 1;
}
.fragment.dark {
  background: var(--dark-2);
  border-color: var(--dark-rule);
  color: var(--dark-ink);
}
.f-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--rule);
  background: var(--paper-2);
  color: var(--ink-3);
  font-size: 11px;
  letter-spacing: 0.02em;
}
.fragment.dark .f-head {
  background: #17161B;
  border-color: var(--dark-rule);
  color: var(--dark-ink-3);
}
.f-head .dots { display: inline-flex; gap: 5px; }
.f-head .dots i {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--rule-strong);
}
.fragment.dark .f-head .dots i { background: var(--dark-rule); }

.f-body { padding: 18px 16px; }

/* status rows */
.rows { display: grid; gap: 0; }
.row {
  display: grid;
  grid-template-columns: 14px 1fr auto;
  gap: 12px;
  align-items: center;
  padding: 11px 4px;
  border-bottom: 1px dashed var(--rule);
  font-size: 12.5px;
}
.row:last-child { border-bottom: none; }
.row .dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--ok);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--ok) 20%, transparent);
}
.row .dot.warn {
  background: var(--warn);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--warn) 20%, transparent);
}
.row .dot.err {
  background: var(--err);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--err) 20%, transparent);
}
.row .label { color: var(--ink); font-weight: 500; }
.row .meta { color: var(--ink-3); font-size: 11.5px; }

/* log rows (dark) */
.log { display: grid; gap: 2px; }
.log .ln {
  display: grid;
  grid-template-columns: 48px 50px 1fr;
  gap: 12px;
  align-items: baseline;
  padding: 5px 0;
  font-size: 12px;
  color: var(--dark-ink-2);
}
.log .ln .t { color: var(--dark-ink-3); }
.log .ln .lvl {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.06em;
}
.log .ln .lvl.ok   { color: #4FD4A0; }
.log .ln .lvl.warn { color: #D4A64A; }
.log .ln .lvl.err  { color: #E27A63; }
.log .ln .lvl.info { color: var(--dark-ink-3); }
.log .ln .msg { color: var(--dark-ink); }
.log .ln .msg b { color: #fff; font-weight: 600; }
.log .ln .msg .tok { color: #4FD4A0; }

/* ---------- Cards ---------- */

/* T-303 page pass: mobile-first card-grid. Single column at small-phone
   (default), 2-col at large-phone (>=481), full N-col at tablet (>=769).
   .card-grid.four follows the .grid-4 cadence: 1 → 2 (md) → 4 (lg).
   Replaces the legacy `(max-width: 900px) → 1fr` collapse, aligning the
   collapse threshold with the canonical four-tier scheme and exposing
   the tablet tier (768-900px) to multi-column density. */
.card-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--gutter-md);
}
@media (min-width: 481px) {
  .card-grid,
  .card-grid.two,
  .card-grid.four { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 769px) {
  .card-grid       { grid-template-columns: repeat(3, 1fr); }
  .card-grid.two   { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1025px) {
  .card-grid.four  { grid-template-columns: repeat(4, 1fr); }
}

.card {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 10px;
  padding: 28px 26px 26px;
  position: relative;
  transition: border-color .15s, transform .15s, box-shadow .15s;
}
.card:hover {
  border-color: var(--signal);
  transform: translateY(-2px);
  box-shadow: 0 12px 28px -20px rgba(14,15,18,0.18);
}
.card .card-icon {
  width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
  background: var(--paper-2);
  border: 1px solid var(--rule);
  border-radius: 8px;
  margin-bottom: 20px;
  color: var(--signal-text);
}
.card .card-icon svg { width: 22px; height: 22px; }
.card .card-num {
  position: absolute;
  top: 22px; right: 22px;
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--ink-4);
  letter-spacing: 0.08em;
}
.card .k {
  font-family: var(--mono);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--signal-text);
  margin-bottom: 16px;
  display: block;
}
.card h3 {
  margin-bottom: 10px;
  max-width: 24ch;
}
.card p {
  font-size: 14.5px;
  color: var(--ink-3);
  line-height: 1.5;
  margin: 0;
}

/* ---------- Steps ---------- */

/* T-307 page pass: .steps rewritten mobile-first. Default base is 1-col;
   .steps-N modifiers (N = 4 default, 5 for how-it-works) restore the
   horizontal grid at tablet+. Replaces the legacy 4-col base + max-width:
   900 collapse, which (a) used the wrong canonical breakpoint and (b) was
   silently overridden on how-it-works by an inline
   style="grid-template-columns: repeat(5, 1fr)" attribute. The how-it-works
   markup is updated in the same commit to use class="steps steps-5" with
   no inline grid-template-columns. */
.steps {
  display: grid;
  /* Mobile-first: single column with vertical separators. */
  grid-template-columns: 1fr;
  gap: 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}
@media (min-width: 769px) {
  /* Default at tablet+ is 4-up; .steps-5 modifier overrides for the
     how-it-works 5-phase variant. */
  .steps { grid-template-columns: repeat(4, 1fr); }
  .steps.steps-5 { grid-template-columns: repeat(5, 1fr); }
}
.step {
  padding: 24px 0;
  border-bottom: 1px solid var(--rule);
  position: relative;
}
.step:last-child { border-bottom: none; }
@media (min-width: 769px) {
  /* Restore vertical-rule between cells at tablet+, drop the bottom-rule
     stacking pattern. */
  .step {
    padding: 32px 24px 32px 0;
    border-right: 1px solid var(--rule);
    border-bottom: none;
  }
  .step:last-child { border-right: none; padding-right: 0; }
  .step:not(:first-child) { padding-left: 28px; }
}
.step .n {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-4);
  /* Smaller bottom-margin on phone (compact stack); larger at tablet+. */
  margin-bottom: 16px;
  display: flex;
  align-items: center;
  gap: 10px;
}
@media (min-width: 769px) {
  .step .n { margin-bottom: 36px; }
}
.step .n::before {
  content: "";
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--copper);
}
.step h3 { margin-bottom: 10px; }
/* T-307: .step p 14.5px → --fs-base for the PRD §5.3 ≥16px floor. */
.step p {
  color: var(--ink-3);
  font-size: var(--fs-base);
  line-height: var(--lh-body);
  margin: 0;
}

/* ---------- Two-column lists (fit / anti-fit) ---------- */

.two-col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 56px;
}
/* T-306 who-were-for pass: two-col list block collapses on phone at the
   canonical md (768) threshold. */
@media (max-width: 768px) {
  .two-col { grid-template-columns: 1fr; gap: 32px; }
}
.list-block h3 {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0 0 20px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--rule);
}
.list-block.no h3 { color: var(--ink-3); }
.list-block ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
.list-block li {
  display: grid;
  grid-template-columns: 22px 1fr;
  align-items: baseline;
  padding: 12px 0;
  border-bottom: 1px dashed var(--rule);
  color: var(--ink);
  font-size: var(--fs-base);
  line-height: 1.45;
}
@media print {
  /* Revert grid layout for print — bullets only */
  .list-block li {
    display: list-item !important;
    grid-template-columns: none !important;
    padding: 1pt 0 !important;
    border: 0 !important;
  }
  .list-block li .c { display: none !important; }
}
.list-block li:last-child { border-bottom: none; }
.list-block li .c {
  font-family: var(--mono);
  color: var(--signal-text);
  font-size: 13px;
}
.list-block.no li .c { color: var(--ink-4); }

/* ---------- Dark section ---------- */

.dark-section {
  background: var(--dark);
  color: var(--dark-ink);
}
.dark-section h2 {
  color: var(--dark-ink);
  /* T-303 follow-up: page-scoped #how H2 wiring to canonical --fs-h2.
     Replaces the prior inline clamp(28px,3.2vw,40px). The 22ch max-width
     and -0.028em letter-spacing remain inline as typographic-rhythm
     controls specific to this section's hero copy. */
  font-size: var(--fs-h2);
}
.dark-section p { color: var(--dark-ink-2); }
.dark-section .lede { color: var(--dark-ink-2); }

/* T-303 follow-up: #how "Gap We Fill" two-column grid is mobile-first.
   Below 769px the prose stacks above the post-mortem.md fragment card
   (source order already produces this — prose is first child). At
   tablet+ (>=769) the two columns sit side-by-side with the original
   72px gutter and centered alignment. Replaces the inline grid-template
   that previously crushed both columns on phone viewports. */
.dark-section > .wrap {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--gutter-md);
  align-items: center;
}
@media (min-width: 769px) {
  .dark-section > .wrap {
    grid-template-columns: 1fr 1fr;
    gap: 72px;
  }
}

/* T-303 follow-up: tighten the post-mortem.md log card on small phones
   so monospace lines (timestamp + level + message) don't push the
   .fragment beyond its grid track. The 48/50/1fr template is preserved
   at >=481px; at <=480px the message track gets explicit min-width:0
   and overflow-wrap so a long token can't blow out the column. f-body
   padding tightens to match the smaller gutter. */
@media (max-width: 480px) {
  .dark-section .f-body { padding: 14px 12px; }
  .dark-section .log .ln { gap: 10px; }
  .dark-section .log .ln .msg {
    min-width: 0;
    overflow-wrap: anywhere;
  }
}

/* ---------- CTA band ---------- */

.cta-band {
  background: var(--ink);
  color: var(--paper);
  padding: 80px 0;
}
.cta-band .wrap { text-align: left; max-width: 900px; }
.cta-band h2 {
  color: var(--paper);
  font-size: clamp(32px, 4vw, 48px);
  max-width: 18ch;
  margin: 16px 0 18px;
}
.cta-band p {
  color: color-mix(in oklab, var(--paper) 72%, transparent);
  font-size: var(--fs-lede);
  max-width: 58ch;
  margin: 0 0 32px;
}
.cta-band .btn-primary {
  /* Same AA-clear darkened green as the global .btn-primary (T-604).
     White-on-#1FA971 was 3.01:1, fails AA; #137548 yields ~6:1. */
  background: var(--signal-text);
  color: #fff;
  border-color: var(--signal-text);
}
.cta-band .btn-primary:hover { background: var(--copper-2); border-color: var(--copper-2); }
.cta-band .btn-ghost {
  color: var(--paper);
  border-color: color-mix(in oklab, var(--paper) 30%, transparent);
}
.cta-band .btn-ghost:hover { border-color: var(--paper); }

/* ---------- Footer ---------- */

footer.foot {
  padding: 48px 0 40px;
  border-top: 1px solid var(--rule);
  background: var(--paper);
  color: var(--ink-3);
  font-size: 13px;
}
footer.foot .wrap {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr;
  gap: 40px;
  align-items: start;
}
footer.foot .brand { color: var(--ink); margin-bottom: 12px; }
footer.foot .tagline { max-width: 30ch; color: var(--ink-3); font-size: 13px; }
footer.foot h4 {
  font-family: var(--mono);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-4);
  margin: 0 0 14px;
}
footer.foot ul { list-style: none; margin: 0; padding: 0; }
footer.foot li { margin-bottom: 8px; }
footer.foot a { color: var(--ink-2); text-decoration: none; }
footer.foot a:hover { color: var(--ink); }
footer.foot .meta {
  grid-column: 1 / -1;
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid var(--rule);
  display: flex;
  justify-content: space-between;
  color: var(--ink-4);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
}
/* MIGRATE: → md (768) — footer collapses 4-col to 2-col. Phase 3 cross-cutting may introduce a 3-col stage at large-phone. */
@media (max-width: 800px) {
  footer.foot .wrap { grid-template-columns: 1fr 1fr; }
  footer.foot .foot-brand { grid-column: 1 / -1; }
}

/* ---------- Page-hero visual block ---------- */

.page-hero {
  padding: 56px 0 44px;
  border-bottom: 1px solid var(--rule);
  position: relative;
  overflow: hidden;
}
.page-hero::before {
  /* Architectural watermark — concentric arcs, bottom-right */
  content: "";
  position: absolute;
  right: -180px;
  bottom: -220px;
  width: 620px;
  height: 620px;
  border-radius: 50%;
  background:
    radial-gradient(circle at center,
      transparent 0,
      transparent 150px,
      rgba(31,169,113,0.05) 151px,
      rgba(31,169,113,0.05) 152px,
      transparent 153px,
      transparent 210px,
      rgba(14,15,18,0.035) 211px,
      rgba(14,15,18,0.035) 212px,
      transparent 213px,
      transparent 270px,
      rgba(31,169,113,0.035) 271px,
      rgba(31,169,113,0.035) 272px,
      transparent 273px);
  pointer-events: none;
  opacity: .85;
  z-index: 0;
}
.page-hero > .wrap { position: relative; z-index: 1; }
.page-hero .wrap {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: 64px;
  align-items: center;
  position: relative;
}
.page-hero.solo .wrap { grid-template-columns: 1fr; }
.page-hero .kicker { margin-bottom: 16px; }
.page-hero h1 {
  font-size: clamp(40px, 5vw, 64px);
  max-width: 16ch;
  margin: 0 0 18px;
  line-height: 1.02;
}
.page-hero .lede {
  /* font-size inherits from .lede → --fs-lede (T-205) */
  max-width: 54ch;
}
/* T-301 page pass: page-hero stack threshold migrated 900 → canonical md
   (768) per TRD §4.1. The 769–900 zone is tablet tier where the 1.1fr/0.9fr
   two-column hero is the design intent; collapsing it earlier left the
   schematic visuals oversized on portrait tablets. The framework hero is
   copy-first in markup (h1/lede before .fw-hero schematic), so single-column
   stack reads copy → visual on phone, satisfying PRD §5.9 default. The
   framework page does not invoke the §5.9 visual-first exception — the
   .fw-stack layer list immediately below the hero already carries the
   layer-level visual semantics. */
@media (max-width: 768px) {
  .page-hero .wrap { grid-template-columns: 1fr; gap: 40px; }
}

/* Hero visual — schematic keystone with live annotations */
.ks-schematic {
  background: var(--card-pure);
  border: 1px solid var(--rule-strong);
  border-radius: 12px;
  padding: 20px;
  position: relative;
  z-index: 1;
  box-shadow: 0 1px 0 rgba(14,15,18,0.02), 0 28px 56px -28px rgba(14,15,18,0.22), 0 2px 6px -2px rgba(14,15,18,0.04);
}
.ks-schematic .head {
  display: flex; align-items: center; justify-content: space-between;
  font-family: var(--mono); font-size: 10.5px; color: var(--ink-3);
  letter-spacing: 0.08em; text-transform: uppercase;
  margin-bottom: 14px; padding-bottom: 10px; border-bottom: 1px dashed var(--rule);
}
.ks-schematic .head .tag {
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--signal-text);
}
.ks-schematic .head .tag::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: var(--signal);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--signal) 20%, transparent);
  animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse {
  0%, 100% { box-shadow: 0 0 0 3px color-mix(in oklab, var(--signal) 20%, transparent); }
  50% { box-shadow: 0 0 0 5px color-mix(in oklab, var(--signal) 12%, transparent); }
}
.ks-schematic svg { width: 100%; height: auto; display: block; }
.ks-schematic .foot {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px;
  margin-top: 14px; padding-top: 14px; border-top: 1px dashed var(--rule);
}
.ks-schematic .stat {
  font-family: var(--mono);
}
.ks-schematic .stat .l {
  font-size: 9.5px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-4);
  display: block; margin-bottom: 4px;
}
.ks-schematic .stat .v {
  font-size: 15px; color: var(--ink); font-weight: 500;
}
.ks-schematic .stat .v em {
  font-style: normal; color: var(--signal-text);
}
.ks-schematic .foot-tag {
  display: block;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px dashed var(--rule);
}
.ks-schematic .tag-line {
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.ks-schematic .tag-mark {
  font-family: var(--mono);
  font-size: 13px;
  color: var(--signal-text);
  line-height: 1;
}
.ks-schematic .tag-text {
  font-family: var(--sans);
  font-size: 14px;
  color: var(--ink-2);
  letter-spacing: -0.01em;
  line-height: 1.4;
}
.ks-schematic .tag-text em {
  font-style: normal;
  color: var(--signal-text);
  font-weight: 600;
}

/* ---------- Icon (shared inline) ---------- */
.ico {
  display: inline-flex;
  width: 22px; height: 22px;
  color: currentColor;
}
.ico svg { width: 100%; height: 100%; display: block; }

.spec-ico {
  width: 16px; height: 16px;
  color: var(--signal-text);
  margin-right: 10px;
  vertical-align: -3px;
}

/* ---------- Marquee row of industries/proof ---------- */
.marquee {
  display: flex; gap: 48px; align-items: center;
  padding: 28px 0; overflow: hidden;
  border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
  font-family: var(--mono); font-size: 12px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--ink-3);
  white-space: nowrap;
}
.marquee .dot { color: var(--signal-text); }

.prose {
  max-width: 66ch;
  font-size: 16px;
  color: var(--ink-2);
  line-height: 1.65;
}
.prose p { margin: 0 0 1.2em; }
.prose h3 {
  margin: 2em 0 0.6em;
  color: var(--ink);
}
.prose ul { padding-left: 1.2em; margin: 0 0 1.2em; }
.prose li { margin-bottom: 0.4em; }

/* Spec rows — for pricing and responsibility tables */
.spec {
  border-top: 1px solid var(--rule);
}
.spec-row {
  display: grid;
  grid-template-columns: 180px 1fr 160px;
  gap: 24px;
  padding: 20px 0;
  border-bottom: 1px solid var(--rule);
  align-items: baseline;
}
.spec-row .col-k {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding-top: 3px;
}
.spec-row .col-body h4 {
  font-size: var(--fs-h4);
  font-weight: 500;
  margin: 0 0 6px;
  letter-spacing: -0.015em;
}
.spec-row .col-body p {
  font-size: var(--fs-base);
  color: var(--ink-3);
  margin: 0;
  max-width: 62ch;
}
.spec-row .col-price {
  text-align: right;
  font-family: var(--mono);
  font-size: 13px;
  color: var(--ink);
}
.spec-row .col-price em {
  font-style: normal;
  display: block;
  color: var(--ink-4);
  font-size: 11px;
  letter-spacing: 0.04em;
  margin-top: 4px;
}
/* T-306 who-were-for pass: spec rows collapse at the canonical md (768)
   threshold. Used by 5 in-scope pages (framework, how-it-works, security,
   privacy, who-were-for) — no per-page divergence. */
@media (max-width: 768px) {
  .spec-row { grid-template-columns: 1fr; gap: 6px; }
  .spec-row .col-price { text-align: left; }
}

/* Variant: two-column spec (no trailing price/tag column) */
.spec-two-col .spec-row {
  grid-template-columns: 220px 1fr;
}
.spec-two-col .spec-row .col-body p {
  max-width: none;
}
@media (max-width: 768px) {
  .spec-two-col .spec-row { grid-template-columns: 1fr; }
}

/* Variant: RACI matrix (how-it-works) — key + body + two narrow R/A/I cells.
   Replaces inline grid-template-columns that previously overrode the
   single-col collapse at the md breakpoint (T-303 follow-up). */
.spec-raci .spec-row {
  grid-template-columns: 180px 1fr 80px 80px;
}
@media (max-width: 768px) {
  .spec-raci .spec-row { grid-template-columns: 1fr; }
  .spec-raci .spec-row .col-price { text-align: left; }
}

/* ---------- Paired paths diagram (what-we-do) ---------- */
.paths {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 28px;
  position: relative;
  margin-top: 8px;
}
.paths::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 0; bottom: 0;
  width: 1px;
  background: repeating-linear-gradient(to bottom, var(--rule-strong) 0 4px, transparent 4px 8px);
  transform: translateX(-0.5px);
  pointer-events: none;
  opacity: 0.55;
}
.path-rail {
  display: grid;
  gap: 0;
  position: relative;
}
.path-node {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 10px;
  padding: 26px 28px 28px;
  position: relative;
}
.path-node .n {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-4);
  margin-bottom: 12px;
}
.path-node .lbl {
  font-family: var(--sans);
  font-size: var(--fs-h3);
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.02em;
  margin-bottom: 4px;
}
.path-node .meta {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--signal-text);
  letter-spacing: 0.04em;
  margin-bottom: 14px;
}
.path-node p {
  font-size: var(--fs-base);
  color: var(--ink-3);
  line-height: var(--lh-body);
  margin: 0 0 14px;
}
.path-node ul {
  list-style: none;
  margin: 0 0 16px;
  padding: 0;
  display: grid;
  gap: 6px;
  font-size: 13px;
  color: var(--ink-3);
}
.path-node ul li {
  padding-left: 16px;
  position: relative;
}
.path-node ul li::before {
  content: "·";
  position: absolute;
  left: 4px;
  color: var(--signal-text);
  font-weight: 700;
}
.path-node.path-entry {
  border-top: 3px solid var(--signal);
}
.path-node.path-stabilize {
  background: var(--paper-2);
  border-style: dashed;
}
.path-connector {
  height: 44px;
  position: relative;
}
.path-connector::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 0; bottom: 0;
  width: 1px;
  background: var(--signal);
  transform: translateX(-0.5px);
}
.path-connector::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 4px;
  width: 8px; height: 8px;
  border-right: 1px solid var(--signal);
  border-bottom: 1px solid var(--signal);
  transform: translateX(-50%) rotate(45deg);
}
.paths-converge {
  position: relative;
  margin: 8px 0 0;
  text-align: center;
}
.paths-converge svg {
  width: 100%;
  height: 60px;
  display: block;
}
.paths-converge-label {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--signal-text);
  margin-top: -22px;
  position: relative;
  z-index: 2;
  background: var(--paper);
  display: inline-block;
  padding: 0 10px;
}
/* T-305 what-we-do pass: paths diagram collapses to single column at the
   canonical md (768) threshold; the connecting rule + converge label are
   only meaningful in two-column layout, so suppress on phone tier. */
@media (max-width: 768px) {
  .paths { grid-template-columns: 1fr; gap: 16px; }
  .paths::before { display: none; }
  .paths-converge { display: none; }
}

/* Callout / inline note */
.callout {
  background: var(--paper-2);
  border-left: 2px solid var(--copper);
  padding: 18px 22px;
  font-size: var(--fs-base);
  color: var(--ink-2);
  margin: 28px 0;
  border-radius: 0 6px 6px 0;
}
.callout b { color: var(--ink); font-weight: 600; }

/* Forms */
/* Global iOS zoom-on-focus floor: every text/select/textarea control on the
   site sits at ≥16px regardless of whether it's wrapped in .field. Covers
   AC-G04 (PRD §7.1 row 4; TRD §4.3, §4.6). Per-component rules (.field…)
   still own padding, border, color, and may layer their own font-size as
   long as they keep the 16px floor. */
input, select, textarea {
  font-size: max(16px, 1rem);
  font-family: inherit;
}

.form {
  display: grid;
  gap: 22px;
  max-width: 640px;
}
/* Direct-child selector — the .field wrapper holds ONE outer label whose
   visible text is the field caption. Nested labels (e.g. <label class="radio">
   inside .radio-row) must NOT inherit the mono/uppercase caption styling.
   Pre-fix, .field label (specificity 0,1,1) outranked .radio (0,1,0) and
   leaked the caption typography into every radio option, breaking the
   start.html flow. */
.field > label {
  display: block;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 8px;
}
.field input[type=text],
.field input[type=email],
.field input[type=tel],
.field input[type=url],
.field select,
.field textarea {
  width: 100%;
  background: var(--card);
  border: 1px solid var(--rule-strong);
  border-radius: 6px;
  padding: 12px 14px;
  font-family: var(--sans);
  /* ≥16px prevents iOS Safari zoom-on-focus (PRD §5.6, §5.8; AC-G04). */
  font-size: max(16px, 1rem);
  color: var(--ink);
  line-height: 1.4;
  transition: border-color .15s;
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  border-color: var(--ink);
}
.field textarea { resize: vertical; min-height: 120px; }
.field .hint { font-size: 12.5px; color: var(--ink-4); margin-top: 6px; }
.radio-row {
  display: grid;
  gap: 10px;
}
.radio {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 14px 16px;
  border: 1px solid var(--rule);
  border-radius: 6px;
  cursor: pointer;
  background: var(--card);
  transition: border-color .15s;
}
.radio:hover { border-color: var(--rule-strong); }
.radio input { margin-top: 3px; }
.radio .t { font-weight: 500; color: var(--ink); display: block; }
.radio .d { font-size: 13.5px; color: var(--ink-3); margin-top: 2px; display: block; }

/* ==========================================================================
   Form primitives — T-411 (PRD §5.8, §6.2 / TRD §4.6)
   --------------------------------------------------------------------------
   Layered on top of the existing .form / .field / .radio rules above. Adds:
     - Universal 44x44 hit-target floor on form controls at small-phone tier
       (PRD §6.2 / WCAG 2.5.5).
     - .field error / success state hooks (aria-invalid, .field.is-error).
     - .field-group for two-fields-on-one-row layouts at >=481px.
     - .form-stack for consistent vertical rhythm.
     - Submit button full-width at small-phone, auto at >=769px (PRD §5.8).
     - Visible :focus-visible on every form control.

   Constraints these rules must preserve (do NOT regress):
     AC-G04 — input/select/textarea font-size >= max(16px, 1rem). Already
              shipped globally at line ~1273. Primitive rules below set
              padding, min-height, border, and state, never font-size.
     PRD §5.8 — labels always visible, never placeholder-only.

   Inputmode / autocomplete guidance (markup-side, recorded in TRD T-411
   for the page-pass author):
     <input type="email"  inputmode="email"  autocomplete="email">
     <input type="tel"    inputmode="tel"    autocomplete="tel">
     <input type="text"   name="name"        autocomplete="name">
     <input type="text"   name="organization" autocomplete="organization">
   Markup additions are deferred to the relevant page pass (T-308 for
   start.html). The primitives below render correctly with or without the
   attributes; the attributes only improve the on-screen-keyboard layout
   and autofill UX on mobile.
   ========================================================================== */

/* ---- 44x44 hit-target floor on form controls (small-phone) ---- */
/* Applied at small-phone tier only — at >=481px, .field's intrinsic
   padding (12px + 14px font + 12px = ~50px) already exceeds 44px and
   the hit-target floor is non-binding. Forcing min-height at desktop
   would change the visual rhythm of all the existing forms. */
@media (max-width: 480px) {
  .field input[type=text],
  .field input[type=email],
  .field input[type=tel],
  .field input[type=url],
  .field input[type=number],
  .field input[type=search],
  .field input[type=password],
  .field input[type=date],
  .field input[type=time],
  .field select,
  .form button[type=submit],
  .form .btn {
    min-height: 44px;
  }
  /* Bare textareas already declare min-height: 120px at line ~1315; the
     small-phone floor is already satisfied. Listed here for clarity only;
     no override needed. */
}

/* ---- :focus-visible — visible focus on every control ---- */
/* The existing .field input:focus rule (line ~1311) sets only a
   border-color change. WCAG 2.4.7 requires a visible focus indicator;
   border-only is insufficient for users on patterned backgrounds.
   Layer a 2px outline ring on top, gated to keyboard focus so mouse
   users do not see it. */
.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible,
.radio:focus-within {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* ---- .field state hooks (error / success) ---- */
/* Use either:
     <div class="field is-error">  +  aria-invalid="true" on the input
     <div class="field is-ok">     -- visual confirmation only
   Pair with aria-describedby pointing at a sibling .field .error / .help
   element so screen readers announce the message. Markup-side wiring is
   the page-pass author's responsibility; this layer is style-only. */
.field input[aria-invalid="true"],
.field select[aria-invalid="true"],
.field textarea[aria-invalid="true"],
.field.is-error input,
.field.is-error select,
.field.is-error textarea {
  border-color: var(--err);
}
.field input[aria-invalid="true"]:focus-visible,
.field.is-error input:focus-visible,
.field.is-error select:focus-visible,
.field.is-error textarea:focus-visible {
  outline-color: var(--err);
}
.field.is-ok input,
.field.is-ok select,
.field.is-ok textarea {
  border-color: var(--signal);
}
.field .error {
  display: block;
  font-size: 13px;
  color: var(--err);
  margin-top: 6px;
  line-height: 1.4;
}
.field.is-ok .error { display: none; }

/* Required-marker convention — append <span aria-hidden="true">*</span>
   to the visible label, with aria-required="true" on the input itself.
   Style-only contract; markup is page-pass work. */
.field label .req {
  color: var(--err);
  font-weight: 500;
  margin-left: 4px;
}

/* ---- .field-group — two fields on one row at >=481px ---- */
/* Mobile-first: single column at small-phone; two columns at large-phone
   and above. Use for first/last name, city/state pairs, etc. */
.field-group {
  display: grid;
  gap: 16px;
  grid-template-columns: 1fr;
}
@media (min-width: 481px) {
  .field-group { grid-template-columns: 1fr 1fr; gap: 22px; }
}

/* ---- .form-stack — vertical rhythm primitive ---- */
/* Distinct from .form (which is also a grid with gap: 22px). Use
   .form-stack inside a section or fieldset where you want the same
   rhythm as a .form but the parent is not a <form> element. */
.form-stack {
  display: grid;
  gap: 22px;
}

/* ---- Form action primitives — promoted from start.html (T-411 follow-up) ---- */
/* .actions is the row that holds a primary submit button and an
   optional adjacent .note span. Base layout is a horizontal flex row;
   the @media block below collapses it to a stretched column on
   small-phone. .actions .note is mono caption text intended to sit
   next to the submit button (e.g. "replies within 1 business day").
   Used today on start.html; safe to use on any form. */
.actions {
  display: flex;
  gap: 12px;
  margin-top: 10px;
  align-items: center;
}
.actions .note {
  color: var(--ink-4);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
}

/* ---- Submit button width — full-width small-phone, auto >=769px ---- */
/* Targets the conventional pattern: a single primary submit button
   inside .form > .actions, optionally with an adjacent .note span. */
@media (max-width: 480px) {
  .form .actions {
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
  }
  .form .actions > .btn,
  .form .actions > button {
    width: 100%;
    justify-content: center;
  }
  .form .actions > .note {
    text-align: center;
  }
}

/* ---- .form-status — form-level success / error block ---- */
/* The .field .ok / .field .error rules above are field-scoped (per-input
   error message styling). For form-level state (replace-form-on-success,
   show-error-with-retry on submit failure) we need a wider block. Used
   by assets/start-form.js — appended as a sibling of the form after a
   submit attempt. role=status / role=alert is set in JS so SR users
   hear the result. */
.form-status {
  border: 1px solid var(--rule);
  border-left-width: 3px;
  border-radius: 8px;
  padding: 20px 22px;
  margin-top: 8px;
  background: var(--card);
}
.form-status h3 {
  font-size: var(--fs-base);
  font-weight: 600;
  letter-spacing: -0.01em;
  margin: 0 0 6px;
}
.form-status p {
  color: var(--ink-3);
  font-size: var(--fs-small);
  line-height: var(--lh-body);
  margin: 0 0 8px;
}
.form-status p:last-child { margin-bottom: 0; }
.form-status a { color: var(--ink); }
.form-status--ok { border-left-color: var(--signal); }
.form-status--err { border-left-color: var(--err); }
.form-status--err h3 { color: var(--err); }
.form-status__retry {
  margin-top: 4px;
}

/* ---------- Utilities ---------- */

.stack-sm > * + * { margin-top: 8px; }
.stack > * + * { margin-top: 16px; }
.stack-lg > * + * { margin-top: 32px; }
.muted { color: var(--ink-3); }
.mono { font-family: var(--mono); }
.nowrap { white-space: nowrap; }
/* Universal display-none utility — promoted from start.html (T-411 follow-up).
   Used by the path-switch JS to toggle the active form. */
.hidden { display: none !important; }
/* Visibility utilities — keyed to canonical md (768) breakpoint per PRD §5.6. */
.hide-mobile { }
.hide-desktop { }
@media (max-width: 768px) { .hide-mobile { display: none !important; } }
@media (min-width: 769px) { .hide-desktop { display: none !important; } }

/* Grid → stack primitives — mobile-first single-column base, expanding at
   tablet/desktop. PRD §5.6: at ≤md (768) all multi-column grids collapse
   to single column. T-203. Use .grid-1/2/3 on new layouts; existing named
   grids (.card-grid, .fw-stack, etc.) retain their own breakpoint behaviour
   and will be consolidated into these primitives during Phase 3 page passes. */
.grid {
  display: grid;
  gap: var(--gutter-md);
}
.grid-1, .grid-2, .grid-3, .grid-4 {
  display: grid;
  gap: var(--gutter-md);
  grid-template-columns: 1fr;
}
@media (min-width: 769px) {
  .grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1025px) {
  .grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ---------- Diagram scroll primitive (T-403, PRD §5.5 / TRD §4.4) ---------- */
/* Wrap a wide inline diagram (SVG, schematic, table-shaped figure) in
   .diagram-scroll to opt into "scroll, don't stack" containment at small-phone
   tier. Page-level horizontal scroll is already prevented by the global
   html, body { overflow-x: clip } guard, so any horizontal panning stays
   confined to this wrapper.

   Markup (see TRD §T-403):
     <div class="diagram-scroll" role="region"
          aria-label="<diagram name>. Scroll horizontally to view." tabindex="0">
       <... wide content ...>
     </div>

   tabindex="0" is essential — it makes the wrapper keyboard-scrollable
   (Left/Right arrows pan the overflow). Per WCAG 2.1 SC 2.1.1, scrollable
   regions that are not also focusable cannot be operated by keyboard.

   Behaviour by tier:
     ≤480px (small phone): overflow-x: auto + right-edge fade affordance.
     ≥481px:                wrapper is layout-transparent (no scroll, no fade).
   This avoids forcing a scroll affordance onto tablet/desktop where the
   diagram already fits its container. */
.diagram-scroll {
  position: relative;
  /* Layout-transparent at large-phone tier and above. */
  max-width: 100%;
}
.diagram-scroll:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
  border-radius: 4px;
}
@media (max-width: 480px) {
  .diagram-scroll {
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    /* Prevent vertical scroll-chain from clobbering horizontal pan on iOS. */
    overscroll-behavior-x: contain;
    /* Optional snap; "proximity" never traps the user mid-pan. */
    scroll-snap-type: x proximity;
  }
  /* Force the inner content to its native size on phone so the scroll is
     meaningful. Without this, child elements that already declare width:
     100% (like .ks-schematic) shrink to fit the wrapper and the user has
     nothing to pan — the SVG still renders illegibly small. The 480px
     min-width matches the small-phone tier upper bound (--bp-sm); diagrams
     authored against a viewBox <= 480 wide will still fit if they declare
     their own narrower max-width. Exposed as a custom property for the
     rare case where a diagram needs a wider native canvas
     (.diagram-scroll { --diagram-min: 560px } in the page-local style). */
  .diagram-scroll > * {
    min-width: var(--diagram-min, 480px);
  }
  /* Right-edge fade hint — signals "more content this way" without taking
     interactive surface. Sized in viewport units so it stays proportional
     across phone widths; uses the page paper as the fade target so it blends
     into either light or dark sections (.framework-section etc. use the same
     paper family). pointer-events: none keeps the affordance non-blocking. */
  .diagram-scroll::after {
    content: "";
    position: absolute;
    inset-block: 0;
    inset-inline-end: 0;
    width: 32px;
    background: linear-gradient(
      to right,
      transparent,
      var(--paper) 85%
    );
    pointer-events: none;
  }
}

/* selection */
::selection { background: var(--copper-tint); color: var(--signal-ink); }

/* ==========================================================================
   Framework — Managed Ops Agent Framework (core IP differentiator)
   ========================================================================== */

/* Dedicated section background — slightly deeper warm stone to signal "platform" */
.framework-section {
  background: linear-gradient(180deg, var(--paper) 0%, var(--paper-2) 100%);
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  position: relative;
  overflow: hidden;
}
.framework-section::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(to right, rgba(14,15,18,0.035) 1px, transparent 1px);
  background-size: 120px 100%;
  mask: linear-gradient(to bottom, transparent, black 20%, black 80%, transparent);
  opacity: .6;
}
.framework-section > .wrap { position: relative; z-index: 1; }

/* Layer stack — the visual signature of the framework */
.fw-stack {
  display: grid;
  gap: 10px;
  margin-top: 32px;
}
.fw-layer {
  display: grid;
  grid-template-columns: 56px 1fr auto;
  gap: 20px;
  align-items: center;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 10px;
  padding: 20px 24px;
  transition: border-color .15s, background .15s;
  position: relative;
}
.fw-layer:hover {
  border-color: var(--signal);
  background: var(--card-pure);
}
.fw-layer .fw-num {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--ink-4);
  font-weight: 500;
}
.fw-layer .fw-num em {
  font-style: normal;
  display: block;
  font-size: 22px;
  font-family: var(--sans);
  color: var(--ink);
  font-weight: 500;
  letter-spacing: -0.02em;
  margin-top: 2px;
}
.fw-layer .fw-title {
  display: flex;
  align-items: center;
  gap: 12px;
}
.fw-layer .fw-title .ico {
  width: 32px; height: 32px;
  background: var(--paper-2);
  border: 1px solid var(--rule);
  border-radius: 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--signal-text);
  flex: 0 0 32px;
}
.fw-layer .fw-title .ico svg { width: 16px; height: 16px; }
.fw-layer .fw-body h3 {
  /* T-301: 17px → --fs-h4 (17→20 fluid). */
  font-size: var(--fs-h4);
  margin: 0 0 4px;
  letter-spacing: -0.015em;
}
.fw-layer .fw-body p {
  /* T-301: 14px → --fs-base (≥16px floor) for body-copy compliance with
     PRD §5.3. The 58ch max keeps reading-line constrained. */
  font-size: var(--fs-base);
  line-height: var(--lh-body);
  color: var(--ink-3);
  margin: 0;
  max-width: 58ch;
}
.fw-layer .fw-tag {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--signal-text);
  background: var(--copper-tint);
  padding: 4px 10px;
  border-radius: 4px;
  white-space: nowrap;
}
.fw-layer .fw-tag.muted {
  color: var(--ink-3);
  background: var(--paper-2);
}
/* T-301 page pass: .fw-layer collapse migrated 800 → canonical md (768)
   per TRD §4.1. The 769-800 zone now retains the 56-1fr-auto three-column
   layout, which fits comfortably at iPad-Mini (768) lower bound. */
@media (max-width: 768px) {
  .fw-layer { grid-template-columns: 1fr; gap: 12px; }
  .fw-layer .fw-tag { justify-self: start; }
}

/* Framework hero schematic — agent-loop visualization */
.fw-hero {
  background: var(--dark);
  color: var(--dark-ink);
  border-radius: 12px;
  padding: 28px 32px;
  position: relative;
  overflow: hidden;
  box-shadow: 0 24px 56px -28px rgba(14,15,18,0.4);
}
.fw-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(to right, rgba(231,234,238,0.04) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(231,234,238,0.04) 1px, transparent 1px);
  background-size: 40px 40px;
  pointer-events: none;
}
.fw-hero > * { position: relative; }
.fw-hero .fw-hero-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--dark-ink-3);
  padding-bottom: 14px;
  margin-bottom: 18px;
  border-bottom: 1px dashed var(--dark-rule);
}
.fw-hero .fw-hero-head .tag {
  color: #4FD4A0;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.fw-hero .fw-hero-head .tag::before {
  content: "";
  width: 6px; height: 6px; border-radius: 50%;
  background: #4FD4A0;
  box-shadow: 0 0 0 3px rgba(79, 212, 160, 0.2);
  animation: pulse-green 2s ease-in-out infinite;
}
@keyframes pulse-green {
  0%, 100% { box-shadow: 0 0 0 3px rgba(79, 212, 160, 0.2); }
  50% { box-shadow: 0 0 0 5px rgba(79, 212, 160, 0.1); }
}
.fw-hero svg { width: 100%; height: auto; }

/* Two-column list blocks (framework "plain terms") — duplicate of the
   earlier .two-col rule with a different phone-tier gap (36 vs 32). The
   second declaration wins by source order; legacy callsites depend on
   it, so kept until a focused dedupe pass. T-306 migrates the breakpoint
   to canonical md (768). */
.two-col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 56px;
}
@media (max-width: 768px) {
  .two-col { grid-template-columns: 1fr; gap: 36px; }
}
.list-block h3 {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0 0 20px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--rule);
}
.list-block ul {
  list-style: none;
  padding: 0;
  margin: 0;
}
.list-block li {
  display: grid;
  grid-template-columns: 20px 1fr;
  gap: 10px;
  align-items: baseline;
  padding: 14px 0;
  border-bottom: 1px dashed var(--rule);
  font-size: var(--fs-base);
  line-height: 1.55;
  color: var(--ink-2);
}
@media print {
  /* Revert grid layout for print — bullets only */
  .list-block li {
    display: list-item !important;
    grid-template-columns: none !important;
    gap: 0 !important;
    padding: 1pt 0 !important;
    border: 0 !important;
  }
  .list-block li .c { display: none !important; }
}
.list-block li:last-child { border-bottom: 0; }
.list-block li .c {
  font-family: var(--mono);
  font-size: 13px;
  color: var(--signal-text);
  line-height: 1.55;
}
.list-block li em {
  font-style: normal;
  color: var(--ink);
  font-weight: 500;
}
/* "What it replaces" uses a muted marker */
.list-block + .list-block li .c,
.list-block:nth-child(2) li .c {
  color: var(--ink-4);
}


/* ==========================================================================
   MOBILE RESPONSIVE PASS (≤ 600px, 420px)
   Scales type, tightens padding, collapses grids. Desktop layout unchanged.
   ========================================================================== */

/* Hamburger button — hidden on desktop, shown ≤1024px (PRD §5.2). */
.nav-toggle {
  display: none;
  width: 44px;
  height: 44px;
  min-width: 44px;
  min-height: 44px;
  padding: 0;
  border: 1px solid var(--rule-strong);
  border-radius: 8px;
  background: transparent;
  cursor: pointer;
  position: relative;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  color: var(--ink);
}
.nav-toggle span {
  display: block;
  width: 18px;
  height: 1.5px;
  background: var(--ink);
  border-radius: 1px;
}
@media (prefers-reduced-motion: no-preference) {
  .nav-toggle span { transition: transform .18s ease, opacity .18s ease; }
}
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(5.5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-5.5px) rotate(-45deg); }
.nav-toggle:focus-visible { outline: 2px solid var(--signal); outline-offset: 2px; }

/* Mobile menu panel — base (hidden) state; shown via media query below. */
.nav-mobile { display: none; }

/* Stop horizontal scroll from any stray overflow */
html { overflow-x: clip; }
body { overflow-x: clip; }

/* Mobile nav surface — active ≤lg (1024). PRD §5.2.
   JS owns open/close, focus trap, scroll lock, Escape, outside-tap. */
@media (max-width: 1024px) {
  .nav a:not(.btn):not(.nav-cta) { display: none; }
  .nav .sep { display: none; }
  .nav-toggle { display: inline-flex; }
  .nav-mobile {
    display: block;
    position: fixed;
    inset: 64px 0 0 0;
    z-index: 49;
    background: var(--paper);
    border-top: 1px solid var(--rule);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }
  .nav-mobile[hidden] { display: none; }
  .nav-mobile .wrap {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding-top: 8px;
    padding-bottom: 24px;
  }
  .nav-mobile a:not(.btn) {
    display: flex;
    align-items: center;
    min-height: 44px;
    padding: 14px 4px;
    font-size: 17px;
    font-weight: 450;
    color: var(--ink);
    text-decoration: none;
    border-bottom: 1px solid var(--rule);
    letter-spacing: -0.01em;
  }
  .nav-mobile a.active { color: var(--signal-text); }
  .nav-mobile a:focus-visible { outline: 2px solid var(--signal); outline-offset: 2px; }
  .nav-mobile-cta {
    margin-top: 20px;
    justify-content: center;
    min-height: 44px;
    padding: 14px 18px;
    font-size: 15px;
  }
  .nav-mobile-cta:focus-visible { outline: 2px solid var(--signal); outline-offset: 2px; }
  @media (prefers-reduced-motion: no-preference) {
    .nav-mobile { animation: navSlide .18s ease-out; }
    @keyframes navSlide {
      from { opacity: 0; transform: translateY(-4px); }
      to   { opacity: 1; transform: translateY(0); }
    }
  }
  body.nav-open { overflow: hidden; }

  /* When the mobile menu is open, chrome.js pins the body with
     `position: fixed; top: -<scrollY>px` to lock background scroll.
     The topnav is `position: sticky` (see §Top chrome), which sticks
     relative to its scrolling ancestor — i.e. the body. Once the body
     itself is shifted to top: -1000px, the sticky topnav rides along
     and disappears off the top of the viewport. Anchor the topnav to
     the viewport directly while the menu is open so it stays visible
     above the panel regardless of pre-open scrollY. */
  body.nav-open .topnav {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
  }
}

/* Print: ensure mobile nav chrome is suppressed (PRD §6.4). */
@media print {
  .nav-toggle,
  .nav-mobile { display: none !important; }
}

/* MIGRATE: → sm (480) and md (768) — large mobile-pass block; Phase 3 page passes will split this between small-phone (<=480) and large-phone (481-768) tiers per PRD §5.1. */
@media (max-width: 600px) {
  :root {
    --pad: 20px;
  }

  /* Type scale: heading, body, and lede sizes now driven by canonical
     --fs-* tokens (PRD §5.3, T-004/T-201/T-205). Phone-specific
     letter-spacing/line-height refinements retained; inline clamp()
     overrides removed to enforce a single fluid scale. .lede tracks
     --fs-lede; p inherits --fs-base from <body>. */
  h1 { letter-spacing: -0.025em; line-height: 1.05; }
  h2 { line-height: 1.15; }

  /* Section spacing */
  .section { padding: 48px 0; }
  .section-head { margin-bottom: 28px; padding-bottom: 16px; }

  /* Top nav phone tweaks (sizing only — visibility owned by ≤1024 block above) */
  .topnav .wrap { height: 56px; }
  .brand { font-size: 15px; }
  .brand-mark { width: 20px; height: 20px; }
  .nav { gap: 10px; }
  .nav-cta { padding: 8px 12px; font-size: 12.5px; }
  .nav-cta .arrow { display: none; }
  /* When topnav shrinks to 56px, mobile panel inset top must follow. */
  .nav-mobile { inset: 56px 0 0 0; }

  /* Buttons: prevent tiny tap targets */
  .btn { padding: 12px 18px; font-size: 14px; min-height: 44px; }
  .btn-sm { padding: 10px 14px; min-height: 40px; }
  .btn-lg { padding: 14px 20px; font-size: 15px; }

  /* Page hero: more breathing room, smaller */
  .page-hero { padding: 40px 0 36px; }
  .page-hero .wrap { grid-template-columns: 1fr; gap: 32px; }
  .page-hero::before {
    right: -260px; bottom: -280px;
    width: 480px; height: 480px;
  }

  /* Generic hero (home) */
  .hero { padding: 40px 0 56px !important; }
  .hero .wrap { grid-template-columns: 1fr !important; gap: 36px !important; }

  /* Spec rows — single-col already triggered at md (768) above. Phone
     tier just tightens padding/gap; type sizes now driven by --fs-h4
     and --fs-base tokens (T-306). col-k and col-price retain their
     mono caption-class sizes (12px) — visual signature, not body copy. */
  .spec-row {
    padding: 16px 0;
    gap: 4px;
  }
  .spec-row .col-k { font-size: 12px; }
  .spec-row .col-price { font-size: 12px; }

  /* Section-head stack tighter */
  .section-head { grid-template-columns: 1fr; gap: 12px; margin-bottom: 28px; }

  /* CTA band: tighter padding on phones; type sizes now driven by
     --fs-h2 and --fs-lede tokens (T-303). */
  .cta-band { padding: 56px 0 !important; }
  .cta-band h2 { margin-bottom: 14px !important; }

  /* Lists / list-block readable */
  .list-block li { padding: 10px 0; font-size: 14.5px; gap: 8px; grid-template-columns: 18px 1fr; }

  /* Footer: single column on phones */
  .foot { padding: 48px 0 32px; }
  .foot .wrap {
    grid-template-columns: 1fr !important;
    gap: 28px;
  }
  .foot .foot-brand { grid-column: auto; }
  .foot .tagline { max-width: 42ch; }
  .foot .meta {
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
    margin-top: 8px;
  }

  /* Framework layered section — stack */
  .fw-layer { grid-template-columns: 1fr !important; gap: 16px !important; }

  /* Prose blocks (security page etc.) */
  .prose-block { grid-template-columns: 1fr !important; gap: 20px !important; }

  /* About / team grids */
  .team-grid { grid-template-columns: 1fr !important; }
  .thesis-list > div { grid-template-columns: 1fr !important; gap: 6px !important; }

  /* Pricing tier grids that are 3-col */
  .tier-grid, .pricing-3col, .rider-grid { grid-template-columns: 1fr !important; }

  /* Kicker: slightly smaller */
  .kicker { font-size: 10.5px; gap: 8px; }

  /* Start page sidebar */
  .start-grid { grid-template-columns: 1fr !important; gap: 32px !important; }
  .path-switch { position: static !important; }
}

/* keep: 380 — extra-tight tweaks for sub-380 viewports (e.g., 320px Galaxy Fold cover); inside the small-phone tier so does not collide with the canonical sm/md/lg thresholds. */
/* Very small phones (≤ 380px) — tighten just a bit more.
   Heading font-size overrides removed: --fs-h1 / --fs-h2 already clamp at
   32px / 24px floors, which match (and slightly improve on) the prior
   30px / 22px hard sizes. PRD §5.3 single-scale enforcement. */
@media (max-width: 380px) {
  :root { --pad: 16px; }
  .btn { padding: 11px 14px; font-size: 13.5px; }
  .nav-cta { padding: 7px 10px; font-size: 12px; }
}

/* ==========================================================================
   ADDED FROM MASTER MERGE — Pagefind/FAQ/Blog/SEO additions
   (skip-link, foot-address, blog, post body, team-roles, self-hosted fonts,
    breadcrumbs, post-pager, related-posts, post-meta tag/author, auto-link,
    faq-section)
   ========================================================================== */

.skip-to-content {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--signal);
  color: #fff;
  padding: 10px 14px;
  z-index: 1000;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  border-radius: 0 0 4px 0;
}
.skip-to-content:focus {
  left: 0;
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

main:focus { outline: none; }

.foot-address {
  font-style: normal;
  font-size: 13px;
  color: var(--ink-3);
  margin-top: 10px;
}
.foot-address a { color: var(--ink-2); text-decoration: none; }
.foot-address a:hover { color: var(--ink); }

/* Blog */
.blog-list { display: grid; gap: 32px; }
.blog-card { padding: 24px 0; border-bottom: 1px solid var(--rule); }
.blog-card:last-child { border-bottom: 0; }
.blog-card .kicker { font-family: var(--mono); font-size: 11px; letter-spacing: 0.1em; color: var(--ink-3); text-transform: uppercase; margin-bottom: 8px; }
.blog-card h2 { font-size: 24px; margin: 0 0 8px; letter-spacing: -0.015em; }
.blog-card h2 a { color: var(--ink); text-decoration: none; }
.blog-card h2 a:hover { color: var(--signal); }
.blog-card p { color: var(--ink-3); margin: 0 0 12px; max-width: 64ch; }

.post-body { font-size: 17px; line-height: 1.65; color: var(--ink-2); }
.post-body h2 { font-size: 24px; margin: 36px 0 12px; letter-spacing: -0.02em; }
.post-body h3 { font-size: 19px; margin: 28px 0 8px; }
.post-body p { margin: 0 0 16px; max-width: 70ch; }
.post-body ul, .post-body ol { padding-left: 24px; margin: 0 0 18px; }
.post-body li { margin: 6px 0; }
.post-body code { font-family: var(--mono); font-size: 0.9em; background: var(--paper-2); padding: 2px 6px; border-radius: 3px; }
.post-body pre { background: var(--dark); color: var(--dark-ink); padding: 18px 20px; border-radius: 6px; overflow-x: auto; font-size: 13px; }
.post-body pre code { background: transparent; padding: 0; color: inherit; }
.post-body blockquote { border-left: 3px solid var(--signal); margin: 0 0 16px; padding: 4px 0 4px 18px; color: var(--ink-2); font-style: italic; }
.post-body a { color: var(--signal-ink); text-decoration: underline; text-underline-offset: 2px; }
.post-body img { max-width: 100%; height: auto; border-radius: 6px; }
.post-body .tag { display: inline-block; font-family: var(--mono); font-size: 11px; letter-spacing: 0.06em; color: var(--ink-3); padding: 2px 6px; border: 1px solid var(--rule); border-radius: 3px; margin-right: 4px; }

/* About — team-roles (replaces team-grid until named bios land) */
.team-roles {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}
@media (max-width: 900px) { .team-roles { grid-template-columns: 1fr; } }
.role-card {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 24px 24px 26px;
}
.role-card .role-num {
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.1em;
  color: var(--ink-3); text-transform: uppercase; margin-bottom: 8px;
}
.role-card h3 {
  font-size: 20px; letter-spacing: -0.015em; margin: 0 0 10px;
}
.role-card p {
  font-size: 14px; color: var(--ink-3); line-height: 1.55; margin: 0;
}
/* Author-bio CTAs: standalone link wrapped in <h3> or <p> needs the
   44px hit-target floor (T-602 / WCAG 2.5.5). The branch's hit-target
   test correctly excludes inline-prose anchors; these anchors are the
   sole content of their wrapper, so they're tap-targets, not flowing
   prose. */
.role-card h3 > a:only-child,
.role-card p > a:only-child {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 10px 0;
}

/* Self-hosted fonts (Inter, JetBrains Mono — variable font binaries) */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/assets/fonts/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/assets/fonts/inter-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 100 800;
  font-display: swap;
  src: url('/assets/fonts/jetbrainsmono-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 100 800;
  font-display: swap;
  src: url('/assets/fonts/jetbrainsmono-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ==========================================================================
   Phase 6 additions: breadcrumbs, post pager, related posts, tag links
   ========================================================================== */

.breadcrumbs {
  background: var(--paper-2);
  border-bottom: 1px solid var(--rule);
  padding: 14px 0;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--ink-3);
}
.breadcrumbs ol {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
}
.breadcrumbs li {
  display: inline-flex; align-items: center;
}
.breadcrumbs li + li::before {
  content: "›"; color: var(--ink-4); margin-right: 8px; font-size: 13px;
}
.breadcrumbs a {
  color: var(--ink-3); text-decoration: none;
}
.breadcrumbs a:hover { color: var(--ink); }
.breadcrumbs li[aria-current="page"] {
  color: var(--ink); font-weight: 500;
}

/* Post pager (prev/next) */
.post-pager {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  margin-top: 56px;
  padding-top: 32px;
  border-top: 1px solid var(--rule);
}
.post-pager-cell { min-width: 0; }
.post-pager-cell.next { text-align: right; }
.post-pager a {
  display: flex; flex-direction: column; gap: 4px;
  text-decoration: none; color: var(--ink-2);
  padding: 12px 0;
}
.post-pager a:hover { color: var(--signal-ink); }
.post-pager a:hover .ttl { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.post-pager .lbl {
  font-family: var(--mono); font-size: 11px; color: var(--ink-3);
  letter-spacing: 0.08em; text-transform: uppercase;
}
.post-pager .ttl {
  font-size: 16px; font-weight: 500; color: var(--ink);
  letter-spacing: -0.01em; line-height: 1.3;
}
@media (max-width: 600px) {
  .post-pager { grid-template-columns: 1fr; gap: 24px; }
  .post-pager-cell.next { text-align: left; }
}

/* Related posts block */
.related-posts {
  margin-top: 56px;
  padding-top: 32px;
  border-top: 1px solid var(--rule);
}
.related-posts h2 {
  font-size: 18px; letter-spacing: -0.01em;
  font-family: var(--mono); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--ink-3); margin: 0 0 20px;
}
.related-posts ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 0; }
.related-posts li { border-top: 1px solid var(--rule); }
.related-posts li:last-child { border-bottom: 1px solid var(--rule); }
.related-posts a {
  display: grid;
  grid-template-columns: 110px 1fr;
  gap: 16px;
  padding: 16px 0;
  text-decoration: none;
  color: var(--ink-2);
  align-items: baseline;
}
.related-posts a:hover { color: var(--ink); }
.related-posts .r-date {
  font-family: var(--mono); font-size: 11px; color: var(--ink-4);
  letter-spacing: 0.04em; text-transform: uppercase;
  white-space: nowrap;
}
.related-posts .r-title {
  display: block; font-size: 16px; font-weight: 500;
  color: var(--ink); letter-spacing: -0.01em; line-height: 1.3;
  margin-bottom: 4px;
}
.related-posts .r-desc {
  display: block; font-size: 13.5px; color: var(--ink-3); line-height: 1.5;
}
.related-posts a:hover .r-title { color: var(--signal-ink); text-decoration: underline; text-underline-offset: 3px; }
@media (max-width: 600px) {
  .related-posts a { grid-template-columns: 1fr; gap: 4px; }
}

/* Tag links in post meta */
.post-meta a.tag {
  text-decoration: none;
  color: var(--ink-3);
  border: 1px solid var(--rule);
  padding: 2px 8px;
  border-radius: 3px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  margin-right: 4px;
  transition: border-color .15s, color .15s;
}
.post-meta a.tag:hover {
  color: var(--signal-ink);
  border-color: var(--signal);
}

/* Author byline link (inside post-meta) */
.post-meta a[rel="author"] {
  color: var(--ink-2);
  text-decoration: none;
  font-weight: 500;
  border-bottom: 1px dotted var(--rule-strong);
}
.post-meta a[rel="author"]:hover {
  color: var(--signal-ink);
  border-bottom-color: var(--signal);
}

/* Reduced motion: disable nav animation, pager hover transitions, etc. */
@media (prefers-reduced-motion: reduce) {
  .nav-mobile { animation: none !important; }
  .nav-toggle span { transition: none !important; }
  .post-pager a, .post-meta a, .related-posts a, .tag {
    transition: none !important;
  }
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; }
}

/* Auto-linked glossary terms (subtle, indicates a definition link) */
dfn { font-style: normal; }
a.auto-link {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--rule-strong);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: text-decoration-color .15s, color .15s;
}
a.auto-link:hover {
  color: var(--signal-ink);
  text-decoration-color: var(--signal);
}

/* ==========================================================================
   FAQ block (details/summary, accessible, no JS)
   ========================================================================== */

.faq-section {
  border-top: 1px solid var(--rule);
}
.faq-section .kicker { margin-bottom: 12px; }
.faq-section h2 { margin-bottom: 32px; max-width: 28ch; }
.faq-list {
  display: grid;
  gap: 0;
  border-top: 1px solid var(--rule);
}
.faq-item {
  border-bottom: 1px solid var(--rule);
}
.faq-item summary {
  list-style: none;
  cursor: pointer;
  padding: 22px 28px 22px 0;
  font-size: 17px;
  font-weight: 500;
  letter-spacing: -0.015em;
  color: var(--ink);
  position: relative;
  transition: color .15s;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: "+";
  position: absolute;
  right: 0; top: 50%;
  transform: translateY(-50%);
  font-family: var(--mono);
  font-size: 22px;
  font-weight: 400;
  color: var(--ink-3);
  transition: transform .18s ease, color .15s;
}
.faq-item[open] summary::after {
  content: "−";
  color: var(--signal);
}
.faq-item summary:hover { color: var(--signal-ink); }
.faq-item[open] summary { color: var(--ink); }
.faq-answer {
  padding: 0 0 22px;
  max-width: 70ch;
}
.faq-answer p {
  font-size: 15.5px;
  color: var(--ink-2);
  line-height: 1.65;
  margin: 0;
}

@media (prefers-reduced-motion: reduce) {
  .faq-item summary, .faq-item summary::after { transition: none; }
}
