/* Generated by scripts/build-css.mjs. Do not edit directly. */
/* source: styles/fonts.css */
/* Barlow and Barlow Condensed, served from this domain.
 *
 * Previously pulled from fonts.googleapis.com, which sent every visitor's
 * IP to Google before they clicked anything — the only third-party request
 * the site made. Barlow is SIL OFL licensed, so self-hosting is allowed and
 * it removes the transfer entirely. Latin and latin-ext subsets only.
 *
 * font-display: swap keeps text readable while the file loads.
 */

@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/assets/fonts/barlow-400-latin-ext.122b24bc.woff2) format('woff2');
  unicode-range:
    U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
    U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
    U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/assets/fonts/barlow-400-latin.b0a8ad37.woff2) format('woff2');
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212,
    U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(/assets/fonts/barlow-500-latin-ext.3facdf66.woff2) format('woff2');
  unicode-range:
    U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
    U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
    U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(/assets/fonts/barlow-500-latin.cd759df8.woff2) format('woff2');
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212,
    U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(/assets/fonts/barlow-700-latin-ext.88c786d5.woff2) format('woff2');
  unicode-range:
    U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
    U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
    U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(/assets/fonts/barlow-700-latin.2d797dd8.woff2) format('woff2');
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212,
    U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Barlow Condensed';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/assets/fonts/barlow-condensed-400-latin-ext.1eb62753.woff2) format('woff2');
  unicode-range:
    U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
    U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
    U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Barlow Condensed';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/assets/fonts/barlow-condensed-400-latin.7fff1bb2.woff2) format('woff2');
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212,
    U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Barlow Condensed';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/assets/fonts/barlow-condensed-600-latin-ext.aef7edf5.woff2) format('woff2');
  unicode-range:
    U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
    U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
    U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Barlow Condensed';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/assets/fonts/barlow-condensed-600-latin.215a93c6.woff2) format('woff2');
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212,
    U+2215, U+FEFF, U+FFFD;
}

/* source: styles/industry.css */
/* Industry — the scales and the few shared classes the site actually uses.
   This file declares the type, space and colour scales; brand.css retunes
   them for LA2SOFT. Sections keep their own scoped styles, so only the
   classes consumed by more than one of them live here. */
/* Fonts are self-hosted — see src/styles/fonts.css, imported first in main.js. */

:root {
  --color-bg: #f2f2f3;
  --color-surface: #e9e9ea;
  --color-text: #1d1f20;
  --color-accent: #5980a6;
  /* The second accent has no ramp: nothing has ever needed a tint of it, and
     the site's second ground reads it as one flat colour. It keeps its paired
     ink role below — the primitive and its --color-on- partner are one unit,
     and that unit is in use. */
  --color-accent-2: #728fab;
  --color-divider: color-mix(in srgb, #1d1f20 16%, transparent);

  /* Tonal ramps — generated in OKLCH on one shared lightness scale, so the
     same step of any role matches the others in visual value. */
  --color-neutral-100: #f5f5f8;
  --color-neutral-200: #e7e7ea;
  --color-neutral-300: #d4d4d7;
  --color-neutral-400: #b7b7ba;
  --color-neutral-500: #98989b;
  --color-neutral-600: #7a7a7d;
  --color-neutral-700: #5d5d60;
  --color-neutral-800: #424244;
  --color-neutral-900: #2b2b2d;

  --color-accent-100: #eef6ff;
  --color-accent-200: #d6ebff;
  --color-accent-300: #b5d9fd;
  --color-accent-400: #94bce3;
  --color-accent-500: #749dc4;
  --color-accent-600: #597ea3;
  --color-accent-700: #416180;
  --color-accent-800: #2c455d;
  --color-accent-900: #1d2d3d;

  /* Semantic roles. The ramps above name an appearance; these name a job,
     and each pair is verified for WCAG 2.1 AA contrast at the point where
     the underlying colour is known — which is why a brand that retunes the
     accent must retune these too (see brand.css). */
  --color-on-accent: var(--color-bg);
  --color-on-accent-2: var(--color-text);
  --color-danger: #8e3730;
  /* The amber callout the legal pages use to mark a fact that is still
     unresolved. A role, not a decoration: it is what a reader looks for to
     tell a published statement from a placeholder. */
  --color-notice-surface: #f6e9d3;
  --color-on-notice: #9a5b08; /* 4.52:1 on --color-notice-surface */
  --color-border-input: var(--color-divider);
  /* A surface that sits above the page ground, where --color-surface sits
     below it: form controls and cards that need to read as raised. */
  --color-surface-raised: #fff;

  --font-heading: 'Barlow Condensed', system-ui, sans-serif;
  --font-heading-weight: 600;
  --font-body: 'Barlow', system-ui, sans-serif;

  /* Type scale. In rem, not px: a px font-size ignores the reader's browser
     font-size setting, which is the one accessibility control a low-vision
     visitor is most likely to have already set. At the default 16px root
     these render identically to the px values they replace. */
  --text-2xs: 0.6875rem; /* 11px */
  --text-xs: 0.75rem; /* 12px */
  --text-sm: 0.8125rem; /* 13px */
  --text-md: 0.875rem; /* 14px */
  --text-base: 0.9375rem; /* 15px — body copy */
  --text-lg: 1rem; /* 16px */
  --text-xl: 1.0625rem; /* 17px */
  --text-2xl: 1.1875rem; /* 19px */
  --text-3xl: 1.375rem; /* 22px */
  --text-4xl: 1.5625rem; /* 25px */
  --text-5xl: 2rem; /* 32px */
  --text-6xl: 2.625rem; /* 42px */

  /* Space scale. Deliberately coarse: a fine grid would re-admit the
     per-component drift this scale exists to remove. Anything that cannot
     land on a step is either a section rhythm or a named constant below. */
  --space-3xs: 2px;
  --space-2xs: 4px;
  --space-xs: 8px;
  --space-sm: 12px;
  --space-md: 16px;
  --space-lg: 20px;
  --space-xl: 24px;
  --space-2xl: 32px;
  --space-3xl: 40px;
  --space-4xl: 48px;
  --space-5xl: 56px;

  /* Section rhythm — page-level, not component-level, and coarser on purpose.
     56px is deliberately absent: it is a scale step above, because the same
     value serves as a column gap, and naming that "section rhythm" would
     misdescribe it. */
  --space-section-sm: 52px;
  --space-section-lg: 90px;

  /* Named constants. Not scale members: each is derived from something
     external — the sticky header's own height, a WCAG minimum — so folding
     them into the space scale would lose the reason they hold that value. */
  --header-offset: 78px;
  --header-offset-compact: 70px;
  --tap-target-min: 44px;
}

body {
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
}
h1,
h2,
h3,
h4 {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
}

.blueprint {
  position: relative;
  border: 1px solid var(--color-divider);
  border-radius: 0;
}
.blueprint > .corner {
  position: absolute;
  width: 11px;
  height: 11px;
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}
.blueprint > .corner::before,
.blueprint > .corner::after {
  content: '';
  position: absolute;
  background: currentColor;
}
.blueprint > .corner::before {
  left: 5px;
  top: 0;
  width: 1px;
  height: 100%;
}
.blueprint > .corner::after {
  top: 5px;
  left: 0;
  width: 100%;
  height: 1px;
}
.blueprint > .corner.tl {
  top: -6px;
  left: -6px;
}
.blueprint > .corner.tr {
  top: -6px;
  right: -6px;
}
.blueprint > .corner.bl {
  bottom: -6px;
  left: -6px;
}
.blueprint > .corner.br {
  bottom: -6px;
  right: -6px;
}

/* ══════════════════════════════════════════════════════════════════════════
   Element defaults and the shared classes. A class earns its place here only
   by being used outside a single component; anything one section needs alone
   belongs in that section's <style> block.
   ══════════════════════════════════════════════════════════════════════ */

*,
*::before,
*::after {
  box-sizing: border-box;
}
body {
  margin: 0;
  font-size: var(--text-base);
  line-height: 1.55;
  font-weight: 400;
}
h1,
h2,
h3,
h4,
h5,
h6 {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  line-height: 1.12;
  letter-spacing: -0.015em;
  margin: 0 0 var(--space-xs);
}
h1 {
  font-size: var(--text-6xl);
}
h2 {
  font-size: var(--text-5xl);
}
h3 {
  font-size: var(--text-4xl);
}
h4 {
  font-size: var(--text-2xl);
}
h5 {
  font-size: var(--text-lg);
}
h6 {
  font-size: var(--text-sm);
}
h6 {
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
p {
  margin: 0 0 var(--space-sm);
}
a {
  color: var(--color-accent);
  text-underline-offset: 3px;
}
img {
  display: block;
  max-width: 100%;
}
figure {
  margin: 0;
}
figcaption {
  font-size: var(--text-2xs);
  margin-top: var(--space-2xs);
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}
:focus {
  outline: none;
}
:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}
::selection {
  background: color-mix(in srgb, var(--color-accent) 30%, transparent);
}

/* — buttons — */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  cursor: pointer;
  text-decoration: none;
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: var(--text-md);
  line-height: 1.2;
  color: var(
    --color-text
  ); /* matches the .input's 14px —
     the pair sits side by side in sign-up rows */
  background: transparent;
  border: 1px solid transparent;
  padding: var(--space-xs) calc(var(--space-sm) * 1.2);
}
.btn svg {
  display: block;
}
.btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
.btn-secondary {
  border-color: var(--color-divider);
}
.btn-secondary:hover {
  background: color-mix(in srgb, var(--color-text) 7%, transparent);
}
.btn-secondary:active {
  background: color-mix(in srgb, var(--color-text) 14%, transparent);
}

/* — forms — */
.field > label {
  display: block;
  font-size: var(--text-xs);
  margin-bottom: var(--space-2xs);
  color: color-mix(in srgb, var(--color-text) 70%, transparent);
}
.input {
  width: 100%;
  min-height: 36px;
  padding: var(--space-xs) var(--space-sm);
  font: inherit;
  font-size: var(--text-md);
  color: var(--color-text);
  caret-color: var(--color-accent);
  background: var(--color-surface);
  border: 1px solid var(--color-divider);
}
.input:hover {
  border-color: color-mix(in srgb, var(--color-text) 45%, transparent);
}
.input:focus-visible {
  border-color: var(--color-accent);
  outline-offset: 0;
}
textarea.input {
  min-height: 90px;
  resize: vertical;
}

/* — blueprint frame: components are wireframe objects (see .blueprint
     and .corner above) — square, transparent, hairline-bordered — */
.btn,
.input {
  border-radius: 0;
}
.btn {
  border: 1px solid var(--color-divider);
}

/* source: styles/brand.css */
/* LA2SOFT brand override of the Industry tokens.
   The steel accent is replaced by the company blue; everything else
   (type, spacing, blueprint frames, buttons) comes from industry.css. */
:root {
  --color-accent: #344fea;
  --color-accent-2: var(--brand-cyan);

  /* The accent ramp, retuned to the company blue. It overrides every step:
     a partial override leaves the rest at the imported steel, and a steel
     step in a blue brand is a trap nothing warns you about — four of these
     were exactly that until this override was completed.

     The ramp has two regions, and they do different jobs.

     Steps 100–500 and 800–900 are surfaces. They sit on the shared OKLCH
     lightness curve that industry.css declares — same lightness as
     --color-neutral-N at the same step — with the brand hue and industry's
     chroma profile, so a tint of the accent still matches a tint of the
     neutral in visual value.

     Steps 600 and 700 are deliberately NOT on that curve, and must not be
     "corrected" onto it. They are the only two steps carrying text: 700 is
     the link colour and the CTA hover, 600 is the language selector. The
     shared curve is a surface scale and was never built to hold text —
     industry's own accent-600 measures 3.80:1 on the page ground, and the
     generated brand equivalent measures 4.07:1. Both fail AA. These two are
     hand-darkened until they pass, and the ratios below are measured on
     --color-bg (#f2f2f3). */
  --color-accent-100: #f1f5ff;
  --color-accent-200: #dfe8ff;
  --color-accent-300: #c3d4ff;
  --color-accent-400: #99b5ff;
  --color-accent-500: #6d90ff;
  --color-accent-600: #2a41c6; /* text role — 7.03:1, off-curve on purpose */
  --color-accent-700: #22349c; /* text role — 9.20:1, off-curve on purpose */
  --color-accent-800: #213498;
  --color-accent-900: #152364;

  --brand-blue: #344fea;
  --brand-cyan: #4db8ee;
  --brand-cyan-rule: #72c5f2;
  --brand-deep: #131c52;

  /* Text colours for the brand fills, each measured against its own ground.
     The cyan is the trap: it looks like a dark brand colour but it is light,
     so white on it reaches only 2.23:1 — far under the 4.5:1 AA needs. Ink
     on cyan reaches 7.41:1. Never write a literal #fff over --brand-cyan. */
  --color-on-accent: #fff; /* on --brand-blue — 6.08:1 */
  --color-on-accent-2: var(--color-text); /* on --brand-cyan — 7.41:1 */

  /* The blue has far less room than the navy: it is a mid-tone, so white
     fades below AA much sooner. The muted step that reads 9.20:1 on
     --brand-deep would be 4.07:1 here — a failure. These are the quiet
     steps the blue can actually afford; do not swap the two sets. */
  --color-on-accent-strong: rgba(255, 255, 255, 0.94); /* 5.57:1 */
  --color-on-accent-muted: rgba(255, 255, 255, 0.88); /* 5.08:1 */
  --color-on-accent-rule: rgba(255, 255, 255, 0.6);
  --color-on-accent-rule-subtle: rgba(255, 255, 255, 0.24);

  /* Text on the deep navy sections, replacing twelve hand-picked alpha values
     that fell into three clusters anyway. Ratios are against --brand-deep;
     all clear AA for normal text by a wide margin. */
  --color-on-deep: #fff; /* 15.96:1 — headings, emphasis */
  --color-on-deep-strong: rgba(255, 255, 255, 0.9); /* 13.09:1 — body copy */
  --color-on-deep-muted: rgba(255, 255, 255, 0.74); /* 9.20:1 — secondary */
  --color-on-deep-subtle: rgba(255, 255, 255, 0.58); /* 6.15:1 — tertiary */

  /* Non-text treatments on the same ground. Separate roles on purpose: these
     carry no information, so they answer to the eye rather than to a ratio,
     and collapsing them into the text steps would over-darken the rules. */
  --color-on-deep-rule-subtle: rgba(255, 255, 255, 0.15);
  --color-on-deep-rule: rgba(255, 255, 255, 0.24);
  --color-on-deep-rule-strong: rgba(255, 255, 255, 0.45);
  --color-on-deep-rule-bright: rgba(255, 255, 255, 0.55);
  --color-on-deep-surface: rgba(255, 255, 255, 0.08);
  /* Links on the navy ground. The accent ramp is tuned for the light
     page and turns periwinkle here; this stays in the cyan family the
     footer reads as, and clears AA. */
  --color-on-deep-link: #94bce3; /* 7.95:1 */
}

html {
  scroll-behavior: smooth;
}

/* The header overlay owns this runtime state; the document foundation owns
   the scroll container it locks. */
html.header-overlay-open {
  overflow: hidden;
}
body {
  margin: 0;
}

/* The header is sticky (88px, 62px once scrolled). Without this, every nav
   click parked the section title underneath it — a live navigation bug.
   The legacy fragment aliases are scroll targets too, so they carry the same
   offset: an inbound /fr/#services link must not land under the header. */
section[id],
[id].alias {
  scroll-margin-top: var(--header-offset);
}
@media (max-width: 1040px) {
  section[id],
  [id].alias {
    scroll-margin-top: var(--header-offset-compact);
  }
}
/* An alias is a scroll target, not content: out of flow so that opening a
   section with one does not push the heading down by a line. Three sections
   carry one, and all three used to say this themselves. */
.alias {
  position: absolute;
}
a {
  color: var(--color-accent-700);
  text-decoration: none;
}
a:hover {
  color: var(--brand-cyan);
}

.wrap {
  max-width: 1240px;
  margin: 0 auto;
  padding: 0 var(--space-2xl);
}
.section-title {
  font-family: var(--font-heading);
  font-size: var(--text-6xl);
  margin: 0;
}
.rule {
  width: 33px;
  height: 3px;
  background: var(--brand-cyan);
}
/* Under a centred heading. The block margin is part of the pattern — the
   three sections that centre their intro all used the same one. A rule that
   sits in a left-aligned column takes its own margin from its section, which
   is a spacing decision that section owns. */
.rule.center {
  margin: var(--space-xl) auto;
}

/* Section intro — heading, rule, standfirst, centred. The width cap is the
   one part that differs between sections, so it arrives as a property
   instead of forcing three near-identical blocks. Sections that cap an
   intro without centring it are not this pattern and do not use it. */
.section-intro {
  --intro-width: none;
  max-width: var(--intro-width);
  margin-inline: auto;
  text-align: center;
}
.cta {
  border-radius: 0;
  padding: var(--space-md) var(--space-xl);
  font-size: var(--text-lg);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}
.cta-primary {
  background: var(--brand-blue);
  color: var(--color-bg);
  border: 0;
}
.cta-primary:hover {
  background: var(--color-accent-700);
}

/* ── Brand grounds ─────────────────────────────────────────────────────────
   A fill and the ink that is legible on it, declared together and nowhere
   else. The pairing is the thing that was got wrong twice — once in each
   copy of the coloured tile — because each copy chose its own text colours
   for the same fill. A block picks a ground and then reads --ink-*; it never
   names a colour for a ground itself.

   The four grounds are not interchangeable. Cyan is a light fill and takes
   ink. Blue is a mid-tone with far less headroom than the navy, so its quiet
   steps stay brighter. The ratios are recorded where the text steps are
   declared above; --ink-rule and --ink-border carry no information and
   answer to the eye instead. */
.ground-blue {
  background: var(--brand-blue);
  color: var(--color-on-accent);
  --ink: var(--color-on-accent);
  --ink-strong: var(--color-on-accent-strong);
  --ink-muted: var(--color-on-accent-muted);
  --ink-rule: var(--color-on-accent-rule);
  --ink-border: var(--color-on-accent-rule-subtle);
}
.ground-cyan {
  background: var(--brand-cyan);
  color: var(--color-on-accent-2);
  --ink: var(--color-text);
  --ink-strong: var(--color-text);
  --ink-muted: color-mix(in srgb, var(--color-text) 70%, transparent);
  --ink-rule: color-mix(in srgb, var(--color-text) 55%, transparent);
  --ink-border: color-mix(in srgb, var(--color-text) 28%, transparent);
}
.ground-deep {
  background: var(--brand-deep);
  color: var(--color-on-deep);
  --ink: var(--color-on-deep);
  --ink-strong: var(--color-on-deep-strong);
  --ink-muted: var(--color-on-deep-muted);
  --ink-rule: var(--color-on-deep-rule-bright);
  --ink-border: var(--color-on-deep-rule);
}
/* The quiet ground: the page surface, used where a run of saturated tiles
   needs one that is deliberately not a brand colour. */
.ground-muted {
  background: var(--color-surface);
  color: var(--color-text);
  --ink: var(--color-text);
  --ink-strong: var(--color-text);
  --ink-muted: color-mix(in srgb, var(--color-text) 70%, transparent);
  --ink-rule: var(--color-neutral-400);
  --ink-border: var(--color-divider);
}

/* The rule under a card or tile heading. It takes the ink of the ground it
   sits on; the space around it stays with the block that uses it. */
.head-rule {
  height: 3px;
  background: var(--ink-rule);
}

/* Mobile scroll budget. The copy is deliberately precise, which costs words;
   the section chrome is what gets cut instead — no content removed.
   Sections pad either themselves or an .inner wrapper, so the vertical rhythm
   is normalised onto the section and zeroed on the wrapper. Without that
   second rule the two paddings stack and mobile gets longer, not shorter. */
@media (max-width: 700px) {
  section {
    padding-block: var(--space-section-sm) !important;
    padding-inline: var(--space-lg) !important;
  }
  section > .inner {
    padding-block: 0 !important;
  }
  .wrap {
    padding-inline: 0;
  }
  .section-title {
    font-size: var(--text-5xl);
  }
}

/* scroll reveal */
.js .reveal {
  opacity: 0;
  transform: translateY(18px);
  transition:
    opacity 0.6s ease,
    transform 0.6s ease;
}
.js .reveal.visible {
  opacity: 1;
  transform: none;
}
@media (prefers-reduced-motion: reduce) {
  .js .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* source: styles/components/rich.css */
strong.c-rich.accent {
    color: var(--brand-blue);
  }

/* source: styles/components/collapse.css */
.collapse.c-collapse {
    border-top: 1px solid var(--color-divider);
  }
  .c-collapse .sum {
    display: none;
    width: 100%;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-sm);
    min-height: 48px;
    padding: var(--space-md) 0;
    background: none;
    border: 0;
    cursor: pointer;
    color: inherit;
    text-align: left;
    font-family: var(--font-heading);
    font-size: var(--text-xl);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
  }
  .c-collapse .sum:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
  }
  .c-collapse .mark {
    font-size: var(--text-3xl);
    line-height: 1;
    color: var(--color-accent-700);
  }

  .c-collapse .body {
    display: block;
  }
  .c-collapse.c-collapse--enhanced .sum {
    display: flex;
  }
  .c-collapse.c-collapse--enhanced .body {
    display: none;
    padding-bottom: var(--space-lg);
  }
  .collapse.c-collapse.open .body {
    display: block;
  }

  @media (min-width: 900px) {
    .collapse.c-collapse {
      border-top: 0;
    }
    .c-collapse .sum,
    .c-collapse.c-collapse--enhanced .sum {
      display: none;
    }
    .c-collapse.c-collapse--enhanced .body {
      display: block;
      padding-bottom: 0;
    }
  }

/* source: styles/components/header.css */
.skip.c-header {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 100;
    background: var(--brand-deep);
    color: var(--color-on-deep);
    padding: var(--space-sm) var(--space-lg);
    font-family: var(--font-heading);
    text-transform: uppercase;
    letter-spacing: 0.08em;
  }
  .skip.c-header:focus {
    left: 0;
  }

  header.c-header {
    position: sticky;
    top: 0;
    z-index: 60;
    background: color-mix(in srgb, var(--color-bg) 94%, transparent);
    backdrop-filter: blur(6px);
    border-bottom: 1px solid var(--color-divider);
  }
  .c-header .bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 88px;
    transition: height 0.25s ease;
  }
  header.c-header.scrolled .bar {
    height: 62px;
  }
  .c-header .brand {
    display: flex;
    align-items: center;
  }
  .c-header .brand img {
    height: var(--tap-target-min);
    width: auto;
    transition: height 0.25s ease;
  }
  header.c-header.scrolled .brand img {
    height: 32px;
  }

  .c-header nav.desk {
    display: flex;
    align-items: center;
    gap: var(--space-xl);
  }
  .c-header nav.desk > a {
    font-family: var(--font-heading);
    font-size: var(--text-xl);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--color-text);
    /* 44px minimum hit area — these are standalone controls, not inline links */
    display: inline-flex;
    align-items: center;
    min-height: var(--tap-target-min);
  }
  .c-header nav.desk > a:hover {
    color: var(--brand-blue);
  }
  .c-header nav.desk > a.cta {
    color: var(--color-bg);
    font-size: var(--text-base);
    padding: var(--space-xs) var(--space-lg);
  }

  .c-header .langs {
    display: flex;
    align-items: center;
    gap: var(--space-xs);
    font-family: var(--font-heading);
    font-size: var(--text-base);
    letter-spacing: 0.08em;
    padding-left: var(--space-xs);
    border-left: 1px solid var(--color-divider);
  }
  .c-header .langs .separator {
    color: var(--color-neutral-400);
  }
  .c-header .langs a,

  .c-header .langs span[aria-current='page'] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-xs) var(--space-xs);
    min-width: var(--tap-target-min);
    min-height: var(--tap-target-min);
  }
  .c-header .langs span[aria-current='page'] {
    color: var(--color-neutral-700);
    /* The alternate locale owns the link styling, so the current one carries
       its own weight cue rather than reading as the de-emphasized option. */
    font-weight: 600;
  }
  .c-header .langs a {
    color: var(--brand-blue);
    text-decoration: underline;
    text-underline-offset: 5px;
  }
  /* The global a:hover cyan is 2.26:1 on the light header, so the switcher
     deepens the blue instead: 7.07:1, and darker than its resting 6.08:1. */
  .c-header .langs a:hover {
    color: var(--color-accent-600);
  }
  .c-header .lang-name {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    white-space: nowrap;
    clip-path: inset(50%);
  }

  .c-header .burger {
    display: none;
    align-items: center;
    justify-content: center;
    width: 46px;
    height: 46px;
    background: none;
    color: var(--color-text);
    border: 1px solid var(--color-divider);
    cursor: pointer;
  }

  .overlay.c-header {
    position: fixed;
    inset: 0;
    z-index: 80;
    background: var(--brand-deep);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-sm);
    padding: var(--space-xl);
    overflow-y: auto;
  }
  .overlay.c-header a {
    font-family: var(--font-heading);
    font-size: clamp(26px, 7vw, 40px);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-on-deep);
    text-align: center;
    padding: var(--space-xs) 0;
  }
  .overlay.c-header a.accent {
    color: var(--brand-cyan);
  }
  .c-header .close {
    position: absolute;
    top: 26px;
    right: 26px;
    width: 46px;
    height: 46px;
    background: none;
    border: 1px solid var(--color-on-deep-rule-strong);
    color: var(--color-on-deep);
    cursor: pointer;
  }
  .c-header .langs.big {
    margin-top: var(--space-xl);
    border: 0;
    padding: 0;
  }
  /* `.overlay a` sets a nav-scale font clamp with a direct rule, and a direct
     rule always beats an inherited value: sizing the container would apply to
     the current-locale <span> only, leaving the link at nav scale. The switcher
     is secondary chrome, so both elements are pinned here, below nav scale. */
  .c-header .langs.big a,

  /* `.overlay a` sets a nav-scale font clamp with a direct rule, and a direct
     rule always beats an inherited value: sizing the container would apply to
     the current-locale <span> only, leaving the link at nav scale. The switcher
     is secondary chrome, so both elements are pinned here, below nav scale. */
  .c-header .langs.big span[aria-current='page'] {
    color: var(--color-on-deep);
    font-size: var(--text-2xl);
    letter-spacing: 0.1em;
    text-transform: none;
    min-width: var(--tap-target-min);
    min-height: var(--tap-target-min);
  }
  .c-header .langs.big a {
    color: var(--brand-cyan);
    text-decoration: underline;
    text-underline-offset: 6px;
  }
  .c-header .langs.big a:hover {
    color: var(--brand-cyan-rule);
  }

  @media (max-width: 1040px) {
    .c-header nav.desk {
      display: none;
    }
    .c-header .burger.c-header__burger--enhanced {
      display: inline-flex;
    }
  }

.c-header.overlay[hidden] {
  display: none;
}

/* source: styles/components/hero.css */
.hero.c-hero {
    /* ds-exempt: asymmetric on purpose, so the hero's optical centre sits
       above the geometric one. Not a rhythm — it answers to the eye. */
    padding-top: 84px;
    /* ds-exempt: the other half of the same optical pair */
    padding-bottom: 80px;
  }
  .c-hero .grid {
    display: grid;
    grid-template-columns: 1.05fr 1fr;
    gap: var(--space-5xl);
    align-items: center;
  }
  .c-hero .kicker {
    font-family: var(--font-heading);
    font-size: var(--text-2xl);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--color-accent-700);
  }
  .c-hero .rule {
    margin: var(--space-lg) 0 var(--space-xl);
  }
  .c-hero h1 {
    font-size: clamp(34px, 4.4vw, 54px);
    line-height: 1.06;
    margin: 0 0 var(--space-xl);
    text-wrap: balance;
  }
  .c-hero .sub {
    font-size: var(--text-2xl);
    line-height: 1.55;
    max-width: 46ch;
    margin: 0 0 var(--space-2xl);
    color: var(--color-neutral-700);
  }
  .c-hero .actions {
    display: flex;
    gap: var(--space-md);
    flex-wrap: wrap;
  }
  .c-hero .frame {
    padding: var(--space-sm);
  }
  .c-hero .video {
    position: relative;
    overflow: hidden;
    background: var(--brand-deep);
    aspect-ratio: 16 / 9;
  }
  .c-hero .video video {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
  .c-hero .wash {
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(
      90deg,
      color-mix(in srgb, var(--brand-blue) 55%, transparent) 0%,
      color-mix(in srgb, var(--brand-cyan) 45%, transparent) 100%
    );
  }
  .c-hero figcaption {
    font-family: var(--font-heading);
    font-size: var(--text-sm);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    margin-top: var(--space-sm);
  }
  @media (max-width: 980px) {
    .c-hero .grid {
      grid-template-columns: 1fr;
      gap: var(--space-3xl);
    }
  }

/* source: styles/components/situations.css */
section.c-situations {
    padding: var(--space-lg) var(--space-2xl) var(--space-section-lg);
  }
  .c-situations .section-intro {
    --intro-width: 700px;
  }
  .c-situations .section-intro p {
    margin: 0;
    font-size: var(--text-xl);
    color: var(--color-neutral-700);
  }

  .c-situations .cards {
    list-style: none;
    margin: var(--space-4xl) 0 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: var(--space-xs);
  }
  /* Fill and ink come from the ground class selected by the markup; this
     component owns the card's shape and motion. */
  .c-situations .card-item {
    padding: var(--space-xl) var(--space-2xl) var(--space-2xl);
    transition: transform 0.3s ease;
  }
  .c-situations .card-item:hover {
    transform: translateY(-5px);
  }
  @media (prefers-reduced-motion: reduce) {
    .c-situations .card-item:hover {
      transform: none;
    }
  }
  .c-situations .idx {
    font-family: var(--font-heading);
    font-size: var(--text-md);
    letter-spacing: 0.16em;
    color: var(--ink-muted);
  }
  .c-situations .card-item h3 {
    font-size: var(--text-4xl);
    margin: var(--space-xs) 0 0;
    text-transform: uppercase;
    line-height: 1.1;
  }
  .c-situations .head-rule {
    margin: var(--space-md) 0;
  }
  .c-situations .card-item p {
    margin: 0;
    font-size: var(--text-lg);
    line-height: 1.6;
    color: var(--ink);
  }
  .c-situations .card-item strong {
    color: var(--ink);
    font-weight: 700;
  }

  .c-situations .new-process {
    margin-top: var(--space-xs);
    padding: var(--space-2xl);
  }
  .c-situations .new-process h3 {
    margin: 0 0 var(--space-sm);
    color: var(--brand-cyan);
    font-size: var(--text-4xl);
    text-transform: uppercase;
  }
  .c-situations .new-process p {
    margin: 0;
    max-width: 82ch;
    color: var(--ink-strong);
  }
  .c-situations .new-process .corner {
    color: var(--ink-rule);
  }

  /* the calmer ground breaks the rhythm after seven saturated tiles */
  .c-situations .covers {
    position: relative;
    margin-top: var(--space-5xl);
    padding: var(--space-3xl) var(--space-3xl);
    background: var(--color-surface);
    border: 1px solid var(--color-divider);
    scroll-margin-top: var(--header-offset);
  }
  .c-situations .covers-h {
    font-size: var(--text-4xl);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    margin: 0 0 var(--space-md);
    padding-bottom: var(--space-md);
    border-bottom: 3px solid var(--brand-cyan);
  }
  .c-situations .covers-intro {
    margin: 0 0 var(--space-2xl);
    font-size: var(--text-lg);
    max-width: 74ch;
    color: var(--color-neutral-800);
  }

  .c-situations .groups {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: var(--space-2xl);
  }
  .c-situations .group h4 {
    font-size: var(--text-2xl);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin: 0 0 var(--space-sm);
    color: var(--color-accent-700);
  }
  .c-situations .group ul {
    margin: 0;
    padding-left: var(--space-lg);
  }
  .c-situations .group li {
    font-size: var(--text-base);
    margin-bottom: var(--space-xs);
    color: var(--color-neutral-800);
  }

  .c-situations .limit {
    margin: var(--space-2xl) 0 0;
    padding: var(--space-lg) var(--space-xl);
    font-size: var(--text-lg);
    background: var(--color-bg);
    border-left: 4px solid var(--brand-blue);
    max-width: none;
  }
  .c-situations .after {
    margin: var(--space-xl) 0 0;
    padding: var(--space-xl) var(--space-xl);
    background: var(--color-bg);
  }
  .c-situations .after h4 {
    margin: 0 0 var(--space-xs);
    font-size: var(--text-2xl);
    text-transform: uppercase;
    letter-spacing: 0.04em;
  }
  .c-situations .after p {
    margin: 0;
    font-size: var(--text-lg);
    max-width: 78ch;
    color: var(--color-neutral-800);
  }

  .c-situations .sources {
    margin-top: var(--space-xs);
    padding: var(--space-xl) var(--space-2xl);
    border-color: var(--brand-blue);
  }
  .c-situations .sources h3 {
    margin: 0 0 var(--space-xs);
    font-size: var(--text-2xl);
    text-transform: uppercase;
    color: var(--ink);
  }
  .c-situations .sources p {
    margin: 0;
    font-size: var(--text-lg);
    max-width: 76ch;
    color: var(--ink-strong);
  }
  .c-situations .sources .corner {
    color: var(--ink-rule);
  }

  .c-situations .foot {
    text-align: center;
    margin-top: var(--space-4xl);
  }

  @media (max-width: 700px) {
    .c-situations .covers {
      padding: var(--space-xl) var(--space-lg);
      margin-top: var(--space-3xl);
    }
    .c-situations .covers-h {
      font-size: var(--text-3xl);
    }
    .c-situations .groups {
      gap: var(--space-xl);
    }
  }

/* source: styles/components/reglemente.css */
section.c-reglemente {
    background: var(--brand-deep);
    color: var(--color-on-deep);
  }
  .c-reglemente .inner {
    padding-top: var(--space-section-lg);
    padding-bottom: var(--space-section-lg);
  }
  .c-reglemente .intro {
    max-width: 70ch;
  }
  .c-reglemente h2 {
    color: var(--color-on-deep);
  }
  .c-reglemente .rule {
    margin: var(--space-xl) 0;
  }
  .c-reglemente .lead {
    font-size: var(--text-2xl);
    line-height: 1.5;
    margin: 0 0 var(--space-xl);
    color: var(--color-on-deep);
  }
  .c-reglemente .cred {
    font-size: var(--text-xl);
    line-height: 1.6;
    margin: 0 0 var(--space-md);
    color: var(--color-on-deep-strong);
  }
  .c-reglemente .disc {
    font-size: var(--text-base);
    line-height: 1.6;
    margin: 0;
    color: var(--color-on-deep-muted);
    border-left: 2px solid var(--color-on-deep-rule);
    padding-left: var(--space-md);
  }

  .c-reglemente .blocks {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: var(--space-3xs);
    margin-top: var(--space-section-sm);
  }
  .c-reglemente .block {
    background: var(--color-on-deep-surface);
    padding: var(--space-xl) var(--space-2xl);
  }
  .c-reglemente .block h3 {
    font-size: var(--text-2xl);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    margin: 0 0 var(--space-sm);
    color: var(--brand-cyan);
  }
  .c-reglemente .block p {
    margin: 0;
    font-size: var(--text-base);
    line-height: 1.6;
    color: var(--color-on-deep-strong);
  }

  .c-reglemente .outro {
    margin-top: var(--space-section-sm);
    padding: var(--space-2xl) var(--space-2xl);
    border-color: var(--color-on-deep-rule);
  }
  .c-reglemente .outro p {
    margin: 0;
    font-size: var(--text-lg);
    line-height: 1.6;
    color: var(--color-on-deep-strong);
    max-width: 74ch;
  }
  .c-reglemente .outro strong {
    color: var(--color-on-deep);
  }
  .c-reglemente .outro .corner {
    color: var(--color-on-deep-subtle);
  }

  /* the collapse sits on the deep ground, so its summary must invert */
  section.c-reglemente .c-collapse {
    border-top-color: var(--color-on-deep-rule);
  }
  section.c-reglemente .c-collapse .sum {
    color: var(--color-on-deep);
  }
  section.c-reglemente .c-collapse .sum:focus-visible {
    outline-color: var(--color-on-deep);
  }
  section.c-reglemente .c-collapse .mark {
    color: var(--brand-cyan);
  }

/* source: styles/components/plateformes.css */
section.c-plateformes {
    padding: var(--space-lg) var(--space-2xl) var(--space-section-lg);
  }
  .c-plateformes .section-intro {
    --intro-width: 660px;
  }
  .c-plateformes .section-intro p {
    margin: 0;
    font-size: var(--text-xl);
    color: var(--color-neutral-700);
  }

  .c-plateformes .grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: var(--space-xs);
    margin-top: var(--space-3xl);
  }
  /* The fill and the ink that goes with it come from the ground class in the
     markup — .ground-blue, .ground-cyan, .ground-muted in brand.css. This
     block owns the tile's shape, not its colours. */
  .c-plateformes .tile {
    padding: var(--space-xl);
  }
  .c-plateformes .tile.ground-muted {
    border-color: var(--color-neutral-400);
  }
  .c-plateformes .tile h3 {
    font-size: var(--text-3xl);
    margin: 0;
    text-transform: uppercase;
    line-height: 1.15;
  }
  .c-plateformes .tile h3 em {
    font-style: normal;
    font-size: var(--text-sm);
    letter-spacing: 0.06em;
    opacity: 0.8;
    text-transform: none;
  }
  .c-plateformes .head-rule {
    margin: var(--space-sm) 0 var(--space-md);
  }
  .c-plateformes .tile ul {
    list-style: none;
    margin: 0;
    padding: 0;
  }
  .c-plateformes .tile li {
    font-size: var(--text-base);
    padding: var(--space-2xs) 0;
    border-bottom: 1px solid var(--ink-border);
  }
  .c-plateformes .tile li:last-child {
    border-bottom: 0;
  }

  .c-plateformes .exit {
    margin: var(--space-3xl) auto 0;
    max-width: 62ch;
    text-align: center;
    font-size: var(--text-xl);
    font-weight: 700;
  }

/* source: styles/components/apropos.css */
section.c-apropos {
    padding: var(--space-section-lg) var(--space-2xl);
    background-image:
      linear-gradient(
        color-mix(in srgb, var(--color-bg) 93%, transparent),
        color-mix(in srgb, var(--color-bg) 96%, transparent)
      ),
      url(/assets/valeurs_background.dc0b8448.jpg);
    background-size: cover;
    background-position: center;
    border-top: 1px solid var(--color-divider);
  }
  .c-apropos .intro {
    max-width: 68ch;
  }
  .c-apropos .rule {
    margin: var(--space-xl) 0;
  }
  .c-apropos .lead {
    margin: 0;
    font-size: var(--text-xl);
    color: var(--color-neutral-800);
  }

  .c-apropos .team {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: var(--space-xs);
    margin-top: var(--space-4xl);
  }
  .c-apropos .person {
    background: var(--color-surface-raised);
    padding: var(--space-xl) var(--space-xl) var(--space-xl);
  }
  .c-apropos .person h3 {
    font-size: var(--text-2xl);
    margin: 0;
    text-transform: uppercase;
    letter-spacing: 0.02em;
  }
  .c-apropos .role {
    font-family: var(--font-heading);
    font-size: var(--text-sm);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--color-accent-700);
    margin-top: var(--space-2xs);
  }
  .c-apropos .person p {
    margin: var(--space-sm) 0 0;
    font-size: var(--text-base);
    color: var(--color-neutral-700);
  }

  .c-apropos .facts {
    margin: var(--space-3xl) 0 0;
    display: grid;
    gap: 0;
  }
  .c-apropos .facts dt {
    font-family: var(--font-heading);
    font-size: var(--text-md);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--color-accent-700);
    padding-top: var(--space-lg);
    border-top: 1px solid var(--color-divider);
  }
  .c-apropos .facts dd {
    margin: var(--space-xs) 0 var(--space-lg);
    font-size: var(--text-lg);
    max-width: 78ch;
  }

  .c-apropos .quote {
    margin: var(--space-2xl) 0 0;
    border-left: 5px solid var(--brand-cyan);
    padding-left: var(--space-xl);
  }
  .c-apropos .quote blockquote {
    margin: 0;
    font-family: var(--font-heading);
    font-size: var(--text-4xl);
    line-height: 1.25;
    max-width: 34em;
  }
  .c-apropos .quote figcaption {
    margin-top: var(--space-sm);
    font-size: var(--text-md);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    font-family: var(--font-heading);
    color: var(--color-neutral-700);
  }

/* source: styles/components/contact.css */
section.c-contact {
    background: var(--color-surface);
    border-top: 1px solid var(--color-divider);
  }
  .c-contact .inner {
    max-width: 940px;
    margin: 0 auto;
    padding: var(--space-section-lg) var(--space-2xl);
  }
  .c-contact .first {
    font-size: var(--text-xl);
    margin: 0 0 var(--space-sm);
    max-width: 72ch;
    margin-inline: auto;
  }
  .c-contact .lead {
    font-size: var(--text-lg);
    color: var(--color-neutral-700);
    margin: 0 0 var(--space-3xl);
    max-width: 72ch;
    margin-inline: auto;
  }

  .c-contact form {
    padding: var(--space-2xl);
    background: var(--color-bg);
    display: grid;
    gap: var(--space-lg);
  }
  .c-contact .row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: var(--space-lg);
  }
  .c-contact .field {
    display: grid;
    gap: var(--space-xs);
    font-family: var(--font-heading);
    font-size: var(--text-base);
    letter-spacing: 0.1em;
    text-transform: uppercase;
  }
  .c-contact .field em {
    font-style: normal;
    text-transform: lowercase;
    letter-spacing: 0.02em;
    opacity: 0.6;
  }
  .c-contact .req {
    color: var(--brand-blue);
  }
  .c-contact input,

  .c-contact textarea,

  .c-contact select {
    border-radius: 0;
    /* neutral-400 on white is 2.00:1 — under the 3:1 WCAG asks of a control
       border. --color-border-input is the hairline the rest of the system
       already uses, and clears it. */
    border: 1px solid var(--color-border-input);
    background: var(--color-surface-raised);
    padding: var(--space-sm) var(--space-sm);
    min-height: var(--tap-target-min);
    font-family: var(--font-body);
    font-size: var(--text-base);
    letter-spacing: normal;
    text-transform: none;
  }
  .c-contact textarea {
    resize: vertical;
  }
  .c-contact input:focus-visible,

  .c-contact textarea:focus-visible,

  .c-contact select:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
  }
  .c-contact .trap {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
  }

  .c-contact .consent {
    display: grid;
    grid-template-columns: var(--tap-target-min) 1fr;
    align-items: start;
    gap: var(--space-xs);
    font-family: var(--font-body);
    font-size: var(--text-md);
    line-height: 1.55;
    letter-spacing: normal;
    text-transform: none;
  }
  .c-contact .consent input {
    width: var(--space-lg);
    height: var(--space-lg);
    margin: var(--space-3xs) 0 0 var(--space-sm);
    /* was --color-primary, which is declared nowhere: the checkbox fell back
       to the browser's own accent instead of the brand's. */
    accent-color: var(--color-accent);
  }
  .c-contact .gdpr {
    margin: 0;
    font-size: var(--text-sm);
    line-height: 1.55;
    color: var(--color-neutral-700);
  }
  .c-contact .submit {
    display: flex;
    align-items: center;
    gap: var(--space-lg);
    flex-wrap: wrap;
  }
  .c-contact .or {
    font-size: var(--text-base);
  }
  /* inline in a sentence, so exempt from target-size rules — but it is a real
     contact route, and some of this audience never fills in a web form */
  .c-contact .or a {
    display: inline-flex;
    align-items: center;
    min-height: var(--tap-target-min);
  }

/* source: styles/components/jobs.css */
section.c-jobs {
    background: var(--brand-deep);
    color: var(--color-on-deep);
  }
  .c-jobs .inner {
    padding-top: var(--space-5xl);
    padding-bottom: var(--space-5xl);
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-4xl);
    align-items: start;
  }
  .c-jobs h2 {
    color: var(--color-on-deep);
  }
  .c-jobs .rule {
    margin: var(--space-lg) 0;
  }
  .c-jobs .left p {
    margin: 0;
    font-size: var(--text-lg);
    line-height: 1.6;
    color: var(--color-on-deep-strong);
  }

  .c-jobs .roles {
    list-style: none;
    margin: 0 0 var(--space-md);
    padding: 0;
    display: grid;
    gap: var(--space-xs);
  }
  .c-jobs .roles li {
    font-family: var(--font-heading);
    font-size: var(--text-2xl);
    text-transform: uppercase;
    letter-spacing: 0.02em;
    padding-bottom: var(--space-xs);
    border-bottom: 1px solid var(--color-on-deep-rule);
  }
  .c-jobs .meta {
    font-size: var(--text-md);
    color: var(--color-on-deep-muted);
    margin-bottom: var(--space-lg);
  }
  .c-jobs .right a.cta {
    color: var(--color-on-deep);
    border-color: var(--color-on-deep-rule-strong);
  }
  .c-jobs .right a.cta:hover {
    background: var(--color-on-deep-surface);
    color: var(--color-on-deep);
  }
  .c-jobs .spont {
    margin: var(--space-md) 0 0;
    font-size: var(--text-base);
    color: var(--color-on-deep-muted);
  }

  @media (max-width: 860px) {
    .c-jobs .inner {
      grid-template-columns: 1fr;
      gap: var(--space-2xl);
    }
  }

/* source: styles/components/footer.css */
footer.c-footer {
    background: var(--brand-deep);
    color: var(--color-on-deep);
    border-top: 1px solid var(--color-on-deep-rule-subtle);
  }
  .c-footer .cols {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: var(--space-3xl);
    padding-top: var(--space-5xl);
    padding-bottom: var(--space-2xl);
  }
  .c-footer img {
    height: var(--tap-target-min);
    width: auto;
  }
  .c-footer .desc {
    margin: var(--space-lg) 0 0;
    color: var(--color-on-deep-muted);
    max-width: 40ch;
    font-size: var(--text-base);
  }
  .c-footer h3 {
    font-size: var(--text-2xl);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    margin: 0;
    color: var(--color-on-deep);
  }
  .c-footer .rule {
    margin: var(--space-md) 0;
  }
  .c-footer p {
    margin: 0;
    color: var(--color-on-deep-muted);
  }
  /* 44px hit area per link; the gap is folded into the padding so the column
     does not grow taller than it did with an 8px gap. */
  .c-footer .links {
    display: grid;
    gap: 0;
  }
  .c-footer .links a,

  .c-footer p a {
    display: inline-flex;
    align-items: center;
    min-height: var(--tap-target-min);
  }
  footer.c-footer a {
    color: var(--color-on-deep-link);
  }
  .c-footer .links a {
    color: var(--color-on-deep-muted);
    font-size: var(--text-base);
  }
  footer.c-footer a:hover {
    color: var(--brand-cyan);
  }
  .c-footer .bottom {
    border-top: 1px solid var(--color-on-deep-rule-subtle);
    font-family: var(--font-heading);
    font-size: var(--text-sm);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--color-on-deep-subtle);
  }
  .c-footer .bottom .wrap {
    padding-top: var(--space-lg);
    padding-bottom: var(--space-lg);
  }

/* source: styles/components/sticky-cta.css */
.stickycta.c-sticky-cta {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 55;
    padding: var(--space-sm) var(--space-md)
      calc(var(--space-sm) + env(safe-area-inset-bottom));
    background: color-mix(in srgb, var(--color-bg) 96%, transparent);
    backdrop-filter: blur(6px);
    border-top: 1px solid var(--color-divider);
    transform: translateY(110%);
    transition: transform 0.28s ease;
  }
  .stickycta.c-sticky-cta.visible {
    transform: none;
  }
  @media (prefers-reduced-motion: reduce) {
    .stickycta.c-sticky-cta {
      transition: none;
    }
  }
  .stickycta.c-sticky-cta a {
    display: flex;
    width: 100%;
    justify-content: center;
    min-height: 48px;
    align-items: center;
  }
  /* desktop has the header CTA always in view — this would only be clutter */
  @media (min-width: 900px) {
    .stickycta.c-sticky-cta {
      display: none;
    }
  }

/* source: styles/legal.css */
/* The four legal pages (mentions-legales.html/legal-notice.html,
   confidentialite.html/privacy.html in the source project), ported into
   `templates/legal/notice.html.j2` (`.legal-page.legal-notice`) and
   `templates/legal/privacy.html.j2` (`.legal-page.legal-privacy`).

   Every rule below is scoped under `.legal-page` (shared) or one of the two
   per-document modifiers — never under the source's own bare selectors
   (`.wrap`, `.rule`, `h1`, `h2`, `p`, `a`, `:focus-visible`) unscoped. The
   task-16 brief warns that a class "audited globally was reported live
   when each of its four apparent users declared its own copy" — the
   opposite trap is the one that matters here: the source's inline
   `<style>` was the ONLY consumer of `.wrap`/`.rule` on those pages,
   because they loaded `foundation.css`, a generated snapshot never
   actually served alongside the rest of the site. This file IS served
   alongside the rest of the site (appended to the one `site.css` every
   page loads — a later task wires up the append), and `site.css` already
   declares `.wrap` (a 1240px, `--space-2xl`-padded container used by the
   header/hero/every section) and `.rule` (an unmargined 33×3 accent tick).
   Landing this file's `.wrap`/`.rule` unscoped would win the cascade on
   specificity and silently restyle the home page's header, hero and every
   section that centres a `.rule` under a heading — the exact "collision
   that silently restyles something in a different section" the brief
   names. `h1`/`h2`, `p`, `a` and `:focus-visible` collide the same way.

   The two source stylesheets are not identical. The list below is not a
   standing claim of completeness — a hand-maintained list of differences
   between two files in another repository cannot stay true across future
   edits to either file, and a reader has no way to tell from the list
   alone whether it still is. Treat it as a snapshot with a reproduction
   procedure instead:

   Derived by diffing the two source `<style>` blocks directly —
   `diff <(sed -n '/<style>/,/<\/style>/p' public/mentions-legales.html)
        <(sed -n '/<style>/,/<\/style>/p' public/confidentialite.html)`
   run from the source project's root — and re-reading every hunk to
   decide whether it is a real value difference or just reordering. To
   re-verify this list, or to check it after either source file changes,
   re-run that diff and re-read every hunk the same way; do not trust the
   list below without doing so.

   As of the last time that diff was run, it surfaced:
   - `header`'s `z-index` — privacy only (`.legal-privacy header`).
   - `header .wrap`'s `flex-wrap` — privacy only (`.legal-privacy header
     .wrap`).
   - `.back`'s `font-size` — privacy only (`.legal-privacy .back`); the
     legal notice's `.back` has no `font-size` at all and inherits
     `.legal-page`'s own `--text-xl`.
   - `.lede`'s `margin` — differs (`.legal-notice .lede` vs.
     `.legal-privacy .lede`).
   - `main`'s horizontal padding — differs (`.legal-notice main` vs.
     `.legal-privacy main`; both inert, see below).
   - `h2` — the legal notice's is plain; the privacy notice's additionally
     carries `letter-spacing`, `line-height`, a `border-top` divider and a
     `:first-of-type` reset (`.legal-notice h2` vs. `.legal-privacy h2`/
     `.legal-privacy h2:first-of-type`).
   - `.card`'s padding and margin — differ (`.legal-notice .card` vs.
     `.legal-privacy .card`).
   - `.card p:last-child` — privacy only (`confidentialite.html:169`;
     `.legal-privacy .card p:last-child`).
   - `.updated`, `ul`, `li`, `.authority`, `.todo` — privacy-only
     selectors; the legal notice's markup never contains these elements
     (and its own `templates/legal/notice.html.j2` never calls the
     `pending_fact` macro `.todo` depends on either), so scoping them to
     `.legal-privacy` costs nothing and there is no "both pages use this,
     but only one page's stylesheet declares it" case to reason about.
   Each of the above is kept under its own `.legal-notice`/`.legal-privacy`
   modifier rather than merged into one shared rule that would silently
   pick one page's value for the other, or — for the privacy-only ones —
   quietly apply a rule the other page's own source never had at all.

   This is a CSS-only artefact with no equivalent in the automated test
   suite: `tests/legal_rendering.rs` checks rendered HTML, not the
   stylesheet a later task appends this file to, so a wrong entry here
   would not fail a green `cargo test`. The diff-and-re-read procedure
   above is the actual verification, not the tests.

   One selector genuinely differs between the two source stylesheets and
   is still kept SHARED: `strong { font-weight: 700; }` is declared only
   by `confidentialite.html`'s `<style>`, not `mentions-legales.html`'s.
   Unlike the entries above, this is safe to share for a reason that does
   not depend on anything about this page or this codebase today, so it
   does not need re-checking the way the list above does: a browser's own
   default stylesheet already renders `<strong>` at `font-weight: bold`
   (CSS2.1 §18.2 / the HTML user-agent stylesheet), universally, so an
   explicit `font-weight: 700` rule can never change what a `<strong>`
   element looks like, on either document, in any browser, now or later.
   That is a permanent fact about `<strong>`'s own UA default, not a
   situational claim about this page's current layout staying
   conflict-free.

   Two rules from the source are deliberately NOT ported:
   - `* { box-sizing: border-box; }` — `site.css` already applies this
     universally (`*, *::before, *::after { box-sizing: border-box; }`).
   - `:focus-visible { outline: 2px solid var(--brand-blue); ... }` —
     identical in both source stylesheets, and `site.css`'s own global
     `:focus-visible` already outlines in `var(--color-accent)`, which the
     brand-override block retunes to the exact same hex LA2SOFT's brand
     blue is (`#344fea`). A `.legal-page`-scoped rule would resolve to a
     byte-identical colour — a duplicate, not an override.

   `.todo` IS ported, but conditionally applied — see
   `templates/legal/privacy.html.j2`'s `pending_fact` macro. The source
   used this class on its three hard-coded placeholder spans
   (`confidentialite.html:157,223,277,280`, e.g.
   `<span class="todo">[à compléter — …]</span>`) for exactly one job:
   making an unfilled fact visibly unfilled. The `‹N6 · …›` marker a
   `Pending::Blocking(None)` renders in development serves that same job,
   so wrapping it in the source's own styling is a faithful port, not an
   invention — but only while the marker is actually showing. A real,
   supplied value must never wear it: a published legal date inside amber
   "still a TODO" chrome would tell a reader the date is provisional when
   it is not, which is worse than either the plain value or the marker,
   because it looks deliberate rather than missing.
   `tests/legal_rendering.rs::a_supplied_legal_fact_never_carries_the_todo_styling`
   and `::an_absent_legal_fact_renders_its_marker_inside_the_todo_wrapper`
   pin both halves of that condition. */

.legal-page {
  /* The source's inline `<style>` set these on `body`, at a size and
     line-height distinct from `site.css`'s own body defaults
     (`--text-base`, 1.55) — a deliberately roomier measure for a
     long-form legal document, identical in both source stylesheets. Set
     on the wrapper, not `body` itself, so every other page keeps
     `site.css`'s own defaults. */
  font-size: var(--text-xl);
  line-height: 1.62;
}
.legal-page .wrap {
  max-width: 760px;
  margin: 0 auto;
  padding: 0 var(--space-xl);
}
.legal-page header {
  position: sticky;
  top: 0;
  background: color-mix(in srgb, var(--color-surface-raised) 94%, transparent);
  border-bottom: 1px solid var(--color-divider);
  backdrop-filter: blur(6px);
}
.legal-page header .wrap {
  display: flex;
  min-height: 72px;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
}
.legal-page header img {
  display: block;
  width: auto;
  height: 34px;
}
.legal-page .back {
  display: inline-flex;
  min-height: var(--tap-target-min);
  align-items: center;
  color: var(--brand-blue);
  font-family: var(--font-heading);
  font-weight: 600;
  letter-spacing: 0.07em;
  text-decoration: none;
  text-transform: uppercase;
}
.legal-page .back:hover {
  color: var(--brand-cyan);
}
.legal-page h1 {
  margin: 0 0 var(--space-sm);
  font-family: var(--font-heading);
  font-size: clamp(32px, 6vw, 46px);
  font-weight: 600;
  line-height: 1.05;
  text-transform: uppercase;
}
.legal-page .rule {
  width: 33px;
  height: 3px;
  margin: var(--space-xl) 0 var(--space-2xl);
  background: var(--brand-cyan);
}
.legal-page p {
  margin: 0 0 var(--space-md);
}
.legal-page a {
  color: var(--brand-blue);
}
.legal-page a:hover {
  color: var(--brand-cyan);
}
.legal-page strong {
  /* A no-op in every browser (`<strong>` is already bold) — ported anyway
     because `confidentialite.html`/`privacy.html` declare it and it costs
     nothing to keep both stylesheets' rules faithfully represented. */
  font-weight: 700;
}
.legal-page footer {
  background: var(--brand-deep);
  color: var(--color-on-deep-muted);
}
.legal-page footer .wrap {
  /* The two source stylesheets spell this differently
     (`padding-top`/`padding-bottom` separately in the legal notice,
     one `padding` shorthand in the privacy notice) but resolve to the
     same four values either way — `--space-2xl` vertical, and
     `--space-xl` horizontal from `.wrap` above in both cases — so this is
     safe to share. */
  padding: var(--space-2xl) var(--space-xl);
  font-size: var(--text-base);
}
.legal-page footer a {
  color: var(--color-on-deep-link);
}
@media (max-width: 600px) {
  .legal-page .wrap {
    /* Same reasoning as `footer .wrap` above: the legal notice only
       touches the horizontal sides at this breakpoint and the privacy
       notice writes the full shorthand, but both leave/set the vertical
       sides at 0, so one shared rule reproduces both. */
    padding: 0 var(--space-lg);
  }
  .legal-page header .wrap {
    min-height: 60px;
  }
  .legal-page header img {
    height: 30px;
  }
}

/* ── `templates/legal/notice.html.j2` only ──────────────────────────── */

.legal-notice .lede {
  margin: 0;
  color: var(--color-neutral-700);
  font-size: var(--text-2xl);
}
.legal-notice main {
  /* Ported faithfully, including the source's own dead vertical padding:
     `.wrap`'s two-value shorthand (declared above) sets padding-top and
     padding-bottom to 0 on every element carrying both classes
     (`<main class="wrap">`), and a class selector always beats this
     element selector regardless of source order — so `main.wrap`'s actual
     top/bottom padding comes from `.legal-page .wrap`, never from this
     rule; only its horizontal value could ever show, and `.wrap` sets
     that too. This rule is therefore fully inert in every browser, on
     both the legal notice and (see below) the privacy notice — the task-16
     report flags this as a defect discovered in the source project,
     reproduced rather than silently corrected. */
  padding: var(--space-section-sm) var(--space-xl) var(--space-5xl);
}
.legal-notice h2 {
  margin: var(--space-3xl) 0 var(--space-sm);
  font-family: var(--font-heading);
  font-size: var(--text-4xl);
  font-weight: 600;
  text-transform: uppercase;
}
.legal-notice .card {
  padding: var(--space-xl);
  border: 1px solid var(--color-divider);
  background: var(--color-surface-raised);
}
@media (max-width: 600px) {
  .legal-notice main {
    /* Inert — see the desktop rule's comment above. */
    padding-top: var(--space-3xl);
    padding-bottom: var(--space-5xl);
  }
}

/* ── `templates/legal/privacy.html.j2` only ─────────────────────────── */

.legal-privacy header {
  /* Privacy is the longer document type (up to ten `<h2>` sections vs. the
     legal notice's two), so its own stylesheet raises the sticky header
     above everything else on the page — the legal notice's stylesheet
     never sets this at all, leaving it at the initial `auto`. */
  z-index: 10;
}
.legal-privacy header .wrap {
  /* Same reasoning: only the privacy notice's stylesheet lets the bar wrap
     onto a second line rather than overflow if the viewport is narrow but
     not narrow enough to hit the 600px breakpoint below. The legal
     notice's stylesheet never sets this either. */
  flex-wrap: wrap;
}
.legal-privacy .back {
  /* Only the privacy notice's stylesheet sets this explicitly (16px); the
     legal notice's `.back` has no font-size rule at all and inherits
     `.legal-page`'s own `--text-xl` (17px) instead — a real, if small,
     difference between the two documents' back links that a shared rule
     would have erased. */
  font-size: var(--text-lg);
}

.legal-privacy .todo {
  /* Applied by `pending_fact` in `templates/legal/privacy.html.j2` only
     while a legal fact is still showing its `‹N6 · …›` marker — see this
     file's own top comment for why that condition matters. */
  padding: var(--space-3xs) var(--space-xs);
  background: var(--color-notice-surface);
  color: var(--color-on-notice);
  font-weight: 700;
}
.legal-privacy .updated {
  margin: 0 0 var(--space-xs);
  font-family: var(--font-heading);
  font-size: var(--text-base);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-neutral-700);
}
.legal-privacy .lede {
  margin: 0 0 var(--space-xs);
  color: var(--color-neutral-700);
  font-size: var(--text-2xl);
}
.legal-privacy main {
  /* Inert on every side — see `.legal-notice main`'s comment above; the
     privacy notice's own `.wrap` sets the same horizontal padding this
     rule tries to set to 0, and wins the same way. */
  padding: var(--space-section-sm) 0 var(--space-5xl);
}
.legal-privacy h2 {
  margin: var(--space-3xl) 0 var(--space-sm);
  padding-top: var(--space-xl);
  border-top: 1px solid var(--color-divider);
  font-family: var(--font-heading);
  font-size: var(--text-4xl);
  font-weight: 600;
  line-height: 1.15;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.legal-privacy h2:first-of-type {
  border-top: 0;
  padding-top: 0;
}
.legal-privacy ul {
  margin: 0 0 var(--space-md);
  padding-left: var(--space-lg);
}
.legal-privacy li {
  margin-bottom: var(--space-xs);
}
.legal-privacy .card {
  padding: var(--space-lg) var(--space-xl);
  margin: 0 0 var(--space-lg);
  border: 1px solid var(--color-divider);
  background: var(--color-surface-raised);
}
.legal-privacy .card p:last-child {
  margin-bottom: 0;
}
.legal-privacy .authority {
  padding: var(--space-lg) var(--space-xl);
  background: var(--color-surface);
}
.legal-privacy .authority p {
  margin: 0 0 var(--space-2xs);
}
@media (max-width: 600px) {
  .legal-privacy main {
    /* Inert — see the desktop rule's comment above. */
    padding: var(--space-3xl) 0 var(--space-5xl);
  }
}
