/* ============================================================================
   InfraEdge — components. Tokens and type live in base.css.
   Hard rules: no drop shadows; gold is a surface or a shape, never text on light.
   ========================================================================= */

/* ---------------------------------------------------------------- layout */
.container { width: 100%; max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }
.container-narrow { max-width: 860px; }

/* Find-your-path hero — illustration beside the intro, quiz stays narrow below. */
.path-hero { padding-bottom: var(--s-3); }
.path-hero-split {
  align-items: center;
  gap: clamp(1.75rem, 4vw, 3.5rem);
}
.path-hero-split .lead { max-width: 42ch; }
.path-hero-art {
  margin: 0;
  justify-self: end;
  width: min(100%, 34rem);
}
.path-hero-art img {
  width: 100%;
  height: auto;
  max-height: none;
  display: block;
  border-radius: var(--r-m);
  border: 1px solid var(--line);
  background: color-mix(in srgb, var(--sky-600) 6%, var(--white));
}
:root[data-theme='dark'] .path-hero-art img {
  border-color: color-mix(in srgb, var(--sky-600) 35%, var(--line));
}
@media (max-width: 900px) {
  .path-hero-art { justify-self: stretch; width: 100%; max-width: 28rem; margin-inline: auto; }
}

.section { padding-block: var(--section); position: relative; }
.section.is-tight { padding-block: calc(var(--section) * .55); }
.section.pt-0 { padding-top: 0; }
.section.pb-0 { padding-bottom: 0; }

/*
  Security and About are long pages of short blocks. Default section padding
  leaves large empty bands between them; keep the same structure, less air.
*/
body[data-page='security'] .hero {
  padding-block: clamp(2.25rem, 5vw, 3.75rem) clamp(1.75rem, 3.5vw, 2.75rem);
}
body[data-page='security'] .hero .lead { margin-bottom: var(--s-2); }
body[data-page='security'] .hero .lead + .lead { margin-bottom: var(--s-3); }
body[data-page='security'] .section,
body[data-page='about'] .section {
  padding-block: calc(var(--section) * .48);
}
body[data-page='security'] .section.pt-0,
body[data-page='about'] .section.pt-0 {
  padding-top: 0;
}
body[data-page='security'] .section.pb-0,
body[data-page='about'] .section.pb-0 {
  padding-bottom: 0;
}
body[data-page='security'] .sec-head,
body[data-page='about'] .sec-head {
  margin-bottom: var(--s-3);
}
body[data-page='security'] .sec-head h2 { margin-bottom: .5rem; }
body[data-page='about'] .split {
  gap: clamp(1.5rem, 3vw, 2.75rem);
  align-items: start;
}
body[data-page='about'] .about-hero-split {
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.75fr);
}
body[data-page='about'] .about-hero-photo {
  max-width: 340px;
  margin-inline-start: auto;
}
body[data-page='about'] .about-hero-photo img {
  max-height: 420px;
  object-position: center 18%;
}
@media (max-width: 900px) {
  body[data-page='about'] .about-hero-split { grid-template-columns: 1fr; }
  body[data-page='about'] .about-hero-photo {
    max-width: 360px;
    margin-inline: 0;
  }
  body[data-page='about'] .about-hero-photo img { max-height: 380px; }
}
body[data-page='about'] .prose h2 {
  margin-top: var(--s-3);
}
body[data-page='about'] .prose h2:first-of-type {
  margin-top: var(--s-2);
}
body[data-page='about'] .prose p { margin-bottom: .85rem; }
body[data-page='about'] .prose strong,
body[data-page='about'] .lead strong {
  color: var(--ink);
  font-weight: 600;
}

.tone-mist { background: var(--mist); }
.tone-white { background: var(--white); }
.tone-navy {
  background: var(--tone-navy-bg); color: var(--on-navy);
  --hover-border: var(--gold-400);
  --hover-ink: var(--gold-400);
}
.tone-navy h1, .tone-navy h2, .tone-navy h3, .tone-navy strong { color: var(--tone-navy-ink); }
.tone-navy .lead, .tone-navy .muted { color: var(--on-navy-quiet); }
/*
  Prose links on navy go gold. Buttons must be excluded, and the exclusion has
  to live here rather than be fought downstream: `.tone-navy a` is specificity
  (0,1,1) and `.btn-gold` is (0,1,0), so without this every gold-filled button
  inside a navy section rendered gold type on a gold fill — an invisible
  label. Buttons already set their own colour a few rules below.
*/
.tone-navy a:not(.btn):not(.btn-ghost) { color: var(--gold-400); }

/* Section header: eyebrow left, running index right, then title and lead. */
.sec-head { margin-bottom: var(--s-4); }
.sec-head-top {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-3); margin-bottom: var(--s-2);
  border-bottom: 1px solid var(--line); padding-bottom: var(--s-2);
}
.tone-navy .sec-head-top { border-color: var(--navy-line); }
.sec-head h2 { margin-bottom: .75rem; max-width: 22ch; }
.sec-head .lead { max-width: 62ch; }

.grid { display: grid; gap: var(--s-3); }
.cols-2 { grid-template-columns: repeat(2, 1fr); }
.cols-3 { grid-template-columns: repeat(3, 1fr); }
.cols-4 { grid-template-columns: repeat(4, 1fr); }
.split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem, 5vw, 4.5rem); align-items: center; }

@media (max-width: 900px) {
  .cols-3, .cols-4 { grid-template-columns: repeat(2, 1fr); }
  .split { grid-template-columns: 1fr; }
}
@media (max-width: 600px) {
  .cols-2, .cols-3, .cols-4 { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------- buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  font-size: var(--t-body); font-weight: 600; letter-spacing: -0.01em;
  padding: .8rem 1.4rem; border-radius: var(--r-s);
  text-decoration: none; white-space: nowrap;
  /* nowrap keeps a label on one line, which is right until the label is
     longer than a 360px screen. Capping the width lets the longest CTAs wrap
     rather than push the page sideways. */
  max-width: 100%;
  transition: background var(--dur-fast) ease, color var(--dur-fast) ease,
              border-color var(--dur-fast) ease;
}
@media (max-width: 460px) {
  .btn { white-space: normal; text-align: center; }
}
.btn:active { transform: translateY(1px); }

/* Gold fill with navy type — 9.29:1. This is the correct way to use gold.
   Use --ink-on-gold (theme-invariant), never --navy-900/--ink: those flip
   light in dark mode and become white-on-yellow. strong/b inherit the same. */
.btn-gold { background: var(--gold-400); color: var(--ink-on-gold); }
.btn-gold:hover { background: var(--gold-hover); color: var(--ink-on-gold); }
.btn-gold strong, .btn-gold b,
.badge-gold strong, .badge-gold b,
.badge-partial strong, .badge-partial b { color: inherit; }

.btn-sky { background: var(--sky-700); color: var(--white); }
.btn-sky:hover { background: var(--sky-600); color: var(--white); }

.btn-outline { border: 1px solid var(--line-strong); color: var(--ink); background: var(--white); }
.btn-outline:hover { border-color: var(--hover-border); color: var(--hover-ink); }
.tone-navy .btn-outline { background: transparent; border-color: var(--navy-line-2); color: var(--tone-navy-ink); }
.tone-navy .btn-outline:hover { border-color: var(--hover-border); color: var(--hover-ink); }

.btn-lg { padding: 1rem 1.75rem; font-size: var(--t-lead); }

.btn-ghost {
  display: inline-flex; align-items: center; gap: .4rem;
  font-weight: 600; color: var(--sky-700); text-decoration: none;
}
.btn-ghost::after { content: '→'; transition: transform var(--dur-fast) ease; }
.btn-ghost:hover::after { transform: translateX(3px); }
.tone-navy .btn-ghost { color: var(--gold-400); }

.actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3); }

/* ---------------------------------------------------------------- badges */
.badge {
  display: inline-flex; align-items: center; gap: .35rem;
  font-size: var(--t-micro); font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  padding: .25rem .6rem; border-radius: 999px; white-space: nowrap;
}
.badge-sky { background: var(--sky-tint); color: var(--sky-700); }
.badge-navy { background: var(--tone-navy-bg); color: var(--tone-navy-ink); }
.badge-gold { background: var(--gold-400); color: var(--ink-on-gold); }
.badge-ok { background: var(--sky-tint); color: var(--sky-700); }
.badge-partial { background: var(--gold-400); color: var(--ink-on-gold); }
.badge-high { background: var(--amber-tint); color: var(--amber-ink); }

/* ---------------------------------------------------------------- cards */
.card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-m);
  padding: var(--s-3);
  display: flex; flex-direction: column; gap: .6rem;
  transition: border-color var(--dur-fast) ease;
  /* No shadows. Separation comes from the hairline and the mist fill. */
}
.card h3 { margin-bottom: .1rem; }
.card p { font-size: var(--t-small); color: var(--ink-quiet); }
.tone-mist .card { background: var(--white); }
.tone-navy .card { background: var(--tone-navy-card); border-color: var(--navy-line); }
/*
  Card body text is --ink-quiet, which is a slate meant for white surfaces.
  Left alone on navy-800 it lands at 2.4:1 — a straightforward AA failure that
  hid for a while because these cards start at opacity 0 and contrast checkers
  skip invisible elements. Same story for the section index on navy.
*/
.tone-navy .card p { color: var(--on-navy-quiet); }
.tone-navy .index { color: var(--on-navy-faint); }
/*
  The running index is "03 / 03": the whole unit is faint, the current number
  is a <b> set brighter. base.css gives that <b> --ink, which on a navy ground
  is the ground — the number rendered navy on navy at 1.00:1 and had simply
  been invisible on every navy section header. Same on the CTA panel.
*/
.tone-navy .index b,
.cta-panel .index b { color: var(--on-navy); }

a.card { text-decoration: none; color: inherit; }
.card:hover { border-color: var(--hover-border); }
.card:hover h3, .card:hover .h3 { color: var(--hover-ink); }

.card-num {
  font-family: var(--font); font-size: var(--t-micro); font-weight: 600;
  letter-spacing: .1em; color: var(--sky-700);
}
.tone-navy .card-num { color: var(--gold-400); }

/* ---------------------------------------------------------------- header */
.site-header {
  position: sticky; top: 0; z-index: 100;
  background: var(--header-bg);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid transparent;
  transition: border-color 200ms ease, background 200ms ease;
}
.site-header.is-stuck { border-bottom-color: var(--line); background: var(--header-bg-stuck); }
.header-inner { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); min-height: 72px; }
.logo-link { display: inline-flex; align-items: center; flex: none; }
.logo-img { width: 188px; height: auto; }

.header-tools {
  display: flex; align-items: center; gap: .5rem; flex: none;
  /* Sit above the nav so a long CTA cannot paint over the expanding label. */
  position: relative;
  z-index: 2;
  /* A touch more air between the gold CTA and the theme control. */
  margin-inline-start: .35rem;
}
.header-inner > nav { flex: 1; display: flex; justify-content: flex-end; min-width: 0; }

/* One lockup at a time. data-resolved-theme is written by js/theme.js and
   always holds a concrete light/dark, never "system", so this needs no
   media query of its own — the resolution happens in one place. */
.logo-on-dark { display: none; }
:root[data-resolved-theme='dark'] .logo-on-light { display: none; }
:root[data-resolved-theme='dark'] .logo-on-dark { display: inline-block; }

/*
  Theme control. Icon-only until hover or keyboard focus, then the box grows
  to the current mode word. No underline — the word is the label. Pointer
  devices get the hover; coarse pointers stay icon-only so a tap still
  swaps the theme rather than expanding first.
*/
.theme-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  position: relative; isolation: isolate; overflow: hidden;
  height: 38px; min-width: 38px; padding: 0 12px 0 10px; gap: .45rem;
  border: 1px solid var(--line); border-radius: var(--r-s);
  background: var(--surface-raised); color: var(--ink-soft);
  cursor: pointer;
  transition: border-color var(--dur-fast) ease, color var(--dur-fast) ease;
}
.theme-toggle:hover,
.theme-toggle:focus-visible { border-color: var(--hover-border); color: var(--ink); }
.theme-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.theme-toggle-icon {
  display: inline-flex; flex: none; width: 16px; height: 16px;
  position: relative; z-index: 1;
  transition: transform 700ms cubic-bezier(.2, .7, .3, 1);
}
.theme-icon { fill: currentColor; display: none; width: 16px; height: 16px; }
.theme-toggle[data-mode='light'] .theme-icon-light,
.theme-toggle[data-mode='dark'] .theme-icon-dark { display: block; }
.theme-toggle[data-mode='dark'] .theme-toggle-icon { transform: rotate(-30deg); }
/*
  The 2px that stops the last glyph clipping sits on the container, not on the
  element that clips. overflow:hidden clips at the padding box, so a pad on the
  inner leaked 2px of the word through the collapsed 0fr track — a faint arc
  when the label was "System", and a clean stray "|" once it became "Light".
*/
.theme-toggle-copy {
  display: grid; grid-template-columns: 0fr;
  position: relative; z-index: 1;
  transition: grid-template-columns 280ms cubic-bezier(.2, .7, .3, 1);
}
.theme-toggle-copy-inner {
  min-width: 0; overflow: hidden;
  font-size: 13px; font-weight: 500; letter-spacing: -.011em;
  white-space: nowrap; line-height: 1;
}
.theme-toggle-word { display: none; }
.theme-toggle[data-mode='light'] .theme-toggle-word[data-for='light'],
.theme-toggle[data-mode='dark'] .theme-toggle-word[data-for='dark'] { display: inline; }
.theme-toggle-sheen {
  /* Behind the icon + word so the hover sweep cannot veil “Light”. */
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--sky-500) 18%, transparent), transparent);
  transform: translateX(-100%);
}
@media (hover: hover) and (pointer: fine) {
  .theme-toggle:hover .theme-toggle-copy,
  .theme-toggle:focus-visible .theme-toggle-copy {
    grid-template-columns: 1fr; padding-inline-end: 2px;
  }
  .theme-toggle:hover .theme-toggle-icon,
  .theme-toggle:focus-visible .theme-toggle-icon {
    transform: rotate(360deg) scale(1.08);
  }
  .theme-toggle:hover .theme-toggle-sheen,
  .theme-toggle:focus-visible .theme-toggle-sheen {
    transform: translateX(100%);
    transition: transform 500ms ease;
  }
}
@media (hover: none), (pointer: coarse) {
  .theme-toggle:focus-visible .theme-toggle-copy { grid-template-columns: 1fr; padding-inline-end: 2px; }
}
.tone-navy .theme-toggle { background: transparent; border-color: var(--navy-line-2); color: var(--on-navy); }
.tone-navy .theme-toggle-sheen {
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--gold-400) 22%, transparent), transparent);
}

/* Seven items and the call button. The gap is one step tighter than it was
   with six. From 1200px up every label sits on one line; between the 1040
   breakpoint and 1200px the longer labels wrap to two, as they did before,
   which keeps the row clear of the logo (tests/responsive.test.js measures
   that). Below the breakpoint the drawer takes over. */
.nav-links { display: flex; align-items: center; gap: var(--s-2); }
@media (min-width: 1200px) { .nav-links > li > a, .nav-drop-btn { white-space: nowrap; } }
.nav-links > li > a,
.nav-drop-btn {
  font-size: var(--t-small); font-weight: 500; color: var(--ink-soft);
  text-decoration: none; padding: .4rem 0; display: inline-flex; align-items: center; gap: .3rem;
}
.nav-links > li > a:hover, .nav-drop-btn:hover { color: var(--ink); }
.nav-links > li > a[aria-current='page'],
.nav-drop-btn[aria-current='page'] { color: var(--ink); font-weight: 600; }
/* .nav-links > li > a out-specifies .btn-gold, so the button colour has to be
   restated here or the gold CTA inherits slate type and drops to 4.2:1. */
.nav-links > li > a.btn-gold { color: var(--ink-on-gold); }
.nav-links > li > a.btn-sky { color: var(--white); }
.nav-links .btn { padding: .6rem 1.05rem; font-size: var(--t-small); }

.nav-drop { position: relative; }
.nav-drop-btn::after { content: '⌄'; font-size: .8em; transform: translateY(-2px); }
.nav-drop-panel {
  position: absolute; top: calc(100% + .6rem); left: -1rem; z-index: 10;
  width: 420px; padding: .6rem;
  background: var(--white); border: 1px solid var(--line); border-radius: var(--r-m);
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity 160ms ease, transform 160ms ease, visibility 160ms;
}
.nav-drop.is-open .nav-drop-panel { opacity: 1; visibility: visible; transform: none; }
.nav-drop-panel a {
  display: grid; grid-template-columns: auto 1fr; gap: .1rem .7rem; align-items: start;
  padding: .6rem .75rem; border-radius: var(--r-s);
  text-decoration: none; color: var(--ink);
}
/* The last row is "How the four fit together", which has no product mark and
   so has no first column to sit in. */
.nav-drop-panel > a { grid-template-columns: 1fr; }
.nav-drop-text { display: grid; gap: .1rem; min-width: 0; }
.nav-drop-panel a strong { font-size: var(--t-body); }
.nav-drop-panel a span { font-size: var(--t-small); color: var(--ink-quiet); }
.nav-drop-panel a:hover { background: var(--mist); }

/* ----------------------------------------------------------- product marks

   One square raster on a white ground per product, drawn as a chip. See
   productMark() in partials/chrome.js for why it is raster and why the ground
   is opaque rather than transparent.

   The chip is what makes one file work in both themes and on the navy footer:
   the ground stays white, and the hairline around it comes from a token, so a
   mark never sits directly on a colour it was not drawn for. --prod-mark is
   the drawn size, set per call site.
*/
.prod-mark {
  display: block; flex: none;
  width: var(--prod-mark, 40px); height: var(--prod-mark, 40px);
  border-radius: var(--r-s);
  border: 1px solid var(--line);
  background: var(--mark-ground);
  overflow: hidden;
}
.prod-mark img {
  display: block; width: 100%; height: 100%;
  /* The source already carries its own optical padding, so the image fills
     the chip rather than being inset twice. */
  object-fit: contain;
}
/* On navy the hairline would sink into the ground, and a white chip needs no
   help separating from navy — so it goes. */
.site-footer .prod-mark, .tone-navy .prod-mark { border-color: transparent; }

/*
  Track markers in the Services dropdown. Operating track: gold hairline
  (same accent as the logo mark). Investor track: sky hairline so EdgeSignal
  reads as a sibling group, not an ungrouped leftover.
*/
.nav-drop-group {
  font-family: var(--font); font-size: var(--t-micro); font-weight: 500;
  letter-spacing: .11em; text-transform: uppercase; color: var(--ink-quiet);
  padding: .75rem .9rem .3rem;
}
.nav-drop-group:first-child { padding-top: .4rem; }
.nav-drop-start { border-left: 2px solid var(--gold-400); }
.nav-drop-start a strong { color: var(--navy-900); }
.nav-drop-invest { border-left: 2px solid var(--sky-500); }
.nav-drop-invest a strong { color: var(--navy-900); }

.mobile-sub-group {
  font-family: var(--font); font-size: var(--t-micro); font-weight: 500;
  letter-spacing: .11em; text-transform: uppercase; color: var(--ink-quiet);
  padding: .9rem 0 .2rem;
}
.mobile-sub-group:first-child { padding-top: .3rem; }

.mobile-toggle { display: none; width: 44px; height: 44px; flex-direction: column; gap: 5px; align-items: center; justify-content: center; }
.mobile-toggle span { display: block; width: 22px; height: 2px; background: var(--ink); transition: transform 200ms var(--ease), opacity 200ms; }
.mobile-toggle[aria-expanded='true'] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.mobile-toggle[aria-expanded='true'] span:nth-child(2) { opacity: 0; }
.mobile-toggle[aria-expanded='true'] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.mobile-panel {
  display: none; position: fixed; inset: 72px 0 0; z-index: 99;
  background: var(--white); padding: var(--s-3) var(--gutter) var(--s-6);
  overflow-y: auto; flex-direction: column; gap: .25rem;
}
.mobile-panel.is-open { display: flex; }
.mobile-panel > a, .mobile-panel .sub-toggle {
  padding: .9rem 0; font-size: 1.05rem; font-weight: 500;
  border-bottom: 1px solid var(--line); text-decoration: none; color: var(--ink); text-align: left; width: 100%;
}
.mobile-panel .btn { margin-top: var(--s-3); border-bottom: 0; justify-content: center; }
/* `.mobile-panel > a` (0,1,1) out-specifies `.btn-gold` (0,1,0), so without
   this the drawer's primary CTA takes --ink. In light mode --ink is navy and
   it looks correct by accident; in dark mode it is near-white on gold, which
   measured 1.41:1. Same trap, same fix as `.nav-links > li > a.btn-gold`. */
.mobile-panel > a.btn-gold { color: var(--ink-on-gold); }
.mobile-panel > a.btn-gold:hover { color: var(--ink-on-gold); }
.mobile-sub { display: none; padding-left: var(--s-2); }
.mobile-sub.is-open { display: block; }
.mobile-sub a {
  display: flex; align-items: center; gap: .6rem;
  padding: .65rem 0; font-size: var(--t-body); color: var(--ink-soft); text-decoration: none;
}

@media (max-width: 1040px) {
  .nav-links { display: none; }
  .mobile-toggle { display: flex; }
  .logo-img { width: 164px; }
}

/* At 320px the logo, the theme control and its word, and the 44px menu button
   added up to 343px inside a 320px viewport, so every page scrolled sideways.
   The theme word is already aria-hidden — it is decoration — so it is the
   first thing to go, and the menu button keeps its 44px target. */
@media (max-width: 380px) {
  .container { padding-inline: 1rem; }
  .logo-img { width: 132px; }
  .header-tools { gap: .25rem; margin-inline-start: 0; }
  .theme-toggle { padding: 0 8px; min-width: 38px; gap: 0; }
  .theme-toggle-copy { display: none; }
}

/* Scroll progress — one hairline, top of the viewport. */
.scroll-progress {
  position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 101;
  background: linear-gradient(90deg, var(--sky-600), var(--gold-400));
  transform: scaleX(0); transform-origin: 0 50%;
}

/* ---------------------------------------------------------------- hero */
.hero { position: relative; padding-block: clamp(3.5rem, 8vw, 6.5rem) var(--section); overflow: hidden; }
.hero-grid { display: grid; grid-template-columns: 1.05fr .95fr; gap: clamp(2rem, 5vw, 4rem); align-items: center; }
.hero h1 { font-size: var(--t-display); font-weight: 700; margin: var(--s-2) 0 var(--s-3); }
.hero .lead { max-width: 60ch; margin-bottom: var(--s-4); }
.hero-note { margin-top: var(--s-3); font-size: var(--t-small); color: var(--ink-quiet); }

/* The mark, very large and very quiet, behind the hero. Not a gradient blob. */
.hero-mark {
  position: absolute; right: -6%; top: -12%; width: min(52vw, 720px);
  opacity: .05; pointer-events: none; z-index: 0;
}
.hero-grid { position: relative; z-index: 1; }
@media (max-width: 900px) {
  .hero-grid { grid-template-columns: 1fr; }
  .hero-mark { opacity: .04; }
}

/*
  Homepage full-bleed photo hero. Image fills the section; copy sits on the
  left with a scrim so the production-ready line stays readable.
  Type uses on-navy tokens — the photo is dark in both themes; --white would
  flip in dark mode and vanish.
*/
.hero-bleed {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: flex-start;
  min-height: min(88vh, 820px);
  padding-top: clamp(5rem, 12vw, 8.5rem);
  padding-bottom: clamp(5.5rem, 11vw, 8rem);
  color: var(--on-navy);
  overflow: hidden;
  /* Dark fallback so any sub-pixel gap reads as navy, not page surface. */
  background: var(--ink-on-gold);
  /* Above the fixed spine so --line cannot cut through the photo. */
  z-index: 2;
}
.hero-bleed-media {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}
/* Single hero photo — same frame in light and dark mode. */
.hero-bleed-photo {
  position: absolute;
  inset: 0;
  margin: 0;
}
.hero-bleed-photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 68% 42%;
  /* Avoid inline-img baseline gap that can flash as a light hairline. */
  vertical-align: top;
}
.hero-bleed-scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(90deg,
      color-mix(in srgb, var(--ink-on-gold) 94%, transparent) 0%,
      color-mix(in srgb, var(--ink-on-gold) 86%, transparent) 32%,
      color-mix(in srgb, var(--ink-on-gold) 55%, transparent) 58%,
      color-mix(in srgb, var(--ink-on-gold) 22%, transparent) 100%),
    linear-gradient(180deg,
      color-mix(in srgb, var(--ink-on-gold) 48%, transparent) 0%,
      transparent 30%,
      transparent 70%,
      color-mix(in srgb, var(--ink-on-gold) 62%, transparent) 100%);
}
.hero-bleed-copy {
  position: relative;
  z-index: 2;
  box-sizing: border-box;
  /* Wide enough that the three-sentence H1 lands on three lines at
     desktop width instead of five in a narrow strip. */
  width: min(52rem, 100%);
  max-width: 100%;
  margin: 0;
  /* Match the site container’s left edge, not a centred flex item. */
  padding-left: max(var(--gutter), calc((100vw - var(--container)) / 2));
  padding-right: var(--gutter);
  text-align: left;
}
/* The hero with the film in it: copy left, player right. The photograph
   stays as texture only, under a heavier scrim, so the film is the subject. */
.hero-has-film { justify-content: center; }
.hero-has-film .hero-bleed-scrim {
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--ink-on-gold) 95%, transparent) 0%,
    color-mix(in srgb, var(--ink-on-gold) 86%, transparent) 100%);
}
.hero-bleed-grid {
  position: relative; z-index: 2; box-sizing: border-box; width: 100%;
  padding-inline: max(var(--gutter), calc((100vw - var(--container)) / 2));
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.08fr);
  gap: clamp(2rem, 4vw, 4rem); align-items: center;
}
.hero-bleed-grid .hero-bleed-copy { width: auto; padding: 0; }
.hero-film .xvid-frame { border-color: color-mix(in srgb, var(--on-navy-quiet) 45%, transparent); }
.hero-film-label {
  margin: 0 0 .7rem; font-size: var(--t-micro); font-weight: 600; letter-spacing: .1em;
  text-transform: uppercase; color: var(--on-navy-quiet);
}
.hero-bleed .xvid-caption-compact, .hero-bleed .xvid-caption-compact a, .hero-path a { color: var(--on-navy); }
.hero-path { margin: 1.1rem 0 0; font-size: var(--t-small); color: var(--on-navy-quiet); }
@media (max-width: 980px) {
  .hero-bleed-grid { grid-template-columns: 1fr; }
}
.hero-bleed .eyebrow { color: var(--on-navy-quiet); }
.hero-bleed .eyebrow::before { background: var(--gold-400); }
.hero-bleed h1 { color: var(--tone-navy-ink); text-wrap: balance; }
.hero-bleed .lead {
  color: color-mix(in srgb, var(--on-navy) 92%, transparent);
  max-width: 52ch;
}
.hero-bleed .hero-note {
  color: color-mix(in srgb, var(--on-navy) 72%, transparent);
  max-width: 42ch;
}
.hero-bleed-outline {
  background: transparent;
  /* Strong enough to read as a real action over the photo, not a ghost. */
  border-color: color-mix(in srgb, var(--on-navy) 80%, transparent);
  color: var(--on-navy);
}
.hero-bleed-outline:hover {
  border-color: var(--on-navy);
  color: var(--tone-navy-ink);
  background: color-mix(in srgb, var(--on-navy) 10%, transparent);
}
.hero-bleed .awsb-strip {
  background: transparent;
  border-color: color-mix(in srgb, var(--on-navy) 28%, transparent);
  color: color-mix(in srgb, var(--on-navy) 88%, transparent);
}
.hero-bleed .awsb-proof,
.hero-bleed .awsb-proof li {
  color: inherit;
}
/* Space between the photo hero and the tech strip — was flush with pt-0.
   Beats .section.is-tight’s padding-block so the gap actually lands. */
.section.is-tight.hero-follow {
  padding-top: clamp(3.5rem, 8vw, 6rem);
}
@media (max-width: 720px) {
  .hero-bleed { min-height: min(84vh, 680px); }
  .hero-bleed-copy {
    padding-left: var(--gutter);
  }
  .hero-bleed-scrim {
    background:
      linear-gradient(180deg,
        color-mix(in srgb, var(--ink-on-gold) 72%, transparent) 0%,
        color-mix(in srgb, var(--ink-on-gold) 84%, transparent) 45%,
        color-mix(in srgb, var(--ink-on-gold) 92%, transparent) 100%),
      linear-gradient(90deg,
        color-mix(in srgb, var(--ink-on-gold) 55%, transparent) 0%,
        color-mix(in srgb, var(--ink-on-gold) 25%, transparent) 100%);
  }
  .hero-bleed-photo img { object-position: 72% 35%; }
  /* Two stacked hero buttons at two different widths read as clutter;
     full width makes them one column of equal targets. */
  .hero-bleed-copy .actions .btn { width: 100%; }
}

/* ---------------------------------------------------------------- tech strip */
.tech-strip {
  display: flex; flex-wrap: wrap; gap: .4rem 1.75rem; align-items: center;
  padding-block: var(--s-2); border-block: 1px solid var(--line);
}
.tech-strip span {
  font-size: var(--t-small); font-weight: 500; color: var(--ink-quiet);
  letter-spacing: .02em;
}
.tech-points {
  display: flex; flex-wrap: wrap; gap: .4rem .9rem;
  margin: var(--s-2) 0 0; padding: 0; list-style: none;
  font-size: var(--t-small); color: var(--ink);
}
.tech-points li { position: relative; padding-left: .85rem; }
.tech-points li::before {
  content: ''; position: absolute; left: 0; top: .55em;
  width: 5px; height: 5px; border-radius: 50%; background: var(--sky-600);
}
/* "Your tools aren't the problem" — the copy block that opens the homepage's
   argument. It was .funnel-intro, named for the scroll-scrubbed funnel it used
   to introduce; that section is gone and the name went with it. */
.sprawl-intro .sec-head { margin-bottom: var(--s-2); }
.sprawl-intro .sec-head h2 { margin-bottom: .4rem; max-width: 24ch; }
.sprawl-intro-split { margin-bottom: var(--s-3); align-items: start; }
.sprawl-intro-split .sec-head { margin-bottom: 0; }
.sprawl-intro-accent {
  margin: .85rem 0 0;
  max-width: 42ch;
  font-weight: 600;
  color: var(--ink);
}

/* Intro estate schematic — replaces the glass-facade photo in this section only. */
.estate-sketch {
  margin: 0;
  padding: 1.15rem 1.25rem 1.25rem;
  border: 1px solid var(--line);
  border-radius: var(--r-m);
  background: var(--white);
}
.estate-sketch-kicker {
  margin: 0 0 .85rem;
  font-family: var(--font);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--sky-700);
}
.estate-sketch-tools {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: .55rem .65rem;
}
.estate-sketch-tool {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .35rem;
  font-size: var(--t-micro);
  color: var(--ink-soft);
  text-align: center;
}
.estate-sketch-plate {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  border: 1px solid var(--line-strong);
  background: var(--mist);
}
.estate-sketch-link {
  margin: .85rem 0 0;
  text-align: center;
}
.estate-sketch-arrow {
  width: 1px;
  height: 1.1rem;
  margin: .7rem auto;
  background: var(--sky-600);
  position: relative;
}
.estate-sketch-arrow::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -1px;
  width: 7px;
  height: 7px;
  border-right: 1.5px solid var(--sky-600);
  border-bottom: 1.5px solid var(--sky-600);
  transform: translateX(-50%) rotate(45deg);
}
.estate-sketch-control {
  padding: .85rem 1rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-s);
  background: var(--mist);
  text-align: center;
}
.estate-sketch-brand {
  margin: 0;
  font-size: var(--t-body);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--navy-900);
}
.estate-sketch-verbs {
  list-style: none;
  margin: .45rem 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: .35rem .75rem;
  font-family: var(--font);
  font-size: var(--t-micro);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--sky-700);
}
.estate-sketch-path {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: .35rem .45rem;
  padding: .7rem .85rem;
  border: 1px solid var(--line);
  border-radius: var(--r-s);
  background: var(--white);
  font-size: var(--t-small);
  font-weight: 600;
  color: var(--navy-900);
}
.estate-sketch-path span[aria-hidden='true'] {
  color: var(--sky-600);
  font-weight: 500;
}
.estate-sketch-path-git {
  display: inline-block;
  padding: .15rem .45rem;
  border-radius: 6px;
  background: var(--gold-400);
  color: var(--ink-on-gold);
  font-weight: 700;
}
.estate-sketch-outcome {
  margin: .85rem 0 0;
  text-align: center;
  font-size: var(--t-micro);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

@media (max-width: 900px) {
  .estate-sketch-tools { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.cost-compound-split {
  margin-bottom: var(--s-4);
  align-items: start;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 0.65fr);
}
.cost-compound-split .sec-head { margin-bottom: 0; }
.cost-compound-split .photo.photo-aside {
  max-width: 340px;
  margin-inline-start: auto;
}
.cost-compound-split .photo.photo-aside img {
  max-height: 280px;
}
@media (max-width: 900px) {
  .cost-compound-split { grid-template-columns: 1fr; }
  .cost-compound-split .photo.photo-aside {
    max-width: 420px;
    margin-inline: 0;
  }
  .cost-compound-split .photo.photo-aside img { max-height: 260px; }
}

/* The hire-bridge photograph. photo-aside caps height at 520px, which a 3:2
   landscape never reaches in this column; this keeps it tied to the top of the
   copy beside it instead of centring in a taller grid row. */
.hire-intro-split { align-items: start; }
.hire-intro-split .sec-head { margin-bottom: 0; }

/* Side photos next to section copy — soft crop, no card chrome. */
.photo.photo-aside img {
  border-radius: var(--r-m);
  max-height: min(520px, 68vh);
}

/* Kyndryl-style faded atmosphere strip between sections. Decorative. */
.photo-band {
  position: relative;
  height: clamp(120px, 18vw, 200px);
  overflow: hidden;
  margin: 0;
  pointer-events: none;
}
.photo-band picture,
.photo-band img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center bottom;
}
.photo-band img { opacity: .48; }
.photo-band::before,
.photo-band::after {
  content: '';
  position: absolute;
  left: 0; right: 0;
  z-index: 1;
  height: 42%;
  pointer-events: none;
}
.photo-band::before {
  top: 0;
  background: linear-gradient(to bottom, var(--surface) 0%, transparent 100%);
}
.photo-band::after {
  bottom: 0;
  background: linear-gradient(to top, var(--surface) 0%, transparent 100%);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .photo-band img { opacity: .34; }
}
:root[data-theme='dark'] .photo-band img { opacity: .34; }
@media (max-width: 900px) {
  .photo-band { height: clamp(110px, 32vw, 180px); }
  .photo.photo-aside img { max-height: 360px; }
}

/* After the gap scrub: fade mist → navy before the quiz CTA. */
.photo-band--after-gap {
  height: clamp(140px, 22vw, 240px);
  background: var(--mist);
}
.photo-band--after-gap img {
  object-position: center 40%;
}
.photo-band--after-gap::before {
  background: linear-gradient(to bottom, var(--mist) 0%, transparent 100%);
}
.photo-band--after-gap::after {
  background: linear-gradient(to top, var(--tone-navy-bg) 0%, transparent 100%);
}

/*
  "Start here" cards. The signal is a gold rule across the top plus a small
  label — gold as a shape, never as type: --gold-600 is the only gold that
  clears AA on white and only at display sizes, which a 12px label is not.
*/
.card.is-start { border-color: var(--line-strong); position: relative; }
.card.is-start::before {
  content: ''; position: absolute; inset: -1px -1px auto -1px; height: 3px;
  background: var(--gold-400); border-radius: var(--r-m) var(--r-m) 0 0;
}
.start-flag {
  display: block; margin-bottom: .5rem;
  font-family: var(--font); font-size: var(--t-micro); font-weight: 500;
  letter-spacing: .11em; text-transform: uppercase; color: var(--ink-quiet);
}

/* ---------------------------------------------------------------- service list */
.service-list { border-top: 1px solid var(--line); }
.service-row {
  display: grid; grid-template-columns: minmax(150px, 210px) 1fr auto;
  gap: var(--s-3); align-items: baseline;
  padding: var(--s-3) 0; border-bottom: 1px solid var(--line);
  text-decoration: none; color: inherit; position: relative;
  transition: border-color var(--dur-fast) ease;
}
.service-row:hover { border-color: var(--hover-border); }
/* The two starting offers carry a gold rule down their left edge. */
.service-row.is-start { padding-left: 1rem; }
.service-row.is-start::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--gold-400);
}
.service-row strong { font-size: var(--t-h3); letter-spacing: -0.02em; }
.service-row:hover strong { color: var(--hover-ink); }
.service-row p { font-size: var(--t-small); color: var(--ink-quiet); margin: 0; }
.service-row .arrow { color: var(--sky-700); transition: transform var(--dur-fast) ease; }
.service-row:hover .arrow { transform: translateX(4px); }
@media (max-width: 700px) {
  .service-row { grid-template-columns: 1fr auto; }
  .service-row p { grid-column: 1 / -1; }
}

/* ---------------------------------------------------------------- steps */
.steps { display: grid; gap: var(--s-3); counter-reset: step; }
.steps > * {
  border-top: 2px solid var(--line); padding-top: var(--s-2);
  transition: border-color var(--dur-fast) ease;
}
.steps > *:hover { border-color: var(--hover-border); }
.step-num {
  font-family: var(--font); font-size: var(--t-micro); font-weight: 600;
  letter-spacing: .12em; color: var(--sky-700); margin-bottom: .4rem;
}
.tone-navy .step-num { color: var(--gold-400); }

/* Dimension annotation, borrowed from engineering drawings: ← 5 DAYS → */
.dimension {
  display: inline-flex; align-items: center; gap: .5rem;
  font-family: var(--font); font-size: var(--t-micro); letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-quiet);
}
.dimension::before, .dimension::after {
  content: ''; width: 26px; height: 1px; background: var(--line-strong);
}

/* ---------------------------------------------------------------- tables */
.table-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--r-m); background: var(--white); }
table.data { font-size: var(--t-small); }
table.data th, table.data td { text-align: left; padding: .85rem 1rem; border-bottom: 1px solid var(--line); vertical-align: top; }
table.data thead th {
  font-size: var(--t-micro); text-transform: uppercase; letter-spacing: .1em;
  color: var(--ink-quiet); font-weight: 600; background: var(--mist); white-space: nowrap;
}
table.data tbody tr { transition: background var(--dur-fast) ease; }
table.data tbody tr:hover { background: var(--mist); }
table.data tbody tr:last-child td { border-bottom: 0; }
table.data td:first-child { font-weight: 600; color: var(--ink); }
table.data .muted { color: var(--ink-quiet); font-weight: 400; }

/* ---------------------------------------------------------------- CTA panel */
.cta-panel {
  background: var(--tone-navy-bg); color: var(--tone-navy-ink);
  border-radius: var(--r-l); padding: clamp(2rem, 5vw, 3.5rem);
  position: relative; overflow: hidden;
  --hover-border: var(--gold-400);
  --hover-ink: var(--gold-400);
}
.cta-panel::before {
  content: ''; position: absolute; left: clamp(2rem, 5vw, 3.5rem); top: 0;
  width: 56px; height: 4px; background: var(--gold-400);
}
/* A CTA panel with a photograph beside the copy.
   Photo column shares height with the copy so a short square does not float
   with empty band underneath. */
.cta-split {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(280px, 0.95fr);
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: stretch;
}
.cta-split .photo {
  display: flex; min-height: 0; height: 100%;
}
.cta-split .photo img {
  flex: 1; width: 100%; height: 100%; min-height: 320px;
  aspect-ratio: auto; object-fit: cover;
}
@media (max-width: 860px) {
  .cta-split { grid-template-columns: 1fr; }
  .cta-split .photo img { min-height: 260px; aspect-ratio: 4 / 3; height: auto; }
}

.cta-panel h2 { color: var(--tone-navy-ink); margin-bottom: .75rem; max-width: 20ch; }
.cta-panel .eyebrow { color: var(--gold-400); }
.cta-panel .eyebrow::before { background: var(--gold-400); }
.cta-panel p { color: var(--on-navy-quiet); max-width: 58ch; margin-bottom: var(--s-3); }
.cta-panel strong { color: var(--tone-navy-ink); }
.cta-panel a:not(.btn) { color: var(--gold-400); }
.cta-panel .btn-ghost { color: var(--gold-400); }

/* ---------------------------------------------------------------- footer */
.site-footer { background: var(--tone-navy-bg); color: var(--on-navy-quiet); padding-block: var(--s-6) var(--s-4); }
/* Five link columns since the free tools got one of their own; below 1100px
   the brand takes a row to itself so the columns keep their width. */
.footer-grid { display: grid; grid-template-columns: 1.6fr repeat(5, 1fr); gap: var(--s-4); }
@media (max-width: 1100px) { .footer-grid { grid-template-columns: repeat(3, 1fr); } .footer-brand { grid-column: 1 / -1; } }
/* Legal and Contact share the last column, two short lists one above the other. */
.site-footer .footer-h3-stacked { margin-top: var(--s-3); }
.footer-brand .logo-img { width: 200px; margin-bottom: var(--s-2); }
.footer-brand p { font-size: var(--t-small); max-width: 34ch; }
/* h3, not h4: the page above ends at h2, and jumping to h4 skipped a level on
   every page. The size is set here, so the level is free to be correct. */
.site-footer h3 { font-size: var(--t-micro); text-transform: uppercase; letter-spacing: .12em; color: var(--tone-navy-ink); margin-bottom: .9rem; }
.site-footer li { margin-bottom: .5rem; }
.site-footer a { color: var(--on-navy-quiet); text-decoration: none; font-size: var(--t-small); }
/* Only the four service rows carry a mark; everything else in the column is a
   plain link and keeps its own line height. */
.site-footer li a:has(.prod-mark) { display: flex; align-items: center; gap: .5rem; }
.site-footer a:hover { color: var(--gold-400); }
.footer-bottom {
  margin-top: var(--s-5); padding-top: var(--s-3); border-top: 1px solid var(--navy-line);
  display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4); justify-content: space-between;
}
.footer-bottom p { font-size: var(--t-micro); color: var(--on-navy-faint); }
@media (max-width: 900px) { .footer-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .footer-grid { grid-template-columns: 1fr; } }

/* ---------------------------------------------------------------- spine */
/* A hairline down the document; the fill tracks scroll. Each section is a node.
   z-index stays under the photo hero (and the sticky header) so the light
   --line colour cannot flash as a white stripe through dark full-bleed art. */
.spine { position: fixed; left: max(1.25rem, calc((100vw - var(--container)) / 2 - 2.2rem)); top: 0; bottom: 0; width: 2px; z-index: 1; pointer-events: none; }
.spine-base { position: absolute; inset: 0; background: linear-gradient(180deg, transparent, var(--line) 8%, var(--line) 88%, transparent); }
.spine-fill {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, var(--sky-500), var(--sky-600) 45%, var(--gold-400));
  transform: scaleY(0); transform-origin: top center; /* scaled directly by motion.js */
}
@media (max-width: 1320px) { .spine { display: none; } }
/* Full-bleed photo hero: the light --line hairline reads as a white stripe
   through the art, so drop the spine on the homepage entirely. */
body[data-page='home'] .spine { display: none; }

/* ---------------------------------------------------------------- prose */
.prose { max-width: 68ch; }
.prose h2 { font-size: var(--t-h3); margin: var(--s-4) 0 .75rem; }
.prose h3 { font-size: var(--t-lead); margin: var(--s-3) 0 .5rem; }
.prose p { margin-bottom: var(--s-2); color: var(--ink-soft); }
.prose ul { margin: 0 0 var(--s-2); display: grid; gap: .5rem; }
.prose ul li { padding-left: 1.35rem; position: relative; color: var(--ink-soft); font-size: var(--t-body); }
.prose ul li::before { content: ''; position: absolute; left: 0; top: .62em; width: 7px; height: 7px; border-radius: 2px; background: var(--gold-400); }
.prose code { font-family: var(--mono); font-size: .92em; background: var(--mist); padding: .1em .35em; border-radius: 4px; }

/* Included / excluded, at equal visual weight. Exclusions are a selling point. */
.io-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-3); }
.io-col {
  border: 1px solid var(--line); border-radius: var(--r-m); padding: var(--s-3); background: var(--white);
  transition: border-color var(--dur-fast) ease;
}
.io-col:hover { border-color: var(--hover-border); }
.io-col h3 { font-size: var(--t-lead); margin-bottom: .9rem; }
.io-col ul { display: grid; gap: .55rem; }
.io-col li { font-size: var(--t-small); color: var(--ink-soft); padding-left: 1.3rem; position: relative; }
.io-col.is-in li::before { content: ''; position: absolute; left: 0; top: .55em; width: 8px; height: 8px; border-radius: 999px; background: var(--sky-600); }
.io-col.is-out li::before { content: ''; position: absolute; left: 1px; top: .78em; width: 9px; height: 1.5px; background: var(--slate-500); }
@media (max-width: 700px) { .io-grid { grid-template-columns: 1fr; } }

/* ---------------------------------------------------------------- service rail */
.rail-layout { display: grid; grid-template-columns: 1fr 320px; gap: clamp(2rem, 5vw, 4rem); align-items: start; }
.rail {
  position: sticky; top: 96px;
  border: 1px solid var(--line); border-radius: var(--r-m); background: var(--white); padding: var(--s-3);
}
.rail dl { display: grid; gap: .9rem; margin-bottom: var(--s-3); }
.rail dt { font-size: var(--t-micro); text-transform: uppercase; letter-spacing: .1em; color: var(--ink-quiet); font-weight: 600; }
.rail dd { font-size: var(--t-small); color: var(--ink); font-weight: 600; }
.rail .btn { width: 100%; }
.rail-note { margin-top: .9rem; font-size: var(--t-micro); color: var(--ink-quiet); }
@media (max-width: 1000px) {
  .rail-layout { grid-template-columns: 1fr; }
  .rail { position: static; order: -1; }
}

/* Product-page hero: ring beside the copy. Side is set by data-ring-side on
   .service-hero — flip SERVICE_RING_SIDE in scripts/pages/services.js:
     end    = ring on the right (default)
     start  = ring on the left
     center = stacked under the lead (old layout) */
/* The product mark leads the hero, with the eyebrow beside it. They share a
   baseline rather than stacking, so the badge does not push the H1 down a
   line on a phone. */
.service-mark-row { display: flex; align-items: center; gap: .75rem; }
.service-mark-row .eyebrow { margin: 0; }

/* The four cards on /services. The mark and the name are one header row; the
   description keeps the card's own measure underneath. */
.offer-card-head {
  display: flex; align-items: center; gap: .8rem;
  margin-bottom: .6rem;
}
.offer-card-head .card-num { margin-bottom: .1rem; }
.offer-card-head h2 { margin: 0; }

.service-hero {
  margin-bottom: clamp(1.75rem, 4vw, 2.75rem);
}
.service-hero-copy .lead {
  max-width: 54ch;
}
.service-hero-copy h1 {
  /* Wide enough that the title sits as a block next to the ring, not a
     tall stack of short lines that leave the ring floating above it. */
  max-width: 28ch;
}
.service-ring {
  max-width: 340px;
  width: 100%;
}

.service-hero[data-ring-side='end'],
.service-hero[data-ring-side='start'] {
  display: grid;
  gap: clamp(1.5rem, 3vw, 2.75rem);
  align-items: start;
}
.service-hero[data-ring-side='end'] .service-ring,
.service-hero[data-ring-side='start'] .service-ring {
  /* Sit the drawing beside the title, not the eyebrow */
  margin-top: 1.85rem;
}
.service-hero[data-ring-side='end'] {
  grid-template-columns: minmax(0, 1fr) minmax(240px, 320px);
}
.service-hero[data-ring-side='end'] .service-hero-copy { grid-column: 1; grid-row: 1; }
.service-hero[data-ring-side='end'] .service-ring { grid-column: 2; grid-row: 1; }

.service-hero[data-ring-side='start'] {
  grid-template-columns: minmax(240px, 320px) minmax(0, 1fr);
}
.service-hero[data-ring-side='start'] .service-ring { grid-column: 1; grid-row: 1; }
.service-hero[data-ring-side='start'] .service-hero-copy { grid-column: 2; grid-row: 1; }

.service-hero[data-ring-side='center'] {
  display: block;
}
.service-hero[data-ring-side='center'] .service-ring {
  max-width: 420px;
  margin: 1.5rem auto 0;
}
.service-hero[data-ring-side='center'] .ring-wrap.is-compact {
  max-width: 420px;
}
.service-hero[data-ring-side='center'] .ring-wrap.is-compact .ring-legend {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.service-hero[data-ring-side='center'] .ring-wrap.is-compact .ring-legend a {
  display: block; text-align: center;
}
.service-hero[data-ring-side='center'] .ring-wrap.is-compact .ring-legend b {
  display: block; margin-bottom: .15rem;
}
.service-hero[data-ring-side='center'] .ring-wrap.is-compact .ring-legend span::before {
  content: none;
}
.service-hero[data-ring-side='center'] .service-hero-copy .lead {
  max-width: 68ch;
}
.service-hero[data-ring-side='center'] .service-hero-copy h1 {
  max-width: none;
}

.service-page { min-width: 0; overflow-x: clip; }

/* Match the mobile-nav breakpoint so a hamburger viewport does not keep a
   cramped two-column hero with the ring stranded above the title. */
@media (max-width: 1040px) {
  .service-hero[data-ring-side='end'],
  .service-hero[data-ring-side='start'] {
    grid-template-columns: 1fr;
    align-items: start;
  }
  .service-hero[data-ring-side='end'] .service-ring,
  .service-hero[data-ring-side='start'] .service-ring {
    grid-column: 1;
    grid-row: auto;
    max-width: 300px;
    margin-inline: auto;
    order: 2;
  }
  .service-hero[data-ring-side='end'] .service-hero-copy,
  .service-hero[data-ring-side='start'] .service-hero-copy {
    grid-column: 1;
    grid-row: auto;
    order: 1;
  }
  .service-hero-copy h1 { max-width: 22ch; }
  .service-hero-copy .lead { max-width: 68ch; }
}

/* Floating triage CTA — follows the reader on the three operating products.
   Starts .is-away until the ring has scrolled past (see js/app.js). */
.float-cta {
  position: fixed;
  right: max(1rem, env(safe-area-inset-right));
  bottom: max(1rem, env(safe-area-inset-bottom));
  z-index: 80;
  width: min(18.5rem, calc(100vw - 2rem));
  padding: .9rem .95rem 1rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-m);
  background: var(--white);
  display: grid;
  gap: .65rem;
  transition: opacity 200ms ease, transform 200ms ease;
}
.float-cta.is-away {
  visibility: hidden;
  opacity: 0;
  transform: translateY(12px);
  pointer-events: none;
}
.float-cta-product {
  margin: 0;
  display: flex; align-items: center; gap: .5rem;
  font-family: var(--font); font-size: var(--t-micro); font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase; color: var(--sky-700);
}
.float-cta-facts { margin: 0; display: grid; gap: .5rem; }
.float-cta-facts dt {
  font-size: 10px; text-transform: uppercase; letter-spacing: .1em;
  color: var(--ink-quiet); font-weight: 600; margin: 0 0 .12rem;
}
.float-cta-facts dd {
  margin: 0; font-size: var(--t-small); color: var(--ink); font-weight: 600; line-height: 1.35;
}
.float-cta .btn { width: 100%; justify-content: center; text-align: center; }

@media (min-width: 1100px) {
  /* Keep long-form copy clear of the docked card once it is on screen. */
  body:has(.float-cta:not(.is-away)) .service-page {
    padding-right: 20rem;
  }
}

/* A full facts card has no reserved column below 1100px. Use the compact
   dock throughout that range, including tablets and landscape phones. */
@media (max-width: 1099px) {
  .float-cta {
    left: max(.75rem, env(safe-area-inset-left));
    right: max(.75rem, env(safe-area-inset-right));
    bottom: max(.75rem, env(safe-area-inset-bottom));
    width: auto;
    padding: .75rem .85rem;
    gap: .5rem;
  }
  .float-cta-facts { display: none; }
  body:has(.float-cta) {
    padding-bottom: 5rem;
  }
}

@media (min-width: 641px) and (max-width: 1099px) {
  .float-cta { grid-template-columns: minmax(0, 1fr) auto; align-items: center; }
  .float-cta .btn { width: auto; }
}

@media (prefers-reduced-motion: reduce) {
  .float-cta { transition: opacity 1ms linear; }
}

@media print {
  .float-cta { display: none; }
}

/* ---------------------------------------------------------------- forms */
.field { display: grid; gap: .4rem; margin-bottom: var(--s-2); }
.field label { font-size: var(--t-small); font-weight: 600; }
.field input, .field textarea, .field select {
  border: 1px solid var(--line-strong); border-radius: var(--r-s);
  padding: .7rem .85rem; background: var(--white); font-size: var(--t-body);
  /* A <select> sizes to its longest option and an <input> defaults to about
     twenty characters, neither of which knows how wide the column is. Without
     this the contact form pushes the page sideways on a phone. */
  width: 100%; max-width: 100%; min-width: 0; box-sizing: border-box;
  transition: border-color var(--dur-fast) ease, background var(--dur-fast) ease;
}
.field input:hover, .field textarea:hover, .field select:hover { border-color: var(--hover-border); }
.field input:focus, .field textarea:focus, .field select:focus { border-color: var(--hover-border); outline: 2px solid transparent; }
.field textarea { min-height: 130px; resize: vertical; }
.hp { position: absolute; left: -9999px; }

/* ---------------------------------------------------------------- misc */
.rule { height: 1px; background: var(--line); border: 0; margin-block: var(--s-4); }
/* The facts strip under the company page's lead. */
.company-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--s-2) var(--s-3); margin: var(--s-3) 0 0; padding: var(--s-3) 0 0; border-top: 1px solid var(--line); }
.company-facts div { display: grid; gap: .25rem; align-content: start; min-width: 0; }
.company-facts dd { overflow-wrap: anywhere; }
.company-facts dt { font-family: var(--font); font-size: var(--t-micro); font-weight: 500; letter-spacing: .11em; text-transform: uppercase; color: var(--ink-quiet); }
.company-facts dd { margin: 0; font-size: var(--t-body); }

.stat { display: grid; gap: .2rem; }
.stat b { font-size: var(--t-h2); font-weight: 700; letter-spacing: -0.03em; line-height: 1; }
.stat span { font-size: var(--t-small); color: var(--ink-quiet); }
.pill-row { display: flex; flex-wrap: wrap; gap: .5rem; }
.pill {
  font-size: var(--t-small); border: 1px solid var(--line); background: var(--white);
  border-radius: 999px; padding: .3rem .8rem; color: var(--ink-soft);
  transition: border-color var(--dur-fast) ease, color var(--dur-fast) ease;
}
.pill:hover { border-color: var(--hover-border); color: var(--ink); }
.no-js-note { display: none; }
html.no-js .no-js-note { display: block; }

/* ---------------------------------------------------- product marks */
/*
  The technology strip. Colour comes from the products themselves — it is the
  one place on the site where the palette is not ours, and that is the point:
  it says what we work in without us having to claim anything.
*/
.pstrip { display: flex; flex-wrap: wrap; gap: .5rem; }
.pchip {
  display: inline-flex; align-items: center; gap: .5rem;
  padding: .4rem .8rem .4rem .55rem;
  background: var(--white); border: 1px solid var(--line); border-radius: 999px;
  font-size: var(--t-small); font-weight: 500; color: var(--ink-soft);
  transition: border-color var(--dur-fast) ease;
}
.pchip:hover { border-color: var(--hover-border); }
.pchip-more {
  padding-left: .85rem; padding-right: .85rem;
  color: var(--sky-700); font-weight: 600; letter-spacing: .02em;
}
.pchip-more:hover { border-color: var(--hover-border); color: var(--hover-ink); }
.pmark { flex: none; }
/* Inside a chip the mark carries its own white tile: brand glyphs are drawn
   for light grounds and GitHub's near-black one vanished on a dark chip. */
.pchip .pmark { background: var(--mark-ground); color: var(--mark-ink); border-radius: 5px; padding: 2px; box-sizing: content-box; }
.tone-navy .pchip, .tone-mist .pchip { background: var(--white); }
/* A labelled row of marks beside prose that names specific products. */
.sp-marks { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem .9rem; margin-top: var(--s-3); }
.sp-marks-label { font-size: var(--t-micro); font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-soft); }
.tone-navy .pchip { background: var(--tone-navy-card); border-color: var(--navy-line); color: var(--on-navy); }

/* Marks sitting inside a diagram, on a white plate so brand colours stay legible. */
.plate { fill: var(--white); stroke: var(--line); stroke-width: 1; }

/*
  The HTML sibling of .plate: a tile behind a product mark wherever the mark
  sits directly on page surface rather than inside an SVG. --mark-ground is
  the token that stays white in both themes — brand glyphs are drawn for
  light grounds, and GitHub's near-black one disappears without this.
*/
.pplate {
  display: inline-grid; place-items: center; flex: none;
  width: 54px; height: 54px; border-radius: var(--r-s);
  background: var(--mark-ground); border: 1px solid var(--line);
}
.pplate-s { width: 32px; height: 32px; border-radius: 7px; }

/*
  The technology band: four stages a change passes through, left to right,
  joined by a rule with a gold marker so it reads as a path and not a logo
  wall. Two stages a row on a phone.
*/
.pplate { color: var(--mark-ink); }
.pplate-m { width: 40px; height: 40px; }
.pband {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--s-4);
}
.pband-stage { position: relative; min-width: 0; padding-top: var(--s-2); border-top: 2px solid var(--line-strong); }
.pband-stage::after {
  content: ""; position: absolute; top: -6px; right: calc(var(--s-4) * -.5 - 5px);
  width: 10px; height: 10px; border-radius: 50%; background: var(--gold-400);
}
.pband-stage:last-child::after { display: none; }
.pband-label {
  display: flex; align-items: baseline; gap: .6rem; margin: 0 0 var(--s-2);
  font-size: var(--t-small); font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink);
}
.pband-step { color: var(--sky-700); font-variant-numeric: tabular-nums; }
.pband-stage ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .65rem; }
.pband-item {
  display: flex; align-items: center; gap: .75rem; min-width: 0;
  font-size: var(--t-body); font-weight: 600; color: var(--ink-soft);
}
/* What kind of tool the stage holds, beside its label: the general term
   first, the products under it as examples. */
.pband-kind {
  margin-left: auto; padding: .1rem .5rem; border: 1px solid var(--line); border-radius: 999px;
  font-size: var(--t-micro); font-weight: 600; letter-spacing: .06em; color: var(--ink-soft);
}
/* The open tile that ends every stage: a dashed plate where a mark would sit. */
.pplate-open { background: transparent; border: 1.5px dashed var(--line-strong); color: var(--sky-700); }
.pband-item-open { font-weight: 500; color: var(--ink-soft); }
.pchip-open { border-style: dashed; color: var(--ink-soft); padding-left: .85rem; padding-right: .85rem; }
.pband-more { margin-top: var(--s-3); }
.pband-more summary { list-style: none; cursor: pointer; display: inline-block; border-radius: 999px; }
.pband-more summary::-webkit-details-marker { display: none; }
.pband-more[open] summary { margin-bottom: var(--s-2); }
@media (max-width: 860px) {
  .pband { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-3); }
  .pband-stage::after { display: none; }
  .pband-item { font-size: var(--t-small); }
  /* Two stages a row leaves no room for the label and its kind chip on one
     line: let the chip drop under the label rather than push the page wide. */
  .pband-label { flex-wrap: wrap; row-gap: .35rem; }
  .pband-kind { margin-left: 0; }
  .pband-item > span:last-child { min-width: 0; }
}
/* Below 360px two columns cannot hold "CloudFormation" beside its plate
   without breaking the word, so the stages stack. */
@media (max-width: 359px) {
  .pband { grid-template-columns: 1fr; }
}

/* "Typical systems in scope" on a situation page's hero. */
.sit-stack { display: grid; gap: .7rem; margin-bottom: 1.6rem; }
.sit-stack-label {
  font-size: var(--t-micro); font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase; color: var(--ink-quiet);
}
.sit-stack-list {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: .5rem 1.4rem;
}
.sit-stack-list li {
  display: inline-flex; align-items: center; gap: .55rem;
  font-size: var(--t-small); font-weight: 500; color: var(--ink-soft);
}

/* ------------------------------------------------- sample report block */
/*
  Grid children default to `min-width: auto`, which resolves to min-content —
  so a grid track refuses to shrink below its widest unbreakable child and the
  whole column pushes past the viewport instead. That is a horizontal
  scrollbar on a phone, and it is invisible on a desktop while you build it.
  Every grid container on the site opts its children out.
*/
.grid > *, .split > *, .rail-layout > *, .sample > *, .io-grid > *, .hero-grid > * { min-width: 0; }

.sample {
  display: grid; grid-template-columns: 300px 1fr; gap: clamp(1.5rem, 4vw, 3rem);
  align-items: center;
  border: 1px solid var(--line); border-radius: var(--r-m);
  background: var(--white); padding: var(--s-4) var(--s-3);
}

/*
  Three real pages from the report, fanned. They are screenshots of the
  generated document rather than a drawing of one, because the whole claim
  of this block is "judge the deliverable, not the pitch" — and a mockup
  here would be exactly the wrong thing to put next to that sentence.
*/
.sample-spreads { position: relative; padding: 0 0 1.5rem; isolation: isolate; }
.sample-spreads .spread {
  /* The page's own ratio, stated: WebKit takes no size from a lazy image's
     width and height attributes until it loads. On a phone this block was
     3px tall, then jumped to its full height and moved everything below it. */
  width: 100%; height: auto; aspect-ratio: 420 / 594; border-radius: 3px;
  border: 1px solid var(--line-strong);
  transition: transform var(--dur) var(--ease);
}
.sample-spreads .spread-1, .sample-spreads .spread-2 { position: absolute; inset: 0; }
.spread-2 { transform: rotate(-7deg) translate(-12%, 3%); z-index: 1; }
.spread-1 { transform: rotate(-3.5deg) translate(-6%, 1.5%); z-index: 2; }
.spread-0 { position: relative; z-index: 3; }
.sample:hover .spread-2 { transform: rotate(-9.5deg) translate(-17%, 4%); }
.sample:hover .spread-1 { transform: rotate(-4.5deg) translate(-9%, 2%); }

.sample-pages {
  position: absolute; right: -.5rem; bottom: 0; z-index: 4;
  background: var(--tone-navy-bg); color: var(--tone-navy-ink);
  padding: .3rem .7rem; border-radius: 999px; font-size: var(--t-micro);
}
.gate-note { margin-top: .6rem; color: var(--sky-700); font-weight: 500; }
/* The document itself, handed over the moment the details are in. The button
   said "Download the sample report" and the endpoint has never emailed one —
   see the note at the top of js/gate.js. */
.gate-note a { color: inherit; }
.gate-note a[data-gate-download] {
  display: inline-block; margin-top: .35rem; font-weight: 700;
}

@media (max-width: 760px) {
  .sample { grid-template-columns: 1fr; }
  /* Centred with auto margins, a grid item shrinks to its content, and an
     unloaded lazy image has none in WebKit: say the width outright. */
  .sample-spreads { width: 100%; max-width: 260px; margin-inline: auto; }
}
@media (prefers-reduced-motion: reduce) {
  .sample-spreads .spread { transition: none; }
  .sample:hover .spread-1, .sample:hover .spread-2 { transform: none; }
  .spread-1, .spread-2 { display: none; }
}

/* -------------------------------------------------------- capture gate */
.gate {
  border: 1px solid var(--line); border-radius: var(--r-m);
  padding: clamp(1.5rem, 4vw, 2.25rem); max-width: 27rem; width: calc(100vw - 2rem);
  background: var(--white); color: var(--ink);
  /* A modal <dialog> is centred by the UA's own `margin: auto` against the
     inset-0 it is given. base.css resets `* { margin: 0 }`, which beats the UA
     sheet and pinned this to the top-left corner of the viewport. Putting the
     margin back is the whole fix; nothing else here positions it. */
  margin: auto;
}
.gate::backdrop { background: rgba(11, 37, 69, .55); }
.gate h2 { margin-bottom: .5rem; }
.gate .field { margin-top: var(--s-2); }
.gate [data-gate-error]:not(:empty) { color: var(--amber-ink); margin-top: .75rem; }
.gate-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); margin-top: var(--s-3); }
/* A live region: the sending, timed-out and failed states are announced, not
   only shown. Empty it collapses, so a quiet dialog does not carry a gap. */
.gate-status:not(:empty) {
  margin-top: var(--s-2);
  color: var(--ink-soft);
  line-height: 1.5;
}
/* A quiet text button. Not .btn-ghost — that one grows a → after it, which
   points the wrong way when the word is Cancel. */
.btn-quiet { font-weight: 500; color: var(--ink-quiet); padding: .5rem; }
.btn-quiet:hover { color: var(--ink); text-decoration: underline; }
.gate-legal { margin-top: var(--s-2); }

/* -------------------------------------------------------------- photos */
/*
  One component for every photograph on the site. With a src it renders the
  picture; without one it renders this placeholder at the same shape, so the
  layout is finished before the photography is. See partials/chrome.js.
*/
.photo { margin: 0; }
.photo picture { display: block; width: 100%; }
.photo img {
  width: 100%; aspect-ratio: var(--ratio, 4 / 3); object-fit: cover;
  border-radius: var(--r-m);
}
@media (max-width: 900px) {
  /* HTML dimensions reserve space, but their fixed height must not survive
     a narrow fluid width. The 1024px portrait otherwise spans two screens. */
  .photo img { height: auto; }
}
.photo-cap { margin-top: .6rem; }

.photo.is-placeholder .photo-brief {
  aspect-ratio: var(--ratio, 4 / 3);
  border: 1.5px dashed var(--line-strong); border-radius: var(--r-m);
  background: var(--mist); color: var(--ink-quiet);
  display: grid; align-content: center; justify-items: center; gap: .4rem;
  padding: var(--s-3); text-align: center;
}
.photo.is-placeholder b {
  font-family: var(--font); font-size: var(--t-micro); font-weight: 500;
  letter-spacing: .12em; text-transform: uppercase; color: var(--ink-quiet);
}
.photo.is-placeholder p { font-size: var(--t-small); max-width: 34ch; margin: 0; }

/* On navy the dashed box needs its own contrast or it disappears. */
.tone-navy .photo.is-placeholder .photo-brief,
.cta-panel .photo.is-placeholder .photo-brief {
  background: var(--tone-navy-card); border-color: var(--navy-line-2); color: var(--on-navy-quiet);
}
.tone-navy .photo.is-placeholder b,
.cta-panel .photo.is-placeholder b { color: var(--on-navy-quiet); }

/* ---------------------------------------------------------------- surfaces
   Shared hover idiom: border → --hover-border, titles → --hover-ink.
   Colour only — no translate, scale, or padding shifts.
   ========================================================================== */

/* The home hero ran 1167px tall in a 900px viewport, which put both of its
   calls to action just past the fold on the commonest laptop screen — the
   primary CTA of the whole site, visible only after a scroll. Trimming the
   top padding on this hero alone brings them back above it without touching
   the heroes on every other page. */
@media (min-width: 1024px) {
  body[data-page='home'] .hero { padding-block-start: 4rem; }
}
/* On a 1920x1080 screen the hero grows with the viewport and the CTA landed
   ten pixels past the fold again, so the largest screens trim a little more. */
@media (min-width: 1600px) {
  body[data-page='home'] .hero { padding-block-start: 3rem; }
}

/* ==========================================================================
   Problems we solve — the hub rows and the situation pages.

   Deliberately a list rather than a grid of equal cards. Fourteen identical
   tiles is the layout that makes a reader give up; a scannable row where the
   buyer's own sentence is the heading is the one they read. The four with a
   page of their own are links and say so; the rest are plain rows, because
   a card that looks clickable and is not is worse than one that never did.
   ========================================================================== */

.phub-rows { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-2); }
/* Group sections are homepage anchor targets (#g-delivery …); without the
   margin the sticky header sits on the landing heading. */
section[id^="g-"] { scroll-margin-top: 4.5rem; }
.phub-row { display: grid; scroll-margin-top: 6rem; }
.phub-row > a,
.phub-row > div {
  display: grid;
  gap: .45rem;
  padding: var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-m);
  background: var(--surface-raised);
  text-decoration: none;
  color: inherit;
}
.phub-row-linked > a:hover { border-color: var(--hover-border); }
.phub-row-linked > a:hover .phub-row-title { color: var(--hover-ink); }
.phub-row-linked > a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.phub-row-title { font-size: var(--t-h3); font-weight: 700; letter-spacing: -0.02em; color: var(--ink); }
.phub-row-lead { font-size: var(--t-body); color: var(--ink-soft); max-width: 78ch; }
.phub-row-meta {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--ink-quiet);
}
.phub-row-go {
  font-size: var(--t-small);
  font-weight: 600;
  color: var(--accent);
}
.phub-row-go::after { content: " \2192"; }
.phub-row:target > a,
.phub-row:target > div { border-color: var(--accent); }
.phub-brief {
  margin: .6rem 0 0;
  display: grid;
  gap: .55rem;
}
.phub-brief > div {
  display: grid;
  grid-template-columns: 7rem minmax(0, 1fr);
  gap: var(--s-2);
}
.phub-brief dt {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink-quiet);
}
.phub-brief dd { margin: 0; color: var(--ink-soft); }
/* .phub-evidence-none was removed with the "no published case study" line:
   an evidence-less entry now simply carries no delivery link. */

/* The decision material sits behind a native disclosure so the hub scans
   as one-breath rows. Native <details>: keyboard and screen-reader
   behaviour come free, and no JavaScript is involved. */
.phub-more { margin-top: .5rem; }
.phub-more summary {
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  font-size: var(--t-small);
  font-weight: 600;
  color: var(--sky-700);
  list-style: none;
}
.phub-more summary::-webkit-details-marker { display: none; }
.phub-more summary::after { content: "+"; font-weight: 700; }
.phub-more[open] summary::after { content: "\2013"; }
.phub-more summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.phub-more[open] { padding-bottom: .25rem; }

@media (max-width: 640px) {
  .phub-brief > div { grid-template-columns: 1fr; gap: .15rem; }
}

.phub-investor {
  display: grid;
  gap: .9rem;
  max-width: 78ch;
  padding: var(--s-3);
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-m);
  background: var(--mist);
}

/* ------------------------------------------------- a single situation */

.sit-buyer { font-size: var(--t-body); color: var(--ink-soft); max-width: 70ch; line-height: 1.7; margin-bottom: 1.5rem; }

.sit-symptoms,
.sit-exclusions { list-style: none; margin: 0; padding: 0; display: grid; gap: .7rem; max-width: 84ch; }
.sit-symptoms li,
.sit-exclusions li {
  position: relative;
  padding-left: 1.6rem;
  font-size: var(--t-body);
  color: var(--ink);
}
.sit-symptoms li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .5em;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--sky-500);
}
/* A deliberate visual difference from the symptoms list: these are the
   things we will not do, and they should not read as more features. */
.sit-exclusions li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .62em;
  width: 11px;
  height: 2px;
  background: var(--gold-600);
}

.sit-block { display: grid; gap: .8rem; align-content: start; }
.sit-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .55rem; }
.sit-list li {
  position: relative;
  padding-left: 1.4rem;
  font-size: var(--t-body);
  color: var(--ink);
}
.sit-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .55em;
  width: 6px;
  height: 6px;
  border-radius: 2px;
  background: var(--sky-500);
}

.sit-done {
  display: grid;
  gap: .5rem;
  max-width: 84ch;
  padding: var(--s-3);
  border-radius: var(--r-m);
  background: var(--gold-tint);
  border: 1px solid var(--line);
}
.sit-done-tag {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--gold-700);
}
.sit-done p { font-size: var(--t-body); color: var(--ink); }
.sit-done code { font-family: var(--mono); font-size: .95em; }

.sit-answer { max-width: 80ch; }

.sit-evidence { display: grid; gap: .9rem; }
.sit-evidence-label {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-quiet);
}
.sit-evidence-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-2); }
.sit-evidence-list a {
  display: grid;
  gap: .5rem;
  justify-items: start;
  padding: var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-m);
  background: var(--surface-raised);
  text-decoration: none;
  color: var(--ink);
  font-size: var(--t-body);
}
.sit-evidence-list a:hover { border-color: var(--hover-border); color: var(--hover-ink); }
.sit-evidence-list a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.sit-evidence-none p { max-width: 80ch; font-size: var(--t-body); color: var(--ink-soft); }

/* ------------------------------------------------------- partner Q & A */

.partner-qa { display: grid; gap: var(--s-2); margin-top: var(--s-4); }
/* The six questions as native disclosures, same reasoning as .phub-more on
   the hub: the list scans in one screen, each answer is one tap away, and
   the full text still ships in the HTML and the FAQ JSON-LD. */
.pqa {
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-m);
  background: var(--surface-raised);
}
.pqa summary {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  cursor: pointer; list-style: none;
  font-size: var(--t-h3); font-weight: 700; letter-spacing: -0.02em; color: var(--ink);
}
.pqa summary::-webkit-details-marker { display: none; }
.pqa summary::after { content: "+"; font-weight: 700; color: var(--sky-700); flex: none; }
.pqa[open] summary::after { content: "\2013"; }
.pqa summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.pqa p { margin: .6rem 0 .2rem; font-size: var(--t-body); color: var(--ink-soft); max-width: 84ch; }

/* Who carries what, three ways — the partner page's responsibility map. */
.pbd { display: grid; gap: var(--s-2); }
.pbd-cols { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: var(--s-2); }
.pbd-col {
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--line); border-radius: var(--r-m); background: var(--white);
  border-top: 3px solid var(--line-strong);
}
.pbd-partner { border-top-color: var(--gold-400); }
.pbd-kind {
  font-size: var(--t-micro); font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase; color: var(--sky-700);
  margin-bottom: .3rem;
}
.pbd-partner .pbd-kind { color: var(--gold-700); }
.pbd-who { font-size: var(--t-body); font-weight: 600; color: var(--ink); margin-bottom: .7rem; }
.pbd-col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .45rem; }
.pbd-col li {
  position: relative; padding-left: 1.1rem;
  font-size: var(--t-small); color: var(--ink-soft);
}
.pbd-col li::before {
  content: ''; position: absolute; left: 0; top: .5em;
  width: 6px; height: 6px; border-radius: 50%; background: var(--sky-500);
}
.pbd-partner li::before { background: var(--gold-400); }
.pbd-foot { font-size: var(--t-small); color: var(--ink-quiet); max-width: 80ch; }
@media (max-width: 860px) { .pbd-cols { grid-template-columns: 1fr; } }

/* ==========================================================================
   sgrp — the four outcome groups on the homepage.

   Two columns rather than four, because four columns of a list reads as a
   sitemap and two reads as an argument. The situations inside each group
   are the buyer's short phrasing; the four with a page of their own are
   links, the rest are plain text that the hub picks up.
   ========================================================================== */

.sgrp-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--s-3);
}
.sgrp {
  display: grid;
  gap: .7rem;
  align-content: start;
  padding: var(--s-3);
  background: var(--surface-raised);
  border: 1px solid var(--line);
  border-radius: var(--r-m);
}
.sgrp-lead { font-size: var(--t-small); color: var(--ink-quiet); }
.sgrp-list { list-style: none; margin: .2rem 0 0; padding: 0; display: grid; gap: .5rem; }
.sgrp-list li {
  position: relative;
  padding-left: 1.2rem;
  font-size: var(--t-body);
  color: var(--ink);
}
.sgrp-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .55em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--sky-500);
}
.sgrp-list a { color: var(--accent); text-decoration: none; border-bottom: 1px solid transparent; }
.sgrp-list a:hover { border-bottom-color: currentColor; }
.sgrp-list a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* The route to the rest of a group's situations on /problems. */
.sgrp-all {
  justify-self: start; margin-top: .3rem;
  font-size: var(--t-small); font-weight: 600; color: var(--accent);
  text-decoration: none; border-bottom: 1px solid transparent;
}
.sgrp-all::after { content: " \2192"; }
.sgrp-all:hover { border-bottom-color: currentColor; }
.sgrp-all:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.hero-follow-note { max-width: 62ch; margin: var(--s-2) 0 var(--s-4); }

@media (max-width: 860px) {
  .sgrp-grid { grid-template-columns: 1fr; }
}

/* ==========================================================================
   xvid — the homepage explainer film.

   One player, no autoplay, and a small link to the written engagement steps.
   The page does not repeat the film scene by scene beside it.
   ========================================================================== */

.xvid {
  margin: 0 auto;
  max-width: 70rem;
}
.xvid-frame {
  border: 1px solid var(--line);
  border-radius: var(--r-m);
  overflow: hidden;
  background: var(--navy-900);
  aspect-ratio: 16 / 9;
}
.xvid-player { display: block; width: 100%; height: 100%; }
.xvid-caption-compact {
  margin-top: .75rem;
  font-size: var(--t-small);
}
.xvid-caption-compact a { color: var(--accent); }

/* ==========================================================================
   appoint — the commercial path from first contact to acceptance, on /about.
   A numbered list rather than cards: it is a sequence, and five equal cards
   would say the opposite.
   ========================================================================== */

.appoint { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-2); max-width: 90ch; counter-reset: none; }
.appoint-step {
  display: grid;
  grid-template-columns: 3.2rem 1fr;
  gap: var(--s-2);
  align-items: start;
  padding: var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-m);
  background: var(--surface-raised);
}
.appoint-num {
  font-family: var(--mono);
  font-size: var(--t-small);
  font-weight: 700;
  color: var(--gold-700);
  padding-top: .15rem;
}
.appoint-mark { display: grid; justify-items: center; gap: .35rem; color: var(--sky-700); }
.appoint-mark .appoint-num { padding-top: 0; }
.about-photo img { aspect-ratio: 16 / 9; height: auto; object-position: 50% 30%; border-radius: var(--r-m); }
.appoint-body { display: grid; gap: .3rem; }
.appoint-body strong { font-size: var(--t-h3); font-weight: 700; letter-spacing: -0.02em; color: var(--ink); }
.appoint-body span { font-size: var(--t-body); color: var(--ink-soft); }

@media (max-width: 600px) {
  .appoint-step { grid-template-columns: 1fr; gap: .4rem; }
}

/* ==========================================================================
   sz — what makes a package larger or smaller.

   Added after a Round 1 commercial review found that a buyer could read a
   bounded package and still not know whether it was a fortnight or a quarter.
   The site publishes no prices and that policy is not changing, so this gives
   the scoping variables instead of a figure.
   ========================================================================== */

.sz { display: grid; gap: var(--s-3); max-width: 90ch; }
.sz-cols { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-3); }
.sz-col {
  display: grid;
  gap: .8rem;
  align-content: start;
  padding: var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-m);
}
.sz-bigger { background: var(--surface-raised); }
.sz-smaller { background: var(--mist); }
.sz-col-title {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--gold-700);
}
.sz-foot { font-size: var(--t-small); color: var(--ink-quiet); max-width: 80ch; }

@media (max-width: 760px) {
  .sz-cols { grid-template-columns: 1fr; }
}

/* Destinations on a hub entry that has no page of its own. Round 1 found
   eight of twelve were inert; these are the two routes that genuinely exist. */
.phub-row-links { display: flex; flex-wrap: wrap; gap: .4rem 1.1rem; margin-top: .3rem; }
.phub-row-links a {
  font-size: var(--t-small);
  font-weight: 600;
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.phub-row-links a:hover { border-bottom-color: currentColor; }
.phub-row-links a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Commercial terms on /services. Round 1 found the assessment credit and the
   EdgeAssure minimum term were real, published and buried — the credit only on
   /how-it-works, the term only in a float that appears on scroll. Neither term
   changed; both are now where somebody deciding will look. */
.terms { display: grid; gap: var(--s-2); margin-top: var(--s-3); max-width: 90ch; }
.terms-row {
  display: grid;
  grid-template-columns: 18rem 1fr;
  gap: var(--s-2);
  align-items: baseline;
  padding: var(--s-2) 0;
  border-top: 1px solid var(--line);
}
.terms-row dt { font-weight: 700; font-size: var(--t-body); color: var(--ink); }
.terms-row dd { margin: 0; font-size: var(--t-body); color: var(--ink-soft); }

@media (max-width: 700px) {
  .terms-row { grid-template-columns: 1fr; gap: .3rem; }
}

/* One finding, end to end: the illustrative diff on a situation page. The
   change is the point, so it is drawn plainly — mono, hairline, no syntax
   theatre. Colour is never the only carrier: every line keeps its +/-
   marker, and the removed lines are --ink-soft rather than --ink-quiet
   because the block sits on mist. */
.diffb {
  margin: .25rem 0 0;
  padding: var(--s-2);
  font-family: var(--mono);
  font-size: var(--t-small);
  line-height: 1.6;
  background: var(--mist);
  border: 1px solid var(--line);
  border-radius: var(--r-s);
  overflow-x: auto;
  white-space: pre;
}
.diffb-file { display: block; color: var(--ink-soft); padding-bottom: .4rem; }
.diffb-del { color: var(--ink-soft); }
.diffb-add { color: var(--ink); font-weight: 600; }

/* On phones nothing may hide behind a horizontal scroll the reader cannot
   see: wrap instead. The +/- marker still opens every line, so a wrapped
   continuation cannot be mistaken for a new one. */
@media (max-width: 620px) {
  .diffb { white-space: pre-wrap; overflow-wrap: anywhere; }
}

/* The worked example embeds a pre inside the .ec labelled stack (which
   concepts.css owns). A grid child's min-width defaults to its content, so
   without this the pre's intrinsic width widens the body column and the
   neighbouring rows' text clips behind the card's overflow on phones. The
   pre then scrolls inside its own box, which is the intended behaviour. */
.ec-body { min-width: 0; }

/* ==========================================================================
   sit-ico — one pictogram per buying situation (partials/situation-icons.js).

   A tinted plate with the drawing in the accent blue and one detail in gold.
   --gold-600 rather than --gold-400 on light: the detail is a shape, not
   text, but at 1.6px a 1.66:1 stroke disappears into a pale plate.
   ========================================================================== */
.sit-ico {
  display: inline-grid; place-items: center; flex: none;
  width: 44px; height: 44px; border-radius: 12px;
  background: var(--sky-tint); color: var(--sky-700);
  border: 1px solid color-mix(in srgb, var(--sky-500) 22%, transparent);
}
.sit-ico svg { width: 24px; height: 24px; }
.sit-ico-a { stroke: var(--gold-600); }
.sit-ico-s { width: 38px; height: 38px; border-radius: 10px; }
.sit-ico-s svg { width: 21px; height: 21px; }
.sit-ico-l { width: 64px; height: 64px; border-radius: 16px; margin-bottom: var(--s-2); }
.sit-ico-l svg { width: 34px; height: 34px; }

/* Hub rows: the pictogram sits in its own column beside the row's text. */
.phub-row > a.phub-row-pic,
.phub-row > div.phub-row-pic { grid-template-columns: auto minmax(0, 1fr); column-gap: var(--s-2); align-items: start; }
.phub-row-text { display: grid; gap: .45rem; min-width: 0; }

/* Homepage groups: the pictogram replaces the list bullet. */
.sgrp-list.has-ico { gap: .6rem; }
.sgrp-list.has-ico li { padding-left: 0; }
.sgrp-list.has-ico li::before { display: none; }
.sgrp-list.has-ico a { display: inline-flex; align-items: center; gap: .7rem; border-bottom: 0; }
.sgrp-list.has-ico a > span:last-child { border-bottom: 1px solid transparent; }
.sgrp-list.has-ico a:hover > span:last-child { border-bottom-color: currentColor; }

/* Related-situation cards carry theirs above the title. */
.card .sit-ico { margin-bottom: .75rem; }

/* ==========================================================================
   who — the points at which a client speaks to the engineer on their work.
   Used on /about (#who) and, as a strip, under the homepage hero.
   ========================================================================== */
.who-card { display: grid; gap: .5rem; align-content: start; }
.who-card p { color: var(--ink-soft); font-size: var(--t-body); }
.who-mark { display: inline-flex; align-items: center; gap: .6rem; color: var(--sky-700); }
.who-num {
  font-size: var(--t-micro); font-weight: 700; letter-spacing: .08em;
  font-variant-numeric: tabular-nums; color: var(--ink-quiet);
}

.who-strip {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-3);
  margin: 0; padding: var(--s-3); list-style: none;
  background: var(--surface-raised); border: 1px solid var(--line); border-radius: var(--r-m);
}
.who-strip li { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: .85rem; align-items: start; }
.who-strip-ico {
  display: inline-grid; place-items: center; width: 40px; height: 40px; border-radius: 50%;
  background: var(--gold-tint); color: var(--gold-700);
  border: 1px solid color-mix(in srgb, var(--gold-400) 45%, transparent);
}
.who-strip strong { display: block; font-size: var(--t-body); color: var(--ink); line-height: 1.35; }
.who-strip span.who-strip-text { font-size: var(--t-small); color: var(--ink-soft); }
@media (max-width: 860px) {
  .who-strip { grid-template-columns: 1fr; gap: var(--s-2); padding: var(--s-2); }
}

/* "Who you deal with" under each step on /how-it-works. */
.who-line {
  display: flex; align-items: flex-start; gap: .7rem; max-width: 72ch;
  margin: 0 0 var(--s-3); padding: .7rem .95rem;
  background: var(--gold-tint); border: 1px solid color-mix(in srgb, var(--gold-400) 45%, transparent);
  border-radius: var(--r-s); font-size: var(--t-body); color: var(--ink);
}
.who-line svg { flex: none; margin-top: .15rem; color: var(--gold-700); }
.who-line b { font-weight: 700; }
.hero-who { margin-bottom: var(--s-5); }
.split-head { margin: var(--s-5) auto var(--s-3); max-width: 980px; }
/* The tooling column is the quiet one: collection and repetition. */
.rsp-yours.rsp-tool .rsp-list li::before { background: var(--ink-quiet); border-radius: 50%; }

.sit-who { margin-top: var(--s-3); }

/* Anchor targets on /about: clear the sticky header so the eyebrow is not under it. */
#who, #continuity { scroll-margin-top: 4.5rem; }

/* ------------------------------------------------------- EdgePQ Check */
/* The tool page. Everything is drawn from tokens; the only new shapes are
   a code-sized textarea and the finding cards. */
.pq-form textarea { font-family: var(--mono); font-size: var(--t-small); min-height: 320px; line-height: 1.5; tab-size: 2; }
.pq-actions { display: flex; flex-wrap: wrap; gap: .75rem; align-items: center; }
.pq-status { margin-top: .75rem; color: var(--ink-quiet); }
.pq-status.is-ok { color: var(--pass-ok); }
.pq-status.is-bad { color: var(--amber-ink); }
.pq-results { margin-top: var(--s-5); border-top: 1px solid var(--line); padding-top: var(--s-4); }
.pq-summary-line { font-size: var(--t-lead); }
.pq-downloads { display: flex; flex-wrap: wrap; gap: .75rem; margin: var(--s-3) 0 var(--s-4); }
.pq-group { font-size: var(--t-h4); margin: var(--s-4) 0 var(--s-2); }
.pq-finding { border: 1px solid var(--line); border-radius: var(--r-m); padding: var(--s-3); margin-bottom: var(--s-3); background: var(--white); }
.pq-finding-fail { border-left: 4px solid var(--amber-ink); }
.pq-finding-unknown { border-left: 4px solid var(--slate-500); }
.pq-finding-not_configurable { border-left: 4px solid var(--gold-600); }
.pq-finding-pass { border-left: 4px solid var(--pass-ok); }
.pq-finding h3 { font-family: var(--mono); font-size: var(--t-body); font-weight: 400; margin: .35rem 0 .5rem; overflow-wrap: anywhere; }
.pq-finding-head { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; }
.pq-rule-id { font-family: var(--mono); font-size: var(--t-small); }
.pq-category { font-size: var(--t-small); color: var(--ink-quiet); }
.pq-badge-critical, .pq-badge-high { background: var(--amber-tint); color: var(--amber-ink); }
.pq-badge-medium { background: var(--gold-tint); color: var(--gold-700); }
.pq-badge-low, .pq-badge-info { background: var(--mist); color: var(--slate-600); }
.pq-observed { display: grid; grid-template-columns: max-content 1fr; gap: .25rem 1rem; font-size: var(--t-small); margin: .75rem 0; }
.pq-observed dt { font-family: var(--mono); color: var(--ink-quiet); }
.pq-observed dd { overflow-wrap: anywhere; }
.pq-fix pre { background: var(--mist); border-radius: var(--r-s); padding: .75rem 1rem; overflow-x: auto; font-size: var(--t-small); margin: .5rem 0; }
.pq-sources { margin-top: .75rem; color: var(--ink-quiet); }
.pq-sources li { overflow-wrap: anywhere; }
.pq-rules li, .pq-not-covered li { padding: .35rem 0; border-bottom: 1px solid var(--line); }
.pq-rules .badge { margin-left: .35rem; }
.tone-mist .pq-finding { background: var(--white); }
@media (max-width: 600px) { .pq-observed { grid-template-columns: 1fr; gap: 0 } .pq-observed dd { margin-bottom: .4rem; } }

/* --------------------------------------------------------- free tools */
/* The tool mark is a line icon on a mist plate, drawn in sky-700 so it reads
   as a control rather than a logo; the same plate the diagrams use. */
.tool-mark { display: inline-grid; place-items: center; width: calc(var(--tool-mark, 24px) + 12px); height: calc(var(--tool-mark, 24px) + 12px); border-radius: var(--r-s); background: var(--mist); color: var(--sky-700); flex: none; }
.nav-drop-panel .tool-mark { width: 34px; height: 34px; }
.nav-drop-panel .tool-mark svg { width: 20px; height: 20px; }
.mobile-sub .tool-mark { width: 26px; height: 26px; }
.mobile-sub .tool-mark svg { width: 16px; height: 16px; }
.tone-navy .tool-mark { background: var(--tone-navy-card); color: var(--gold-400); }

/* A site of ours with its own mark: the chip holds the mark as an image, and
   the name is its wordmark, drawn at the row's text height with the width
   following from the SVG's own ratio. The provider colours in the wordmark
   are the brand and stay as they are in both themes. */
.tool-mark-img img { width: var(--tool-mark, 24px); height: var(--tool-mark, 24px); display: block; border-radius: 4px; }
.nav-drop-panel .tool-mark-img img { width: 20px; height: 20px; }
.mobile-sub .tool-mark-img img { width: 16px; height: 16px; }
.site-wordmark { display: block; width: auto; }
.nav-drop-panel .site-wordmark { height: 18px; margin: .15rem 0 .1rem; }
.mobile-sub .site-wordmark { height: 15px; }
.tool-card-head .site-wordmark { height: 24px; }
/* The second group in a menu: the same rows, without a track colour. */
.nav-drop-also { border-left: 2px solid var(--line); }
.tool-grid { align-items: stretch; }
.tool-card { display: flex; flex-direction: column; gap: .6rem; }
.tool-card-head { display: flex; align-items: center; gap: .75rem; }
.tool-card-head h3 { margin: 0; }
.tool-card-facts { display: grid; grid-template-columns: max-content 1fr; gap: .25rem .75rem; font-size: var(--t-small); margin: .25rem 0 .5rem; }
.tool-card-facts dt { color: var(--ink-quiet); }
.tool-card .btn-ghost { margin-top: auto; }
/* A command in a card fact never breaks at its own hyphen. */
.tool-card-needs code { white-space: nowrap; font-size: inherit; }
