@layer reset, tokens, base, layout, components, pages, motion, utilities;

/* 00-tokens.css */
/* Direction « Calque » : Archivo et IBM Plex Mono, SIL Open Font License 1.1,
   auto-hébergées (font-src 'self'). Archivo est livrée en deux fichiers,
   instanciés depuis la police variable (tools/fonts/build-fonts.sh) :
   - titres : largeur 80 %, graisse 700, statique (12 Ko) ;
   - texte : largeur 100 %, graisses 400 à 700, variable (28 Ko).
   Les deux sont préchargées (partials/head.njk) : sans cela, la police du
   texte n'est découverte qu'après le CSS et retarde le premier rendu.
   Une demande de largeur 85 ou 90 % se résout sur le fichier titres (80 %).
   Licences servies dans /licences/OFL-*.txt. */
@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 700;
  font-stretch: 80%;
  font-display: swap;
  src: url("/fonts/archivo-titre-700.c675bba2e7.woff2") format("woff2");
  unicode-range: U+0020-007E, U+00A0-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+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 400 700;
  font-stretch: 100%;
  font-display: swap;
  src: url("/fonts/archivo-texte-var.6135d20816.woff2") format("woff2");
  unicode-range: U+0020-007E, U+00A0-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+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/ibm-plex-mono-400.a976d292de.woff2") format("woff2");
  unicode-range: U+0020-007E, U+00A0-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+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/fonts/ibm-plex-mono-500.abfe1adf54.woff2") format("woff2");
  unicode-range: U+0020-007E, U+00A0-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+2212, U+2215, U+FEFF, U+FFFD;
}

/* Polices de repli ajustées : Arial (ou Liberation Sans / Arimo, métriquement
   identiques) redimensionnée pour occuper la même largeur qu'Archivo sur le
   texte réel du site (paragraphes pour le texte, h1/h2 pour les titres,
   instance largeur 80 / graisse 700), avec les mêmes hauteurs de ligne. Le
   texte provisoire casse donc aux mêmes endroits pendant le chargement
   (font-display: swap) : pas de décalage de mise en page. Valeurs calculées
   avec fontTools sur dist/ ; les recalculer si les polices changent. */
@font-face {
  font-family: "Archivo Fallback";
  font-style: normal;
  font-weight: 400 500;
  src: local("Arial"), local("ArialMT"), local("Liberation Sans"), local("LiberationSans-Regular"), local("Arimo");
  size-adjust: 97.83%;
  ascent-override: 89.75%;
  descent-override: 21.47%;
  line-gap-override: 0%;
}

@font-face {
  font-family: "Archivo Fallback";
  font-style: normal;
  font-weight: 600 700;
  src: local("Arial Bold"), local("Arial-BoldMT"), local("Liberation Sans Bold"), local("LiberationSans-Bold"), local("Arimo Bold");
  size-adjust: 94.45%;
  ascent-override: 92.95%;
  descent-override: 22.23%;
  line-gap-override: 0%;
}

@font-face {
  font-family: "Archivo Titre Fallback";
  font-style: normal;
  font-weight: 600 700;
  src: local("Arial Bold"), local("Arial-BoldMT"), local("Liberation Sans Bold"), local("LiberationSans-Bold"), local("Arimo Bold");
  size-adjust: 81.73%;
  ascent-override: 107.43%;
  descent-override: 25.7%;
  line-gap-override: 0%;
}

/* Plex Mono et Liberation Mono / Courier New ont la même chasse (0,6 em) :
   seules les hauteurs sont alignées. */
@font-face {
  font-family: "Plex Mono Fallback";
  font-style: normal;
  font-weight: 400 500;
  src: local("Courier New"), local("CourierNewPSMT"), local("Liberation Mono"), local("LiberationMono-Regular"), local("Cousine");
  size-adjust: 100%;
  ascent-override: 102.5%;
  descent-override: 27.5%;
  line-gap-override: 0%;
}

@layer tokens {
  :root {
    /* Palette officielle Échelon Noroît (valeurs inchangées). */
    --papier: #e8e6df;
    --nuit: #0f161b;
    --ardoise: #1b252c;
    --trait: #3a4a55;
    --brume: #8a96a0;
    --texte-nuit: #d3d9dc;
    --signal: #c97b2e;
    --perte: #9e3b39;

    /* Tricolore : filet horizontal uniquement. */
    --fr-bleu: #274371;
    --fr-blanc: #cfcec6;
    --fr-rouge: #9e2f36;

    /* Rôles de la direction « Calque ». Chaque rôle coloré a une variante par
       fond quand la teinte officielle n'y atteint pas le contraste AA
       (mesures : docs/ARCHITECTURE.md, « Couleurs »). */
    --fond-papier: var(--papier);
    --fond-papier-2: #dedbd2;          /* papier ombré : second plan, bandes */
    --fond-nuit: var(--nuit);
    --surface-nuit: var(--ardoise);
    --encre: var(--nuit);              /* 14,6:1 sur papier */
    --encre-douce: var(--trait);       /* 7,3:1 sur papier */
    --ami: var(--fr-bleu);             /* 7,9:1 sur papier */
    --ami-nuit: #8ea6c9;               /* 7,3:1 sur nuit (--ami : 1,9:1) */
    --ennemi: var(--perte);            /* 5,4:1 sur papier */
    --ennemi-nuit: #d9706b;            /* 5,6:1 sur nuit (--ennemi : 2,7:1) */
    --action: var(--signal);           /* aplat des CTA, texte encre 5,5:1 ; jamais du texte sur papier (2,6:1) */
    --action-hover: #dd8f3f;
    --action-nuit: var(--signal);      /* texte orange sur nuit : 5,5:1 */
    --genie: #d2443c;                  /* tracés, filets, symboles : 4,0:1 sur nuit, jamais du texte courant */
    --carroyage: color-mix(in srgb, var(--trait) 35%, transparent);

    /* Espacements : base 4 px. */
    --s-1: .25rem;   /* 4 */
    --s-2: .5rem;    /* 8 */
    --s-3: .75rem;   /* 12 */
    --s-4: 1rem;     /* 16 */
    --s-5: 1.5rem;   /* 24 */
    --s-6: 2rem;     /* 32 */
    --s-7: 3rem;     /* 48 */
    --s-8: 4rem;     /* 64 */
    --s-9: 6rem;     /* 96 */
    --s-10: 8rem;    /* 128 */
    --s-11: 12rem;   /* 192 */
    --section-y: clamp(56px, 10vw, 160px);

    /* Grille : 4 colonnes, 8 dès 768 px, 12 dès 1024 px. */
    --container: 1360px;
    --gutter: clamp(1rem, 4vw, 3rem);
    --cols: 4;
    --gap: 16px;
    --measure: 68ch;
    --header-height: 60px;

    /* Typographie. */
    --font: "Archivo", "Archivo Fallback", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    --font-titre: "Archivo", "Archivo Titre Fallback", "Arial Narrow", Arial, sans-serif;
    --mono: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, "Courier New", monospace;
    --t-h1: clamp(2.5rem, 6vw, 5.5rem);
    --t-h2: clamp(1.75rem, 3.5vw, 3rem);
    --t-h3: 1.25rem;
    --t-texte: clamp(1.0625rem, .35vw + 1rem, 1.125rem);
    --t-petit: .9375rem;
    --t-label: .8125rem;
    --t-data: .8125rem;
    --stretch-titre: 80%;

    /* Géométrie : ni rayon ni ombre. */
    --radius: 0;
    --radius-fn: 2px;
    --bord: 1px;
    --bord-actif: 2px;

    /* Mouvement. */
    --d-retour: 120ms;
    --d-ui: 240ms;
    --d-recit: 1000ms;
    --ease: cubic-bezier(.2, .7, .2, 1);
  }

  @media (min-width: 768px) {
    :root {
      --cols: 8;
      --gap: 20px;
      --header-height: 64px;
    }
  }

  @media (min-width: 1024px) {
    :root {
      --cols: 12;
      --gap: 24px;
      --header-height: 68px;
    }
  }

  /* Rôles de surface : chaque composant lit --fg, --fg-2, --ligne, --c-ami…
     et s'adapte au fond sur lequel il est posé. */
  :root,
  .surface-papier,
  .surface-papier-2 {
    --fond: var(--fond-papier);
    --fg: var(--encre);
    --fg-2: var(--encre-douce);
    --ligne: color-mix(in srgb, var(--trait) 45%, transparent);
    --ligne-forte: var(--encre);
    --c-ami: var(--ami);
    --c-ami-fond: color-mix(in srgb, var(--ami) 14%, var(--fond-papier));
    --c-ennemi: var(--ennemi);
    --c-ennemi-fond: color-mix(in srgb, var(--ennemi) 14%, var(--fond-papier));
    --c-focus: var(--encre);
    --c-carroyage: var(--carroyage);
  }

  .surface-papier-2 {
    --fond: var(--fond-papier-2);
  }

  .surface-nuit {
    --fond: var(--fond-nuit);
    --fg: var(--texte-nuit);
    --fg-2: var(--brume);
    --ligne: color-mix(in srgb, var(--brume) 32%, transparent);
    --ligne-forte: var(--texte-nuit);
    --c-ami: var(--ami-nuit);
    --c-ami-fond: color-mix(in srgb, var(--ami-nuit) 16%, var(--fond-nuit));
    --c-ennemi: var(--ennemi-nuit);
    --c-ennemi-fond: color-mix(in srgb, var(--ennemi-nuit) 16%, var(--fond-nuit));
    --c-focus: var(--papier);
    --c-carroyage: color-mix(in srgb, var(--brume) 14%, transparent);
  }
}

/* 10-base.css */
@layer reset {
  *,
  *::before,
  *::after {
    box-sizing: border-box;
  }

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

  img {
    height: auto;
  }

  a {
    color: inherit;
  }

  button {
    color: inherit;
    font: inherit;
  }

  h1,
  h2,
  h3,
  h4,
  p,
  ul,
  ol,
  dl,
  dd,
  figure,
  blockquote {
    margin: 0;
  }
}

@layer base {
  /* Une seule compensation du header collant pour toutes les ancres (y compris
     le lien d'évitement) : scroll-padding sur la racine. Ne pas y ajouter de
     scroll-margin sur les cibles, les deux se cumuleraient. */
  html {
    scroll-behavior: smooth;
    scroll-padding-top: calc(var(--header-height) + var(--s-4));
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
  }

  body {
    margin: 0;
    background: var(--fond-papier);
    color: var(--encre);
    font-family: var(--font);
    font-size: var(--t-texte);
    line-height: 1.6;
    font-synthesis: none;
    text-rendering: optimizeLegibility;
  }

  .surface-papier,
  .surface-papier-2,
  .surface-nuit {
    background: var(--fond);
    color: var(--fg);
  }

  h1,
  h2,
  h3 {
    font-family: var(--font-titre);
    font-weight: 700;
    line-height: 1.02;
    letter-spacing: -.01em;
    text-wrap: balance;
  }

  h1 {
    font-size: var(--t-h1);
    font-stretch: var(--stretch-titre);
  }

  h2 {
    font-size: var(--t-h2);
    font-stretch: var(--stretch-titre);
  }

  h3 {
    font-family: var(--font);
    font-size: var(--t-h3);
    font-weight: 600;
    line-height: 1.25;
    letter-spacing: 0;
  }

  p,
  li,
  dd {
    text-wrap: pretty;
  }

  strong {
    font-weight: 650;
  }

  code,
  kbd,
  time {
    font-family: var(--mono);
  }

  a {
    text-decoration-thickness: 1px;
    text-underline-offset: .22em;
  }

  a:hover {
    text-decoration-thickness: 2px;
  }

  ::selection {
    background: var(--encre);
    color: var(--papier);
  }

  .surface-nuit ::selection {
    background: var(--papier);
    color: var(--encre);
  }

  .skip-link {
    position: fixed;
    z-index: 1000;
    top: var(--s-4);
    left: var(--s-4);
    padding: var(--s-3) var(--s-4);
    border: var(--bord-actif) solid var(--encre);
    background: var(--papier);
    color: var(--encre);
    font-weight: 600;
    translate: 0 calc(-100% - var(--s-6));
  }

  .skip-link:focus {
    translate: none;
  }

  :focus-visible {
    outline: 3px solid var(--c-focus, var(--encre));
    outline-offset: 3px;
  }

  /* Symboles SVG partagés (partials/symbols.svg) : jamais rendus tels quels. */
  .svg-defs {
    position: absolute;
    width: 0;
    height: 0;
    overflow: hidden;
  }
}

/* 20-layout.css */
@layer layout {
  .container {
    width: min(var(--container), calc(100% - 2 * var(--gutter)));
    margin-inline: auto;
  }

  /* Grille de mise en page : 4 / 8 / 12 colonnes (voir --cols). Les enfants
     se placent avec les utilitaires .col-* (90-utilities.css) ou les règles de
     leur composant. */
  .grid {
    display: grid;
    grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
    column-gap: var(--gap);
  }

  .section {
    position: relative;
    padding-block: var(--section-y);
  }

  .section--serre {
    padding-block: calc(var(--section-y) * .6);
  }

  /* Carroyage : filets verticaux calés sur les colonnes du .container et
     filets horizontaux tous les 96 px. Posé en fond d'une section
     (.carroyage), il matérialise la grille de mise en page, comme le
     quadrillage d'une carte. Les pourcentages du dégradé se rapportent à la
     largeur du pseudo-élément, qui est exactement celle du conteneur. */
  .carroyage {
    position: relative;
    isolation: isolate;
  }

  .carroyage::before {
    position: absolute;
    z-index: -1;
    inset-block: 0;
    inset-inline: max(var(--gutter), calc((100% - var(--container)) / 2));
    border-inline-end: var(--bord) solid var(--c-carroyage);
    background:
      repeating-linear-gradient(90deg, var(--c-carroyage) 0 1px, transparent 1px calc((100% + var(--gap)) / var(--cols))),
      repeating-linear-gradient(180deg, var(--c-carroyage) 0 1px, transparent 1px 96px);
    content: "";
    pointer-events: none;
  }

  .editorial-shell {
    padding-bottom: var(--section-y);
  }

  .measure {
    max-width: var(--measure);
  }
}

/* 30-components.css */
@layer components {
  /* ------------------------------------------------------------------
     Textes d'appoint
     ------------------------------------------------------------------ */
  .label {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    margin-bottom: var(--s-4);
    color: var(--fg-2);
    font-size: var(--t-label);
    font-weight: 500;
    letter-spacing: .08em;
    line-height: 1.3;
    text-transform: uppercase;
  }

  /* Filet d'amorce : neutre, rouge côté ennemi, écarlate côté Génie. */
  .label::before {
    flex: none;
    width: var(--s-5);
    height: var(--bord-actif);
    background: var(--fg);
    content: "";
  }

  .label--ennemi::before {
    background: var(--c-ennemi);
  }

  .label--genie::before {
    background: var(--genie);
  }

  .lead {
    font-size: clamp(1.125rem, .5vw + 1rem, 1.3125rem);
    line-height: 1.5;
  }

  .lien-fleche {
    font-weight: 600;
  }

  .lien-fleche::after {
    margin-inline-start: .35em;
    content: "→" / "";
  }

  .filet {
    display: block;
    width: 72px;
    height: 3px;
    background: linear-gradient(90deg, var(--fr-bleu) 0 33.33%, var(--fr-blanc) 0 66.66%, var(--fr-rouge) 0);
  }

  /* ------------------------------------------------------------------
     Boutons : un seul orange par vue (le parcours « jouer »).
     ------------------------------------------------------------------ */
  .button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--s-2);
    min-height: 48px;
    padding: 0 var(--s-5);
    border: var(--bord) solid var(--fg);
    border-radius: var(--radius);
    background: transparent;
    color: var(--fg);
    font-size: 1rem;
    font-weight: 600;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--d-ui) var(--ease), color var(--d-ui) var(--ease);
  }

  .button:hover {
    background: var(--fg);
    color: var(--fond);
  }

  /* Aplat orange, texte et filet encre sur tous les fonds : 5,5:1. */
  .button--action {
    border-color: var(--encre);
    background: var(--action);
    color: var(--encre);
  }

  .button--action:hover {
    background: var(--action-hover);
    color: var(--encre);
  }

  .button--secondaire-nuit {
    border-color: var(--texte-nuit);
    color: var(--texte-nuit);
  }

  /* ------------------------------------------------------------------
     server-callsign + copy-button
     ------------------------------------------------------------------ */
  .callsign {
    display: inline-flex;
    align-items: stretch;
    max-width: 100%;
    min-height: 48px;
    border: var(--bord) solid var(--fg);
    background: var(--fond);
  }

  .callsign__label {
    display: flex;
    align-items: center;
    padding: 0 var(--s-3);
    border-inline-end: var(--bord) solid var(--ligne);
    color: var(--fg-2);
    font-family: var(--mono);
    font-size: .75rem;
    letter-spacing: .04em;
    text-transform: uppercase;
    white-space: nowrap;
  }

  .callsign__nom {
    display: flex;
    align-items: center;
    padding: 0 var(--s-3);
    font-family: var(--mono);
    font-size: .9375rem;
    font-weight: 500;
    white-space: nowrap;
    user-select: all;
  }

  .copy-button {
    display: inline-flex;
    align-items: center;
    min-width: 44px;
    padding: 0 var(--s-3);
    border: 0;
    border-inline-start: var(--bord) solid var(--fg);
    background: transparent;
    color: var(--fg);
    font-size: .875rem;
    font-weight: 600;
    cursor: pointer;
    transition: background-color var(--d-retour) var(--ease), color var(--d-retour) var(--ease);
  }

  .copy-button[hidden] {
    display: none;
  }

  .copy-button:hover,
  .copy-button.is-copie {
    background: var(--fg);
    color: var(--fond);
  }

  .copy-button:focus-visible {
    outline-offset: -3px;
  }

  .callsign--compact {
    min-height: 36px;
  }

  .callsign--compact .callsign__nom {
    font-size: .8125rem;
  }

  .callsign--compact .copy-button {
    font-size: .8125rem;
  }

  /* ------------------------------------------------------------------
     status-badge : texte + forme + couleur (jamais la couleur seule).
     Le texte reste à la couleur du fond (--fg) ; seule la pastille porte
     la teinte, sa forme suffit à distinguer les statuts.
     ------------------------------------------------------------------ */
  .status {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    padding: 1px var(--s-2);
    border: var(--bord) solid var(--ligne);
    color: var(--fg);
    font-family: var(--mono);
    font-size: .75rem;
    font-weight: 500;
    line-height: 1.6;
    white-space: nowrap;
    vertical-align: middle;
  }

  .status__forme {
    flex: none;
    width: 10px;
    height: 10px;
    border: 1.5px solid;
  }

  .status--published .status__forme {
    border-color: var(--fg);
    background: var(--fg);
  }

  .status--developed .status__forme {
    border-color: var(--c-ami);
  }

  .status--validation .status__forme {
    border-color: var(--action);
    background: linear-gradient(90deg, var(--action) 0 50%, transparent 0);
  }

  .status--preparation .status__forme {
    border-style: dashed;
    border-color: var(--fg-2);
    border-radius: 50%;
  }

  /* ------------------------------------------------------------------
     dtg + log-entry (main courante)
     ------------------------------------------------------------------ */
  .dtg {
    font-family: var(--mono);
    font-size: var(--t-data);
    font-weight: 500;
    letter-spacing: .02em;
    white-space: nowrap;
  }

  .category {
    color: var(--fg-2);
    font-family: var(--mono);
    font-size: .75rem;
    letter-spacing: .04em;
    text-transform: uppercase;
  }

  .log {
    margin: 0;
    padding: 0;
    border-inline-start: var(--bord) solid var(--ligne);
    list-style: none;
  }

  .log-entry {
    position: relative;
    display: grid;
    gap: var(--s-1);
    padding: var(--s-4) 0 var(--s-4) var(--s-5);
    border-bottom: var(--bord) solid var(--ligne);
  }

  .log-entry::before {
    position: absolute;
    top: 1.55rem;
    left: 0;
    width: var(--s-3);
    height: var(--bord);
    background: var(--fg-2);
    content: "";
  }

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

  .log-entry__titre {
    font-family: var(--font);
    font-size: 1.125rem;
    font-weight: 600;
    line-height: 1.3;
  }

  .log-entry__titre a {
    text-decoration: none;
  }

  .log-entry__titre a:hover {
    text-decoration: underline;
  }

  .log-entry__texte {
    color: var(--fg-2);
    font-size: var(--t-petit);
    line-height: 1.55;
  }

  /* Marque posée par main.js sur les entrées postérieures à la dernière
     visite (date gardée dans ce navigateur seulement). */
  .nouveau {
    padding: 0 var(--s-2);
    border: var(--bord) solid currentColor;
    color: var(--c-releve, var(--fg));
    font-family: var(--mono);
    font-size: .75rem;
    font-weight: 500;
  }

  .surface-nuit .nouveau {
    --c-releve: var(--action-nuit);
  }

  /* ------------------------------------------------------------------
     Symboles et tracés SVG (tactical-symbol, front-line, maneuver-arrow,
     tactical-map, schémas). Les couleurs viennent de la surface.
     ------------------------------------------------------------------ */
  .sym__cadre {
    fill: var(--c-ami-fond);
    stroke: var(--c-ami);
    stroke-width: 2.5;
  }

  .sym--ennemi .sym__cadre {
    fill: var(--c-ennemi-fond);
    stroke: var(--c-ennemi);
  }

  .sym__trait {
    fill: none;
    stroke: var(--c-ami);
    stroke-width: 2.5;
  }

  .sym__echelon {
    fill: none;
    stroke: var(--c-ami);
    stroke-width: 1.8;
  }

  .sym--ennemi .sym__echelon {
    stroke: var(--c-ennemi);
  }

  .sym__echelon--plein,
  .sym__echelon--plein circle {
    fill: var(--c-ami);
    stroke: none;
  }

  .front {
    fill: none;
    stroke: var(--fg);
    stroke-linecap: round;
    stroke-linejoin: round;
    stroke-width: 4;
  }

  .front--precedent {
    stroke: var(--fg-2);
    stroke-dasharray: 3 6;
    stroke-width: 1.5;
  }

  .fleche {
    fill: none;
    stroke-linecap: round;
    stroke-width: 3.5;
  }

  .fleche--ennemi {
    stroke: var(--c-ennemi);
  }

  .fleche--ami {
    stroke: var(--c-ami);
  }

  .fleche--principal {
    stroke-width: 5;
  }

  .fleche--reco {
    stroke-dasharray: 2 7;
    stroke-width: 2.5;
  }

  .fleche--tir {
    stroke-dasharray: 12 7;
    stroke-width: 2;
  }

  .pointe--ennemi {
    fill: var(--c-ennemi);
  }

  .pointe--ami {
    fill: var(--c-ami);
  }

  .obj circle {
    fill: none;
    stroke: var(--fg);
    stroke-dasharray: 5 5;
    stroke-width: 2;
  }

  .secteur path {
    fill: transparent;
    stroke: var(--fg-2);
    stroke-dasharray: 2 5;
    stroke-width: 1.25;
    transition: fill var(--d-ui) var(--ease);
  }

  .secteur:hover path {
    fill: color-mix(in srgb, var(--fg) 5%, transparent);
  }

  .secteur-trait {
    fill: none;
    stroke: var(--fg-2);
    stroke-dasharray: 2 4;
    stroke-width: 1.5;
  }

  .limite {
    fill: none;
    stroke: var(--fg-2);
    stroke-dasharray: 14 6 2 6;
    stroke-width: 1.25;
  }

  .position-tenue circle {
    fill: color-mix(in srgb, var(--c-ami) 6%, transparent);
    stroke: var(--c-ami);
    stroke-dasharray: 6 5;
    stroke-width: 1.5;
  }

  /* Annotations : mono, capitales, halo couleur du fond pour rester lisibles
     au-dessus des courbes de niveau. */
  .map-note {
    fill: var(--fg-2);
    font-family: var(--mono);
    font-size: 17px;
    font-weight: 500;
    letter-spacing: .06em;
    paint-order: stroke;
    stroke: var(--fond);
    stroke-linejoin: round;
    stroke-width: 5px;
    text-transform: uppercase;
  }

  .map-note--front {
    fill: var(--fg);
  }

  .map-note--ennemi {
    fill: var(--c-ennemi);
  }

  .repere-num circle {
    fill: var(--fond);
    stroke: var(--c-ennemi);
    stroke-width: 2;
  }

  .repere-num text {
    fill: var(--c-ennemi);
    font-family: var(--mono);
    font-size: 15px;
    font-weight: 500;
  }

  /* ------------------------------------------------------------------
     tactical-map + schémas
     ------------------------------------------------------------------ */
  .tactical-map {
    margin: 0;
  }

  .tactical-map__canvas,
  .schema__canvas,
  .timeline-state__carte {
    position: relative;
    overflow: hidden;
  }

  .tactical-map__fond,
  .tactical-map__calque {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
  }

  .tactical-map__fond {
    object-fit: cover;
    object-position: right center;
  }

  .provenance {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    color: var(--fg);
    font-family: var(--mono);
    font-size: .75rem;
    line-height: 1.4;
  }

  .provenance__marque {
    flex: none;
    width: 10px;
    height: 10px;
    border: 1.5px dashed var(--fg);
  }

  .legende {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-1) var(--s-4);
    margin: var(--s-2) 0 0;
    padding: 0;
    color: var(--fg-2);
    font-family: var(--mono);
    font-size: .75rem;
    list-style: none;
  }

  .legende li {
    display: inline-flex;
    align-items: center;
    gap: var(--s-3);
  }

  .legende__symbole {
    width: 26px;
    height: 18px;
    overflow: visible;
  }

  .schema {
    margin: 0;
  }

  .schema__canvas {
    aspect-ratio: 8 / 5;
    border: var(--bord) solid var(--ligne-forte);
    background: var(--fond);
  }

  .schema__canvas img,
  .schema__canvas svg,
  .timeline-state__carte img,
  .timeline-state__carte svg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  .schema__legende {
    margin-top: var(--s-3);
    color: var(--fg-2);
    font-size: .875rem;
  }

  .schema-mention {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    margin-inline-end: var(--s-2);
    padding: 1px var(--s-2);
    border: var(--bord) dashed var(--fg);
    color: var(--fg);
    font-family: var(--mono);
    font-size: .75rem;
    font-weight: 500;
    letter-spacing: .04em;
    text-transform: uppercase;
  }

  .schema-mention--bloc {
    display: block;
    width: fit-content;
    max-width: 100%;
    margin: 0 0 var(--s-5);
    text-transform: none;
  }

  .schema-mention--bloc span {
    color: var(--fg-2);
    font-weight: 400;
  }

  /* ------------------------------------------------------------------
     timeline-state
     ------------------------------------------------------------------ */
  .timeline-state__defile:focus-visible {
    outline-offset: 6px;
  }

  /* Le conteneur focalisable est aussi celui qui défile (clavier). */
  .timeline-state__defile {
    padding-bottom: var(--s-4);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
  }

  .timeline-state {
    display: grid;
    grid-auto-columns: minmax(260px, 84%);
    grid-auto-flow: column;
    gap: var(--gap);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .timeline-state__etat {
    scroll-snap-align: start;
  }

  .timeline-state figure {
    margin: 0;
  }

  .timeline-state__carte {
    aspect-ratio: 400 / 260;
    border: var(--bord) solid var(--ligne-forte);
    background: var(--fond-papier);
  }

  .timeline-state__repere {
    position: absolute;
    top: var(--s-2);
    left: var(--s-2);
    padding: 0 var(--s-2);
    background: var(--encre);
    color: var(--papier);
    font-family: var(--mono);
    font-size: .75rem;
    font-weight: 500;
  }

  .timeline-state figcaption {
    padding-top: var(--s-4);
  }

  .timeline-state h3 {
    font-size: 1.125rem;
  }

  .timeline-state__temps {
    display: block;
    margin-bottom: var(--s-1);
    color: var(--fg-2);
    font-family: var(--mono);
    font-size: .75rem;
    font-weight: 500;
    letter-spacing: .04em;
    text-transform: uppercase;
  }

  .timeline-state p {
    margin-top: var(--s-2);
    color: var(--fg-2);
    font-size: var(--t-petit);
  }

  @media (min-width: 768px) {
    .timeline-state {
      grid-auto-columns: minmax(280px, 46%);
    }
  }

  @media (min-width: 1024px) {
    .timeline-state__defile {
      padding-bottom: 0;
      overflow: visible;
    }

    .timeline-state {
      grid-auto-flow: row;
      grid-template-columns: repeat(3, minmax(0, 1fr));
    }

    /* Liaison entre deux temps : un trait dans la gouttière, à mi-hauteur
       de la carte (ratio 400 / 260). */
    .timeline-state__etat {
      position: relative;
    }

    .timeline-state__etat + .timeline-state__etat::before {
      position: absolute;
      top: 0;
      left: calc(-1 * var(--gap));
      width: var(--gap);
      height: 2px;
      margin-top: 32.5%;
      background: var(--fg);
      content: "";
    }
  }

  /* ------------------------------------------------------------------
     sector-sheet
     ------------------------------------------------------------------ */
  .sector-sheet {
    padding-top: var(--s-4);
    border-top: var(--bord-actif) solid var(--fg);
  }

  .sector-sheet__ref {
    color: var(--fg-2);
    font-family: var(--mono);
    font-size: .75rem;
    letter-spacing: .06em;
    text-transform: uppercase;
  }

  .sector-sheet__titre {
    margin-top: var(--s-2);
    font-family: var(--font-titre);
    font-size: clamp(1.375rem, 1.2vw + 1rem, 1.75rem);
    font-stretch: var(--stretch-titre);
    font-weight: 700;
  }

  .sector-sheet__corps {
    margin-top: var(--s-3);
  }

  /* ------------------------------------------------------------------
     join-order
     ------------------------------------------------------------------ */
  .join-order {
    display: grid;
    gap: 0;
    margin: 0;
    padding: 0;
    border-top: var(--bord) solid var(--fg);
    list-style: none;
  }

  .join-order__etape {
    display: grid;
    align-content: start;
    gap: var(--s-2);
    padding: var(--s-4) 0;
    border-bottom: var(--bord) solid var(--ligne);
  }

  .join-order__etape h3 {
    font-family: var(--font-titre);
    font-size: 1.5rem;
    font-stretch: var(--stretch-titre);
    font-weight: 700;
  }

  .join-order__num {
    display: block;
    margin-bottom: var(--s-2);
    color: var(--fg-2);
    font-family: var(--mono);
    font-size: .875rem;
    font-weight: 500;
    font-stretch: 100%;
  }

  .join-order__etape p {
    font-size: var(--t-petit);
  }

  .join-order__aide {
    color: var(--fg-2);
  }

  .join-order__lien a {
    font-weight: 600;
  }

  .join-order__lien a::after {
    margin-inline-start: .35em;
    content: "→" / "";
  }

  .join-order__lien a[target]::after {
    content: none;
  }

  .join-order .callsign {
    justify-self: start;
  }

  /* Le titre de l'étape (« Indicatif ») nomme déjà le bloc. */
  .join-order .callsign__label {
    display: none;
  }

  @media (min-width: 768px) {
    .join-order {
      grid-template-columns: repeat(2, minmax(0, 1fr));
      column-gap: var(--gap);
    }
  }

  @media (min-width: 1280px) {
    .join-order {
      grid-template-columns: repeat(4, minmax(0, 1fr));
      border-bottom: var(--bord) solid var(--fg);
    }

    .join-order__etape {
      padding: var(--s-5) var(--s-5) var(--s-6) 0;
      border-bottom: 0;
    }

    .join-order__etape + .join-order__etape {
      padding-inline-start: var(--s-5);
      border-inline-start: var(--bord) solid var(--ligne);
    }
  }

  /* ------------------------------------------------------------------
     operation-strip
     ------------------------------------------------------------------ */
  .operation-strip {
    padding-block: var(--s-8);
    border-top: var(--bord) solid var(--ligne);
  }

  .operation-strip__inner {
    display: grid;
    gap: var(--s-4) var(--gap);
  }

  .operation-strip__label {
    color: var(--fg-2);
    font-family: var(--mono);
    font-size: .75rem;
    letter-spacing: .06em;
    text-transform: uppercase;
  }

  .operation-strip h2 {
    font-size: clamp(1.625rem, 2.6vw, 2.5rem);
  }

  .operation-strip__corps p {
    max-width: 56ch;
    margin-top: var(--s-3);
    color: var(--fg-2);
  }

  @media (min-width: 1024px) {
    .operation-strip__inner {
      grid-template-columns: repeat(12, minmax(0, 1fr));
      align-items: end;
    }

    .operation-strip__label {
      grid-column: 1 / 4;
      align-self: start;
      padding-top: .6rem;
    }

    .operation-strip__corps {
      grid-column: 4 / 10;
    }

    .operation-strip__actions {
      grid-column: 10 / 13;
      justify-self: end;
    }
  }

  /* ------------------------------------------------------------------
     FAQ
     ------------------------------------------------------------------ */
  .faq-grid {
    display: grid;
    gap: var(--s-6) var(--gap);
  }

  .faq-list {
    border-top: var(--bord) solid var(--fg);
  }

  .faq-list details {
    border-bottom: var(--bord) solid var(--ligne);
  }

  .faq-list summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-4);
    min-height: 48px;
    padding: var(--s-4) 0;
    font-size: 1.0625rem;
    font-weight: 600;
    line-height: 1.35;
    list-style: none;
    cursor: pointer;
  }

  .faq-list summary::-webkit-details-marker {
    display: none;
  }

  .faq-signe {
    position: relative;
    flex: none;
    width: 14px;
    height: 14px;
  }

  .faq-signe::before,
  .faq-signe::after {
    position: absolute;
    top: 6px;
    left: 0;
    width: 14px;
    height: 2px;
    background: currentColor;
    content: "";
    transition: transform var(--d-ui) var(--ease);
  }

  .faq-signe::after {
    transform: rotate(90deg);
  }

  details[open] .faq-signe::after {
    transform: rotate(0);
  }

  .faq-r p {
    max-width: 64ch;
    padding-bottom: var(--s-5);
    color: var(--fg-2);
  }

  @media (min-width: 1024px) {
    .faq-grid {
      grid-template-columns: repeat(12, minmax(0, 1fr));
    }

    .faq-intro {
      grid-column: 1 / 5;
    }

    .faq-list {
      grid-column: 6 / 13;
    }
  }

  /* ------------------------------------------------------------------
     En-tête
     ------------------------------------------------------------------ */
  .site-header {
    position: sticky;
    z-index: 50;
    top: 0;
    border-bottom: var(--bord) solid var(--encre);
  }

  .header-inner {
    display: flex;
    align-items: center;
    gap: var(--s-5);
    height: var(--header-height);
  }

  .wordmark {
    flex: none;
  }

  .wordmark img {
    width: 112px;
  }

  .header-panel {
    display: flex;
    flex: 1;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-5);
  }

  .main-nav ul {
    display: flex;
    gap: var(--s-1);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .main-nav a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 var(--s-3);
    font-size: .9375rem;
    font-weight: 500;
    text-decoration: none;
  }

  .main-nav a:hover {
    text-decoration: underline;
  }

  .main-nav a[aria-current="page"] {
    text-decoration: underline;
    text-decoration-thickness: 2px;
    text-underline-offset: .45em;
  }

  .header-tools {
    display: flex;
    align-items: center;
    gap: var(--s-4);
  }

  .header-discord {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    font-size: .9375rem;
    font-weight: 500;
  }

  .nav-toggle {
    display: none;
  }

  @media (min-width: 768px) and (max-width: 1279px) {
    .header-tools .callsign__label {
      position: absolute;
      width: 1px;
      height: 1px;
      overflow: hidden;
      clip: rect(0, 0, 0, 0);
      white-space: nowrap;
    }
  }

  @media (min-width: 768px) and (max-width: 1023px) {
    .header-inner,
    .header-panel {
      gap: var(--s-3);
    }

    .main-nav a {
      padding: 0 var(--s-2);
      font-size: .875rem;
    }

    .header-discord {
      font-size: .875rem;
    }

    .header-tools {
      gap: var(--s-3);
    }

    .header-tools .callsign__nom {
      padding: 0 var(--s-2);
      font-size: .75rem;
    }
  }

  /* Menu compact (site.breakpoints.navCompact, partagé avec main.js).
     Par défaut (sans JavaScript, ou navigateur ignorant @media scripting) :
     le panneau s'affiche en clair sous le logo, liens et indicatif compris,
     et l'en-tête n'est pas collant (il serait trop haut). Le menu déroulant
     n'existe que si un script peut l'ouvrir. */
  @media (max-width: 767px) {
    .site-header {
      position: static;
    }

    .wordmark img {
      width: 96px;
    }

    .header-inner {
      flex-wrap: wrap;
      height: auto;
      min-height: var(--header-height);
      padding-block: var(--s-3);
    }

    .header-panel {
      flex-direction: column;
      flex-basis: 100%;
      align-items: stretch;
      gap: var(--s-4);
    }

    .main-nav ul {
      flex-wrap: wrap;
    }

    .main-nav a {
      padding: 0 var(--s-3) 0 0;
    }

    .header-tools {
      flex-wrap: wrap;
    }

    .nav-toggle__barres span {
      height: 2px;
      background: currentColor;
      transition: transform var(--d-ui) var(--ease);
    }
  }

  @media (max-width: 767px) and (scripting: enabled) {
    .site-header {
      position: sticky;
    }

    .header-inner {
      flex-wrap: nowrap;
      height: var(--header-height);
      padding-block: 0;
    }

    .nav-toggle {
      display: inline-flex;
      align-items: center;
      gap: var(--s-2);
      min-height: 44px;
      margin-inline-start: auto;
      padding: 0 var(--s-3);
      border: var(--bord) solid var(--encre);
      background: transparent;
      font-size: .9375rem;
      font-weight: 600;
      cursor: pointer;
    }

    .nav-toggle__barres {
      display: grid;
      gap: 5px;
      width: 18px;
    }

    .nav-toggle[aria-expanded="true"] .nav-toggle__barres span:first-child {
      transform: translateY(3.5px) rotate(45deg);
    }

    .nav-toggle[aria-expanded="true"] .nav-toggle__barres span:last-child {
      transform: translateY(-3.5px) rotate(-45deg);
    }

    .header-panel {
      position: absolute;
      top: 100%;
      right: 0;
      left: 0;
      display: none;
      gap: var(--s-5);
      max-height: calc(100svh - var(--header-height));
      padding: var(--s-4) var(--gutter) var(--s-6);
      overflow-y: auto;
      border-bottom: var(--bord) solid var(--encre);
      background: var(--fond-papier);
    }

    .header-panel.is-open {
      display: flex;
    }

    .main-nav ul {
      flex-direction: column;
      flex-wrap: nowrap;
      gap: 0;
    }

    .main-nav li + li {
      border-top: var(--bord) solid var(--ligne);
    }

    .main-nav a {
      width: 100%;
      min-height: 52px;
      padding: 0;
      font-family: var(--font-titre);
      font-size: 1.5rem;
      font-stretch: var(--stretch-titre);
      font-weight: 700;
    }

    .header-tools {
      flex-direction: column;
      flex-wrap: nowrap;
      align-items: flex-start;
      gap: var(--s-4);
      padding-top: var(--s-4);
      border-top: var(--bord) solid var(--encre);
    }
  }

  /* ------------------------------------------------------------------
     Pied de page
     ------------------------------------------------------------------ */
  .site-footer {
    padding-block: var(--s-8) var(--s-7);
  }

  .footer-inner {
    display: grid;
    gap: var(--s-6) var(--gap);
  }

  .footer-marque .wordmark img {
    width: 140px;
  }

  .footer-marque .filet {
    margin-top: var(--s-4);
  }

  .footer-devise {
    margin-top: var(--s-5);
    font-family: var(--font-titre);
    font-size: 1.5rem;
    font-stretch: 80%;
    font-weight: 700;
  }

  .footer-tagline {
    margin-top: var(--s-2);
    color: var(--fg-2);
    font-size: .875rem;
  }

  .footer-nav {
    display: grid;
    gap: var(--s-4) var(--gap);
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .footer-nav ul {
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .footer-nav a {
    display: inline-flex;
    align-items: center;
    min-height: 40px;
    font-size: .9375rem;
    text-decoration: none;
  }

  .footer-nav a:hover,
  .footer-nav a[aria-current="page"] {
    text-decoration: underline;
  }

  .footer-haut a {
    font-family: var(--mono);
    font-size: .8125rem;
  }

  @media (min-width: 1024px) {
    .footer-inner {
      grid-template-columns: repeat(12, minmax(0, 1fr));
    }

    .footer-marque {
      grid-column: 1 / 5;
    }

    .footer-nav {
      grid-column: 6 / 11;
    }

    .footer-haut {
      grid-column: 11 / 13;
      justify-self: end;
    }
  }
}

/* 40-pages.css */
@layer pages {
  /* ==================================================================
     ACCUEIL
     ================================================================== */

  /* ---------- Situation (hero) ----------
     < 1024 px : la carte est un bandeau recadré au-dessus du texte.
     ≥ 1024 px : elle occupe tout le fond, le texte est posé sur un calque
     translucide à gauche, les tracés vivent à droite. */
  .situation {
    display: flex;
    flex-direction: column;
    border-bottom: var(--bord) solid var(--encre);
  }

  .situation .tactical-map--hero {
    position: relative;
    order: -1;
    height: clamp(210px, 52vw, 380px);
    border-bottom: var(--bord) solid var(--encre);
  }

  .situation .tactical-map__canvas {
    position: absolute;
    inset: 0 0 0 auto;
    width: 200%;
  }

  .situation .tactical-map__legende {
    position: absolute;
    right: var(--gutter);
    bottom: var(--s-3);
    left: var(--gutter);
    display: flex;
    justify-content: flex-start;
  }

  .situation .provenance {
    padding: var(--s-1) var(--s-2);
    border: var(--bord) solid var(--ligne);
    background: var(--fond-papier);
  }

  .situation .legende,
  .situation .map-note,
  .coords {
    display: none;
  }

  .situation__grille {
    position: relative;
    padding-block: var(--s-6) var(--s-7);
  }

  /* Sous 1024 px, le texte du hero n'est pas posé sur le carroyage : la
     carte en bandeau porte déjà la trame. */
  @media (max-width: 1023px) {
    .situation.carroyage::before {
      content: none;
    }
  }

  .situation__texte {
    grid-column: 1 / -1;
  }

  .situation__titre {
    font-size: inherit;
    font-stretch: 100%;
  }

  .situation__surtitre {
    display: block;
    margin-bottom: var(--s-4);
    color: var(--fg-2);
    font-family: var(--font);
    font-size: var(--t-label);
    font-weight: 500;
    letter-spacing: .08em;
    line-height: 1.4;
    text-transform: uppercase;
  }

  .situation__slogan {
    display: block;
    font-size: clamp(2.5rem, 5.4vw, 5rem);
    font-stretch: var(--stretch-titre);
    line-height: .98;
    letter-spacing: -.015em;
  }

  /* Deux lignes maîtrisées (« La guerre continue. » / « Avec ou sans
     vous. »), chacune libre de se replier sur petit écran. */
  .situation__slogan > span {
    display: block;
  }

  .situation__resume {
    max-width: 44ch;
    margin-top: var(--s-5);
    font-size: clamp(1.125rem, .5vw + 1rem, 1.25rem);
    line-height: 1.5;
  }

  .situation__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    gap: var(--s-3);
    margin-top: var(--s-6);
  }

  /* Bogue corrigé : chaque état est un élément de liste, séparé par un
     repère carré qui survit au retour à la ligne (plus de « · » masqués). */
  .etat-serveur {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2) var(--s-4);
    margin: var(--s-5) 0 0;
    padding: 0;
    font-size: .875rem;
    font-weight: 500;
    list-style: none;
  }

  .etat-serveur li {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
  }

  .etat-serveur li::before {
    width: 6px;
    height: 6px;
    background: var(--fg);
    content: "";
  }

  @media (max-width: 479px) {
    .situation__actions .button {
      flex: 1 1 100%;
    }

    .situation__actions .callsign,
    .article-body .callsign {
      flex: 1 1 100%;
      flex-wrap: wrap;
    }

    .article-body .callsign {
      display: flex;
    }

    .situation__actions .callsign__label,
    .article-body .callsign__label {
      flex: 1 1 100%;
      min-height: 32px;
      border-inline-end: 0;
      border-bottom: var(--bord) solid var(--ligne);
    }

    .situation__actions .callsign__nom,
    .article-body .callsign__nom {
      flex: 1;
      min-height: 48px;
    }
  }

  @media (min-width: 768px) {
    .situation .tactical-map__canvas {
      width: 150%;
    }

    .situation .legende,
    .situation .map-note {
      display: revert;
    }

    .situation .tactical-map__legende {
      flex-direction: column;
      align-items: flex-start;
    }

    .situation .legende {
      display: flex;
      padding: var(--s-1) var(--s-2);
      background: var(--fond-papier);
    }

    .situation__texte {
      grid-column: 1 / 8;
    }
  }

  @media (min-width: 1024px) {
    .situation {
      display: block;
      position: relative;
    }

    /* Seul le canevas passe sous le carroyage (-1) ; la légende reste
       au-dessus. La figure ne crée donc pas de contexte d'empilement. */
    .situation .tactical-map--hero {
      position: absolute;
      inset: 0;
      height: auto;
      border: 0;
      pointer-events: none;
    }

    /* La figure couvre tout le hero : elle laisse passer les clics vers le
       texte ; seuls le calque (survol des secteurs) et la légende en
       reçoivent. */
    .situation .tactical-map__calque,
    .situation .tactical-map__legende {
      pointer-events: auto;
    }

    .situation .tactical-map__canvas {
      z-index: -2;
      inset: 0;
      width: 100%;
    }

    .situation .tactical-map__legende {
      z-index: 1;
      right: var(--gutter);
      bottom: var(--s-5);
      left: auto;
      align-items: flex-end;
      max-width: 52%;
    }

    .coords {
      position: absolute;
      top: var(--s-2);
      right: 0;
      left: 0;
      display: grid;
      grid-template-columns: repeat(12, minmax(0, 1fr));
      column-gap: var(--gap);
      width: min(var(--container), calc(100% - 2 * var(--gutter)));
      margin: 0 auto;
      padding: 0;
      color: var(--fg-2);
      font-family: var(--mono);
      font-size: .75rem;
      list-style: none;
    }

    .coords li {
      padding-inline-start: var(--s-2);
    }

    /* La grille couvre la largeur du hero : seul le panneau de texte
       capte le pointeur, le reste laisse survoler la carte. */
    .situation__grille {
      padding-block: clamp(56px, 7vw, 120px) clamp(96px, 9vw, 150px);
      pointer-events: none;
    }

    .situation__texte {
      pointer-events: auto;
    }

    .situation__texte {
      grid-column: 1 / 7;
      padding: var(--s-6);
      margin-inline-start: calc(-1 * var(--s-6));
      background: color-mix(in srgb, var(--fond-papier) 90%, transparent);
      border-inline-end: var(--bord) solid var(--ligne);
    }
  }

  /* ≥ 1600 px : la carte gagne du champ, pas le texte. Le hero prend la
     hauteur de l'écran, plafonnée au format de la carte (16:9), pour que le
     recadrage ne coupe pas les tracés ; le texte reste centré à sa mesure. */
  @media (min-width: 1600px) {
    .situation {
      display: flex;
      align-items: center;
      min-height: min(calc(100svh - var(--header-height)), 56.25vw);
    }
  }

  /* 1024-1279 px : le recadrage (slice, ancré à droite) dépend de la seule
     hauteur ; le calque tactique est donc décalé vers la droite pour que le
     panneau de texte ne recouvre aucun symbole (le relief, abstrait, ne
     bouge pas). */
  @media (min-width: 1024px) and (max-width: 1279px) {
    .situation .tactical-map__calque {
      translate: 6% 0;
    }
  }

  /* ---------- Main courante ---------- */
  .main-courante__tete,
  .main-courante__registre {
    grid-column: 1 / -1;
  }

  .main-courante__tete h2 {
    max-width: 14ch;
  }

  .main-courante__tete h2 > span {
    display: block;
  }

  .main-courante__tete > p:not(.label) {
    max-width: 44ch;
    margin-top: var(--s-4);
    color: var(--fg-2);
  }

  .main-courante__nouveau {
    font-family: var(--mono);
    font-size: .8125rem;
  }

  .main-courante__registre {
    margin-top: var(--s-7);
  }

  .log-groupe + .log-groupe {
    margin-top: var(--s-7);
  }

  .log-groupe__tete {
    display: grid;
    gap: var(--s-1);
    padding-bottom: var(--s-4);
    border-bottom: var(--bord) solid var(--fg);
  }

  .log-groupe__tete .dtg {
    color: var(--action-nuit);
  }

  .log-groupe__tete h3 {
    font-size: 1.25rem;
  }

  .log-groupe__tete h3 a {
    text-decoration: none;
  }

  .log-groupe__tete h3 a:hover {
    text-decoration: underline;
  }

  .main-courante__suite {
    margin-top: var(--s-5);
  }

  .rejoindre__suite {
    margin-top: var(--s-5);
    max-width: 68ch;
  }

  @media (min-width: 1024px) {
    .main-courante__tete {
      grid-column: 1 / 5;
      align-self: start;
    }

    .main-courante__registre {
      grid-column: 6 / 13;
      margin-top: 0;
    }
  }

  /* ---------- Adversaire ---------- */
  .adversaire__grille {
    row-gap: var(--s-6);
  }

  .adversaire__grille > * {
    grid-column: 1 / -1;
  }

  .adversaire__tete .lead {
    max-width: 52ch;
    margin-top: var(--s-4);
  }

  .adversaire__theatre {
    max-width: 52ch;
    margin-top: var(--s-4);
    color: var(--fg-2);
  }

  .modes {
    display: grid;
    gap: 0;
    margin: 0;
    padding: 0;
    border-top: var(--bord) solid var(--fg);
    list-style: none;
  }

  .modes li {
    display: grid;
    grid-template-columns: 40px 1fr;
    column-gap: var(--s-3);
    padding: var(--s-4) 0;
    border-bottom: var(--bord) solid var(--ligne);
  }

  .modes__num {
    grid-row: span 2;
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    border: 2px solid var(--c-ennemi);
    border-radius: 50%;
    color: var(--c-ennemi);
    font-family: var(--mono);
    font-size: .875rem;
    font-weight: 500;
  }

  .modes h3 {
    font-size: 1.125rem;
  }

  .modes p {
    margin-top: var(--s-1);
    color: var(--fg-2);
    font-size: var(--t-petit);
  }

  /* Téléphone : les modes d'action deviennent une légende compacte du
     schéma (numéro + verbe, deux colonnes) ; le détail reste dès 480 px. */
  @media (max-width: 479px) {
    .modes {
      grid-template-columns: repeat(2, minmax(0, 1fr));
      column-gap: var(--s-3);
    }

    .modes li {
      grid-template-columns: 30px 1fr;
      align-items: center;
      padding: var(--s-3) 0;
    }

    .modes__num {
      grid-row: auto;
      width: 24px;
      height: 24px;
      font-size: .8125rem;
    }

    .modes h3 {
      font-size: 1rem;
    }

    .modes p {
      display: none;
    }
  }

  @media (min-width: 768px) {
    .modes {
      grid-template-columns: repeat(2, minmax(0, 1fr));
      column-gap: var(--gap);
    }
  }

  @media (min-width: 1024px) {
    .adversaire__grille {
      grid-template-rows: auto 1fr;
      align-items: start;
    }

    .adversaire__tete,
    .modes {
      grid-column: 1 / 6;
    }

    .modes {
      grid-template-columns: 1fr;
    }

    .adversaire__schema {
      grid-column: 7 / 13;
      grid-row: 1 / 3;
      padding-top: var(--s-8);
    }
  }

  /* ---------- Front persistant ---------- */
  .front__tete {
    row-gap: var(--s-4);
    margin-bottom: var(--s-6);
  }

  .front__intro,
  .front__texte {
    grid-column: 1 / -1;
  }

  .front__texte {
    max-width: 52ch;
    font-size: clamp(1.0625rem, .4vw + 1rem, 1.1875rem);
  }

  @media (min-width: 1024px) {
    .front__intro {
      grid-column: 1 / 6;
    }

    .front__texte {
      grid-column: 7 / 13;
      align-self: end;
    }
  }

  /* Constat : le fait daté qui appuie le schéma de principe. Filet ennemi
     épais, pas de fond : une pièce versée au dossier, pas une carte. */
  .constat {
    max-width: 64ch;
    margin-top: var(--s-7);
    padding: var(--s-5) 0 0 var(--s-5);
    border-top: var(--bord) solid var(--fg);
    border-inline-start: var(--bord-actif) solid var(--c-ennemi);
  }

  .constat__ref {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--s-3);
    margin-bottom: var(--s-3);
    font-family: var(--mono);
    font-size: var(--t-data);
  }

  .constat__ref .label {
    margin: 0;
  }

  .constat h3 {
    font-family: var(--font-titre);
    font-size: clamp(1.375rem, 1.6vw + 1rem, 2rem);
    font-stretch: var(--stretch-titre);
    font-weight: 700;
    line-height: 1.1;
  }

  .constat h3 + p {
    margin-top: var(--s-3);
  }

  .constat p + p {
    margin-top: var(--s-3);
  }

  /* ---------- Génie ---------- */
  .genie__tete,
  .genie__epure,
  .genie__capacites,
  .genie__citation,
  .genie__suite {
    grid-column: 1 / -1;
  }

  .genie h2 {
    max-width: 12ch;
  }

  .genie .lead {
    max-width: 50ch;
    margin-top: var(--s-4);
  }

  .genie__epure {
    display: none;
    width: min(100%, 360px);
    margin-top: var(--s-6);
  }

  @media (min-width: 768px) {
    .genie__epure {
      display: block;
    }
  }

  .genie__epure svg {
    width: 100%;
    height: auto;
    overflow: visible;
  }

  .genie__cadre {
    fill: none;
    stroke: var(--genie);
    stroke-width: 2.5;
  }

  .genie__creneau {
    fill: none;
    stroke: var(--genie);
    stroke-linejoin: miter;
    stroke-width: 4;
  }

  .cote path {
    fill: none;
    stroke: var(--brume);
    stroke-width: 1;
  }

  .cote text {
    fill: var(--brume);
    font-family: var(--mono);
    font-size: 13px;
    letter-spacing: .08em;
    text-transform: uppercase;
  }

  .genie__capacites {
    display: grid;
    gap: var(--s-7) var(--gap);
    margin-top: var(--s-7);
  }

  .genie .sector-sheet {
    border-top-color: var(--genie);
  }

  .genie .sector-sheet__corps > p {
    font-size: 1.125rem;
  }

  .verbes {
    margin: var(--s-4) 0 0;
    padding: 0;
    list-style: none;
  }

  .verbes li {
    padding: var(--s-2) 0;
    border-bottom: var(--bord) solid var(--ligne);
    color: var(--fg-2);
    font-size: var(--t-petit);
  }

  .verbes strong {
    color: var(--fg);
  }

  .genie__citation {
    margin-top: var(--s-8);
    padding-inline-start: var(--s-5);
    border-inline-start: 3px solid var(--genie);
  }

  .genie__citation p {
    max-width: 30ch;
    font-family: var(--font-titre);
    font-size: clamp(1.5rem, 2.4vw, 2.25rem);
    font-stretch: var(--stretch-titre);
    font-weight: 700;
    line-height: 1.15;
  }

  .genie__suite {
    margin-top: var(--s-6);
  }

  @media (min-width: 768px) {
    .genie__capacites {
      grid-template-columns: repeat(2, minmax(0, 1fr));
    }
  }

  @media (min-width: 1024px) {
    .genie__tete {
      grid-column: 1 / 8;
    }

    .genie__epure {
      grid-column: 9 / 13;
      grid-row: 1;
      align-self: center;
      justify-self: end;
      margin-top: 0;
    }

    .genie__citation {
      grid-column: 1 / 9;
    }

    .genie__suite {
      grid-column: 1 / 13;
    }
  }

  /* ---------- Trinôme ---------- */
  .trinome__tete,
  .echelons {
    grid-column: 1 / -1;
  }

  .trinome .lead {
    max-width: 50ch;
    margin-top: var(--s-4);
  }

  .trinome__texte {
    max-width: 50ch;
    margin-top: var(--s-3);
    color: var(--fg-2);
  }

  .echelons {
    display: grid;
    gap: 0;
    margin: var(--s-7) 0 0;
    padding: 0;
    list-style: none;
  }

  .echelon {
    position: relative;
    display: grid;
    grid-template-columns: 72px 1fr;
    column-gap: var(--s-4);
    padding: var(--s-5) 0;
  }

  .echelon__symbole {
    grid-row: span 2;
    width: 72px;
    height: auto;
    overflow: visible;
  }

  .echelon h3 {
    font-family: var(--font-titre);
    font-size: 1.5rem;
    font-stretch: var(--stretch-titre);
    font-weight: 700;
  }

  .echelon p {
    margin-top: var(--s-2);
    color: var(--fg-2);
    font-size: var(--t-petit);
  }

  /* Liaison d'échelon : trait vertical entre les symboles (mobile), puis
     horizontal (≥ 768 px). */
  .echelon + .echelon::before {
    position: absolute;
    top: calc(-1 * var(--s-5) + 8px);
    left: 35px;
    width: 2px;
    height: calc(var(--s-5) * 2 - 16px);
    background: var(--fg);
    content: "";
  }

  @media (min-width: 768px) {
    .echelons {
      grid-template-columns: repeat(3, minmax(0, 1fr));
      column-gap: var(--gap);
    }

    .echelon {
      grid-template-columns: 1fr;
      padding: 0;
    }

    .echelon__symbole {
      grid-row: auto;
      margin-bottom: var(--s-4);
    }

    .echelon + .echelon::before {
      top: 28px;
      left: calc(-1 * var(--gap) - 40px);
      width: calc(var(--gap) + 24px);
      height: 2px;
    }
  }

  @media (min-width: 1024px) {
    .trinome__tete {
      grid-column: 1 / 7;
    }
  }

  /* ---------- Manifeste ----------
     Le seul texte de la page composé en très grand : quatre temps, la
     chute sur deux lignes maîtrisées. */
  .manifeste {
    border-block: var(--bord) solid var(--encre);
  }

  .manifeste__label,
  .manifeste__texte {
    grid-column: 1 / -1;
  }

  .manifeste__texte {
    max-width: 28ch;
    font-family: var(--font-titre);
    font-size: clamp(1.5rem, 2.6vw + .5rem, 2.75rem);
    font-stretch: var(--stretch-titre);
    font-weight: 700;
    line-height: 1.08;
    letter-spacing: -.01em;
    text-wrap: balance;
  }

  .manifeste__texte p:not(.manifeste__chute) {
    color: var(--fg-2);
  }

  .manifeste__texte .manifeste__chute {
    margin-top: var(--s-6);
    padding-top: var(--s-5);
    border-top: 3px solid var(--fg);
  }

  .manifeste__chute > span {
    display: block;
  }

  @media (min-width: 1024px) {
    .manifeste__label {
      grid-column: 1 / 4;
      align-self: start;
      margin-top: .75em;
    }

    .manifeste__texte {
      grid-column: 4 / 13;
    }
  }

  .manifeste__texte p + p {
    margin-top: var(--s-3);
  }

  /* ---------- En pratique ---------- */
  .pratique__tete,
  .fiche-pratique {
    grid-column: 1 / -1;
  }

  .fiche-pratique {
    display: grid;
    margin: var(--s-5) 0 0;
    border-top: var(--bord) solid var(--fg);
  }

  .fiche-pratique div {
    display: grid;
    gap: var(--s-1) var(--gap);
    padding: var(--s-4) 0;
    border-bottom: var(--bord) solid var(--ligne);
  }

  .fiche-pratique dt {
    color: var(--fg-2);
    font-family: var(--mono);
    font-size: var(--t-data);
    letter-spacing: .06em;
    text-transform: uppercase;
  }

  .fiche-pratique dd {
    font-size: 1.0625rem;
  }

  @media (min-width: 768px) {
    .fiche-pratique div {
      grid-template-columns: 10rem 1fr;
      align-items: baseline;
    }
  }

  @media (min-width: 1024px) {
    .pratique__tete {
      grid-column: 1 / 5;
    }

    .fiche-pratique {
      grid-column: 6 / 13;
      margin-top: 0;
    }
  }

  /* ---------- Rejoindre ---------- */
  .ordre-tete {
    margin-bottom: var(--s-6);
    padding-top: var(--s-4);
    border-top: 3px solid var(--fg);
  }

  .ordre-tete__ref {
    margin-bottom: var(--s-4);
    color: var(--fg-2);
    font-family: var(--mono);
    font-size: .8125rem;
    letter-spacing: .06em;
    text-transform: uppercase;
  }

  .ordre-tete h2 {
    max-width: 18ch;
  }

  .ordre-tete > p:last-child {
    max-width: 58ch;
    margin-top: var(--s-4);
    color: var(--fg-2);
  }

  /* ==================================================================
     PAGES ÉDITORIALES (rejoindre, recrutement, milsim, articles)
     ================================================================== */
  .breadcrumb {
    padding-top: var(--s-5);
    font-family: var(--mono);
    font-size: .75rem;
  }

  .breadcrumb ol {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .breadcrumb li + li::before {
    margin-inline-end: var(--s-2);
    color: var(--fg-2);
    content: "/" / "";
  }

  .breadcrumb [aria-current] {
    color: var(--fg-2);
  }

  .article-header,
  .journal-hero,
  .legal-header {
    max-width: 920px;
    padding-block: var(--s-7) var(--s-6);
  }

  .article-header h1,
  .journal-hero h1,
  .legal-header h1 {
    font-size: clamp(2.25rem, 5vw, 4.25rem);
  }

  .article-header .filet,
  .journal-hero .filet,
  .legal-header .filet {
    margin-top: var(--s-5);
  }

  .article-meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2) var(--s-4);
    margin-top: var(--s-4);
    color: var(--fg-2);
    font-family: var(--mono);
    font-size: .8125rem;
  }

  .article-header > p:not(.label),
  .journal-hero > p:not(.label),
  .legal-header > p:not(.label) {
    max-width: var(--measure);
    margin-top: var(--s-4);
  }

  .article-lead {
    font-size: clamp(1.125rem, .5vw + 1rem, 1.3125rem);
    line-height: 1.5;
  }

  .article-header > p:not(.label, .article-lead) {
    color: var(--fg-2);
  }

  .article-toc {
    max-width: var(--measure);
    margin-block: var(--s-5) var(--s-6);
    padding: var(--s-4) var(--s-5);
    border: var(--bord) solid var(--fg);
  }

  .article-toc h2 {
    margin-bottom: var(--s-3);
    font-family: var(--mono);
    font-size: .75rem;
    font-stretch: 100%;
    font-weight: 500;
    letter-spacing: .06em;
    text-transform: uppercase;
  }

  .article-toc ol {
    margin: 0;
    padding-inline-start: 1.5em;
    font-size: var(--t-petit);
  }

  .article-toc li + li {
    margin-top: var(--s-1);
  }

  .article-toc li::marker {
    color: var(--fg-2);
    font-family: var(--mono);
    font-size: .8125rem;
  }

  .article-body {
    max-width: var(--measure);
  }

  .article-body section {
    padding-top: var(--s-7);
  }

  .article-body h2 {
    padding-top: var(--s-4);
    border-top: var(--bord) solid var(--fg);
  }

  .article-body h3 {
    margin-top: var(--s-6);
  }

  .article-body p,
  .article-body ul,
  .article-body ol {
    margin-top: var(--s-4);
  }

  .article-body .callsign {
    margin-block: var(--s-4);
  }

  .article-body ul {
    padding-inline-start: 1.1em;
    list-style: square;
  }

  .article-body li + li {
    margin-top: var(--s-2);
  }

  .article-body li::marker {
    color: var(--fg-2);
  }

  .rubrique {
    margin-bottom: var(--s-3);
    color: var(--fg-2);
    font-family: var(--mono);
    font-size: .8125rem;
    letter-spacing: .04em;
    text-transform: uppercase;
  }

  .rubrique__num {
    margin-inline-end: var(--s-2);
    padding: 0 var(--s-1);
    border: var(--bord) solid var(--fg-2);
  }

  .article-body .rubrique + h2 {
    padding-top: 0;
    border-top: 0;
  }

  .article-body section:has(> .rubrique) {
    border-top: var(--bord) solid var(--fg);
    margin-top: var(--s-7);
    padding-top: var(--s-4);
  }

  .status-heading {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--s-2) var(--s-3);
    margin-top: var(--s-6);
  }

  .status-heading h3 {
    margin-top: 0;
  }

  /* Bogue corrigé : liens de fin de page séparés et alignés aux deux bords,
     même quand il n'y en a qu'un. */
  .article-pagination {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: var(--s-3) var(--s-6);
    max-width: var(--measure);
    margin-top: var(--s-8);
    padding-top: var(--s-4);
    border-top: var(--bord) solid var(--fg);
  }

  .article-pagination a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    font-weight: 600;
  }

  .article-pagination a:only-child {
    margin-inline-start: auto;
  }

  .status-legend {
    max-width: var(--measure);
    margin-block: var(--s-5);
    padding: var(--s-4) var(--s-5);
    border: var(--bord) solid var(--ligne);
  }

  .status-legend h2 {
    margin-bottom: var(--s-3);
    font-family: var(--mono);
    font-size: .75rem;
    font-stretch: 100%;
    font-weight: 500;
    letter-spacing: .06em;
    text-transform: uppercase;
  }

  .status-legend dl {
    display: grid;
    gap: var(--s-3);
  }

  .status-legend dl div {
    display: grid;
    gap: var(--s-1) var(--s-4);
  }

  .status-legend dt {
    min-width: 0;
  }

  .status-legend dd {
    color: var(--fg-2);
    font-size: .9375rem;
  }

  @media (min-width: 768px) {
    .status-legend dl div {
      grid-template-columns: 11rem 1fr;
      align-items: baseline;
    }
  }

  /* Pages longues ≥ 1024 px : sommaire en rail à gauche, texte à droite,
     mesure constante. */
  @media (min-width: 1024px) {
    .article-layout {
      display: grid;
      grid-template-columns: repeat(12, minmax(0, 1fr));
      column-gap: var(--gap);
      align-items: start;
    }

    .article-layout > .breadcrumb {
      grid-column: 1 / -1;
    }

    .article-layout > .article-header,
    .article-layout > .status-legend {
      grid-column: 1 / 11;
    }

    .article-layout > .status-legend {
      grid-column: 4 / 11;
    }

    .article-layout > .article-toc {
      grid-column: 1 / 4;
      grid-row: span 3;
      position: sticky;
      top: calc(var(--header-height) + var(--s-5));
      margin: 0;
      padding: var(--s-4) 0 0;
      border: 0;
      border-top: var(--bord-actif) solid var(--fg);
    }

    .article-layout > .article-body,
    .article-layout > .article-pagination {
      grid-column: 4 / 12;
    }
  }

  /* ==================================================================
     JOURNAL
     ================================================================== */
  .journal-list {
    max-width: 980px;
    margin-top: var(--s-6);
  }

  .journal-log {
    margin: 0;
    padding: 0;
    border-top: var(--bord) solid var(--fg);
    list-style: none;
  }

  .journal-item {
    display: grid;
    gap: var(--s-3) var(--gap);
    padding: var(--s-5) 0;
    border-bottom: var(--bord) solid var(--ligne);
  }

  .journal-item__meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2) var(--s-4);
    align-items: center;
    font-family: var(--mono);
    font-size: .8125rem;
  }

  .journal-item__num {
    color: var(--fg-2);
  }

  .journal-item h3 {
    font-family: var(--font-titre);
    font-size: clamp(1.5rem, 2vw, 2rem);
    font-stretch: var(--stretch-titre);
    font-weight: 700;
  }

  .journal-item h3 a {
    text-decoration: none;
  }

  .journal-item h3 a:hover {
    text-decoration: underline;
  }

  .journal-item__resume {
    max-width: 60ch;
    color: var(--fg-2);
  }

  .tag-list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .tag-list li {
    color: var(--fg-2);
    font-family: var(--mono);
    font-size: .75rem;
    letter-spacing: .04em;
    text-transform: uppercase;
  }

  .tag-list li + li::before {
    margin-inline-end: var(--s-2);
    content: "·" / "";
  }

  @media (min-width: 768px) {
    .journal-item {
      grid-template-columns: 12rem 1fr;
    }

    .journal-item__meta {
      flex-direction: column;
      align-items: flex-start;
      gap: var(--s-2);
    }
  }

  /* ==================================================================
     PAGES SIMPLES (mentions légales, 404)
     ================================================================== */
  .legal-content {
    max-width: var(--measure);
  }

  .legal-section {
    padding-block: var(--s-5);
    border-top: var(--bord) solid var(--ligne);
  }

  .legal-section h2 {
    font-size: clamp(1.375rem, 2vw, 1.75rem);
  }

  .legal-section p,
  .legal-section ul {
    margin-top: var(--s-3);
  }

  .legal-section ul {
    padding-inline-start: 1.1em;
    list-style: square;
  }

  .legal-section .actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-3);
    margin-top: var(--s-5);
  }

  .hors-carte {
    font-family: var(--mono);
    color: var(--fg-2);
  }
}

/* 50-motion.css */
@layer motion {
  /* Seules animations du site, toutes narratives :
     - la ligne de front et les flèches de manœuvre se tracent ;
     - les entrées de main courante apparaissent à leur tour ;
     (le retour du bouton copier et le survol d'un secteur sont de simples
     transitions, voir 30-components.css).
     Rien n'est déclaré sous prefers-reduced-motion: reduce : l'état final
     s'affiche directement. Sans ces règles, tout est lisible. */
  @media screen and (prefers-reduced-motion: no-preference) {
    @keyframes tracer {
      from {
        stroke-dashoffset: 1;
      }

      to {
        stroke-dashoffset: 0;
      }
    }

    @keyframes apparaitre {
      from {
        opacity: 0;
        translate: 0 .5rem;
      }

      to {
        opacity: 1;
        translate: 0 0;
      }
    }

    /* Hero : au chargement. pathLength="1" sur les tracés normalise la
       longueur ; le tracé part vide (offset 1) et se dessine. */
    .trace {
      stroke-dasharray: 1 1;
      animation: tracer var(--d-recit) var(--ease) both;
    }

    .trace--differe {
      animation-duration: 800ms;
      animation-delay: 600ms;
    }

    /* Ailleurs : le tracé suit l'entrée de la carte dans la fenêtre, quand le
       navigateur sait lier une animation au défilement. */
    @supports (animation-timeline: view()) {
      .schema .trace,
      .timeline-state .trace {
        animation: tracer linear both;
        animation-delay: 0s;
        animation-timeline: view();
        animation-range: entry 30% cover 50%;
      }

      .log-entry {
        animation: apparaitre linear both;
        animation-timeline: view();
        animation-range: entry 0% entry 70%;
      }
    }
  }
}

/* 90-utilities.css */
@layer utilities {
  .visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }

  /* Mouvement réduit : toute animation s'affiche directement dans son état
     final (les animations narratives de 50-motion.css ne sont de toute façon
     déclarées que sous prefers-reduced-motion: no-preference). */
  @media (prefers-reduced-motion: reduce) {
    html {
      scroll-behavior: auto;
    }

    *,
    *::before,
    *::after {
      scroll-behavior: auto !important;
      transition-duration: .01ms !important;
      animation-duration: .01ms !important;
      animation-iteration-count: 1 !important;
    }
  }
}
