@charset "UTF-8";
/* ==========================================================================
   Next Cyber — design system
   Plan. Protect. Perform.

   The blue sphere in the wordmark is a full stop. Every structural device on
   this site derives from that: headings are complete sentences, the terminal
   period is the brand mark, and each page gets exactly one full-bleed signal
   section — the page's own full stop.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Fonts
   -------------------------------------------------------------------------- */

/* Both faces are self-hosted. Nothing on this site calls a third-party origin —
   no Google Fonts, no CDN. Faster (no extra DNS + TLS handshake before text can
   render), and a security firm should not be handing every visitor's IP address
   to an analytics-adjacent third party just to load a typeface. It also means
   the site renders correctly on locked-down government and corporate networks. */

/* The wordmark face. Only weight 800 is shipped, because the logo is the only
   thing set in it — see tools/vendor.mjs. */
@font-face {
  font-family: "Open Sauce One";
  src: url("../fonts/open-sauce-one-800.woff2") format("woff2");
  font-weight: 800;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "General Sans";
  src: url("../fonts/GeneralSans-Variable.woff2") format("woff2");
  font-weight: 200 700;
  font-style: normal;
  font-display: swap;
}

/* Archivo variable, latin + latin-ext. Split so most visitors fetch only the
   90 KB latin subset. Sourced from Google Fonts, served from our own origin. */
@font-face {
  font-family: "Archivo";
  src: url("../fonts/archivo-latin.woff2") format("woff2");
  font-weight: 400 900;
  font-stretch: 75% 125%;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Archivo";
  src: url("../fonts/archivo-latin-ext.woff2") format("woff2");
  font-weight: 400 900;
  font-stretch: 75% 125%;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --------------------------------------------------------------------------
   2. Tokens
   -------------------------------------------------------------------------- */

:root {
  /* Colour — sampled from the wordmark and the Plan/Protect/Perform banner */
  --ink: #101014;
  --ink-soft: #2c2f3a;
  --muted: #5a6072;
  --paper: #ffffff;
  --mist: #f2f4f8;
  --signal: #2f3fff;
  /* The lift is the brightest point of the signal field, so it sets the
     contrast ceiling for everything written on top of it. At #6478ff even
     pure white came in at 3.7:1 and body copy read as grey. */
  --signal-lift: #3847ff;
  --signal-deep: #1526d6;
  --rule: #e1e5ee;
  --rule-strong: #c8cede;

  /* Text on the signal blue. One token, because the field is not flat: the
     radial lift means anything under 88% white drops below 4.5:1 near the
     gradient centre. Never write body copy on the signal at a lower alpha,
     and never use --muted or --rule-strong on a dark ground. */
  --on-signal: rgba(255, 255, 255, 0.88);
  --on-signal-line: rgba(255, 255, 255, 0.3);
  --on-ink: rgba(255, 255, 255, 0.72);

  /* The sphere, reproduced. Highlight sits at centre, not top-left. */
  --sphere: radial-gradient(
    circle at 50% 56%,
    #4a5cff 0%,
    #2f3fff 46%,
    #2431f6 80%,
    #1e2ae8 100%
  );

  /* Type */
  --f-display: "Archivo", "Helvetica Neue", Helvetica, Arial, sans-serif;
  /* The logo only. Everything else stays on --f-display. */
  --f-mark: "Open Sauce One", "Archivo", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --f-body: "General Sans", "Archivo", system-ui, -apple-system, sans-serif;

  --t-display: clamp(2.55rem, 6.3vw, 5.5rem);
  --t-h1: clamp(2.35rem, 5.4vw, 4.4rem);
  --t-h2: clamp(1.85rem, 3.5vw, 3rem);
  --t-h3: clamp(1.2rem, 1.7vw, 1.55rem);
  --t-h4: clamp(1.02rem, 1.2vw, 1.15rem);
  --t-lead: clamp(1.08rem, 1.5vw, 1.4rem);
  --t-body: 1.0625rem;
  --t-small: 0.9375rem;
  --t-label: 0.7rem;

  /* Space */
  --wrap: 1200px;
  --gutter: clamp(1.25rem, 5vw, 4rem);
  --section-y: clamp(4.5rem, 9vw, 9rem);
  --rail-w: 190px;

  --radius: 4px;
  --radius-lg: 8px;

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* --------------------------------------------------------------------------
   3. Reset
   -------------------------------------------------------------------------- */

*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 96px;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--f-body);
  font-size: var(--t-body);
  line-height: 1.65;
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

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

h1, h2, h3, h4, h5, p, figure, blockquote, ul, ol, dl, dd { margin: 0; }
ul, ol { padding: 0; list-style: none; }

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

button,
input,
select,
textarea { font: inherit; color: inherit; }

hr { border: 0; border-top: 1px solid var(--rule); margin: 0; }

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

::selection { background: var(--signal); color: #fff; }

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

.skip-link {
  position: absolute;
  top: -100px; left: var(--gutter);
  z-index: 200;
  background: var(--ink); color: #fff;
  padding: 0.75rem 1.25rem;
  border-radius: var(--radius);
  transition: top 0.2s var(--ease);
}
.skip-link:focus { top: 0.75rem; }

/* --------------------------------------------------------------------------
   4. Typography
   -------------------------------------------------------------------------- */

h1, h2, h3, h4, .h-display {
  font-family: var(--f-display);
  font-weight: 700;
  line-height: 1.04;
  letter-spacing: -0.028em;
  font-stretch: 92%;
  text-wrap: balance;
}

h3, h4 { line-height: 1.22; letter-spacing: -0.016em; font-stretch: 96%; }

.h-display { font-size: var(--t-display); letter-spacing: -0.038em; font-stretch: 88%; }
h1 { font-size: var(--t-h1); letter-spacing: -0.032em; }
h2 { font-size: var(--t-h2); }
h3 { font-size: var(--t-h3); }
h4 { font-size: var(--t-h4); font-weight: 600; }

p { text-wrap: pretty; }

.lead {
  font-size: var(--t-lead);
  line-height: 1.5;
  color: var(--ink-soft);
  font-weight: 400;
  max-width: 46ch;
}

.muted { color: var(--muted); }
.small { font-size: var(--t-small); }

/* The signature. A terminal period, drawn as the wordmark's sphere. */
.stop {
  display: inline-block;
  width: 0.2em;
  height: 0.2em;
  margin-left: 0.075em;
  border-radius: 50%;
  background: var(--sphere);
  vertical-align: baseline;
}
.stop--on-signal { background: #fff; }

/* Section classification label — lives in the left rail. */
.eyebrow {
  font-family: var(--f-display);
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-stretch: 108%;
  color: var(--muted);
  display: block;
}
.eyebrow .stop { width: 0.34em; height: 0.34em; margin-left: 0.2em; }
.eyebrow--on-signal { color: var(--on-signal); }

/* --------------------------------------------------------------------------
   5. Layout primitives
   -------------------------------------------------------------------------- */

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.wrap--wide { max-width: 1480px; }
.wrap--narrow { max-width: 780px; }

.section { padding-block: var(--section-y); }
.section--tight { padding-block: clamp(3rem, 5.5vw, 5rem); }
.section--top-flush { padding-block-start: 0; }
.section--bottom-flush { padding-block-end: 0; }

/* --top-flush closes the gap where a section simply continues the one above
   it on the same ground. A section that paints its own band, or draws a rule
   across the top, is not a continuation: the whitespace above it sits outside
   the band, so the heading ends up hard against the top edge. Give the
   padding back. */
.section--top-flush.section--mist,
.section--top-flush.section--ruled,
.section--top-flush.section--ink,
.section--top-flush.signal { padding-block-start: var(--section-y); }
.section--mist { background: var(--mist); }
.section--ink { background: var(--ink); color: #fff; }
.section--ruled { border-top: 1px solid var(--rule); }

/* Dark grounds re-point the light-mode text tokens at their own scale.
   --muted and --rule-strong are quoted by roughly thirty component rules
   (card bodies, spec lists, figure captions, table cells, FAQ copy); without
   this, any one of those components dropped into a dark section renders as
   grey-on-blue and the fix has to be repeated per page as an inline style.
   --ink and --paper are deliberately left alone: they are load-bearing as
   backgrounds in here (.btn, .section--ink .stat). */
.signal {
  --muted: var(--on-signal);
  --rule: rgba(255, 255, 255, 0.24);
  --rule-strong: var(--on-signal-line);
}
.section--ink {
  --muted: rgba(255, 255, 255, 0.72);
  --rule: rgba(255, 255, 255, 0.2);
  --rule-strong: rgba(255, 255, 255, 0.3);
}

.section--ink .lead,
.section--ink .muted { color: rgba(255, 255, 255, 0.72); }
.section--ink .eyebrow { color: rgba(255, 255, 255, 0.6); }

/* Hanging rail: classification left, argument right.
   Tracks are minmax(0,…) and children get min-width:0 so a wide child — a
   comparison table, a long unbroken string — scrolls inside itself instead of
   widening the page. */
.rail { display: grid; gap: 1.5rem; grid-template-columns: minmax(0, 1fr); }
.rail > * { min-width: 0; }
.rail > .rail-head { align-self: start; }

@media (min-width: 900px) {
  .rail {
    grid-template-columns: var(--rail-w) minmax(0, 1fr);
    gap: clamp(2rem, 5vw, 5rem);
  }
  .rail > .rail-head { position: sticky; top: 110px; }
}

/* Main column plus a narrower aside. Used for the contact form and any page
   where the rail's 190px classification column would squeeze the content. */
.split { display: grid; gap: 2.5rem; grid-template-columns: minmax(0, 1fr); }
.split > * { min-width: 0; }
@media (min-width: 940px) {
  .split {
    grid-template-columns: minmax(0, 1.45fr) minmax(0, 0.85fr);
    gap: clamp(2.5rem, 5vw, 4.5rem);
    align-items: start;
  }
  .split--aside-first { grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.4fr); }
}

.stack > * + * { margin-top: 1.25rem; }
.stack--lg > * + * { margin-top: 2rem; }
.stack--sm > * + * { margin-top: 0.65rem; }

/* Heading states the claim, lead qualifies it. Side by side once there's room. */
.section-head { max-width: 62ch; }
.section-head .lead { margin-top: 1.15rem; max-width: 54ch; }

@media (min-width: 1040px) {
  .section-head {
    max-width: none;
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    gap: clamp(2rem, 4vw, 3.5rem);
    align-items: end;
  }
  .section-head > h2 { max-width: 20ch; }
  .section-head .lead { margin-top: 0; }
  .section-head--single { display: block; }
  .section-head--single > h2 { max-width: 24ch; }
}

/* --------------------------------------------------------------------------
   6. Buttons & links
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--f-display);
  font-weight: 600;
  font-size: 0.95rem;
  letter-spacing: -0.01em;
  padding: 0.85rem 1.4rem;
  border-radius: var(--radius);
  border: 1px solid transparent;
  background: var(--ink);
  color: #fff;
  cursor: pointer;
  transition: background 0.2s var(--ease), color 0.2s var(--ease),
    border-color 0.2s var(--ease), transform 0.2s var(--ease);
}
.btn:hover { background: var(--signal); }
.btn:active { transform: translateY(1px); }

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

.btn--signal { background: var(--signal); }
.btn--signal:hover { background: var(--signal-deep); }

.btn--on-dark { background: #fff; color: var(--ink); }
.btn--on-dark:hover { background: var(--signal-lift); color: #fff; }

.btn--on-signal { background: #fff; color: var(--signal-deep); }
.btn--on-signal:hover { background: var(--ink); color: #fff; }

.btn--ghost-on-dark {
  background: transparent;
  color: #fff;
  border-color: rgba(255, 255, 255, 0.35);
}
.btn--ghost-on-dark:hover { border-color: #fff; background: transparent; color: #fff; }

.btn .arw { transition: transform 0.2s var(--ease); }
.btn:hover .arw { transform: translateX(4px); }

.btn-row { display: flex; flex-wrap: wrap; gap: 0.75rem; }

/* Inline text link */
.tlink {
  color: var(--signal);
  font-weight: 500;
  box-shadow: inset 0 -1px 0 rgba(47, 63, 255, 0.32);
  transition: box-shadow 0.2s var(--ease), color 0.2s var(--ease);
}
.tlink:hover { box-shadow: inset 0 -1px 0 var(--signal); }

/* Arrow link used on cards and lists */
.alink {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--f-display);
  font-weight: 600;
  font-size: 0.92rem;
  color: var(--ink);
}
.alink .arw { transition: transform 0.2s var(--ease); color: var(--signal); }
.alink:hover .arw { transform: translateX(4px); }
.alink--on-signal { color: #fff; }
.alink--on-signal .arw { color: #fff; }

/* --------------------------------------------------------------------------
   7. Header
   -------------------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(255, 255, 255, 0.86);
  backdrop-filter: saturate(150%) blur(14px);
  -webkit-backdrop-filter: saturate(150%) blur(14px);
  border-bottom: 1px solid var(--rule);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  min-height: 72px;
}

/* Horizontal lockup: wordmark + the sphere sitting at cap height, as in the logo. */
.brand {
  position: relative;
  display: inline-flex;
  align-items: center;
  font-family: var(--f-mark);
  font-weight: 800;
  font-size: 1.28rem;
  letter-spacing: -0.03em;
  line-height: 1;
  padding-right: 0.85em;
  color: var(--ink);
  white-space: nowrap;
}
.brand span { display: inline-block; }
.brand .brand__gap { width: 0.34em; }
.brand::after {
  content: "";
  position: absolute;
  top: -0.1em;
  right: 0.1em;
  width: 0.32em;
  height: 0.32em;
  border-radius: 50%;
  background: var(--sphere);
}
.brand--footer { font-size: 1.6rem; color: #fff; }

.nav { display: flex; align-items: center; gap: 0.35rem; }

.nav__link {
  font-family: var(--f-display);
  font-weight: 500;
  font-size: 0.94rem;
  letter-spacing: -0.008em;
  padding: 0.55rem 0.8rem;
  border-radius: var(--radius);
  color: var(--ink-soft);
  transition: color 0.18s var(--ease), background 0.18s var(--ease);
}
.nav__link:hover { color: var(--ink); background: var(--mist); }
.nav__link[aria-current="page"] { color: var(--ink); font-weight: 600; }

/* Services dropdown */
.nav__item { position: relative; }
.nav__toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  background: none;
  border: 0;
  cursor: pointer;
}
.nav__caret { transition: transform 0.2s var(--ease); }
.nav__toggle[aria-expanded="true"] .nav__caret { transform: rotate(180deg); }

.nav__panel {
  position: absolute;
  top: calc(100% + 0.6rem);
  left: -0.8rem;
  width: min(640px, 78vw);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  box-shadow: 0 24px 60px -24px rgba(16, 16, 20, 0.28);
  padding: 0.75rem;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.15rem;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity 0.18s var(--ease), transform 0.18s var(--ease), visibility 0.18s;
}
.nav__toggle[aria-expanded="true"] + .nav__panel {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
.nav__panel a {
  display: block;
  padding: 0.6rem 0.75rem;
  border-radius: var(--radius);
  transition: background 0.16s var(--ease);
}
.nav__panel a:hover { background: var(--mist); }
.nav__panel strong {
  display: block;
  font-family: var(--f-display);
  font-weight: 600;
  font-size: 0.94rem;
  letter-spacing: -0.012em;
}
.nav__panel span { display: block; font-size: 0.82rem; color: var(--muted); line-height: 1.4; }

.nav__cta { margin-left: 0.5rem; }

.burger {
  display: none;
  width: 44px; height: 44px;
  align-items: center; justify-content: center;
  background: none; border: 1px solid var(--rule); border-radius: var(--radius);
  cursor: pointer;
}
.burger span {
  display: block; position: relative;
  width: 18px; height: 1.5px; background: var(--ink);
  transition: background 0.15s var(--ease);
}
.burger span::before,
.burger span::after {
  content: ""; position: absolute; left: 0;
  width: 18px; height: 1.5px; background: var(--ink);
  transition: transform 0.22s var(--ease), top 0.22s var(--ease);
}
.burger span::before { top: -6px; }
.burger span::after { top: 6px; }
.burger[aria-expanded="true"] span { background: transparent; }
.burger[aria-expanded="true"] span::before { top: 0; transform: rotate(45deg); }
.burger[aria-expanded="true"] span::after { top: 0; transform: rotate(-45deg); }

@media (max-width: 980px) {
  .burger { display: inline-flex; }
  .nav {
    position: fixed;
    inset: 72px 0 auto 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--paper);
    border-bottom: 1px solid var(--rule);
    padding: 1rem var(--gutter) 2rem;
    max-height: calc(100dvh - 72px);
    overflow-y: auto;
    transform: translateY(-8px);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.2s var(--ease), transform 0.2s var(--ease), visibility 0.2s;
  }
  .nav[data-open="true"] { opacity: 1; visibility: visible; transform: translateY(0); }
  .nav__link { padding: 0.9rem 0; font-size: 1.05rem; border-bottom: 1px solid var(--rule); border-radius: 0; }
  .nav__link:hover { background: transparent; }
  .nav__toggle { width: 100%; justify-content: space-between; }
  .nav__panel {
    position: static; width: auto; border: 0; box-shadow: none; padding: 0.25rem 0 0.75rem;
    grid-template-columns: 1fr; opacity: 1; visibility: visible; transform: none;
    display: none; background: transparent;
  }
  .nav__toggle[aria-expanded="true"] + .nav__panel { display: grid; }
  .nav__panel a { padding: 0.55rem 0.75rem; background: var(--mist); margin-bottom: 0.15rem; }
  .nav__cta { margin: 1.25rem 0 0; justify-content: center; }
}

/* --------------------------------------------------------------------------
   8. Hero
   -------------------------------------------------------------------------- */

.hero { padding-block: clamp(3.5rem, 8vw, 7.5rem) clamp(2.5rem, 5vw, 4.5rem); }

/* Full-height variant: the hero and the status strip together fill the viewport,
   so the fold lands exactly on the strip rather than part-way through an image.
   min-height, never height — on a short laptop it simply grows to fit content
   instead of clipping. Capped so a tall monitor doesn't leave the type stranded
   in the middle of an empty field. */
.hero--fill {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: min(calc(100dvh - 72px - 45px), 820px);
  padding-block: clamp(2.5rem, 5vw, 4rem);
}

.hero__line { display: block; }

.hero__foot {
  display: grid;
  gap: 1.75rem;
  margin-top: clamp(2rem, 4vw, 3.25rem);
  align-items: end;
}
@media (min-width: 860px) {
  .hero__foot { grid-template-columns: minmax(0, 1fr) auto; gap: 3rem; }
}

/* Page hero for interior pages */
.page-hero { padding-block: clamp(3rem, 6vw, 5.5rem) clamp(2.25rem, 4vw, 3.5rem); }
.page-hero__grid { display: grid; gap: 1.75rem; }
@media (min-width: 900px) {
  .page-hero__grid { grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); gap: clamp(2rem, 6vw, 5rem); align-items: end; }
}

.breadcrumb {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.45rem;
  font-size: 0.82rem; color: var(--muted); margin-bottom: 1.5rem;
}
.breadcrumb a:hover { color: var(--ink); }
.breadcrumb .sep { color: var(--rule-strong); }

/* --------------------------------------------------------------------------
   9. Status strip — the dot doing its second job
   -------------------------------------------------------------------------- */

.statusbar { border-block: 1px solid var(--rule); background: var(--paper); }
.statusbar__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  /* 1.35rem is the widest column gap that still keeps the five home-page
     items on one line at the 1200px grid (1061px of 1072px). */
  gap: 0.6rem 1.35rem;
  padding-block: 0.9rem;
  font-family: var(--f-display);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
  font-stretch: 104%;
}
.statusbar__item { display: inline-flex; align-items: center; gap: 0.55rem; white-space: nowrap; }
/* For items that are a sentence rather than a label. */
.statusbar__item--flow { display: inline; white-space: normal; }
.statusbar__item--live { color: var(--ink); font-weight: 600; }

.led {
  position: relative;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--sphere);
  flex: none;
}
.led::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: 50%;
  background: var(--signal);
  animation: led-pulse 2.6s var(--ease) infinite;
}
@keyframes led-pulse {
  0%   { opacity: 0.55; transform: scale(1); }
  70%  { opacity: 0; transform: scale(3.2); }
  100% { opacity: 0; transform: scale(3.2); }
}

/* --------------------------------------------------------------------------
   10. Media bands & placeholders
   -------------------------------------------------------------------------- */

.band { position: relative; overflow: hidden; background: var(--mist); }
.band img { width: 100%; height: 100%; object-fit: cover; }
.band--cinema { aspect-ratio: 21 / 8; }
.band--wide { aspect-ratio: 24 / 9; }
@media (max-width: 700px) {
  .band--cinema { aspect-ratio: 4 / 3; }
  .band--wide { aspect-ratio: 4 / 3; }
}

.band--inset { border-radius: var(--radius-lg); }

/* Photography is monochrome so mixed sources read as one set; the blue dot stays
   the only colour on the page. Screens keep their colour — severity states and
   selection highlights carry meaning that grayscale would destroy. */
.band img,
.figure img { filter: grayscale(1) contrast(1.03); }
.band--screen img,
.figure--screen img { filter: none; }

.figure { display: block; }
.figure img { width: 100%; border-radius: var(--radius-lg); background: var(--mist); }
.figure figcaption {
  margin-top: 0.75rem;
  font-size: 0.82rem;
  color: var(--muted);
  display: flex; align-items: baseline; gap: 0.5rem;
}
.figure figcaption::before {
  content: ""; flex: none;
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--sphere);
  transform: translateY(-1px);
}

/* Locations map. Inline SVG rather than a raster so it stays sharp at any
   density and can use the brand tokens directly. Being an <svg> and not an
   <img>, it is untouched by the photography monochrome rule above — the
   office markers keep the signal blue. */
.map {
  background: var(--mist);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  padding: clamp(1rem, 3vw, 2.25rem);
}
.map svg { width: 100%; height: auto; display: block; }

.media-portrait { aspect-ratio: 4 / 5; }
.media-square { aspect-ratio: 1 / 1; }
.media-landscape { aspect-ratio: 3 / 2; }
.media-portrait img,
.media-square img,
.media-landscape img { width: 100%; height: 100%; object-fit: cover; border-radius: var(--radius-lg); }

/* --------------------------------------------------------------------------
   11. Cards
   -------------------------------------------------------------------------- */

.grid { display: grid; gap: 1px; background: var(--rule); border: 1px solid var(--rule); }
.grid--2 { grid-template-columns: minmax(0, 1fr); }
.grid--3 { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 700px) { .grid--2, .grid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.card {
  position: relative;
  background: var(--paper);
  padding: clamp(1.5rem, 2.6vw, 2.15rem);
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
  min-height: 100%;
  transition: background 0.22s var(--ease);
}
a.card:hover { background: var(--mist); }
a.card:hover .alink .arw { transform: translateX(4px); }

.card__title { font-family: var(--f-display); font-size: var(--t-h3); font-weight: 700; letter-spacing: -0.018em; line-height: 1.16; }
.card__body { color: var(--muted); font-size: 0.95rem; line-height: 1.62; flex: 1; }
.card__foot { margin-top: 0.4rem; }

.card__index {
  font-family: var(--f-display);
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: 0.14em;
  /* Quiet, but it is a label people read — the tracking and the size already
     carry the hierarchy. --rule-strong is for hairlines, not for text. */
  color: var(--muted);
}

/* Detached card variant used on light backgrounds without the hairline grid */
.tile {
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  padding: clamp(1.4rem, 2.4vw, 2rem);
  display: flex; flex-direction: column; gap: 0.7rem;
}
.tile--mist { background: var(--mist); border-color: transparent; }

.tiles { display: grid; gap: 1rem; }
@media (min-width: 700px) { .tiles--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 760px) { .tiles--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1040px) { .tiles--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 700px) { .tiles--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1040px) { .tiles--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* --------------------------------------------------------------------------
   12. Signal section — one per page. The page's full stop.
   -------------------------------------------------------------------------- */

.signal {
  background: var(--signal);
  /* Both stops are the lift colour so this is a pure alpha ramp — a different
     RGB at the transparent end would drag the midtones somewhere brighter
     than --signal-lift, and the contrast ceiling above assumes it does not. */
  background-image: radial-gradient(120% 140% at 78% 8%, var(--signal-lift) 0%, rgba(56, 71, 255, 0) 58%);
  color: #fff;
}
.signal h2, .signal h3 { color: #fff; }
.signal .lead,
.signal .muted,
.signal .small { color: var(--on-signal); }
.signal hr { border-color: rgba(255, 255, 255, 0.22); }

/* Links written into signal copy. The default --signal blue is the ground
   here, so it has to invert. */
.signal .tlink { color: #fff; box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.5); }
.signal .tlink:hover { box-shadow: inset 0 -1px 0 #fff; }

/* Maturity meter. The Essential Eight is scored in three discrete levels, so
   the mark is three discrete segments — not a continuous bar. */
.meter { display: grid; }

.meter__legend,
.meter__row {
  display: grid;
  align-items: center;
  grid-template-columns: minmax(0, 1fr) repeat(3, clamp(42px, 6.5vw, 76px));
  gap: 0.35rem;
}

.meter__legend {
  font-family: var(--f-display);
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--on-signal);
  padding-bottom: 0.6rem;
}
.meter__legend span + span { text-align: center; }

.meter__row {
  padding-block: 0.62rem;
  border-top: 1px solid rgba(255, 255, 255, 0.2);
}
.meter__row:last-child { border-bottom: 1px solid rgba(255, 255, 255, 0.2); }

.meter__name {
  font-family: var(--f-display);
  font-weight: 500;
  font-size: 0.95rem;
  letter-spacing: -0.008em;
  padding-right: 1rem;
}

.meter__seg {
  position: relative;
  height: 11px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.22);
  overflow: hidden;
}
.meter__seg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: #fff;
  transform-origin: left;
  transform: scaleX(var(--on, 0));
}

.meter__row[data-level="1"] .meter__seg:nth-child(-n + 2)::after,
.meter__row[data-level="2"] .meter__seg:nth-child(-n + 3)::after,
.meter__row[data-level="3"] .meter__seg:nth-child(-n + 4)::after { --on: 1; }

/* The bars carry a value, so they earn an animation: filling left to right
   reads as the score being measured rather than merely appearing. Driven from
   CSS rather than through Motion because the fill is a ::after pseudo-element,
   which the Web Animations API cannot target. site/js/animate.js only adds
   .is-filled, on first view. Without that module the segments are filled from
   the start. */
.js-motion .meter:not(.is-filled) .meter__seg::after { transform: scaleX(0); }
.js-motion .meter .meter__seg::after {
  transition: transform 0.55s var(--ease) calc(var(--r, 0) * 60ms);
}

.meter__key {
  display: flex; flex-wrap: wrap; gap: 0.4rem 1.5rem;
  margin-top: 1.15rem;
  font-size: 0.83rem;
  color: var(--on-signal);
}
.meter__key b { font-family: var(--f-display); font-weight: 600; color: #fff; }

/* --------------------------------------------------------------------------
   13. Stats
   -------------------------------------------------------------------------- */

.stats { display: grid; gap: 1px; background: var(--rule); border-block: 1px solid var(--rule); }
@media (min-width: 600px) { .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 940px) { .stats { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.stat { background: var(--paper); padding: clamp(1.4rem, 3vw, 2.25rem) clamp(1.25rem, 2.4vw, 2rem); }
.stat__num {
  font-family: var(--f-display);
  font-size: clamp(2.3rem, 4.4vw, 3.4rem);
  font-weight: 700; line-height: 1; letter-spacing: -0.04em; font-stretch: 88%;
}
.stat__label { margin-top: 0.6rem; font-size: 0.88rem; color: var(--muted); line-height: 1.45; }

.section--ink .stats { background: rgba(255, 255, 255, 0.22); border-color: rgba(255, 255, 255, 0.22); }
.section--ink .stat { background: var(--ink); }

/* On ink the cells are opaque, so the panel tint shows only in the 1px gaps
   and reads as hairlines. On the signal the cells are transparent — the tint
   floods the whole block — so it has to recess rather than lift: a white tint
   here washed the blue out to a point where even solid white text failed.
   The block is framed by its top and bottom rule instead. Tinting the cells
   as well does not restore the hairlines, it just stacks two tints and lands
   back on a lighter ground than the field. */
.signal .stats { background: rgba(0, 0, 0, 0.2); border-color: rgba(255, 255, 255, 0.3); }
.signal .stat { background: transparent; }
.signal .stat__label { color: var(--on-signal); }
.section--ink .stat__label { color: rgba(255, 255, 255, 0.68); }

/* --------------------------------------------------------------------------
   14. Steps — numbering only where order genuinely matters
   -------------------------------------------------------------------------- */

.steps { counter-reset: step; display: grid; gap: 0; }
.step {
  counter-increment: step;
  display: grid;
  gap: 0.5rem 1.75rem;
  padding-block: clamp(1.5rem, 3vw, 2.25rem);
  border-top: 1px solid var(--rule);
}
.step:last-child { border-bottom: 1px solid var(--rule); }
@media (min-width: 780px) {
  .step { grid-template-columns: 4.5rem minmax(0, 20ch) minmax(0, 1fr); align-items: start; }
}
.step::before {
  content: counter(step, decimal-leading-zero);
  font-family: var(--f-display);
  font-size: 0.82rem; font-weight: 600; letter-spacing: 0.1em;
  color: var(--signal);
  padding-top: 0.35rem;
}
.step__title { font-family: var(--f-display); font-size: var(--t-h3); font-weight: 700; letter-spacing: -0.018em; line-height: 1.18; }
.step__body { color: var(--muted); font-size: var(--t-small); line-height: 1.62; }
.signal .step { border-color: var(--on-signal-line); }
.signal .step::before { color: #fff; }
.signal .step__body { color: var(--on-signal); }
.section--ink .step { border-color: rgba(255, 255, 255, 0.24); }
.section--ink .step::before { color: #fff; }
.section--ink .step__body { color: rgba(255, 255, 255, 0.72); }

/* --------------------------------------------------------------------------
   15. Checklists & spec lists
   -------------------------------------------------------------------------- */

.checks { display: grid; gap: 0.7rem; }
.checks li { position: relative; padding-left: 1.4rem; line-height: 1.55; }
.checks li::before {
  content: ""; position: absolute; left: 0; top: 0.62em;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--sphere);
}
.checks--2 { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 720px) { .checks--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.7rem 2.5rem; } }

.checks--3 { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 640px) { .checks--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.6rem 2.5rem; } }
@media (min-width: 1000px) { .checks--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.6rem 2.5rem; } }

/* Industry index: name plus a one-line qualifier, kept on one visual level. */
.checks--index li { line-height: 1.45; }
.checks--index b { font-family: var(--f-display); font-weight: 600; letter-spacing: -0.012em; display: block; }
.checks--index span { font-size: 0.88rem; color: var(--muted); }
.signal .checks li::before { background: #fff; }

.speclist { display: grid; }
.speclist > div {
  display: grid; gap: 0.2rem 2rem;
  padding-block: 1.15rem;
  border-top: 1px solid var(--rule);
}
.speclist > div:last-child { border-bottom: 1px solid var(--rule); }
@media (min-width: 720px) { .speclist > div { grid-template-columns: minmax(0, 15rem) minmax(0, 1fr); align-items: baseline; } }
.speclist dt { font-family: var(--f-display); font-weight: 600; letter-spacing: -0.012em; }
.speclist dd { color: var(--muted); font-size: var(--t-small); line-height: 1.6; }

/* --------------------------------------------------------------------------
   16. Tables
   -------------------------------------------------------------------------- */

.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; min-width: 0; max-width: 100%; }

/* Tables keep their columns and scroll sideways on small screens. Say so,
   because an overlay scrollbar gives no hint that there is more to the right. */
.table-hint {
  display: none;
  align-items: center; gap: 0.45rem;
  margin-top: 0.7rem;
  font-size: 0.8rem; color: var(--muted);
}
.table-hint::before {
  content: ""; flex: none;
  width: 6px; height: 6px; border-radius: 50%; background: var(--sphere);
}
.signal .table-hint { color: var(--on-signal); }
.signal .table-hint::before { background: #fff; }
@media (max-width: 760px) { .table-hint { display: flex; } }
.table { width: 100%; border-collapse: collapse; min-width: 640px; font-size: var(--t-small); }
.table th, .table td { text-align: left; padding: 1rem 1.15rem; border-bottom: 1px solid var(--rule); vertical-align: top; }
.table thead th {
  font-family: var(--f-display); font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted);
  border-bottom-color: var(--rule-strong);
}
.table tbody th { font-family: var(--f-display); font-weight: 600; letter-spacing: -0.012em; font-size: var(--t-body); }
.table td { color: var(--muted); }
.table .yes { color: var(--signal); font-weight: 600; }
/* "Not included" is still a value the reader has to read, so it is quieter
   than --muted only in weight. --rule-strong is a hairline colour and came
   out at 1.6:1 against paper. */
.table .no { color: var(--muted); }

/* A table on a dark ground. `.table td` and `.table thead th` set a colour on
   the cell itself, so a colour inherited from the section — or from a style
   attribute on the <table> or <tbody> — never reaches it. The override has to
   land on the same elements, or the copy stays --muted grey on blue at
   1:1 and disappears. Do not solve this per-page with inline styles. */
.signal .table,
.signal .table tbody th { color: #fff; }
.signal .table th,
.signal .table td { border-bottom-color: var(--on-signal-line); }
.signal .table thead th { color: var(--on-signal); border-bottom-color: rgba(255, 255, 255, 0.5); }
.signal .table td { color: var(--on-signal); }
.signal .table .yes { color: #fff; }
.signal .table .no { color: var(--on-signal); }

.section--ink .table,
.section--ink .table tbody th { color: #fff; }
.section--ink .table th,
.section--ink .table td { border-bottom-color: rgba(255, 255, 255, 0.24); }
.section--ink .table thead th { color: var(--on-ink); border-bottom-color: rgba(255, 255, 255, 0.4); }
.section--ink .table td,
.section--ink .table .no { color: rgba(255, 255, 255, 0.78); }
.section--ink .table .yes { color: #fff; }

/* --------------------------------------------------------------------------
   17. Accordion (FAQ)
   -------------------------------------------------------------------------- */

.faq { border-top: 1px solid var(--rule); }
.faq details { border-bottom: 1px solid var(--rule); }
.faq summary {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 1.5rem;
  padding-block: 1.35rem;
  cursor: pointer; list-style: none;
  font-family: var(--f-display); font-weight: 600; font-size: 1.06rem;
  letter-spacing: -0.014em; line-height: 1.35;
  transition: color 0.18s var(--ease);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--signal); }
.faq summary::after {
  content: ""; flex: none;
  width: 13px; height: 13px; margin-top: 0.4rem;
  background: currentColor;
  clip-path: polygon(46% 0, 54% 0, 54% 46%, 100% 46%, 100% 54%, 54% 54%, 54% 100%, 46% 100%, 46% 54%, 0 54%, 0 46%, 46% 46%);
  transition: transform 0.24s var(--ease);
}
.faq details[open] summary::after { transform: rotate(135deg); }
.faq__body { padding-bottom: 1.5rem; color: var(--muted); max-width: 68ch; }
.faq__body > * + * { margin-top: 0.9rem; }

/* --------------------------------------------------------------------------
   18. Logo wall
   -------------------------------------------------------------------------- */

/* The 1px gaps show the wall's background through, so the cells have to tile
   the grid exactly — any cell shorter than its row leaves a grey strip. The
   row height therefore lives here rather than on the cell: floored at the
   tallest content it can hold (34px logo + 1.25rem padding, top and bottom)
   so a cell is never asked to be shorter than what is inside it.

   Do NOT put an aspect-ratio on the cell to do this. An item with an
   aspect-ratio does not stretch to its grid area, which is what caused the
   grey underlines; and once its height is made definite the ratio starts
   resolving the *width* instead, which overflowed the page at 320px. */
.logowall { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-rows: minmax(74px, auto); gap: 1px; background: var(--rule); border: 1px solid var(--rule); }
@media (min-width: 620px) {
  .logowall { grid-template-columns: repeat(3, minmax(0, 1fr)); grid-auto-rows: minmax(clamp(74px, 11.5vw, 108px), auto); }
}
@media (min-width: 940px) { .logowall { grid-template-columns: repeat(5, minmax(0, 1fr)); grid-auto-rows: minmax(74px, auto); } }
.logowall__cell {
  background: var(--paper);
  display: grid; place-items: center;
  padding: 1.25rem 0.85rem;
  min-width: 0;
}
/* Constrain both axes. Height alone would let a wide wordmark (Dell, Crowdstrike)
   dwarf a squarer one (Meraki, Pax8) and the wall would read as uneven. */
.logowall__cell img {
  max-height: 34px;
  max-width: 76%;
  width: auto;
  object-fit: contain;
  opacity: 0.62;
  filter: grayscale(1);
  transition: opacity 0.2s var(--ease), filter 0.2s var(--ease);
}
.logowall__cell:hover img { opacity: 1; filter: grayscale(0); }
.logowall__cell span {
  font-family: var(--f-display); font-weight: 600; font-size: 0.85rem;
  letter-spacing: 0.02em; color: var(--muted); text-align: center;
  max-width: 100%; overflow-wrap: anywhere; line-height: 1.3;
}

/* --------------------------------------------------------------------------
   19. Pull quote
   -------------------------------------------------------------------------- */

.pull { display: grid; gap: 1.5rem; }
.pull blockquote {
  font-family: var(--f-display);
  font-size: clamp(1.4rem, 2.6vw, 2.15rem);
  font-weight: 500; line-height: 1.24; letter-spacing: -0.026em;
  text-wrap: balance;
}
.pull figcaption { font-size: var(--t-small); color: var(--muted); }
.pull figcaption b { display: block; color: var(--ink); font-family: var(--f-display); font-weight: 600; letter-spacing: -0.01em; }
.signal .pull figcaption { color: var(--on-signal); }
/* The attribution is set in --ink, so on a dark ground it was ink on ink. */
.signal .pull figcaption b,
.section--ink .pull figcaption b { color: #fff; }
.section--ink .pull figcaption { color: var(--on-ink); }

/* --------------------------------------------------------------------------
   20. Forms
   -------------------------------------------------------------------------- */

.form { display: grid; gap: 1.15rem; }
.form__row { display: grid; gap: 1.15rem; }
@media (min-width: 640px) { .form__row--2 { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }

.field { display: grid; gap: 0.4rem; }
.field > label {
  font-family: var(--f-display); font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted);
}
.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 0.85rem 1rem;
  background: var(--paper);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  transition: border-color 0.18s var(--ease), box-shadow 0.18s var(--ease);
}
.field textarea { min-height: 140px; resize: vertical; }
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--signal);
  box-shadow: 0 0 0 3px rgba(47, 63, 255, 0.14);
}
.field__hint { font-size: 0.8rem; color: var(--muted); }

.consent { display: flex; align-items: flex-start; gap: 0.7rem; font-size: 0.86rem; color: var(--muted); }
.consent input { margin-top: 0.25rem; width: 16px; height: 16px; accent-color: var(--signal); flex: none; }

.form-note {
  font-size: 0.82rem; color: var(--muted);
  border-left: 2px solid var(--signal); padding-left: 0.9rem;
}

/* --------------------------------------------------------------------------
   21. Contact rows
   -------------------------------------------------------------------------- */

.contact-list { display: grid; gap: 0; }
.contact-list > div { padding-block: 1.25rem; border-top: 1px solid var(--rule); }
.contact-list > div:last-child { border-bottom: 1px solid var(--rule); }
.contact-list dt {
  font-family: var(--f-display); font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); margin-bottom: 0.3rem;
}
.contact-list dd { font-family: var(--f-display); font-size: 1.12rem; font-weight: 600; letter-spacing: -0.018em; }
.contact-list dd a:hover { color: var(--signal); }

/* --------------------------------------------------------------------------
   22. Article / insights
   -------------------------------------------------------------------------- */

.article-meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1rem;
  font-family: var(--f-display); font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted);
}
.article-meta .dot-sep { width: 4px; height: 4px; border-radius: 50%; background: var(--rule-strong); }

.prose { max-width: 68ch; }
.prose > * + * { margin-top: 1.15rem; }
.prose h2 { font-size: clamp(1.5rem, 2.4vw, 2rem); margin-top: 2.75rem; }
.prose h3 { font-size: var(--t-h3); margin-top: 2.25rem; }
.prose h2 + p, .prose h3 + p { margin-top: 0.85rem; }
.prose ul { display: grid; gap: 0.6rem; }
.prose ul li { position: relative; padding-left: 1.4rem; }
.prose ul li::before {
  content: ""; position: absolute; left: 0; top: 0.62em;
  width: 7px; height: 7px; border-radius: 50%; background: var(--sphere);
}
.prose ol { display: grid; gap: 0.6rem; counter-reset: pl; }
.prose ol li { position: relative; padding-left: 1.9rem; counter-increment: pl; }
.prose ol li::before {
  content: counter(pl) "."; position: absolute; left: 0; top: 0;
  font-family: var(--f-display); font-weight: 600; color: var(--signal);
}
.prose strong { font-weight: 600; color: var(--ink); }
.prose blockquote {
  border-left: 2px solid var(--signal);
  padding-left: 1.25rem;
  font-size: 1.1rem;
  color: var(--ink-soft);
}

.toc { border: 1px solid var(--rule); border-radius: var(--radius-lg); padding: 1.25rem 1.4rem; }
.toc ol { display: grid; gap: 0.5rem; margin-top: 0.75rem; counter-reset: toc; }
.toc li { counter-increment: toc; font-size: var(--t-small); }
.toc a { color: var(--muted); }
.toc a:hover { color: var(--signal); }
/* Set by the scroll-spy. Weight and colour only — the rest of the site marks
   state that way, and a rule or dot here would fight the numbered list. */
.toc a[aria-current="location"] { color: var(--ink); font-weight: 600; }

/* Related reading. Two pieces per article, chosen on subject rather than
   recency — the point is to answer the next question, not to fill a slot. */
.related-reading {
  margin-top: 3rem; padding-top: 1.75rem;
  border-top: 1px solid var(--rule);
}
.related-reading__head {
  font-family: var(--f-display); font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted);
  margin-bottom: 1rem;
}
.related-reading__head .stop { width: 0.34em; height: 0.34em; margin-left: 0.2em; }
.related-reading ul { display: grid; gap: 0.7rem; list-style: none; }
.related-reading li { font-family: var(--f-display); font-size: 1.06rem; line-height: 1.35; }

/* Share row at the foot of an article. Hidden until scripting confirms the
   clipboard is actually available, so there is never a button that does
   nothing. */
.share {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem;
  margin-top: 2.5rem; padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
}
.share[hidden] { display: none; }
.share__label {
  font-family: var(--f-display); font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted);
}
.share__btn {
  font: inherit; font-size: 0.86rem; font-weight: 500;
  padding: 0.45rem 0.9rem;
  border: 1px solid var(--rule-strong); border-radius: 999px;
  background: transparent; color: var(--ink); cursor: pointer;
  transition: border-color 0.18s var(--ease), color 0.18s var(--ease);
}
.share__btn:hover { border-color: var(--ink); }
.share__btn[hidden] { display: none; }
.share__status { font-size: 0.82rem; color: var(--muted); }

/* --------------------------------------------------------------------------
   Insights search

   Ships hidden and is revealed by site/js/search.js, so with scripting off
   the reader simply gets the full article list with no dead input.
   -------------------------------------------------------------------------- */

.search { margin-bottom: 2.5rem; }
.search[hidden] { display: none; }
.search__label {
  display: block; margin-bottom: 0.6rem;
  font-family: var(--f-display); font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted);
}
.search__input {
  width: 100%; font: inherit; font-size: 1.02rem;
  padding: 0.85rem 1.1rem;
  color: var(--ink); background: var(--paper);
  border: 1px solid var(--rule-strong); border-radius: var(--radius-lg);
  transition: border-color 0.18s var(--ease);
}
.search__input::placeholder { color: var(--muted); }
.search__input:focus { border-color: var(--signal); outline: none; }
.search__input:focus-visible { outline: 2px solid var(--signal); outline-offset: 2px; }
.search__status { margin-top: 0.7rem; font-size: 0.86rem; color: var(--muted); }
.search__results:not(:empty) { margin-top: 1.5rem; }
/* Pagefind wraps matched terms in <mark>. */
.search__results mark {
  background: transparent; color: var(--ink); font-weight: 600;
}

/* --------------------------------------------------------------------------
   23. Footer
   -------------------------------------------------------------------------- */

.site-footer { background: var(--ink); color: #fff; padding-block: clamp(3.5rem, 6vw, 5.5rem) 2rem; }

.site-footer__top { display: grid; gap: 2.75rem; }
@media (min-width: 900px) {
  .site-footer__top { grid-template-columns: minmax(0, 1.25fr) repeat(3, minmax(0, 0.85fr)); gap: 3rem; }
}

.footer-tagline {
  font-family: var(--f-display);
  font-size: clamp(1.6rem, 3vw, 2.35rem);
  font-weight: 700; line-height: 1.1; letter-spacing: -0.032em;
  margin-top: 1.5rem;
  font-stretch: 90%;
}
/* Direct children only — a descendant selector here would also catch the
   nested .stop and knock each full stop onto its own line. */
.footer-tagline > span { display: block; }

.footer-col h2 {
  font-family: var(--f-display); font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase; color: rgba(255, 255, 255, 0.5);
  margin-bottom: 1rem;
}
.footer-col ul { display: grid; gap: 0.6rem; }
.footer-col a { color: rgba(255, 255, 255, 0.78); font-size: var(--t-small); transition: color 0.18s var(--ease); }
.footer-col a:hover { color: #fff; }

.site-footer__bottom {
  margin-top: clamp(3rem, 5vw, 4.5rem);
  padding-top: 1.75rem;
  border-top: 1px solid rgba(255, 255, 255, 0.16);
  display: flex; flex-wrap: wrap; gap: 0.85rem 2rem;
  align-items: center; justify-content: space-between;
  font-size: 0.82rem; color: rgba(255, 255, 255, 0.55);
}
.site-footer__bottom a { color: rgba(255, 255, 255, 0.72); }
.site-footer__bottom a:hover { color: #fff; }
.site-footer__legal { display: flex; flex-wrap: wrap; gap: 1.25rem; }


/* --------------------------------------------------------------------------
   24. CTA block
   -------------------------------------------------------------------------- */

.cta-block { display: grid; gap: 2rem; align-items: end; }
@media (min-width: 880px) { .cta-block { grid-template-columns: minmax(0, 1fr) auto; gap: 3.5rem; } }
.cta-block h2 { max-width: 18ch; }

/* --------------------------------------------------------------------------
   25. Motion
   -------------------------------------------------------------------------- */

/* Section-wide scroll reveals were removed: every block fading up as it
   entered the viewport read as clunky, and it delayed content the reader had
   already scrolled to. What is left is deliberate and small.

   The remaining animation is driven by site/js/animate.js through the Web
   Animations API, so it runs on the compositor rather than in JavaScript.
   The only state this stylesheet owns is the starting position — scoped to
   .js-motion, which that module sets on itself. If the module never loads,
   or the reader prefers reduced motion, nothing is ever hidden. */
.js-motion .hero__line,
.js-motion .hero__aside { opacity: 0; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .js-motion .hero__line,
  .js-motion .hero__aside { opacity: 1; transform: none; }
  .led::after { display: none; }
  /* The blanket animation-duration override above does not reach the
     view-transition pseudo-elements, so the transition is declined outright. */
  @view-transition { navigation: none; }
}

/* --------------------------------------------------------------------------
   Cross-document view transitions

   Both the outgoing and incoming page opt in through this stylesheet, so
   same-origin navigation cross-fades instead of flashing white. Kept short:
   the point is to remove the flash, not to add choreography. Declined
   entirely under prefers-reduced-motion, above.
   -------------------------------------------------------------------------- */

@view-transition { navigation: auto; }

::view-transition-old(root),
::view-transition-new(root) { animation-duration: 160ms; }

/* The header and footer are identical on every page. Naming them holds them
   still rather than cross-fading each with an identical copy of itself. */
.site-header { view-transition-name: site-header; }
.site-footer { view-transition-name: site-footer; }

/* --------------------------------------------------------------------------
   26. Utilities
   -------------------------------------------------------------------------- */

.mt-0 { margin-top: 0; }
.mt-1 { margin-top: 0.75rem; }
.mt-2 { margin-top: 1.5rem; }
.mt-3 { margin-top: 2.25rem; }
.mt-4 { margin-top: 3rem; }
.mt-5 { margin-top: clamp(3rem, 6vw, 5rem); }
.max-46 { max-width: 46ch; }
.max-56 { max-width: 56ch; }
.max-64 { max-width: 64ch; }
.text-signal { color: var(--signal); }
.nowrap { white-space: nowrap; }

@media print {
  .site-header, .site-footer, .statusbar, .burger { display: none; }
  body { color: #000; }
}
