@charset "UTF-8";
/* ==========================================================================
   WB SYNERGY — WEB DESIGN SYSTEM v1.0
   Derived strictly from Brand Charter V1.3 and tokens/wbs_tokens.json
   (2026-08-03). Contrast ratios below are the computed values from
   tokens/contrast_matrix.json — do not substitute colours without
   re-running that matrix.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. FONTS — self-hosted (SIL OFL 1.1).
   Self-hosting is deliberate: it avoids a third-party font CDN request,
   which would transfer visitor IP addresses outside the EU and require
   consent. (docs/PRIVACY_DECISIONS.md was referenced here but never existed;
   the reasoning now lives in src/pages/cookies.njk, which is the version
   visitors actually read, and in docs/intelligence-portal/04-PHASE1-PART-A.md.)
   -------------------------------------------------------------------------- */
@font-face {
  font-family: "EB Garamond";
  src: url("../fonts/EBGaramond.woff2") format("woff2");
  font-weight: 400 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Source Sans 3";
  src: url("../fonts/SourceSans3.woff2") format("woff2");
  font-weight: 200 900;
  font-style: normal;
  font-display: swap;
}

/* --------------------------------------------------------------------------
   2. DESIGN TOKENS
   -------------------------------------------------------------------------- */
:root {
  /* Logo height, fluid. The horizontal logo SVG was cropped to its ink bounds
     (43% of its declared height was empty padding), so this value is now the
     real visible height of the mark — not a box containing it. Capped at 4rem
     because the cropped artwork is 5.44:1, and a taller logo would collide
     with the horizontal nav between 1000px and 1200px. */
  --logo-h: clamp(2.6rem, 4.6vw, 3.9rem);
  /* Sticky header height derives from the logo — one number to change, and
     the mobile nav panel below stays anchored to it automatically. */
  --header-h: calc(var(--logo-h) + 2.25rem);
  /* Brand colour — canonical values, wbs_tokens.json */
  --wbs-evergreen: #123f33;      /* 11.77:1 on white  — headings, surfaces   */
  --wbs-gold: #8c7a45;           /*  4.21:1 on white  — LARGE text / UI only */
  /* Accessibility-derived extension of Brand Charter V1.3. The charter
     restricts #8C7A45 to large text and UI, because at 4.21:1 it fails the
     4.5:1 AA threshold for text below 18.66px bold. This variant keeps the
     same hue and saturation, darkened until it passes AA on BOTH white
     (5.47:1) and Mist (4.58:1). Used for small gold text and for the
     primary button fill (white on it = 5.47:1). */
  --wbs-gold-deep: #78683b;
  --wbs-heritage-gold: #a3925c;  /*  3.08:1 on white  — display accent only  */
  --wbs-night-blue: #1e3a5f;     /* 11.50:1 on white  — links, data          */
  --wbs-gold-tint: #c9b77e;      /*  5.92:1 on evergreen — gold on dark      */
  --wbs-ink: #101314;            /* 18.66:1 on white  — body text            */
  --wbs-slate: #55605c;          /*  6.53:1 on white  — secondary text       */
  --wbs-mist: #edebe3;           /* light panels                             */
  --wbs-white: #ffffff;

  /* Derived surfaces */
  --wbs-evergreen-deep: #0d2f26;
  --wbs-rule: #d9d5c8;
  --wbs-rule-soft: #e8e5db;

  /* Semantic */
  --c-bg: var(--wbs-white);
  --c-text: var(--wbs-ink);
  --c-text-soft: var(--wbs-slate);
  --c-heading: var(--wbs-evergreen);
  --c-link: var(--wbs-night-blue);
  --c-accent: var(--wbs-gold);

  /* Type */
  --f-display: "EB Garamond", Georgia, "Times New Roman", serif;
  --f-body: "Source Sans 3", Arial, Helvetica, sans-serif;

  /* Fluid type scale — 1.25 ratio, clamped */
  --fs-xs: 0.8125rem;
  --fs-sm: 0.9375rem;
  --fs-base: clamp(1rem, 0.97rem + 0.15vw, 1.0625rem);
  --fs-lg: clamp(1.125rem, 1.08rem + 0.22vw, 1.25rem);
  --fs-xl: clamp(1.375rem, 1.28rem + 0.45vw, 1.625rem);
  --fs-2xl: clamp(1.625rem, 1.45rem + 0.85vw, 2.125rem);
  --fs-3xl: clamp(1.875rem, 1.6rem + 1.15vw, 2.5rem);
  --fs-4xl: clamp(2.25rem, 1.75rem + 1.75vw, 3.25rem);

  --lh-tight: 1.15;
  --lh-snug: 1.3;
  --lh-body: 1.65;

  /* Spacing — 4px base */
  --s-1: 0.25rem;  --s-2: 0.5rem;   --s-3: 0.75rem;  --s-4: 1rem;
  --s-5: 1.5rem;   --s-6: 2rem;     --s-7: 2.5rem;   --s-8: 3rem;
  --s-9: 4rem;     --s-10: 5rem;    --s-11: 6.5rem;  --s-12: 8rem;

  /* Layout */
  --measure: 68ch;
  --wrap: 1200px;
  --wrap-narrow: 860px;
  --gutter: clamp(1.25rem, 4vw, 3rem);

  --radius: 2px;
  --border: 1px solid var(--wbs-rule);
  --focus-ring: 3px solid var(--wbs-night-blue);
  --transition: 160ms ease;
}

/* --------------------------------------------------------------------------
   3. RESET & BASE
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

/* No global `scroll-behavior: smooth`. It is decorative motion with no
   business value here, it makes scrollIntoView asynchronous (which breaks
   background resolution for contrast tooling and any script that measures
   after scrolling), and it can disorient users on long legal pages.
   scroll-padding-top keeps in-page anchors clear of the sticky header. */
html {
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: 6rem;
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  background: var(--c-bg);
  color: var(--c-text);
  font-family: var(--f-body);
  font-size: var(--fs-base);
  line-height: var(--lh-body);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

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

/* Visible focus on every interactive element — WCAG 2.2 SC 2.4.11/2.4.13 */
:focus-visible {
  outline: var(--focus-ring);
  outline-offset: 3px;
  border-radius: var(--radius);
}
:focus:not(:focus-visible) { outline: none; }

::selection { background: var(--wbs-evergreen); color: var(--wbs-white); }

/* --------------------------------------------------------------------------
   4. TYPOGRAPHY
   -------------------------------------------------------------------------- */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--f-display);
  color: var(--c-heading);
  font-weight: 600;
  line-height: var(--lh-tight);
  text-wrap: balance;
}
h1 { font-size: var(--fs-4xl); letter-spacing: -0.015em; }
h2 { font-size: var(--fs-3xl); letter-spacing: -0.01em; margin-block-end: var(--s-4); }
h3 { font-size: var(--fs-xl); margin-block-end: var(--s-3); }
h4 { font-size: var(--fs-lg); margin-block-end: var(--s-2); }

p, li { max-width: var(--measure); }
p + p { margin-block-start: var(--s-4); }

a { color: var(--c-link); text-decoration-thickness: 1px; text-underline-offset: 0.2em; }
a:hover { text-decoration-thickness: 2px; }

strong { font-weight: 600; }

.lede {
  font-size: var(--fs-lg);
  color: var(--wbs-slate);
  line-height: 1.55;
  max-width: 62ch;
}

/* Small-caps section label — gold is used at ≥14px bold + letterspaced,
   above the 4.21:1 large-text threshold. Never used for body copy. */
.eyebrow {
  font-family: var(--f-body);
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--wbs-gold-deep);
  margin-block-end: var(--s-3);
  display: block;
  max-width: none;
}
.eyebrow--on-dark { color: var(--wbs-gold-tint); }

.text-soft { color: var(--wbs-slate); }
.text-sm { font-size: var(--fs-sm); }
.text-xs { font-size: var(--fs-xs); }

/* --------------------------------------------------------------------------
   5. LAYOUT
   -------------------------------------------------------------------------- */
.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gutter); }
.wrap--narrow { max-width: var(--wrap-narrow); }

.section { padding-block: clamp(3.5rem, 8vw, var(--s-11)); }
.section--tight { padding-block: clamp(2.5rem, 5vw, var(--s-9)); }
.section--mist { background-color: var(--wbs-mist); }
.section--dark { background-color: var(--wbs-evergreen); color: var(--wbs-white); }
.section--dark h2, .section--dark h3, .section--dark h4 { color: var(--wbs-white); }
.section--dark p, .section--dark li { color: #e4e9e6; }
/* Buttons carry their own colour pair; excluding them keeps the link
   recolouring from overriding a validated foreground/background combination. */
.section--dark a:not(.btn) { color: var(--wbs-gold-tint); }

/* Explicit opaque background. Without it the ancestor chain from a text node
   up to <body> is fully transparent, so contrast tooling — and compositing
   behind the fixed consent banner — has to infer the backdrop and can resolve
   it against the footer. Making it explicit removes the ambiguity. */
main { flex: 1 0 auto; background-color: var(--c-bg); position: relative; z-index: 0; }

/* --------------------------------------------------------------------------
   BRAND WATERMARK
   A tiled mark carried across every surface of the site. Implemented as a
   background-image, deliberately: a background layer paints above the
   background-colour and below every piece of content, so it needs no
   pseudo-element, no z-index and no new stacking context. That matters here —
   an earlier layering bug in this build put the contact aside over the footer,
   and the cheapest way not to repeat it is not to add layers.

   THREE TONAL VARIANTS, one per surface, and the choice is an accessibility
   decision rather than a stylistic one. Worst-case contrast was computed with
   the mark sitting at full strength directly behind the lowest-contrast text
   on each surface:

     surface        mark                 worst-case   baseline
     white          evergreen  @ 0.045      5.04        5.47
     mist           WHITE      @ 0.45       4.97        4.58   ← improves
     evergreen      deep green @ 0.70       6.84        5.92   ← improves

   On mist and on the dark bands the mark moves the background AWAY from the
   text luminance, so it raises contrast. Only on white does it cost anything,
   which is why that one alpha is an order of magnitude lower. Every figure
   stays above the 4.5:1 AA threshold, mask-failure worst case included.
   Do not raise these values without re-running the numbers.
   -------------------------------------------------------------------------- */
main,
.section--mist,
.section--dark {
  background-repeat: repeat;
  background-size: 320px 320px;
  background-position: center top;
}
main            { background-image: url("../brand/wm-on-light.svg"); }
.section--mist  { background-image: url("../brand/wm-on-mist.svg"); }
.section--dark  { background-image: url("../brand/wm-on-dark.svg"); }

/* Respect an explicit request for maximum contrast, and never paint decoration
   into a forced-colours palette — there it would render as a solid block. */
@media (prefers-contrast: more) {
  main, .section--mist, .section--dark { background-image: none; }
}
@media (forced-colors: active) {
  main, .section--mist, .section--dark { background-image: none; }
}

.grid { display: grid; gap: var(--s-6); }
@media (min-width: 700px)  { .grid--2 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 980px)  { .grid--3 { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 700px)  { .grid--sidebar { grid-template-columns: minmax(0,1.55fr) minmax(0,1fr); gap: var(--s-8); } }

.stack > * + * { margin-block-start: var(--s-4); }
.stack-lg > * + * { margin-block-start: var(--s-6); }

.rule { border: 0; border-top: 2px solid var(--wbs-gold); width: 3.5rem; margin-block: var(--s-5); }
.rule--full { width: 100%; border-top: 1px solid var(--wbs-rule); }

/* --------------------------------------------------------------------------
   6. SKIP LINK
   -------------------------------------------------------------------------- */
.skip-link {
  position: absolute;
  left: var(--s-4);
  top: -100px;
  z-index: 999;
  background: var(--wbs-evergreen);
  color: var(--wbs-white);
  padding: var(--s-3) var(--s-5);
  font-weight: 600;
  text-decoration: none;
  transition: top var(--transition);
}
.skip-link:focus { top: var(--s-4); }

/* --------------------------------------------------------------------------
   7. HEADER / NAVIGATION
   -------------------------------------------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(255, 255, 255, 0.97);
  backdrop-filter: saturate(180%) blur(8px);
  border-block-end: 1px solid var(--wbs-rule-soft);
}
.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-5);
  min-height: var(--header-h);
}
.brand { display: flex; align-items: center; flex-shrink: 0; }
.brand img { height: var(--logo-h); width: auto; }

.nav { display: flex; align-items: center; gap: var(--s-5); }
.nav__list { display: flex; align-items: center; gap: var(--s-5); list-style: none; padding: 0; margin: 0; }
.nav__list li { max-width: none; }
.nav__link {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--wbs-ink);
  text-decoration: none;
  padding-block: var(--s-2);
  border-block-end: 2px solid transparent;
  white-space: nowrap;
  display: block;
}
.nav__link:hover { color: var(--wbs-evergreen); border-block-end-color: var(--wbs-gold); }
.nav__link[aria-current="page"] { color: var(--wbs-evergreen); border-block-end-color: var(--wbs-gold); }

/* Language switcher */
.lang { display: flex; align-items: center; gap: var(--s-1); font-size: var(--fs-sm); }
.lang__link {
  padding: var(--s-1) var(--s-2);
  text-decoration: none;
  color: var(--wbs-slate);
  font-weight: 600;
  border-radius: var(--radius);
  min-height: 2.75rem;
  display: inline-flex;
  align-items: center;
}
.lang__link[aria-current="true"] { color: var(--wbs-evergreen); background: var(--wbs-mist); }
.lang__sep { color: var(--wbs-rule); }

/* Mobile toggle */
.nav-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  background: none;
  border: 1px solid var(--wbs-rule);
  border-radius: var(--radius);
  padding: var(--s-2) var(--s-3);
  font-family: var(--f-body);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--wbs-evergreen);
  cursor: pointer;
  min-height: 2.75rem;
}
@media (min-width: 1000px) { .nav-toggle { display: none; } }

@media (max-width: 999px) {
  .nav {
    position: fixed;
    inset: var(--header-h) 0 auto 0;
    background: var(--wbs-white);
    border-block-end: 1px solid var(--wbs-rule);
    flex-direction: column;
    align-items: stretch;
    padding: var(--s-4) var(--gutter) var(--s-6);
    gap: var(--s-2);
    max-height: calc(100vh - var(--header-h));
    overflow-y: auto;
  }
  .nav[hidden] { display: none; }
  .nav__list { flex-direction: column; align-items: stretch; gap: 0; }
  .nav__link {
    padding: var(--s-3) 0;
    border-block-end: 1px solid var(--wbs-rule-soft);
    min-height: 2.75rem;
  }
  .nav__link[aria-current="page"] { border-block-end-color: var(--wbs-gold); }
  .lang { padding-block-start: var(--s-3); }
}

/* --------------------------------------------------------------------------
   8. HERO
   -------------------------------------------------------------------------- */
.hero {
  background-color: var(--wbs-evergreen);
  color: var(--wbs-white);
  position: relative;
  overflow: hidden;
  padding-block: clamp(3.5rem, 10vw, 7rem);
}
.hero::after {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-end: -8%;
  width: min(46%, 520px);
  background: url("../brand/hero-tile.svg") no-repeat center / contain;
  opacity: 0.13;
  pointer-events: none;
}
@media (max-width: 780px) { .hero::after { display: none; } }

.hero__inner { position: relative; z-index: 1; max-width: 44rem; }
.hero h1 { color: var(--wbs-white); margin-block-end: var(--s-5); }
.hero__lede { font-size: var(--fs-lg); color: #dfe6e2; line-height: 1.55; max-width: 38rem; }
.hero__tagline {
  font-family: var(--f-display);
  font-style: italic;
  font-size: var(--fs-lg);
  color: var(--wbs-gold-tint);
  margin-block-start: var(--s-6);
}
.hero__actions { display: flex; flex-wrap: wrap; gap: var(--s-4); margin-block-start: var(--s-7); }

/* Page header (interior pages) */
.page-head { background: var(--wbs-mist); padding-block: clamp(2.5rem, 6vw, var(--s-9)); border-block-end: 1px solid var(--wbs-rule); }
.page-head h1 { margin-block-end: var(--s-4); }

/* --------------------------------------------------------------------------
   9. BUTTONS
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: 2.875rem;               /* ≥24px target, WCAG 2.2 SC 2.5.8 */
  padding: var(--s-3) var(--s-6);
  font-family: var(--f-body);
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: 0.03em;
  text-decoration: none;
  border: 2px solid transparent;
  border-radius: var(--radius);
  cursor: pointer;
  transition: background var(--transition), color var(--transition), border-color var(--transition);
}
.btn--primary { background: var(--wbs-gold-deep); color: #fff; border-color: var(--wbs-gold-deep); }
.btn--primary:hover { background: #5f5330; border-color: #5f5330; }
.btn--secondary { background: transparent; color: var(--wbs-white); border-color: rgba(255,255,255,0.5); }
.btn--secondary:hover { border-color: var(--wbs-white); background: rgba(255,255,255,0.08); }
.btn--dark { background: var(--wbs-evergreen); color: var(--wbs-white); border-color: var(--wbs-evergreen); }
.btn--dark:hover { background: var(--wbs-evergreen-deep); border-color: var(--wbs-evergreen-deep); }
.btn--ghost { background: transparent; color: var(--wbs-evergreen); border-color: var(--wbs-rule); }
.btn--ghost:hover { border-color: var(--wbs-evergreen); background: var(--wbs-mist); }

/* --------------------------------------------------------------------------
   10. CARDS & PILLARS
   -------------------------------------------------------------------------- */
.card {
  background: var(--wbs-white);
  border: var(--border);
  border-block-start: 3px solid var(--wbs-gold);
  padding: var(--s-6);
  display: flex;
  flex-direction: column;
  /* No height:100%. When a .card sits inside a stretched grid item (e.g. the
     contact aside) it creates a cyclic height dependency: the row is sized
     from content, then the card resolves 100% against it and overflows —
     which pushed the aside's content on top of the footer on mobile.
     Cards used directly as grid items are already equalised by grid stretch. */
}
.card h3 { margin-block-end: var(--s-3); }
.card p { font-size: var(--fs-sm); color: var(--wbs-slate); }
/* Deep gold, not the charter gold: at the mobile end of the fluid scale this
   renders ~22px at weight 600, which is below the 24px large-text threshold
   (weight 600 is not "bold" for contrast purposes), so it needs the full
   4.5:1 rather than 3:1. */
.card__num {
  font-family: var(--f-display);
  font-size: var(--fs-xl);
  color: var(--wbs-gold-deep);
  font-weight: 600;
  line-height: 1;
  margin-block-end: var(--s-3);
}
.card__list { list-style: none; padding: 0; margin-block-start: var(--s-4); font-size: var(--fs-sm); }
.card__list li { padding-inline-start: var(--s-5); position: relative; margin-block-start: var(--s-2); color: var(--wbs-slate); }
.card__list li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: 0.62em;
  width: 6px; height: 6px;
  background: var(--wbs-gold);
}

/* --------------------------------------------------------------------------
   11. STATUS / DATA COMPONENTS
   -------------------------------------------------------------------------- */
.status-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: var(--s-2) var(--s-3);
  border: 1px solid currentColor;
  border-radius: var(--radius);
  max-width: none;
}
.status-badge--dev { color: #6b5a2c; background: #f6f2e4; }
.status-badge--dark { color: var(--wbs-gold-tint); background: rgba(201,183,126,0.12); }

/* Key-figure row — every figure carries its own qualifier */
.figures { display: grid; gap: var(--s-5); border-block-start: 1px solid var(--wbs-rule); padding-block-start: var(--s-6); }
@media (min-width: 640px) { .figures { grid-template-columns: repeat(3, 1fr); } }
.figure__value {
  font-family: var(--f-display);
  font-size: var(--fs-2xl);
  color: var(--wbs-evergreen);
  font-weight: 600;
  line-height: 1.05;
}
.section--dark .figure__value { color: var(--wbs-gold-tint); }
.figure__label { font-size: var(--fs-sm); font-weight: 600; margin-block-start: var(--s-2); }
.figure__note { font-size: var(--fs-xs); color: var(--wbs-slate); margin-block-start: var(--s-1); }
.section--dark .figure__note { color: #b9c4bf; }

/* Definition table */
.spec-table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); margin-block-start: var(--s-5); }
.spec-table caption { text-align: left; font-size: var(--fs-xs); color: var(--wbs-slate); padding-block-end: var(--s-3); }
.spec-table th, .spec-table td { text-align: left; padding: var(--s-3) var(--s-4); border-block-end: 1px solid var(--wbs-rule); vertical-align: top; }
.spec-table th { font-weight: 600; color: var(--wbs-evergreen); width: 38%; background: var(--wbs-mist); }
.spec-table td { color: var(--wbs-ink); }

/* Milestone list */
.milestones { list-style: none; padding: 0; margin-block-start: var(--s-5); }
.milestones li {
  position: relative;
  padding-inline-start: var(--s-7);
  padding-block-end: var(--s-5);
  border-inline-start: 2px solid var(--wbs-rule);
  margin-inline-start: 5px;
  max-width: 60ch;
}
.milestones li:last-child { padding-block-end: 0; border-inline-start-color: transparent; }
.milestones li::before {
  content: "";
  position: absolute;
  inset-inline-start: -7px;
  inset-block-start: 0.45em;
  width: 12px; height: 12px;
  background: var(--wbs-gold);
  border: 2px solid var(--wbs-white);
  border-radius: 50%;
}
.milestones li.is-next::before { background: var(--wbs-white); border-color: var(--wbs-gold); }
.milestones__label { font-weight: 600; color: var(--wbs-evergreen); display: block; }
.milestones__meta { font-size: var(--fs-xs); color: var(--wbs-slate); text-transform: uppercase; letter-spacing: 0.08em; font-weight: 700; }

/* Evidence / integrity note */
.note {
  border-inline-start: 3px solid var(--wbs-gold);
  background: var(--wbs-mist);
  padding: var(--s-4) var(--s-5);
  font-size: var(--fs-sm);
  color: var(--wbs-slate);
  margin-block-start: var(--s-5);
}
.note p { max-width: none; }
.note strong { color: var(--wbs-evergreen); }

/* --------------------------------------------------------------------------
   12. FORMS
   -------------------------------------------------------------------------- */
.form { margin-block-start: var(--s-6); max-width: 40rem; }
.field { margin-block-end: var(--s-5); }
.field label { display: block; font-weight: 600; font-size: var(--fs-sm); margin-block-end: var(--s-2); color: var(--wbs-evergreen); }
.field .hint { display: block; font-weight: 400; font-size: var(--fs-xs); color: var(--wbs-slate); margin-block-start: var(--s-1); }
.field .req { color: #8a2f22; font-weight: 700; }

.field input, .field select, .field textarea {
  width: 100%;
  font-family: var(--f-body);
  font-size: var(--fs-base);
  color: var(--wbs-ink);
  background: var(--wbs-white);
  border: 1px solid var(--wbs-slate);
  border-radius: var(--radius);
  padding: var(--s-3) var(--s-4);
  min-height: 2.875rem;
}
.field textarea { min-height: 9rem; resize: vertical; line-height: 1.55; }
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible {
  outline: var(--focus-ring);
  outline-offset: 1px;
  border-color: var(--wbs-night-blue);
}
.field input[aria-invalid="true"], .field textarea[aria-invalid="true"], .field select[aria-invalid="true"] {
  border-color: #8a2f22;
  border-width: 2px;
}
.field__error { display: block; color: #8a2f22; font-size: var(--fs-sm); font-weight: 600; margin-block-start: var(--s-2); }

.consent { display: flex; gap: var(--s-3); align-items: flex-start; }
.consent input { width: 1.25rem; height: 1.25rem; min-height: 0; flex-shrink: 0; margin-block-start: 0.2rem; }
.consent label { font-weight: 400; font-size: var(--fs-sm); color: var(--wbs-ink); }

.form__status { margin-block-start: var(--s-5); padding: var(--s-4) var(--s-5); font-size: var(--fs-sm); border-inline-start: 3px solid; }
.form__status--ok { border-color: var(--wbs-evergreen); background: #eef3f0; color: var(--wbs-evergreen); }
.form__status--err { border-color: #8a2f22; background: #fbf0ee; color: #7a291d; }

.honeypot { position: absolute; left: -9999px; opacity: 0; height: 0; overflow: hidden; }

/* --------------------------------------------------------------------------
   13. FOOTER
   -------------------------------------------------------------------------- */
.site-footer { background: var(--wbs-evergreen); color: #d5ded9; padding-block: var(--s-9) var(--s-6); margin-block-start: auto; font-size: var(--fs-sm); }
.site-footer h2, .site-footer h3 { color: var(--wbs-white); font-size: var(--fs-sm); font-family: var(--f-body); font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; margin-block-end: var(--s-4); }
.site-footer a { color: #e8e4d6; text-decoration: none; }
.site-footer a:hover { color: var(--wbs-gold-tint); text-decoration: underline; }
.site-footer ul { list-style: none; padding: 0; }
.site-footer li { margin-block-end: var(--s-2); max-width: none; }
.site-footer p { color: #c3cfc9; }

.footer-grid { display: grid; gap: var(--s-7); }
@media (min-width: 720px) { .footer-grid { grid-template-columns: 1.6fr 1fr 1fr; } }
.footer__logo img { height: 2.6rem; margin-block-end: var(--s-4); }
.footer__tagline { font-family: var(--f-display); font-style: italic; color: var(--wbs-gold-tint); }
.footer__legal {
  border-block-start: 1px solid rgba(255,255,255,0.18);
  margin-block-start: var(--s-8);
  padding-block-start: var(--s-5);
  font-size: var(--fs-xs);
  color: #a9b7b1;
}
.footer__legal p { color: #a9b7b1; max-width: none; }
.footer__legal a { color: #cfd8d3; }

/* --------------------------------------------------------------------------
   13a. OFF-SCREEN DIAGRAM RENDERING
   The hand-coded diagrams are INLINE SVG, which is what makes them themeable,
   selectable and pannable — but it also means the browser lays out every one
   of them before it can paint anything, and Lighthouse's mobile profile runs
   at 4x CPU throttling. On the Ntui page, four inline diagrams plus a long
   document put the largest text block at ~2.6s, over the 2.5s gate.

   content-visibility: auto lets the browser skip layout and paint for a
   diagram until it is near the viewport. contain-intrinsic-size supplies a
   placeholder box so the scrollbar does not jump as each one is realised;
   the value is a rough average of the rendered heights, not a measurement of
   any single diagram. Modern browsers still find text inside these for
   find-in-page and for anchor navigation.

   If a diagram ever flashes in late on a slow device, raise the intrinsic
   size rather than removing this — deleting it puts the LCP back over budget.
   -------------------------------------------------------------------------- */
.media-figure--diagram {
  content-visibility: auto;
  contain-intrinsic-size: auto 420px;
}

/* --------------------------------------------------------------------------
   13b. PARTNER MARKS (project role cards)
   A fixed-height band so three marks of very different proportions — a
   horizontal lock-up, a wordmark and a crest — sit on one baseline without
   any of them being stretched. Height is set per mark inline; this rule only
   reserves the band and pins the marks to its bottom edge, which is what
   makes the row read as aligned even though the marks differ in height.
   -------------------------------------------------------------------------- */
.party-logo {
  display: flex;
  align-items: flex-end;
  min-block-size: 3.5rem;          /* 56px — the tallest mark, the crest */
  margin-block-end: var(--s-4);
}
.party-logo img {
  inline-size: auto;               /* never constrain width: it would distort */
  max-inline-size: 100%;
  object-fit: contain;
}
@media print { .party-logo { min-block-size: 0; } }

/* --------------------------------------------------------------------------
   14. AUDIENCE-MEASUREMENT OPT-OUT
   Replaced the fixed consent banner on 14 Aug 2026. Measurement now runs
   under CNIL's audience-measurement exemption, so there is nothing to
   consent to — but the right to object has to be genuinely usable, which
   means a real 24px target, a visible focus ring, and a state line that
   says what is currently true rather than what was clicked.
   -------------------------------------------------------------------------- */
.optout {
  border: 1px solid var(--wbs-mist);
  border-inline-start: 3px solid var(--wbs-gold);
  background: var(--wbs-white);
  padding: var(--s-5);
  border-radius: 2px;
}
.optout[hidden] { display: none; }
.optout__row { display: flex; align-items: flex-start; gap: var(--s-3); }
.optout__row input[type="checkbox"] {
  inline-size: 1.5rem; block-size: 1.5rem;   /* 24px — AAA target size */
  margin: 0; flex: 0 0 auto;
  /* --wbs-evergreen, not --wbs-green: the latter does not exist, and an
     undefined custom property fails silently to the browser's default blue
     rather than to anything in the brand palette. */
  accent-color: var(--wbs-evergreen);
  cursor: pointer;
}
.optout__row label {
  font-weight: 600; cursor: pointer;
  /* The label is the rest of the target: the pair clears 44px comfortably. */
  padding-block: 0.125rem;
}
.optout p { max-width: 68ch; }

/* --------------------------------------------------------------------------
   15. UTILITIES
   -------------------------------------------------------------------------- */
.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.list-clean { list-style: none; padding: 0; }
.list-check { list-style: none; padding: 0; }
.list-check li { position: relative; padding-inline-start: var(--s-6); margin-block-end: var(--s-3); }
.list-check li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: 0.55em;
  width: 10px; height: 2px;
  background: var(--wbs-gold);
}
.mt-0 { margin-block-start: 0; }
.mt-5 { margin-block-start: var(--s-5); }
.mt-6 { margin-block-start: var(--s-6); }
.mt-7 { margin-block-start: var(--s-7); }

/* Legal footnote — subordinate by design. Colour is --wbs-slate (6.53:1 on
   white), so it stays above the AA threshold despite the smaller size; the
   :target rule gives a visible landing cue when the reference is followed,
   which SC 2.4.7 expects of an in-page jump. */
.footnote {
  font-size: var(--fs-xs);
  color: var(--wbs-slate);
  margin-block-start: var(--s-4);
  max-width: var(--measure);
}
.footnote:target { background: var(--wbs-mist); outline: 2px solid var(--wbs-gold-deep); outline-offset: 4px; }
.spec-table sup a { text-decoration: none; padding-inline: 0.15em; }
.spec-table sup a:hover { text-decoration: underline; }

/* --------------------------------------------------------------------------
   16. PRINT
   -------------------------------------------------------------------------- */
@media print {
  .site-header, .optout, .nav-toggle, .hero::after { display: none !important; }
  main, .section--mist, .section--dark, .hero { background-image: none !important; }
  body { color: #000; font-size: 11pt; }
  a::after { content: " (" attr(href) ")"; font-size: 9pt; word-break: break-all; }
  .section--dark, .hero { background: #fff !important; color: #000 !important; }
  .section--dark h2, .hero h1 { color: #000 !important; }
}

/* --------------------------------------------------------------------------
   17. FORCED COLOURS / HIGH CONTRAST
   -------------------------------------------------------------------------- */
@media (forced-colors: active) {
  .btn { border: 2px solid ButtonText; }
  .card { border: 1px solid CanvasText; }
  .milestones li::before { background: CanvasText; }
}

/* --------------------------------------------------------------------------
   18. MEDIA FIGURES, CAPTIONS AND INTERIM DIAGRAMS — visual update, Aug 2026
   Photographs and hand-coded interim SVG diagrams. Principles:
   - Every photograph carries a VISIBLE caption (.figure__caption): place,
     creator/platform, and a status disclosure. No competitor captions or
     credits its imagery; doing so here is deliberate and load-bearing for
     the factual-restraint doctrine. Never move captions into title
     attributes.
   - No fetchpriority anywhere: the LCP element is a text block on every
     page (typographic hero by decision). Promoting an image would delay
     the real LCP.
   - Diagrams are inline SVG so their bilingual text reaches the
     accessibility tree; wide/stack variants swap at 768 px because a
     single SVG cannot reflow.
   -------------------------------------------------------------------------- */
.media-figure { margin: var(--s-7) 0 0; }
.media-figure picture { display: block; }
.media-figure--photo img {
  width: 100%;
  height: auto;
  aspect-ratio: var(--ar-m, auto);
  object-fit: cover;
  border-radius: var(--radius);
}
@media (min-width: 640px)  { .media-figure--photo img { aspect-ratio: var(--ar-t, var(--ar-m, auto)); } }
@media (min-width: 1024px) { .media-figure--photo img { aspect-ratio: var(--ar-d, var(--ar-t, auto)); } }

/* Visible caption — slate on light surfaces stays ≥4.5:1 (6.53:1 on white,
   ~5.3:1 on mist); on the dark band the caption sits inside a white frame
   or is lightened to the band's secondary text colour. */
.figure__caption {
  font-size: var(--fs-xs);
  color: var(--wbs-slate);
  line-height: 1.5;
  margin-block-start: var(--s-3);
  max-width: var(--measure);
}
.section--dark .media-figure:not(.media-figure--frame) .figure__caption { color: #b9c4bf; }

/* White card frame for diagrams sitting on mist or dark surfaces */
.media-figure--frame {
  background: var(--wbs-white);
  border: var(--border);
  padding: var(--s-5);
}
.media-figure--frame .figure__caption { padding-inline: var(--s-1); }

/* Full-bleed page-opener band (activities): image spans the viewport,
   caption stays aligned with the content column. */
.media-figure--bleed { margin: 0; }
.media-figure--bleed img { border-radius: 0; }
.media-figure--bleed .figure__caption { padding-block-start: var(--s-3); }

/* Inline interim diagrams. forced-color-adjust: none — these are data
   graphics with computed brand-token contrast; forcing them into a
   system palette would destroy the encoding (as it would a raster
   image, which is what they replace).
   ONE horizontal artwork per diagram (v2, 10 Aug 2026): stacked mobile
   variants are retired. Below its legible minimum width the figure pans
   horizontally, like a wide data table — the artwork never shrinks past
   readability and never duplicates. */
.diagram svg { width: 100%; height: auto; display: block; forced-color-adjust: none; }
.diagram--pan { overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: thin; }
.diagram--pan svg { min-width: var(--pan-min, 760px); }

/* Five-activity icons — 2 px geometric line icons from the inline sprite.
   Tonal variants follow the watermark logic via currentColor: evergreen on
   white, gold-deep on mist, white reversed on dark. Icons are decorative
   (aria-hidden); the visible text labels carry the meaning. */
.card__icon { width: 44px; height: 44px; color: var(--wbs-evergreen); margin-block-end: var(--s-3); }
.icon--on-mist { color: var(--wbs-gold-deep); }
.icon--on-dark { color: var(--wbs-white); }
.pillar__icon { width: 40px; height: 40px; color: var(--wbs-evergreen); margin-block-end: var(--s-2); }

@media print {
  .media-figure--photo { display: none; }            /* photographs are ambient */
  .diagram--pan { overflow: visible; }               /* print the full artwork */
  .diagram--pan svg { min-width: 0; width: 100%; }
}
