/* ═══════════════════════════════════════════════════════════════════════════
   SMSPAY — DIRECTION « ZÉRO », PALETTE DE MARQUE
   ---------------------------------------------------------------------------
   Le concept : tout l'argument de SMSPay est une série de zéros (0 % de
   commission, 0 € d'abonnement, 0 engagement). Le zéro — l'anneau, le vide,
   le prélèvement absent — est le motif fondateur.

   LA PALETTE EST CELLE DU LOGO, pas une palette inventée. Le logo SMSPay
   porte exactement deux couleurs, en dégradé : un bleu #455FFD et un cyan
   #20CAE2. Le site n'en utilise pas une troisième. Le crème et l'encre ne
   sont pas des couleurs, ce sont les deux supports.

   ─── LES CINQ RÈGLES ───────────────────────────────────────────────────────

   1. DEUX FORMES. Le rectangle à 4 px de rayon — l'exact arrondi de l'icône
      du logo — et le cercle parfait. Aucune autre géométrie.

   2. DEUX VOIX TYPOGRAPHIQUES. Les TITRES et les CHIFFRES parlent en Satoshi,
      les MOTS en Supreme. IBM Plex Mono n'étiquette, n'horodate, n'indexe.

   3. TROIS ENVIRONNEMENTS, jamais mélangés, tous dérivés du logo :
        · LAVIS — le support par défaut : un dégradé de soie fixe, tiré des
                  deux couleurs du logo et posé sur le crème, accent bleu
        · ENCRE — la rupture sombre (section 05), accent cyan de marque
        · BLEU  — la rupture de choc (section 08), accent cyan de marque
      Chacun redéfinit les MÊMES jetons : un composant traverse les trois
      sans une ligne de CSS supplémentaire. Le lavis vit sur le body : les
      sections claires sont transparentes et le laissent traverser, les deux
      ruptures le couvrent d'un aplat.

   4. L'ACCENT NE DÉCORE JAMAIS. Il signale ce qui est confirmé : distribué,
      encaissé, la ligne payée, le total, le tarif, le champ actif.

   5. AUCUNE OMBRE FLOUE. Un seul dégradé dans tout le site : le lavis de
      fond, plus celui du logo, qui garde le sien.

   Performance : rien d'animé hors transform / opacity / clip-path.
   Aucune bibliothèque, aucune ressource extérieure.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Polices auto-hébergées : rien ne part chez Google ──────────────────── */
/* Satoshi porte les titres et les grands chiffres, Supreme le texte courant.
   Les deux viennent de Fontshare et sont copiées ici : aucune requête ne part
   vers un serveur extérieur, ni chez Google ni chez Fontshare. */
@font-face {
  font-family: 'Satoshi';
  src: url('fonts/satoshi-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Satoshi';
  src: url('fonts/satoshi-500.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Satoshi';
  src: url('fonts/satoshi-700.woff2') format('woff2');
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Satoshi';
  src: url('fonts/satoshi-900.woff2') format('woff2');
  font-weight: 900; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Supreme';
  src: url('fonts/supreme-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Supreme';
  src: url('fonts/supreme-500.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Supreme';
  src: url('fonts/supreme-700.woff2') format('woff2');
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'IBM Plex Mono';
  src: url('fonts/ibm-plex-mono-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'IBM Plex Mono';
  src: url('fonts/ibm-plex-mono-500.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}

/* ═══════════════════════════════════════════════════════════════════════════
   1 · JETONS
   ═══════════════════════════════════════════════════════════════════════════ */
:root {
  /* Les deux supports */
  --creme:     #EFEDE6;
  --creme-2:   #F6F5F1;   /* panneaux : plus clair que le support, jamais plus sombre */
  --encre:     #121210;

  /* Le lavis : les quatre arrêts du dégradé de fond, tous tirés du logo.
     Brume et ciel viennent du bleu #455FFD, l'eau du cyan #20CAE2, et le
     dernier arrêt est le crème du site : le lavis finit sur le papier.
     Les quatre valeurs sont volontairement TRÈS proches les unes des autres :
     le fond doit se remarquer sans se regarder. Pour le rendre plus présent,
     éloigner ces quatre valeurs ; pour l'effacer, les rapprocher. */
  --lavis-brume: #F1F3FC;
  --lavis-ciel:  #E9EEFA;
  --lavis-eau:   #EDF6F7;
  --lavis-creme: #F6F3EB;

  /* Les deux couleurs de marque, relevées sur le logo */
  --bleu:      #455FFD;   /* la valeur exacte du logo — aplats, grands chiffres */
  --bleu-texte:#2F41C4;   /* la même teinte assombrie — petits corps sur crème, 6,7:1 */
  --bleu-fond: #3A4FE0;   /* la même teinte, pour que le crème passe dessus à 5,6:1 */
  --cyan:      #20CAE2;   /* la seconde couleur du logo — réservée aux fonds sombres */
  --bleu-pale: #D8E1FF;   /* les aplats des icônes, tiré du bleu de marque */
  --cyan-profond:#0E8CA3; /* le MÊME cyan, assombri pour tenir sur fond clair, 3,2:1 */

  /* Le dégradé de marque, repris du logo : l'axe du SVG est cyan en haut à
     gauche, bleu en bas à droite, soit 114° en CSS. Sur fond clair le cyan
     passe en cyan profond, sinon la fin du mot devient illisible (1,6:1). */
  --degrade-marque: linear-gradient(114deg, var(--cyan-profond) 0%, var(--bleu) 100%);

  /* Jetons contextuels : ce sont EUX que les composants consomment. */
  /* Le fond des sections est BLANC. Le lavis reste sur le body, donc il ne se
     voit plus que là où une section le laisse passer : le hero, et lui seul.
     Les deux ruptures gardent leur aplat. */
  --fond:         #FFFFFF;
  --surface:      #F4F6FD;   /* panneaux et champs posés sur le blanc */
  --texte:        var(--encre);
  --texte-2:      #5E5C55;   /* 4,9:1 sur l'arrêt le plus soutenu du lavis */
  --texte-3:      #63605A;   /* 4,5:1 — annotations, index */
  /* Les filets deviennent froids : sur du blanc, les gris chauds du papier
     tiraient vers le sale. */
  --trait:        #E6E8F0;
  --trait-fort:   #C9CDDB;
  --accent:       var(--bleu-texte);  /* accent lisible en TEXTE COURANT */
  --accent-fort:  var(--bleu);        /* accent en APLAT et GRANDS CHIFFRES */
  --accent-texte: #FFFFFF;            /* le texte posé sur un aplat d'accent */

  /* Rythme — échelle 4 px */
  --e1: 4px;   --e2: 8px;   --e3: 12px;  --e4: 16px;  --e5: 24px;
  --e6: 32px;  --e7: 48px;  --e8: 64px;  --e9: 96px;  --e10: 128px;
  --e11: 176px;

  /* LE PAS DES SECTIONS, une seule valeur pour toute la page. Il était de 176 px
     en haut et en bas des sections blanches, mais de 128/64 et 64/96 sur les
     autres, au fil des refontes : les sections n'étaient donc pas à la même
     distance les unes des autres, et l'écart était trop grand. */
  --pas-section: var(--e9);

  /* Structure */
  --entete-h: 68px;
  --gouttiere: clamp(20px, 7.4vw, 116px);
  /* La carte du hero est posée à l'intérieur de la page, pas collée aux bords.
     Sa marge est retirée de son padding interne, si bien que son contenu
     retombe EXACTEMENT sur la gouttière commune : le logo, le titre du hero,
     les titres de section et le pied de page s'alignent tous sur la même
     verticale. C'est la clé de la cohérence des marges. */
  --marge-carte: clamp(10px, 1.1vw, 18px);
  --rayon-carte: clamp(22px, 2vw, 38px);
  /* La course de la pile de la section 04, après sa dernière carte. Elle sert
     deux fois : à la cale, et à la marge basse du champ de gauche. */
  --pile-cale: 280px;
  --largeur-max: 1520px;
  /* Les rayons. Le motif du site est l'anneau, le zéro : les angles droits
     n'ont donc aucune raison de dominer. Trois valeurs, jamais d'autres. */
  --rayon: 16px;             /* champs, petits panneaux */
  --rayon-grand: 28px;       /* la bulle du SMS, le journal */
  --rayon-plein: 999px;      /* boutons, pastilles, choix */

  /* Voix
     --f-titre   : Satoshi, les titres et sous-titres
     --f-chiffre : Satoshi aussi, en Black, pour les grands chiffres
     --f-mot     : Supreme, tout le texte courant
     --f-etiq    : IBM Plex Mono, inchangé : il étiquette, horodate, indexe */
  --f-titre:   'Satoshi', 'Helvetica Neue', Arial, sans-serif;
  --f-chiffre: 'Satoshi', 'Arial Black', sans-serif;
  --f-mot:     'Supreme', 'Helvetica Neue', Arial, sans-serif;
  --f-etiq:    'IBM Plex Mono', 'Courier New', monospace;

  /* Échelle typographique */
  --t-etiq:  11px;
  --t-corps: clamp(16px, 0.6vw + 14px, 18px);
  --t-lead:  clamp(19px, 1.1vw + 14px, 26px);
  --t-h3:    clamp(20px, 0.9vw + 16px, 28px);
  /* LA taille des titres de section, la seule. Tous les h2 de la page la
     prennent, sans exception : la refonte du 31/07 a supprimé les cinq tailles
     particulières qui traînaient (44, 30, 52, 82 et 104 px). Le h1 de
     l'accroche reste plus grand : ce n'est pas un titre de section, c'est le
     titre de la page. */
  --t-h2:    clamp(30px, 3.5vw, 56px);
  --t-num:   clamp(52px, 8.4vw, 128px);
  --t-num-xl:clamp(72px, 15vw, 260px);

  /* Courbes */
  --sortie:  cubic-bezier(0.22, 1, 0.36, 1);
  --ressort: cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* L'environnement ENCRE a été retiré : plus aucune section n'est sombre. La
   rupture de la page est désormais portée par la carte de la section 06, en
   lavis, et par l'aplat bleu du tarif. */

/* Les environnements ENCRE et BLEU ont tous deux été retirés : plus aucune
   section n'est en aplat sombre. Les ruptures de la page sont maintenant les
   trois cartes en lavis — l'accroche, « Comment ça marche », « Où va l'argent »
   — et le liseré du tarif. */

/* ═══════════════════════════════════════════════════════════════════════════
   2 · SOCLE
   ═══════════════════════════════════════════════════════════════════════════ */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html {
  scroll-padding-top: calc(var(--entete-h) + var(--e6));
  -webkit-text-size-adjust: 100%;
}
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

/* Le fond de la page est BLANC, sans réserve. Le lavis n'est plus ici : il a
   été déplacé dans la carte du hero, seul endroit où il se voit désormais.
   Voir « LA CARTE DU HERO » plus bas. */
body {
  background: #FFFFFF;
  color: var(--texte);
  font-family: var(--f-mot);
  font-size: var(--t-corps);
  line-height: 1.6;
  letter-spacing: -0.005em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: clip;
}

::selection { background: var(--bleu); color: #FFFFFF; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: var(--rayon); }
img, svg { display: block; max-width: 100%; }

.evitement {
  position: fixed; z-index: 200;
  top: var(--e3); left: var(--e3);
  transform: translateY(-220%);
  background: var(--bleu); color: #FFFFFF;
  font-family: var(--f-etiq); font-size: var(--t-etiq);
  letter-spacing: 0.12em; text-transform: uppercase;
  padding: var(--e3) var(--e4);
  border-radius: var(--rayon);
  text-decoration: none;
  transition: transform 0.24s var(--sortie);
}
.evitement:focus { transform: translateY(0); }

/* ═══════════════════════════════════════════════════════════════════════════
   4 · EN-TÊTE — le logo de marque, à sa taille juste
   ═══════════════════════════════════════════════════════════════════════════ */
/* ── L'EN-TÊTE : UNE ÎLE FLOTTANTE ───────────────────────────────────────
   ELLE FAISAIT 1 408 px DE LARGE POUR TROIS ÉLÉMENTS — un logotype, un lien, un
   bouton — soit environ mille pixels de vide au milieu. C'est le défaut signalé, et
   la réponse est le motif que les barres de navigation ont adopté en 2026 : une île
   qui ne fait que la largeur de son contenu, posée au centre, en verre dépoli.

   DEUX ÉLÉMENTS, DEUX RÔLES. La bande fixe reste, mais transparente : elle ne sert
   plus qu'à RÉSERVER LA HAUTEUR. C'est de cette hauteur que dépendent le
   `scroll-padding-top` du document, le point de collage des trois cartes de la
   section 04 et le décalage du champ collant : toucher `--entete-h` aurait obligé à
   reprendre les trois d'un coup. L'île, à l'intérieur, porte le verre et mesure
   56 px — elle respire donc dans une bande de 68 sans que rien d'autre bouge.

   `pointer-events` : la bande n'en capte aucun, l'île les capte tous. Sans cela, une
   barre transparente de 1 408 px sur 68 aurait continué d'intercepter les clics sur
   toute la largeur du haut de page, y compris là où il n'y a rien.

   ELLE EST CENTRÉE, et c'est le seul endroit du site qui échappe à la gouttière.
   C'est assumé : une île n'est pas du contenu de page, c'est un objet posé dessus.
   Le logotype ne tombe donc plus sur la verticale commune, mais l'alternative était
   de garder une barre vide sur mille pixels.
   ──────────────────────────────────────────────────────────────────────── */
.entete {
  position: fixed;
  top: var(--marge-carte); left: var(--marge-carte); right: var(--marge-carte);
  height: var(--entete-h);
  z-index: 85;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.entete-ile {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: var(--e6);
  /* Asymétrique : le logotype a besoin d'air à gauche, le bouton porte le sien à
     droite. Un padding égal aurait laissé 24 px de blanc entre le bouton et le bord
     de l'île. */
  padding: var(--e2) var(--e2) var(--e2) var(--e5);
  border-radius: var(--rayon-plein);
  background: rgba(255, 255, 255, 0.68);
  -webkit-backdrop-filter: saturate(160%) blur(18px);
          backdrop-filter: saturate(160%) blur(18px);
  /* Le liseré est un ombrage à zéro flou, pas une bordure : il n'entre pas dans la
     boîte et ne décale donc pas le contenu d'un pixel. */
  box-shadow: 0 0 0 1px rgba(38, 52, 120, 0.06),
              0 1px 2px rgba(38, 52, 120, 0.04),
              0 14px 30px -18px rgba(38, 52, 120, 0.26);
  transition: box-shadow 0.4s var(--sortie);
}
/* AU DÉFILEMENT, L'ÎLE SE DÉTACHE UN PEU PLUS. Avant, c'était le verre lui-même qui
   apparaissait au défilement ; une île sans matière en haut de page n'aurait été
   qu'un logotype et un bouton flottant dans le vide. Elle a donc son verre dès le
   départ, et c'est son OMBRE qui s'allonge quand la page bouge sous elle. */
.entete.est-posee .entete-ile {
  box-shadow: 0 0 0 1px rgba(38, 52, 120, 0.07),
              0 2px 4px rgba(38, 52, 120, 0.05),
              0 22px 44px -22px rgba(38, 52, 120, 0.34);
}

.entete-marque { display: flex; align-items: center; flex: none; }
.entete-marque img { height: 22px; width: auto; }

.entete-nav { display: flex; align-items: center; gap: var(--e5); flex: none; }
.entete-client {
  font-size: 14px; font-weight: 500;
  color: var(--texte-2);
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.2s var(--sortie);
}
.entete-client:hover { color: var(--texte); }
.entete-client:focus-visible { outline: 2px solid var(--bleu); outline-offset: 3px; border-radius: var(--e1); }

@media (max-width: 719px) {
  /* L'île se resserre et perd l'accès client : sur 430 px de large, trois éléments
     dans une capsule la ramèneraient à la pleine largeur, ce qui annulerait tout. */
  .entete-ile { gap: var(--e4); padding-left: var(--e4); }
  .entete-client { display: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   5 · GRILLE ET SECTIONS
   ═══════════════════════════════════════════════════════════════════════════ */
.section {
  position: relative;
  background: var(--fond);
  color: var(--texte);
  padding: var(--pas-section) 0;
}
/* Aucun filet entre les sections : c'est l'air qui les sépare, et le
   changement d'environnement (lavis, encre, bleu) qui marque les ruptures. */

.corps {
  width: 100%;
  max-width: var(--largeur-max);
  margin: 0 auto;
  padding: 0 var(--gouttiere);
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--e5);
  row-gap: var(--e7);
}

/* ═══════════════════════════════════════════════════════════════════════════
   6 · TYPOGRAPHIE
   ═══════════════════════════════════════════════════════════════════════════ */
.titre {
  font-family: var(--f-titre);
  font-weight: 900;
  font-size: var(--t-h2);
  line-height: 0.95;
  letter-spacing: -0.036em;
  text-wrap: balance;
}

/* ── LE MOT-CLÉ : LE DÉGRADÉ DE MARQUE, PEINT DANS LE TEXTE ─────────────────
   UN SEUL dispositif, une seule règle, pour tous les titres de la page. Chaque
   titre de section a son mot-clé peint dans le dégradé du logo : « déjà » pour
   les clients, « relevé », « ça marche », « son dernier ticket », « l'argent »,
   « votre dossier », et la ligne « Zéro commission » de l'accroche. Aucun mot
   n'a été ajouté à la page : la couleur porte l'accent, pas une étiquette.

   Il existait en trois exemplaires, écrits deux fois : ils sont factorisés ici.

   `color` reste déclaré : c'est le repli des navigateurs qui ne savent pas
   découper un fond dans du texte. */
.mot-cle {
  color: var(--bleu);
  background-image: var(--degrade-marque);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}
/* Contrastes forcés et impression : on revient à un aplat, sinon le texte
   disparaît (le fond n'est pas imprimé, la couleur de remplissage l'est). */
@media (forced-colors: active), print {
  .mot-cle {
    background-image: none;
    -webkit-text-fill-color: currentColor;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   7 · COMPOSANTS
   ═══════════════════════════════════════════════════════════════════════════ */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--e3);
  font-family: var(--f-mot);
  font-size: 15px;
  font-weight: 600;
  line-height: 1;
  padding: var(--e4) var(--e6);
  border: 1px solid transparent;
  border-radius: var(--rayon-plein);
  text-decoration: none;
  cursor: pointer;
  overflow: hidden;
  transition: background-color 0.24s var(--sortie), color 0.24s var(--sortie),
              border-color 0.24s var(--sortie), transform 0.16s var(--sortie),
              box-shadow 0.24s var(--sortie);
}
/* L'ENFONCEMENT. Un bouton doit répondre au doigt avant de répondre au clic :
   3 % de retrait, 160 ms, et l'interface a l'air d'écouter. C'est le seul
   endroit du site où l'on met à l'échelle un élément d'interface. */
.btn:active { transform: scale(0.97); }
/* LE FOCUS CLAVIER. Il n'y en avait aucun : un visiteur au clavier n'avait que
   le contour par défaut du navigateur, qui ne suit ni le rayon du bouton ni la
   palette. Même procédé que les choix de métier du formulaire. */
.btn:focus-visible { outline: 2px solid var(--bleu); outline-offset: 3px; }
.btn::before {
  content: '';
  position: absolute; inset: 0;
  background: currentColor;
  opacity: 0.12;
  clip-path: inset(0 100% 0 0);
  transition: clip-path 0.42s var(--sortie);
}
.btn:hover::before { clip-path: inset(0 0 0 0); }
.btn > * { position: relative; }
.btn:disabled { opacity: 0.5; cursor: default; }

/* ── L'APPEL À L'ACTION PLEIN ─────────────────────────────────────────────
   IL ÉTAIT UN APLAT, SANS RELIEF NI OMBRE. Mesuré : `box-shadow: none` sur les
   six boutons de la page. Sur une page qui, partout ailleurs, pose ses objets
   avec une ombre et un liseré, le bouton le plus important était le seul élément
   parfaitement plat.

   Trois couches, et une seule idée : l'ombre est TEINTÉE de la couleur du bouton,
   pas noire. Une ombre noire sous un aplat bleu grise le bleu ; une ombre bleue le
   pose sans le salir. C'est la règle que la page suit déjà pour ses cartes.
     · un liseré clair en haut, dans la boîte : la lumière vient du haut ;
     · une ombre de contact courte, qui pose le bouton ;
     · une ombre longue et basse, qui le décolle de la page.
   ──────────────────────────────────────────────────────────────────────── */
.btn-plein {
  background: var(--accent-fort);
  color: var(--accent-texte);
  border-color: var(--accent-fort);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.22) inset,
              0 2px 4px -2px rgba(38, 52, 120, 0.28),
              0 12px 24px -12px rgba(69, 95, 253, 0.55);
}
/* AU SURVOL, IL SE SOULÈVE D'UN PIXEL et son ombre s'allonge. Un pixel, pas
   quatre : au-delà, le bouton saute au lieu de répondre. Le balayage clair de
   `.btn::before` reste, c'est la signature du site. */
@media (hover: hover) and (pointer: fine) {
  .btn-plein:hover {
    transform: translateY(-1px);
    box-shadow: 0 1px 0 rgba(255, 255, 255, 0.28) inset,
                0 3px 6px -3px rgba(38, 52, 120, 0.3),
                0 18px 34px -14px rgba(69, 95, 253, 0.62);
  }
}
/* À L'APPUI, l'inverse exact : il redescend, s'enfonce, et son ombre se referme.
   La règle vient après le survol pour gagner à spécificité égale. */
.btn-plein:active {
  transform: scale(0.97);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.18) inset,
              0 1px 2px rgba(38, 52, 120, 0.3);
}
.btn-grand { padding: 20px var(--e7); font-size: 16px; }
.btn-entete { padding: var(--e3) var(--e5); font-size: 14px; }

.fleche { display: inline-block; transition: transform 0.34s var(--sortie); }
.btn:hover .fleche, .lien:hover .fleche { transform: translateX(4px); }

.lien {
  display: inline-flex; align-items: center; gap: var(--e2);
  color: var(--texte);
  font-weight: 600;
  font-size: 15px;
  text-decoration: none;
  padding-bottom: 3px;
  background-image: linear-gradient(var(--accent), var(--accent));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 1px;
  transition: background-size 0.4s var(--sortie), color 0.24s var(--sortie);
}
.lien:hover { color: var(--accent); background-size: 100% 1px; }

/* Les pilules « Vérifié » et « API SMSPay » ont été retirées de la page : une
   étiquette encadrée qui ne dit rien de vérifiable est un ornement, et une
   page qui en accumule ressemble à toutes les autres. Seul reste le point du
   tampon « Reçu », qui confirme un envoi réel. */
.jeton-point::before {
  content: '';
  width: 5px; height: 5px; border-radius: 50%;
  background: currentColor;
  flex: none;
}

/* ═══════════════════════════════════════════════════════════════════════════
   8 · SYSTÈME D'ANIMATION
   Aucun fondu, aucun glissement : balayage clip-path, comme une tête
   d'impression. Composé par le GPU.
   ═══════════════════════════════════════════════════════════════════════════ */
.js [data-rev] {
  clip-path: inset(0 0 100% 0);
  opacity: 0.001;
  transform: scale(0.985);
  transform-origin: left bottom;
}
.js [data-rev].est-visible {
  /* Les insets sont NÉGATIFS à l'arrivée, donc le masque finit hors de la boîte.
     Deux raisons, dans l'ordre où elles ont été découvertes :

       · SATOSHI DESCEND BAS. Un inset à 0 coupait la jambe des « g » et des « p »
         des titres. C'est ce qui a motivé les premières valeurs, en em, calées sur
         un jambage : -0,14 / -0,06 / -0,42 / -0,06.

       · LES OMBRES DES BOUTONS SONT PLUS LONGUES QU'UN JAMBAGE. Mesuré : l'ombre
         d'un appel à l'action porte 24 px sous sa boîte, alors que -0,42 em ne
         faisait que 7,6 px sur `.hero-actions`. Le masque coupait donc l'ombre net,
         et un aplat bleu dont l'ombre s'arrête à la règle a l'air faux — c'était
         exactement le défaut signalé. Un jambage se mesure en em, une ombre en
         pixels : les valeurs sont donc données en PIXELS, et généreusement.

     Ce que ces marges autorisent : 56 px sous la boîte, 48 px de chaque côté,
     12 px au-dessus. Toutes les ombres du site tiennent dedans, la plus longue
     portant 34 px. Élargir un masque ne peut rien casser : il ne fait que découper
     moins. */
  clip-path: inset(-12px -48px -56px -48px);
  opacity: 1;
  transform: scale(1);
  transition:
    clip-path 0.9s var(--sortie) calc(var(--d, 0) * 75ms),
    opacity   0.5s linear        calc(var(--d, 0) * 75ms),
    transform 0.9s var(--sortie) calc(var(--d, 0) * 75ms);
}
.js [data-pose] { opacity: 0.001; transform: scale(1.09); }
.js [data-pose].est-visible {
  opacity: 1; transform: scale(1);
  transition:
    transform 0.82s var(--ressort) calc(var(--d, 0) * 85ms),
    opacity   0.34s linear         calc(var(--d, 0) * 85ms);
}

/* ═══════════════════════════════════════════════════════════════════════════
   9 · 01 · HERO — BLOC DE TITRE ET SCÈNE
   ---------------------------------------------------------------------------
   Deux objets : le TITRE à gauche, la SCÈNE à droite — le SMS dans sa bulle,
   ses deux confirmations, et l'anneau du logo derrière.

   La photo du téléphone a été retirée. Le hero ne montre donc plus le produit
   par une capture, il montre le MESSAGE, qui est ce que le client reçoit
   vraiment. Conséquence sur la composition : la droite n'est plus un champ
   plein bord à bord mais un objet posé dans l'air, et c'est l'anneau qui
   l'empêche de flotter.
   ═══════════════════════════════════════════════════════════════════════════ */
/* ── LA CARTE DU HERO ────────────────────────────────────────────────────
   Le premier écran n'est pas une bande pleine largeur : c'est une CARTE aux
   bords arrondis, posée sur le blanc de la page, qui porte le lavis. Tout ce
   qui suit est blanc, donc le dégradé ne se voit qu'ici.

   Le lavis n'est plus fixe : il appartient à la carte et se déplace avec elle.
   Quatre couches, de la plus haute à la plus basse : le grain de film, le bleu
   du logo en haut à gauche, le cyan en bas à droite, la soie à 150°.
   ──────────────────────────────────────────────────────────────────────── */
.hero {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 48%);
  align-items: center;
  column-gap: var(--e7);
  overflow: clip;

  margin: var(--marge-carte);
  border-radius: var(--rayon-carte);
  min-height: calc(100svh - var(--marge-carte) * 2);

  /* Le contenu retombe sur la gouttière commune, marge de carte déduite. */
  padding: var(--entete-h) calc(var(--gouttiere) - var(--marge-carte)) 0;

  background-color: var(--lavis-brume);
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.1'/%3E%3C/svg%3E"),
    radial-gradient(88% 74% at 4% -6%, rgba(69, 95, 253, 0.16) 0%, rgba(69, 95, 253, 0) 60%),
    radial-gradient(76% 66% at 100% 104%, rgba(32, 202, 226, 0.20) 0%, rgba(32, 202, 226, 0) 62%),
    radial-gradient(38% 40% at 99% 0%, rgba(247, 236, 218, 0.62) 0%, rgba(247, 236, 218, 0) 62%),
    linear-gradient(150deg,
      var(--lavis-brume) 0%,
      var(--lavis-ciel)  34%,
      var(--lavis-eau)   68%,
      var(--lavis-creme) 100%);
  background-size: 120px 120px, auto, auto, auto, auto;
  background-repeat: repeat, no-repeat, no-repeat, no-repeat, no-repeat;
  background-blend-mode: overlay, normal, normal, normal, normal;
  /* INDISPENSABLE : par défaut les dégradés démarrent à la boîte de padding,
     donc sous les 68 px réservés à l'en-tête, et une bande plate apparaissait
     en haut de la carte. Ils doivent partir du bord. */
  background-origin: border-box;
}

/* ── Le bloc de titre ───────────────────────────────────────────────────── */
.hero-champ {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: var(--e9) 0;
  min-width: 0;
}

/* La pastille de preuve : trois faits, un point qui bat. Elle occupe la place
   de la note d'avis du modèle, qu'on ne peut pas prouver. */
.hero-preuve {
  display: inline-flex; align-items: center; gap: var(--e3);
  align-self: flex-start;
  font-size: 13px;
  font-weight: 500;
  color: var(--texte-2);
  background: rgba(255, 255, 255, 0.72);
  border-radius: var(--rayon-plein);
  padding: 8px var(--e5) 8px var(--e4);
  margin-bottom: var(--e6);
}
.hero-preuve-point {
  flex: none;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--accent-fort);
  box-shadow: 0 0 0 4px rgba(69, 95, 253, 0.16);
}

.hero-titre {
  margin-bottom: var(--e6);
  font-family: var(--f-titre);
  font-weight: 900;
  /* UN seul corps pour les trois lignes. */
  font-size: clamp(40px, 4.9vw, 80px);
  line-height: 1.0;
  letter-spacing: -0.034em;
  max-width: 15ch;
}
.hero-titre span { display: block; }
/* Le seul accent du hero : la ligne qui porte l'argument. */
/* La seule particularité de la ligne de l'accroche : elle est un BLOC pleine
   largeur, sa boîte doit donc épouser les mots, sinon le dégradé s'étale bien
   au-delà du texte et celui-ci n'en reçoit que la première moitié. Les autres
   mots-clés sont en ligne, leur boîte épouse le texte d'elle-même. */
.hero-ligne-accent { width: fit-content; }

.hero-texte { font-size: clamp(17px, 0.7vw + 15px, 21px); line-height: 1.5; color: var(--texte-2); max-width: 52ch; }
.hero-texte strong { color: var(--texte); font-weight: 600; }
.hero-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--e5) var(--e6); margin-top: var(--e7); }

/* ═══════════════════════════════════════════════════════════════════════
   LA SCÈNE — ce que le client reçoit, sans photo et sans cadre
   -----------------------------------------------------------------------
   La capture du téléphone est partie. Ce qui tient maintenant la droite du
   hero n'est pas une image de la chose, c'est la chose : le SMS lui-même,
   dans une bulle qui s'écrit, et les deux confirmations qui s'y accrochent.
   Aucun angle droit dans ce bloc : une bulle, deux pastilles, un anneau.
   ═══════════════════════════════════════════════════════════════════════ */
.scene {
  position: relative;
  min-width: 0;
  align-self: stretch;
  display: flex;
  align-self: stretch;
  align-items: flex-start;
  justify-content: flex-start;
}
/* L'anneau : le zéro du logo, à l'échelle de la page, à peine visible. Il ne
   décore pas, il tient la composition — c'est lui qui empêche la moitié
   droite de flotter maintenant que la photo n'y est plus. */
.scene-anneau {
  position: absolute;
  z-index: -1;
  top: 46%; left: 52%;
  width: min(52vw, 560px);
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border: 1px solid var(--trait-fort);
  border-radius: 50%;
  opacity: 0.5;
  pointer-events: none;
}

/* ════════════════════════════════════════════════════════════════════════
   L'APPAREIL — dessiné, pas photographié
   ------------------------------------------------------------------------
   Aucune image : un cadre, un écran, et de vrais éléments de texte. On peut
   donc lire « 340,00 € » et « Par SMS » à n'importe quelle taille d'écran,
   et l'écran suit la palette du logo sans retouche.

   L'appareil est ancré en BAS et déborde du hero, qui le coupe proprement
   (overflow: clip). C'est ce débord qui donne au hero sa profondeur.
   ════════════════════════════════════════════════════════════════════════ */
.mobile {
  position: relative;
  z-index: 1;
  /* HORS DU FLUX. C'est la seule façon de le laisser dépasser du bas de la
     carte sans l'étirer : dans le flux, sa hauteur devenait la hauteur du
     hero, qui cessait de tenir dans l'écran.
     Le débord est produit par la réserve de padding au bas de l'écran (voir
     .mobile-ecran), donc ce que la carte rogne est toujours du vide, jamais
     une ligne de l'interface. */
  position: absolute;
  top: var(--e8); left: 0;
  width: min(100%, 444px);
  margin-bottom: 0;
}
.mobile-corps {
  position: relative;
  border-radius: 54px;
  padding: var(--e3);
  background: linear-gradient(160deg, #2B2F45 0%, #14161F 52%, #2B2F45 100%);
  box-shadow: 0 50px 90px -50px rgba(28, 36, 78, 0.55),
              0 8px 22px -12px rgba(28, 36, 78, 0.35);
}
/* L'île, en haut de l'écran. */
.mobile-ile {
  position: absolute;
  z-index: 2;
  top: var(--e5); left: 50%;
  transform: translateX(-50%);
  width: 96px; height: var(--e5);
  border-radius: var(--rayon-plein);
  background: #0B0C11;
}
.mobile-ecran {
  position: relative;
  border-radius: 42px;
  background: #FFFFFF;
  padding: var(--e5) var(--e5) var(--e10);
  min-height: 0;
  overflow: hidden;
}

.ecran-barre {
  display: flex; align-items: center; justify-content: space-between;
  font-family: var(--f-etiq);
  font-size: 11px; font-weight: 500;
  color: var(--encre);
  padding: 0 var(--e2) var(--e5);
}
.ecran-signaux { display: inline-flex; align-items: flex-end; gap: 2px; }
/* Trois barres de réseau et une pile : des formes, pas une police d'icônes. */
.ecran-onde { width: 3px; border-radius: 1px; background: var(--encre); }
.ecran-onde:nth-child(1) { height: 5px; }
.ecran-onde:nth-child(2) { height: 8px; }
.ecran-onde:nth-child(3) { height: 11px; }
.ecran-pile {
  width: 20px; height: 10px;
  margin-left: 5px;
  border: 1px solid var(--encre);
  border-radius: 3px;
  position: relative;
}
.ecran-pile::before {
  content: '';
  position: absolute; inset: 2px;
  right: 6px;
  border-radius: 1px;
  background: var(--encre);
}

.ecran-chapitre {
  font-family: var(--f-titre);
  font-weight: 900;
  font-size: 26px;
  letter-spacing: -0.026em;
  color: var(--encre);
  margin-bottom: var(--e6);
}
.ecran-libelle {
  font-size: 14px;
  font-weight: 500;
  color: #7C8194;
  margin-bottom: var(--e2);
}
.ecran-libelle-choix { margin: var(--e4) 0 var(--e3); }

/* Le montant : c'est LE chiffre de l'écran, il porte le dégradé de marque. */
.ecran-somme {
  background: #F4F6FD;
  border-radius: var(--rayon);
  padding: var(--e5) var(--e5) var(--e6);
}
.ecran-montant {
  font-family: var(--f-chiffre);
  font-weight: 900;
  font-size: 44px;
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--bleu);
  font-variant-numeric: tabular-nums;
}

.ecran-choix { list-style: none; display: grid; gap: var(--e3); }
.ecran-choix li {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--e3);
  font-size: 15px;
  font-weight: 500;
  color: #5B6076;
  background: #F4F6FD;
  border-radius: var(--rayon);
  padding: var(--e5) var(--e4);
}
/* Le choix retenu, en aplat de marque : c'est la ligne qui raconte le produit. */
.ecran-choix .est-choisi {
  color: #FFFFFF;
  font-weight: 600;
  background: var(--bleu);
}
.ecran-coche {
  flex: none;
  width: 17px; height: 17px;
  border-radius: 50%;
  background: #FFFFFF;
  position: relative;
}
.ecran-coche::before {
  content: '';
  position: absolute;
  left: 5px; top: 4px;
  width: 4px; height: 8px;
  border: 2px solid var(--bleu);
  border-top: 0; border-left: 0;
  transform: rotate(42deg);
}

.ecran-bouton {
  margin-top: var(--e6);
  text-align: center;
  font-size: 16px; font-weight: 600;
  color: #FFFFFF;
  background: var(--encre);
  border-radius: var(--rayon-plein);
  padding: var(--e5);
}

.bulle {
  position: absolute;
  z-index: 2;
  /* Le message est à DROITE de l'appareil : son bord droit tombe sur la
     gouttière de la page, comme le texte du hero, et il mord le flanc droit
     de l'appareil. Tout ce que l'écran doit dire est aligné à gauche, donc
     rien d'important ne passe dessous. */
  right: 0; bottom: var(--e8);
  width: max(224px, calc(100% - 388px));
  background: #FFFFFF;
  border-radius: var(--rayon-grand) var(--rayon-grand) var(--rayon-grand) var(--e2);
  padding: var(--e4) var(--e5) var(--e5);
  box-shadow: 0 22px 50px -26px rgba(38, 52, 120, 0.42);
}
/* La pointe de la bulle, en bas à gauche : c'est elle qui dit « message reçu »
   sans qu'on ait besoin de dessiner un téléphone autour. */
.bulle::after {
  content: '';
  position: absolute;
  left: 0; bottom: -9px;
  width: 18px; height: 18px;
  background: #FFFFFF;
  clip-path: path('M0 0 C0 10 6 16 18 18 C6 14 2 8 0 0 Z');
}
.bulle-de {
  font-size: 13px;
  font-weight: 600;
  color: var(--accent);
  margin-bottom: var(--e2);
}
.bulle-texte {
  font-size: 15px;
  line-height: 1.5;
  letter-spacing: -0.01em;
  color: var(--texte);
  min-height: 4.5em;
}

/* Les deux confirmations, sous le message, dans la même bulle. */
.scene-etats {
  display: flex; flex-direction: column; align-items: flex-start;
  gap: var(--e2);
  margin-top: var(--e4);
}
.curseur {
  display: inline-block;
  width: 2px; height: 0.92em;
  background: var(--bleu);
  vertical-align: -0.1em;
  margin-left: 3px;
  animation: clignote 1.1s steps(2, jump-none) infinite;
}
@keyframes clignote { 50% { opacity: 0; } }

/* Les deux états deviennent des PASTILLES qui s'inscrivent l'une après
   l'autre. L'ancienne version les alignait sous une conduite verticale, avec
   un filet et deux anneaux : trois traits pour dire ce qu'un point coloré dit
   mieux. */
.scene-etats::before { content: none; }

.etat {
  position: relative;
  display: inline-flex; align-items: center; gap: var(--e2);
  font-size: 13px;
  font-weight: 500;
  color: var(--texte-2);
  background: rgba(255, 255, 255, 0.72);
  border-radius: var(--rayon-plein);
  padding: var(--e2) var(--e4) var(--e2) var(--e3);
  white-space: nowrap;
  opacity: 0;
  transform: translate3d(0, 6px, 0);
  transition: opacity 0.45s var(--sortie), transform 0.5s var(--sortie);
}
.etat.est-inscrit { opacity: 1; transform: translate3d(0, 0, 0); }
.etat::before {
  content: '';
  flex: none;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--trait-fort);
}
.etat-conf { color: var(--accent); font-weight: 600; }
.etat-conf::before { background: var(--accent-fort); }
/* ═══════════════════════════════════════════════════════════════════════════
   10 · 02 · ILS ENCAISSENT DÉJÀ — dispositif « la bande de logos »
   ---------------------------------------------------------------------------
   Titre centré, seul. La bande passe dessous, de bord à bord, et déborde
   volontairement des gouttières : c'est la seule section de la page dans ce cas.

   Le pas vertical est réduit de moitié par rapport aux autres sections, et
   resserré en haut pour qu'elle suive le hero de près : cette bande n'est pas un
   chapitre, elle atteste. On lit la promesse dans le hero, on voit tout de suite
   qui la tient déjà, puis on entre dans le détail.

   POURQUOI TROIS PISTES ET NON DEUX. La translation ne fait que -100 % d'une
   piste : au retour, la suivante est exactement là où était la précédente, donc
   la boucle est invisible. Mais une piste ne fait que 1 322 px, moins qu'un
   écran de bureau : avec deux pistes, le contenu total (2 644 px) ne couvrait
   plus que 1 322 px en fin de cycle et un trou de plus de cent pixels
   apparaissait au bord droit. Le défilement paraissait donc s'interrompre. Il
   faut assez de matière pour couvrir l'écran ENTIER pendant tout le cycle, d'où
   la troisième. Une seule transform, aucun recalcul de mise en page.

   TOUS LES LOGOS À LA MÊME ÉCHELLE VISUELLE. Attention, ce n'est pas la même
   hauteur en pixels : les rapports vont de 1:1 (3J, Flash, AACE) à 5,5:1 (Roy
   Automobiles). À hauteur rigoureusement égale, un carré de 42 px occupe huit
   fois moins de surface qu'un logotype long de 42 px de haut, et il paraît
   minuscule. Les quatre familles sont donc calées pour occuper la MÊME SURFACE
   à l'œil : entre 3 300 et 5 000 px² pour les six.
   ═══════════════════════════════════════════════════════════════════════════ */
/* ELLE SE RAPPROCHE DE CE QUI SUIT. Mesuré : le creux visuel entre cette bande et
   « Le relevé » valait 192 px, celui entre deux sections pleines 208. Sur le papier
   la bande était donc DÉJÀ la plus proche de sa voisine ; à l'œil c'était l'inverse,
   parce que cette section est BASSE et se termine par une bande de logos. Après un
   objet aussi court, 192 px de vide se lisent comme un trou, là où entre deux
   sections hautes ils se lisent comme un changement de chapitre. Sa marge basse
   tombe donc à 32 px : le creux passe à 128 px, et la bande s'attache à ce qu'elle
   annonce. C'est la seule section de la page qui n'a pas le pas commun en bas, et
   c'est assumé : elle atteste, elle n'argumente pas. */
.sec-bande { overflow: hidden; padding-bottom: var(--e6); }
.bande-tete { margin-bottom: var(--e7); }
/* Le seul titre centré de la page : la bande n'a pas de grille, son titre est
   donc posé sur son axe.
   C'est aussi le seul dont la TAILLE sort du système. Exception assumée : à la
   taille commune, il devenait l'élément le plus fort d'une section qui ne fait
   qu'attester, et il écrasait les logos qu'il est censé annoncer. */
.titre-bande {
  grid-column: 1 / -1;
  text-align: center;
  font-size: clamp(21px, 1.9vw, 28px);
  line-height: 1.15;
}

.bande {
  display: flex;
  width: 100%;
  padding: var(--e5) 0;
  /* Les logos s'effacent aux deux bords : la bande continue hors de l'écran au
     lieu d'y être coupée net. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
}
.bande-piste {
  display: flex;
  align-items: center;
  gap: var(--e10);
  flex: none;
  padding-right: var(--e10);
  animation: bande-defile 34s linear infinite;
  will-change: transform;
}
/* Aucune pause au survol : le défilement doit être continu, et une bande qui
   s'arrête sous le curseur donne exactement l'impression d'un blocage. */
@keyframes bande-defile {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-100%, 0, 0); }
}

.bande-logo {
  flex: none;
  /* Hauteur de référence : les marques dont le rapport est proche de 2:1. */
  height: 44px;
  width: auto;
  max-width: 210px;
  object-fit: contain;
  /* Les logos gardent LEURS couleurs. Une version en niveaux de gris a été
     essayée puis abandonnée : celui de Depann 2000, dont la palette est claire,
     devenait un fantôme illisible. Ils sont juste très légèrement retenus, et
     reprennent tout leur éclat au survol. */
  opacity: 0.88;
  transition: opacity 0.3s var(--sortie), transform 0.3s var(--sortie);
}
.bande-logo:hover { opacity: 1; transform: scale(1.04); }

/* Quatre familles, selon le rapport largeur/hauteur du fichier : les carrés et
   les ronds montent, les logotypes longs descendent. Depann 2000 a besoin d'un
   cran de plus que Roy Automobiles, sa signature manuscrite se perd. */
.bande-logo.logo-carre     { height: 58px; }   /* rapport ~1:1   */
.bande-logo.logo-long      { height: 36px; }   /* rapport ~3,9:1 */
.bande-logo.logo-tres-long { height: 28px; }   /* rapport ~5,5:1 */

@media (max-width: 899px) {
  .bande-logo { height: 34px; max-width: 160px; }
  .bande-logo.logo-carre     { height: 44px; }
  .bande-logo.logo-long      { height: 28px; }
  .bande-logo.logo-tres-long { height: 22px; }
  .bande-piste { gap: var(--e8); padding-right: var(--e8); }
}

/* ═══════════════════════════════════════════════════════════════════════════
   11 · 03 · LE RELEVÉ — quatre cartes en dégradé, en grand
   ---------------------------------------------------------------------------
   Le titre est posé au-dessus et la grille prend toute la largeur : les cartes
   font donc la moitié de la page chacune. Le titre en marge collante qui les
   accompagnait a été retiré, il les rétrécissait de quatre colonnes.

   LES CARTES. Le patron vient du composant fourni : un dégradé pâle, une
   pastille de catégorie avec son point, le chiffre en grand, sa phrase, et une
   illustration en volume qui déborde du coin inférieur droit.

   Quatre dégradés, tirés de la palette du site : le bleu du logo, son cyan, le
   crème du lavis, et un gris bleuté. Pas de cinquième teinte inventée. Les
   illustrations, elles, apportent leurs propres couleurs — c'est voulu, elles
   font l'accent chaud de la section.

   LE MOUVEMENT. Le composant d'origine utilise framer-motion. Ici, deux
   transitions sur transform suffisent : la carte se soulève de 4 px, son
   illustration grandit de 6 % et pivote de 3°. Composé par le GPU, aucune
   dépendance ajoutée.
   ═══════════════════════════════════════════════════════════════════════════ */
.tete-releve { grid-column: 1 / span 8; }
.tete-note {
  margin-top: var(--e5);
  font-size: var(--t-corps);
  line-height: 1.5;
  color: var(--texte-2);
  max-width: 48ch;
}

.releve {
  grid-column: 1 / -1;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--e6);
}

.carte {
  position: relative;
  overflow: hidden;
  min-height: 320px;
  padding: var(--e7);
  border-radius: var(--rayon-grand);
  display: flex;
  flex-direction: column;
  transition: transform 0.4s var(--sortie), box-shadow 0.4s var(--sortie);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.7) inset;
}
.carte:hover {
  transform: translateY(-4px);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.7) inset,
              0 28px 50px -34px rgba(38, 52, 120, 0.5);
}
/* Les quatre dégradés. L'illustration de chaque carte lui répond : le
   portefeuille brun sur le crème, la bulle bleue sur le bleu, et les deux
   rouges sur les teintes froides, où ils font l'accent. */
.carte-1 { background: linear-gradient(150deg, #F8F2E8 0%, #F1E6D5 100%); }
.carte-2 { background: linear-gradient(150deg, #ECEFFE 0%, #D8E0FC 100%); }
.carte-3 { background: linear-gradient(150deg, #E7F5F8 0%, #D2EBF1 100%); }
.carte-4 { background: linear-gradient(150deg, #F0F2F7 0%, #E0E5EE 100%); }

/* L'illustration déborde du coin, et ne réagit qu'au survol de sa carte. */
.carte-illu {
  position: absolute;
  z-index: 0;
  right: -14%; bottom: -16%;
  width: 54%;
  height: auto;
  pointer-events: none;
  transform-origin: center;
  transition: transform 0.5s var(--sortie);
}
.carte:hover .carte-illu { transform: scale(1.06) rotate(3deg); }

/* La pastille de catégorie : verre dépoli sur le dégradé, comme dans le
   composant d'origine, avec le point de la carte. */
.carte-badge {
  position: relative;
  z-index: 1;
  align-self: flex-start;
  display: inline-flex; align-items: center; gap: var(--e2);
  font-size: 13px;
  font-weight: 500;
  color: var(--texte-2);
  background: rgba(255, 255, 255, 0.62);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  border-radius: var(--rayon-plein);
  padding: 6px var(--e4) 6px var(--e3);
  margin-bottom: var(--e6);
}
.carte-point {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--accent-fort);
}
.carte-1 .carte-point { background: #C08A3E; }
.carte-3 .carte-point { background: var(--cyan-profond); }
.carte-4 .carte-point { background: #7B8194; }

/* Le chiffre : c'est lui l'argument, il prend la place du titre du composant. */
.carte-chiffre {
  position: relative;
  z-index: 1;
  font-family: var(--f-chiffre);
  font-weight: 900;
  font-size: clamp(38px, 3.4vw, 54px);
  line-height: 0.9;
  letter-spacing: -0.045em;
  color: var(--texte);
  font-variant-numeric: tabular-nums;
  margin-bottom: var(--e4);
}
.carte-texte {
  position: relative;
  z-index: 1;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.45;
  color: var(--texte);
  max-width: 27ch;
}
/* La note prend la place de l'appel à l'action du composant : quatre liens
   identiques n'auraient mené nulle part, une précision, elle, dit quelque
   chose. Elle se cale en bas de la carte, comme le lien d'origine. */
.carte-note {
  position: relative;
  z-index: 1;
  margin-top: auto;
  padding-top: var(--e5);
  font-size: 13px;
  line-height: 1.5;
  color: var(--texte-2);
  max-width: 30ch;
}

@media (max-width: 1023px) {
  .releve { grid-column: 1 / -1; }
}
@media (max-width: 719px) {
  .releve { grid-template-columns: 1fr; }
  .carte { min-height: 0; padding: var(--e5); }
  /* Plus petite et plus dans l'angle : sur une seule colonne, l'illustration
     mordait sur le texte. Les colonnes de texte se resserrent avec elle. */
  .carte-illu { width: 38%; right: -11%; bottom: -13%; }
  .carte-texte { max-width: 24ch; }
  .carte-note { max-width: 26ch; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   12 · 04 · COMMENT ÇA MARCHE — la pile qui se referme
   ---------------------------------------------------------------------------
   Une carte en lavis, comme l'accroche et comme la section 06 : les trois
   cartes de la page se répondent d'un bout à l'autre de la lecture.

   LA PILE. Les trois étapes sont en position COLLANTE, toutes au MÊME
   décalage. Conséquence directe : la deuxième monte, atteint ce décalage et se
   cale exactement sur la première, qu'elle recouvre ; puis la troisième sur la
   deuxième. On passe de trois cartes visibles à deux, puis à une.

   Pourquoi la position collante et pas du JavaScript : elle est RÉVERSIBLE par
   construction. Le navigateur recalcule la position à chaque image dans les
   deux sens, donc l'effet se rejoue à l'identique quand on remonte, sans
   écouteur, sans mesure, sans risque de désynchronisation.

   Deux conditions pour que ça marche, faciles à casser plus tard :
     · les cartes doivent être OPAQUES, sinon on verrait à travers la pile ;
     · aucun ancêtre ne doit porter overflow: hidden, auto ou scroll — cela
       ferait de lui le conteneur de défilement de référence, et la position
       collante n'aurait plus rien à quoi s'accrocher. Cette section n'en a
       donc pas, contrairement à l'accroche.

   UNE SCÈNE A VÉCU ICI, du 3 août au 3 août : un panneau blanc collant dans la
   colonne de gauche, qui jouait l'étape en cours — l'interface, puis le SMS du
   client, puis l'encaissement. Retirée sur demande, avec tout son contenu. Ce
   qu'elle laisse et qu'il faut garder : la colonne du titre est passée de cinq à
   six colonnes sur douze, les cartes de 601 à 497 px de large et de 270 à
   217 px de haut, leur texte de 44 à 52 caractères de mesure, leur padding de
   48 à 32, et l'écart entre deux cartes de 96 à 128 px pour que la course d'une
   étape reste à 345 px.
   ═══════════════════════════════════════════════════════════════════════════ */
.sec-marche {
  margin: var(--marge-carte);
  padding: var(--pas-section) 0;
  /* Ni fond, ni rayon, ni transformation : tout cela est passé dans le calque
     .marche-fond. Cette boîte-ci ne fait plus que tenir la mise en page, ce qui
     est la condition pour que les cartes collantes soient stables au pixel. */
}

/* ── LE CALQUE DE FOND ────────────────────────────────────────────────────
   Il porte le lavis, le rayon et le rétrécissement au défilement. Il se découpe
   lui-même (overflow), ce que la section ne peut pas faire : un overflow sur
   elle casserait la position collante de la pile.

   LA PHOTO DE BUREAU A ÉTÉ RETIRÉE D'ICI. Elle n'existait que pour occuper le
   vide de la colonne de gauche, vide que la scène occupe désormais — et elle
   montrait un téléphone posé sur un bureau, à 40 px d'un écran de téléphone
   dessiné : deux appareils dans la même carte, dont un muet. Le fichier reste
   dans assets/illustrations/bureau.webp, la remettre est une règle de six
   lignes.
   ──────────────────────────────────────────────────────────────────────── */
.marche-fond {
  position: absolute;
  z-index: 0;
  inset: 0;
  border-radius: var(--rayon-carte);
  overflow: hidden;
  pointer-events: none;

  background-color: var(--lavis-brume);
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.1'/%3E%3C/svg%3E"),
    /* Ce halo-ci est posé SOUS LA CARTE EN VERRE du champ de gauche : sans lui,
       le verre n'a qu'un aplat pâle à réfracter et il ne se voit pas. Il ne se
       remarque pas non plus tout seul, et c'est voulu. */
    radial-gradient(30% 26% at 26% 16%, rgba(69, 95, 253, 0.26) 0%, rgba(69, 95, 253, 0) 72%),
    radial-gradient(88% 74% at 4% -6%, rgba(69, 95, 253, 0.16) 0%, rgba(69, 95, 253, 0) 60%),
    radial-gradient(76% 66% at 100% 104%, rgba(32, 202, 226, 0.20) 0%, rgba(32, 202, 226, 0) 62%),
    radial-gradient(38% 40% at 99% 0%, rgba(247, 236, 218, 0.62) 0%, rgba(247, 236, 218, 0) 62%),
    linear-gradient(150deg,
      var(--lavis-brume) 0%,
      var(--lavis-ciel)  34%,
      var(--lavis-eau)   68%,
      var(--lavis-creme) 100%);
  background-size: 120px 120px, auto, auto, auto, auto, auto;
  background-repeat: repeat, no-repeat, no-repeat, no-repeat, no-repeat, no-repeat;
  background-blend-mode: overlay, normal, normal, normal, normal, normal;
  background-origin: border-box;
}

/* ── LA PHOTO DE FOND ────────────────────────────────────────────────────
   Une photo de bureau, téléphone posé, notification floutée. Elle occupe toute
   la largeur de la carte et ses deux tiers bas : c'est la moitié basse de la
   section qui se vide quand la pile a fini de se refermer, et c'est là que
   tombe le téléphone de la photo, dont la composition le met dans son propre
   tiers inférieur gauche. Le vide de sa moitié droite passe sous les cartes
   blanches, qui le couvrent : rien n'est perdu et rien ne gêne.

   ELLE NE TOUCHE JAMAIS UN TEXTE. Deux masques se croisent, l'un qui l'efface
   vers le haut, l'autre vers la droite : elle est franche dans l'angle et se
   dissout avant d'atteindre le titre, l'appel à l'action et la pile.

   Son angle reprend le rayon de la carte, car la section n'a pas de découpe :
   `overflow` y est interdit, il casserait la position collante de la pile.
   ──────────────────────────────────────────────────────────────────────── */
.marche-fond::before {
  content: '';
  position: absolute;
  z-index: 0;
  /* PLEINE LARGEUR, ET LA HAUTEUR DÉDUITE DU RAPPORT DE LA PHOTO. C'est le point
     à ne pas casser : la boîte garde exactement le rapport 21:9 de l'image, donc
     `cover` ne recadre jamais rien, à aucune largeur d'écran. Deux essais avant
     celui-là partaient d'une hauteur en pourcentage de la carte : à 72 % la
     boîte devenait trop carrée et le recadrage mangeait un quart de la largeur ;
     sur mobile, la même règle donnait une boîte presque verticale où il ne
     restait que le bord du bureau. */
  left: 0; right: 0; bottom: 0;
  aspect-ratio: 21 / 9;
  background: url('illustrations/bureau.webp') left bottom / cover no-repeat;
  border-radius: 0 0 var(--rayon-carte) var(--rayon-carte);
  /* DISCRÉTION : FUSION EN LUMINOSITÉ, pas seulement de l'opacité. L'opacité
     seule a été essayée à 42 % : la photo devenait laiteuse et grisâtre, et le
     téléphone perdait sa matière — un fond coloré vu à travers une image
     translucide délave l'image. En fusion « luminosité », la photo ne garde que
     ses valeurs et prend la COULEUR du lavis : elle devient une matière de la
     carte au lieu d'une image posée dessus, et le téléphone reste un objet.
     L'opacité ne sert plus qu'à régler l'intensité du relief. */
  opacity: 0.62;
  mix-blend-mode: luminosity;
  pointer-events: none;

  -webkit-mask-image:
    linear-gradient(to top, #000 26%, transparent 94%),
    linear-gradient(to right, #000 34%, transparent 96%);
          mask-image:
    linear-gradient(to top, #000 26%, transparent 94%),
    linear-gradient(to right, #000 34%, transparent 96%);
  -webkit-mask-composite: source-in;
          mask-composite: intersect;
}
@media (max-width: 899px) {
  /* Le rapport se garde tout seul ; il n'y a plus que l'intensité à retenir un
     peu, la photo étant proportionnellement plus présente sur une colonne. */
  .marche-fond::before { opacity: 0.85; }
}

/* Le contenu passe devant le calque et devant la photo, sans exception. */
.sec-marche .corps {
  padding: 0 calc(var(--gouttiere) - var(--marge-carte));
  position: relative;
  z-index: 1;
  align-items: start;
}

/* ── LA SECTION SE RÉTRÉCIT AU DÉFILEMENT ────────────────────────────────
   Plus on descend, plus la carte se resserre ; plus on remonte, plus elle se
   rouvre. C'est une ANIMATION PILOTÉE PAR LE DÉFILEMENT, native : sa ligne de
   temps n'est pas l'horloge mais la position de la section dans l'écran. Elle
   est donc réversible par construction, comme la pile, et elle tourne sur le
   compositeur — aucun écouteur de défilement, aucune ligne de JavaScript.

   ELLE PORTE SUR LE CALQUE DE FOND, ET SUR RIEN D'AUTRE. Elle portait d'abord
   sur la section entière : la boîte des cartes collantes était donc mise à
   l'échelle avec elle, et leur largeur variait de 32 px pendant l'empilement,
   en valeurs sous-pixel — c'était la cause des vibrations et des pertes
   d'alignement. Mesuré, puis corrigé.

   LA PLAGE, ET D'OÙ VIENNENT SES DEUX NOMBRES. Les plages nommées ne tombent
   pas juste : `contain` finit son retrait bien avant que la pile ait fini de se
   refermer, `exit` est deux fois trop lente. La plage est donc donnée en
   pourcentage de `cover`, qui couvre toute la traversée, de l'entrée par le bas
   à la sortie par le haut. Les deux repères sont RECALCULÉS à chaque fois que
   la course de la pile change, et ils l'ont été pour cette refonte :
     · début  = le moment où le haut de la section atteint le haut de l'écran,
                soit une hauteur d'écran de traversée ;
     · fin    = le moment où la dernière carte se cale.
   Le retrait commence donc quand on entre dans la section et s'achève quand la
   pile a fini de se refermer : les deux mouvements terminent ensemble. Mesuré,
   pas deviné, pour un écran d'environ 900 px de haut ; sur un écran plus court
   le retrait démarre un peu plus tard, sans rien casser.
   ──────────────────────────────────────────────────────────────────────── */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .marche-fond {
      animation: retrait-carte linear both;
      animation-timeline: view();
      /* 37,4 % = le haut de la section atteint le haut de l'écran (2 346 px de
         défilement) ; 71,2 % = la dernière carte se verrouille (3 160 px). La
         traversée complète vaut 2 407 px, soit la section (1 507) plus l'écran
         (900). Mesuré le 03/08. À REPRENDRE chaque fois que la course de la pile
         change : ces deux nombres en dépendent entièrement. */
      animation-range: cover 37% cover 71%;
      transform-origin: center center;
      will-change: transform;
    }
    /* Amplitude 3 %. À 7 %, le bord du calque rentrait de 49 px et venait
       mordre sur le contenu, qui ne bouge plus avec lui. */
    @keyframes retrait-carte {
      from { scale: 1; }
      to   { scale: 0.97; }
    }
  }
}

/* ── LE CHAMP DE GAUCHE, COLLANT ──────────────────────────────────────────
   SIX COLONNES SUR DOUZE, contre cinq auparavant, et la pile est passée de six à
   cinq. C'est ce qu'il reste du partage établi pour la scène, et c'est le bon :
   les cartes n'étaient pas plus lisibles à 601 px avec un texte bridé à 44
   caractères, elles étaient seulement plus larges.
   ──────────────────────────────────────────────────────────────────────── */
.marche-champ {
  grid-column: 1 / span 6;
  position: sticky;
  top: calc(var(--entete-h) + var(--e6));
  align-self: start;
  /* ── LA CARTE EN VERRE ──────────────────────────────────────────────────
     Même recette que la carte de gauche de la section 05 : un blanc très
     translucide, un flou de fond, un liseré blanc et une ombre basse. Le verre
     n'a de matière que s'il a quelque chose à réfracter : ici c'est le lavis de
     .marche-fond, à qui on a ajouté un halo bleu sous cette carte précisément
     pour lui donner de quoi travailler.
     Le flou de fond crée un contexte d'empilement, ce qui est sans conséquence
     sur la position collante de cet élément-ci. */
  border-radius: var(--rayon-grand);
  --carte-pad: var(--e7);
  padding: var(--carte-pad);
  /* ELLE DÉBORDE À GAUCHE DE SON PROPRE PADDING. Sans ce retrait, le padding de
     la carte poussait le titre 48 px à droite de la gouttière : « Comment ça
     marche » ne commençait plus sur la même verticale que tous les autres titres
     de la page, ce qui est la règle d'alignement à laquelle tout le reste obéit.
     Le contenu de la carte retombe donc exactement sur la gouttière, et c'est la
     carte qui va chercher son air vers le bord de la section. Même raisonnement
     que la marge de la carte du hero, retirée de son padding interne.

     LE `min()` EST INDISPENSABLE. Un retrait fixe de 48 px faisait sortir la carte
     de la section sur les écrans étroits : mesuré, 38 px dehors à 430 px de large
     et 14 px à 600. Et le vérificateur ne le voyait pas, parce qu'un débordement
     À GAUCHE n'agrandit pas `scrollWidth`. Le retrait est donc borné à la
     gouttière disponible : la carte s'arrête pile au bord intérieur de la section,
     et le titre reste sur la gouttière à toutes les largeurs. */
  margin-left: calc(-1 * min(var(--carte-pad), var(--gouttiere) - var(--marge-carte)));
  background: rgba(255, 255, 255, 0.38);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
          backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid rgba(255, 255, 255, 0.75);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.9) inset,
              0 30px 60px -40px rgba(38, 52, 120, 0.35);
  /* IL S'ARRÊTE AVEC LA PILE, ni avant ni après. Sa borne est le bas de sa
     rangée, qui est aussi celle de la pile : il se décolle donc à l'instant où
     la dernière carte se décolle, et les deux quittent l'écran ensemble.
     Une marge basse a été essayée pour le libérer plus tôt : mauvais, il
     partait derrière l'en-tête pendant que la dernière carte restait seule,
     laissant la moitié gauche vide.

     ATTENTION EN L'ALLONGEANT. Un élément collant se décroche quand le bas de son
     conteneur atteint le bas de sa bande épinglée, soit sa hauteur plus son
     décalage. Le champ mesure 273 px depuis l'ajout du chapeau, sa bande vaut donc
     373 quand celle de la dernière carte vaut 317 : il part 56 px avant elle, ce
     qui ne se voit pas. Mais l'écart grandit d'autant qu'on ajoute du contenu ici,
     et au-delà d'une centaine de pixels on verra la colonne de gauche s'en aller
     pendant que la dernière carte reste seule. C'est ce qui est arrivé avec la
     scène, qui portait le champ à 594 px : 377 px d'avance. */
}
.marche-titre { margin-bottom: var(--e5); }
/* LE CHAPEAU. Même traitement que la note du relevé, à la même taille de corps :
   c'est le second niveau de lecture de la page, il ne doit pas s'inventer une
   échelle à lui. Sa mesure est bornée à 46 caractères pour qu'il tienne dans la
   colonne du titre sans s'étirer sur toute sa largeur. */
.marche-chapeau {
  font-size: var(--t-corps);
  line-height: 1.55;
  color: var(--texte-2);
  max-width: 46ch;
}

/* ── LA PILE ─────────────────────────────────────────────────────────────── */
.etapes-pile {
  grid-column: 8 / -1;
  list-style: none;
  /* EN FLUX NORMAL, PAS EN GRILLE. Pour un élément de grille, la position
     collante est bornée à sa propre rangée : la course d'une carte valait donc
     sa propre hauteur. En flux normal, chaque carte est bornée par le
     CONTENEUR, cale comprise. */
  display: block;
  /* DE LA COURSE AVANT LA PREMIÈRE CARTE. Sans elle, la carte 1 se cale à
     l'instant même où la section atteint le haut de l'écran : l'état où les
     trois cartes se lisent côte à côte, écartées, n'existe donc que pendant
     l'entrée de la section, et l'empilement paraît commencer trop tôt. Ces
     128 px donnent une course pendant laquelle les trois cartes sont immobiles
     et respirent, avant que la première ne se cale. Ils décalent aussi la pile
     sous le titre, ce qui est voulu. */
  padding-top: var(--e10);
}
/* LA COURSE FINALE, ET POURQUOI CE N'EST PAS UN PADDING. Sans course après la
   dernière carte, la troisième se décolle à l'instant même où elle arrive au
   sommet : l'état final, celui où il ne reste qu'une carte, n'a aucun temps de
   lecture. Un padding-bottom sur la pile ne suffit PAS : le rectangle qui borne
   une position collante est la boîte de CONTENU du parent, le padding en est
   exclu. Il faut donc du contenu, d'où cette cale vide.

   ET ELLE DOIT RESTER VIDE : elle suit la carte collée dans le document, donc
   elle passe PAR-DESSUS elle. L'appel à l'action y a été posé, puis retiré, il
   venait se coucher en travers du texte de l'étape 03. En fin de course la cale
   monte jusqu'à 37 px du haut de l'écran alors que la carte occupe 100 à 317 px.
   Mesuré.

   280 px, et non 480 : la valeur haute avait été calculée pour un champ de
   gauche de 594 px, qui contenait la scène. Un élément collant se décroche quand
   le bas de son conteneur atteint le bas de sa bande épinglée, soit sa hauteur
   plus son décalage — un champ haut se décroche donc bien avant la dernière
   carte, et il fallait rallonger la course pour compenser. Le champ ne fait plus
   que 136 px : il tient jusqu'au bout tout seul. */
.pile-cale { height: var(--pile-cale); }
/* L'appel à l'action ferme la colonne de gauche, sous la scène : il occupe le
   bas du champ collant, qui sans lui se terminait 296 px avant le bas de
   l'écran. */
.marche-cta { margin-top: var(--e6); }

/* L'ÉCART, QUI EST LE TEMPS DE LECTURE. La distance de défilement d'une étape
   vaut la hauteur d'une carte plus cet écart : à 24 px, la carte suivante
   commençait à recouvrir la précédente presque aussitôt lue. À 96 px, chaque
   étape dispose d'environ 350 px de course avant d'être recouverte, et les
   cartes respirent avant que la pile ne commence.
   L'écart se referme ensuite tout seul, progressivement, puisque la carte
   suivante monte pendant que la précédente est immobilisée : c'est la mécanique
   de la position collante, il n'y a rien à animer.
   PORTÉ DE 96 À 128 px avec cette refonte : les cartes ont maigri de 270 à
   217 px en changeant de largeur et de mise en page, et la course d'une étape
   vaut la hauteur d'une carte PLUS cet écart. À 96 px elle serait tombée de 366
   à 313 px, c'est-à-dire que l'empilement se serait accéléré tout seul. */
.etape-carte + .etape-carte { margin-top: var(--e10); }
.etape-carte {
  position: relative;
  position: sticky;
  /* LE MÊME décalage pour les trois : c'est ce qui les fait se recouvrir
     exactement au lieu de s'échelonner. */
  top: calc(var(--entete-h) + var(--e6));
  /* Opaque, obligatoirement : la pile doit cacher ce qu'elle recouvre. */
  background: #FFFFFF;
  border-radius: var(--rayon-grand);
  /* 32 px et non 48 : la carte a maigri de 601 à 497 px, un padding de 48
     n'aurait laissé que 401 px de texte dans une colonne qui en offre 433. */
  padding: var(--e6);
  /* L'OMBRE, EN QUATRE COUCHES, ET AUCUNE BORDURE.
     · le liseré est un ombrage à zéro flou, pas une bordure : une bordure
       entre dans la boîte et se rasterise, un liseré non ;
     · une ombre de contact très courte, pour poser la feuille ;
     · une ombre moyenne, qui donne la flottaison ;
     · une ombre longue et basse, qui donne la profondeur ;
     · et une ombre VERS LE HAUT, indispensable : sans elle, la carte qui monte
       se confond avec le fond blanc de celle qu'elle recouvre, et le texte du
       dessous paraît coupé au hasard. */
  box-shadow:
    0 0 0 1px rgba(38, 52, 120, 0.05),
    0 1px 2px rgba(38, 52, 120, 0.04),
    0 -12px 30px -20px rgba(38, 52, 120, 0.20),
    0 16px 32px -20px rgba(38, 52, 120, 0.16),
    0 40px 72px -44px rgba(38, 52, 120, 0.38);
}
.etape-carte-ico {
  flex: none;
  display: grid; place-items: center;
  width: 44px; height: 44px;
  border-radius: 14px;
  background: var(--bleu-pale);
  margin-bottom: var(--e5);
  transition: background-color 0.24s var(--sortie);
}
.etape-carte-ico svg { display: block; overflow: visible; }
.etape-carte-ico .ico-plein,
.etape-carte-ico .ico-trait {
  transition: fill 0.24s var(--sortie), stroke 0.24s var(--sortie);
}
/* LA CARTE LUE ALLUME SA VIGNETTE. Dans une pile, la carte calée au sommet est
   celle qu'on lit : son aplat passe au bleu de marque, et c'est le seul repère de
   progression une fois les précédentes recouvertes. Une couleur, rien de plus :
   la carte ne change ni de taille, ni de position, ni d'ombre. Le script pose la
   classe, il le faisait déjà. */
.etape-carte.est-lue .etape-carte-ico { background: var(--bleu); }
.etape-carte.est-lue .etape-carte-ico .ico-plein { fill: rgba(255, 255, 255, 0.28); }
.etape-carte.est-lue .etape-carte-ico .ico-trait { stroke: #FFFFFF; }

.etape-carte-titre {
  font-family: var(--f-titre);
  font-weight: 900;
  font-size: clamp(19px, 1.4vw, 23px);
  letter-spacing: -0.024em;
  line-height: 1.16;
  color: var(--texte);
  margin-bottom: var(--e3);
}
.etape-carte-texte {
  font-size: 15.5px;
  line-height: 1.6;
  color: var(--texte-2);
  /* 52 caractères et non 44 : dans une colonne de 433 px, la mesure de 44
     laissait 40 px de vide au bout de chaque ligne. */
  max-width: 52ch;
}

/* ── SOUS 1024 px : UNE SEULE COLONNE, ET PAS DE SCÈNE ────────────────────
   La scène est une COMPAGNE COLLANTE de la pile : elle n'a de sens que dans une
   grille à deux colonnes, où elle peut rester à côté des cartes qui défilent.
   En une seule colonne elle n'a aucune course où se coller — elle passerait une
   fois, puis disparaîtrait pendant tout l'empilement, et les cartes
   glisseraient par-dessus. Elle est donc retirée, et les trois cartes portent
   seules le texte, qui est complet : rien de ce qui est dit n'est perdu.
   ──────────────────────────────────────────────────────────────────────── */
@media (max-width: 1023px) {
  .marche-champ { grid-column: 1 / -1; position: static; }
  .etapes-pile { grid-column: 1 / -1; }
}
/* ── MOBILE : PAS D'EMPILEMENT ────────────────────────────────────────────
   Sous 900 px, la pile n'est pas agréable : une carte qui recouvre l'autre sur
   une colonne étroite masque la moitié du texte qu'on vient de lire, et le
   moindre à-coup du défilement tactile se voit. Les cartes se suivent donc
   simplement, et chacune se lève à son entrée dans l'écran.
   L'apparition est pilotée par le défilement, donc réversible et sans
   JavaScript ; elle ne joue pas du tout si le visiteur a demandé moins de
   mouvement, et les navigateurs qui ne la connaissent pas affichent les cartes
   en place.
   ──────────────────────────────────────────────────────────────────────── */
@media (max-width: 899px) {
  .etape-carte { position: static; }
  .etape-carte + .etape-carte { margin-top: var(--e6); }
  .etapes-pile { padding-top: var(--e7); }
  /* La course finale n'a plus de pile à retenir : elle n'est plus qu'un écart
     avant l'appel à l'action. */
  .pile-cale { height: auto; padding-top: var(--e7); }
}
@media (max-width: 899px) and (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .etape-carte {
      animation: carte-se-leve linear both;
      animation-timeline: view();
      animation-range: entry 10% entry 65%;
    }
    @keyframes carte-se-leve {
      from { opacity: 0; transform: translate3d(0, 24px, 0); }
      to   { opacity: 1; transform: translate3d(0, 0, 0); }
    }
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   13 · 05 · LE DERNIER TICKET — deux cartes, deux matières
   ---------------------------------------------------------------------------
   L'argument de la section est un contraste. Il est donc porté par la MATIÈRE
   des deux cartes avant de l'être par les chiffres :

     · à gauche, du VERRE. Translucide, elle floute ce qui passe derrière elle.
     · à droite, le LAVIS de l'accroche. C'est la nôtre, elle a la couleur de
       la maison.

   POURQUOI UN HALO DERRIÈRE LA CARTE DE GAUCHE. Le verre a besoin de quelque
   chose à flouter : sur une section blanche posée sur une page blanche, une
   carte en verre n'est qu'un rectangle blanc bordé. Deux halos très pâles sont
   donc posés dans la section, derrière elle, et c'est ce qu'elle réfracte. Si
   on les retire, l'effet disparaît — ce n'est pas une décoration.

   LES CORPS DE TEXTE, RELEVÉS. Tout était trop petit pour être lu : le titre de
   bloc à 15 px, le contenu à 15, les valeurs chiffrées à 12 et les unités à 11.
   Le titre passe à 23 px, le contenu à 17, les valeurs à 18. Il y a maintenant
   une marche nette entre le titre d'un bloc et son contenu, et plus rien sous
   14 px.
   ═══════════════════════════════════════════════════════════════════════════ */
.sec-ticket { position: relative; isolation: isolate; }
/* Les deux halos. Ils ne se voient presque pas, et c'est voulu : leur seul rôle
   est de donner de la matière au verre de la carte de gauche. */
.sec-ticket::before {
  content: '';
  position: absolute;
  z-index: -1;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(44% 48% at 18% 40%, rgba(69, 95, 253, 0.24) 0%, rgba(69, 95, 253, 0) 70%),
    radial-gradient(36% 40% at 2% 80%, rgba(32, 202, 226, 0.22) 0%, rgba(32, 202, 226, 0) 70%);
  /* IL NE S'ARRÊTE PLUS NET. Les deux halos sont des dégradés radiaux dont les
     cercles dépassent la section : ils étaient donc coupés au couteau sur le bord
     bas, et on voyait une ligne horizontale là où le fond redevenait blanc d'un
     coup. Un masque vertical les éteint avant les bords, en haut comme en bas :
     le fond se dissout dans le blanc au lieu de s'y interrompre.
     Pourquoi un masque et pas un vrai débordement sur la section suivante : chaque
     section peint son propre fond blanc OPAQUE, et elle le peint après. Tout ce
     qui déborderait serait donc recouvert, quel que soit le z-index — sauf à
     passer le halo par-dessus le contenu de la section d'après, ce qui en
     teinterait le texte. Le masque donne le même œil, sans ce prix. */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 8%, #000 76%, transparent 100%);
          mask-image: linear-gradient(to bottom, transparent 0%, #000 8%, #000 76%, transparent 100%);
}

.ticket-titre { grid-column: 1 / span 9; }
.addition {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--e6);
  align-items: start;
}
.addition-col {
  position: relative;
  border-radius: var(--rayon-grand);
  padding: var(--e7);
}

/* ── LA CARTE EN VERRE ───────────────────────────────────────────────────── */
.addition-tpe {
  background: rgba(255, 255, 255, 0.38);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
          backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid rgba(255, 255, 255, 0.75);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.9) inset,
              0 30px 60px -40px rgba(38, 52, 120, 0.35);
}

/* ── LA CARTE AU LAVIS ───────────────────────────────────────────────────── */
.addition-smspay {
  border: 1px solid rgba(255, 255, 255, 0.7);
  background-color: var(--lavis-brume);
  background-image:
    radial-gradient(88% 74% at 4% -6%, rgba(69, 95, 253, 0.18) 0%, rgba(69, 95, 253, 0) 60%),
    radial-gradient(76% 66% at 100% 104%, rgba(32, 202, 226, 0.22) 0%, rgba(32, 202, 226, 0) 62%),
    linear-gradient(150deg,
      var(--lavis-brume) 0%,
      var(--lavis-ciel)  34%,
      var(--lavis-eau)   68%,
      var(--lavis-creme) 100%);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.9) inset,
              0 30px 60px -40px rgba(38, 52, 120, 0.35);
}

/* ── LE TITRE DE BLOC, ET SON ICÔNE ──────────────────────────────────────── */
.addition-titre {
  display: flex;
  align-items: center;
  gap: var(--e4);
  font-family: var(--f-titre);
  font-weight: 900;
  font-size: clamp(19px, 1.5vw, 23px);
  letter-spacing: -0.024em;
  line-height: 1.15;
  color: var(--texte);
  margin-bottom: var(--e6);
}
.addition-ico {
  flex: none;
  display: grid; place-items: center;
  width: 42px; height: 42px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.8);
  box-shadow: 0 6px 16px -12px rgba(38, 52, 120, 0.5);
}
.addition-smspay .addition-ico { background: #FFFFFF; }
.addition-ico svg { display: block; overflow: visible; }

/* ── LES LIGNES ──────────────────────────────────────────────────────────── */
/* AUCUN TRAIT. Ni filet entre les lignes, ni conduite pointillée, ni case à
   remplir : c'est l'espace qui sépare, donc il en faut davantage. Le libellé et
   sa valeur se poussent aux deux bords de la ligne. */
.addition-lignes {
  list-style: none;
  display: grid;
  gap: var(--e5);
}
.addition-lignes li {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--e5);
}
.addition-quoi {
  font-size: 17px;
  line-height: 1.35;
  color: var(--texte);
}
/* MÊME POLICE QUE LE LIBELLÉ. Les valeurs étaient en mono, ce qui en faisait
   une autre voix dans une même ligne. Elles sont maintenant dans la police du
   texte, simplement plus appuyées, avec des chiffres à largeur fixe pour qu'une
   colonne de valeurs reste alignée. */
.addition-val {
  flex: none;
  font-size: 18px;
  font-weight: 600;
  color: var(--texte);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.addition-note {
  margin-top: var(--e6);
  font-size: 15px;
  line-height: 1.5;
  color: var(--texte-2);
}

/* L'unité tient la place de la valeur absente : c'est elle, seule, qui dit que
   la ligne est à remplir. Même police que le reste, et alignée à droite comme
   les valeurs d'en face. */
.addition-unite {
  flex: none;
  font-size: 16px;
  font-weight: 500;
  color: var(--texte-3);
  text-align: right;
  white-space: nowrap;
}

/* ── LE TOTAL ────────────────────────────────────────────────────────────── */
/* LE TOTAL. Il était mal proportionné : un chiffre de 46 px dans une gélule
   entièrement arrondie, dont les bouts en demi-cercle mesuraient plus que le
   texte, et une mention de 15 px écrasée à côté. Le chiffre descend à 34, la
   mention monte à 16, et la forme prend le grand rayon des panneaux au lieu de
   la gélule : le contenant suit enfin son contenu. */
.addition-total {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--e5);
  margin-top: var(--e7);
  padding: var(--e5) var(--e6);
  border-radius: var(--rayon-grand);
  background: var(--bleu);
  color: #FFFFFF;
  clip-path: inset(0 0 0 0);
}
.addition-total span {
  font-size: 16px;
  font-weight: 500;
  line-height: 1.3;
}
.addition-total strong {
  font-family: var(--f-chiffre);
  font-weight: 900;
  font-size: 34px;
  letter-spacing: -0.04em;
  line-height: 1;
  white-space: nowrap;
}

@media (max-width: 899px) {
  .addition { grid-template-columns: 1fr; }
  .addition-col { padding: var(--e6); }
  .addition-trou { min-width: 48px; }
  .addition-unite { width: 76px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   14 · 06 · OÙ VA L'ARGENT — la bande à chevrons, la preuve
   ---------------------------------------------------------------------------
   La section reprend le traitement du hero : même lavis, même rayon, même
   marge blanche, donc elle est posée DANS la page au lieu de la traverser.

   TROIS BLOCS, un pas régulier : le titre, la bande, la preuve.

   POURQUOI UNE BANDE ET PLUS UN RAIL. Les deux versions précédentes reposaient
   sur un filet de 2 px avec des anneaux posés dessus. À l'échelle de la page,
   un filet ne peut pas représenter un flux : il n'a pas de matière, et des
   pointes de 8 px au bout n'en donnent pas. Le flux est donc devenu un OBJET,
   une bande découpée en trois pans qui s'emboîtent par des chevrons. Le sens
   de circulation est porté par la géométrie des pans, pas par un ornement
   ajouté, et la valeur monte de gauche à droite pour que la destination soit
   visiblement le terme du trajet.
   ═══════════════════════════════════════════════════════════════════════════ */
.sec-flux {
  margin: var(--marge-carte);
  border-radius: var(--rayon-carte);
  padding: var(--pas-section) 0;
  overflow: clip;

  background-color: var(--lavis-brume);
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.1'/%3E%3C/svg%3E"),
    radial-gradient(88% 74% at 4% -6%, rgba(69, 95, 253, 0.16) 0%, rgba(69, 95, 253, 0) 60%),
    radial-gradient(76% 66% at 100% 104%, rgba(32, 202, 226, 0.20) 0%, rgba(32, 202, 226, 0) 62%),
    radial-gradient(38% 40% at 99% 0%, rgba(247, 236, 218, 0.62) 0%, rgba(247, 236, 218, 0) 62%),
    linear-gradient(150deg,
      var(--lavis-brume) 0%,
      var(--lavis-ciel)  34%,
      var(--lavis-eau)   68%,
      var(--lavis-creme) 100%);
  background-size: 120px 120px, auto, auto, auto, auto;
  background-repeat: repeat, no-repeat, no-repeat, no-repeat, no-repeat;
  background-blend-mode: overlay, normal, normal, normal, normal;
  background-origin: border-box;
}
/* La gouttière de la carte compense sa marge : le contenu retombe sur la même
   verticale que tout le reste de la page. */
.sec-flux .corps { padding: 0 calc(var(--gouttiere) - var(--marge-carte)); }

/* ── LE TITRE ────────────────────────────────────────────────────────────── */
.flux-titre { grid-column: 1 / span 8; }

/* ── LE TRAJET ET SES TROIS OBJETS ──────────────────────────────────────
   CINQUIÈME DISPOSITIF. Les quatre premiers — anneaux sur un trait, rail à
   stations, bandeau à compartiments, points sur une courbe — échouaient tous sur
   la même chose : ils décrivaient le trajet sans montrer ce qui le parcourt. À
   chaque fois trois repères abstraits alignés, c'est-à-dire la silhouette qu'on
   reconnaît à dix mètres comme un « composant à trois étapes ».

   Les trois arrêts sont maintenant TROIS OBJETS RÉELS, et leur matière dit à qui
   ils appartiennent : la carte du client est neutre, la plaque des prestataires
   est blanche et cerclée, le compte porte l'aplat de marque. Neutre, tiers, vous.
   C'est la même règle que partout ailleurs sur la page — la destination porte la
   couleur de la maison.

   LA LIGNE EST DROITE, et c'est un choix de fond. Le texte de la section dit
   « crédité directement, SANS DÉTOUR » : une courbe est un détour. Une version en
   courbe a été construite puis retirée — son creux au milieu se lisait comme un
   graphique qui baisse, donc comme une perte, sur une page dont tout l'argument
   est que rien n'est prélevé en route. La forme disait le contraire du texte.

   ELLE PASSE DERRIÈRE LES OBJETS. Ils sont opaques : la voie entre dans chacun et
   en ressort, on ne voit donc que les deux segments entre eux, et ses deux
   extrémités sont cachées sous les objets d'extrémité. Rien à découper.

   AUCUN NOMBRE MAGIQUE. Les neuf cases tiennent dans UNE grille de trois colonnes
   sur trois rangées. Les rangées d'une grille étant partagées par ses colonnes,
   les trois objets sont sur la même ligne quelles que soient leurs hauteurs, et la
   voie est elle-même une case de cette grille, centrée sur la rangée du milieu.
   Aucune coordonnée, aucun pourcentage : si un objet change de taille, rien n'est
   à recalculer. Les versions précédentes reposaient sur six à neuf nombres calés à
   la main sur un viewBox.
   ──────────────────────────────────────────────────────────────────────── */
.flot { grid-column: 1 / -1; }

/* TROIS RANGÉES EXPLICITES : les libellés, les détails, les objets. C'est ce qui
   met les trois libellés exactement au même niveau, et les trois détails aussi,
   quelles que soient leurs longueurs. Avant, chaque légende était un seul bloc placé
   dans une rangée, et celle du milieu passait sous la ligne : les trois libellés
   n'étaient donc jamais alignés entre eux. */
.trajet {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-template-rows: auto auto auto;
  column-gap: var(--e6);
  row-gap: var(--e5);
  align-items: center;
}

/* LA VOIE. Une case de la grille, sur toute la largeur, centrée sur la rangée du
   milieu — donc sur l'axe des trois objets, sans qu'on ait à le connaître.
   Elle se dessine à la révélation par un `clip-path`, de gauche à droite : un
   `scaleX` aurait comprimé son dégradé, la découpe le révèle intact. Une seule
   fois, et rien ne tourne en boucle après. */
.trajet-voie {
  grid-column: 1 / -1;
  grid-row: 3;
  align-self: center;
  z-index: 0;
  height: 3px;
  border-radius: var(--rayon-plein);
  background: linear-gradient(90deg,
    rgba(69, 95, 253, 0.30) 0%,
    rgba(32, 202, 226, 0.60) 46%,
    var(--bleu) 100%);
  box-shadow: 0 0 0 5px rgba(69, 95, 253, 0.06);
}
@media (prefers-reduced-motion: no-preference) {
  .trajet-voie { clip-path: inset(0 100% 0 0); }
  .flot.est-visible .trajet-voie {
    clip-path: inset(0 0 0 0);
    transition: clip-path 1.6s var(--sortie);
  }
}

/* LES TROIS OBJETS, sur la rangée du milieu, au-dessus de la voie. */
.trajet-piece { grid-row: 3; z-index: 1; }
.trajet-piece-1 { grid-column: 1; justify-self: start; }
.trajet-piece-2 { grid-column: 2; justify-self: center; }
.trajet-piece-3 { grid-column: 3; justify-self: end; }

/* 1 · LA CARTE DU CLIENT. Matière neutre, pas la nôtre : c'est son instrument.
   Rapport exact d'une carte de paiement, et tout son contenu en unités d'elle-même
   pour qu'elle se comporte comme une carte photographiée à n'importe quelle
   échelle — même procédé que la plaque du tarif, mêmes deux pièges évités : le
   cadre déclare le conteneur, et la puce ne se laisse pas écraser. */
.piece-carte {
  /* LE CADRE NE FAIT QUE DÉCLARER LE CONTENEUR. Un élément ne peut pas se mesurer
     lui-même : `container-type` sert ses descendants, jamais lui. C'est le même
     piège que sur la plaque du tarif, et j'y suis retombé — sans la séparation, les
     `cqw` de la face se résolvaient sur la fenêtre et la carte devenait un carré
     sombre de 365 px avec 86 px de rayon. */
  container-type: inline-size;
  display: block;
  width: clamp(132px, 13vw, 188px);
}
.piece-carte-face {
  position: relative;
  aspect-ratio: 1.586 / 1;
  display: flex;
  flex-direction: column;
  padding: 9cqw;
  border-radius: 6cqw;
  background: linear-gradient(152deg, #3A4260 0%, #1C2138 54%, #2E3552 100%);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.18) inset,
              0 18px 34px -20px rgba(20, 26, 52, 0.7);
}
.piece-puce {
  flex: none;
  width: 15cqw; height: 11cqw;
  border-radius: 2cqw;
  background: linear-gradient(152deg, #EADFBE 0%, #C3A868 48%, #E9DFBC 100%);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.28);
  margin-bottom: auto;
}
.piece-carte-face .piece-numero {
  font-family: var(--f-etiq);
  font-size: 7.5cqw;
  letter-spacing: 0.08em;
  color: rgba(255, 255, 255, 0.9);
}

/* 2 · LA PLAQUE DES PRESTATAIRES. Blanche et cerclée : la matière des tiers.
   Les trois enseignes SONT le contenu de cet arrêt, elles n'ont pas besoin d'un
   libellé de plus à l'intérieur. */
.piece-plaque {
  display: flex;
  align-items: center;
  gap: var(--e4);
  white-space: nowrap;
  padding: var(--e4) var(--e5);
  border-radius: var(--rayon);
  background: #FFFFFF;
  box-shadow: 0 0 0 1px rgba(38, 52, 120, 0.07),
              0 14px 30px -20px rgba(38, 52, 120, 0.4);
}

/* 3 · VOTRE COMPTE. L'aplat de marque, comme toutes les destinations de la page. */
.piece-compte {
  display: flex;
  align-items: center;
  gap: var(--e3);
  padding: var(--e4) var(--e5);
  border-radius: var(--rayon);
  background: var(--bleu);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.22) inset,
              0 16px 32px -18px rgba(69, 95, 253, 0.7);
}
.piece-marque { flex: none; display: block; }
.piece-marque svg { display: block; }
.piece-compte .piece-numero {
  font-family: var(--f-etiq);
  font-size: 14px;
  letter-spacing: 0.08em;
  color: #FFFFFF;
}

/* ── LES TROIS LÉGENDES, EN ALTERNANCE ───────────────────────────────────
   Celle du milieu passe SOUS la ligne, les deux autres restent au-dessus. C'est
   ce qui empêche la rangée de se reformer : trois légendes au même niveau sous
   trois objets au même niveau, ce serait à nouveau le composant à trois étapes.
   Les rangées de la grille font le calage : rien à positionner à la main. */
/* `min-width: 0` : un élément de grille a une largeur minimale égale à son
   contenu, et une légende dont le mot le plus long dépasse sa colonne la
   ferait grandir au détriment des deux autres. */
/* LES TROIS LÉGENDES SONT AU-DESSUS DE LA LIGNE, ET ALIGNÉES ENTRE ELLES.
   Chacune occupe les rangées 1 et 2 de la grille et les REPREND en sous-grille :
   son libellé tombe donc dans la rangée 1, son détail dans la rangée 2, et comme les
   rangées d'une grille sont partagées par ses colonnes, les trois libellés sont
   exactement au même niveau et les trois détails aussi. Aucune hauteur à connaître,
   aucun pourcentage à caler — c'est la grille qui aligne.

   L'alternance a disparu : la légende du milieu était sous la ligne pour empêcher le
   schéma de reprendre la silhouette d'un « composant à trois étapes ». Ce rôle est
   maintenant tenu par les trois objets, qui n'ont ni la même forme ni la même taille,
   et l'alternance n'était plus qu'un décrochement.

   `min-width: 0` : un élément de grille a une largeur minimale égale à son contenu, et
   une légende dont le mot le plus long dépasse sa colonne la ferait grandir au
   détriment des deux autres. */
.trajet-note {
  min-width: 0;
  grid-row: 1 / 3;
  display: grid;
  grid-template-rows: subgrid;
  align-content: end;
}
.trajet-note-1 { grid-column: 1; }
.trajet-note-2 { grid-column: 2; text-align: center; }
.trajet-note-3 { grid-column: 3; text-align: right; }

.etape-role {
  display: flex;
  align-items: center;
  gap: var(--e3);
  font-family: var(--f-titre);
  font-weight: 900;
  font-size: clamp(18px, 1.4vw, 23px);
  letter-spacing: -0.024em;
  line-height: 1.1;
  color: var(--texte);
  /* L'écart entre le libellé et son détail est le `row-gap` de la grille, pas une
     marge : c'est lui qui garantit que les trois détails restent alignés. Une marge
     ici s'ajouterait à l'écart de rangée et ne serait comptée qu'une fois. */
  align-self: end;
}
.trajet-note-2 .etape-role { justify-content: center; }
.trajet-note-3 .etape-role { justify-content: flex-end; }
.etape-marque { flex: none; display: block; }
.etape-marque svg { display: block; overflow: visible; }

.etape-etat {
  font-size: 15px;
  line-height: 1.5;
  color: var(--texte-2);
}
.etape-etat strong {
  font-family: var(--f-chiffre);
  font-weight: 900;
  font-size: 21px;
  letter-spacing: -0.03em;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

/* LES TROIS ENSEIGNES. Elles gardent LEURS COULEURS de marque, et leurs trois
   hauteurs de boîte comme leurs trois décalages verticaux sont différents, et
   c'est exprès : chaque dessin réserve une place différente au-dessus et
   au-dessous des minuscules. Les hauteurs égalisent le CORPS des lettres sur celui
   du texte courant, les décalages alignent les PIEDS. Mesuré à l'écran, à huit fois
   la résolution. Ne pas uniformiser. */
.enseigne { display: block; width: auto; }
.enseigne-stripe   { height: 12.9px; }
.enseigne-ingenico { height: 9.9px; transform: translateY(0.7px); }
.enseigne-worldpay { height: 14.2px; }

/* ── LA PREUVE ───────────────────────────────────────────────────────────
   L'affirmation est le TITRE des quatre garanties : elle affirme, elles
   démontrent.

   Son style a été refait. Elle portait un surlignage cyan pleine largeur,
   hérité de l'époque où cette section était noire : sur le lavis, au milieu
   d'une section qui ne parle qu'en encre et en bleu de marque, ce bloc de
   cyan était un corps étranger. L'accent est maintenant porté par le SEUL mot
   qui compte, « jamais », dans le bleu de la maison.
   ──────────────────────────────────────────────────────────────────────── */
.preuve {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
  column-gap: var(--e8);
  row-gap: var(--e6);
  align-items: start;
  margin-top: var(--e6);
}
.preuve-titre {
  font-family: var(--f-titre);
  font-weight: 900;
  font-size: clamp(24px, 2.4vw, 34px);
  line-height: 1.1;
  letter-spacing: -0.028em;
  color: var(--texte);
  max-width: 20ch;
}
.preuve-titre em { font-style: normal; color: var(--accent); }

.garanties {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--e6);
  row-gap: var(--e5);
}
.garantie {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: var(--e4);
  font-size: 15px;
  line-height: 1.45;
  color: var(--texte-2);
}
/* L'icône est posée sur une pastille blanche : sur le lavis, une icône nue
   flotterait. Ronde, comme tout le reste de la page. */
.garantie-ico {
  flex: none;
  width: 40px; height: 40px;
  display: grid; place-items: center;
  background: #FFFFFF;
  border-radius: 50%;
  box-shadow: 0 8px 18px -14px rgba(38, 52, 120, 0.5);
}
/* Les icônes viennent de Streamline. Leurs couleurs d'origine sont réécrites
   par la palette du site : le trait prend le bleu de marque, les aplats sa
   version pâle. Elles sont posées dans la page, donc elles suivent les jetons
   sans aucune requête. */
.garantie-ico svg { display: block; overflow: visible; }
.ico-trait {
  fill: none;
  stroke: var(--bleu);
  stroke-width: 1;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.ico-plein { fill: var(--bleu-pale); }
.ico-blanc { fill: #FFFFFF; }

/* ═══════════════════════════════════════════════════════════════════════════
   15 · 07 · LE TARIF — la carte adossée à droite
   ---------------------------------------------------------------------------
   LA COMPOSITION EST EN MIROIR. Le contenu s'ancre au bord droit et se lit vers
   la gauche : le titre au fer à droite, la carte dans les DIX colonnes de
   droite. Les deux colonnes de gauche restent vides, ce qui suffit à dire que
   le bloc est adossé à droite.

   Ce n'est PAS `direction: rtl`. Cette propriété inverserait le rendu du texte
   lui-même — ponctuation en bout de ligne, ordre des signes — ce qui n'a aucun
   sens dans une page française. Seule la composition est retournée.

   LE LISERÉ QUI TOURNE. Un dégradé conique tourne derrière la carte, et le
   corps blanc le recouvre entièrement sauf sur deux pixels : on ne voit donc
   que le liseré, et la lueur s'y promène. C'est la transposition du composant
   fourni, qui faisait la même chose en React ; ici, un pseudo-élément et une
   rotation suffisent, sans dépendance.

   L'APLAT BLEU DE LA SECTION A ÉTÉ RETIRÉ. C'est la carte qui porte la couleur,
   par son liseré et son bouton, et la page n'a donc plus aucune rupture en
   aplat. Le corps de la carte n'a plus besoin de redéclarer les jetons de la
   page claire, puisque la section est claire elle-même : ces sept lignes ont
   été supprimées avec l'aplat.
   ═══════════════════════════════════════════════════════════════════════════ */
/* Les mentions sont DANS la carte, sous le bouton : elles appartiennent au
   tarif, elles n'ont pas à vivre à côté de lui. Elles restent au fer à gauche
   comme tout le contenu de la carte. */
/* LE FOND DE LA SECTION : les deux mêmes halos que la section 05, mais EN MIROIR,
   posés à droite. Deux sections séparées par une seule autre avaient exactement le
   même fond, au même endroit ; retourner celui-ci suffit à les distinguer, et ça
   va dans le sens de la composition, qui est elle-même adossée à droite.
   Ils ne sont pas décoratifs pour rien : ce sont eux qui donnent une couleur au
   blanc de la page derrière une carte blanche. */
.sec-tarif { position: relative; isolation: isolate; }
.sec-tarif::before {
  content: '';
  position: absolute;
  z-index: -1;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(44% 48% at 82% 40%, rgba(69, 95, 253, 0.24) 0%, rgba(69, 95, 253, 0) 70%),
    radial-gradient(36% 40% at 98% 80%, rgba(32, 202, 226, 0.22) 0%, rgba(32, 202, 226, 0) 70%);
  /* IL NE S'ARRÊTE PLUS NET. Les deux halos sont des dégradés radiaux dont les
     cercles dépassent la section : ils étaient donc coupés au couteau sur le bord
     bas, et on voyait une ligne horizontale là où le fond redevenait blanc d'un
     coup. Un masque vertical les éteint avant les bords, en haut comme en bas :
     le fond se dissout dans le blanc au lieu de s'y interrompre.
     Pourquoi un masque et pas un vrai débordement sur la section suivante : chaque
     section peint son propre fond blanc OPAQUE, et elle le peint après. Tout ce
     qui déborderait serait donc recouvert, quel que soit le z-index — sauf à
     passer le halo par-dessus le contenu de la section d'après, ce qui en
     teinterait le texte. Le masque donne le même œil, sans ce prix. */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 8%, #000 76%, transparent 100%);
          mask-image: linear-gradient(to bottom, transparent 0%, #000 8%, #000 76%, transparent 100%);
}

.tarif-mentions {
  margin-top: var(--e6);
  font-size: 14px;
  line-height: 1.6;
  color: var(--texte-3);
}

/* ── LA CARTE ────────────────────────────────────────────────────────────── */
.tarif-carte {
  /* Douze colonnes : son bord gauche tombe sur la gouttière de la page, donc
     exactement sous le « O » de « Où va l'argent », le titre de la section du
     dessus. */
  grid-column: 1 / -1;
  position: relative;
  isolation: isolate;
  overflow: hidden;
  border-radius: var(--rayon-carte);
  padding: 2px;                     /* l'épaisseur du liseré, rien de plus */
  background: var(--trait);
}
/* Le dégradé conique qui tourne. Il est plus large que la carte pour qu'aucun
   coin ne se vide pendant la rotation, et flouté pour que la lueur soit une
   lueur et non un rayon. */
.tarif-carte::before {
  content: '';
  position: absolute;
  z-index: -1;
  inset: -60%;
  /* Sur du blanc, un liseré blanc ne se voit pas : le dégradé passe du cyan au
     bleu de marque, saturé, avec deux secteurs transparents pour que la lueur
     tourne au lieu de cercler la carte en continu. */
  background: conic-gradient(from 0deg,
    rgba(69, 95, 253, 0) 0deg,
    var(--cyan) 45deg,
    var(--bleu) 105deg,
    var(--cyan) 165deg,
    rgba(69, 95, 253, 0) 225deg,
    rgba(69, 95, 253, 0) 360deg);
  filter: blur(6px);
  animation: liseré-tourne 5s linear infinite;
}
@keyframes liseré-tourne { to { transform: rotate(1turn); } }

.tarif-carte-corps {
  position: relative;
  border-radius: calc(var(--rayon-carte) - 2px);
  background: #FFFFFF;
  color: var(--texte);
  /* TOUT AU FER À DROITE. La lecture part du bord droit et va vers la gauche :
     c'est la demande, et elle vaut pour l'intérieur de la carte, pas seulement
     pour sa position dans la page. */
  text-align: right;
  padding: var(--e8);
  box-shadow: 0 40px 80px -50px rgba(38, 52, 120, 0.45);
}

/* ── LE HAUT : LA PLAQUE ET LE DISCOURS ──────────────────────────────────
   La plaque occupe la moitié gauche, restée vide depuis que le contenu s'est
   adossé à droite. Le discours reste au fer à droite. */
.tarif-haut {
  display: grid;
  grid-template-columns: minmax(0, 0.64fr) minmax(0, 1fr);
  gap: var(--e8);
  align-items: center;
  margin-bottom: var(--e8);
}

/* ── LA PLAQUE ───────────────────────────────────────────────────────────
   POURQUOI LE PRIX, ET PAS LA CARTE ENTIÈRE. La demande était de faire de la
   carte du tarif une carte de paiement. Trois raisons de ne pas le faire, et
   d'appliquer ses codes au seul prix :

     · LE DISCOURS. Les deux affirmations les plus fortes de la page sont
       « sans terminal » et « votre argent ne passe JAMAIS par SMSPay ». Un
       panneau de tarif en forme de carte bancaire dit exactement le contraire :
       il fait de SMSPay un émetteur qui détient l'argent. C'est le seul
       contresens que cette page ne peut pas se permettre.
     · LA GÉOMÉTRIE. Une carte fait 1,586 de rapport et tient dans une main. Ce
       panneau fait 1 226 px de large : à ce rapport il mesurerait 773 px de
       haut, et personne ne lit un rectangle de 1 226 × 773 comme une carte de
       crédit — on lit un grand rectangle aux angles arrondis. Pour qu'il en
       devienne une, il faudrait qu'il rétrécisse, donc que le contenu sorte.
     · LE CONTENU. La face d'une carte porte un numéro, un nom, une date. La
       nôtre porte un prix, quatre garanties, un appel à l'action et deux lignes
       de mentions légales. Forcer l'un dans l'autre donne un pastiche.

   La plaque, elle, a le rapport EXACT d'une carte (85,60 × 53,98 mm) et ses
   codes : la puce, le chiffre en relief, la ligne de pied de face, la lueur qui
   passe dans le plastique. À cette taille et sur ce seul élément, la métaphore
   tient et ne dit rien de faux : c'est le prix d'un encaissement par carte.
   ──────────────────────────────────────────────────────────────────────── */
.tarif-plaque {
  /* IL NE FAIT QUE DÉCLARER LE CONTENEUR. Un élément ne peut pas se mesurer
     lui-même : `container-type` sert ses descendants, jamais lui. La face est
     donc un élément séparé, et ses `cqw` se résolvent sur CE cadre. Sans cette
     séparation, elles se résolvaient sur la fenêtre : à 1 200 px de large, la
     face prenait 96 px de padding et 66 px de rayon au lieu de 26 et 18. Vu à
     l'écran, puis compris. */
  container-type: inline-size;
}
.plaque-face {
  position: relative;
  overflow: hidden;
  /* LE RAPPORT D'UNE CARTE, au centième. C'est lui qui fait la reconnaissance,
     bien avant la puce et le relief. */
  aspect-ratio: 1.586 / 1;
  display: flex;
  flex-direction: column;
  /* Une carte se lit de gauche à droite, même dans une composition adossée à
     droite : c'est un objet, pas un paragraphe. */
  text-align: left;
  padding: 8cqw;
  border-radius: 5.5cqw;
  background:
    radial-gradient(120% 90% at 12% 8%, rgba(255, 255, 255, 0.30) 0%, rgba(255, 255, 255, 0) 58%),
    linear-gradient(148deg, var(--cyan) 0%, var(--bleu) 52%, #2B34C9 100%);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.35) inset,
              0 30px 60px -28px rgba(38, 52, 120, 0.55);
}
/* LA LUEUR DANS LE PLASTIQUE. Une bande claire en biais, hors du cadre, qui le
   traverse au survol. Elle ne tourne pas en boucle : une carte ne scintille pas
   toute seule, elle prend la lumière quand on la bouge. */
.plaque-face::after {
  content: '';
  position: absolute;
  top: -60%; bottom: -60%;
  left: -40%;
  width: 26%;
  background: linear-gradient(90deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, 0.34) 50%,
    rgba(255, 255, 255, 0) 100%);
  transform: rotate(14deg) translateX(0);
  pointer-events: none;
  opacity: 0;
}
@media (hover: hover) and (pointer: fine) {
  .tarif-carte:hover .plaque-face::after {
    animation: plaque-lueur 0.9s var(--sortie) both;
  }
}
@keyframes plaque-lueur {
  from { opacity: 0; transform: rotate(14deg) translateX(0); }
  20%  { opacity: 1; }
  80%  { opacity: 1; }
  to   { opacity: 0; transform: rotate(14deg) translateX(560%); }
}

/* LA PUCE. Un laiton désaturé, pas un or de carte de fidélité : le lavis de la
   page a déjà un arrêt crème, la chaleur n'y est donc pas étrangère. Deux traits
   de contact suffisent à la faire lire — une puce dessinée dans le détail
   deviendrait une illustration. */
.plaque-puce {
  position: relative;
  /* `flex: none` : sans lui, la puce est un élément flexible comme les autres et
     c'est elle que flexbox écrase en premier quand la place manque. */
  flex: none;
  width: 13cqw; height: 9.5cqw;
  border-radius: 1.8cqw;
  background: linear-gradient(152deg, #F0E4BE 0%, #C9AC63 46%, #EEE2BA 100%);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.34), 0 1px 2px rgba(12, 20, 60, 0.35);
  margin-bottom: auto;
}
.plaque-puce::before,
.plaque-puce::after {
  content: '';
  position: absolute;
  left: 22%; right: 22%;
  height: 1px;
  background: rgba(90, 70, 20, 0.42);
}
.plaque-puce::before { top: 34%; }
.plaque-puce::after  { top: 62%; }

/* LA MARQUE, EN BAS À DROITE. Une face de carte sans marque n'est pas une carte,
   c'est une maquette de carte. C'est le logotype du site, repeint en blanc par un
   MASQUE : un `img` ne se recolore pas, un masque si, et il n'y a donc aucun
   fichier de plus à produire. En filigrane, à 62 % : il signe sans réclamer. */
.plaque-marque {
  position: absolute;
  right: 8cqw; bottom: 8cqw;
  width: 22cqw; height: 4cqw;
  background: #FFFFFF;
  opacity: 0.62;
  -webkit-mask: url('/assets/logo-smspay.svg') right bottom / contain no-repeat;
          mask: url('/assets/logo-smspay.svg') right bottom / contain no-repeat;
}

/* LE CHIFFRE, EN RELIEF. Deux ombres de texte : une claire au-dessus, une
   sombre au-dessous. C'est l'estampage d'un numéro de carte, et ça ne coûte
   rien — aucun calque, aucune image. */
.plaque-face .tarif-montant {
  display: block;
  font-family: var(--f-chiffre);
  font-weight: 900;
  font-size: 15.4cqw;
  line-height: 0.95;
  letter-spacing: -0.04em;
  color: #FFFFFF;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 -1px 0 rgba(255, 255, 255, 0.5),
               0 2px 3px rgba(12, 20, 60, 0.42);
  margin-top: 6cqw;
}
/* La ligne de pied de face, en mono espacé : c'est là que figure le nom du
   porteur sur une carte. Ici, ce que le prix achète. */
.plaque-face .tarif-unite {
  display: block;
  margin-top: 3cqw;
  /* ELLE RÉSERVE LA PLACE DE LA MARQUE, qui est en position absolue dans le même
     coin : sans ce retrait, les deux se chevauchaient dès que la plaque
     rétrécissait. Vu à 1 024 px. */
  padding-right: 27cqw;
  font-family: var(--f-etiq);
  /* La seule mesure qui NE suit pas la largeur de la plaque : un mono qui
     descendrait à 8 px ne se lirait plus. */
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.78);
}

/* ── LE DISCOURS, AU FER À DROITE ────────────────────────────────────────── */
.tarif-dire { display: grid; gap: var(--e4); }
/* LE JETON AU-DESSUS DU NOM DU PLAN. `column-reverse` et non `column` : l'ordre
   du document reste le bon — le titre d'abord, puis son étiquette — donc le plan
   du document et les lecteurs d'écran annoncent bien un h2 suivi de sa mention.
   C'est l'affichage qui est retourné, pas le balisage.
   Les deux restent au fer à droite, comme tout le contenu de la carte. */
.tarif-tete {
  display: flex;
  flex-direction: column-reverse;
  align-items: flex-end;
  gap: var(--e3);
}
.tarif-plan {
  font-family: var(--f-titre);
  font-weight: 900;
  font-size: clamp(26px, 2.4vw, 34px);
  letter-spacing: -0.026em;
  line-height: 1.1;
  color: var(--texte);
}
.tarif-jeton {
  flex: none;
  font-size: 14px;
  font-weight: 600;
  color: var(--accent);
  background: var(--bleu-pale);
  border-radius: var(--rayon-plein);
  padding: var(--e2) var(--e5);
}
.tarif-descr {
  font-size: 18px;
  line-height: 1.5;
  color: var(--texte-2);
  max-width: 46ch;
  margin-left: auto;   /* le bloc se cale sur le bord droit */
}

/* ── LES QUATRE PREUVES, EN DONNÉES ──────────────────────────────────────
   Elles étaient quatre phrases cochées, sur deux colonnes : le dispositif le
   plus banal qu'un tarif puisse porter, et il enterrait ce qu'il y a de plus
   fort dans ce bloc — quatre chiffres dont trois sont des zéros. Chaque preuve
   devient donc une CASE de données : le chiffre en grand, sa phrase dessous.
   Aucun mot n'a changé ; c'est le `strong` déjà présent dans le balisage qui
   passe en bloc et devient le chiffre. */
.tarif-atouts {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--e4);
}
.tarif-atouts li {
  display: grid;
  justify-items: end;
  align-content: start;
  gap: var(--e3);
  background: var(--surface);
  border-radius: var(--rayon);
  padding: var(--e5);
  font-size: 14px;
  line-height: 1.45;
  color: var(--texte-2);
}
.tarif-atouts strong {
  display: block;
  font-family: var(--f-chiffre);
  font-weight: 900;
  font-size: clamp(24px, 2vw, 32px);
  line-height: 1;
  letter-spacing: -0.035em;
  /* LE MÊME ACCENT QUE LE « JAMAIS » de la section 06 : c'est le bleu de marque
     assombri, celui qui reste lisible en texte courant (6,7:1). Les quatre
     chiffres sont l'argument du tarif, ils portent donc la couleur qui, sur cette
     page, désigne ce qui compte. */
  color: var(--accent);
  font-variant-numeric: tabular-nums;
  margin-bottom: var(--e2);
}

/* IL N'EST PLUS UNE BARRE DE 1 180 px. Pleine largeur, il était l'élément le
   plus lourd du bloc — plus lourd que le prix, ce qui est un contresens dans un
   tarif. Il reprend sa taille et se cale au bord droit, comme tout le reste. */
.tarif-cta { margin-top: var(--e7); }

@media (max-width: 1199px) {
  .tarif-carte { grid-column: 1 / -1; grid-row: 2; }
  /* La plaque passe au-dessus du discours : côte à côte, elle n'aurait plus la
     place d'avoir le rapport d'une carte sans devenir minuscule. Elle garde son
     rapport et se borne en largeur pour ne pas devenir un panneau. */
  .tarif-haut { grid-template-columns: minmax(0, 1fr); gap: var(--e7); }
  .tarif-plaque { width: min(100%, 400px); }
  /* Quatre cases sur une largeur de tablette donneraient quatre colonnes de
     150 px : les phrases y tiendraient sur cinq lignes. Deux par deux. */
  .tarif-atouts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 599px) {
  .tarif-atouts { grid-template-columns: minmax(0, 1fr); }
  .tarif-cta { width: 100%; justify-content: center; }
}
@media (max-width: 599px) {
  .tarif-carte-corps { padding: var(--e7) var(--e6); }
}

/* Le liseré s'immobilise si le visiteur a demandé moins de mouvement : il reste
   un liseré, il cesse d'être une lueur qui tourne. */
@media (prefers-reduced-motion: reduce) {
  .tarif-carte::before { animation: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   16 · 08 · OUVREZ VOTRE DOSSIER
   ═══════════════════════════════════════════════════════════════════════════ */
.dossier-titre { grid-column: 1 / -1; }

/* ── LA SECTION EST UNE CARTE EN LAVIS ───────────────────────────────────
   POURQUOI. Le tarif et le dossier étaient deux grandes cartes BLANCHES sur deux
   sections BLANCHES, l'une après l'autre : même matière, même silhouette, et on
   s'ennuie en défilant. La section 08 reprend donc le lavis de l'accroche, de la
   section 04 et de la section 06. La page s'ouvre sur une carte en lavis et se
   ferme sur une carte en lavis, ce qui ne fait pas de mal.

   Effet de bord bienvenu : une carte blanche posée sur du lavis n'a plus besoin de
   son liseré pour exister, c'est le fond qui la détache.

   LA CHEMISE ET SON ONGLET ONT ÉTÉ RETIRÉS avec la ligne « Dossier n° … » qu'ils
   portaient. Un onglet vide n'est pas un onglet, c'est un décrochement.
   ──────────────────────────────────────────────────────────────────────── */
.sec-dossier {
  margin: var(--marge-carte);
  border-radius: var(--rayon-carte);
  overflow: clip;

  background-color: var(--lavis-brume);
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.1'/%3E%3C/svg%3E"),
    radial-gradient(72% 62% at 96% 6%, rgba(69, 95, 253, 0.16) 0%, rgba(69, 95, 253, 0) 62%),
    radial-gradient(64% 58% at 2% 100%, rgba(32, 202, 226, 0.18) 0%, rgba(32, 202, 226, 0) 64%),
    radial-gradient(34% 36% at 4% 2%, rgba(247, 236, 218, 0.58) 0%, rgba(247, 236, 218, 0) 64%),
    linear-gradient(126deg,
      var(--lavis-creme) 0%,
      var(--lavis-eau)   32%,
      var(--lavis-ciel)  66%,
      var(--lavis-brume) 100%);
  background-size: 120px 120px, auto, auto, auto, auto;
  background-repeat: repeat, no-repeat, no-repeat, no-repeat, no-repeat;
  background-blend-mode: overlay, normal, normal, normal, normal;
  background-origin: border-box;
}
/* La gouttière de la carte compense sa marge : le contenu retombe sur la même
   verticale que tout le reste de la page. */
.sec-dossier .corps { padding: 0 calc(var(--gouttiere) - var(--marge-carte)); }

/* ── LA CARTE DU FORMULAIRE ───────────────────────────────────────────────
   Ce qui vient du composant donné en référence : la carte elle-même, le découpage
   en trois zones séparées par de l'air et non par des filets, les champs en surface
   blanche cerclée avec l'anneau de focus de 3 px, l'étiquette à pleine force
   d'encre, l'erreur en boîte d'alerte, le pied en deux colonnes.
   Ce qui n'en vient pas, faute d'équivalent dans le contenu : la barre de
   progression et son compteur « 2/3 », qui supposent plusieurs étapes ; la croix de
   fermeture ; l'animation de passage d'une étape à l'autre.
   ──────────────────────────────────────────────────────────────────────── */
.formulaire {
  grid-column: 1 / -1;
  position: relative;
  display: grid;
  gap: var(--e7);
  padding: var(--e7);
  background: #FFFFFF;
  border-radius: var(--rayon-carte);
  /* Carte blanche sur section blanche : c'est le filet et l'ombre qui la
     détachent, exactement comme le `border` et le `shadow-sm` du modèle. Le
     filet est un ombrage à zéro flou et non une bordure, pour ne pas entrer
     dans la boîte et décaler le contenu d'un pixel. */
  box-shadow: 0 0 0 1px rgba(38, 52, 120, 0.08),
              0 1px 2px rgba(38, 52, 120, 0.04),
              0 26px 54px -34px rgba(38, 52, 120, 0.30);
}

/* LE CORPS. La grille des champs, inchangée : c'est elle qui portait déjà les
   deux colonnes du modèle. */
.formulaire-corps {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--e5);
  row-gap: var(--e6);
}
.pot-de-miel { position: absolute; left: -9999px; opacity: 0; pointer-events: none; }

.champ { display: flex; flex-direction: column; gap: var(--e3); border: 0; min-width: 0; }
.champ-nom   { grid-column: 1 / span 6; }
.champ-tel   { grid-column: 7 / span 6; }
.champ-metier{ grid-column: 1 / -1; }
.champ-email { grid-column: 1 / span 6; }
.champ-msg   { grid-column: 7 / span 6; }

.champ-etiquette {
  /* À PLEINE FORCE D'ENCRE, comme le Label du modèle. Elles étaient en gris
     secondaire : dans une carte blanche, une étiquette pâle au-dessus d'un champ
     blanc cerclé se lit moins bien que le champ lui-même. */
  font-size: 14px;
  font-weight: 500;
  line-height: 1.3;
  color: var(--texte);
  padding: 0;
}
.champ-obligatoire { color: var(--accent); font-weight: 500; }
.champ-facultatif { color: var(--texte-3); font-weight: 400; }

/* LE CHAMP. Surface BLANCHE cerclée d'un filet, avec une ombre de contact d'un
   pixel : c'est la matière du modèle. Il était en aplat gris sans bordure, ce
   qui se lisait bien sur une page blanche mais disparaissait dans une carte
   blanche — la carte et le champ auraient eu la même valeur. */
.champ-saisie {
  width: 100%;
  font-family: var(--f-mot);
  font-size: 16px;
  line-height: 1.35;
  color: var(--texte);
  background: #FFFFFF;
  border: 1px solid var(--trait-fort);
  border-radius: var(--rayon);
  padding: var(--e3) var(--e4);
  box-shadow: 0 1px 2px rgba(38, 52, 120, 0.05);
  transition: border-color 0.2s var(--sortie), box-shadow 0.2s var(--sortie);
}
.champ-saisie::placeholder { color: var(--texte-3); }
/* L'ANNEAU DE FOCUS, signature du modèle : la bordure prend la couleur de marque
   et un anneau de 3 px à 20 % d'opacité s'ajoute autour. Il remplace l'ancien
   procédé, qui épaississait la bordure du bas et compensait par le padding —
   donc décalait le texte d'un pixel au moment du focus. */
.champ-saisie:focus-visible {
  outline: none;
  border-color: var(--bleu);
  box-shadow: 0 0 0 3px rgba(69, 95, 253, 0.20);
}
.champ-zone { resize: vertical; min-height: 4.2em; line-height: 1.5; }

.metiers { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--e3); }
.metier { position: relative; cursor: pointer; }
.metier input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; margin: 0; cursor: pointer; }
/* Elles se rapprochent de la hauteur des champs. À 48 px de padding vertical,
   les quatre pastilles faisaient 68 px de haut contre 48 aux champs, et c'était
   la ligne la plus lourde de la carte alors qu'elle porte le choix le moins
   engageant. Le modèle donne une hauteur commune à tous ses contrôles ; ici les
   deux lignes de texte des pastilles empêchent l'égalité exacte. */
.metier span {
  display: block;
  padding: var(--e3) var(--e4);
  border: 1px solid var(--trait-fort);
  border-radius: var(--rayon-plein);
  font-size: 14px; font-weight: 500; line-height: 1.3;
  text-align: center;
  color: var(--texte-2);
  transition: border-color 0.24s var(--sortie), color 0.24s var(--sortie),
              background-color 0.24s var(--sortie);
}
.metier:hover span { border-color: var(--texte-3); color: var(--texte); }
.metier input:checked + span {
  background: var(--bleu);
  border-color: var(--bleu);
  color: #FFFFFF;
  font-weight: 600;
}
.metier input:focus-visible + span { outline: 2px solid var(--bleu); outline-offset: 3px; }

/* LE PIED, EN DEUX COLONNES. Les mentions à gauche, le bouton à droite, alignés
   sur la même ligne de base : c'est le CardFooter du modèle, `justify-between`.
   Le bouton n'est plus pleine largeur — une barre bleue de 1 226 px au bas d'une
   carte était l'élément le plus lourd de la page. */
.formulaire-pied {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--e5) var(--e7);
}
.formulaire-rgpd {
  flex: 1 1 44ch;
  font-size: 12px;
  line-height: 1.6;
  color: var(--texte-3);
  max-width: 78ch;
}
.btn-envoi { flex: none; }

/* L'ALERTE. Un cadre, un rayon, une icône, comme le composant Alert du modèle.
   Elle garde la couleur de la maison : la palette du site n'a pas de rouge, et en
   introduire un ici en ferait la seule tache de la page. Elle n'occupe aucune
   place tant qu'elle est masquée. */
.formulaire-erreur[hidden] { display: none; }
.formulaire-erreur {
  display: flex;
  align-items: flex-start;
  gap: var(--e3);
  font-size: 14px;
  line-height: 1.5;
  color: var(--accent);
  /* Un voile, pas un aplat. En bleu pâle plein, l'alerte devenait le bloc le plus
     coloré de la carte alors qu'elle n'apparaît qu'en cas d'échec. */
  background: rgba(69, 95, 253, 0.06);
  border-radius: var(--rayon);
  box-shadow: 0 0 0 1px rgba(69, 95, 253, 0.24);
  padding: var(--e4) var(--e5);
}
.alerte-ico { flex: none; display: block; }
.alerte-ico svg { display: block; overflow: visible; }

.confirmation[hidden] { display: none; }
.confirmation {
  position: absolute; inset: 0;
  display: grid; place-content: center; justify-items: start;
  gap: var(--e4);
  background: var(--bleu);
  color: #FFFFFF;
  /* Le rayon de LA CARTE, pas celui des champs : la confirmation recouvre le
     formulaire entier, ses angles doivent donc épouser les siens. */
  border-radius: var(--rayon-carte);
  padding: var(--e8);
  clip-path: inset(0 0 100% 0);
  transition: clip-path 0.7s var(--sortie);
}
.formulaire.est-envoye > *:not(.confirmation) { visibility: hidden; }
.formulaire.est-envoye .confirmation { clip-path: inset(0 0 0 0); }
.confirmation:focus { outline: none; }
.recu {
  display: inline-flex; align-items: center; gap: var(--e2);
  font-family: var(--f-etiq);
  font-size: 10px; letter-spacing: 0.18em; text-transform: uppercase;
  border: 1px solid #FFFFFF;
  border-radius: var(--rayon-plein);
  padding: var(--e2) var(--e3);
  transform: scale(0.8); opacity: 0;
}
.recu.est-tamponne {
  transform: scale(1); opacity: 1;
  transition: transform 0.5s var(--ressort) 0.25s, opacity 0.3s linear 0.25s;
}
.confirmation-titre { font-family: var(--f-titre); font-weight: 900; font-size: clamp(28px, 3.6vw, 48px); letter-spacing: -0.032em; line-height: 1; }
.confirmation-texte { font-size: var(--t-lead); max-width: 34ch; line-height: 1.4; }

/* ═══════════════════════════════════════════════════════════════════════════
   17 · PIED DE PAGE — le logo à sa juste échelle, les mentions à la leur
   ═══════════════════════════════════════════════════════════════════════════ */
/* ── LE PIED DE PAGE, UN BLOC D'ENCRE ────────────────────────────────────
   HISTOIRE COURTE. Il mesurait 413 px pour 172 px de contenu, soit 58 % d'air : la
   marque flottait seule sur sa rangée, les liens étaient noyés dans la troisième
   colonne de mentions, et deux respirations de 78 et 90 px séparaient trois lignes
   de texte. Compacté à 269 px, il était juste, et plat.

   IL EST MAINTENANT LA SEULE ZONE SOMBRE DU SITE, et c'en est la place : un pied de
   page n'est pas une section, c'est la fin. Avant, la page se terminait sur un pied
   BLANC posé sous une carte en lavis, donc sur la zone la plus pâle et la plus
   anonyme de tout le document. L'œil n'avait nulle part où atterrir.

   LA CARTE. Elle a la marge et le rayon des autres cartes de la page : le pied entre
   donc dans la même grammaire que l'accroche, la section 04, la 06 et la 08, au lieu
   d'être une bande étrangère collée dessous.

   LE FILIGRANE. Le logotype est repris en très grand au bas de la carte, rogné par
   son bord, à 6 % de blanc. C'est le dispositif que les pieds de page ont adopté en
   2026 : une marque énorme qui déborde du cadre, assez pâle pour rester une matière
   et non un cri. Il ne coûte aucun contenu — c'est le logotype du site, repeint en
   blanc par un filtre. Aucun fichier de plus.
   ──────────────────────────────────────────────────────────────────────── */
.pied { background: var(--fond); padding: 0 0 var(--marge-carte); }
.pied-carte {
  position: relative;
  /* C'est lui qui rogne le filigrane. Sans découpe, la marque géante dépasserait
     sous la carte et se poserait sur le blanc de la page. */
  overflow: clip;
  margin: 0 var(--marge-carte);
  border-radius: var(--rayon-carte);
  background: var(--encre);
  /* LA RÉSERVE BASSE EST LA PLACE DU FILIGRANE. Elle vaut 96 px et non 176 : le
     filigrane est un FOND, il a le droit de passer derrière le copyright, et
     réserver toute sa hauteur rendait le pied plus haut qu'avant sa compaction. */
  padding: var(--e8) 0 var(--e9);
}
/* Le contenu passe devant le filigrane, sans exception. */
.pied-carte .corps { position: relative; z-index: 1; }

.pied-filigrane {
  position: absolute;
  z-index: 0;
  /* IL DÉBORDE SUR TROIS CÔTÉS, et c'est tout l'effet : rogné en bas par le bord de
     la carte, à gauche et à droite parce qu'il est plus large qu'elle. Une marque
     entière et cadrée serait un logo ; une marque coupée est une matière. Aligné sur
     la gouttière, la vignette du logotype faisait un gros pâté au coin gauche —
     débordante, elle n'est plus qu'une forme qui entre dans le cadre. */
  left: -7%;
  width: 114%;
  height: auto;
  bottom: calc(var(--e9) * -1);
  pointer-events: none;
  /* LE LOGOTYPE EST EN DÉGRADÉ CYAN-BLEU. `brightness(0)` l'aplatit en noir, puis
     `invert(1)` le rend blanc : un `img` ne se recolore pas autrement, et c'est plus
     court qu'un masque. */
  filter: brightness(0) invert(1);
  opacity: 0.06;
}

.pied-tete {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--e4) var(--e6);
}
/* La marque garde son propre bloc : c'est lui qui la tient à gauche de la rangée
   quand les liens passent à la ligne sur un petit écran. */
.pied-marque { flex: none; }
.pied-logo {
  height: 30px; width: auto; display: block;
  filter: brightness(0) invert(1);
}
.pied-liens {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--e3) var(--e6);
}
/* Les liens du pied prennent la flèche des appels à l'action : c'est le même geste,
   « ça mène ailleurs », et elle avance de la même façon. Le point médian qui les
   séparait a disparu, l'écart et les flèches suffisent. */
.pied-liens a {
  display: inline-flex;
  align-items: center;
  gap: var(--e2);
  font-size: 14px;
  font-weight: 500;
  color: #FFFFFF;
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.28);
  transition: border-color 0.24s var(--sortie);
}
.pied-liens a:hover { border-bottom-color: #FFFFFF; }
.pied-liens a:focus-visible { outline: 2px solid #FFFFFF; outline-offset: 3px; }

.pied .corps { row-gap: var(--e6); }
.pied-colonnes {
  grid-column: 1 / -1;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--e6);
}
/* SUR L'ENCRE, LES OPACITÉS SONT CALÉES SUR LE CONTRASTE, pas à l'œil : 58 % de
   blanc sur #121210 donne 6,3:1, ce qui tient pour du 12 px ; le copyright est à
   48 %, soit 4,6:1, juste au-dessus du seuil. En dessous, ces deux blocs
   deviendraient illisibles avant d'être discrets. */
.pied-bloc {
  font-size: 12px;
  line-height: 1.65;
  color: rgba(255, 255, 255, 0.58);
}
.pied-bloc strong { color: rgba(255, 255, 255, 0.92); font-weight: 600; }
.pied-copyright {
  grid-column: 1 / -1;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.48);
}

/* ═══════════════════════════════════════════════════════════════════════════
   18 · BARRE MOBILE
   ═══════════════════════════════════════════════════════════════════════════ */
.barre-mobile {
  position: fixed;
  left: var(--e4); right: var(--e4); bottom: var(--e4);
  z-index: 95;
  display: none;
  transform: translate3d(0, 0, 0);
  transition: transform 0.45s var(--sortie), opacity 0.3s linear;
}
.barre-mobile.est-cachee { transform: translate3d(0, 160%, 0); opacity: 0; }
.btn-barre { width: 100%; justify-content: center; background: var(--bleu); color: #FFFFFF; font-weight: 700; padding: var(--e5); }
@media (max-width: 899px) { .barre-mobile { display: block; } }

/* ═══════════════════════════════════════════════════════════════════════════
   19 · LES PAGES ANNEXES — l'accusé de réception, les conditions, l'introuvable
   ---------------------------------------------------------------------------
   Trois pages qui ne sont pas l'accueil : /merci, /cguv, et la page servie
   quand une adresse n'existe pas. Elles reprennent l'en-tête, le pied de page
   et tous les jetons du site ; ce bloc n'ajoute que ce dont l'accueil n'avait
   pas besoin.

   AUCUNE DE CES PAGES N'A DE FEUILLE DE STYLE À ELLE, ni de style en attribut.
   La page /merci en avait une, en attribut, dans la version précédente du site :
   la moitié de sa mise en page vivait dans son propre <head>, si bien qu'une
   retouche de la marque en oubliait la moitié. Tout est ici, à un seul endroit,
   et c'est ce que contrôle tools/verifie.mjs — une classe employée dans une
   page sans aucune règle est la signature d'un bloc perdu.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── LE CHAPEAU — la carte en lavis, ramenée à la hauteur d'un titre ──────
   C'est la carte du hero, sans la scène et sans le plein écran : un document
   contractuel n'a pas d'accroche à faire, et sa première ligne utile doit être
   lisible sans défiler. Le lavis reste le seul endroit coloré de la page,
   comme sur l'accueil où tout ce qui suit le hero est blanc.

   LE GRAIN DE FILM N'EST PAS REPRIS. Sur les 100 vh du hero il donne sa matière
   au dégradé ; sur une bande de 260 px il n'est plus qu'un fichier de plus à
   décoder. Les deux lueurs et la soie à 150° sont en revanche les mêmes
   valeurs, au chiffre près : les deux cartes doivent être de la même famille.
   ──────────────────────────────────────────────────────────────────────── */
.chapeau {
  position: relative;
  overflow: clip;
  margin: var(--marge-carte);
  border-radius: var(--rayon-carte);
  /* L'en-tête est flottant : sans cette réserve en haut, l'étiquette passerait
     dessous. En bas, le pas des sections. */
  padding: calc(var(--entete-h) + var(--e9)) 0 var(--e9);

  background-color: var(--lavis-brume);
  background-image:
    radial-gradient(88% 120% at 4% -24%, rgba(69, 95, 253, 0.16) 0%, rgba(69, 95, 253, 0) 60%),
    radial-gradient(76% 116% at 100% 124%, rgba(32, 202, 226, 0.20) 0%, rgba(32, 202, 226, 0) 62%),
    linear-gradient(150deg,
      var(--lavis-brume) 0%,
      var(--lavis-ciel)  34%,
      var(--lavis-eau)   68%,
      var(--lavis-creme) 100%);
  background-origin: border-box;
}

/* La carte est en retrait de --marge-carte : sans cette déduction, son contenu
   tomberait ces quelques pixels plus à droite que les titres des sections
   suivantes, et la verticale commune du site serait rompue sur ces trois pages.
   C'est le calcul que fait déjà le hero. */
.chapeau-corps {
  display: block;
  padding-left: calc(var(--gouttiere) - var(--marge-carte));
  padding-right: calc(var(--gouttiere) - var(--marge-carte));
}

.chapeau-etiquette {
  font-family: var(--f-etiq);
  font-size: var(--t-etiq);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--texte-3);
  margin-bottom: var(--e5);
}
.chapeau-titre { max-width: 20ch; }
.chapeau-date {
  margin-top: var(--e5);
  font-family: var(--f-etiq);
  font-size: 12px;
  color: var(--texte-2);
}

/* ── LE DOCUMENT — le sommaire à gauche, le texte à droite ────────────────
   LE SOMMAIRE EST COLLANT et ce n'est pas un ornement : le document compte
   quatorze articles, dont deux dépassent l'écran à eux seuls. Sans lui, la
   seule façon d'atteindre l'article 9 est de faire défiler les huit premiers
   en les lisant de l'œil pour ne pas le rater.

   LA COLONNE DE LECTURE EST BORNÉE À 68 CARACTÈRES. Sur 1 520 px, une ligne de
   texte courant en fait plus de 200 : l'œil ne retrouve pas le début de la
   ligne suivante. C'est la seule vraie contrainte de mise en page d'un
   document de cette longueur.
   ──────────────────────────────────────────────────────────────────────── */
/* Le document suit une carte, pas une section : le pas complet du site ferait
   compter deux fois l'air que la marge de la carte a déjà donné. */
.sec-doc { padding-top: var(--e8); }
.doc { align-items: start; }

.doc-sommaire {
  grid-column: 1 / span 3;
  position: sticky;
  top: calc(var(--entete-h) + var(--e5));
  align-self: start;
}
.doc-sommaire-titre {
  font-family: var(--f-etiq);
  font-size: var(--t-etiq);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--texte-3);
  padding-bottom: var(--e3);
  margin-bottom: var(--e3);
  border-bottom: 1px solid var(--trait);
}
.doc-sommaire-liste { list-style: none; display: grid; gap: 2px; }
.doc-sommaire-liste a {
  display: grid;
  grid-template-columns: 2.4ch minmax(0, 1fr);
  gap: var(--e3);
  padding: 7px var(--e3);
  margin-left: calc(var(--e3) * -1);
  border-radius: var(--e2);
  font-size: 14px;
  line-height: 1.35;
  color: var(--texte-2);
  text-decoration: none;
  transition: background-color 0.2s var(--sortie), color 0.2s var(--sortie);
}
.doc-sommaire-liste a:hover { background: var(--surface); color: var(--texte); }
.doc-somm-num {
  font-family: var(--f-etiq);
  font-size: 11px;
  color: var(--accent);
  padding-top: 2px;
}
.doc-somm-mot { min-width: 0; }

.doc-lecture {
  grid-column: 5 / -1;
  max-width: 68ch;
}

/* Le préambule n'est pas un article : il n'a pas de numéro, il pose le contrat.
   Un panneau le distingue des quatorze qui suivent, sans lui donner plus de
   poids qu'ils n'en ont. */
.doc-preambule {
  background: var(--surface);
  border-radius: var(--rayon);
  padding: var(--e5) var(--e6);
}
.doc-preambule p {
  font-size: 15px;
  line-height: 1.6;
  color: var(--texte-2);
}
.doc-preambule p + p { margin-top: var(--e3); }

/* Le filet entre deux articles : c'est le seul trait du document. Les titres
   seuls ne suffisaient pas à séparer quatorze blocs de texte de longueurs
   très inégales. */
.doc-article + .doc-article,
.doc-preambule + .doc-article {
  margin-top: var(--e8);
  padding-top: var(--e8);
  border-top: 1px solid var(--trait);
}

.doc-titre {
  display: flex;
  align-items: baseline;
  gap: var(--e4);
  font-family: var(--f-titre);
  font-weight: 900;
  font-size: var(--t-h3);
  line-height: 1.15;
  letter-spacing: -0.024em;
  text-wrap: balance;
}
.doc-numero {
  flex: none;
  font-family: var(--f-etiq);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--accent);
}
.doc-sous-titre {
  margin-top: var(--e6);
  font-family: var(--f-titre);
  font-weight: 700;
  font-size: 17px;
  letter-spacing: -0.012em;
  line-height: 1.3;
}
.doc-article p {
  margin-top: var(--e4);
  font-size: 16px;
  line-height: 1.65;
  color: var(--texte-2);
}
.doc-liste {
  list-style: none;
  margin-top: var(--e4);
  display: grid;
  gap: var(--e2);
}
.doc-liste li {
  position: relative;
  padding-left: var(--e5);
  font-size: 16px;
  line-height: 1.6;
  color: var(--texte-2);
}
/* La puce est l'anneau du logo en tout petit : un point, pas un tiret. */
.doc-liste li::before {
  content: '';
  position: absolute;
  left: 0; top: 0.62em;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--bleu-pale);
}

/* ── L'ACCUSÉ DE RÉCEPTION — le même bloc bleu, en pleine page ────────────
   Un visiteur avec JavaScript ne voit jamais cette page : sa confirmation
   recouvre le formulaire sur place. Sans JavaScript, le formulaire part en POST
   classique et notify.php redirige ici. LES DEUX CHEMINS DOIVENT DONNER LA MÊME
   CHOSE : même aplat de bleu, même tampon, mêmes mots. C'est pourquoi la page
   emprunte .confirmation-titre et .confirmation-texte au formulaire au lieu de
   s'en écrire des jumeaux qui divergeraient à la première retouche.
   ──────────────────────────────────────────────────────────────────────── */
.sec-accuse { padding-top: calc(var(--entete-h) + var(--e9)); }
.accuse {
  grid-column: 1 / -1;
  display: grid;
  align-content: center;
  justify-items: start;
  gap: var(--e4);
  min-height: min(56vh, 480px);
  padding: clamp(32px, 6vw, 96px);
  border-radius: var(--rayon-carte);
  background: var(--bleu);
  color: #FFFFFF;
}
.accuse .confirmation-texte { color: rgba(255, 255, 255, 0.86); }
.accuse-liens {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e4) var(--e6);
  margin-top: var(--e5);
}
/* Le lien souligné de la maison, repeint pour tenir sur l'aplat bleu. */
.lien-clair {
  color: #FFFFFF;
  background-image: linear-gradient(#FFFFFF, #FFFFFF);
}
.lien-clair:hover { color: #FFFFFF; }
.lien-clair:focus-visible { outline-color: #FFFFFF; }

/* ── ADRESSE INTROUVABLE ──────────────────────────────────────────────────
   LE NOMBRE EST LE SUJET DE LA PAGE. Il est écrit dans la police des chiffres
   du site et peint du dégradé de marque, comme les mots-clés des titres — donc
   avec la même précaution : le dégradé se découpe dans la boîte de l'élément,
   et un bloc pleine largeur n'en recevrait que la première moitié. D'où le
   `width: fit-content`, exactement comme pour la ligne d'accroche du hero.

   LA PAGE DONNE LA SORTIE. Le site tient en trois pages : un 404 qui n'offre
   qu'un « retour à l'accueil » laisse le visiteur refaire seul le chemin.
   ──────────────────────────────────────────────────────────────────────── */
.sec-perdu { padding-top: calc(var(--entete-h) + var(--e9)); }
.perdu { grid-column: 1 / -1; }
.perdu-etiquette {
  font-family: var(--f-etiq);
  font-size: var(--t-etiq);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--texte-3);
}
.perdu-nombre {
  width: fit-content;
  margin: var(--e3) 0 var(--e6);
  font-family: var(--f-chiffre);
  font-size: clamp(96px, 21vw, 240px);
  line-height: 0.78;
  letter-spacing: -0.05em;
}
.perdu-titre { max-width: 16ch; }
.perdu-texte {
  margin-top: var(--e5);
  max-width: 46ch;
  font-size: 17px;
  line-height: 1.55;
  color: var(--texte-2);
}
.perdu-sorties {
  list-style: none;
  display: grid;
  gap: var(--e4);
  max-width: 42ch;
  margin-top: var(--e7);
  padding-top: var(--e6);
  border-top: 1px solid var(--trait);
}

/* ── Les pages annexes en petite largeur ─────────────────────────────────
   Le sommaire cesse d'être une colonne : sous 1 024 px il n'en reste pas assez
   pour poser quatorze titres à côté du texte. Il passe au-dessus du document,
   où il reste ce qu'il est — la liste des articles, cliquable. */
@media (max-width: 1023px) {
  .doc-sommaire { grid-column: 1 / -1; position: static; }
  .doc-sommaire-liste {
    grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
    gap: 2px var(--e4);
  }
  .doc-lecture { grid-column: 1 / -1; }
}
@media (max-width: 899px) {
  .chapeau { padding: calc(var(--entete-h) + var(--e8)) 0 var(--e8); }
  .doc-article + .doc-article,
  .doc-preambule + .doc-article { margin-top: var(--e7); padding-top: var(--e7); }
  .sec-accuse, .sec-perdu { padding-top: calc(var(--entete-h) + var(--e7)); }
  /* La barre mobile n'existe pas sur ces pages : rien à réserver en bas. */
  .accuse { min-height: 0; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   20 · RESPONSIVE
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 1279px) {
  :root { --e11: 132px; --e10: 104px; }
  .hero { grid-template-columns: minmax(0, 1fr) minmax(0, 46%); }
  .hero-champ { padding-right: var(--e8); }
  .addition-tpe { grid-column: 1 / span 6; }
  .addition-smspay { grid-column: 7 / span 6; }
  .tarif-zeros { grid-column: 9 / span 4; }
}

@media (max-width: 1279px) {
  /* Palier intermédiaire. Le hero garde ses deux colonnes, mais la colonne de
     droite n'est plus assez large pour poser le message À CÔTÉ de l'appareil :
     il repasse dessous. Superposer davantage aurait mangé la moitié de l'écran.
     La pastille perd son troisième fait, qui la faisait passer sur deux lignes. */
  .scene {
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding-top: 0;
  }
  .mobile { position: static; top: auto; width: min(100%, 372px); margin-bottom: 0; }
  .mobile-ecran { padding-bottom: var(--e5); }
  .bulle {
    position: static;
    width: min(100%, 32ch);
    margin-top: calc(var(--e6) * -1);
    z-index: 3;
  }
  .bulle-texte { min-height: 3.4em; }
  .scene-anneau { width: min(46vw, 460px); top: 44%; left: 50%; }
  .hero-preuve-plus { display: none; }
}

@media (max-width: 1023px) {
  /* Le split se défait : le titre d'abord, la scène ensuite. */
  .hero { grid-template-columns: 1fr; min-height: 0; row-gap: var(--e6); }
  .hero-champ { padding: var(--e9) 0 var(--e5); }
  .hero-titre { max-width: 18ch; }
  /* La scène se remet à plat : l'appareil au centre, entier, et la bulle
     dessous plutôt que par-dessus. Superposer sur 430 px de large cacherait
     l'écran, qui est justement ce qu'on vient montrer. */
  .scene {
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    padding: 0 0 var(--e7);
  }
  .scene-anneau { width: min(88vw, 420px); top: 38%; left: 50%; }
  .mobile { position: static; top: auto; width: min(100%, 300px); margin-bottom: 0; }
  .mobile-ecran { padding-bottom: var(--e5); }
  .bulle {
    position: static;
    width: min(100%, 34ch);
    margin-top: calc(var(--e6) * -1);
    z-index: 3;
  }
  .bulle-texte { min-height: 3.4em; }
  /* Le titre en marge cesse d'être une marge : il repasse en tête de section. */
  .tete-releve { grid-column: 1 / -1; }
  .marche-titre, .dossier-titre, .ticket-titre { grid-column: 1 / -1; }
  /* LE TRAJET SE REDRESSE. Sur une colonne, les trois objets se suivent avec leur
     légende à droite : la voie horizontale n'a plus lieu d'être et disparaît. C'est
     le seul cas où la rangée est la bonne forme, puisqu'il n'y en a plus. */
  .trajet { grid-template-columns: auto minmax(0, 1fr); column-gap: var(--e5); row-gap: var(--e7); }
  .trajet-voie { display: none; }
  .trajet-piece-1, .trajet-piece-2, .trajet-piece-3 {
    grid-column: 1; justify-self: start; align-self: center;
  }
  .trajet-piece-1 { grid-row: 1; }
  .trajet-piece-2 { grid-row: 2; }
  .trajet-piece-3 { grid-row: 3; }
  /* LA SOUS-GRILLE EST ANNULÉE. Sur une colonne, chaque légende n'occupe plus qu'UNE
     rangée : une sous-grille d'une seule rangée y empile le libellé et son détail au
     même endroit, donc superposés — et `align-content: end` les remettait en plus
     dans l'ordre inverse. Vu à l'écran, à 430 px. En flux normal, ils se suivent. */
  .trajet-note {
    display: block;
    grid-template-rows: none;
    align-content: normal;
  }
  /* L'écart entre le libellé et son détail était le `row-gap` de la grille ; en flux
     normal, il redevient une marge. */
  .etape-role { margin-bottom: var(--e2); }
  .trajet-note-1, .trajet-note-2, .trajet-note-3 {
    grid-column: 2; align-self: center; text-align: left;
  }
  .trajet-note-1 { grid-row: 1; }
  .trajet-note-2 { grid-row: 2; }
  .trajet-note-3 { grid-row: 3; }
  .trajet-note-2 .etape-role,
  .trajet-note-3 .etape-role { justify-content: flex-start; }
  /* La preuve repasse en une colonne, l'affirmation au-dessus de ses preuves. */
  .preuve { grid-template-columns: 1fr; row-gap: var(--e7); }
  .preuve-titre { max-width: 26ch; }
  /* Les rangées sont libérées : en une colonne, le prix et les trois zéros
     doivent se suivre, pas se superposer dans la même case. */
  .tarif-prix, .tarif-zeros, .tarif-mentions { grid-column: 1 / -1; grid-row: auto; }
  .tarif-zeros { align-self: start; }
  .pied-colonnes { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 899px) {
  :root { --e11: 104px; --e10: 84px; --e9: 72px; }
  /* La réserve basse dégage la barre fixe. Elle est sur la CARTE et non sur le pied :
     c'est elle qui porte le fond sombre, et la barre passe par-dessus. */
  .pied-carte { padding-bottom: calc(var(--e6) + 60px); }
  /* LE FILIGRANE DOIT GRANDIR EN MÊME TEMPS QUE LA CARTE RÉTRÉCIT. À 114 % de large
     sur une carte de 410 px, il ne faisait plus que 87 px de haut et tombait
     entièrement sous le bord : on ne voyait qu'une grande zone sombre vide. À 200 %,
     il en dépasse assez pour redevenir une matière. Vu à l'écran, à 430 px. */
  .pied-filigrane { left: -70%; width: 240%; bottom: calc(var(--e5) * -1); }
  .champ-nom, .champ-tel, .champ-email, .champ-msg { grid-column: 1 / -1; }
  .metiers { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .garanties { grid-template-columns: 1fr; }
  .addition-tpe, .addition-smspay { grid-column: 1 / -1; }
  .addition-barre { top: 50%; }
  .addition-trou { flex: 1 1 auto; margin-left: 0; }
}

@media (max-width: 599px) {
  :root { --e11: 84px; --e10: 68px; --gouttiere: 20px; }
  .corps { column-gap: var(--e4); row-gap: var(--e6); }
  /* La carte en verre resserre son air : 48 px de padding sur une colonne de
     390 px ne laissaient plus grand-chose au texte. */
  .marche-champ { --carte-pad: var(--e5); }
  /* La carte du formulaire resserre son air, et son bouton prend toute la
     largeur : 251 px sous un bloc de mentions de 326 px paraissaient timides. */
  .formulaire { padding: var(--e6); gap: var(--e6); }
  .btn-envoi { flex: 1 1 100%; justify-content: center; }
  .hero-champ { padding-top: var(--e8); }
  .hero-actions { flex-direction: column; align-items: stretch; }
  .hero-actions .btn { justify-content: center; }
  .journal-ligne-payee { margin: 0 calc(var(--e4) * -1); padding: var(--e4); }
  .metiers { grid-template-columns: 1fr; }
  .pied-colonnes { grid-template-columns: 1fr; }
  .confirmation { padding: var(--e5); }
}

/* ═══════════════════════════════════════════════════════════════════════════
   21 · MOUVEMENT RÉDUIT — tout est livré en place
   ═══════════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .js [data-rev], .js [data-pose] { clip-path: none; opacity: 1; transform: none; }
  .curseur { display: none; }
  .addition-tpe .addition-barre { transform: scaleX(1); }

  /* La bande ne défile pas : les noms restent lisibles, à l'arrêt. */
  /* La bande ne défile pas : les logos se rangent, à l'arrêt et centrés. */
  .bande-piste { animation: none; flex-wrap: wrap; justify-content: center; gap: var(--e7); padding-right: 0; }
  .bande-piste:nth-child(n+2) { display: none; }
  .bande { flex-wrap: wrap; padding: var(--e5) var(--gouttiere); }
  .bande { -webkit-mask-image: none; mask-image: none; }
}

/* ── Repli sans JavaScript : tout est visible, rien n'est masqué ────────── */
.etat { opacity: 1; }
.etat-conf::after { transform: scale(1); }
.js .etat { opacity: 0; }
.js .etat.est-inscrit { opacity: 1; }
.js .etat-conf::after { transform: scale(0); }
.js .etat-conf.est-inscrit::after { transform: scale(1); }
.recu { opacity: 1; transform: none; }
.js .recu { opacity: 0; transform: scale(0.8); }
.js .recu.est-tamponne { opacity: 1; transform: scale(1); }
