/* ============================================================
   Novus Point — novus-point.co.uk
   "Bone, with one dark band" — light ground, single tonal accent.

   Three rulings drive this sheet:
   · SITE-STRUCTURE-PLAN §I (2026-08-26) — THE LIGHT FLIP. Decision 1 (dark
     base) is REVERSED. The ground is bone #F2F0EC on every page; sections are
     separated by a hairline rule, not by a change of colour; and each page
     carries EXACTLY ONE `white-on-abyss` band, placed on its central claim.
     :root therefore declares the ink-on-bone values, so a page with no
     data-color-scheme attribute renders light.
   · TYPEFACE-PANEL.md (2026-08-26) — Source Serif 4 is the DISPLAY face
     (h1/h2/h3 and the big card headings, sentence case, never uppercase,
     never below 26px). Montserrat keeps every UI role: eyebrows, nav, buttons,
     panel heads, ledger names, card links, footer titles, labels, numerals.
     Lato keeps body and leads.
   · Restraint over texture. The global dot grid and film grain are retired and
     bone bands carry `--cs-atmos: none`. On cream, a tinted radial reads as a
     stain and a noise layer reads as dirt. What separates two sections is one
     hairline; what carries the small print is the .caption layer at 11px/0.14em.

   Colour rule of the house: #4fc3d9 means ACTION, and since the flip it means
   action ON THE DARK BAND ONLY — on bone the primary button is brand blue
   #004868 with white text. Eyebrows and in-headline accents read from the
   scheme. Greens (#26b75c, #bbd319) are never text — status dots only.

   Every component reads --cs-* tokens. Change one attribute on a section and
   the whole module re-colours. Anything that must stay fixed across bands (the
   nav, the footer floor) carries literal values and says so at the rule.
   ============================================================ */

:root {
  /* ---- Brand book (Novus Point Brand Guidelines) ---- */
  --blue: #004868;         /* Dark Blue  */
  --teal: #00798e;         /* Dark Cyan  */
  --cyan: #4fc3d9;         /* action fill — the only light vivid we own */
  --lime: #26b75c;         /* live status only, never text */
  --grass: var(--cyan);    /* legacy alias — kept so old rules keep resolving */
  --accent: var(--cyan);          /* legacy alias */
  --accent-deep: var(--teal);     /* legacy alias */
  --live: var(--lime);

  /* ---- Proposed extensions — NO brand-book authority, flagged --ext-* ---- */
  --ext-bone: #F2F0EC;     /* warm neutral band          */
  --ext-mist: #DFF1F5;     /* pale teal band             */
  --ext-ink:  #1A2B33;     /* softened navy-black        */
  --ext-teal-aa: #00697C;  /* #00798e fails AA at 11.5px on bone (4.47:1);
                              this measures 5.57:1 on bone, 5.45:1 on mist  */

  /* ---- Atmosphere ---- */
  --abyss: #011721;        /* page base */
  --deep:  #022634;        /* section elevation 1 */
  --panel: rgba(255, 255, 255, 0.055);
  --panel-hover: rgba(255, 255, 255, 0.09);
  --line: rgba(255, 255, 255, 0.08);
  --line-strong: rgba(255, 255, 255, 0.14);

  /* Text on dark — kept as tokens for the nav and footer chrome, which are
     dark on every page regardless of the band they sit against. */
  --ink-hi: #E5F0F3;
  --ink-mid: rgba(229, 240, 243, 0.72);
  --ink-low: rgba(229, 240, 243, 0.62);

  --grad-accent: linear-gradient(92deg, #4fc3d9, #00798e);
  --grad-green:  var(--grad-accent);   /* legacy alias */
  --grad-sea:    linear-gradient(120deg, #00798e, #004868);
  --grad-edge: linear-gradient(140deg,
      rgba(79, 195, 217, 0.28),
      rgba(0, 121, 142, 0.24) 42%,
      rgba(255, 255, 255, 0.06) 78%,
      rgba(255, 255, 255, 0.03));
  --grad-edge-hot: linear-gradient(140deg,
      rgba(79, 195, 217, 0.60),
      rgba(0, 121, 142, 0.46) 45%,
      rgba(255, 255, 255, 0.12));

  /* ---- Elevation ---- */
  --e-1: 0 1px 2px rgba(0, 0, 0, 0.4);
  --e-2: 0 24px 60px rgba(0, 0, 0, 0.35);
  --e-light: 0 1px 2px rgba(1, 23, 33, 0.06);
  --e-light-2: 0 18px 44px rgba(1, 23, 33, 0.10);

  /* ---- Radius — Decision 6a retired the 999px pill ---- */
  --r-sm: 10px;
  --r-md: 16px;
  --r-lg: 22px;
  --r-xl: 26px;

  /* ---- Spacing (4px base) ---- */
  --s-1: 4px;  --s-2: 8px;   --s-3: 12px;  --s-4: 16px;
  --s-6: 24px; --s-8: 32px;  --s-12: 48px; --s-14: 56px; --s-16: 64px;
  --s-24: 96px; --s-28: 112px;

  --ease: cubic-bezier(0.16, 1, 0.3, 1);

  /* Band padding — fixed 104/118px cost 208-236px per boundary on a phone. */
  --band-pad: clamp(56px, 8.4vw, 112px);

  --w-wide: 1080px;      /* light flip — editorial column, was 1160 */
  --w-read: 820px;
  --w-col: 920px;

  /* ---- Type stacks. Three voices, three jobs. ---- */
  --font-display: 'Source Serif 4', Georgia, 'Times New Roman', serif;
  --font-ui:      'Montserrat', 'Avenir Next', 'Segoe UI', sans-serif;
  --font-body:    'Lato', 'Helvetica Neue', Arial, sans-serif;

  /* Display coordinates — panel conditions 5 and 6.
     line-height is UNITLESS: a unit value destroys the zero-CLS property. */
  --display-lh: 1.06;
  --display-ls: -0.012em;      /* never carry Montserrat's -0.035em onto serif */
  --display-ls-sm: -0.004em;
  --display-w-hero: 380;       /* >=350 on dark; never 300 on a dark ground */
  --display-w-h2: 400;         /* lightened to 360 above 1024px, where h2 >= 40px */
  --display-w-h3: 400;         /* the serif floor: >=400 below ~40px */

  --fs-body: 1rem;
  --fs-small: 0.9rem;
  --fs-micro: 0.82rem;
  /* 28px — the BCG standfirst, Decision C.2 "do this regardless". Held exactly
     from ~825px up; floored at 24px on phones, where 28px/34ch wraps to nine
     lines of display-scale type. */
  --fs-lead: clamp(1.5rem, 3.4vw, 1.75rem);
  --fs-h3: 1.625rem;    /* 26px — the serif floor, exactly */

  --fs-eyebrow: 11.5px;
  --ls-eyebrow: 0.12em;        /* Decision 3 — brand-book value */

  /* ---- Textures, referenced by both the body plate and the dark schemes ---- */
  --tex-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='0.055'/%3E%3C/svg%3E");
  --tex-dots: radial-gradient(rgba(255, 255, 255, 0.06) 1px, transparent 1px);

  /* The logo rhombus at marker size. Two inks: brand gradient for dark grounds,
     solid Dark Blue for light bands, where the cyan stroke disappears. */
  --mark-echo: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'%3E%3ClinearGradient id='m' x1='2' y1='2' x2='22' y2='22' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%234fc3d9'/%3E%3Cstop offset='1' stop-color='%2300798e'/%3E%3C/linearGradient%3E%3Cpath d='M12 2.4 21.6 12 12 21.6 2.4 12Z' stroke='url(%23m)' stroke-width='2'/%3E%3Cpath d='M11 7.9 15.1 12 11 16.1' stroke='url(%23m)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --mark-echo-ink: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'%3E%3Cpath d='M12 2.4 21.6 12 12 21.6 2.4 12Z' stroke='%23004868' stroke-width='2'/%3E%3Cpath d='M11 7.9 15.1 12 11 16.1' stroke='%23004868' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --mark-frame: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'%3E%3ClinearGradient id='f' x1='3' y1='3' x2='21' y2='21' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%234fc3d9'/%3E%3Cstop offset='1' stop-color='%2300798e'/%3E%3C/linearGradient%3E%3Cpath d='M12 1.6 22.4 12 12 22.4 1.6 12Z' stroke='url(%23f)' stroke-width='0.7'/%3E%3C/svg%3E");
  --mark-frame-ink: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'%3E%3Cpath d='M12 1.6 22.4 12 12 22.4 1.6 12Z' stroke='%23004868' stroke-width='0.8' opacity='0.55'/%3E%3C/svg%3E");
}

/* ============================================================
   COLOUR SCHEMES — the contract every component reads from

   --cs-bg          module ground
   --cs-color       primary text
   --cs-dim         secondary text (>= 4.5:1 on --cs-bg and on --cs-panel)
   --cs-rule        hairlines, dividers
   --cs-rule-strong visible outlines (ghost button, toggle)
   --cs-eyebrow     eyebrows, labels, kickers
   --cs-accent      in-headline accent, decorative rules — NEVER the action colour
   --cs-link        links and inline anchors — the action colour for this ground
   --cs-link-hover
   --cs-panel       card fill
   --cs-edge / --cs-edge-hot   .edge hairline
   --cs-focus       :focus-visible ring
   --cs-mark / --cs-frame      logo rhombus ink
   --cs-atmos / --cs-atmos-size / --cs-atmos-repeat   band atmosphere
   --cs-dot-ring    halo behind a status dot

   Measured (WCAG 2.x, sRGB):
   abyss  #E5F0F3 15.79 · dim .72 8.50 · #A8DCE8 12.28 · #4fc3d9 8.85
   blue   #FFFFFF  9.87 · dim .80 6.90 · #BFE9F2  7.59 · #4fc3d9 4.77
   bone   #011721 16.10 · #46555e 6.78 (7.72 on white card) · #00697C 5.57
   mist   #011721 15.74 · #3d5058 7.25 (8.44 on white card) · #00697C 5.45
   fills  #011721 on #4fc3d9 8.85 · #FFFFFF on #00798e 5.09
   ============================================================ */

[data-color-scheme] {
  position: relative;
  isolation: isolate;          /* lets the atmosphere sit at z-index -1, above
                                  the band ground and below all content */
  background-color: var(--cs-bg);
  color: var(--cs-color);
}
[data-color-scheme]::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image: var(--cs-atmos);
  background-size: var(--cs-atmos-size, auto);
  background-repeat: var(--cs-atmos-repeat, no-repeat);
}

/* Ruling of 2026-08-26 (light flip): the site's ground is bone. One continuous
   warm ground, sections separated by a hairline rule, and exactly ONE dark band
   per page as the single tonal accent. Root therefore defaults to ink-on-bone,
   so an unschemed page renders light rather than dark. */
[data-color-scheme="white-on-abyss"] {
  --cs-bg: #011721;
  --cs-color: #E5F0F3;
  --cs-dim: rgba(229, 240, 243, 0.72);
  --cs-rule: rgba(229, 240, 243, 0.12);
  --cs-rule-strong: rgba(229, 240, 243, 0.24);
  --cs-eyebrow: #A8DCE8;
  --cs-accent: #A8DCE8;
  --cs-link: #4fc3d9;
  --cs-link-hover: #9ee3f2;
  --cs-panel: rgba(255, 255, 255, 0.055);
  --cs-panel-hover: rgba(255, 255, 255, 0.09);
  --cs-edge: var(--grad-edge);
  --cs-edge-hot: var(--grad-edge-hot);
  --cs-focus: #4fc3d9;
  --cs-mark: var(--mark-echo);
  --cs-frame: var(--mark-frame);
  --cs-shadow: var(--e-2);
  --cs-dot-ring: rgba(38, 183, 92, 0.16);
  --cs-live: var(--lime);
  --cs-atmos:
    var(--tex-grain),
    var(--tex-dots),
    radial-gradient(46rem 30rem at 88% -10%, rgba(0, 121, 142, 0.30), transparent 62%),
    radial-gradient(40rem 28rem at -10% 26%, rgba(0, 72, 104, 0.45), transparent 66%);
  --cs-atmos-size: 180px 180px, 26px 26px, auto, auto;
  --cs-atmos-repeat: repeat, repeat, no-repeat, no-repeat;
}

[data-color-scheme="white-on-blue"] {
  --cs-bg: #004868;
  --cs-color: #FFFFFF;
  --cs-dim: rgba(255, 255, 255, 0.80);
  --cs-rule: rgba(255, 255, 255, 0.20);
  --cs-rule-strong: rgba(255, 255, 255, 0.38);
  --cs-eyebrow: #BFE9F2;
  --cs-accent: #BFE9F2;
  --cs-link: #FFFFFF;
  --cs-link-hover: #BFE9F2;
  --cs-panel: rgba(255, 255, 255, 0.08);
  --cs-panel-hover: rgba(255, 255, 255, 0.13);
  --cs-edge: linear-gradient(140deg, rgba(255, 255, 255, 0.34), rgba(255, 255, 255, 0.10) 60%, rgba(255, 255, 255, 0.05));
  --cs-edge-hot: linear-gradient(140deg, rgba(255, 255, 255, 0.60), rgba(255, 255, 255, 0.18));
  --cs-focus: #BFE9F2;
  --cs-mark: var(--mark-echo);
  --cs-frame: var(--mark-frame);
  --cs-shadow: 0 24px 60px rgba(0, 30, 44, 0.34);
  --cs-dot-ring: rgba(255, 255, 255, 0.22);
  --cs-live: var(--lime);
  --cs-atmos:
    var(--tex-grain),
    radial-gradient(48rem 30rem at 94% 4%, rgba(79, 195, 217, 0.16), transparent 62%),
    radial-gradient(42rem 30rem at -8% 96%, rgba(1, 23, 33, 0.30), transparent 66%);
  --cs-atmos-size: 180px 180px, auto, auto;
  --cs-atmos-repeat: repeat, no-repeat, no-repeat;
}

:root,
[data-color-scheme="ink-on-bone"] {
  --cs-bg: #F2F0EC;
  --cs-color: #011721;
  --cs-dim: #46555e;
  --cs-rule: rgba(1, 23, 33, 0.14);
  --cs-rule-strong: rgba(1, 23, 33, 0.50);   /* 3.37:1 — .btn--ghost's only boundary */
  --cs-eyebrow: #00697C;
  --cs-accent: #004868;
  --cs-link: #00697C;
  --cs-link-hover: #011721;
  --cs-panel: #FFFFFF;
  --cs-panel-hover: #FFFFFF;
  --cs-edge: linear-gradient(140deg, rgba(1, 23, 33, 0.14), rgba(1, 23, 33, 0.07) 60%, rgba(1, 23, 33, 0.05));
  --cs-edge-hot: linear-gradient(140deg, rgba(0, 105, 124, 0.45), rgba(1, 23, 33, 0.12));
  --cs-focus: #004868;
  --cs-mark: var(--mark-echo-ink);
  --cs-frame: var(--mark-frame-ink);
  --cs-shadow: var(--e-light-2);
  --cs-dot-ring: rgba(1, 23, 33, 0.18);
  /* #26b75c measures 2.30:1 on bone and 2.62:1 on white — below the 3:1 that
     WCAG 1.4.11 requires of a graphic carrying meaning, and these dots encode
     in-force versus not-yet-in-force. Darkened for the light grounds:
     4.17:1 on bone, 4.75:1 on a white card. */
  --cs-live: #1a8442;
  /* Light flip: no atmosphere on the bone ground. A tinted radial on cream
     reads as a stain or a printing fault, never as depth. */
  --cs-atmos: none;
}

[data-color-scheme="ink-on-mist"] {
  --cs-bg: #DFF1F5;
  --cs-color: #011721;
  --cs-dim: #3d5058;
  --cs-rule: rgba(1, 23, 33, 0.16);
  --cs-rule-strong: rgba(1, 23, 33, 0.50);   /* 3.37:1 — .btn--ghost's only boundary */
  --cs-eyebrow: #00697C;
  --cs-accent: #004868;
  --cs-link: #00697C;
  --cs-link-hover: #011721;
  --cs-panel: #FFFFFF;
  --cs-panel-hover: #FFFFFF;
  --cs-edge: linear-gradient(140deg, rgba(1, 23, 33, 0.15), rgba(1, 23, 33, 0.07) 60%, rgba(1, 23, 33, 0.05));
  --cs-edge-hot: linear-gradient(140deg, rgba(0, 105, 124, 0.45), rgba(1, 23, 33, 0.12));
  --cs-focus: #004868;
  --cs-mark: var(--mark-echo-ink);
  --cs-frame: var(--mark-frame-ink);
  --cs-shadow: var(--e-light-2);
  --cs-dot-ring: rgba(1, 23, 33, 0.18);
  /* #26b75c measures 2.30:1 on bone and 2.62:1 on white — below the 3:1 that
     WCAG 1.4.11 requires of a graphic carrying meaning, and these dots encode
     in-force versus not-yet-in-force. Darkened for the light grounds:
     4.17:1 on bone, 4.75:1 on a white card. */
  --cs-live: #1a8442;
  --cs-atmos: none;
}

/* ---------------------------------------------------------- reset */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; scroll-padding-top: 90px; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.65;
  color: var(--cs-dim);
  background-color: var(--ext-bone);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img { max-width: 100%; height: auto; display: block; }
ul, ol { list-style: none; }
a { color: inherit; }

::selection { background: rgba(79, 195, 217, 0.28); color: #011721; }

/* ---------------------------------------------------------- typographic rhythm */
h1, h2, h3,
.hero__title, .contact__title, .h2, .h3,
.creds__mark, .principal__name {
  text-wrap: balance;
}
p, .body, .lead, .hero__lead, .creds__line, .note {
  text-wrap: pretty;
}

/* ---------------------------------------------------------- page atmosphere
   The plate: three fixed layers, all at negative z-index, all BEHIND every
   scheme module. On a banded page they show only where a module is
   transparent; on an unschemed page (404) they are the whole atmosphere.
   Dark schemes carry their own copy of the grain and the dot grid so the
   texture survives the opaque band without ever washing over a light one. */
.page-bg {
  position: fixed;
  inset: 0;
  z-index: -3;
  pointer-events: none;
  /* Light flip: the aurora was the signature of the dark build. On bone it
     would read as a stain, so what remains is a single near-invisible warm
     lift at the top of the page and the flat ground underneath. */
  background:
    radial-gradient(60rem 34rem at 84% -8%, rgba(0, 121, 142, 0.045), transparent 64%),
    var(--ext-bone);
}
/* The dot grid and the page-wide film grain were both calibrated as white-on-
   dark. On a bone ground they read as dirt rather than texture, and the light
   flip's whole argument is that the premium register comes from restraint. Both
   global texture layers are therefore retired. The markup stays (it is inert and
   aria-hidden) and the dark bands keep their own grain through --cs-atmos. */
.page-grid { display: none; }
body::after { content: none; }

/* ---------------------------------------------------------- helpers */
.container { width: 100%; margin-inline: auto; padding-inline: clamp(20px, 5vw, 48px); }
.container--narrow,
.container--mid { max-width: var(--w-read); }
.container--wide { max-width: var(--w-wide); }

.measure { max-width: 64ch; }

/* ---------------------------------------------------------- caption layer
   The small-type register that carries metadata, source lines, figure captions
   and band labels. Deliberately tiny and widely tracked: on a quiet ground it
   is what makes a page read as a set document rather than a web page. Never
   below 11px, never used for anything a reader must be able to skim.
   Referenced by no HTML yet — the existing eyebrow and kicker rules still carry
   the small print, and folding them into this one class is a later pass. */
.caption {
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  line-height: 1.5;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--cs-dim);
}
.caption--quiet { opacity: 0.72; }

/* ---------------------------------------------------------- arrow link
   The inline call to action. The nav carries its own copy of this treatment in
   .nav__cta; this is the reusable version for body copy and section footers.
   It is NOT the primary action — that stayed a solid block (.btn--primary, in
   brand blue since the flip), because a board-facing page wants one
   unambiguous target per screen. Referenced by no HTML yet: it is here for the
   section-footer retrofit, which is deliberately a later pass. */
.cta-arrow {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  font-family: var(--font-ui);
  font-size: var(--fs-small);
  font-weight: 700;
  letter-spacing: 0.03em;
  text-decoration: none;
  color: var(--cs-color);
  transition: color 0.25s var(--ease);
}
.cta-arrow::after {
  content: "\2192";
  transition: transform 0.25s var(--ease);
}
.cta-arrow:hover { color: var(--cs-link); }
.cta-arrow:hover::after { transform: translateX(4px); }
@media (prefers-reduced-motion: reduce) {
  .cta-arrow::after, .nav__cta::after { transition: none; }
}

.skip-link {
  position: absolute; left: -999px; top: 0;
  background: var(--cyan); color: #011721;
  padding: 10px 18px; font-family: var(--font-ui); font-weight: 700;
  z-index: 100; border-radius: 0 0 var(--r-sm) 0;
}
.skip-link:focus { left: 0; }

/* Focus — SC 2.4.11. One system, re-coloured by the band it lands in.
   The double ring guarantees a visible edge on any ground the element sits on. */
a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible {
  outline: 3px solid var(--cs-focus);
  outline-offset: 3px;
  border-radius: var(--r-sm);
}
.btn:focus-visible,
.nav__cta:focus-visible,
.nav__links-cta a:focus-visible {
  outline-offset: 4px;
  border-radius: var(--r-md);
}
.skip-link:focus-visible { outline-color: #011721; outline-offset: 2px; }
main:focus { outline: none; }

/* ---------------------------------------------------------- gradient hairline edge
   One card pattern, one ::before, re-inked by the scheme. */
.edge {
  position: relative;
  background: var(--cs-panel);
  border: 0;
  border-radius: var(--r-md);
  box-shadow: var(--e-1);
}
[data-color-scheme="ink-on-bone"] .edge,
[data-color-scheme="ink-on-mist"] .edge { box-shadow: var(--e-light); }
.edge::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: var(--cs-edge);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  pointer-events: none;
  transition: background 0.45s var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .edge:hover::before { background: var(--cs-edge-hot); }
}

/* ============================================================
   TYPOGRAPHY
   Serif = display only. Sentence case always. Never uppercase, never
   positively tracked, never below 26px, never weight 300 on a dark ground.
   ============================================================ */

/* B1 — one eyebrow: one size, one weight, one tracking, two colour roles.
   Montserrat, per panel condition 7. */
.eyebrow, .label, .creds__kicker, .principal__role,
.ledger__head, .tl__date, .footer__title {
  font-family: var(--font-ui);
  font-size: var(--fs-eyebrow);
  font-weight: 700;
  letter-spacing: var(--ls-eyebrow);
  line-height: 1.4;
  text-transform: uppercase;
  color: var(--cs-eyebrow);
}
.eyebrow--muted,
.ledger__head, .tl__date, .footer__title { color: var(--cs-dim); }

.eyebrow {
  display: inline-flex;
  align-items: flex-start;
  gap: 12px;
}
.eyebrow::before {
  content: "";
  flex: none;
  width: 16px; height: 16px;
  margin-top: 0.16em;
  background-image: var(--cs-mark);
  background-repeat: no-repeat;
  background-size: contain;
}
.eyebrow--onband { margin-bottom: var(--s-8); }

/* --- display --- */
.hero__title {
  font-family: var(--font-display);
  font-weight: var(--display-w-hero);
  font-size: clamp(3.2rem, 7.8vw, 6rem);
  line-height: var(--display-lh);
  letter-spacing: var(--display-ls);
  color: var(--cs-color);
  margin: 26px 0 30px;
}
/* The in-headline accent. It used to be the action gradient, which is why
   "cyan means clickable" had stopped meaning anything. Now a scheme value. */
.grad-text {
  background: none;
  -webkit-background-clip: border-box;
  background-clip: border-box;
  color: var(--cs-accent);
}

.h2 {
  font-family: var(--font-display);
  font-weight: var(--display-w-h2);
  font-size: clamp(2.15rem, 4.8vw, 3.7rem);
  line-height: 1.08;
  letter-spacing: var(--display-ls);
  color: var(--cs-color);
  margin: 18px 0 22px;
}
/* Above 1024px the h2 clears 49px, so the light cut is safe. Below it the
   serif floor applies and the weight stays at 400. */
@media (min-width: 1024px) {
  .h2 { font-weight: 360; }
}

.h3 {
  font-family: var(--font-display);
  font-weight: var(--display-w-h3);
  font-size: var(--fs-h3);          /* 26px — the floor, exactly */
  line-height: 1.2;
  letter-spacing: var(--display-ls-sm);
  color: var(--cs-color);
  margin: 14px 0 12px;
}

/* Lead / standfirst — Lato 300, 28px, 1.28, 34ch. 30ch orphans words. */
.lead {
  font-family: var(--font-body);
  font-size: var(--fs-lead);
  font-weight: 300;
  line-height: 1.28;
  color: var(--cs-dim);
  max-width: 34ch;
}
/* .lead.measure widens the standfirst where a section head carries a full
   argument rather than a single sentence. Same type, longer measure. */
.lead.measure { max-width: 46ch; }

.body { color: var(--cs-dim); font-size: var(--fs-body); }
/* Run-in emphasis. lato-700 is gone, so a <strong> set in Lato would be a
   synthesised bold; Montserrat 600 is a real cut and is already the label
   face of this system, which is the job these run-ins actually do. */
.body strong, .creds__line strong, .ledger__meta strong {
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 0.94em;
  letter-spacing: -0.005em;
  color: var(--cs-color);
}
.body + .body { margin-top: 12px; }

/* Ordinals are labels, not display. Demoted out of the cyan (panel §6.10:
   at 34px in cyan they read as SaaS pricing tiers) into Montserrat micro-type
   at the scheme's dim value. */
.numeral {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: var(--fs-eyebrow);
  line-height: 1.4;
  letter-spacing: var(--ls-eyebrow);
  color: var(--cs-dim);
}

.rule {
  display: block;
  width: 28px; height: 2px;
  background: var(--cs-accent);
  border-radius: 1px;
  opacity: 0.85;
}

.note {
  position: relative;
  max-width: var(--w-col);
  margin-top: var(--s-12);
  padding: 26px 30px 26px 34px;
  border-radius: var(--r-md);
  color: var(--cs-dim);
  font-size: var(--fs-body);
}
.note::after {
  content: "";
  position: absolute;
  top: 22px; bottom: 22px; left: 0;
  width: 2px;
  border-radius: 1px;
  background: var(--cs-accent);
}

/* ---------------------------------------------------------- links
   Cyan on dark, #00697C on light: the action colour of the ground it sits on. */
.link {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: var(--fs-body);
  letter-spacing: 0.02em;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  /* SC 2.5.8 — the bare inline link measured 18px tall. Padding clears the
     24x24 minimum; the negative margin keeps the visual rhythm unchanged. */
  min-height: 24px;
  padding-block: 5px;
  margin-block: -5px;
  transition: color 0.3s var(--ease);
}
.link span { display: inline-block; transition: transform 0.3s var(--ease); }
@media (hover: hover) and (pointer: fine) {
  .link:hover span { transform: translateX(5px); }
}
.link--grass { color: var(--cs-link); }
.link--grass:hover { color: var(--cs-link-hover); }
.link--quiet { color: var(--cs-dim); }
.link--quiet:hover { color: var(--cs-link); }

/* ---------------------------------------------------------- buttons
   Decision 6a — the pill is retired. Decision 6b — #4fc3d9 fill with #011721
   ink (8.85:1) on every ground, so the action colour is constant across bands.
   Hover is #00798e with white ink (5.09:1) plus the BCG padding slide: the
   right padding grows and the arrow rides out from under the edge. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  text-align: center;
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0.045em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 16px 24px;
  border-radius: var(--r-md);
  transition: background 0.35s var(--ease), color 0.35s var(--ease),
              box-shadow 0.35s var(--ease), padding 0.35s var(--ease);
}
.btn__arrow {
  display: inline-block;
  transition: transform 0.35s var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .btn:hover { padding-right: 34px; }
  .btn:hover .btn__arrow { transform: translateX(3px); }
  .btn--ghost:hover .btn__arrow { transform: translateY(2px); }
}

/* Light flip: on bone, a cyan fill with a glow reads as software marketing.
   The primary action is now a solid brand-blue block with no shadow.
   Measured: #FFFFFF on #004868 = 9.87:1, #FFFFFF on #00697C = 5.83:1. */
.btn--primary {
  background: var(--blue);
  color: #FFFFFF;
  box-shadow: none;
}
@media (hover: hover) and (pointer: fine) {
  .btn--primary:hover {
    background: var(--ext-teal-aa);
    color: #FFFFFF;
    box-shadow: none;
  }
}
/* On the one dark band the blue block would disappear into the ground, so
   there the action keeps the cyan fill it was designed with. */
[data-color-scheme="white-on-abyss"] .btn--primary {
  background: var(--cyan);
  color: #011721;
}
@media (hover: hover) and (pointer: fine) {
  [data-color-scheme="white-on-abyss"] .btn--primary:hover {
    background: #9ee3f2;
    color: #011721;
  }
}
.btn--ghost {
  color: var(--cs-color);
  box-shadow: inset 0 0 0 1px var(--cs-rule-strong);
  background: transparent;
}
@media (hover: hover) and (pointer: fine) {
  .btn--ghost:hover {
    box-shadow: inset 0 0 0 1px var(--cs-color);
    background: var(--cs-panel);
  }
}

/* ---------------------------------------------------------- nav
   Chrome, not a band. Since the light flip the nav sits on bone on every page,
   so it carries fixed INK values rather than the old --ink-* (which are the
   text-on-dark tokens). It does not read --cs-*: a nav that recoloured itself
   over the one dark band would flicker mid-scroll. */
.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 50;
  color: var(--ext-ink);
  transition: background 0.4s var(--ease), border-color 0.4s var(--ease), box-shadow 0.4s var(--ease);
  border-bottom: 1px solid transparent;
}
.nav.is-scrolled {
  background: rgba(242, 240, 236, 0.88);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  border-bottom-color: rgba(1, 23, 33, 0.12);
  box-shadow: none;
}
/* The 2px cyan sweep under the scrolled nav belonged to the dark build. On
   bone the hairline border alone carries the separation. */
.nav::after { content: none; }

.nav__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 78px;
}
.nav__logo img { height: 34px; width: auto; }
.nav__nav { display: flex; align-items: center; gap: 34px; }
.nav__links { display: flex; gap: 30px; align-items: center; }
.nav__links a {
  font-family: var(--font-ui);
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-decoration: none;
  color: rgba(1, 23, 33, 0.70);
  transition: color 0.3s var(--ease);
  position: relative;
  padding: 6px 0;
}
.nav__links a::after {
  content: "";
  position: absolute;
  left: 0; right: 100%; bottom: 0;
  height: 1px;
  background: var(--ext-teal-aa);
  transition: right 0.35s var(--ease);
  border-radius: 1px;
}
.nav__links a:hover { color: var(--ext-ink); }
.nav__links a:hover::after { right: 0; }
.nav__links a[aria-current="true"] { color: var(--ext-ink); }
.nav__links a[aria-current="true"]::after { right: 0; }

/* Light flip: the filled/bordered pill read as SaaS. The nav CTA is now an
   arrow link in the same register as every other call to action on the site. */
.nav__cta {
  font-family: var(--font-ui);
  font-size: var(--fs-small);
  font-weight: 700;
  letter-spacing: 0.03em;
  text-decoration: none;
  color: var(--ext-ink);
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  transition: color 0.3s var(--ease);
}
.nav__cta::after {
  content: "\2192";
  transition: transform 0.25s var(--ease);
}
.nav__cta:hover { color: var(--ext-teal-aa); }
.nav__cta:hover::after { transform: translateX(4px); }

.nav__links-cta { display: none; }

.nav__toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  width: 44px; height: 44px;
  background: none;
  border: 1px solid rgba(1, 23, 33, 0.50);
  border-radius: var(--r-sm);
  cursor: pointer;
  align-items: center;
}
.nav__bar {
  width: 18px; height: 2px;
  background: var(--ext-ink);
  border-radius: 1px;
  transition: transform 0.3s var(--ease), opacity 0.2s var(--ease);
}
.nav__toggle[aria-expanded="true"] .nav__bar:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.nav__toggle[aria-expanded="true"] .nav__bar:nth-child(2) { opacity: 0; }
.nav__toggle[aria-expanded="true"] .nav__bar:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

/* ---------------------------------------------------------- hero */
.hero {
  position: relative;
  min-height: 92vh;
  display: flex;
  align-items: center;
  padding: 150px 0 110px;
  overflow: hidden;
}
.hero__inner {
  display: grid;
  gap: var(--s-12);
  align-items: center;
}
@media (min-width: 1080px) {
  .hero__inner {
    grid-template-columns: minmax(0, 1fr) 360px;
    gap: var(--s-12);
  }
}
.hero__copy { min-width: 0; }
.hero__aside { position: relative; }
/* The oversized ghost mark was a light shape at 6% on a dark ground. On bone it
   inverts into a grey smudge with no reading, so it is dark-band only. */
.hero__mark { display: none; }
[data-color-scheme="white-on-abyss"] .hero__mark {
  display: block;
  position: absolute;
  right: -16%;
  top: 50%;
  width: clamp(300px, 32vw, 520px);
  opacity: 0.06;
  pointer-events: none;
  user-select: none;
  filter: saturate(0.6);
  transform: translateY(-50%);
  animation: markFloat 16s ease-in-out 1 alternate both;
}
@keyframes markFloat {
  from { transform: translateY(-53%) rotate(-1.5deg); }
  to   { transform: translateY(-47%) rotate(1.5deg); }
}
/* The glowing beam under the hero was a dark-build device. On bone the section
   hairline is the separator; the beam only survives on the dark band. */
.hero__beam { display: none; }
[data-color-scheme="white-on-abyss"] .hero__beam {
  display: block;
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(79, 195, 217, 0.45), rgba(0, 121, 142, 0.5), transparent);
  pointer-events: none;
}
/* The hero standfirst is a lead: same 28px Lato 300 as every other band. */
.hero__lead {
  font-family: var(--font-body);
  font-size: var(--fs-lead);
  font-weight: 300;
  line-height: 1.28;
  color: var(--cs-dim);
  max-width: 34ch;
  margin-bottom: 18px;
}
.hero__copy .body { max-width: 52ch; margin-bottom: 38px; }
.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  align-items: center;
}
.hero__panel-kicker { display: block; margin-bottom: 10px; }
.hero__panel {
  position: relative;
  padding: 28px 28px 24px;
  border-radius: var(--r-lg);
  background: var(--cs-panel);
  /* --cs-panel is opaque #FFFFFF on both light schemes, so the blur buys
     nothing there and still forces a compositing layer on the largest
     above-the-fold element. Scoped to the schemes where the panel is
     translucent. */
  box-shadow: var(--cs-shadow);
}
[data-color-scheme="white-on-abyss"] .hero__panel,
[data-color-scheme="white-on-blue"] .hero__panel {
  -webkit-backdrop-filter: blur(14px) saturate(130%);
          backdrop-filter: blur(14px) saturate(130%);
}
.hero__mail {
  margin-top: 20px;
  font-size: var(--fs-small);
  color: var(--cs-dim);
}

/* ---------------------------------------------------------- the ledger
   The one device on the page made of content rather than style:
   status dot -> named fact -> qualifying line. */
.ledger { display: grid; }
.ledger li {
  display: grid;
  grid-template-columns: 14px 1fr;
  column-gap: 14px;
  align-items: baseline;
  padding: 15px 0;
}
.ledger li + li { border-top: 1px solid var(--cs-rule); }
.ledger__head {
  display: block;
  padding-bottom: 18px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--cs-rule);
}
.ledger__dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  align-self: center;
  justify-self: center;
  background: var(--cs-live);
  box-shadow: 0 0 0 3px var(--cs-dot-ring);
}
.ledger__dot--future {
  background: var(--teal);
  box-shadow: 0 0 0 3px var(--cs-dot-ring);
}
.ledger__name {
  font-family: var(--font-ui);
  font-size: var(--fs-small);
  font-weight: 700;
  color: var(--cs-color);
  letter-spacing: -0.005em;
}
.ledger__meta {
  grid-column: 2;
  font-size: var(--fs-micro);
  color: var(--cs-dim);
  line-height: 1.5;
  margin-top: 2px;
}
.ledger-block { max-width: 40rem; margin-top: var(--s-12); }
.contact .ledger-block { margin-inline: auto; text-align: left; }

/* In force versus not yet in force — the only place motion carries meaning. */
@media (prefers-reduced-motion: no-preference) {
  .hero__panel .ledger__dot:not(.ledger__dot--future) {
    animation: dotLive 2.6s ease-in-out infinite;
  }
}
@keyframes dotLive { 50% { box-shadow: 0 0 0 6px rgba(0, 121, 142, 0.09); } }

/* Load-in sequence */
@media (prefers-reduced-motion: no-preference) {
  .hero .eyebrow, .hero__title, .hero__lead, .hero__actions, .hero__aside {
    opacity: 0;
    transform: translateY(24px);
    animation: riseIn 0.9s var(--ease) forwards;
  }
  .hero__title { animation-delay: 0.1s; }
  .hero__lead { animation-delay: 0.22s; }
  .hero__actions { animation-delay: 0.34s; }
  .hero__aside { animation-delay: 0.46s; }
}
@keyframes riseIn {
  to { opacity: 1; transform: translateY(0); }
}

/* ---------------------------------------------------------- sections
   Band boundaries are now made of colour. The hairline survives only where
   two modules share a ground (and on pages not yet re-cut). */
.section { position: relative; padding: var(--band-pad) 0; }
.section__head { margin-bottom: var(--s-12); }
.section__head .lead { margin-top: 4px; }
/* A standfirst followed by the argument it opens: the body paragraph sits at
   the same measure, one step down in scale. */
.section__head .lead + .body { margin-top: 20px; }

.section + .section,
.creds + .section,
.section + .contact {
  border-top: 1px solid var(--cs-rule);
}
/* Two bands of DIFFERENT ground need no rule — the colour change is the join.
   Since the light flip most neighbours share the bone ground, and there the
   hairline is the only thing separating one section from the next. */
[data-color-scheme] + [data-color-scheme] { border-top: 0; }
[data-color-scheme="ink-on-bone"] + [data-color-scheme="ink-on-bone"],
[data-color-scheme="ink-on-mist"] + [data-color-scheme="ink-on-mist"],
[data-color-scheme="white-on-abyss"] + [data-color-scheme="white-on-abyss"] {
  border-top: 1px solid var(--cs-rule);
}

/* Per-band atmosphere overrides. These used to paint a background directly,
   which would now fight --cs-bg; they tune the scheme's own atmosphere layer
   instead, so a band keeps its own anchor point and hue. */
[data-color-scheme="white-on-abyss"]#services,
[data-color-scheme="white-on-blue"]#services {
  --cs-atmos:
    radial-gradient(46rem 30rem at -8% 10%, rgba(0, 121, 142, 0.10), transparent 60%),
    radial-gradient(40rem 26rem at 104% 92%, rgba(0, 72, 104, 0.06), transparent 62%);
  --cs-atmos-size: auto, auto;
  --cs-atmos-repeat: no-repeat, no-repeat;
}
[data-color-scheme="white-on-abyss"]#governance,
[data-color-scheme="white-on-blue"]#governance {
  --cs-atmos:
    var(--tex-grain),
    var(--tex-dots),
    radial-gradient(48rem 30rem at 110% 8%, rgba(0, 121, 142, 0.22), transparent 60%),
    radial-gradient(38rem 26rem at -8% 88%, rgba(0, 72, 104, 0.30), transparent 64%);
}
[data-color-scheme="white-on-abyss"]#approach,
[data-color-scheme="white-on-blue"]#approach {
  --cs-atmos:
    radial-gradient(50rem 30rem at 104% 4%, rgba(0, 121, 142, 0.09), transparent 60%),
    radial-gradient(44rem 28rem at -10% 96%, rgba(0, 72, 104, 0.07), transparent 62%);
  --cs-atmos-size: auto, auto;
  --cs-atmos-repeat: no-repeat, no-repeat;
}
[data-color-scheme="white-on-abyss"]#about,
[data-color-scheme="white-on-blue"]#about {
  --cs-atmos:
    var(--tex-grain),
    radial-gradient(46rem 28rem at 104% 90%, rgba(79, 195, 217, 0.18), transparent 62%),
    radial-gradient(40rem 26rem at -6% 4%, rgba(1, 23, 33, 0.30), transparent 64%);
  --cs-atmos-size: 180px 180px, auto, auto;
  --cs-atmos-repeat: repeat, no-repeat, no-repeat;
}

/* ---------------------------------------------------------- credentials */
.creds { position: relative; padding: clamp(52px, 6vw, 88px) 0; }
.creds__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 18px;
}
.creds__item {
  padding: 24px 26px 26px;
  display: grid;
  grid-template-rows: auto auto 1fr;
  align-content: start;
  transition: transform 0.4s var(--ease), background 0.4s var(--ease), box-shadow 0.4s var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .creds__item:hover {
    transform: translateY(-4px);
    background: var(--cs-panel-hover);
    box-shadow: var(--cs-shadow);
  }
}
.creds__kicker { margin-bottom: 12px; }
@media (min-width: 401px) {
  .creds__kicker { min-height: 3.3em; }
}
.creds__byline {
  font-family: var(--font-body);
  font-size: var(--fs-small);
  color: var(--cs-dim);
  margin: -16px 0 28px;
}
/* The proof line. A numeral-as-label, so it stays Montserrat — and it stays
   out of the gradient, which now belongs to nothing but the action colour. */
.creds__mark {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 1.75rem;
  color: var(--cs-color);
  letter-spacing: -0.02em;
  line-height: 1.15;
  min-height: 2.3em;
  display: flex;
  align-items: flex-end;
  margin-bottom: 10px;
}
.creds__line { font-size: var(--fs-small); color: var(--cs-dim); line-height: 1.55; }

/* ---------------------------------------------------------- pillars (bento) */
.pillars {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 22px;
}
.pillar {
  padding: 32px 30px 30px;
  border-radius: var(--r-md);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: transform 0.45s var(--ease), background 0.45s var(--ease), box-shadow 0.45s var(--ease);
}
.pillar::after {
  content: "";
  position: absolute;
  inset: -40% -40% auto auto;
  width: 260px; height: 260px;
  background: radial-gradient(closest-side, rgba(0, 121, 142, 0.18), transparent);
  opacity: 0;
  transition: opacity 0.5s var(--ease);
  pointer-events: none;
}
@media (hover: hover) and (pointer: fine) {
  .pillar:hover {
    transform: translateY(-6px);
    background: var(--cs-panel-hover);
    box-shadow: var(--cs-shadow);
  }
  .pillar:hover::after { opacity: 1; }
}
.pillar__icon {
  display: block;
  width: 48px; height: 48px;
  padding: 13px;
  color: var(--cs-link);
  background-image: var(--cs-frame);
  background-repeat: no-repeat;
  background-size: contain;
  margin-bottom: 18px;
}
.pillar .label { display: block; }
.pillar .h3 { margin: 14px 0 14px; }
.pillar__main { display: flex; flex-direction: column; flex: 1; }
.pillar .body { margin-bottom: 22px; }
.pillar__main .link { margin-top: auto; align-self: flex-start; }

@media (min-width: 901px) {
  .pillar:not(.pillar--feature) .h3 { min-height: 2.4em; }
  .pillar--feature {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr);
    column-gap: var(--s-12);
    align-items: center;
    padding: 34px 36px 34px 30px;
  }
  .pillar--feature .pillar__head { grid-column: 1; }
  .pillar--feature .pillar__main { grid-column: 2; grid-row: 1; }
  .pillar--feature .h3 { margin-bottom: 0; }
}
.pillar--feature { grid-column: 1 / -1; }

/* ---------------------------------------------------------- AI Act timeline */
.timeline {
  position: relative;
  display: grid;
  gap: 30px;
}
.timeline::before {
  content: "";
  position: absolute;
  left: 6px; top: 12px; bottom: 12px;
  width: 1px;
  background: linear-gradient(180deg, var(--cs-accent), var(--cs-rule) 72%, transparent);
}
.tl { position: relative; padding-left: 44px; }
.tl__date { display: block; margin-bottom: 12px; }
.tl__dot {
  position: absolute;
  left: 0; top: 3px;
  width: 13px; height: 13px;
  border-radius: 50%;
  background: var(--cs-bg);
  border: 2px solid var(--cs-live);
  box-shadow: 0 0 0 4px var(--cs-bg);
}
.tl--future .tl__dot { border-color: var(--teal); }

.qitem {
  display: grid;
  grid-template-columns: 48px 1fr;
  column-gap: 20px;
  row-gap: 6px;
  align-items: baseline;
  padding: 28px 32px 30px;
  border-radius: var(--r-md);
  transition: background 0.4s var(--ease), transform 0.4s var(--ease), box-shadow 0.4s var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .qitem:hover {
    background: var(--cs-panel-hover);
    transform: translateX(6px);
    box-shadow: var(--cs-shadow);
  }
}
.qitem .numeral { grid-row: 1; grid-column: 1; }
.qitem .h3   { grid-column: 2; margin: 0 0 4px; }
.qitem .body { grid-column: 2; max-width: 62ch; }

/* ---------------------------------------------------------- steps */
.steps {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px;
}
.step {
  padding: 34px 30px 36px;
  border-radius: var(--r-md);
  z-index: 1;
  transition: transform 0.45s var(--ease), background 0.45s var(--ease), box-shadow 0.45s var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .step:hover {
    transform: translateY(-5px);
    background: var(--cs-panel-hover);
    box-shadow: var(--cs-shadow);
  }
}
.step .numeral { display: block; }
.step .rule { margin: 12px 0 0; }
.step .h3 { margin-top: 18px; }
.step .body { font-size: var(--fs-body); }

@media (min-width: 901px) {
  .step .h3 { min-height: 2.5em; }
  .steps::before {
    content: "";
    position: absolute;
    top: 62px; left: 4%; right: 4%;
    height: 1px;
    z-index: 0;
    background: linear-gradient(90deg, transparent, var(--cs-rule), var(--cs-rule), transparent);
  }
}

/* ---------------------------------------------------------- principal */
.prose {
  padding: 38px 42px 34px;
  border-radius: var(--r-lg);
  overflow: hidden;
  max-width: 780px;
}
.prose::after {
  content: "";
  position: absolute;
  top: 24px; bottom: 24px; left: 0;
  width: 2px;
  border-radius: 1px;
  background: var(--cs-accent);
}
.principal__lockup {
  padding-bottom: 22px;
  margin-bottom: 26px;
  border-bottom: 1px solid var(--cs-rule);
}
/* A name lockup, not display: Montserrat, per panel condition 7. */
.principal__name {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 1.5rem;
  letter-spacing: -0.02em;
  line-height: 1.2;
  color: var(--cs-color);
}
.principal__role { margin-top: 8px; display: block; }
.prose .body + .body { margin-top: 18px; }
.prose__link { margin-top: 26px; }

/* ---------------------------------------------------------- contact */
.contact {
  position: relative;
  padding: calc(var(--band-pad) * 1.15) 0 var(--band-pad);
  text-align: center;
  overflow: hidden;
  isolation: isolate;
}
/* The closing glow. It shares the pseudo-element with the scheme atmosphere,
   so it re-declares the whole stack rather than fighting it. On bone it is
   suppressed: the ruling that retired the band atmospheres applies here too —
   a teal radial on cream reads as a printing fault, not as a close. */
.contact::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image: var(--cs-atmos);
  background-size: var(--cs-atmos-size, auto);
  background-repeat: var(--cs-atmos-repeat, no-repeat);
}
[data-color-scheme="white-on-abyss"].contact::before,
[data-color-scheme="white-on-blue"].contact::before {
  background-image:
    radial-gradient(50rem 24rem at 50% 116%, rgba(0, 121, 142, 0.30), transparent 70%),
    var(--cs-atmos);
  background-size: auto, var(--cs-atmos-size, auto);
  background-repeat: no-repeat, var(--cs-atmos-repeat, no-repeat);
}
.contact .container { position: relative; }
.contact .eyebrow { justify-content: center; }
.contact__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.15rem, 4.2vw, 3.3rem);
  line-height: 1.1;
  letter-spacing: var(--display-ls);
  color: var(--cs-color);
  max-width: 20ch;
  margin: 20px auto 20px;
}
.contact__actions { margin: 42px 0 20px; }
.contact__mail { margin-bottom: 16px; font-size: var(--fs-body); color: var(--cs-dim); }
/* One inline-link pattern, three jobs: the contact address, the hero mailto
   safety net and every primary-source citation. */
.contact__mail a,
.hero__mail a,
.src-link {
  font-family: inherit;
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--cs-link);
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
  word-break: break-word;
  transition: color 0.3s var(--ease), text-decoration-color 0.3s var(--ease);
}
.contact__mail a:hover,
.hero__mail a:hover,
.src-link:hover { color: var(--cs-link); }
.contact__alt { position: relative; }
.contact__alt .link { justify-content: center; }

/* ---------------------------------------------------------- footer */
.footer {
  position: relative;
  /* A half-step deeper than the page ground so the document has a visible floor
     without introducing a second colour. Set through the token rather than
     background-color, so it does not depend on source order against
     [data-color-scheme], which has identical specificity. */
  --cs-bg: #ECE9E3;
  border-top: 1px solid var(--cs-rule);
  padding: var(--s-16) 0 var(--s-8);
}
.footer__cols {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr;
  gap: var(--s-12);
  margin-bottom: var(--s-8);
}
.footer__logo { height: 30px; width: auto; margin-bottom: 20px; }
.footer__legal { font-size: var(--fs-small); color: var(--cs-dim); line-height: 1.7; }
.footer__legal + .footer__legal { margin-top: 6px; }
.footer__title { margin-bottom: 6px; }
.footer__nav, .footer__contact { display: flex; flex-direction: column; }
.footer__nav a, .footer__contact a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-family: var(--font-ui);
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--cs-dim);
  text-decoration: none;
  transition: color 0.3s var(--ease);
}
.footer__nav a:hover, .footer__contact a:hover { color: var(--cs-link); }
.footer__place {
  font-family: var(--font-ui);
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--cs-dim);
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}
.footer__copy {
  font-size: var(--fs-micro);
  color: var(--cs-dim);
  padding-top: var(--s-6);
  border-top: 1px solid var(--cs-rule);
}

/* ---------------------------------------------------------- 404 */
.error-page {
  min-height: 72vh;
  display: flex;
  align-items: center;
  padding: 160px 0 100px;
}
.error-page__code {
  font-family: var(--font-display);
  font-weight: var(--display-w-hero);
  font-size: clamp(3rem, 9vw, 6rem);
  line-height: var(--display-lh);
  letter-spacing: var(--display-ls);
  color: var(--cs-color);
  margin: 22px 0 24px;
}
.error-page__actions { display: flex; gap: 28px; flex-wrap: wrap; margin-top: 34px; }

/* ---------------------------------------------------------- reveal
   .reveal starts hidden and is revealed by the class is-in (main.js) or by
   the native scroll-driven animation below. no-js.css neutralises both. */
.reveal {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
}
.reveal.is-in { opacity: 1; transform: none; }

@keyframes revealRise {
  from { opacity: 0; transform: translateY(26px); }
  to   { opacity: 1; transform: none; }
}
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .reveal {
      opacity: 1;
      transform: none;
      transition: none;
      animation: revealRise linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 55%;
    }
  }
}
/* The scroll-progress bar on .nav::after was retired with the light flip
   (.nav::after is now `content: none`), so its keyframes and the
   scroll-timeline @supports branch went with it. */

@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; animation: none; }
  .hero .eyebrow, .hero__title, .hero__lead, .hero__actions, .hero__aside {
    opacity: 1; transform: none; animation: none;
  }
  .hero__mark { animation: none; }
  .nav__links { transition: none; }
  .nav::after { display: none; }
}

/* ---------------------------------------------------------- responsive */
@media (max-width: 1080px) {
  .creds__grid { grid-template-columns: repeat(2, 1fr); }
  .hero__aside { margin-top: 8px; }
  .hero__mark { right: -8%; opacity: 0.05; }
}

@media (max-width: 900px) {
  /* Full-height sheet. top+bottom, never height: calc(100vh - 78px):
     100vh overshoots by the address-bar height on iOS Safari. */
  .nav__links {
    position: fixed;
    top: 78px; left: 0; right: 0; bottom: 0;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    overflow-y: auto;
    background: var(--ext-bone);
    border-bottom: 1px solid rgba(1, 23, 33, 0.12);
    padding: 12px 0 20px;
    opacity: 0;
    transform: translateY(-8px);
    visibility: hidden;
    pointer-events: none;
    transition: opacity .25s var(--ease), transform .25s var(--ease),
                visibility 0s linear .25s;
  }
  .nav__links.is-open {
    opacity: 1;
    transform: none;
    visibility: visible;
    pointer-events: auto;
    transition: opacity .25s var(--ease), transform .25s var(--ease),
                visibility 0s linear 0s;
  }
  .nav__links a {
    display: block;
    padding: 15px clamp(20px, 5vw, 48px);
    font-size: var(--fs-body);
  }
  .nav__links a::after { display: none; }
  .nav__toggle { display: flex; }
  .nav__cta { display: none; }

  .nav__links-cta { display: block; margin: 12px clamp(20px, 5vw, 48px) 0; }
  .nav__links-cta a {
    display: block;
    text-align: center;
    padding: 15px 20px;
    border-radius: var(--r-md);
    /* Matches .btn--primary since the light flip: the menu sheet sits on bone,
       so the cyan pill would be the one SaaS-register control left on the site.
       #FFFFFF on #004868 = 9.87:1. */
    background: var(--blue);
    color: #FFFFFF;
    font-family: var(--font-ui);
    font-weight: 700;
    font-size: 14.5px;
    letter-spacing: 0.05em;
    text-transform: uppercase;
  }

  .pillars, .steps { grid-template-columns: 1fr; }
  .steps::before { display: none; }
  .hero { min-height: 0; padding: 128px 0 84px; }
  .footer__cols { grid-template-columns: 1fr 1fr; }
  .footer__brand { grid-column: 1 / -1; }
}

@media (max-width: 620px) {
  /* Band boundaries cost twice the padding. At phone width that is the
     difference between a rhythm and a scroll. */
  :root { --band-pad: 52px; }
}

@media (max-width: 560px) {
  body { font-size: 16px; }
  .creds__grid { gap: 14px; }
  .creds__mark { font-size: 1.45rem; }

  .qitem {
    grid-template-columns: 1fr;
    row-gap: 2px;
    padding: 24px 22px 26px;
  }
  .qitem .numeral, .qitem .h3, .qitem .body { grid-column: 1; }
  .qitem .numeral { margin-bottom: 8px; padding-top: 0; }

  .tl { padding-left: 34px; }
  .timeline::before { left: 5px; }

  .prose { padding: 28px 24px; }
  .prose .body { max-width: none; }
  .pillar { padding: 28px 24px 26px; }
  .step { padding: 28px 24px 30px; }

  /* Same padding at both ends of the page; the uppercase CTA is allowed to
     wrap to two centred lines rather than shrink below 13px. */
  .hero__actions .btn,
  .contact__actions .btn { width: 100%; padding: 15px 20px; font-size: 13px; letter-spacing: 0.04em; }
  .hero__actions .btn:hover,
  .contact__actions .btn:hover { padding-right: 20px; }
  .hero__panel { padding: 24px 22px 20px; }

  .footer__cols { grid-template-columns: 1fr; gap: var(--s-8); }
  .footer__brand { grid-column: auto; }
}

@media (max-width: 400px) {
  .creds__grid { grid-template-columns: 1fr; }
  .creds__mark { min-height: 0; }
}

/* ------------------------------------------- audit areas (2026-08-24) */
/* "Under the audit: three areas" cards on the home page. */
.areas__head { margin-top: 40px; }
.areas__intro { margin-top: 6px; }
.areas {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px;
  margin-top: 24px;
}
.area {
  padding: 34px 30px 36px;
  border-radius: var(--r-md);
  transition: transform 0.45s var(--ease), background 0.45s var(--ease), box-shadow 0.45s var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .area:hover {
    transform: translateY(-5px);
    background: var(--cs-panel-hover);
    box-shadow: var(--cs-shadow);
  }
}
.area .h3 { margin-top: 0; }
.area .body { font-size: var(--fs-body); }
.area .link { margin-top: 16px; display: flex; }
/* Stacked practice links on cards: .link is inline-flex, which would sit two
   links on one line — flex gives each its own row. */
.pillar__main .link { display: flex; }
.pillar__main .link + .link { margin-top: 8px; }

@media (max-width: 900px) {
  .areas { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
  .area { padding: 28px 24px 26px; }
}

/* Footer column hooks — semantic wrappers the .footer__cols grid positions.
   Declared so no class in the markup is orphaned; layout still comes from the
   grid and from the inner lists. */
.footer__navcol,
.footer__contactcol { min-width: 0; }
