/* ============================================================
   Satoshi : SERVIE EN LOCAL (assets/fonts/), et non plus par fontshare.
   ------------------------------------------------------------
   Les .woff2 sont les fichiers EXACTS que servait cdn.fontshare.com :
   le rendu est identique au pixel. Trois raisons de les avoir rapatriés :

   1. VITESSE. La feuille venait de api.fontshare.com et les polices de
      cdn.fontshare.com : deux origines de plus à résoudre (DNS + TCP +
      TLS) AVANT le premier texte peint, et la 2e n'était découverte
      qu'une fois la 1re téléchargée puis analysée. En local, la connexion
      est déjà ouverte et les fichiers sont préchargés dès la 1re ligne
      du <head>.
   2. VIE PRIVÉE. Chaque visite envoyait l'adresse IP du visiteur à un
      tiers américain, sans consentement et sans que la page
      « Confidentialité » ne le mentionne. C'est exactement ce qui a valu
      des condamnations à des sites utilisant Google Fonts en Europe.
   3. CHAÎNE D'APPROVISIONNEMENT. Un CDN tiers dans la CSP, c'est un
      domaine de plus autorisé à injecter du style dans la page. Il est
      maintenant retiré de la CSP : tout est en 'self'.

   Si une graisse doit être ajoutée un jour, télécharger le .woff2 depuis
   fontshare, le poser ici, et ajouter un bloc identique.
   ============================================================ */
@font-face {
  font-family: "Satoshi";
  src: url("assets/fonts/satoshi-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Satoshi";
  src: url("assets/fonts/satoshi-500.woff2") format("woff2");
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Satoshi";
  src: url("assets/fonts/satoshi-700.woff2") format("woff2");
  font-weight: 700; font-style: normal; font-display: swap;
}

/* ============================================================
   basarc : landing page
   Typo : Satoshi. Échelle & espacements MESURÉS sur la maquette
   de référence (export mobile 402 px = px CSS réels).
   ============================================================ */

:root {
  /* --- Couleurs (tokens sémantiques) --- */
  --bg:            #ffffff;
  --ink:           #131315;   /* titres */
  --muted:         #6b6f76;   /* corps de texte gris */
  --faint:         #9aa0a8;   /* eyebrow / labels */
  --line:          #e7e7ea;   /* bordures claires */
  --raise:         #8a2b2b;   /* bordeaux sourd : seul accent coloré du site, réservé
                                 au prix de la prochaine session */
  --beurre:        #efe2a2;   /* jaune beurre : uniquement le pied de page */
  --black:         #101012;   /* boutons / section sombre */

  --dark-bg:       #0f0f11;
  --dark-title:    #f6f6f7;
  --dark-text:     #9b9ba2;
  --dark-plc:      #34343a;   /* placeholder média */
  --dark-hair:     rgba(255,255,255,.08);

  /* --- Rayons --- */
  --r-btn:         14px;
  --r-pill:        999px;
  --r-media:       8px;
  --r-card:        22px;

  /* --- Ombres ---
     Les cartes ordinaires portent le seul filet de contact (0 1px 2px) écrit à
     même leur règle. --ombre-hl est réservée aux surfaces MISES EN AVANT : la
     colonne basarc du comparatif, le format recommandé, les garanties et
     l'issue à choisir. Elle ajoute au filet de contact une nappe large et très
     douce (44px de flou à 8 %) : la carte se décolle du fond gris sans qu'on
     voie une ombre, ce qui la sépare de ses voisines avant même la lecture.
     Une seule définition : ces 4 surfaces disent la même chose, elles doivent
     flotter à la même hauteur. */
  --ombre-hl:      0 1px 2px rgba(16, 16, 18, .04),
                   0 20px 44px rgba(16, 16, 18, .08);

  /* --- Grille d'espacement --- */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 20px; --s6: 24px; --s7: 32px; --s8: 40px;
  --s9: 48px; --s10: 56px; --s11: 64px;

  /* --- Échelle typographique (mesurée) --- */
  --t-eyebrow: 13px;
  --t-body:    16px;
  --t-btn:     15px;
  --t-h2:      28px;   /* les deux titres = même taille */
  --t-h1:      28px;

  /* --- Gouttière et largeur de contenu ---
     La page occupe TOUT l'écran (plus de carte posée sur un fond gris). Ce
     n'est donc plus une max-width sur .page qui tient les proportions, c'est la
     gouttière : elle grandit avec l'écran pour que la colonne de contenu reste
     à --contenu, pendant que les fonds (blanc, plaque sombre, pied de page)
     filent d'un bord à l'autre. Sur petit écran le max() retombe sur les 20px
     mesurés d'origine : le dessin de référence ne bouge pas d'un pixel. */
  --contenu: 402px;                                     /* colonne mobile (iPhone 16 Pro) */
  --pad: max(20px, calc((100vw - var(--contenu)) / 2)); /* gouttière (mesurée : 20px) */
  /* Hauteur du header. Elle sert à TROIS choses : figer le hero juste dessous
     (.plate--one), calculer le « 1 écran » du hero, et décaler les ancres
     internes (scroll-margin-top). Les trois étaient donc faussées ensemble.
     Elle valait 56px, calculée sur le CTA (10 + 36 + 10). Mais le plus haut
     enfant du header n'est pas le CTA : c'est le bouton du menu, qui mesure
     40px (.menu__toggle). La vraie hauteur est 10 + 40 + 10 = 60px, mesurée.
     Les 4px d'écart se voyaient en trois endroits : le hero se figeait 4px
     SOUS le bord du header (donc 4px de hero cachés derrière le verre), le
     hero dépassait d'autant la hauteur d'un écran, et la plaque sombre restait
     4px sous la ligne de flottaison au repos.
     `env(safe-area-inset-top)` est repris du padding du header juste en dessous.
     Sans lui, le token se retrouve court de toute la hauteur de l'encoche sur
     les appareils où elle compte (la page est en `viewport-fit=cover`), et les
     mêmes trois calculs repartent en biais. Repris ici, le token suit le header
     par construction : il ne peut plus s'en désolidariser. */
  --header-h: calc(60px + env(safe-area-inset-top));

  /* On déclare le schéma de couleurs de la page. Sans cette ligne, `color-scheme`
     vaut `normal` : le navigateur ne sait pas que la page est conçue en clair et,
     poste en thème sombre, il peut assombrir de lui-même ce qu'il dessine : les
     barres de défilement, les commandes de formulaire, et sur Android Chrome le
     thème sombre automatique qui INVERSE toute la page. Le site n'a aucune règle
     prefers-color-scheme : cette déclaration ne change donc rien à son rendu, elle
     ferme seulement la porte à une inversion décidée par le navigateur. */
  color-scheme: light;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }

body {
  font-family: "Satoshi", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  background: var(--bg);          /* la page occupe tout l'écran : ce fond ne se voit plus */
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  font-feature-settings: "ss01", "cv01";
  -webkit-tap-highlight-color: transparent;   /* pas de halo gris au tap (états :active custom) */
}

/* Supprime le délai de tap 300ms sur les éléments interactifs */
.btn, .logo { touch-action: manipulation; }

/* A2 : zones tactiles ≥44px SANS toucher au visuel (hit-slop invisible) */
.logo, .btn { position: relative; }
.logo::before, .btn::before {
  content: "";
  position: absolute;
  z-index: 0;                 /* transparent : n'affiche rien, capte juste le tap */
}
.logo::before { inset: -6px; }     /* 32 → 44 */
.btn::before  { inset: -2px 0; }   /* 40 → 44 (hauteur) */

.page {
  margin: 0;
  background: var(--bg);
  min-height: 100dvh;
}

/* ===================== EFFET PLAQUES (sticky overlap) ===================== */
/* Plaque 1 (claire) se fige en haut ; Plaque 2 (sombre) glisse par-dessus. */
.plate--one {
  position: sticky;
  top: var(--header-h);       /* se fige SOUS le header dès le 1er px -> hero stable, 0 déplacement */
  z-index: 1;
  background: var(--bg);
}
.plate--two {
  position: relative;
  z-index: 2;                                   /* passe au-dessus de la plaque 1 */
  /* COINS HAUTS ARRONDIS. La plaque GLISSE par-dessus le hero figé : c'est une
     surface qui passe devant une autre, et deux angles droits la faisaient lire
     comme une coupure de la page plutôt que comme un panneau qui recouvre.
     Le rayon n'est arrondi qu'EN HAUT : le bas ne recouvre rien, il rend la main
     au flux normal, un arrondi y ouvrirait une encoche claire sur rien.
     --r-card (22px) et non 16px : le fichier réserve déjà 16px aux composants
     (.quote, .tcard, la pilule du header) et --r-card à la CARTE DE PAGE, la
     surface qui porte tout le reste (voir .page dans evaluation.css et .legal
     dans legal.css, ses deux seuls autres emplois). Cette plaque est de cette
     famille-là, pas de celle des cartes posées dessus.
     L'ombre est inchangée : elle suit le rayon d'elle-même. */
  border-radius: var(--r-card) var(--r-card) 0 0;
  /* Bord droit + ombre. Géométrie inchangée ;
     seule l'opacité descend de .45 à .30 : à .45 l'ombre valait encore ~37 %
     au ras du bord, soit un gris franc sur le blanc du hero, qui se lisait
     comme un trait quand la barre haute la pinçait. À .30 : ~25 %. */
  box-shadow: 0 -20px 44px rgba(0, 0, 0, .30);
}

a { text-decoration: none; color: inherit; }
img { max-width: 100%; display: block; }

/* Accessibilité : focus visible cohérent */
a:focus-visible,
button:focus-visible {
  outline: 2px solid #4c8dff;
  outline-offset: 3px;
  border-radius: 6px;
}

/* ===================== HEADER (barre unique qui se métamorphose) ===================== */
/* Un seul élément : plat & posé sur le hero, puis pilule au scroll.
   Épinglé (sticky) AU-DESSUS des deux plaques -> jamais recouvert.
   EFFET VERRE MAT EN PERMANENCE : le flou est présent dans les deux états
   (blur identique -> jamais animé, donc pas de coût de transition GPU) ;
   seuls la forme, l'opacité du fond et l'ombre changent au scroll. */
.siteheader {
  position: sticky;
  top: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  gap: var(--s3);
  margin: 0;
  /* Géométrie CONSTANTE dans les deux états -> le contenu (logo + CTA) ne bouge
     JAMAIS. Seule la plaque de verre ::before se détache au scroll.
     Hauteur = 60px (= --header-h) : 10 + 40 + 10, où 40 est la hauteur du BOUTON
     DU MENU, le plus haut des trois enfants. Ce commentaire annonçait 56px en
     comptant le CTA (36px) : c'est de là que venait l'erreur du token. */
  padding: calc(10px + env(safe-area-inset-top)) var(--pad) 10px;
  background: transparent;              /* le verre mat est porté par ::before */
  border-radius: 0;
}
/* Verre mat porté par un PSEUDO-ÉLÉMENT : le backdrop-filter n'est pas un ancêtre
   du panneau du menu (pas d'imbrication de flous). C'est LUI, et lui seul, qui
   s'anime : il se rétracte de 6px (haut/bas) et 12px (côtés) pour se détacher en
   pilule flottante. Le contenu, lui, reste fixe -> alignement garanti. */
.siteheader::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;                          /* plat : suit la barre (0 mobile, coins carte sur desktop) */
  background: rgba(250, 250, 251, .72);            /* verre mat (translucide + flou) */
  -webkit-backdrop-filter: blur(18px) saturate(1.4);
  backdrop-filter: blur(18px) saturate(1.4);
  box-shadow: 0 0 0 0 rgba(0, 0, 0, 0);
  transition:
    inset .34s ease,
    border-radius .34s ease,
    background-color .34s ease,
    box-shadow .34s ease;
}
/* Pilule flottante détachée : SEULE la plaque change (inset + rayon + fond + ombre). */
.siteheader.is-condensed::before {
  /* La pilule SUIT LA COLONNE DE CONTENU, elle ne suit pas le bord de l'écran.
     Le retrait latéral valait 12px en dur, mesuré sur mobile où la gouttière
     fait 20px : la pilule dépassait donc le contenu de 8px de chaque côté, et
     c'est ce rapport-là qui fait le dessin. Mais --pad grandit avec l'écran
     (il centre la colonne) pendant que le 12px, lui, ne bougeait pas : le
     débordement passait à 171px sur tablette, 104px à 1440, 464px sur un 2560.
     La pilule finissait par tenir presque toute la largeur de la fenêtre avec
     le logo et le bouton du menu perdus loin de ses extrémités.
     `var(--pad) - 8px` REPREND le rapport mobile et le rend valable partout.
     Sur mobile il vaut 20 - 8 = 12px : la référence ne bouge pas d'un pixel. */
  inset: 6px calc(var(--pad) - 8px);
  border-radius: 16px;
  /* Même verre que le panneau du menu : couleur, transparence (.58) et matière (flou). */
  background: rgba(20, 20, 24, .58);
  -webkit-backdrop-filter: blur(26px) saturate(1.5);
  backdrop-filter: blur(26px) saturate(1.5);
  box-shadow: 0 12px 30px rgba(0, 0, 0, .28);   /* liseré interne retiré : pilule brute */
}
/* Contenu lisible sur la pilule sombre (état « déployé » au scroll) : logo inversé
   (disque clair, étoile sombre) et points en clair. Transition douce. */
.logo svg circle, .logo svg path { transition: fill .34s ease; }
.siteheader.is-condensed .logo svg circle { fill: #f4f4f6; }
.siteheader.is-condensed .logo svg path   { fill: #14141a; }
.siteheader.is-condensed .menu__grid i { background: #f4f4f6; }

.logo { flex: 0 0 auto; display: inline-flex; }
.logo svg { width: 32px; height: 32px; display: block; }   /* mesuré : 32px, constant dans les deux états */

/* Repère invisible qui déclenche la condensation (voir le JS). Ancré au vrai
   haut de la plaque sombre -> déclenchement précis quand elle atteint le header. */
.nav-mark { position: absolute; top: 0; left: 0; width: 0; height: 0; }

/* CTA du header : « Reprendre le contrôle ». Style CONSTANT dans les deux états
   (aucun morph) -> rien à animer, rien à désaligner. Coins carré-doux. */
.hcta {
  position: relative;
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 36px;
  padding: 0 16px;
  border: 1px solid var(--line);
  border-radius: 10px;                  /* carré-doux (léger arrondi), plus pilule */
  background: #fff;
  color: var(--ink);
  font-size: var(--t-btn);
  font-weight: 700;   /* Satoshi n'a pas de 600 -> résolu en 700 : on l'écrit explicitement */
  white-space: nowrap;
  touch-action: manipulation;
  transition: transform .18s ease;
}
.hcta::after { content: ""; position: absolute; inset: -5px 0; }   /* hit-slop 44px */
.hcta:active { transform: scale(.98); }

/* ===================== MENU MORPHING (façon offmenu) ===================== */
.menu { position: relative; margin-left: auto; z-index: 40; }

/* Déclencheur : point + grille 3x3, toujours au-dessus du panneau */
.menu__toggle {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 9px;
  height: 40px;
  padding: 0 6px;
  background: transparent;
  border: none;
  cursor: pointer;
  touch-action: manipulation;
}
.menu__grid {
  display: grid;
  grid-template-columns: repeat(3, 4.5px);
  grid-auto-rows: 4.5px;
  gap: 4.5px;
  transition: transform .45s cubic-bezier(.2, .85, .25, 1);
}
.menu__grid i {
  width: 4.5px; height: 4.5px;
  border-radius: 50%;
  background: #101012;                 /* sombre : visible sur le header clair (menu fermé) */
  transition: background-color .28s ease, opacity .28s ease, transform .28s ease;
}
/* Front de vague anti-diagonal : --f = 0 (haut-gauche) -> 4 (bas-droite). */
.menu__grid i:nth-child(1) { --f: 0; }
.menu__grid i:nth-child(2), .menu__grid i:nth-child(4) { --f: 1; }
.menu__grid i:nth-child(3), .menu__grid i:nth-child(5), .menu__grid i:nth-child(7) { --f: 2; }
.menu__grid i:nth-child(6), .menu__grid i:nth-child(8) { --f: 3; }
.menu__grid i:nth-child(9) { --f: 4; }

.menu__toggle:hover .menu__grid { transform: scale(1.14); }

/* OUVERT : plus de dalle. Le panneau sombre passe derrière -> les points deviennent
   BLANCS (contraste direct). Vague ALLER (haut-gauche -> bas-droite) puis RETOUR
   (bas-droite -> haut-gauche), avant de figer la CROIX (coins + centre). */
.menu.open .menu__grid i {
  background: #fff;
  /* La lumière "s'allume" dans le sens de la vague (retard = front --f). */
  transition: background-color .28s ease calc(var(--f) * 80ms),
              transform .28s ease,
              opacity .28s ease;
  /* Vague ALLER (haut-gauche -> bas-droite) puis RETOUR (bas-droite -> haut-gauche).
     Mouvement uniquement -> proprement désactivé en reduced-motion. */
  animation:
    ledPop .30s ease-in-out calc(var(--f) * 95ms),
    ledPop .30s ease-in-out calc(780ms + (4 - var(--f)) * 95ms);
}
/* CROIX en états DIRECTS (tiennent même sans animation) :
   impairs = coins + centre (restent) ; pairs = bords (s'effacent après les vagues). */
.menu.open .menu__grid i:nth-child(odd) { transform: scale(1.15); }
.menu.open .menu__grid i:nth-child(even) {
  opacity: 0;
  transform: scale(.4);
  transition: background-color .28s ease calc(var(--f) * 80ms),
              opacity .34s ease 1.5s,       /* s'efface APRÈS le passage des deux vagues */
              transform .34s ease 1.5s;
}
@keyframes ledPop {
  0%   { transform: scale(1); }
  50%  { transform: scale(1.55); }
  100% { transform: scale(1); }
}

/* Panneau PLEIN ÉCRAN : ancré en haut-droite, il s'ouvre en deux temps
   (barre vers la gauche, puis descente). position:fixed -> couvre tout l'écran. */
/* LA CARTE PART DE LA BARRE, ELLE NE SE POSE PAS DESSOUS.
   Le panneau était une plaque PLEIN ÉCRAN (`inset: 0`) : elle recouvrait tout,
   et rien ne rattachait son apparition à la barre. Elle est maintenant une
   carte qui reprend la géométrie EXACTE de la pilule du header — mêmes retraits
   latéraux (`--pad - 8px`), même retrait haut (6px), même rayon (16px) — et qui
   s'allonge vers le bas. Le logo, le CTA et le bouton se retrouvent donc DANS
   la carte, en haut, comme sur le modèle : la barre ne se double pas d'un
   panneau, elle DEVIENT le panneau.
   Les 3 valeurs de position sont recopiées de .siteheader.is-condensed::before,
   pas réinventées : si la pilule bouge un jour, elles doivent bouger avec. */
.menu__panel {
  position: fixed;
  top: 6px;
  left: calc(var(--pad) - 8px);
  right: calc(var(--pad) - 8px);
  bottom: auto;
  /* La carte s'arrête où son contenu s'arrête, sans dépasser l'écran. Au-delà,
     elle défile (voir overflow-y plus bas). */
  max-height: min(84vh, 720px);
  /* 76px en haut : la hauteur de la barre, plus de l'air. C'est ce qui laisse
     le logo et le CTA respirer au-dessus du premier lien. */
  padding: 76px 30px 24px;
  border-radius: 16px;
  box-sizing: border-box;
  background: rgba(20, 20, 24, .72);                     /* verre sombre translucide (laisse voir le flou) */
  box-shadow: 0 26px 60px rgba(16, 16, 18, .28);
  -webkit-backdrop-filter: blur(26px) saturate(1.5);
  backdrop-filter: blur(26px) saturate(1.5);
  border: none;
  /* DEFILEMENT DU PANNEAU. En `overflow: hidden`, tout ce qui dépassait était
     perdu : ni la molette ni le doigt ne font défiler une boîte cachée. Le menu
     mesure ~680 px de haut ; sous cette hauteur d'écran il était donc tronqué,
     et TÉLÉPHONE EN PAYSAGE (375 à 430 px de haut) coupait 250 à 320 px, soit
     « Estimer mon potentiel », les quatre réseaux ET « Mentions légales »,
     inatteignables. Même chose sur une fenêtre de bureau de 600 px de haut.
     L'axe horizontal reste caché (rien ne doit déborder sur les côtés) et la
     barre n'apparaît que s'il y a vraiment de quoi défiler : sur un écran de
     hauteur normale, rien ne change à l'affichage.
     `overscroll-behavior: contain` empêche en prime le geste d'atteindre la page
     derrière : le fond ne dérive plus pendant qu'on lit le menu. */
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  pointer-events: none;
  z-index: 1;                            /* sous le bouton (croix reste cliquable) */
  /* La plaque de verre se POSE, elle ne se déroule plus.
     Elle s'ouvrait autrefois en deux temps : une barre de 64 px balayait le haut
     de l'écran vers la gauche, puis descendait en plein écran (0,8 s de clip-path).
     Ce geste n'était visible que sur les appareils SANS « réduire les animations » :
     le poste du client, réglé avec les animations coupées, recevait déjà la plaque
     d'un coup et la cascade de liens seule. Deux menus différents pour le même
     site, dont un jugé désagréable sur téléphone. C'est donc celui du poste qui
     fait foi, pour tout le monde : la plaque paraît, les liens se fondent.
     Le clip-path reste, mais comme simple bascule ouvert/fermé, sans transition :
     c'est lui qui replie le panneau à zéro quand le menu est fermé.
     LA VALEUR FERMÉE A CHANGÉ AVEC LA FORME : elle repliait la plaque vers son
     coin haut-gauche (`bottom: 100% - 64px`, `left: 100%`), ce qui décrivait
     une barre. La carte, elle, se replie sur SA LIGNE DU HAUT : `bottom: 100%`
     et rien d'autre. C'est le même geste que celui qu'on lui demande, mais dans
     l'autre sens — elle se déroule vers le bas depuis la barre.
     ET TOUJOURS SANS TRANSITION, pour la raison ci-dessus : le poste du client
     a les animations coupées, une transition ici lui donnerait un menu et aux
     autres un menu différent. */
  clip-path: inset(0 0 100% 0);
}

/* LE VOILE SUR LE RESTE DE LA PAGE.
   La plaque plein écran n'en avait pas besoin : elle couvrait tout. Une carte
   qui laisse voir la page autour d'elle, si — sinon le menu cohabite avec une
   page parfaitement nette, et le regard ne sait plus lequel des deux lire.
   Porté par un pseudo de .menu et non par un élément de plus : le seul rôle de
   cette surface est d'exister quand le menu est ouvert. */
.menu::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0;
  background: rgba(18, 18, 22, .34);
  -webkit-backdrop-filter: blur(7px);
          backdrop-filter: blur(7px);
  transition: opacity .34s ease;
}
.menu.open::after { opacity: 1; }

/* LA PILULE DU HEADER S'EFFACE PENDANT L'OUVERTURE.
   Son verre et celui de la carte se superposeraient sinon : deux surfaces
   translucides empilées, donc une bande plus sombre sur les 60 premiers pixels
   du panneau. C'est la carte qui porte la matière, la pilule n'a plus qu'à
   laisser passer son contenu. */
.siteheader:has(.menu.open)::before {
  background: transparent;
  -webkit-backdrop-filter: none;
          backdrop-filter: none;
  box-shadow: none;
}
/* Et le contenu de la barre repasse AU-DESSUS de la carte. `.menu` est en
   z-index 40, le logo et le CTA sont à `auto` : sans ces 2 lignes la carte les
   recouvrait, alors qu'ils sont censés être posés dessus. */
.siteheader:has(.menu.open) .logo,
.siteheader:has(.menu.open) .hcta { position: relative; z-index: 50; }

/* Le filigrane du modèle : l'étoile du logo, très pâle, en bas à droite.
   Fichier réel et non data-URI : la CSP est en img-src 'self'. */
.menu__panel::after {
  content: "";
  position: absolute;
  right: 18px;
  bottom: 12px;
  width: 190px;
  height: 190px;
  opacity: .07;
  pointer-events: none;
  background: url('assets/etoile.svg') no-repeat center / contain;
}
.menu.open .menu__panel {
  pointer-events: auto;
  clip-path: inset(0 0 0 0);             /* ouvert plein écran */
}
/* Le panneau reçoit le focus à l'ouverture (voir menu.js) : c'est un conteneur,
   pas une cible cliquable, il ne doit donc porter aucun contour. Sans cette
   ligne, le navigateur peindrait autour de lui son propre cadre de mise au
   point, soit un rectangle bleu sur tout l'écran. */
.menu__panel:focus,
.menu__panel:focus-visible { outline: none; }


/* --- Le panneau couvre TOUTE la fenêtre, ses liens suivent la gouttière ------
   Il a longtemps été borné à la largeur de `.page`, du temps où celle-ci était
   une carte centrée posée sur un fond gris : panneau et carte se superposaient
   alors exactement. `.page` occupe désormais tout l'écran (voir --contenu et
   --pad) et ce bornage n'avait plus rien à épouser : il laissait seulement deux
   bandes de page nue de chaque côté du menu ouvert (144 px sur un écran de
   1488 px, 14 px sur un iPhone 16 Pro Max), alors que `inset: 0` promet le
   plein écran.

   Ce n'est donc plus la largeur du panneau qui aligne les liens, c'est la
   GOUTTIÈRE : le panneau file d'un bord à l'autre et `padding-inline` dépose
   son contenu sur le bord de la colonne, comme toutes les sections de la page.

   Le plancher à 30 px protège le dessin de référence : sur l'écran de 402 px,
   --pad vaut 20 px alors que le panneau a toujours été dessiné avec 30 px de
   gouttière propre. Au-delà de ~462 px la gouttière de la page prend le relais,
   sans marche à la traversée du palier 480.

   La signature de bas de page hérite de la même valeur : laissée à 30 px fixes
   elle restait collée au bord de l'écran, décalée de 114 px des liens qu'elle
   est censée aligner.

   >>> CE RAISONNEMENT NE VAUT PLUS, ET LA RÈGLE A ÉTÉ RETIRÉE. Il reposait
   entièrement sur un panneau qui file d'un bord à l'autre de l'écran : c'est
   pour ça que ses liens devaient retrouver la gouttière de la page. Le panneau
   est maintenant une CARTE, bornée à `--pad - 8px` de chaque côté ; son
   padding intérieur est celui d'une carte (30 px, posé plus haut), pas la
   gouttière d'une colonne. Laissée en place, la déclaration donnait 340 px de
   padding intérieur sur un grand écran — la moitié de la carte en marge.
   Le bloc est gardé en commentaire parce qu'il documente POURQUOI le panneau a
   longtemps été plein écran, ce que la forme actuelle ne raconte plus. */

/* Liens du menu (fondu décalé à l'ouverture) */
.menu__nav a {
  display: block;
  font-size: clamp(1.5rem, 7vw, 2.6rem);   /* fluide : proportionnel à la largeur de la fenêtre */
  font-weight: 700;
  line-height: 1.34;
  letter-spacing: -0.02em;
  color: #f4f4f6;
  white-space: nowrap;
  opacity: 0;
  transform: translateY(8px);
  /* Même durée et même courbe que l'exception « accessibilité motion » plus bas :
     un poste qui réduit les animations et un téléphone qui ne les réduit pas
     jouent alors EXACTEMENT le même fondu, au centième près. */
  transition: opacity .45s cubic-bezier(.2, .85, .25, 1), transform .45s cubic-bezier(.2, .85, .25, 1);
}
.menu__nav a:hover { color: rgba(255, 255, 255, .55); }
.menu.open .menu__nav a { opacity: 1; transform: none; }

/* --- CASCADE D'APPARITION -------------------------------------------------
   Le retard de chaque lien se DÉDUIT de son rang, posé par menu.js dans --i.
   Il était auparavant énuméré en nth-child, et l'énumération avait pris du
   retard sur le contenu : elle s'arrêtait au 4e lien du bloc principal (il y en
   a 5) et au 5e des ressources (il y en a 7). « Estimer mon potentiel », « CGV »
   et « Confidentialité » n'avaient donc AUCUN retard : au lieu de se fondre à
   leur tour, ils étaient déjà là avant les autres. Un rang calculé ne peut plus
   se désynchroniser du jour où un lien s'ajoute.

   Les retards partent presque de zéro : ils attendaient auparavant la fin de la
   descente du panneau (~0,76 s), qui n'existe plus.

   `!important` sur le seul transition-delay : le bloc « accessibilité motion »
   remet à zéro toutes les transitions de la page, délai compris. La cascade est
   un fondu d'opacité, pas un déplacement, et elle est conservée par exception
   là-bas ; sans ce marqueur son échelonnement serait effacé et les douze liens
   apparaîtraient d'un bloc. */
.menu__nav      { --casc-debut: .06s; --casc-pas: .06s; }
.menu__nav--sub { --casc-debut: .44s; --casc-pas: .04s; }
.menu.open .menu__nav a {
  transition-delay: calc(var(--casc-debut) + var(--i, 0) * var(--casc-pas)) !important;
}

.menu__sep { height: 1px; background: rgba(255, 255, 255, .14); margin: 18px 0 16px; opacity: 0; transition: opacity .45s cubic-bezier(.2, .85, .25, 1); }
.menu.open .menu__sep { opacity: 1; transition-delay: .36s !important; }
.menu__label { margin: 0 0 12px; font-size: clamp(.66rem, 2.9vw, .9rem); font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: rgba(255, 255, 255, .45); opacity: 0; transition: opacity .45s cubic-bezier(.2, .85, .25, 1); }
.menu.open .menu__label { opacity: 1; transition-delay: .40s !important; }
.menu__nav--sub a { font-size: clamp(1rem, 4.4vw, 1.6rem); font-weight: 500; line-height: 1.55; }

/* Signature de marque : épinglée en bas-gauche du panneau, apparaît en dernier.
   L'étoile du logo reprise en blanc (le disque noir serait invisible sur fond sombre). */
/* LA SIGNATURE EST DANS LE FLUX, PLUS ÉPINGLÉE AU BAS DE L'ÉCRAN.
   Elle était en `position: absolute; bottom: 34px`, ce qui avait un sens sur
   une plaque plein écran : elle se posait au pied de l'ÉCRAN. Sur une carte qui
   s'arrête où son contenu s'arrête, un ancrage au bas laisserait un trou entre
   le dernier lien et elle, ou la ferait chevaucher les liens sur écran court —
   c'est d'ailleurs exactement le bug que corrigeait la règle @media ci-dessous,
   devenue inutile. Rangée après le dernier lien, elle ne peut plus rien
   recouvrir, à aucune hauteur. */
.menu__foot {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid rgba(255, 255, 255, .12);
  opacity: 0;
  transform: translateY(6px);
  transition: opacity .45s cubic-bezier(.2, .85, .25, 1), transform .45s cubic-bezier(.2, .85, .25, 1);
}
.menu.open .menu__foot { opacity: 1; transform: none; transition-delay: .72s !important; }

/* ÉCRAN COURT : la signature reprend sa place dans le flux.
   Épinglée en bas du panneau (position: absolute ; bottom: 34px), elle est
   IMPRIMÉE PAR-DESSUS les liens dès que le menu ne tient plus en hauteur.
   Mesuré : à 720 px de haut elle recouvre « Mentions légales », à 600 px
   « Instagram » et « Facebook », à 390 px (téléphone en paysage) « Questions
   fréquentes » et « Estimer mon potentiel ». Une fenêtre de portable sur un
   écran 1366×768 offre ~660 px : le cas est courant, pas marginal.
   Remise dans le flux, elle se range après le dernier lien et se lit en fin
   de défilement, sans jamais rien recouvrir.
   `min-width: 600px` : en dessous, les liens rapetissent (clamp en vw), le
   menu tient en hauteur et rien ne se chevauche : la bande mobile, qui est le
   dessin de référence, n'est donc pas touchée. */
/* La règle @media qui remettait la signature dans le flux sur écran court a été
   retirée : elle n'a plus rien à corriger, la signature y est en permanence. */
.menu__brand { display: inline-flex; align-items: center; gap: 8px; color: #f2f2f4; }
.menu__star { width: 20px; height: 20px; display: block; }
.menu__wordmark { font-size: 1.28rem; font-weight: 700; letter-spacing: -0.02em; line-height: 1; }
.menu__copy {
  display: block;
  margin-top: 7px;
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .01em;
  color: rgba(255, 255, 255, .38);
}

/* ===================== BOUTONS ===================== */
.btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 40px;          /* mesuré : ~40px */
  padding: 0 var(--s5);
  border-radius: var(--r-btn);
  font-family: inherit;
  font-size: var(--t-btn);
  font-weight: 700;
  letter-spacing: -0.01em;
  cursor: pointer;

  /* ---- Agrandissement (survol / appui) : TOUS les boutons du site ----------
     Seule la BOÎTE change de taille : le libellé (.btn__label) est contre-scalé
     à l'exact inverse (1 / facteur), donc le texte reste figé pendant que les
     bords gagnent du terrain. Grandir et rétrécir décélèrent de la même façon.
     Tout est piloté par les trois variables ci-dessous : une seule valeur à
     retoucher, et le contre-scale reste automatiquement exact.
     Réglé d'abord sur le hero, il est désormais porté par .btn : les boutons des
     offres, le CTA de milieu de page et celui du pied de page ont exactement le
     même geste, aux mêmes valeurs. C'est aussi ce que fait déjà evaluation.css. */
  --btn-ease:  cubic-bezier(.33, 1, .68, 1); /* rapide au début, lent à la fin */
  --btn-hover: 1.026;                        /* facteur d'agrandissement au survol */
  --btn-press: .975;                         /* facteur d'enfoncement à l'appui */
  transition: transform .42s var(--btn-ease), background .3s ease, border-color .3s ease, box-shadow .3s ease;
  will-change: transform;      /* couche GPU dédiée : scale fluide, sans reflow */
  backface-visibility: hidden; /* anti-scintillement pendant le scale */
  -webkit-font-smoothing: antialiased;
}
/* Le libellé suit la même courbe/durée que la boîte -> le contre-scale tient à
   chaque frame et le texte ne bouge jamais. */
.btn__label {
  display: inline-block;                       /* requis pour recevoir un transform */
  transition: transform .42s var(--btn-ease);
  backface-visibility: hidden;
}
@media (hover: hover) {
  .btn:hover             { transform: scale(var(--btn-hover)); }
  .btn:hover .btn__label { transform: scale(calc(1 / var(--btn-hover))); }
}
/* Appui : la boîte s'enfonce vite (.11s), le libellé se re-compense pour rester fixe. */
.btn:active             { transform: scale(var(--btn-press)); transition-duration: .11s; }
.btn:active .btn__label { transform: scale(calc(1 / var(--btn-press))); transition-duration: .11s; }

/* Bouton principal : même matière que la citation de Daniel : plaque translucide et
   les deux nappes de lumière monochromes (voir « VERRE MONOCHROME », section TÉMOIGNAGES).
   Le backdrop-filter de la citation est VOLONTAIREMENT omis : le bouton est posé sur
   l'aplat blanc du hero, il n'y a donc rien à flouter derrière lui, et ce filtre serait
   recalculé à chaque frame de l'agrandissement au survol, pour zéro différence visible. */
.btn-primary {
  position: relative;
  --r-verre: var(--r-btn);     /* rayon du bouton : la découpe des nappes le reprend */
  overflow: hidden;            /* clippe les nappes au rayon du bouton */
  isolation: isolate;          /* contient le mix-blend-mode DANS le bouton */
  background: rgba(20, 20, 20, .74);
  color: #fff;
  border: 1px solid transparent;
  box-shadow: 0 4px 14px rgba(16,16,18,.10);
}
/* Le fond NE CHANGE PAS au survol : le bouton gris s'agrandit, il ne s'assombrit
   plus. L'ombre seule accompagne le mouvement (elle porte la boîte, elle ne
   repeint pas la matière). Effet de bord voulu : le CTA du pied de page, qui
   repasse en aplat plein sur le jaune (.ftr__cta), garde ce noir franc au
   survol au lieu de revenir au noir translucide de .btn-primary. */
.btn-primary:hover { box-shadow: 0 6px 18px rgba(16,16,18,.16); }
.btn-primary .btn__label { position: relative; z-index: 1; }

.btn-outline {
  background: #fff;
  color: var(--ink);
  border: 1px solid var(--line);
}
.btn-outline:hover { background: #fafafa; border-color: #d9d9dd; }

/* ÉTAT DÉSACTIVÉ. Peint avec de vraies couleurs et non avec une opacité, comme
   dans evaluation.css : les blocs animés à l'entrée figent `opacity` en fin de
   course et emporteraient la déclaration.
   ET IL RESTE LISIBLE, À 5,8:1. C'est contre-intuitif pour un bouton éteint,
   mais ici le libellé EST le message : « Complet » doit se lire, sinon la carte
   ne dit plus rien et le visiteur croit à un bouton cassé. Le gris habituel des
   désactivés (#C3C5CA, 2,0:1 sur blanc) conviendrait à un « Continuer » pas
   encore actif, qui ne porte aucune information ; pas à celui-ci.
   Ce qui signale l'inertie n'est donc pas la pâleur mais le reste : plus de
   relief, plus de survol, plus d'enfoncement, et le curseur qui refuse. */
.btn[disabled] {
  pointer-events: none;
  box-shadow: none;
  cursor: not-allowed;
}
.btn[disabled]:active { transform: none; }
.btn-outline[disabled] {
  background: #f4f4f6;
  color: #5c6066;
  border-color: #e6e6ea;
}

/* ===================== HERO ===================== */
/* MOBILE : le hero tient dans 1 écran plein (rien n'est coupé). Flex column ->
   les textes en haut, la photo remplit toute la hauteur restante. */
.hero {
  display: flex;
  flex-direction: column;
  /* 1 écran : viewport moins le header.
     `svh` ET SURTOUT PAS `dvh`, c'est tout l'enjeu de cette ligne.
     ------------------------------------------------------------------
     `dvh` suit la barre d'adresse du navigateur mobile EN CONTINU : elle se
     replie au premier geste de scroll, et `100dvh` grandit d'autant, ici de
     80 px (mesuré : 732 -> 812 sur un iPhone de référence).
     Le hero grandissait donc de 80 px PENDANT qu'on scrollait de 80 px. Comme
     il est le dernier bloc de la plaque claire, la plaque SOMBRE qui le suit
     descendait dans le document exactement autant que le doigt la faisait
     monter : mouvement net nul. Résultat à l'écran, sur Safari comme sur
     Chrome mobile : on scrolle, la barre d'adresse se replie, et la plaque
     noire reste plantée. Elle ne se décidait à monter qu'une fois la barre
     entièrement repliée. Les deux symptômes n'étaient pas seulement liés :
     c'était le même.
     `svh` est la hauteur du viewport barre d'adresse VISIBLE. C'est une
     constante : elle ne bouge plus d'un pixel pendant le scroll, la plaque
     sombre monte donc dès le premier pixel de geste.
     Au chargement, barre d'adresse déployée, `svh` et `dvh` valent la MÊME
     chose : le premier rendu est identique au pixel près. Rien à revoir côté
     dessin. */
  min-height: calc(100svh - var(--header-h));
  padding: 28px var(--pad) 20px;
  box-sizing: border-box;
}

.eyebrow {
  margin: 0 0 var(--s3);
  font-size: var(--t-eyebrow);
  font-weight: 500;
  letter-spacing: 0.01em;
  /* #71767F donnait bien 4,57:1 — mais sur la page BLANCHE d'alors. Depuis que
     le hero est une photo, ce surtitre est la ligne la moins lisible de tout le
     site : 2,4:1 en moyenne, 1,1:1 sur les pixels les plus sombres. Le gris
     n'avait pas bouge, son fond si.
     #34363A est calculé contre le fond réel sous CETTE ligne-ci, voile compris,
     et tient 4,6:1 au 5e centile le plus sombre. C'est elle qui a fixé l'encre
     des 2 lignes grises : plus haute dans le bloc, elle reçoit moins de voile
     que le sous-titre et passe donc au seuil la première. Il va avec
     --voile: .62 dans le bloc .hero : les 2 valeurs ont été dérivées ensemble. */
  color: #34363a;
}

.hero__title {
  margin: 0 0 18px;
  font-size: var(--t-h1);
  line-height: 0.98;         /* interligne serré (mesuré ~27px) */
  font-weight: 500;          /* Satoshi Medium : titres allégés, plus élégants (était 700) */
  letter-spacing: -0.03em;
  color: var(--ink);
}

.hero__text {
  margin: 0 0 20px;                         /* resserré pour le format 1 écran (était 44) */
  font-size: var(--t-body);
  line-height: 1.4;         /* mesuré ~1.22 */
  font-weight: 400;
  /* PAS var(--muted) ICI, ET SURTOUT PAS --muted CHANGÉ. Ce jeton est le gris
     du corps de texte sur fond blanc, où il donne 5,05:1 : il est juste, et il
     sert à 23 autres endroits qui sont tous sur du blanc. Le seul endroit où il
     se retrouve sur une photo est ce sous-titre, où il tombait à 3,0:1. C'est
     donc la ligne qu'on surcharge, pas le jeton — déplacer --muted aurait
     assombri 23 blocs pour régler un problème qui n'existe que dans celui-ci.
     Même encre que .eyebrow, dérivée sur .eyebrow et avec --voile: .62. Ici
     elle donne 5,2:1, au-dessus du seuil : c'est le surtitre qui commande. */
  color: #34363a;
  max-width: none;
}

.hero__actions {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
}

/* ===================== LE FOND DU HERO =====================
   La photo n'est plus une vignette 4/5 posee a droite : elle occupe le hero
   entier, et le texte se pose dessus.

   OU ELLE VIT. Dans le hero, pas derriere lui. .plate--one est `position:
   sticky` avec `background: var(--bg)` opaque : tout ce qui serait pose
   derriere elle serait repeint en blanc.

   LES 3 REGLAGES SONT DES VARIABLES, ET C'EST VOULU : cadrage, zoom et flou se
   reprennent sans toucher au reste de la regle, et separement par bande.
     --fond-zoom : `cover` par defaut. Une longueur (ex. 150%) rapproche.
     --fond-cal  : le point du cadrage qui reste dans la fenetre.
     --fond-flou : le rayon du flou general. 0 rend la photo nette.
     --fond-flou-fort : celui de la zone renforcee, sous le bloc de texte.
     --fond-masque : ou s'arrete cette zone, et sur quelle distance elle fond.
   Repere pour le flou : les comparateurs de cote du carrousel sont a 3,5px, et
   le commentaire qui les regle dit que c'est ce qu'il faut pour rendre leur
   texte ILLISIBLE. 1,5px est donc largement en deca : la photo reste lue comme
   une photo, elle perd juste son arete. Essaye a 2px : c'est deja trop, les
   microscopes et la charpente y perdent leur dessin.

   AUCUN VOILE, AUCUN LAVIS : la photo est servie nue. C'est le CADRAGE qui doit
   amener le texte sur une zone lisible, pas une couche de blanc posee dessus.
   Le chiffre qui guide ce reglage : sur le grand mur blanc l'encre #131315 tient
   15,1:1, partout ailleurs les 5 % de pixels les plus sombres la font tomber a
   1,5-1,8:1. C'est le mur, ou rien. */
.hero {
  --fond-zoom: cover;
  --fond-cal: center;
  /* LES 3 NIVEAUX DE FLOU, du general au local :
       --fond-flou            toute la photo, elle perd juste son arete ;
       --fond-flou-fort       la moitie ou tombe le bloc de texte ;
       --fond-flou-tres-fort  derriere le bloc lui-meme et derriere le socle.
     Repere : les comparateurs de cote du carrousel sont a 3,5px, et le
     commentaire qui les regle dit que c'est ce qu'il faut pour rendre leur
     texte ILLISIBLE. Ici c'est justement ce qu'on cherche pour le fond. */
  --fond-img: url("assets/hero-lab-vert.webp");
  --fond-flou: 1.5px;
  --fond-flou-fort: 5px;
  --fond-flou-tres-fort: 14px;
  /* LE VOILE CLAIR, ET POURQUOI IL N'EST PAS LE FILM D'AVANT.
     Il n'est pas pose sur le hero : il est pose sur la COUCHE TRES FLOUE, donc
     il est decoupe par le meme masque qu'elle et n'existe que derriere le bloc
     de texte et derriere le socle. Le reste de la photo n'en recoit rien.
     La valeur n'est pas choisie a l'oeil. Sous le texte, les 5 % de pixels les
     plus sombres de la photo floutee valent 39/255.

     CE N'EST PLUS LE TITRE QUI COMMANDE, C'EST LE SOUS-TITRE. Le calibrage
     d'origine visait l'encre du titre, #131315 : 0,45 amenait le fond a 136 et
     lui donnait ses 4,5:1. Sauf que le titre n'a jamais ete le cas difficile.
     Il est a 13,9:1 mesure, il passerait sans voile du tout. Les 2 lignes
     grises, elles, tombaient a 3,0:1 et 2,4:1 en moyenne, et jusqu'a 1,3:1 sur
     les pixels les plus sombres : le voile faisait exactement ce pour quoi il
     avait ete regle, et ce n'etait pas la bonne cible.
     0,62 amene donc ce plancher a 173 : (0,62 x 255) + (0,38 x 39). Contre 173,
     l'encre #34363A des 2 lignes grises donne 5,4:1.

     C'EST LE SURTITRE QUI FIXE L'ENCRE, PAS LE SOUS-TITRE, et la raison est
     geometrique : il est plus haut dans le bloc, la ou l'ellipse du voile a
     commence a s'affaiblir. Mesure sur les pixels reellement composites (les 3
     couches empilees, pas la seule photo), il est a 4,6:1 quand le sous-titre
     est deja a 5,2:1. Une encre derivee du sous-titre seul le laissait a 4,0:1,
     sous le seuil : c'est la ligne la plus haute qu'il faut interroger.
     Voir .eyebrow et .hero__text : les 3 valeurs vont ensemble, changer l'une
     sans les autres casse le calcul. */
  --voile: .62;
  /* Le debord commun aux 3 couches. 4 rayons du PLUS FORT des flous : voir le
     bloc ci-dessous, il vaut pour les 3. */
  --debord: calc(var(--fond-flou-tres-fort) * 4);
  /* OU S'ARRETENT LES 2 ZONES. En pile le texte est en haut, en bureau il est a
     gauche : chaque bande redefinit ces 2 masques.

     DES ELLIPSES, ET PLUS DES DEGRADES CROISES. 1er etat : la zone tres floue
     etait l'INTERSECTION d'un degrade en largeur et d'un degrade en hauteur.
     Ca decrit bien 2 rectangles separes par du vide, mais ca ne peut rien
     decrire d'autre : meme avec des fondus, un croisement de degrades lineaires
     garde ses 4 aretes droites et ses 4 coins, et la zone se lisait comme une
     plaque posee sur la photo au lieu d'en faire partie.
     Une ellipse n'a ni coin ni arete, et son fondu part dans toutes les
     directions a la fois. Les 2 zones sont donc 2 ellipses qui s'ADDITIONNENT
     (le comportement par defaut des masques empiles), ce qui supprime au passage
     le besoin de `mask-composite`.
     LES RAYONS NE SONT PAS DECORATIFS : le coeur opaque s'arrete a 39 % du rayon,
     et 39 % de 40 % de largeur = 15,6 %, soit exactement la demi-largeur de la
     colonne de texte. Le texte est donc entierement dans la partie pleine, et
     les 61 % de rayon qui restent ne servent qu'a disparaitre. */
  --fond-masque: linear-gradient(180deg, #000 0%, #000 30%, transparent 74%);
  --fond-masque-fort: radial-gradient(ellipse 62% 34% at 46% 31%,
      #000 0%, #000 39%, transparent 100%);
  position: relative;
  overflow: hidden;
}

/* LE DEBORD N'EST PAS UN REGLAGE, C'EST CE QUI REND LE FLOU POSSIBLE.
   `filter: blur()` etale chaque pixel dans toutes les directions, y compris vers
   l'exterieur : sur un element qui s'arrete pile au bord du hero, les 4 aretes
   se delavent et laissent un lisere transparent. On agrandit donc les couches
   pour que cette retombee tombe HORS du cadre, et `overflow: hidden` sur .hero
   coupe le reste. 4 rayons et non 3 : le flou gaussien de CSS pose un
   ecart-type = rayon, et la retombee est encore visible a 3 ecarts-types.

   LE MEME DEBORD POUR LES 3 COUCHES, ET CE N'EST PAS UNE ECONOMIE D'ECRITURE :
   `background-size: cover` se calcule sur la taille de l'ELEMENT. Des couches de
   tailles differentes cadreraient la meme photo a des echelles differentes, et
   les raccords montreraient des images decalees au lieu d'une seule plus ou
   moins nette. Il est donc pris sur le plus fort des flous, pour tout le monde.

   L'ORDRE DE PEINTURE EST ECRIT, PAS DEDUIT. Sans z-index il suivrait l'ordre de
   l'arbre (::before, puis les enfants, puis ::after), ce qui placerait la couche
   de base par-dessus une des zones. Les 4 valeurs disent l'empilement reel :
   photo, zone forte, zone tres forte, contenu. */
.hero__fond,
.hero::before,
.hero::after {
  position: absolute;
  inset: calc(var(--debord) * -1);
  background-image: var(--fond-img);
  background-size: var(--fond-zoom);
  background-position: var(--fond-cal);
  background-repeat: no-repeat;
}
.hero__fond { z-index: 0; filter: blur(var(--fond-flou)); }

/* LES MASQUES SE MESURENT SUR LE HERO, PAS SUR LA COUCHE. Les couches debordent
   de --debord de chaque cote ; un degre en pourcentage s'etalerait donc sur la
   boite agrandie et tous les arrets glisseraient (56px sur un hero de 1214, ce
   sont 4% d'ecart en haut comme en bas). mask-size et mask-position leur rendent
   exactement la boite du hero. */
.hero::before,
.hero::after {
  content: "";
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: calc(100% - 2 * var(--debord)) calc(100% - 2 * var(--debord));
  mask-size: calc(100% - 2 * var(--debord)) calc(100% - 2 * var(--debord));
  -webkit-mask-position: var(--debord) var(--debord);
  mask-position: var(--debord) var(--debord);
}
.hero::before {
  z-index: 1;
  filter: blur(var(--fond-flou-fort));
  -webkit-mask-image: var(--fond-masque);
  mask-image: var(--fond-masque);
}
/* La zone tres forte : 2 masques croises, d'ou `intersect`. */
.hero::after {
  z-index: 2;
  /* Le voile est une 1re couche de fond posee SUR la photo, pas un element de
     plus : il herite ainsi du masque et du flou sans une ligne de gestion. */
  background-image:
    linear-gradient(rgba(255, 255, 255, var(--voile)), rgba(255, 255, 255, var(--voile))),
    var(--fond-img);
  filter: blur(var(--fond-flou-tres-fort));
  -webkit-mask-image: var(--fond-masque-fort);
  mask-image: var(--fond-masque-fort);
}

/* SOUS @supports, ET C'EST DELIBERE : un masque qui n'est pas compris n'est pas
   ignore, il ne decoupe RIEN, et les 2 couches floues recouvriraient le hero
   entier. La condition fait qu'un navigateur sans masque n'a simplement pas de
   zone renforcee, ce qui est la bonne facon d'echouer.
   Des degrades et non des images : la CSP est en img-src 'self', un masque en
   data-URI ne serait pas charge. */
@supports not (mask-image: linear-gradient(#000, #000)) {
  .hero::before, .hero::after { display: none; }
}

/* Tout le contenu du hero repasse au-dessus des 3 couches. */
.hero > *:not(.hero__fond) { position: relative; z-index: 3; }

/* --- LE PORTRAIT DU HERO : UN HOMME QUI SE TRANSFORME ---------------------
   PAS AVANT 1024, ET C'EST LE MEME MOTIF QUE LE SOCLE. En pile, le hero tient
   dans un ecran de telephone et il y est deja plein : surtitre, titre,
   sous-titre et 2 boutons. Il n'y reste aucun vide ou poser un homme de 500px
   sans le mettre SOUS les boutons, c'est-a-dire apres le seul ecran qui decide.
   Le bloc n'existe donc qu'a partir de la bande ou la 2e colonne est libre,
   exactement comme .hero__proof (voir son commentaire).
   Il n'est pas simplement transparent ni hors champ : `display: none` empeche
   AUSSI le chargement des photos, puisque app.js ne remplit que ce qu'il
   trouve affiche. Une bande qui ne le montre pas ne paie pas ses 50 Ko. */
.hero__mur { display: none; }

/* --- SOCLE DU HERO : 3 réassurances en pied d'écran ---
   Aucun dispositif nouveau : le motif est celui des cartes tarifaires (libellé
   en gras = ce qu'on affirme, ligne grise dessous = ce qui le tient), et la
   séparation est le filet vertical, la seule que la page emploie entre deux
   colonnes de même rang (cf. .value__row, .anch__row).
   Pas de filet horizontal au-dessus : le socle se lit comme le pied du hero,
   pas comme un bloc de plus posé dessous. C'est l'écart qui l'en sépare. */
/* PAS EN PILE. Sur telephone ce bandeau se pose tout en bas du hero, sous la
   photo : il arrive donc APRES le seul ecran qui decide, et il y prend la place
   d'un troisieme argument que personne ne lit a cet endroit. Ses 3 informations
   sont toutes reprises plus bas, et mieux : la note Trustpilot dans le bandeau
   de chiffres cles, les 14 jours dans le bloc Garanties et sous chaque bouton
   d'achat, le protocole dans la section qui l'explique. Il ne reparait qu'a
   partir de 1024px, ou la colonne de texte a la place de le porter a cote de
   la photo, et non dessous. */
.hero__proof {
  display: none;
  list-style: none;
  grid-template-columns: repeat(3, 1fr);
  margin: 18px 0 0;
  padding: 0;
}
.hero__proofitem {
  padding: 0 12px;
  border-left: 1px solid var(--line);
}
/* La 1re colonne s'aligne sur le bord du texte : ni filet, ni retrait. */
.hero__proofitem:first-child { padding-left: 0; border-left: 0; }
.hero__proofitem b {
  display: block;
  font-size: 13px;
  line-height: 1.25;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.hero__proofitem em {
  display: block;
  margin-top: 2px;
  font-style: normal;               /* <em> pour le balisage, pas pour l'italique */
  font-size: 11.5px;
  line-height: 1.3;
  /* --muted et non --faint : à 11,5px, le gris des œilletons tombe à 2,6:1 sur
     blanc, sous le seuil AA. C'est de surcroît le gris que le même motif emploie
     déjà sur les cartes tarifaires (.plan__item em). */
  color: var(--muted);
}

/* ===================== SECTION SOMBRE ===================== */
.dark {
  background: var(--dark-bg);
  padding: 32px var(--pad) 64px;         /* bas */
  color: var(--dark-title);
}

/* --- Bandeau autorité : l'apparence documentée par les médias & études --- */
.authority { padding: var(--s2) 0 var(--s7); } /* 8/32, calé grille (était 6/34) */
/* Légende descriptive sous la bande (remplace l'ancien label du haut "L'apparence change tout") */
.authority__note {
  margin: 12px auto 0;
  max-width: 34ch;
  font-size: 11px;
  font-weight: 500;
  line-height: 1.35;
  letter-spacing: .01em;
  color: rgba(255, 255, 255, .42);
  text-align: center;
}
.authority__viewport {
  margin-top: 0;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
}
.authority__track {
  display: flex;
  width: max-content;
}
.authority__track--ltr { animation: authority-marquee 38s linear infinite; }
.authority__track:hover { animation-play-state: paused; }
.authority__set {
  display: flex;
  align-items: center;
  gap: 14px;
  padding-right: 14px;
}
/* TEST : logos posés directement sur le fond sombre (plus de pastille blanche),
   tous forcés en blanc monochrome -> même les logos noirs (Guardian, BBC…) ressortent. */
.brand-chip {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 46px;
  padding: 0 14px;
  background: transparent;
  border-radius: 0;
}
.brand-chip img {
  height: 28px;
  width: auto;
  display: block;
  opacity: .85;                       /* logos déjà détourés en blanc -> léger retrait discret */
}
@keyframes authority-marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

.dark__title {
  margin: 0 0 var(--s5);            /* 20px, calé grille (était 18) */
  font-size: var(--t-h2);
  line-height: 0.98;
  font-weight: 500;
  letter-spacing: -0.03em;
  color: var(--dark-title);
  text-align: center;
}

.dark__text {
  margin: 0 0 var(--s7);            /* 32px, calé grille (était 28) */
  font-size: var(--t-body);
  line-height: 1.4;
  font-weight: 400;
  color: var(--dark-text);
  text-align: center;
}

/* --- Études : preuves scientifiques par domaine (onglets) --- */
/* Espace généreux au-dessus (séparée nettement des bénéfices) + respiration en bas. */
.studies {
  margin: var(--s11) 0 var(--s2);   /* 64px de respiration au-dessus, en blanc pur (aucun filet) */
}
.studies__title {
  margin: 0 0 var(--s7);            /* 32px sous le titre */
  font-size: var(--t-h2);           /* 28px : aligné sur .dark__title et le hero */
  line-height: 1.0;
  font-weight: 500;
  letter-spacing: -0.03em;
  color: var(--dark-title);
  text-align: center;
}
.studies__title-dim { color: var(--dark-text); font-weight: 500; }

/* Rangée d'onglets : segmented control pleine largeur (piste = largeur des cartes d'arguments) */
.studies__tabs {
  display: flex;
  gap: 4px;
  margin: 0 0 var(--s6);           /* 24px sous les onglets */
  padding: 3px;                    /* respiration interne de la piste (barre amincie) */
  background: #17171b;             /* la « piste » qui recouvre les 3 catégories */
  border: 1px solid rgba(255, 255, 255, .07);
  border-radius: 12px;
  box-sizing: border-box;
}
.studies__tab {
  flex: 1 1 0;                     /* 3 segments égaux -> remplissent toute la largeur */
  height: 28px;                    /* barre amincie : ~1/4 en moins (38 -> 28) */
  padding: 0 10px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: transparent;
  color: #8a8a90;                  /* inactif : gris (comme « Notifications ») */
  font-family: inherit;
  font-size: var(--t-btn);
  font-weight: 500;
  letter-spacing: -0.01em;
  white-space: nowrap;
  cursor: pointer;
  touch-action: manipulation;
  transition: color .2s ease, background-color .2s ease, border-color .2s ease, box-shadow .2s ease;
}
.studies__tab:hover { color: #c7c7cc; }
/* Onglet actif : pilule plus claire, bordée et surélevée (comme « Profile » dans la réf) */
.studies__tab.is-active {
  background: #2a2a30;
  border-color: rgba(255, 255, 255, .12);
  color: #fafafa;
  font-weight: 600;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .4), inset 0 1px 0 rgba(255, 255, 255, .05);
}

/* Panneaux + cartes */
.studies__panel { list-style: none; margin: 0; padding: 0; display: none; }
.studies__panel.is-active {
  display: grid;
  gap: var(--s4);                   /* 16px entre les cartes */
  animation: studiesFade .3s ease;
}
@keyframes studiesFade {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
.scard {
  position: relative;
  padding: 22px 20px 18px;
  /* Le rayon et le débord de la nappe sont des JETONS, pas des valeurs écrites
     deux fois : la découpe de ::after se calcule à partir des deux (voir plus
     bas). Écrits en dur des deux côtés, ils se seraient désynchronisés au
     premier réglage, et la découpe aurait cessé de suivre les coins. */
  --r-verre: 18px;
  --debord: 22;                 /* de combien la nappe déborde de la carte, en % */
  border-radius: var(--r-verre);
  background: rgba(255, 255, 255, .035);
  border: 0;                    /* panneau brut : aucune bordure */
  overflow: hidden;             /* clippe la couche « fond citation » aux coins arrondis */
  isolation: isolate;           /* contient le mix-blend-mode du fond DANS la carte */
  transition: transform .25s ease, box-shadow .25s ease;
}
/* Le contenu reste au-dessus de la couche de verre */
.scard > * { position: relative; z-index: 1; }

/* ---- Fond sombre révélé au survol / à l'appui ----
   ::before = base sombre opaque ; ::after = nappe de lumière en mix-blend screen.
   Révélés en fondu. MONOCHROME : chaque couleur d'origine a été remplacée par son
   niveau de gris équivalent (luminance Rec. 709), suivant la même conversion que le
   « VERRE MONOCHROME » de .quote et des cartes d'avis : la géométrie et les opacités
   propres à ces cartes sont, elles, inchangées. */
.scard::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  opacity: 0;
  transition: opacity .35s ease;
  pointer-events: none;
  background: linear-gradient(160deg, rgba(24, 24, 24, .95), rgba(14, 14, 14, .96));
}
.scard::after {
  content: "";
  position: absolute;
  inset: calc(-1% * var(--debord));   /* déborde -> flou diffus */
  z-index: 0;
  opacity: 0;
  transition: opacity .35s ease;
  pointer-events: none;
  filter: blur(15px);
  mix-blend-mode: screen;
  /* DÉCOUPE AUX COINS ARRONDIS, à ne pas confondre avec l'`overflow: hidden` de
     la carte. Celui-ci suffisait tant que la carte était peinte d'un bloc, mais
     `filter` + `mix-blend-mode` valent à cette nappe sa propre couche de
     composition GPU, et une couche composée n'est rognée qu'au RECTANGLE de son
     parent : les coins arrondis sont perdus. Au survol, la nappe débordait donc
     en quatre équerres claires autour des coins, visibles comme un cadre argenté
     mal découpé. Rien de tout cela en rendu logiciel, où il n'y a pas de couche
     séparée : le défaut ne se voit que sur un vrai navigateur accéléré.
     `clip-path`, lui, est appliqué APRÈS le flou et respecté par le compositeur.
     Le pourcentage replace le bord de la carte dans le repère de la nappe :
     celle-ci mesure (100 + 2 x débord) % de la carte, et la carte y commence à
     débord %. Tout est déduit des deux jetons, donc juste par construction. */
  clip-path: inset(calc(100% * var(--debord) / (100 + 2 * var(--debord))) round var(--r-verre));
  background:
    radial-gradient(52% 60% at 14% 6%,   rgba(162, 162, 162, .85), transparent 60%),
    radial-gradient(50% 56% at 90% 12%,  rgba(161, 161, 161, .78), transparent 58%),
    radial-gradient(64% 72% at 84% 108%, rgba(209, 209, 209, .70), transparent 62%),
    radial-gradient(46% 52% at 56% 92%,  rgba(177, 177, 177, .50), transparent 62%),
    radial-gradient(54% 62% at 42% 52%,  rgba(255, 255, 255, .20), transparent 76%);
}

/* Appui (mobile + clic maintenu) : classe posée par le JS -> fiable sur iOS */
.scard.is-pressed {
  transform: translateY(-2px);
  box-shadow: 0 16px 34px rgba(0, 0, 0, .45);
}
.scard.is-pressed::before,
.scard.is-pressed::after { opacity: 1; }

/* Survol : uniquement sur appareils à pointeur fin (souris) -> pas de hover figé au tap */
@media (hover: hover) and (pointer: fine) {
  .scard:hover {
    transform: translateY(-2px);
    box-shadow: 0 18px 42px rgba(0, 0, 0, .45);
  }
  .scard:hover::before,
  .scard:hover::after { opacity: 1; }
}
.scard__title {
  margin: 0 0 10px;
  font-size: 21px;
  line-height: 1.05;
  font-weight: 500;                 /* Satoshi Medium : titres un peu moins gras (seuls 400/500/700 chargés) */
  letter-spacing: -0.02em;
  color: var(--dark-title);
}
.scard__lead { color: var(--dark-text); }   /* premier mot atténué (pattern bi-ton) */
.scard__claim {
  margin: 0 0 14px;
  font-size: 15px;
  line-height: 1.4;
  font-weight: 400;
  color: #c4c4ca;
}
.scard__cite {
  position: relative;
  margin: 0;
  padding-left: 22px;                 /* place pour l'icône en absolu -> le texte s'écoule normalement */
  font-size: 12px;
  line-height: 1.4;
  font-weight: 500;
  color: rgba(255, 255, 255, .34);
}
.scard__cite svg { position: absolute; left: 0; top: 2px; width: 14px; height: 14px; opacity: .8; }
.scard__cite em { font-style: italic; }

/* --- Bandeau chiffres clés : clôture la section sombre sous les études --- */
/* 3 colonnes égales, filet fin au-dessus (même valeur que les bordures des cartes). */
.keyfig {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  margin: var(--s8) 0 0;                        /* 40px sous les études */
  padding: var(--s6) 0 0;                       /* 24px sous le filet */
  border-top: 1px solid rgba(255, 255, 255, .07);
  text-align: center;
}
.keyfig__item { min-width: 0; }
.keyfig__num {
  margin: 0 0 6px;
  font-size: 26px;
  line-height: 1;
  font-weight: 600;
  letter-spacing: -0.03em;
  color: var(--dark-title);
}
/* Tuiles Trustpilot : cinq carrés verts au gabarit du reste de la ligne. */
.keyfig__tile {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  background: #00b67a;                          /* vert Trustpilot */
}
.keyfig__tile svg { width: 11px; height: 11px; fill: #fff; }
/* 4,9 sur 5 : la cinquième tuile est remplie à 90 %, comme le fait Trustpilot.
   Cinq tuiles pleines annonceraient 5,0 : un dixième de point qu'on n'a pas. */
.keyfig__tile--part {
  background: linear-gradient(90deg, #00b67a 90%, rgba(255, 255, 255, .14) 90%);
}

/* Libellé de la colonne note : étoile verte + wordmark, au gabarit des autres libellés. */
/* Ligne Trustpilot : la note chiffree remplace les cinq etoiles pleines, qui
   affirmaient une reputation sans afficher aucune donnee. Le nombre d'avis passe
   sur une deuxieme ligne (flex-basis 100%) et l'ensemble est cliquable vers le
   profil : c'est la verifiabilite qui fait la valeur du signal, pas la note. */
.keyfig__label--tp { display: block; }
.keyfig__label--tp a {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  color: inherit;
  padding: 1px 0 2px;                  /* zone tactile un peu plus haute */
}
@media (hover: hover) {
  .keyfig__label--tp a:hover { color: rgba(255, 255, 255, .62); }
}
.keyfig__stars { display: flex; gap: 2px; }
/* Le nombre d'avis : sous le nom de la plateforme, et plus discret que lui. */
.keyfig__tp-src { display: block; }
.keyfig__tp-count {
  display: block;
  margin-top: 3px;
  color: rgba(255, 255, 255, .26);
}

.keyfig__label {
  margin: 0;
  font-size: 11px;
  line-height: 1.2;
  font-weight: 500;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .34);
}

/* ===================== CE QUI BLOQUE ===================== */
/* Diagnostic des tentatives passées, posé dans la partie CLAIRE sous le témoignage.
   Reprend la grammaire de la liste .benefit de la section sombre (mêmes gabarits :
   colonne de chiffres 54px, gouttière 16px, padding 20px, filets 1px), transposée
   en clair : chiffres « filigrane » noirs à 14 %, filets sur --line. */
.blockers {
  margin: var(--s11) 0 0;           /* 64px de respiration après la citation */
  text-align: center;               /* eyebrow + titre + sous-titre centrés */
}
.blockers__eyebrow {
  margin: 0 0 var(--s3);
  font-size: 11px;
  line-height: 1;
  font-weight: 700;
  letter-spacing: .16em;            /* même interlettrage que les autres eyebrows */
  text-transform: uppercase;
  color: var(--faint);
}
.blockers__title {
  margin: 0 0 var(--s4);
  text-wrap: balance;
  font-size: var(--t-h2);
  line-height: 1.06;
  font-weight: 500;
  letter-spacing: -0.03em;
  color: var(--ink);
}
/* 2e phrase atténuée, dans le flux du titre (elle enchaîne sur la même ligne). */
.blockers__title-dim { color: var(--muted); font-weight: 500; }
.blockers__sub {
  margin: 0 auto var(--s8);         /* 40px avant la liste */
  max-width: 34ch;
  text-wrap: balance;               /* pas de mot orphelin en dernière ligne */                  /* le sous-titre casse en 2 lignes équilibrées */
  font-size: var(--t-body);
  line-height: 1.35;
  font-weight: 400;
  color: var(--muted);
}

/* DE VRAIES CARTES DES LE TELEPHONE, ET POUR LES 2 BLOCS.
   « Vous avez deja essaye » et « 60 jours, 4 etapes » sont le MEME composant :
   a partir de 1024px ils recoivent tous les deux le chrome de carte (blanc,
   rayon 16, ombre douce, titre 21px/500). En dessous, ils retombaient sur une
   liste a filets, c'est-a-dire sur un tout autre objet que celui qu'on voit
   sur ordinateur. Le chrome est donc pose ICI, dans la base, et non dans une
   regle mobile separee.
   C'est ce qui permet de rester en mobile d'abord. Une regle bornee a
   `.blockers--etapes .blocker` (2 classes) aurait battu la correction du bloc
   >= 1024px, qui s'ecrit `.blocker` (1 classe) : le reglage telephone serait
   remonte sur l'ordinateur sans que rien ne le signale. En corrigeant la base
   au meme niveau de precision, la regle bureau reprend la main d'elle-meme,
   par simple ordre de lecture. */
.blockers__list { list-style: none; margin: 0; padding: 0; text-align: left; display: grid; gap: 14px; }
.blocker {
  display: grid;
  grid-template-columns: 50px 1fr;
  align-items: start;
  gap: 14px;
  padding: 22px;
  border-radius: 16px;
  background: #fff;
  box-shadow: 0 1px 2px rgba(16, 16, 18, .04);
}
/* Chiffres « filigrane » : même gabarit que .benefit__num, transposé en clair. */
.blocker__num {
  /* 38 et non 46 : dans une carte de 402px moins ses 44px de marges, le chiffre
     d'avant touchait presque le titre. Le bureau le reprend a 54px, ligne
     `.benefit__num, .blocker__num` du bloc >= 1024px. */
  font-size: 38px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.03em;
  color: rgba(19, 19, 21, .14);
  font-variant-numeric: tabular-nums;
}
.blocker__body { min-width: 0; }
/* Chevron d'enchainement : masque par defaut. Il ne sert que quand les 4
   etapes forment une rangee, c'est-a-dire a partir de 1024px, ou il est
   rallume et positionne dans la gouttiere. */
.blocker__chev { display: none; }
/* Titre bi-ton, meme convention que .scard__title dans la partie sombre : la
   TETE du groupe est attenuee, ce qui reste en pleine encre est le mot qui
   porte l'etape. Au balayage on ne lit que ces mots-la, et ils suffisent. */
.blocker__lead { color: var(--faint); }
/* Le titre de carte du bureau, des le telephone : 21px en 500, serre a 1,05.
   C'est le reglage de .scard__title, celui des cartes d'etudes, et le bloc
   >= 1024px le reprend a l'identique pour les memes cartes. Il n'y avait pas de
   raison qu'il ne vaille qu'au-dessus de 1024 : un titre de carte en 16px/700
   se lit comme une alerte, pas comme un intitule. */
.blocker__title {
  margin: 0 0 6px;
  font-size: 21px;
  line-height: 1.05;
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--ink);
}
.blocker__text {
  margin: 0;
  font-size: 15px;
  line-height: 1.4;
  font-weight: 400;
  color: var(--muted);
}

/* LES FLECHES D'ENCHAINEMENT, SUR TELEPHONE AUSSI.
   Elles n'existent que dans les 4 etapes, et c'est voulu : les etapes sont une
   SUITE, les 3 constats de « Vous avez deja essaye » n'en sont pas une. Le HTML
   ne les porte donc que sur les cartes 2, 3 et 4 : chacune marque l'ecart qui
   la PRECEDE, et il n'y en a pas avant la premiere.
   Empilees, elles se suivent de haut en bas : la fleche bascule d'un quart de
   tour et se pose dans l'ecart au-dessus de sa carte. C'est ce que le filet
   faisait implicitement dans l'ancienne liste, et que la carte seule perd. */
.blockers--etapes .blocker { position: relative; }   /* ancre la fleche */
.blockers--etapes .blocker__chev {
  display: block;
  position: absolute;
  left: 50%;
  bottom: calc(100% + 7px);        /* 7px = la moitie de l'ecart de 14px */
  width: 16px;
  height: 16px;
  transform: translate(-50%, 50%) rotate(90deg);
  color: rgba(19, 19, 21, .3);
}

/* ===================== QUI A ETABLI LES METHODES =====================
   En-tete emprunte a .blockers : la page n'a qu'une seule facon d'ouvrir un
   bloc clair, ce n'est pas ici qu'on en invente une 2e.

   GABARIT : PORTRAIT EN TETE, puis le nom, puis le reste. Deux etats ont ete
   ecartes avant celui-ci : une table « levier -> publication » (exacte, et sans
   personne dedans), puis des cartes blanches a ombre avec un petit monogramme
   en pastille (l'humain y restait un detail a cote du texte). Ici la tuile
   occupe toute la largeur de la cellule et ouvre la lecture : on voit d'abord
   quelqu'un, on lit ensuite.

   GRILLE A FILETS, PAS DES CARTES FLOTTANTES. Six ombres portees alignees font
   six objets separes ; des filets font UN tableau, ce qui est le bon signal :
   ces gens n'ont rien en commun sauf d'etre chacun a l'origine d'un levier. */

/* CE BLOC A ETE MASQUE SOUS 1024 px PENDANT UN TEMPS, IL NE L'EST PLUS.
   Il etait bati pour 3 colonnes : la tuile de portrait occupait la largeur de
   la cellule, ce qui lui donnait 260 px et ouvrait la lecture. En une seule
   colonne, la meme tuile devenait un aplat gris de 148 px repete 6 fois l'un
   sous l'autre : 1 830 px de defilement pour 6 lignes de texte, dont les deux
   tiers en emplacements vides. Le gabarit ne se transposait pas, et la section
   a donc ete purement retiree du telephone.
   LA LIGNE QUI DEFILE REGLE LE PROBLEME PAR LA GEOMETRIE. Une rangee n'a pas de
   hauteur qui explose quand la largeur diminue : elle montre moins de cartes a
   la fois, c'est tout. Le meme bloc vaut donc a toutes les largeurs, et le
   visiteur sur telephone recupere une section qu'il ne voyait pas du tout. */

/* ===== LA LIGNE QUI DEFILE : MEME MECANIQUE QUE LE BANDEAU DE PRESSE =====
   .authority__track, plus haut dans ce fichier, fait deja exactement ca et
   c'est de lui que tout est repris : une piste en `width: max-content` qui
   contient DEUX FOIS la meme liste et se translate de 0 a -50 %. A -50 % l'image
   est identique a celle du depart, donc la boucle ne se voit pas. L'animation
   `authority-marquee` est litteralement la sienne, reutilisee sans copie.

   58s et non ses 38s : ces cartes portent du texte a lire, pas des logos a
   reconnaitre au vol. */
.auths-vue {
  position: relative;                /* pour les 2 voiles de flou ci-dessous */
  overflow: hidden;
  /* Les 2 bords s'estompent, pour qu'une carte n'arrive pas au ras d'une arete.
     Meme geste que .authority__viewport. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 4%, #000 96%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 4%, #000 96%, transparent);
}

/* LES CARTES ARRIVENT ET REPARTENT FLOUES.
   Le fondu ci-dessus ne faisait que les EFFACER : une carte perdait son encre
   en gardant ses contours nets, ce qui se lit comme un texte trop pale plutot
   que comme un objet qui entre. Le flou ajoute la profondeur qui manquait :
   la carte se forme en avancant et se defait en sortant, et l'oeil comprend
   qu'il y en a d'autres derriere le bord.

   COMMENT. 2 voiles poses sur les bords, qui ne peignent RIEN : ils floutent
   ce qui passe dessous (`backdrop-filter`). Leur propre masque va de l'opaque
   au bord vers le transparent en 12 %, donc le flou est fort a l'arete et a
   disparu bien avant le milieu. Les 2 masques se superposent au fondu du
   parent : la carte perd sa nettete d'abord, sa couleur ensuite.

   `z-index: 1` N'EST PAS DECORATIF. La piste porte un `transform`, ce qui la
   fait peindre au meme etage que les elements positionnes : sans cet index,
   le voile de gauche, qui est le PREMIER enfant, passait DERRIERE les cartes
   et ne floutait rien. Celui de droite, dernier enfant, fonctionnait. Un seul
   bord flou sur les 2 : le defaut se voyait sans qu'on sache d'ou il venait.

   Un navigateur sans `backdrop-filter` n'affiche simplement pas les voiles,
   qui ne peignent aucune couleur : on retombe sur le fondu seul, c'est-a-dire
   sur l'etat d'avant. Rien a prevoir pour ce cas. */
.auths-vue::before,
.auths-vue::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  /* 120 px sur une bande de 1100, mais 22 % sur un telephone : a largeur fixe,
     les 2 voiles mangeaient 240 px d'une bande qui en fait 335, et il ne
     restait presque plus de zone nette au milieu. */
  width: min(120px, 22%);
  z-index: 1;
  pointer-events: none;              /* le survol doit atteindre la piste */
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
}
.auths-vue::before {
  left: 0;
  -webkit-mask-image: linear-gradient(90deg, #000 12%, transparent);
          mask-image: linear-gradient(90deg, #000 12%, transparent);
}
.auths-vue::after {
  right: 0;
  -webkit-mask-image: linear-gradient(270deg, #000 12%, transparent);
          mask-image: linear-gradient(270deg, #000 12%, transparent);
}
.auths-piste {
  display: flex;
  width: max-content;
  animation: authority-marquee 58s linear infinite;
}
.auths-piste:hover { animation-play-state: paused; }

/* LA BANDE DEFILE DANS TOUS LES CAS, Y COMPRIS EN MOUVEMENT REDUIT.
   Ce n'est pas le reglage par defaut pour du texte qui bouge, et ce fichier a
   porte l'inverse : en `prefers-reduced-motion: reduce`, la piste s'arretait et
   se DEPLIAIT en grille de 3 colonnes, parce qu'une bande figee ne montrait que
   4 chercheurs sur 6 sans aucun moyen d'atteindre les 2 autres.
   Le client a tranche autrement : la section doit defiler pour tout le monde,
   c'est ce qu'elle est censee montrer. Le probleme des 2 chercheurs
   inatteignables tombe de lui-meme, puisque la bande ne s'arrete plus.
   CE QUI RESTE POUR CELUI QUI A COUPE LES ANIMATIONS : le survol. La bande
   ralentit de 58s a 200s le tour des qu'on entre dedans (voir `data-bande` dans
   app.js, qui traite cette piste meme en mouvement reduit, grace a
   `data-bande-mouvement="toujours"`), et la regle `:hover` ci-dessus la met en
   pause nette si le script ne tourne pas. Rien ne file sans qu'on puisse le
   lire, et rien n'est hors d'atteinte.
   LE BANDEAU DE PRESSE, LUI, NE CHANGE PAS : il garde son animation CSS en
   mouvement reduit, sans reprise JS. Les 2 bandes ne suivent plus la meme
   regle, et c'est voulu : la decision porte sur cette section-ci. */

.auths {
  list-style: none;
  display: flex;
  /* `flex: 0 0 auto` sur les 2 niveaux : un element de flex se laisse retrecir
     par defaut, et les 2 exemplaires de la liste se chevauchaient au lieu de se
     suivre. */
  flex: 0 0 auto;
  gap: 22px;
  padding: 0 22px 0 0;
  margin: 0;
  text-align: left;
}
.auth {
  flex: 0 0 auto;
  width: 296px;
  display: flex;
  flex-direction: column;
  padding: 0;
}
/* LA TUILE : EMPLACEMENT DU PORTRAIT, tenu par un monogramme.
   Aucune de ces personnes n'a donne son accord, et en usage commercial publier
   un visage sans consentement est une atteinte au droit a l'image, meme sans
   laisser entendre le moindre partenariat. La tuile a donc DEJA la geometrie
   d'une photo (carree, pleine largeur, meme rayon) : le jour ou un accord ecrit
   existe, un <img> remplace ce <span> et rien ne bouge dans la page.
   Le fichier devra etre servi depuis le site : la CSP est en img-src 'self',
   un portrait appele chez un tiers ne s'afficherait pas. */
.auth__tile {
  display: flex;
  align-items: center;
  justify-content: center;
  /* Un cran moins haute que large. Carree, a 340px de large, la tuile faisait
     340px de haut : 6 aplats de cette taille et la section n'etait plus qu'un
     mur gris, le texte reduit a une legende. En 4/3 elle reste un cadre de
     portrait credible et rend un tiers de sa hauteur au contenu. */
  aspect-ratio: 4 / 3;
  /* PLEINE LARGEUR DE SA CARTE, A TOUTES LES LARGEURS D'ECRAN.
     Elle etait bornee a 148px, et cette borne servait au temps de la PILE : en
     une colonne, une tuile pleine largeur faisait 335px sur telephone, et
     6 portraits de cette taille l'un sous l'autre ne faisaient plus qu'un mur.
     La carte de la ligne fait 296px, la meme partout : il n'y a plus de pile a
     proteger, et 2 largeurs de tuile selon l'ecran n'auraient plus de sens. */
  width: 100%;
  margin: 0 0 12px;
  border-radius: 12px;
  background: #ececef;
  color: rgba(19, 19, 21, .22);
  font-size: 34px;
  font-weight: 700;
  letter-spacing: .06em;
  line-height: 1;
}
/* LA TUILE QUAND ELLE PORTE UNE PHOTO.
   Le cadre reste en 4/3 paysage, comme les tuiles a initiales : 6 cartes cote a
   cote doivent garder le meme gabarit, sinon la grille se deforme au fur et a
   mesure que les portraits arrivent.

   ON NE RECADRE PAS LE VISAGE. Ces portraits sont verticaux ; les faire entrer
   de force dans un cadre paysage revient a couper la tete ou le menton. Le fond
   du portrait est donc PROLONGE jusqu'aux proportions du cadre, a la
   fabrication de l'image : le sujet garde sa taille et ses proportions, et ce
   sont des bandes de son propre fond qui completent la largeur.

   L'image arrive donc DEJA en 4/3. Il n'y a plus rien a recadrer ici, et
   object-fit ne sert qu'a se premunir d'un arrondi au pixel.

   Le fond de la tuile reprend celui du portrait, releve dans le fichier et non
   suppose : un noir de tuile different du noir de la photo laisserait une
   couture visible sur les bords arrondis. */
.auth__tile--photo {
  overflow: hidden;
  background: rgb(3, 4, 1);
  padding: 0;
}
.auth__tile--photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  border-radius: inherit;
}

.auth__name {
  margin: 0;
  font-size: 18px;
  line-height: 1.2;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ink);
}
/* L'institution est CITEE, jamais affichee en logo : on nomme d'ou vient le
   travail, on ne fait pas cautionner l'universite. */
.auth__role {
  margin: 4px 0 0;
  font-size: 13px;
  line-height: 1.35;
  color: var(--faint);
}
/* UNE LIGNE, PAS UN RESUME D'ETUDE. Ce bloc a d'abord porte le detail du
   protocole experimental (effectifs, durees, pourcentages) : 4 a 5 lignes par
   carte, et la section redevenait un article. Or ce qui argumente ici, c'est
   la PERSONNE et son titre, pas la methodologie. La phrase a donc le chercheur
   pour sujet (« A etabli que... ») : ca dit ce qu'il possede comme terrain, et
   ca tient en une ligne. Les chiffres, eux, sont deja dans la section Etudes.
   Regle : si une de ces lignes depasse 2 lignes a l'ecran, c'est qu'elle
   explique au lieu de nommer. */
.auth__find {
  flex: 1;                          /* pousse la source en bas : les notes de
                                       toutes les cartes d'une rangee tombent
                                       sur la meme ligne. */
  margin: 16px 0 0;
  font-size: 14px;
  line-height: 1.45;
  color: var(--muted);
}
/* Le levier, en tete de la phrase et non en etiquette flottante : c'est lui qui
   raccroche le chercheur AU PROTOCOLE. Sans lui, la section n'est qu'une
   galerie de gens qui n'ont rien a voir avec ce qu'on vend. */
.auth__lever {
  display: block;
  margin: 0 0 5px;
  font-size: 10px;
  line-height: 1;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink);
}
/* Meme ligne de source que les cartes d'etudes (.scard__cite) : pictogramme
   dans la marge, titre de revue en italique. Le lecteur a deja vu cette ligne
   dans la partie sombre, il sait ce qu'elle veut dire. */
.auth__cite {
  position: relative;
  margin: 12px 0 0;
  padding-left: 19px;
  font-size: 11.5px;
  line-height: 1.35;
  color: var(--faint);
}
.auth__cite svg {
  position: absolute;
  left: 0;
  top: 1px;
  width: 12px;
  height: 12px;
  opacity: .8;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
}
.auth__cite em { font-style: italic; }
/* ===================== LE PROTOCOLE ===================== */
/* Suite directe de « Ce qui bloque » : les 5 métiers en cartes blanches, puis le
   comparatif. En-tête (eyebrow / titre bi-ton / sous-titre) au gabarit exact de
   .blockers pour que les deux blocs de la partie claire s'enchaînent sans rupture. */
.protocole {
  margin: var(--s11) 0 0;           /* 64px, comme entre citation et .blockers */
  text-align: center;
}
.protocole__eyebrow {
  margin: 0 0 var(--s3);
  font-size: 11px;
  line-height: 1;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--faint);
}
.protocole__title {
  margin: 0 0 var(--s4);
  text-wrap: balance;
  font-size: var(--t-h2);
  line-height: 1.06;
  font-weight: 500;
  letter-spacing: -0.03em;
  color: var(--ink);
}
/* Ici la 2e phrase tient sa propre ligne (maquette) -> block, contrairement à .blockers. */
.protocole__title-dim { display: block; color: var(--muted); font-weight: 500; }
.protocole__sub {
  margin: 0 auto var(--s8);         /* 40px avant le comparatif */
  max-width: 34ch;
  text-wrap: balance;               /* « fait. » ne reste pas seul sur sa ligne */
  font-size: var(--t-body);
  line-height: 1.35;
  color: var(--muted);
}

/* --- Comparatif Seul / Un coach / Le protocole --- */
/* La colonne « Le protocole » est surlignée sur toute la hauteur : le fond est posé
   cellule par cellule (un tableau ne permet pas de peindre une colonne d'un bloc),
   les coins arrondis venant de la 1re et de la dernière cellule de la colonne. */
.cmp {
  position: relative;                 /* repère de la carte blanche, voir ::after */
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  text-align: center;
}
.cmp__corner { width: 32%; }
.cmp__head, .cmp__cell { width: 21%; }
.cmp__head--hl, .cmp__cell--hl { width: 26%; }   /* la colonne mise en avant respire le plus */

/* CARTE BLANCHE derrière la colonne mise en avant.
   Dessinée par UN pseudo-élément et non par le fond de chaque cellule, comme
   c'était le cas avant. Une ombre posée sur des <td> se serait redessinée entre
   chaque ligne, en travers de la colonne : ici la surface est continue du haut
   du tableau à son bas, et l'ombre n'a qu'un seul contour à suivre.
   `left: 74%` n'est pas un réglage à l'œil : c'est 32 + 21 + 21, la somme des
   colonnes qui précèdent, et `table-layout: fixed` garantit que le navigateur
   respecte ces largeurs au pixel. Si les pourcentages ci-dessus changent, cette
   ligne se recalcule de la même façon.
   Le rayon vaut 16px : le fichier réserve --r-card (22px) à la carte de page,
   et 16px est le rayon des composants posés dessus (.quote, .tcard, .plan). */
.cmp::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 74%;
  width: 26%;
  z-index: 0;
  border-radius: 16px;
  background: #fff;                   /* la section est sur #f2f2f3 : le blanc suffit à soulever */
  box-shadow: var(--ombre-hl);
}
/* Le contenu repasse AU-DESSUS de la carte. Sans cette remontée, les cellules
   restent au niveau 0 comme le pseudo-élément, qui est écrit après elles dans
   l'ordre du document et les recouvrirait donc entièrement. */
.cmp__head, .cmp__cell, .cmp__row { position: relative; z-index: 1; }

.cmp__head {
  padding: 22px 6px 16px;             /* le haut de la carte respire au-dessus des intitulés */
  font-size: 12px;
  line-height: 1.3;
  font-weight: 500;
  color: var(--faint);
  vertical-align: bottom;
}
/* Le nom de la marque, pas un intitulé de colonne : c'est lui qu'on doit lire en
   premier dans la carte. Minuscules, comme partout où le mot est écrit. */
.cmp__head--hl {
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--ink);
}

/* PAS DE FILETS entre les lignes. C'est l'espacement qui sépare, comme dans les
   comparatifs qui se lisent d'un coup d'œil : 5 filets sur 4 colonnes ajoutaient
   20 segments de gris à une grille que la carte structure déjà toute seule. */
.cmp__row {
  padding: 16px 10px 16px 2px;
  font-size: 13px;
  line-height: 1.35;
  font-weight: 700;
  text-align: left;
  color: var(--ink);                  /* l'intitulé porte la ligne : pleine encre */
}
.cmp__cell {
  padding: 16px 6px;
  font-size: 13px;
  line-height: 1.35;
  color: var(--faint);                /* colonnes « Seul » / « Un coach » en retrait */
}
.cmp__cell--hl {
  font-weight: 700;
  color: var(--ink);                  /* la colonne qui doit gagner : pleine encre */
}
.cmp tbody tr:last-child .cmp__cell,
.cmp tbody tr:last-child .cmp__row { padding-bottom: 24px; }   /* le bas de la carte respire aussi */

/* Coche et croix : mêmes symboles que la liste « c'est pour vous / ce n'est pas
   pour vous » (#i-check, #i-cross), donc même trait et même dessin. Ils ne
   remplacent que les Oui / Non : partout où la valeur dit autre chose qu'un
   binaire (« Parfois », « Les 6 »), le mot reste, il porte plus que le symbole. */
.cmp__ico {
  width: 18px;
  height: 18px;
  display: inline-block;
  vertical-align: -4px;
  color: var(--faint);
}
.cmp__cell--hl .cmp__ico { color: var(--ink); }

/* Le seul accent du tableau, posé sur l'écart le plus fort de la grille
   (« Un seul » contre « Les 6 »). Pastille sombre : c'est le dispositif
   d'emphase du site (les boutons), --raise restant réservé au prix. */
.cmp__badge {
  display: inline-block;
  padding: 4px 10px;
  border-radius: var(--r-pill);
  background: var(--black);
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.2;
}

/* Texte réservé aux lecteurs d'écran : une cellule qui ne contient qu'un
   pictogramme n'a aucun nom accessible, et le tableau se lirait « Savoir par où
   commencer, vide ». Retiré du flux sans `display: none`, qui l'effacerait
   aussi pour eux. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ===================== ADÉQUATION ===================== */
/* Deux cartes en vis-à-vis : à qui le protocole s'adresse, et à qui il ne s'adresse pas.
   La carte « oui » reprend le chrome blanc du site (rayon 16, ombre douce) ; la carte
   « non » est peinte du gris #e9e9ea déjà utilisé par la colonne mise en avant du
   comparatif : c'est le gris « en retrait » de la partie claire, aucune valeur inventée. */
.fit {
  margin: var(--s11) 0 0;
  text-align: center;
}
.fit__eyebrow {
  margin: 0 0 var(--s3);
  font-size: 11px;
  line-height: 1;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--faint);
}
.fit__title {
  margin: 0 0 var(--s6);            /* 24px avant la première carte */
  font-size: var(--t-h2);
  line-height: 1.06;
  font-weight: 500;
  letter-spacing: -0.03em;
  color: var(--ink);
  text-wrap: balance;
}

.fit__card {
  padding: 20px;
  border-radius: 16px;              /* = .objection, .quote, cartes d'avis */
  background: #fff;
  box-shadow: 0 1px 2px rgba(16, 16, 18, .04);
  text-align: left;
}
.fit__card + .fit__card { margin-top: 12px; }
/* Carte « non » : en retrait, ni blanche ni ombrée -> elle recule d'un plan. */
.fit__card--out {
  background: #e9e9ea;
  box-shadow: none;
}

.fit__lead {
  margin: 0 0 14px;
  font-size: var(--t-body);
  line-height: 1.3;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.fit__card--out .fit__lead { color: var(--muted); }

.fit__list { list-style: none; margin: 0; padding: 0; }
.fit__item,
.plan__item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 7px 0;
  font-size: 15px;
  line-height: 1.35;
  color: var(--ink);
}
.fit__card--out .fit__item { color: var(--faint); }
.fit__ico,
.plan__ico {
  flex: none;
  width: 16px;
  height: 16px;
  margin-top: 3px;                  /* aligne le pictogramme sur la 1re ligne de texte */
}

/* ===================== TARIFS ===================== */
/* Deux temps : le détail de ce que vaut chaque pièce, puis les deux formats.
   En-tête au gabarit des autres blocs clairs ; cartes au chrome du site (rayon 16,
   ombre douce) ; les deux CTA réutilisent .btn-outline et .btn-primary, donc aussi
   le verre monochrome du bouton principal, sans une ligne de style en plus. */
.pricing {
  margin: var(--s11) 0 0;
  text-align: center;
}
.pricing__eyebrow {
  margin: 0 0 var(--s3);
  font-size: 11px;
  line-height: 1;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--faint);
}
.pricing__title {
  margin: 0 0 var(--s4);
  font-size: var(--t-h2);
  line-height: 1.06;
  font-weight: 500;
  letter-spacing: -0.03em;
  color: var(--ink);
  text-wrap: balance;
}
/* LE MONTANT BARRÉ du titre des tarifs. Il reprend la seconde voix des titres
   bi-ton de la page (.blockers__title-dim, .protocole__title-dim) : le même gris,
   la même fonction, celle de ce qu'on écarte au profit de ce qui suit. Le trait
   s'y ajoute.
   `line-through` et non un pseudo-élément posé par-dessus : le trait suit ainsi
   le crénage et la taille réelle du chiffre, qui va de 28 à 40px selon l'écran.
   Son épaisseur est donnée en `em` pour la même raison : à 2px fixes, elle
   passait de franche sur téléphone à filiforme sur un 1920. */
.pricing__strike {
  color: var(--faint);
  text-decoration: line-through;
  text-decoration-thickness: .065em;
}

.pricing__sub {
  margin: 0 auto var(--s8);
  max-width: 34ch;
  font-size: var(--t-body);
  line-height: 1.35;
  color: var(--muted);
  text-wrap: balance;
}

/* --- Détail de la valeur --- */
/* Posé à même le fond de section, sans carte : c'est un décompte, pas une offre. */
.value { text-align: left; }
.value__eyebrow {
  margin: 0 0 var(--s3);
  font-size: 11px;
  line-height: 1.3;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--faint);
}
.value__list { margin: 0; padding: 0; }
.value__row {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 11px 0;
  border-bottom: 1px dotted var(--line);   /* filet pointillé : conduit l'œil au prix */
}
.value__label {
  flex: 1;
  min-width: 0;
  font-size: 14px;
  line-height: 1.3;
  color: var(--muted);
}
.value__price {
  flex: none;
  margin: 0;
  white-space: nowrap;                     /* les fourchettes ne cassent jamais */
  font-size: 14px;
  line-height: 1.3;
  font-variant-numeric: tabular-nums;      /* les prix s'alignent au chiffre près */
  color: var(--faint);
}
/* Total : c'est le chiffre qui doit rester en tête -> pleine encre, filet plein. */
.value__row--total {
  border-bottom: 0;
  border-top: 1px solid var(--line);
  margin-top: 4px;
  padding-top: 14px;
}
.value__row--total .value__label { font-weight: 700; color: var(--ink); }
.value__row--total .value__price { font-size: 16px; font-weight: 700; color: var(--ink); }

/* Chute du tableau d'ancrage. Le total au-dessus est le chiffre de l'alternative ;
   celui-ci est le nôtre, et c'est lui qui doit rester. Il est donc en pleine encre
   et à la taille du corps, pas en note de bas de bloc comme l'ancien commentaire. */
.value__kicker {
  margin: var(--s5) 0 0;
  font-size: var(--t-body);
  line-height: 1.4;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--ink);
  text-wrap: balance;
}
.value__kicker strong { font-weight: 700; }

/* Disponibilité : le seul bandeau sombre de la partie claire. Deux essais plus
   discrets (pastille blanche, puis intertitre à filets) passaient inaperçus. On
   emploie donc le dispositif le plus fort de la page : grand chiffre + libellé en
   petites capitales, exactement la grammaire du bandeau « 60 JOURS / 30 MIN » de la
   section sombre. La matière est le VERRE MONOCHROME partagé avec la citation et les
   cartes d'avis, et non un aplat noir : la partie claire n'emploie nulle part de noir
   plein sur toute une largeur, ça tranchait trop. */
.pricing__seats {
  position: relative;
  --r-verre: 16px;                  /* rayon de la plaque : la découpe des nappes le reprend */
  overflow: hidden;                 /* clippe les nappes au rayon */
  isolation: isolate;               /* contient le mix-blend-mode */
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin: var(--s8) 0 0;
  padding: 16px 20px;
  border-radius: var(--r-verre);
  text-align: left;
}
.pricing__seats-num,
.pricing__seats-label { position: relative; z-index: 1; }
.pricing__seats-num {
  font-size: 32px;
  line-height: 1;
  font-weight: 600;
  letter-spacing: -0.03em;
  color: #fff;
  font-variant-numeric: tabular-nums;
}
.pricing__seats-label {
  font-size: 11px;
  line-height: 1.3;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .66);
}
/* Mention en retrait sous le bouton d'une carte : elle se lit comme une note,
   jamais comme un argument de plus. */
.plan__risk {
  /* La marge haute n'est PAS ici : elle est posee plus bas, avec le commentaire
     qui explique pourquoi la mention descend sous les cartes. Une valeur ecrite
     ici serait ecrasee par celle-la, donc trompeuse a la lecture. */
  font-size: 11px;
  line-height: 1.3;
  font-weight: 500;
  letter-spacing: .02em;
  color: var(--muted);
  opacity: .75;
  text-align: center;
}
/* La note d'indisponibilité reprend le même emplacement, mais pas le même
   registre : les 0,75 d'opacité et le gris de --muted conviennent à une mention
   de bas de carte qu'on survole du regard. Ici la phrase doit être LUE, c'est
   elle qui explique un bouton qui ne répond pas et qui indique l'autre chemin.
   Pleine opacité, encre du texte courant. */
.plan__risk--complet {
  opacity: 1;
  color: var(--ink);
  font-weight: 500;
}

/* --- Les formats --- */
.plan {
  position: relative;
  margin: var(--s6) 0 0;
  padding: 20px;
  border-radius: 16px;
  background: #fff;
  border: 1px solid transparent;
  box-shadow: 0 1px 2px rgba(16, 16, 18, .04);
  text-align: left;
}
/* Format recommandé : liseré sombre, pastille débordante et ombre de mise en
   avant, il sort du lot sans changer de couleur de fond (la page reste
   monochrome et claire). Il ouvre la liste des formats, et garde donc la marge
   haute commune : la pastille déborde de 11 px vers le haut, il lui faut cette
   place au-dessus de la carte. */
.plan--reco {
  border-color: var(--black);
  box-shadow: var(--ombre-hl);
}
.plan__badge,
.opt__badge,
.grt__badge {
  position: absolute;
  top: -11px;
  left: 20px;
  padding: 4px 10px;
  border-radius: 8px;               /* = les onglets d'études ; la page n'a pas de pilule ici */
  background: var(--black);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
}
/* La pastille d'ÉTAT, à ne pas confondre avec celle de mise en avant. Même
   gabarit que « Recommandé » pour qu'elles s'alignent, mais remplie de gris et
   non de noir : 2 pastilles noires côte à côte se liraient comme 2 mises en
   avant concurrentes, et « Complet » n'est pas un argument de vente, c'est
   l'état du format. Le gris la range au bon niveau de lecture sans l'effacer
   (8,8:1, elle se lit de loin). */
.plan__badge--complet {
  background: #ececed;
  color: #3d4046;
}
/* La carte complète ne change RIEN d'autre : ni fond, ni opacité, ni bordure.
   Voir le commentaire dans index.html — elle sert d'ancre de prix, l'estomper
   coûterait plus que la disponibilité qu'elle a perdue. */

.plan__name {
  margin: 0 0 6px;
  font-size: 11px;
  line-height: 1;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--faint);
}
.plan__price {
  margin: 0;
  font-size: 34px;
  line-height: 1;
  font-weight: 500;
  letter-spacing: -0.03em;
  color: var(--ink);
}
.plan__term {
  margin: 6px 0 0;
  font-size: 13px;
  line-height: 1.3;
  color: var(--faint);
}
/* Paiement fractionné, à la place de la hausse non datée. Même emplacement
   (au contact du prix, là où la décision se prend), mais c'est un MÉCANISME et
   non une affirmation : il n'y a rien à croire, il se vérifie au paiement.
   Il reprend l'accent bordeaux (--raise), laissé libre par le retrait de la
   hausse, qui reste ainsi le seul point de couleur du site. */
.plan__pay {
  margin: 8px 0 0;
  font-size: 13px;
  line-height: 1.35;
  color: var(--muted);
}
.plan__pay strong { font-weight: 700; color: var(--raise); }
/* Chapeau du Prestige : la phrase qui dit CE QU'ON ACHETE EN PLUS, avant la
   liste. Il n'existe que sur cette carte-la, le Protocole n'en a pas besoin.
   (Cette regle vivait en fin de feuille, entre le bloc reduced-motion et le
   bloc impression, ou personne ne serait alle la chercher : elle rejoint
   ici les autres regles .plan__*, dont elle reprend les jetons.) */
.plan__lead {
  margin: var(--s5) 0 0;
  font-size: 15px;
  line-height: 1.4;
  color: var(--muted);
}
.plan__lead strong { font-weight: 700; color: var(--ink); }
/* UNE LIGNE = UN LIVRABLE, puis ce qu'il recouvre.
   La carte alignait treize puces en phrases completes, groupees sous quatre
   intertitres. Une carte de prix ne se lit pas, elle se BALAYE : l'oeil n'y
   trouvait aucune prise et decrochait avant le bouton. Les livrables sont
   ramenes a 4, chacun ecrit en 2 temps : un groupe nominal en gras, que le
   balayage suffit a saisir, et une ligne grise plus petite qui ne se lit
   qu'ensuite, et seulement si on la cherche. C'est le gabarit deja employe
   par les cartes du tunnel (.pl__item dans evaluation.css) : un seul motif
   pour les 2 ecrans ou l'offre se decide. */
.plan__list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin: var(--s5) 0 var(--s5);
  padding: 0;
}
.plan__item { align-items: flex-start; padding: 0; }
.plan__item b {
  display: block;
  font-size: 15px;
  line-height: 1.3;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.plan__item em {
  display: block;
  margin-top: 3px;
  font-style: normal;                /* <em> pour le balisage, pas pour l'italique */
  font-size: 13.5px;
  line-height: 1.4;
  color: var(--muted);
}

/* --- Ce qui est OFFERT ---
   C'etait la 4e liste de la carte, au gabarit exact des trois autres : rien ne
   disait que c'etait un bonus, et donc personne ne le voyait. Il sort de la
   liste et devient un bloc a lui : un fond distinct pour le detacher du reste
   de la carte, et la pastille noire du site (celle de .plan__badge) pour le
   nommer. C'est le seul aplat noir a l'interieur de la carte : au balayage,
   c'est ce qu'on voit apres le prix. */
.plan__bonus {
  /* Un ecart EN DESSOUS autant qu'au dessus : sans lui le bloc se colle au
     bouton, et l'oeil le rattache au bouton plutot qu'a l'offre. C'est un 5e
     livrable, pas une etiquette de bouton. */
  margin: var(--s5) 0 var(--s5);
  padding: 14px 16px;
  border-radius: 12px;              /* un cran sous les 16px de la carte qui le porte */
  background: #f4f4f5;
}
/* En-tete : la pastille COMPTE les bonus (« 2 bonus offerts »), et la valeur de
   l'alternative se pose en face. Les 2 informations qui decident sont donc lues
   ensemble, avant meme le detail : combien j'en ai, et ce que je ne paie pas. */
.plan__bonus-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: 0 0 10px;
}
.plan__bonus-lab {
  display: inline-block;
  margin: 0;
  padding: 4px 9px;
  border-radius: 8px;
  background: var(--black);
  color: #fff;
  font-size: 10px;
  line-height: 1.3;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
}
/* Pas de prix barre ici : le mot « ailleurs » dit deja que ce n'est pas le notre,
   et la barre est reservee au titre (.pricing__strike), ou elle porte l'ancrage
   principal. Deux barres sur le meme ecran, et aucune ne se voit plus. */
.plan__bonus-worth {
  margin: 0;
  font-size: 12px;
  line-height: 1.3;
  font-weight: 600;
  color: var(--faint);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
/* UNE CARTE = UN BONUS = UN PRIX.
   1er essai : 2 lignes separees par un filet pointille, dans le gabarit de
   .value__row. Trop faible : sous un meme filet, 2 lignes se lisent comme un
   seul poste coupe en 2, ce qui etait exactement le defaut a corriger. Chaque
   bonus prend donc sa propre surface. Blanches sur le gris du bloc, elles se
   comptent d'un coup d'oeil, sans avoir a lire.
   Le rayon descend d'un cran a chaque emboitement : 16 pour la carte de prix,
   12 pour le bloc offert, 10 pour les cartes de bonus. */
.plan__bonus-list { margin: 0; padding: 0; }
.plan__bonus-card {
  position: relative;               /* ancre le « + » de la carte suivante */
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 11px 13px;
  border-radius: 10px;
  background: #fff;
}
/* LE « + » ENTRE LES DEUX, et c'est tout ce qu'il a a dire : « et aussi un
   deuxieme ». Pose en ::before plutot qu'en balise, parce qu'un lecteur d'ecran
   entend deja 2 termes et 2 prix : il n'a pas besoin qu'on lui epelle un signe.
   Pas de pastille sous le signe : le noir de la carte est reserve a la pastille
   « 2 bonus offerts », un 2e aplat et plus aucun des deux ne se voit. */
.plan__bonus-card + .plan__bonus-card { margin-top: 25px; }
.plan__bonus-card + .plan__bonus-card::before {
  content: "+";
  position: absolute;
  top: -20px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 16px;
  line-height: 1;
  font-weight: 600;
  color: var(--muted);
}
.plan__bonus-name {
  flex: 1;
  min-width: 0;
  font-size: 14px;
  line-height: 1.35;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.plan__bonus-price {
  flex: none;
  margin: 0;
  font-size: 13px;
  line-height: 1.35;
  font-weight: 600;
  color: var(--faint);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
/* La raison. Un bonus offert sans motif se lit comme du remplissage ; celui-ci
   dit pourquoi il ne peut PAS etre en option, ce qui le rattache au protocole
   au lieu de le poser a cote. */
.plan__bonus-why {
  margin: 12px 0 0;
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--muted);
}
.plan .btn { width: 100%; }

/* Renversement du risque AU CONTACT DU BOUTON.
   Le bloc « Le risque est de notre côté » reste où il est, mais il est deux
   écrans plus bas sur téléphone, où les cartes s'empilent : celui qui décide
   sur la carte cliquait sans l'avoir lu. La ligne le rejoint donc là où
   l'objection naît, au moment où le prix vient d'être accepté ou refusé.
   C'est déjà le parti pris de la page tunnel, qui colle ses deux garanties
   sous les cartes plutôt qu'en note de bas d'écran.

   Registre : celui d'une mention légale, jamais celui d'un argument de plus. Une
   seule des deux garanties est citée, la plus proche de l'objection du moment
   (« et si je me trompe ? ») ; la seconde se lit dans le bloc. Les 2 cartes la
   portent : la rétractation de 14 jours vaut pour les 2 formats. */
.plan__risk { margin: 10px 0 0; }

/* ===================== OBJECTION ===================== */
/* Carte de réponse à l'objection d'âge, posée JUSTE APRÈS le bloc d'adéquation
   (c'est lui qui annonce « entre 35 et 49 ans », donc lui qui met l'âge dans la
   tête du lecteur) et juste avant la citation qui ouvre les tarifs. Chrome de carte
   du site : blanc, rayon 16 (comme .quote et les avis), ombre douce. Contrairement aux
   autres blocs clairs elle n'a ni accroche ni titre : c'est une prise de parole seule,
   donc alignée à gauche et non centrée. */
.objection {
  margin: var(--s11) 0 0;           /* 64px, comme les autres blocs de la section */
  padding: 20px;
  border-radius: 16px;
  background: #fff;
  box-shadow: 0 1px 2px rgba(16, 16, 18, .04);
  text-align: left;
}
/* L'objection elle-même : c'est la voix du visiteur, on la met en avant. */
.objection__quote {
  margin: 0 0 12px;
  font-size: var(--t-body);
  line-height: 1.3;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ink);
  text-wrap: balance;
}
.objection__text {
  margin: 0;
  font-size: 15px;
  line-height: 1.45;
  color: var(--muted);
}
/* Les quatre causes concrètes : seul passage en pleine encre du paragraphe. */
.objection__text strong { font-weight: 700; color: var(--ink); }

/* ===================== TÉMOIGNAGES (carrousel en éventail) ===================== */
/* Portage en HTML/CSS/JS natif du composant « stagger testimonials » : les cartes
   sont empilées en absolu, décalées horizontalement de cardSize/1.5 par cran,
   inclinées de ±2,5° en alternance ; la carte centrale se redresse, remonte et
   passe en noir. Clic ou glissement = la carte visée revient au centre. La taille
   est fixée ici par --tcard ; le JS la lit pour calculer l'écart entre les crans. */
.tstm {
  margin: var(--s11) 0 0;           /* 64px, comme les autres blocs de la partie claire */
  text-align: center;
}
.tstm__eyebrow {
  margin: 0 0 var(--s3);
  font-size: 11px;
  line-height: 1;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--faint);
}
.tstm__title {
  margin: 0 0 var(--s7);
  text-wrap: balance;
  font-size: var(--t-h2);
  line-height: 1.06;
  font-weight: 500;
  letter-spacing: -0.03em;
  color: var(--ink);
}
.tstm__title-dim { display: block; color: var(--muted); font-weight: 500; }

/* La scène déborde la gouttière de la section : les cartes latérales filent
   jusqu'aux bords de l'écran au lieu d'être coupées à 20px. */
.tstm__stage {
  --tcard: 284px;   /* légèrement plus large que haute (demande client) */
  position: relative;
  height: calc(var(--tcard-h, var(--tcard)) + 120px);   /* remontée de 60px + la nav */
  margin: 0 calc(var(--pad) * -1);
  overflow: hidden;
  touch-action: pan-y;             /* le swipe horizontal nous revient, le scroll reste à la page */
}
.tstm__deck { list-style: none; margin: 0; padding: 0; }

.tcard {
  position: absolute;
  --r-verre: 16px;                  /* rayon de la carte : la découpe des nappes le reprend */
  left: 50%;
  top: 50%;
  display: flex;
  flex-direction: column;           /* photo en haut, citation au centre, signature en bas */
  width: var(--tcard);
  /* Hauteur commune, mesurée par le JS sur le témoignage le plus long (--tcard-h) :
     les cartes restent alignées sans imposer un carré arbitraire qui laisserait un
     vide sous les citations courtes. --tcard sert de repli si le JS ne tourne pas. */
  height: var(--tcard-h, var(--tcard));
  padding: 18px;                    /* resserre a l'epoque ou la carte portait aussi
                                       une ligne de lecture audio ; conserve tel quel
                                       apres son retrait, voir plus bas */
  box-sizing: border-box;
  border-radius: var(--r-verre);    /* aligné sur .quote (l'autre témoignage de la page)
                                       et sur la pilule du header ; --r-card (22px) est
                                       réservé à la carte de page, trop rond ici */
  overflow: hidden;                 /* clippe les nappes aux coins arrondis */
  isolation: isolate;               /* contient le mix-blend-mode DANS la carte */
  background: #fff;
  border: 0;                        /* panneau brut, comme .scard et .quote */
  box-shadow: 0 1px 2px rgba(16, 16, 18, .04);
  text-align: left;
  cursor: pointer;
  transform: translate(-50%, -50%);     /* remplacé par le JS (position dans l'éventail) */
  transition: transform .5s ease, opacity .5s ease, filter .5s ease,
              background-color .5s ease, box-shadow .5s ease, color .5s ease;
}
/* Carte centrale : noire, redressée, posée au-dessus de la pile. */
/* Latérales : reléguées en arrière-plan « verre dépoli », dans l'esprit de la pilule
   du header, floutées et légèrement désaturées. Le flou rend leur texte illisible :
   c'est lui, et non un masque opaque, qui empêche de lire des phrases coupées au bord
   de l'écran. Elles restent donc bien visibles EN TANT QUE cartes, de chaque côté.
   Au-delà de 1024px, les plus éloignées se dissolvent en plus dans la gouttière :
   voir le fondu posé sur .tstm__stage dans la bande grand écran. */
.tcard:not(.is-center) {
  opacity: .85;
  filter: blur(3.5px) saturate(.92);   /* assez pour rendre le texte illisible, pas plus */
}
/* LE FLOU SE CREUSE AVEC L'ELOIGNEMENT, IL N'EST PLUS UNIFORME.
   La règle ci-dessus ne sait dire que « centre ou pas » : les 4 latérales
   recevaient donc le même flou, et les 2 plus éloignées arrivaient au bord de
   la colonne encore bien lisibles comme cartes, tranchées net. `data-rang` est
   posé par app.js (0 au centre, 1, puis 2 au-delà) et permet de les traiter
   séparément.
   C'EST LE FLOU QUI TRAVAILLE, PAS L'OPACITÉ. Le 2e rang a d'abord été descendu
   à 45 % : il s'évaporait dans le fond clair, et c'est précisément ce qu'on ne
   veut pas. La carte doit RESTER là, présente et coupée par le bord de la
   colonne ; c'est sa lisibilité qu'on retire, pas sa matière. L'opacité reste
   donc dans le registre d'origine, et seul le flou se creuse.
   Les 2 règles restent APRÈS celle du dessus, à précision égale : c'est l'ordre
   qui tranche, et l'absence de data-rang (script non exécuté) fait
   naturellement retomber sur le repli. */
.tcard[data-rang="1"] { opacity: .85; filter: blur(6px) saturate(.9); }
.tcard[data-rang="2"] { opacity: .78; filter: blur(13px) saturate(.85); }
.tcard.is-center {
  z-index: 3;                       /* le JS pose la même valeur en ligne */
  opacity: 1;
  cursor: default;
}

/* ---------- VERRE MONOCHROME (fond partagé) ----------
   Une seule définition pour les deux surfaces sombres posées sur la section claire :
   la citation de Daniel (.quote) et la carte d'avis au centre du carrousel.
   Plaque translucide + flou d'arrière-plan + deux nappes de lumière fondues en SCREEN.
   Les nappes viennent de la version iridescente d'origine, chaque couleur ayant été
   remplacée par son NIVEAU DE GRIS équivalent (luminance Rec. 709) : même texture,
   mêmes valeurs, sans la teinte. */
.quote,
.tcard.is-center,
.pricing__seats {
  background: rgba(20, 20, 20, .72);
  -webkit-backdrop-filter: blur(26px) saturate(1.5);
  backdrop-filter: blur(26px) saturate(1.5);
  box-shadow: 0 12px 30px rgba(0, 0, 0, .28);
}
.quote::before,
.quote::after,
.tcard::before,
.tcard::after,
.btn-primary::before,
.btn-primary::after,
.pricing__seats::before,
.pricing__seats::after {
  content: "";
  position: absolute;
  --debord: 25;                     /* de combien les nappes débordent, en % */
  inset: calc(-1% * var(--debord)); /* déborde -> flou diffus, pas de vignette aux bords */
  z-index: 0;
  pointer-events: none;
  /* Même découpe que sur .scard, et pour la même raison : `filter` +
     `mix-blend-mode` donnent à ces nappes leur propre couche de composition, que
     le GPU ne rogne qu'au RECTANGLE du parent. L'`overflow: hidden` des quatre
     porteurs ne suffit donc pas à leur tenir les coins arrondis : sans ce
     clip-path, la lumière déborde en équerres claires autour des quatre angles.
     Chaque porteur déclare son rayon dans --r-verre, juste à côté de son
     border-radius, qui en découle. */
  clip-path: inset(calc(100% * var(--debord) / (100 + 2 * var(--debord))) round var(--r-verre));
}
/* Nappe large : les lumières diffuses. */
.quote::before,
.tcard::before,
.btn-primary::before,
.pricing__seats::before {
  filter: blur(18px);
  mix-blend-mode: screen;
  background:
    radial-gradient(58% 70% at 12% 2%,   rgba(162, 162, 162, .85), transparent 60%),
    radial-gradient(56% 66% at 94% 8%,   rgba(161, 161, 161, .72), transparent 58%),
    radial-gradient(72% 84% at 84% 122%, rgba(209, 209, 209, .68), transparent 62%),
    radial-gradient(50% 58% at 58% 92%,  rgba(177, 177, 177, .45), transparent 62%),
    radial-gradient(60% 70% at 40% 55%,  rgba(255, 255, 255, .22), transparent 76%);
}
/* Sur-reflets : le shimmer par-dessus. */
.quote::after,
.tcard::after,
.btn-primary::after,
.pricing__seats::after {
  filter: blur(13px);
  mix-blend-mode: screen;
  background:
    radial-gradient(40% 32% at 28% 22%, rgba(255, 255, 255, .7),  transparent 68%),
    radial-gradient(46% 36% at 86% 76%, rgba(202, 202, 202, .6),  transparent 70%),
    radial-gradient(38% 30% at 62% 12%, rgba(203, 203, 203, .45), transparent 72%);
}
/* La plaque elle-même bascule d'un gris neutre à un gris froid : mêmes valeurs,
   le bleu n'est ajouté qu'au canal : assez pour que le panneau réponde aux
   reflets, trop peu pour se lire comme une couleur. */
.quote,
.pricing__seats { background: rgba(18, 21, 28, .72); }

/* ---- Exception : reflets bleutés sur la citation de Daniel ----
   Le verre du site est volontairement désaturé (voir plus haut). Ici, et ICI
   SEULEMENT, deux des halos retrouvent une teinte : un bleu froid très pâle,
   posé sur la même géométrie que les nappes grises : mêmes positions, mêmes
   rayons, mêmes opacités. Seule la couleur change, donc la matière reste celle
   du reste du site. Les autres surfaces de verre ne sont pas touchées. */
.quote::before {
  background:
    radial-gradient(58% 70% at 12% 2%,   rgba(151, 180, 216, .80), transparent 60%),
    radial-gradient(56% 66% at 94% 8%,   rgba(161, 161, 161, .72), transparent 58%),
    radial-gradient(72% 84% at 84% 122%, rgba(170, 198, 228, .62), transparent 62%),
    radial-gradient(50% 58% at 58% 92%,  rgba(177, 177, 177, .45), transparent 62%),
    radial-gradient(60% 70% at 40% 55%,  rgba(255, 255, 255, .22), transparent 76%);
}
.quote::after {
  background:
    radial-gradient(40% 32% at 28% 22%, rgba(226, 238, 253, .68), transparent 68%),
    radial-gradient(46% 36% at 86% 76%, rgba(176, 202, 232, .58), transparent 70%),
    radial-gradient(38% 30% at 62% 12%, rgba(203, 203, 203, .45), transparent 72%);
}

/* La citation et le bouton principal portent le verre en permanence ; sur les cartes
   d'avis il se révèle quand la carte arrive au centre, au rythme de la transition. */
.quote::before,
.pricing__seats::before { opacity: 1; }
.quote::after,
.pricing__seats::after  { opacity: .7; }

/* Sur le bouton, les nappes sont fortement atténuées : leurs halos sont dessinés en
   POURCENTAGES, donc sur une boîte de 40px de haut ils se compriment en un dégradé
   diagonal marqué là où ils restent diffus sur un grand panneau. À ce dosage, la
   couleur redevient uniforme et il ne subsiste qu'un voile de matière. */
.btn-primary::before { opacity: .3; }
.btn-primary::after  { opacity: .18; }
.tcard::before,
.tcard::after { opacity: 0; transition: opacity .5s ease; }
.tcard.is-center::before { opacity: 1; }
.tcard.is-center::after  { opacity: .7; }
.tcard__head, .tcard__quote { position: relative; z-index: 1; }
.tcard__who { min-width: 0; }

/* En-tête : portrait + nom sur une même ligne. Regrouper les deux rapproche le visage
   de l'identité (le « lien » recherché) et rend en même temps la carte moins haute que
   lorsque la photo occupait sa propre ligne en haut et la signature une autre en bas. */
.tcard__head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 12px;
}
.tcard__photo {
  display: block;
  flex: none;
  width: 64px;                          /* agrandi : le portrait porte la preuve */
  height: 64px;
  border-radius: 14px;
  overflow: hidden;
  background: #f1f1f3;                  /* emplacement photo, comme les vignettes du site */
}
.tcard__photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tcard.is-center .tcard__photo { background: rgba(255, 255, 255, .10); }   /* = .quote__photo */

/* La citation occupe toute la hauteur libre et s'y centre : les citations courtes
   ne laissent plus un trou au milieu de la carte, quelle que soit leur longueur. */
.tcard__quote {
  flex: 1;
  display: flex;
  align-items: center;
  min-height: 0;
  margin: 0;
  font-size: var(--t-body);
  line-height: 1.3;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--ink);
  transition: color .5s ease;
}
.tcard.is-center .tcard__quote { color: var(--dark-title); }
/* Identité : nom en première ligne, qualificatif en seconde. Deux lignes plutôt qu'une
   seule séparée par un point médian : à côté d'un portrait de 64px, la largeur restante
   ne tient pas « Nicolas, 46 ans · prénom modifié » sur un seul rang. */
.tcard__name {
  margin: 0;
  font-size: 14px;
  line-height: 1.25;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ink);
  transition: color .5s ease;
}
.tcard__meta {
  margin: 2px 0 0;
  font-size: 12px;
  line-height: 1.25;
  font-weight: 500;
  color: var(--faint);
  transition: color .5s ease;
}
/* Sur ce verre plus clair que la section sombre, --dark-text (#9b9ba2) disparaissait :
   la signature passe en blanc atténué, qui garde le même rapport au texte principal. */
.tcard.is-center .tcard__name { color: var(--dark-title); }
.tcard.is-center .tcard__meta { color: rgba(255, 255, 255, .5); }

/* --- PLUS DE LECTEUR AUDIO SUR LES CARTES ---
   Un bloc d'une soixantaine de lignes vivait ici : la ligne de lecture en pied
   de carte (bouton rond de 30px avec sa zone tactile invisible de 44px, piste
   de progression, duree), plus les etats .is-playing et .is-missing.
   Retire le 2026-09-07 avec le son lui-meme, a la demande du client. Le
   pourquoi et la liste complete de ce qui est parti avec sont ecrits une seule
   fois, dans index.html, juste au-dessus de <div class="tstm__stage">.
   UNE SEULE VALEUR N'A PAS BOUGE ET MERITE D'ETRE SIGNALEE : le `padding: 18px`
   de .tcard plus haut avait ete resserre POUR faire de la place a cette ligne.
   Il est laisse tel quel, la carte se contentant d'etre plus courte : y toucher
   changerait le dessin des cartes, ce qui n'est pas ce qui a ete demande. */

/* Mention d'anonymat : discrète, sous la pile. */
.tstm__note {
  margin: 14px 0 0;
  font-size: 11px;
  line-height: 1.3;
  color: var(--faint);
}

/* Nav prev/next, posée sous la pile. */
.tstm__nav {
  position: absolute;
  left: 50%;
  bottom: 0;
  transform: translateX(-50%);
  z-index: 4;   /* au-dessus de la carte centrale (3) */
  display: flex;
  gap: 4px;     /* boutons sans fond : resserrés, ils se lisent comme une seule paire */
}
/* Allégées : format réduit, plus de pastille blanche ni de filet : elles ne doivent
   pas rivaliser avec la carte. La zone tactile reste à 44px via ::before, sous le seuil
   duquel le bouton devient pénible à viser au pouce. */
.tstm__btn {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 0;
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--faint);
  cursor: pointer;
  touch-action: manipulation;
  transition: background-color .2s ease, color .2s ease;
}
.tstm__btn::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);   /* cible tactile confortable, invisible */
}
.tstm__btn svg { width: 18px; height: 18px; display: block; }
.tstm__btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
@media (hover: hover) {
  .tstm__btn:hover { background: rgba(16, 16, 18, .06); color: var(--ink); }
}

/* --- Comparateurs : la piste qui defile --------------------------------
   Ils etaient 2, cote a cote, et la mise en page n'acceptait pas un 3e. La
   piste prend autant de comparateurs qu'on lui en donne : 1 par ecran en pile,
   2 en grand ecran, et l'accrochage (scroll-snap) fait qu'on ne s'arrete
   jamais entre deux. Le defilement natif fait le travail : pas de position
   calculee en JS, donc rien a resynchroniser au redimensionnement. */
/* EN PILE, LA PISTE DEBORDE DANS LES MARGES DE LA PAGE.
   1er essai : des bandes laterales prises SUR la largeur utile. La photo
   tombait de 335 a 283 px, alors que rien ne le demandait : le comparateur est
   le plus gros argument visuel de la page, il ne doit pas payer l'apercu des
   voisins. La piste sort donc de la gouttiere (marge negative de --pad) et
   reprend ses bandes dedans : la photo retrouve la pleine largeur utile, et ce
   sont les marges de la page, jusque-la vides, qui montrent les voisins. */
.ba-car {
  /* Declares ICI, sur l'ancetre commun : la piste ET les voiles en ont besoin,
     et une variable ne descend que vers le bas.
     --recul : l'echelle des comparateurs de cote. C'est celle de l'eventail
     d'avis (0,92). Elle sert 2 fois, et il ne faut jamais l'ecrire ailleurs :
     la carte reduite laisse (1 - 0,92) / 2 = 4% de vide en haut et en bas de la
     piste, et c'est exactement ce que les voiles doivent s'interdire de
     couvrir, sous peine d'y flouter du noir et d'y laisser un halo pale. */
  --peek: var(--pad);
  --recul: .92;
  margin: 0 calc(-1 * var(--pad)) var(--s7);
}
.ba-track {
  /* --peek (declare sur .ba-car) : la bande laissee de chaque cote pour qu'on
     APERCOIVE la page voisine. C'est du padding sur le conteneur de
     defilement, donc les comparateurs des cotes ne sont pas coupes par le
     bord : ils depassent dedans. scroll-padding aligne l'accrochage sur la
     meme bande, sinon la page s'arreterait collee au bord au lieu de se poser
     dans la fenetre. */
  display: grid;
  /* UNE PAGE = UNE COLONNE, ET UNE COLONNE TIENT 2 COMPARATEURS.
     `grid-auto-flow: column` remplit d'abord les rangees de la colonne courante
     avant de passer a la suivante : avec 2 rangees, les comparateurs se posent
     donc 2 par 2, empiles, exactement comme ils l'etaient avant le carrousel.
     Les fleches font glisser la colonne entiere, donc les 2 d'un coup.
     En grand ecran, la meme piste repasse a 1 rangee et 2 demi-colonnes : les
     2 se regardent au lieu de s'empiler, sans une ligne de balisage en plus. */
  grid-auto-flow: column;
  grid-template-rows: auto auto;
  grid-auto-columns: 100%;          /* % du BLOC DE CONTENU, donc hors --peek */
  gap: var(--s7) var(--s5);         /* 32px entre les 2 empiles, comme avant */
  padding-inline: var(--peek);
  scroll-padding-inline: var(--peek);
  overflow-x: auto;
  overscroll-behavior-x: contain;   /* ne remonte pas au navigateur en fin de piste */
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;            /* la barre est remplacee par les fleches */
  -ms-overflow-style: none;
}
.ba-track::-webkit-scrollbar { display: none; }
.ba-track .ba {
  margin: 0;
  scroll-snap-align: start;
  /* Meme transition que .tcard, a la valeur pres : quand une carte quitte ou
     rejoint la page courante, elle change d'echelle, de flou et d'opacite en
     0,5s, comme une carte d'avis qui quitte le centre. Les 2 carrousels de la
     page bougent donc au meme rythme. */
  transition: transform .5s ease, opacity .5s ease, filter .5s ease;
}
/* LES COTES, AU TRAITEMENT EXACT DE L'EVENTAIL D'AVIS.
   La page a deja un carrousel qui met ses voisines de cote, et il ne se sert ni
   de voile ni de fondu : il REDUIT et FLOUTE LA CARTE ELLE-MEME. Les 3 valeurs
   sont recopiees de .tcard (echelle 0,92 posee par le script, opacite .85,
   blur 3,5px + saturate .92) : les 2 carrousels de la page reculent leurs
   voisines de la meme facon.

   POURQUOI PAS LE VOILE QU'IL Y AVAIT ICI. Deux couches de backdrop-filter
   posees sur les bandes laterales floutaient bien, mais un backdrop-filter
   echantillonne AUTOUR de lui : au bord haut d'une carte reduite, il melangeait
   le noir du fond et le blanc de la photo et laissait un rectangle pale
   au-dessus d'elle. Un filter porte par la carte, lui, est decoupe a la carte :
   il ne peut rien deborder. C'est aussi pour ca que l'echelle redevient
   possible, alors qu'elle avait du sauter quand le voile etait la. */
.ba-track .ba.is-side {
  opacity: .85;
  filter: blur(3.5px) saturate(.92);
  transform: scale(var(--recul));
}

/* ---- LE CADRE DES VOILES ----
   La piste, et rien d'autre. Poses sur .ba-car, qui porte aussi les fleches,
   les voiles debordaient de 56px par le bas et floutaient le vide autour des
   boutons. */
.ba-car__vue { position: relative; }

/* ---- LES VOILES : LE FLOU PROGRESSIF ----
   Le filtre porte par la carte (ci-dessus) la fait reculer, mais il est
   UNIFORME : il s'arrete net au bord du comparateur, et l'arete reste. Les
   voiles ajoutent par-dessus un flou qui S'AGGRAVE vers l'exterieur : 2 couches
   de backdrop-filter sur la bande laterale, chacune avec son propre degrade de
   masque, une douce sur toute la bande, une forte sur la moitie exterieure.
   L'image reste une image jusqu'au bout au lieu de disparaitre dans du noir.

   LE RETRAIT VERTICAL DE 4% N'EST PAS UN REGLAGE : c'est (1 - --recul) / 2,
   soit exactement le vide que la mise a l'echelle laisse en haut et en bas de
   la piste. Sans lui, le voile couvre ces 2 bandes, et comme un backdrop-filter
   echantillonne AUTOUR de lui, il y melange le noir du fond et le blanc de la
   photo : ca se voit comme un rectangle pale pose au-dessus de la carte
   apercue. Si --recul change, ce retrait suit tout seul.
   Les voiles ne captent aucun clic : le curseur d'un comparateur qui depasse
   dessous reste attrapable. */
.ba-car__voile {
  position: absolute;
  top: calc((1 - var(--recul)) / 2 * 100%);
  bottom: calc((1 - var(--recul)) / 2 * 100%);
  z-index: 2;
  width: var(--peek);
  pointer-events: none;
}
.ba-car__voile::before,
.ba-car__voile::after {
  content: "";
  position: absolute;
  inset: 0;
}
.ba-car__voile::before {
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
}
.ba-car__voile::after {
  -webkit-backdrop-filter: blur(18px);
          backdrop-filter: blur(18px);
}
.ba-car__voile--g { left: 0; }
.ba-car__voile--d { right: 0; }
/* Le degrade part du BORD EXTERIEUR de chaque bande : opaque dehors, nul au
   contact de la page courante, qui doit rester parfaitement nette. */
.ba-car__voile--g::before {
  -webkit-mask-image: linear-gradient(90deg, #000, transparent);
          mask-image: linear-gradient(90deg, #000, transparent);
}
.ba-car__voile--g::after {
  -webkit-mask-image: linear-gradient(90deg, #000, transparent 55%);
          mask-image: linear-gradient(90deg, #000, transparent 55%);
}
.ba-car__voile--d::before {
  -webkit-mask-image: linear-gradient(90deg, transparent, #000);
          mask-image: linear-gradient(90deg, transparent, #000);
}
.ba-car__voile--d::after {
  -webkit-mask-image: linear-gradient(90deg, transparent 45%, #000);
          mask-image: linear-gradient(90deg, transparent 45%, #000);
}

/* ---- LES FLECHES ----
   Meme gabarit que celles des avis (.tstm__btn), transposees en sombre : ce
   bloc est sur la plaque noire, pas sur la partie claire. Elles restent
   masquees tant qu'il n'y a rien a faire defiler (attribut hidden pose par le
   script).
   >>> CES 2 REGLES AVAIENT ETE SUPPRIMEES PAR ERREUR en meme temps que les
       voiles : les boutons retombaient au gabarit par defaut du navigateur,
       minuscules et colles a gauche. Elles vivent volontairement ici, au
       contact des voiles, pour qu'on voie qu'elles n'ont rien a voir. */
.ba-car__nav {
  display: flex;
  justify-content: center;
  gap: var(--s3);
  margin: var(--s5) 0 0;
}
.ba-car__nav[hidden] { display: none; }
.ba-car__btn {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 0;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, .06);
  color: var(--dark-text);
  cursor: pointer;
  touch-action: manipulation;
  transition: background-color .2s ease, color .2s ease, opacity .2s ease;
}
.ba-car__btn::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);   /* cible tactile confortable, invisible */
}
.ba-car__btn svg { width: 18px; height: 18px; display: block; }
.ba-car__btn[disabled] { opacity: .3; cursor: default; }
.ba-car__btn:focus-visible { outline: 2px solid #4c8dff; outline-offset: 3px; }
@media (hover: hover) {
  .ba-car__btn:not([disabled]):hover { background: rgba(255, 255, 255, .12); color: #fff; }
}

/* --- Comparateur avant / après (interactif) --- */
.ba {
  position: relative;
  aspect-ratio: 0.92;
  border-radius: 14px;             /* conservé comme avant */
  overflow: hidden;
  background: var(--dark-plc);
  margin: 0 0 var(--s7);          /* 32px, calé grille (était 30) */
  border: 0;                      /* bordure claire retirée : cadre brut */
  touch-action: pan-y;            /* scroll vertical OK, drag horizontal capté */
  cursor: ew-resize;
  -webkit-user-select: none;
  user-select: none;
}
.ba__pane {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
}
/* Une url() qui pointe vers un fichier absent part en 404 À CHAQUE chargement de
   la page, et tôt, puisque c'est la feuille de style qui la déclenche : quatre
   allers-retours réseau pour rien, mesurés entre 600 et 920 ms. Les lignes du 2e
   comparateur restent donc EN COMMENTAIRE tant que ses photos ne sont pas dans
   assets/ : ce que le visiteur voit d'ici là est le même aplat sombre.
   >>> QUAND VOUS DÉPOSEREZ LES PHOTOS du 2e comparateur dans assets/ : enlevez
       les marques de commentaire des deux dernières lignes de ce bloc.
   Le background-color reste sous l'image : c'est ce qui est peint le temps qu'elle
   arrive, plutôt qu'un trou blanc. Format .webp sans repli, comme les logos de la
   bande d'autorité : la page en dépend déjà sans condition. */
.ba__pane--after  { z-index: 0; background-color: #34343a; background-image: url('assets/apres.webp'); }
.ba__pane--before { z-index: 1; background-color: #26262b; background-image: url('assets/avant.webp'); clip-path: inset(0 50% 0 0); }
/* 2e comparateur : ses propres images. Cette reprise est OBLIGATOIRE, même
   maintenant qu'elles existent : sans elle il hériterait des photos du 1er
   (mêmes classes de panneau) et les deux comparateurs montreraient le même
   homme. Même format que le 1er couple, 896 × 1100. */
.ba--2 .ba__pane--after  { background-image: url('assets/apres2.webp'); }
.ba--2 .ba__pane--before { background-image: url('assets/avant2.webp'); }
/* COMPARATEURS 3 A 6 : LES 4 DERNIERS COUPLES, COMPLETS DEPUIS LEURS
   PROJECTIONS. Chacun reprend ses 2 photos, et cette reprise est obligatoire
   des deux côtés : sans elle la figure hérite des photos du 1er comparateur, et
   la page montre le même homme à cinq places. Même format que les 2 premiers
   couples, 896 × 1100.
   LES PROJECTIONS SONT CADRÉES PAR CALQUE DE LEUR AVANT
   (atelier/cadrer-comparateur.py, 5e argument : la source de l'avant). Le
   générateur rend les 2 photos d'une paire dans le même cadre ; on retrouve
   donc le cadrage qui a produit l'avant publié, et on l'applique tel quel à sa
   projection. Les yeux, le nez et la ligne des épaules se raccordent au milieu
   sans qu'aucun visage n'ait été mesuré.
   LE MÊME CADRE NE DONNE PAS LA MÊME POSE, et la paire 5 l'a montré : le
   générateur y avait posé la tête de la projection 9 px plus bas que celle de
   son avant, alors que les épaules et le débardeur, eux, ne bougeaient que de
   3. Le calque recopiait donc fidèlement un décalage bien réel, et la bouche se
   coupait en 2 au milieu du cadre. Le script mesure maintenant ce qui reste sur
   les 2 colonnes qui bordent la couture, les seules que le visiteur voit se
   toucher, et remonte la projection d'autant : 11 px ici, 0 à 2 px sur les 3
   autres paires, qui sortent donc inchangées.
   C'est le 2e essai : le 1er cadrait en détectant les pupilles, et les montures
   de lunettes trompaient le détecteur (jusqu'à 100 px d'erreur sur la paire 5).
   Ces projections-là avaient dû être retirées. Ne pas y revenir. */
.ba--3 .ba__pane--before { background-image: url('assets/avant3.webp'); }
.ba--3 .ba__pane--after  { background-image: url('assets/apres3.webp'); }
.ba--4 .ba__pane--before { background-image: url('assets/avant4.webp'); }
.ba--4 .ba__pane--after  { background-image: url('assets/apres4.webp'); }
.ba--5 .ba__pane--before { background-image: url('assets/avant5.webp'); }
.ba--5 .ba__pane--after  { background-image: url('assets/apres5.webp'); }
.ba--6 .ba__pane--before { background-image: url('assets/avant6.webp'); }
.ba--6 .ba__pane--after  { background-image: url('assets/apres6.webp'); }

/* CE QUE FAIT `ba--avant-seul`, EN 3 POINTS, ET POURQUOI CHACUN EST NECESSAIRE.
   PLUS AUCUNE FIGURE NE LE PORTE depuis que les 4 projections sont arrivées :
   ce bloc ne s'applique à rien aujourd'hui. Il reste écrit pour la photo
   suivante, qui arrivera seule elle aussi, et parce qu'il dit ce qu'il faut
   défaire pour ouvrir un couple.
   1. LE PANNEAU « APRES » EST VIDE DE FORCE. Sans cette ligne il n'est pas
      vide : il hérite de `.ba__pane--after`, commun à tous, et affiche donc la
      projection du 1er comparateur. Le curseur révélerait un AUTRE HOMME que
      celui de la photo, ce qui est pire que la plaque sombre. C'est le même
      piège que celui qui a fait naître `ba--vide`.
   2. LA PHOTO OCCUPE TOUTE LA FIGURE. `.ba__pane--before` est découpé à
      `inset(0 50% 0 0)` : c'est ce qui laisse voir l'après dans la moitié
      droite. Sans projection à révéler, ce découpage ne montrerait que la
      moitié gauche de l'homme et la moitié droite en aplat sombre — une image
      qui a l'air cassée. `clip-path: none` rend la photo entière.
   3. PLUS DE CURSEUR NI DE MAIN QUI TIRE. Le pointeur redevient celui du texte :
      rien ici ne se manipule. Le .ba__divider, lui, est absent du HTML, ce qui
      débranche le script (voir le commentaire dans index.html). */
.ba--avant-seul .ba__pane--after  { background-image: none; }
.ba--avant-seul .ba__pane--before { clip-path: none; }
.ba--avant-seul { cursor: default; }
/* EMPLACEMENTS EN ATTENTE : AUCUNE IMAGE.
   PLUS AUCUNE FIGURE NE PORTE `ba--vide` depuis que la 6e photo est arrivee :
   ce bloc ne s'applique donc a rien aujourd'hui. Il reste ecrit pour la 7e
   place, si une devait rouvrir, et parce qu'il documente le piege ci-dessous.
   L'image est posee sur .ba__pane, commun a tous les comparateurs : sans cette
   coupure, un emplacement sans couple d'images a lui herite de celles du 1er,
   et la page affiche le meme homme a chaque place libre. Reste l'aplat sombre
   a 2 tons du background-color, celui qui s'affiche deja le temps qu'une photo
   arrive : ca se lit comme une place reservee, pas comme une image cassee.
   Le curseur n'a rien a couper non plus, on le retire. */
.ba--vide .ba__pane { background-image: none !important; }
.ba--vide { cursor: default; }
.ba--vide .ba__divider { display: none; }
/* ET RAMENES PRES DU FOND DE LA SECTION.
   Les aplats de .ba__pane (#34343a / #26262b) sont regles pour tenir SOUS une
   photo, le temps qu'elle arrive : sur le noir de la plaque (#0f0f11) ils
   ressortent comme deux rectangles gris, et c'est cette arete-la qu'on voit
   avant tout le reste. Ici il n'y a pas de photo a venir dans la seconde : ils
   descendent donc a quelques points du fond. Les 2 tons restent differents,
   assez pour qu'on lise une place de comparateur, plus assez pour qu'on lise
   une boite. */
.ba--vide .ba__pane--after  { background-color: #1a1b1e; }
.ba--vide .ba__pane--before { background-color: #151619; }

/* --- CHARGEMENT DIFFÉRÉ DES QUATRE PHOTOS -------------------------------
   `loading="lazy"` n'existe QUE pour <img>. Une image de fond CSS est
   téléchargée dès que son élément est rendu, et ces panneaux le sont dès la
   première frame : les quatre photos (128 Ko) partaient donc en même temps que
   la photo du hero, pour un comparateur situé à plus de 4 000 px du haut de la
   page. Elles ne s'affichaient pas plus tôt pour autant : elles prenaient juste
   de la bande passante à l'image qui, elle, décide du LCP.
   La règle ci-dessous les retire tant que le comparateur n'approche pas ; le
   script les rallume 400 px avant qu'il entre à l'écran (même marge et même
   procédé que les lecteurs audio des témoignages), donc bien avant qu'on puisse
   les voir : à l'œil, rien ne change.
   Le gabarit `.js …:not(.is-armed)` compte : les images restent déclarées comme
   avant, et c'est leur RETRAIT qui est conditionné au script. Sans JavaScript,
   la classe `js` est absente de <html>, la règle ne s'applique pas, et les
   quatre photos se chargent d'emblée comme avant. */
.js .ba:not(.is-armed) .ba__pane { background-image: none; }
/* Séparateur + poignée (position pilotée par le JS) */
.ba__divider {
  position: absolute;
  z-index: 2;
  top: 0; bottom: 0; left: 50%;
  width: 1px;                                 /* barre BLANCHE retirée */
  transform: translateX(-50%);
  background: rgba(228, 232, 240, .20);       /* filet « verre gris » translucide, très discret */
  pointer-events: none;
}
/* La poignée est montée dans le ciel de la photo. Au milieu du cadre elle se
   posait sur le nez et la bouche ; descendue sur le buste elle ne gênait plus
   mais devait rester discrète pour ne pas peser sur l'image. En haut, elle est
   sur le fond de studio vide : elle ne couvre RIEN, donc elle peut redevenir
   franchement lisible, ce que doit être le seul signe qui dit « ça se tire de
   gauche à droite ».
   7 % de la hauteur : le cadre montre la bande 63 → 1037 des images, et la
   chevelure la plus haute des quatre photos (celle de la projection n° 2)
   commence à 12,6 %. À 30 px, la pastille passe au-dessus des cheveux jusque
   dans la bande téléphone, où le cadre est le plus petit : il y reste 7 px de
   marge sous elle et 12 px au-dessus. C'est ce cas le plus serré qui fixe les
   deux valeurs ; les agrandir rognerait la marge basse.
   À cette hauteur elle est TOUJOURS sur le fond clair, quelle que soit la
   position du curseur : le disque est donc peint sombre et les flèches
   blanches se lisent dessus (7,3:1). Le liseré blanc reste, lui, pour le cas
   où une photo au fond sombre viendrait la remplacer.
   Rien ne change côté usage : le glissement est capturé par TOUTE la figure
   (voir app.js), la poignée est un repère et une cible clavier, pas la seule
   zone attrapable. */
.ba__handle {
  position: absolute;
  top: 7%; left: 50%;
  width: 30px; height: 30px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: rgba(20, 20, 24, .72);          /* verre gris translucide (esprit du sélecteur d'onglets) */
  -webkit-backdrop-filter: blur(10px) saturate(1.15);
  backdrop-filter: blur(10px) saturate(1.15);
  border: 1px solid rgba(255, 255, 255, .5);
  box-shadow: 0 3px 12px rgba(0, 0, 0, .22);
  transition: opacity .22s ease, transform .22s cubic-bezier(.33, 1, .68, 1);
  pointer-events: auto;
  cursor: ew-resize;
}
@media (hover: hover) {
  .ba:hover .ba__handle { transform: translate(-50%, -50%) scale(1.1); }
}
.ba__handle:focus-visible,
.ba__handle:active { transform: translate(-50%, -50%) scale(1.1); }
.ba__handle:focus-visible { outline: 2px solid #4c8dff; outline-offset: 3px; }
.ba__handle::before, .ba__handle::after {
  content: ""; position: absolute; top: 50%;
  width: 0; height: 0;
  border-top: 3px solid transparent;
  border-bottom: 3px solid transparent;
}
.ba__handle::before { left: 7px;  transform: translateY(-50%); border-right: 5px solid rgba(255, 255, 255, .95); }
.ba__handle::after  { right: 7px; transform: translateY(-50%); border-left: 5px solid rgba(255, 255, 255, .95); }
/* Puces AVANT / APRÈS */
.ba__tag {
  position: absolute;
  z-index: 3;
  bottom: 12px;
  font-size: 10px;
  font-weight: 500;               /* fin & discret (était 700 + pilule sombre) */
  letter-spacing: .14em;
  text-transform: uppercase;
  /* Le placeholder sombre a laissé place à de vraies photos, prises sur fond de
     studio clair : du blanc à 72 % y devenait illisible. Le libellé reste blanc
     et fin (la pilule sombre avait été écartée, on n'y revient pas), mais il porte
     désormais son propre relief : une ombre courte pour détacher le dessin des
     lettres, un halo large pour tenir sur les aplats clairs. Sous les deux
     étiquettes la photo va du noir du débardeur (luminance 6) au fond de studio
     (248) : aucune couleur de texte seule ne pouvait couvrir cet écart. */
  color: rgba(255, 255, 255, .92);
  text-shadow: 0 1px 2px rgba(0, 0, 0, .5), 0 0 12px rgba(0, 0, 0, .4);
  pointer-events: none;
}
.ba__tag--before { left: 12px; }
.ba__tag--after  { right: 12px; }

/* --- Bénéfices : 01 / 02 / 03 (bloc éditorial) --- */
.benefits { list-style: none; margin: 0; padding: 0; }
.benefit {
  display: grid;
  grid-template-columns: 54px 1fr;
  align-items: center;
  gap: 16px;
  padding: 20px 2px;
  border-top: 1px solid rgba(255, 255, 255, .10);
}
.benefit:last-child { border-bottom: 1px solid rgba(255, 255, 255, .10); }
/* Chiffres « filigrane » : gros, pleins, très estompés (plus de contour creux) */
.benefit__num {
  font-size: 46px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.03em;
  color: rgba(255, 255, 255, .14);
  font-variant-numeric: tabular-nums;
}
.benefit__text {
  font-size: var(--t-body);
  line-height: 1.35;
  font-weight: 400;
  color: #e9e9ec;
}

/* ===================== PREUVE : transition sombre -> clair + témoignage ===================== */
/* La page « repasse en blanc » : dégradé du noir de la section sombre vers le blanc.
   Le haut de la section sert de zone de fondu (~160px) -> le contenu tombe sur du blanc. */
.proof {
  position: relative;
  z-index: 3;                        /* passe au-dessus de la plaque claire figée */
  padding: var(--s9) var(--pad) var(--s11);   /* 48/64, calé grille (était 52/72) */
  background: #f2f2f3;               /* gris clair solide, bord haut NET (pas de dégradé) */
  border-top: 1px solid rgba(0, 0, 0, .06);   /* fin filet au raccord sombre -> gris */
}

/* Témoignage (panneau de verre gris) : EXACTEMENT le même matériau que la
   pilule flottante / le panneau du menu (rgba(20,20,24,.58) + blur 26 sat 1.5).
   Posé sur le gris clair, ce verre translucide rend un gris moyen. Format
   horizontal : encadré photo à gauche, guillemet + texte + auteur à droite.
   Aucune bordure, aucun dégradé. */
.quote {
  position: relative;
  --r-verre: 16px;                     /* rayon de la plaque : la découpe des nappes le reprend */
  overflow: hidden;                    /* clippe les halos aux coins arrondis */
  display: flex;
  align-items: stretch;                /* la photo remplit toute la hauteur -> pas de gris mort */
  gap: 16px;
  max-width: 402px;
  /* 64px au-dessus : la citation n'ouvre plus la plaque claire, elle est posée
     juste avant les tarifs : 250 000 $ au contact de 390 €. Sans cette
     marge elle collerait au bloc d'adéquation qui la précède désormais. */
  margin: var(--s11) auto 0;
  padding: 14px;
  border-radius: var(--r-verre);       /* même rayon que la pilule */
  text-align: left;
  /* Fond : voir « VERRE MONOCHROME (fond partagé) » dans la section TÉMOIGNAGES. */
}
.quote__photo, .quote__body { position: relative; z-index: 1; }
/* Encadré photo (médecin / scientifique) : sans bordure, étiré sur la hauteur. */
.quote__photo {
  flex: 0 0 auto;
  align-self: stretch;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 84px;
  min-height: 84px;
  border-radius: 12px;
  overflow: hidden;
  background: rgba(255, 255, 255, .10);
  color: rgba(255, 255, 255, .5);      /* icône silhouette */
}
.quote__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.quote__photo svg { width: 32px; height: 32px; }
/* Colonne texte : centrée verticalement en regard de la photo. */
.quote__body {
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
/* Citation : Satoshi, italique, poids REGULAR (400) : fine, pas de gras. */
.quote__text {
  margin: 0 0 9px;
  font-size: 13.5px;
  line-height: 1.45;
  font-style: italic;
  font-weight: 400;
  letter-spacing: 0;
  color: #ededf1;
}
/* Guillemets serif inline (même matière que l'ancien signe) -> ça « fait » citation. */
.quote__text::before { content: "\201C"; }
.quote__text::after  { content: "\201D"; }
.quote__text::before,
.quote__text::after {
  font-family: Georgia, "Times New Roman", serif;
  font-style: normal;
  font-weight: 700;
  font-size: 1.15em;
  line-height: 0;
  color: rgba(255, 255, 255, .5);
}
.quote__text::before { margin-right: 1px; }
.quote__text::after  { margin-left: 1px; }
.quote__cite { display: block; }
.quote__cite strong { display: block; color: #f4f4f6; font-weight: 700; font-size: 14px; letter-spacing: -0.01em; line-height: 1.2; }
.quote__role { display: block; margin-top: 2px; font-size: 12.5px; line-height: 1.4; font-weight: 500; color: rgba(255, 255, 255, .6); }

/* Révélation au scroll : activée seulement si JS (sinon contenu visible par défaut).

   ELLE MONTE PAR `translate`, PAS PAR `transform`, et c'est tout l'enjeu.
   Un des éléments révélés est un BOUTON (le « Estimer mon potentiel » qui suit
   les garanties), et un bouton a déjà un transform à lui : l'agrandissement au
   survol. Or `transform` ne se compose pas : deux règles qui l'écrivent ne
   s'additionnent pas, la plus spécifique efface l'autre. `.js .reveal.is-visible`
   (3 classes) écrasait donc `.btn:hover` (2) et la BOÎTE du bouton restait figée
   au survol, pendant que son libellé, lui, appliquait bien son contre-scale
   prévu pour compenser l'agrandissement : résultat, le texte RÉTRÉCISSAIT au
   survol au lieu que le bouton grandisse.
   `translate` est une propriété distincte, appliquée avant `transform` : les
   deux gestes cohabitent sans qu'aucune règle n'ait à gagner contre l'autre. */
.js .reveal {
  opacity: 0;
  translate: 0 24px;
  transition: opacity .7s ease, translate .7s ease;
}
.js .reveal.is-visible { opacity: 1; translate: none; }
/* La ligne ci-dessus réécrit le raccourci `transition` du bouton : sans ce
   rappel, son agrandissement au survol n'aurait plus aucune durée et sauterait. */
.js .btn.reveal { transition: opacity .7s ease, translate .7s ease, transform .42s var(--btn-ease); }

/* ===================== GARANTIES ===================== */
/* Renversement du risque, au gabarit exact des autres blocs de la partie claire :
   œilleton, titre, sous-titre, puis une carte blanche (rayon 16, ombre douce).
   La première version posait ici une plaque noire pleine : dans cette section, le
   sombre n'apparaît QUE par petites touches (citation de Daniel, plaque des places)
   et jamais sur un bloc entier : le contraste sortait du système, et le rayon 22
   employé alors est celui de la carte-page, pas des cartes de contenu. */
.grt {
  margin: var(--s11) 0 0;           /* 64px, comme les autres blocs de la section */
  text-align: center;
}
.grt__eyebrow {
  margin: 0 0 var(--s3);
  font-size: 11px;
  line-height: 1;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--faint);
}
.grt__title {
  margin: 0 0 var(--s4);
  font-size: var(--t-h2);
  line-height: 1.06;
  font-weight: 500;
  letter-spacing: -0.03em;
  color: var(--ink);
  text-wrap: balance;
}
.grt__sub {
  margin: 0 auto var(--s6);
  max-width: 34ch;
  font-size: var(--t-body);
  line-height: 1.35;
  color: var(--muted);
  text-wrap: balance;
}

/* Deux cartes au gabarit EXACT de .opt : même padding, même rayon, même ombre.
   La version précédente inventait un sceau rond pour signaler les garanties,
   une forme que le site n'emploie nulle part ailleurs, et qui sonnait donc
   rapportée. Le signal est repris là où il existe déjà : liseré noir + pastille
   débordante, la façon dont cette page dit « regardez ici » (.opt--do pour
   l'issue à choisir, .plan--reco pour le format recommandé). Rien de neuf, et
   les garanties se voient de loin. */
.grt__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 24px;
  text-align: left;
}
.grt__item {
  position: relative;
  margin-top: 12px;                 /* laisse respirer la pastille débordante */
  padding: 18px 20px;
  border-radius: 16px;              /* = .opt, .objection, .fit__card, .plan */
  background: #fff;
  border: 1px solid var(--black);
  box-shadow: var(--ombre-hl);
}
/* Le NOM de la garantie, en pleine encre : c'est le seul mot à lire pour savoir
   ce qu'on garantit. « Satisfait ou remboursé » se comprend sans la suite. */
.grt__name {
  margin: 0 0 6px;
  font-size: 17px;
  line-height: 1.2;
  font-weight: 500;
  letter-spacing: -0.025em;
  color: var(--ink);
}
/* La mécanique, en UNE phrase, au gabarit de .opt__text. */
.grt__text {
  margin: 0;
  font-size: 15px;
  line-height: 1.45;
  color: var(--muted);
}

/* Ligne de réassurance : posée à même le fond, comme la note du décompte de valeur. */
.grt__legal {
  margin: 14px 0 0;
  font-size: 11px;
  line-height: 1.4;
  font-weight: 500;
  letter-spacing: .01em;
  color: var(--faint);
}
.grt__sep { margin: 0 8px; color: #c6cad0; }

/* CTA de milieu de page : même bouton que le hero, juste détaché de son bloc. */
.cta-band { margin: var(--s6) 0 0; }

/* ===================== FAQ ===================== */
/* Accordéon natif <details> : filets pleine largeur, aucune carte : la FAQ est
   une liste, pas une galerie. Le signe « + » bascule en « × » par rotation. */
.faq {
  margin: var(--s11) 0 0;
  text-align: center;
}
.faq__eyebrow {
  margin: 0 0 var(--s3);
  font-size: 11px;
  line-height: 1;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--faint);
}
.faq__title {
  margin: 0 0 var(--s6);
  font-size: var(--t-h2);
  line-height: 1.06;
  font-weight: 500;
  letter-spacing: -0.03em;
  color: var(--ink);
  text-wrap: balance;
}

.faq__list { text-align: left; border-top: 1px solid var(--line); }
.faq__item { border-bottom: 1px solid var(--line); }

.faq__q {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px 0;
  font-size: 15px;
  line-height: 1.3;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--ink);
  cursor: pointer;
  list-style: none;                 /* retire le triangle natif (Firefox) */
}
.faq__q::-webkit-details-marker { display: none; }   /* … et sur WebKit */
.faq__q > span { flex: 1 1 auto; }
.faq__q:hover { color: #000; }

.faq__sign {
  flex: none;
  width: 17px;
  height: 17px;
  color: var(--faint);
  transition: transform .3s cubic-bezier(.22, 1, .36, 1), color .2s ease;
}
.faq__item[open] .faq__sign { transform: rotate(45deg); color: var(--ink); }

/* Le panneau est animé en hauteur par le JS (voir index.html) : il ne porte donc
   aucune transition CSS, overflow caché pour que le texte se dévoile par le bas. */
.faq__a { overflow: hidden; }
.faq__a p {
  margin: 0;
  padding: 0 34px 18px 0;           /* dégage la colonne du signe « + » */
  font-size: 15px;
  line-height: 1.45;
  color: var(--muted);
}

/* ===================== TROIS OPTIONS ===================== */
/* Le dernier arbitrage. Il reprend mot pour mot la grammaire déjà posée par
   « Ce n'est pas pour tout le monde » et par les formats : les deux issues qu'on
   ne veut pas reculent d'un plan (gris, sans ombre, texte en retrait), la bonne
   est une carte blanche cerclée de noir avec sa pastille débordante : exactement
   le traitement du format recommandé. Aucune matière nouvelle n'est introduite. */
.opts {
  margin: var(--s11) 0 0;
  text-align: center;
}
.opts__eyebrow {
  margin: 0 0 var(--s3);
  font-size: 11px;
  line-height: 1;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--faint);
}
.opts__title {
  margin: 0 0 var(--s6);
  font-size: var(--t-h2);
  line-height: 1.06;
  font-weight: 500;
  letter-spacing: -0.03em;
  color: var(--ink);
  text-wrap: balance;
}

.opt {
  position: relative;
  padding: 18px 20px;
  border-radius: 16px;              /* = .objection, .fit__card, .plan */
  background: #fff;
  border: 1px solid transparent;
  box-shadow: 0 1px 2px rgba(16, 16, 18, .04);
  text-align: left;
}
.opt + .opt { margin-top: 12px; }
/* Les deux issues subies : même retrait que la carte « ce n'est pas pour vous ». */
.opt--out {
  background: #e9e9ea;
  box-shadow: none;
}
.opt__label {
  margin: 0 0 8px;
  font-size: 11px;
  line-height: 1;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--faint);
}
.opt__text {
  margin: 0;
  font-size: 15px;
  line-height: 1.45;
  color: var(--muted);
}
.opt--out .opt__text { color: var(--faint); }

/* L'issue choisie : liseré noir, pastille et ombre, comme le format recommandé. */
.opt--do {
  margin-top: 20px;                 /* laisse respirer la pastille débordante */
  border-color: var(--black);
  box-shadow: var(--ombre-hl);
}
.opt--do .opt__text strong { font-weight: 700; color: var(--ink); }

/* ===================== PIED DE PAGE =====================
   Grammaire empruntée aux références : libellés courts suivis d'un « / »,
   clause de non-responsabilité numérotée, filigrane de marque en fond.
   Transposée en Satoshi monochrome : aucune nouvelle couleur, aucune nouvelle
   graisse. Le bloc déborde des gouttières de .proof pour toucher les bords de
   la carte, et reprend le coin bas arrondi sur grand écran. */
.ftr {
  /* --- Palette du pied de page ---
     Le pied bascule sur un aplat jaune beurre à encre noire. Toutes les valeurs
     vivent ici : changer --f-bg suffit à changer la teinte du bloc entier, et
     rien d'autre dans la feuille ne porte de couleur en dur. L'encre est un noir
     légèrement chaud (14 14 10) : un noir neutre sur du jaune tire au violet. */
  --f-bg:    var(--beurre);
  --f-ink:   #14140e;
  --f-body:  rgba(20, 20, 14, .74);
  --f-lab:   rgba(20, 20, 14, .70);   /* .52 donnait 3,46:1 sur le jaune, sous AA ;
                                         remonté de .62 à .70 quand le fond a reçu
                                         ses taches : sur le beurre le plus dense,
                                         .62 retombait à 4,17:1. À .70 : 5,2:1. */
  --f-slash: rgba(20, 20, 14, .24);
  --f-hair:  rgba(20, 20, 14, .16);
  --f-todo:  rgba(20, 20, 14, .62);

  /* Force de la matière du fond (voir .ftr::before plus bas). */
  --f-matiere: 1;

  /* Le filigrane (voir .ftr::after plus bas) : sa force, et son dessin.
     Le dessin est un FICHIER (assets/etoile.svg) et non un data-URI collé ici :
     la CSP de la page tient img-src à 'self', et un masque CSS passe par
     img-src : en data-URI le masque échoue à charger, un masque qui échoue
     masque TOUT, et le filigrane disparaît sans rien dire. Le fichier reprend
     l'étoile du logo au chiffre près, recadrée sur ses pointes. */
  --f-filigrane: .08;
  --f-etoile: url("assets/etoile.svg");

  margin: var(--s11) calc(var(--pad) * -1) calc(var(--s11) * -1);
  /* Le bas venait du wordmark (sa hauteur, puis sa marge). Sans lui, la barre
     légale tombait à ras du bord, et la bande que .ftr remonte sur ce qui le
     suit (marge basse négative de --s11) la rognait. Ce fond de page lui rend
     la bande mangée, plus l'air qu'avait le mot. */
  padding: var(--s8) var(--pad) calc(var(--s11) + var(--s7));
  background: var(--f-bg);
  color: var(--f-body);
  text-align: left;
  overflow: hidden;                    /* le filigrane ne déborde jamais la carte */
  position: relative;
  isolation: isolate;                  /* ouvre une pile locale -> les décors en
                                          z-index:-1 se glissent entre le fond noir
                                          et le texte, sans toucher au reste du site */
}

/* --- La matière ---
   Le pied n'est plus un aplat : c'est une nappe de jaunes beurre qui se
   chevauchent. Quinze taches donnent les variations de fond : le halo central
   de la référence n'est plus un disque à part, c'est la première d'entre elles.

   Aucune n'a de bord net (chaque tache s'éteint avant 75 %), et toutes sont des
   VOISINES de --beurre (239 226 162), pas d'autres jaunes : l'écart va de
   (250 242 198) à (210 191 106), soit ± un cran de densité. Premier essai plus
   large (crème quasi blanche d'un côté, doré de l'autre) : la teinte s'éloignait
   du beurre. La variation doit se voir sans qu'on puisse nommer une deuxième
   couleur.

   Un seul réglage : --f-matiere, force des taches (0 = aplat d'origine).

   Pas de grain par-dessus : une trame de points a été essayée puis retirée :
   régulière elle se lisait comme du papier millimétré, et même mangée par un
   masque en nuages elle restait un corps étranger sur cette surface. La
   variation vient des taches, et d'elles seules. */
.ftr::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0;
  opacity: var(--f-matiere);
  background-image:
    /* 1. le halo central : il donne toujours un centre au bandeau d'appel */
    radial-gradient(54% 32% at 50% 14%, rgba(210, 191, 106, .48), transparent 72%),
    /* 2-3. les beurres clairs : le jaune s'éclaircit, il ne blanchit pas */
    radial-gradient(46% 26% at  8%  4%, rgba(250, 242, 198, .70), transparent 70%),
    radial-gradient(38% 26% at 78% 46%, rgba(249, 240, 194, .62), transparent 70%),
    /* 4-5. les beurres denses : il s'épaissit, il ne vire pas au doré */
    radial-gradient(40% 30% at 96% 22%, rgba(212, 194, 114, .44), transparent 72%),
    radial-gradient(44% 30% at  4% 62%, rgba(214, 199, 128, .46), transparent 74%),
    /* 6-7. le bas, sous la marque */
    radial-gradient(50% 34% at 44% 88%, rgba(216, 199, 122, .42), transparent 72%),
    radial-gradient(36% 26% at 92% 92%, rgba(250, 241, 196, .58), transparent 70%),
    /* 8-15. taches courtes : c'est ce qui casse la régularité des grandes
       nappes, et donc ce qui fait vraiment la variation. Positions choisies
       sans symétrie : dès qu'une reprend le pas d'une autre, l'œil voit une
       trame et la matière meurt. */
    radial-gradient(22% 16% at 26% 30%, rgba(211, 192, 110, .30), transparent 70%),
    radial-gradient(20% 14% at 62% 68%, rgba(251, 244, 204, .48), transparent 70%),
    radial-gradient(17% 13% at 71% 11%, rgba(210, 190, 106, .26), transparent 72%),
    radial-gradient(14% 19% at 15% 41%, rgba(250, 243, 202, .40), transparent 70%),
    radial-gradient(19% 12% at 37% 57%, rgba(213, 195, 116, .24), transparent 72%),
    radial-gradient(12% 17% at 88% 63%, rgba(215, 198, 122, .26), transparent 70%),
    radial-gradient(24% 13% at 55% 79%, rgba(250, 242, 198, .36), transparent 72%),
    radial-gradient(15% 15% at  9% 88%, rgba(211, 192, 110, .28), transparent 70%);
  pointer-events: none;
}

/* --- Le filigrane ---
   Le pied ne se ferme plus sur le mot « BASARC » écrit en grand : il se ferme
   sur la marque elle-même, l'étoile du logo, posée EN FOND derrière les trois
   blocs. Ce n'est plus une signature qu'on lit, c'est une empreinte qu'on
   remarque à peine, d'où l'opacité tenue très bas : assez pour donner un
   centre à la nappe de beurres, jamais assez pour venir concurrencer « Le
   premier pas ne coûte rien. » qui se tient juste devant.

   Découpé au masque, pas peint en SVG plein : l'encre reste var(--f-ink), donc
   le filigrane suit la palette du pied comme tout le reste du bloc : changer
   --f-ink le change aussi, et personne n'a à retoucher un fichier d'image.

   Deux réglages, tous deux posés sur .ftr : --f-filigrane (la force) et
   --f-etoile (le dessin). */
.ftr::after {
  content: "";
  position: absolute;
  z-index: -1;
  left: 50%;
  top: 50%;
  width: min(80vw, 420px);
  aspect-ratio: 1;
  translate: -50% -50%;
  background: var(--f-ink);
  opacity: var(--f-filigrane);
  -webkit-mask-image: var(--f-etoile);
          mask-image: var(--f-etoile);
  -webkit-mask-repeat: no-repeat;   mask-repeat: no-repeat;
  -webkit-mask-position: center;    mask-position: center;
  -webkit-mask-size: contain;       mask-size: contain;
  pointer-events: none;
}
/* CONTRASTE ÉLEVÉ DE WINDOWS. Le masque n'est pas touché par forced-colors,
   mais `background` l'est : l'étoile se retrouverait peinte en couleur système
   pleine, c'est-à-dire un bloc opaque au milieu du pied. Un filigrane est un
   décor pur : en contraste élevé il n'a rien à dire, on l'éteint. */
@media (forced-colors: active) {
  .ftr::after { display: none; }
}

/* --- Bandeau d'appel ---
   Titre court centré, bouton dessous : la seule zone du pied qui ne soit pas
   alignée à gauche, donc celle où l'œil tombe en premier. */
.ftr__pitch {
  text-align: center;
  padding: var(--s5) 0 var(--s9);
}
.ftr__pitchline {
  margin: 0 0 var(--s5);
  font-size: var(--t-h2);
  line-height: 1.06;
  font-weight: 500;
  letter-spacing: -0.03em;
  color: var(--f-ink);
  text-wrap: balance;
}
.ftr__cta {
  max-width: 340px;
  margin-inline: auto;
  /* Le bouton du site est un noir TRANSLUCIDE (74 %) habillé de deux nappes de
     verre fondues en screen : sur les fonds sombres et clairs de la page il se
     lit comme du noir, mais sur le jaune il laissait remonter la teinte et
     virait au kaki. Ici il redevient un aplat plein, et les nappes s'éteignent,
     comme le bouton de la référence, franc et sans matière. */
  background: var(--f-ink);
}
.ftr__cta::before,
.ftr__cta::after { opacity: 0; }

/* Libellé de rubrique : petites capitales + barre oblique détachée, comme les
   références. La barre est plus pâle que le mot : elle ponctue, elle ne se lit pas. */
.ftr__lab {
  margin: 0 0 12px;
  font-size: 10px;
  line-height: 1;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--f-lab);
}
.ftr__lab span { margin-left: 5px; color: var(--f-slash); }

/* --- Contact --- */
.ftr__head { padding-bottom: var(--s7); }
.ftr__mail {
  display: inline-block;
  font-size: clamp(21px, 5.4vw, 25px);   /* c'était 15px : l'adresse se lisait comme
                                            une mention légale alors que c'est la
                                            seule porte d'entrée directe du pied. */
  line-height: 1.15;
  letter-spacing: -0.022em;              /* même resserrement que les titres */
  color: var(--f-ink);
  text-decoration: underline;
  text-underline-offset: 5px;
  text-decoration-thickness: 1px;
  text-decoration-color: rgba(20, 20, 14, .30);
  transition: text-decoration-color .3s ease;
}
@media (hover: hover) {
  .ftr__mail:hover { text-decoration-color: var(--f-ink); }
}
.ftr__delay { margin: 10px 0 0; font-size: 12px; line-height: 1.4; }

/* --- Réseaux : flèche sortante, comme dans les références ---
   Sur grand écran ce bloc devient la colonne de droite de la référence (là où
   elle empile ses adresses) : une entrée par ligne, sans filet au-dessus. */
.ftr__social { padding: var(--s6) 0; border-top: 1px solid var(--f-hair); }
.ftr__socialrow { display: grid; grid-template-columns: 1fr 1fr; gap: 10px var(--s4); }
.ftr__socialrow a {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 13px;
  line-height: 1.25;
  color: var(--f-body);
  transition: color .22s ease;
}
.ftr__ar {
  width: 11px; height: 11px; flex: none; opacity: .45;
  transition: transform .34s cubic-bezier(.22, 1, .36, 1), opacity .22s ease;
}

/* --- Barre de bas de page ---
   La rangée fine de la référence : copyright d'un côté, liens légaux de l'autre.
   Ces quatre liens sont tout ce qui reste des mentions dans le pied : identité
   de l'éditeur, hébergeur, médiateur, rétractation et clause de
   non-responsabilité vivent en entier sur leurs pages. C'est ce que demande la
   LCEN (art. 6-III) : accessible en permanence, pas recopié sur chaque écran. */
.ftr__bar {
  display: flex;
  flex-direction: column;
  gap: var(--s5);
  padding: var(--s5) 0 var(--s6);
  border-top: 1px solid var(--f-hair);
}
/* Les réserves : un cran SOUS le corps du pied (10,5 px au lieu de 11) et dans
   le gris des libellés. Elles disent tout, mais se lisent comme une texture :
   c'est ce qu'on attend de petits caractères : présents, jamais criards. Le
   bloc entier reste à peu près de la hauteur de l'ancienne clause numérotée,
   pour trois fois plus de contenu. */
.ftr__fine {
  margin: 0;
  font-size: 10.5px;
  line-height: 1.6;
  letter-spacing: .002em;
  color: var(--f-lab);
  text-wrap: pretty;
  hyphens: auto;
}
.ftr__barrow { display: flex; flex-direction: column; gap: 14px; }
.ftr__copy { margin: 0; font-size: 11px; line-height: 1.4; color: var(--f-lab); }
.ftr__legal { display: flex; flex-wrap: wrap; gap: 10px var(--s5); }
.ftr__legal a {
  position: relative;
  font-size: 12px;
  line-height: 1.25;
  color: var(--f-body);
  transition: color .22s ease;
}
/* Le filet se déroule depuis la gauche : le lien se souligne au lieu de
   simplement changer de gris. Un seul geste, la même courbe que la FAQ. */
.ftr__legal a::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -4px;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform .42s cubic-bezier(.22, 1, .36, 1);
}
@media (hover: hover) {
  .ftr__socialrow a:hover, .ftr__legal a:hover { color: var(--f-ink); }
  .ftr__legal a:hover::after { transform: scaleX(1); }
  /* La flèche sortante part vers où elle pointe. */
  .ftr__socialrow a:hover .ftr__ar { transform: translate(2px, -2px); opacity: .9; }
}

/* Champs à renseigner avant mise en ligne : repérables sans être criards. */
/* Marqueur « lien pas encore ouvert » : souligné en pointillés, couleur
   atténuée. PLUS AUCUN LIEN NE LE PORTE depuis que les trois profils sont
   renseignés ; la règle reste parce qu'elle EST la convention de la page pour
   ce cas, et qu'il se représentera (Facebook n'a pas encore de page). La
   supprimer obligerait à réinventer le même marquage au prochain lien absent. */
.ftr__todo {
  color: var(--f-todo);
  text-decoration: underline dotted;
  text-underline-offset: 3px;
}

/* ===================== ANCRES DE NAVIGATION =====================
   Le header est collant (60px en mobile, 72 en desktop). Sans marge de
   défilement, un lien du menu dépose la cible SOUS la barre : l'œilleton et le
   titre de section passent dessous et le visiteur atterrit au milieu d'un bloc
   sans savoir où il est. */
/* #diagnostic a ete retire de la liste : aucun element du site ne porte cet id.
   Une ancre morte dans un selecteur ne coute rien a l'execution, mais elle fait
   croire a la prochaine lecture qu'il existe une section de ce nom. */
#methode, #resultats, #tarifs, #garanties, #faq {
  /* Suit la hauteur réelle de la barre (--header-h : 60 px en mobile, 72 en
     desktop, encoche comprise) + un peu d'air. Le jeton annonçait 56 px, soit
     4 px de moins que la barre : la cible se déposait juste dessous. */
  scroll-margin-top: calc(var(--header-h) + 16px);
}

/* ===================== RESPONSIVE (grand écran) ===================== */
@media (min-width: 480px) {
  /* La page n'est plus une carte : ni marge, ni rayon, ni ombre : les fonds
     touchent les quatre bords de l'écran, c'est --pad qui centre le contenu. */

  /* Carte desktop : le hero reprend sa mise en page naturelle (pas de "1 écran plein").
     `min-height: 0` datait de l'epoque ou la photo etait un bloc DANS le flux et
     donnait sa hauteur au hero. Elle est passee en fond, donc plus rien ne le
     tient : sans hauteur de plancher, le hero se refermait sur ses 4 lignes de
     texte et la photo n'avait plus que 260px pour exister. */
  .hero { display: block; min-height: 620px; padding: 44px var(--pad) 40px; }
  .hero__text { margin: 0 0 44px; }
}

/* ===================== GRAND ÉCRAN (≥ 1024 px) =====================
   Jusqu'ici le site restait une colonne de 402 px posée au milieu d'un écran de
   1440 : une maquette mobile épinglée sur un moniteur. Cette couche lui donne sa
   vraie mise en page de bureau, SANS toucher au dessin mobile ni à la bande
   480-1023 px (la carte y garde ses espacements au pixel près).

   Trois leviers, d'où la brièveté du bloc :
   1. les jetons (--pad, --s11, échelle typo) grandissent -> gouttières,
      respiration entre sections et titres suivent d'eux-mêmes ;
   2. les listes qui s'empilaient en colonne passent en grille ;
   3. les blocs de texte reçoivent une mesure (58 ch). C'est LE piège d'un simple
      élargissement : une ligne de 1 100 px ne se lit pas.
   Le reste (plaques collantes, carrousel, menu, verre) fonctionne tel quel. */
@media (min-width: 1024px) {

  /* ÉCHELLE DE BUREAU. Ces 5 jetons commandent TOUT ce qui grandit avec
     l'écran : la typo, la respiration entre sections et la largeur de colonne.
     Ils ont été redescendus d'un cran (titres -18 %, section -21 %, colonne
     -7 %) : à 1920 le titre du hero montait à 67px et la colonne à 1520, ce qui
     donnait une page qui se voyait de loin mais se lisait mal , beaucoup
     d'échelle, peu de densité. Le dessin mobile et la bande 480-1023 px ne sont
     pas concernés : ces jetons n'existent qu'au-dessus de 1024. */
  /* ===== LE MENU EN 2 COLONNES, ET SEULEMENT ICI =====
     La carte du menu vaut à toutes les largeurs ; sa mise en colonnes, non.
     À 402 px, mettre les Ressources en 2e colonne les pousse hors de la carte :
     l'intitulé et ses 6 liens deviennent invisibles, mesuré. Sous 1024 px on
     garde donc l'ordre du document — les 5 liens, le filet, Ressources, la
     signature — qui est celui d'aujourd'hui et qui tient dans une colonne.
     Le filet ne disparaît qu'ICI : en pile il sépare vraiment deux groupes,
     alors qu'en 2 colonnes la colonne fait déjà la séparation. */
  .menu__panel {
    display: grid;
    grid-template-columns: 1.1fr 1fr;
    column-gap: 56px;
    align-content: start;
  }
  .menu__nav      { grid-column: 1; grid-row: 1 / span 2; }
  .menu__sep      { display: none; }
  .menu__label    { grid-column: 2; grid-row: 1; margin-top: 6px; }
  .menu__nav--sub { grid-column: 2; grid-row: 2; }
  .menu__foot     { grid-column: 1 / -1; grid-row: 3; }
  /* Les liens tenaient tout un écran, ils tiennent maintenant dans une carte.
     Le `clamp(1.5rem, 7vw, 2.6rem)` de la base montait à 41,6 px : deux
     colonnes de cette taille ne rentrent pas. La base n'est PAS touchée, elle
     porte le dessin de référence du téléphone. */
  .menu__nav a      { font-size: 30px; line-height: 1.42; }
  .menu__nav--sub a { font-size: 15px; line-height: 1.9; }

  :root {
    --pad: clamp(40px, 4.4vw, 64px);   /* gouttière de la carte */
    --s11: clamp(72px, 5.6vw, 108px);  /* respiration entre deux blocs de section */
    /* 10 + 40 + 10, la MEME hauteur qu'en pile. Elle etait a 72 (16 + 40 + 16) :
       12px de plus de chaque cote pour la meme barre, alors qu'elle ne porte
       rien de plus en bureau. Le 40 est incompressible, c'est la hauteur du
       bouton du menu, le plus haut des 3 enfants. */
    --header-h: calc(60px + env(safe-area-inset-top));   /* 10 + 40 (bouton menu) + 10 */
    --t-h1: clamp(40px, 2.9vw, 56px);  /* titre du hero */
    --t-h2: clamp(28px, 2vw, 40px);    /* tous les titres de section */
    --t-body: clamp(16px, 0.88vw, 18px);
    --mesure: 46ch;                    /* ~65 signes : la mesure de lecture.
                                          Le « 0 » de Satoshi est large, 58ch
                                          donnait déjà 90 signes par ligne. */
    /* La colonne se cale sur 1120px. Au-delà, la gouttière absorbe : à 1920 elle
       vaut 400px de chaque côté et le contenu reste à 1120, sans que rien ne
       s'étire. */
    --contenu: 1120px;
    --pad: max(clamp(40px, 4.4vw, 64px), calc((100vw - var(--contenu)) / 2));
  }

  /* --- Barre : même géométrie, à l'échelle de la carte --- */
  .siteheader { padding: calc(10px + env(safe-area-inset-top)) var(--pad) 10px; }
  .logo svg { width: 34px; height: 34px; }
  .hcta { height: 38px; padding: 0 18px; }
  /* Retrait VERTICAL : 8px au lieu de 6, la barre est plus haute sur desktop.
     Retrait LATÉRAL : la marge autour du contenu passe de 8 à 16px. Deux
     raisons qui tombent sur le même nombre.
     1. La pilule a un rayon de 16px. Une marge de 8px plaçait le logo et la
        grille du menu DANS la courbe du coin, là où la place se dérobe : d'où
        l'impression de contenu serré contre les extrémités.
     2. Sur mobile, la marge horizontale vaut le double de la marge verticale du
        bouton du menu (8 contre 4). Sur desktop ce bouton a 8px au-dessus et
        en dessous : le même rapport demande donc 16.
     Le calcul reste accroché à --pad : la pilule continue de suivre la colonne
     de contenu, elle est seulement plus généreuse autour d'elle. */
  /* Le retrait vertical repasse a 6px, celui de la base : la barre est
     descendue de 72 a 60px, et 8px n'y laissaient plus que 2px autour du bouton
     du menu, qui fait 40. A 6px la pilule mesure 48px, exactement le rapport de
     la reference mobile, ou la barre fait deja 60. */
  .siteheader.is-condensed::before { inset: 6px calc(var(--pad) - 16px); }

  /* ===================== HERO =====================
     Le seul écran qui change de composition : énoncé à gauche, image à droite.
     Les deux rangées 1fr encadrent la pile de texte -> elle se centre en face de
     l'image quelle que soit la hauteur de celle-ci. */
  .hero {
    /* LE BLOC DE TEXTE SORT DE LA COLONNE DE 1120.
       --pad ne vaut pas une gouttiere : c'est `max(gouttiere, (100vw - 1120)/2)`,
       donc il CENTRE une colonne de 1120px. A 1440 il vaut 160px, a 1920 400px,
       a 2560 720px. C'est juste pour une section de texte posee sur du blanc.
       Le hero, lui, est devenu une image plein ecran : son bloc se retrouvait
       pousse au tiers de l'ecran, flottant au milieu du labo au lieu de tenir
       un bord. Il reprend donc la GOUTTIERE SEULE, sans le terme de centrage :
       il se cale a gauche et n'y bouge plus, quelle que soit la largeur.
       --hero-x est la molette : monte-la pour l'eloigner du bord.
       La 1re colonne est bornee a 560px pour que le titre garde exactement sa
       mesure actuelle (528px de large) : sans borne, le fr repris a --pad
       l'aurait laisse s'etaler sur toute la moitie gauche. */
    --hero-x: clamp(40px, 4.4vw, 64px);
    display: grid;
    grid-template-columns: minmax(0, 560px) 1fr;
    /* Les 2 `1fr` encadrent la pile de texte et la centrent en face de la photo ;
       les 4 `auto` sont œilleton, titre, texte et boutons. Le socle vient se
       coller au fond du dernier `1fr`. */
    grid-template-rows: 1fr auto auto auto auto 1fr;
    column-gap: clamp(48px, 5vw, 92px);
    padding: clamp(56px, 5vw, 88px) var(--pad) clamp(64px, 5.5vw, 96px) var(--hero-x);
    /* PLEIN ECRAN. `min-height: 0` etait juste tant que la hauteur du hero
       venait de la photo : la carte de droite portait `aspect-ratio: 4 / 5` et
       le hero mesurait 780px. La photo est passee en fond, elle ne mesure plus
       rien, et le hero se refermait sur 448px.
       Il prend maintenant l'ecran entier moins la barre, exactement comme en
       pile : c'est la MEME regle que la base, ecrite une 2e fois seulement
       parce que la grille de bureau remettait min-height a 0.
       `svh` et non `dvh`, pour la raison ecrite sur la regle de base : `dvh`
       suit la barre d'adresse et ferait grandir le hero pendant qu'on scrolle. */
    min-height: calc(100svh - var(--header-h));
  }
  .hero .eyebrow { grid-column: 1; grid-row: 2; }
  .hero__title   { grid-column: 1; grid-row: 3; margin-bottom: 22px; text-wrap: balance; }
  .hero__text    { grid-column: 1; grid-row: 4; max-width: 44ch; margin-bottom: 34px; }
  .hero__actions { grid-column: 1; grid-row: 5; flex-direction: row; gap: var(--s3); }
  .hero__actions .btn { flex: 0 1 240px; }
  /* La 2e colonne n'a plus d'element : elle reserve simplement la moitie droite
     du hero a la photo, en tenant la colonne de texte a sa largeur actuelle.
     En bureau le cadrage repasse au format paysage. */
  .hero {
    --fond-img: url("assets/hero-lab.webp");
    /* La zone forte passe a gauche : c'est la que tombe le bloc de texte. Pleine
       jusqu'a 26% de la largeur, eteinte a 46%, donc le raccord tombe avant le
       grand mur blanc. */
    --fond-masque: linear-gradient(90deg, #000 0%, #000 12%, transparent 62%);
    /* UNE SEULE ELLIPSE, SUR LE BLOC DE TEXTE (mesure : il occupe 39 a 60 % de
       la hauteur du hero et 4 a 35 % de sa largeur).
       IL Y EN AVAIT UNE 2e SUR LE SOCLE, ELLE A ETE RETIREE. Le sol y est
       sombre : moyenne 53/255, 5e centile 42. Pour que l'encre y passe 4,5:1 il
       faut le monter a 128, soit 67 points au-dessus de son voisinage immediat,
       et aucun reglage ne rattrape ca : mesure faite de 14 a 40px de flou,
       l'ecart reste entre 64 et 67. Une tache claire sur un sol sombre se voit,
       point. Le socle passe donc en TEXTE CLAIR sur le sol garde tel quel (voir
       plus bas) : 9,3:1 sans rien poser dessus. */
    --fond-masque-fort:
      radial-gradient(ellipse 40% 30% at 19% 50%, #000 0%, #000 39%, transparent 100%);
  }
  /* LE PORTRAIT PREND LA MOITIE DROITE, ET IL EST HORS DE LA GRILLE.
     La 2e colonne est vide et sert deja a reserver cette moitie ; y poser une
     photo la ferait au contraire dependre de la hauteur du bloc de texte,
     puisque les 2 colonnes partagent les memes rangees. En absolu, le portrait
     se cale sur le HERO et sur rien d'autre : il ne bouge pas quand le titre
     passe sur 3 lignes.
     LE PORTRAIT PREND TOUTE LA PLACE LIBRE, ET CETTE PLACE SE CALCULE.
     `--hero-x + 560px` est le bord droit de la colonne de texte (voir la
     grille ci-dessus, ou 560px est la borne de la 1re colonne). Ce qui reste
     jusqu'au bord droit du hero est exactement ce que le buste peut occuper
     sans jamais toucher le titre, les boutons ni le socle : on le lui donne en
     entier, et la hauteur suit par le format des photos.
     UN POURCENTAGE FIXE NE MARCHAIT PAS, et c'est ce qui a fait ecrire ce
     calcul : la colonne de texte garde 560px a toutes les largeurs, donc la
     place libre passe de 424px a 1024 de fenetre a 1761px a 2400. Une largeur
     en % du hero donnait un buste juste a une seule taille d'ecran et sur le
     bouton  Decouvrir la methode  a toutes les autres.
     BORNEE A 1240px : au-dela, le buste depasse la taille reelle et le
     visiteur d'un 27 pouces se retrouve avec une tete de 40cm.
     LE BAS EST A `bottom: 0`, DONC A LA LIMITE DU HERO. Les photos s'arretent
     au haut du buste et laissent une arete horizontale ; posee ici, elle tombe
     exactement sur le bord bas du hero, la ou commence la plaque sombre. La
     coupe n'a plus besoin d'etre cachee : elle EST la limite de la section, et
     l'homme se lit comme coupe par le bas de l'ecran. C'est aussi pour ca
     qu'il n'y a plus de degrade d'extinction sur .hero__buste. */
  .hero {
    --mur-libre: calc(100% - var(--hero-x) - 560px);
    /* 3 bornes, et chacune repare un cas reel :
         max(560px, ...)  le plancher, pour la fenetre etroite (voir `right`) ;
         (100svh - header) x 1,133  LA HAUTEUR DU HERO, ramenee en largeur par
           le format des photos. Sans elle, une fenetre large mais BASSE (1440
           x 600, un portable pose sur une station) donnait un buste de 662px
           dans un hero de 540 : `overflow: hidden` lui coupait le haut du
           crane. C'est la seule borne qui ne se voit pas en redimensionnant en
           largeur, d'ou son oubli au 1er jet.
           CE FACTEUR EST 1138 / HAUTEUR_SORTIE, il se recalcule des que le
           cadre des photos bouge : il valait 1,211 quand elles sortaient en
           1138 x 940. Le laisser a l'ancienne valeur avec des photos plus
           hautes, c'est autoriser un cadre plus haut que le hero, donc le
           sommet du crane coupe sur les fenetres basses ;
         1240px  le plafond, pour le 27 pouces. */
    --mur-l: min(max(560px, var(--mur-libre)),
                 calc((100svh - var(--header-h)) * 1.133),
                 1240px);
  }
  .hero > .hero__mur {
    display: block;
    position: absolute;
    /* SOUS 1200px DE FENETRE, LE BUSTE SORT PAR LA DROITE AU LIEU DE MAIGRIR.
       La place libre tombe a 424px a 1024 : cale a `right: 0`, le portrait y
       faisait 404 x 334 et se recroquevillait dans le coin bas droit, moitie
       de tete coupee, pendant que les 2 tiers hauts de la moitie droite
       restaient vides. Il garde donc son plancher de 560px et c'est le CADRE
       qui deborde du hero, la ou `overflow: hidden` le coupe : on perd l'epaule
       droite, qui ne porte rien, et on garde la tete a sa taille.
       Le decalage vaut exactement ce qui manque (place libre moins 560px), et
       il est nul des que la place suffit : au-dessus de 1200px cette ligne ne
       fait rien. */
    right: min(0px, calc(var(--mur-libre) - 560px));
    bottom: 0;
    width: var(--mur-l);
    /* La hauteur suit la largeur : les 8 photos sortent toutes en 1138 x 1004
       du meme cadre (voir atelier\detourer-portrait.py), donc une seule
       ecriture suffit et les 2 couches se superposent au px pres.
       CETTE TAILLE-LA VIENT DE L'ECRAN, pas d'un arrondi : a 1800px de fenetre
       le buste est rendu sur 1161px de large, donc a 1 % pres sa taille reelle.
       Le jeu d'avant faisait 944px et montait a 1,23 : la peau et les cheveux
       y perdaient visiblement, et sur un visage de cette taille ca se voit.
       CE QUI FAIT MONTER L'HOMME DANS LE HERO, C'EST CETTE LIGNE. Le cadre est
       cale au bas du hero et l'homme est coupe net par le bas de sa photo :
       une photo plus haute pousse donc le cadre vers le haut, et la tete
       monte d'autant. Les photos sont passees de 940 a 1004 px de haut (du
       torse ajoute en bas, pas un recadrage), soit 66px de plus a 1800px de
       fenetre. Remonter la tete encore demande d'allonger le cadre dans
       detourer-portrait.py, pas de toucher a `bottom` : deplacer le cadre vers
       le haut ferait apparaitre la coupe droite du buste au milieu du hero. */
    aspect-ratio: 1138 / 1004;
    /* Un decor : il ne prend ni le pointeur ni le curseur au texte qui passe
       dessous. */
    pointer-events: none;
  }
  /* LES 2 COUCHES SE RECOUVRENT EXACTEMENT. C'est ce qui fait le fondu croise :
     celle qui arrive monte a 1 pendant que celle qui part descend a 0, et
     comme les 2 hommes sont recales au px pres, on ne voit ni glissement ni
     trou. `object-fit: contain` pour que rien ne soit jamais rogne, meme si
     une photo future n'a pas exactement le meme format. */

  /* LES 2 COURBES NE SONT PAS LA MEME, ET C'EST TOUT L'OBJET DE CES 2 LIGNES.
     EN `linear` DES 2 COTES, LE HERO CLIGNOTE AU MILIEU DU FONDU. Ce n'est pas
     un defaut de reglage, c'est de l'arithmetique : 2 couches empilees a
     l'opacite a et b laissent passer (1-a)(1-b) du fond. A mi-fondu les 2 sont
     a 0,5, donc 25 % DU LABO TRAVERSE L'HOMME. On voyait un etabli au travers
     d'un torse, une demi-seconde, a chaque transformation.
     LA SEULE FACON D'ANNULER CE TROU EXACTEMENT serait de garder une des 2
     couches a 1 tout du long ; mais les 4 hommes n'ont pas la meme silhouette,
     et la couche du dessous laisserait alors depasser les cheveux du precedent
     jusqu'a disparaitre d'un coup. On resserre donc les 2 courbes l'une vers
     l'autre : celle qui arrive monte vite, celle qui part descend tard, et
     elles se croisent toutes les 2 a 0,91 au lieu de 0,5. Le fond visible
     tombe de 25 % a 0,8 %. Ce qu'il en reste vaut 1 niveau sur 255 sur le
     debardeur, l'endroit le plus expose parce qu'il est noir devant un labo
     clair ; sur la peau, un dixieme de niveau.
     LE PRIX EST DANS LE RYTHME, et il faut le savoir avant de retoucher ces
     4 nombres : croiser haut oblige la couche qui arrive a monter vite, donc
     les 2 tiers du changement se font dans le 1er tiers du fondu. Il se lit
     plus vif qu'en `linear`, sans etre plus court. Pour l'etaler, c'est
     `--mur-fondu` qu'on allonge ; adoucir les courbes rouvrirait le trou (a
     mi-chemin des 2, on repasse a 3,6 %, soit 6 niveaux, et ca se revoit).
     ON NE PEUT PAS ECRIRE CA EN UNE SEULE LIGNE : la regle qui s'applique est
     celle de l'etat d'ARRIVEE de la transition. Une couche qui recoit `is-vu`
     lit donc la courbe d'en bas, une couche qui la perd lit celle d'en haut.
     C'est pour cela que la 2e ne redefinit QUE la fonction, sans repeter la
     duree : la repeter la remettrait a sa valeur par defaut. */
  .hero__buste {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    opacity: 0;
    /* celle qui PART : elle tient, puis lache */
    transition: opacity var(--mur-fondu, 1.1s) cubic-bezier(.68, 0, .83, .28);
  }
  /* celle qui ARRIVE : elle monte tout de suite */
  .hero__buste.is-vu {
    opacity: 1;
    transition-timing-function: cubic-bezier(.17, .72, .32, 1);
  }

  /* Le socle occupe la rangée d'appui du bas (le second 1fr) et s'y colle au
     fond : la pile de texte reste centrée en face de la photo, et le socle se
     pose au pied du hero, là où l'œil termine sa descente avant de scroller. */
  .hero__proof {
    display: grid;
    grid-column: 1;
    grid-row: 6;
    align-self: end;
    margin: 0;
  }
  .hero__proofitem    { padding: 0 16px; }
  /* La ligne grasse devient une rangee : elle porte le libelle et, pour la
     colonne Trustpilot, les 5 tuiles a sa droite. Mesure : la colonne fait
     155px utiles, le libelle 60 et les tuiles 78, gouttiere comprise il reste
     9px. Ca tient, mais de justesse, d'ou le `flex-wrap` : si la colonne
     maigrit un jour, les tuiles passent dessous au lieu de deborder. */
  .hero__proofitem b  { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: 15px; }
  .hero__stars        { flex: none; }
  .hero__proofitem em { margin-top: 3px; font-size: 13px; }
  /* SOCLE EN CLAIR : C'EST LE FOND QUI COMMANDE, PAS LA CHARTE.
     Le socle tombe sur le sol de l'atelier, qui est sombre (moyenne 53/255).
     Sur ce fond-la, l'encre #131315 vaut 1,2:1 : il faut donc soit eclaircir le
     sol, ce qui y colle une tache (voir --fond-masque-fort), soit inverser le
     texte. On inverse. Mesure dans le pire cas, c'est-a-dire contre les pixels
     les plus CLAIRS du sol (95e centile, 66/255) :
       #f6f6f7 -> 9,3:1
       #c3c3ca -> 5,7:1
     Les 2 teintes sont celles de la plaque sombre du site (--dark-title et un
     cran au-dessus de --dark-text) : la page a deja un jeu clair, on le reprend
     au lieu d'en inventer un.
     Le filet separateur suit : --line (#e7e7ea) etait fait pour du blanc. */
  .hero__proofitem    { border-left-color: rgba(255, 255, 255, .22); }
  .hero__proofitem b  { color: var(--dark-title); }
  .hero__proofitem em { color: #c3c3ca; }

  /* ===================== PLAQUE SOMBRE ===================== */
  /* Le HAUT est plus court que le bas, et c'est voulu. Mesure : la plaque
     ouvrait sur 97px de noir vide avant des logos qui font 34px de haut, alors
     qu'il n'y a que 84px entre ces memes logos et le titre qui suit. Le vide
     d'entree pesait donc plus que le bloc qu'il annonce. Le bas garde --s11 :
     lui separe deux sections, il a un autre travail. */
  .dark { padding: clamp(24px, 2.2vw, 40px) var(--pad) var(--s11); }
  .dark__title { max-width: 20ch; margin-inline: auto; }
  .dark__text  { max-width: var(--mesure); margin-inline: auto; }

  /* Bandeau d'autorité : logos à l'échelle de la carte. */
  .brand-chip { height: 58px; padding: 0 22px; }
  .brand-chip img { height: 34px; }

  /* Les comparateurs se regardent au lieu de s'empiler : 2 par page.
     La piste est BORNEE a 880 px. Sur toute la largeur, chaque photo depassait
     560 px : deux portraits de cette taille prenaient tout l'ecran et le titre
     au-dessus n'existait plus. A 880 elles retombent a ~430. */
  /* La piste s'elargit des 2 bandes laterales, mais la PAGE UTILE reste a
     880 px : les percentages de grid-auto-columns portent sur le bloc de
     contenu, donc hors --peek. Les 2 comparateurs gardent exactement leur
     taille, ce sont les voisins qui viennent occuper les bords. */
  /* --peek se declare sur .ba-car, jamais sur la piste : les voiles de flou
     sont des freres de la piste, pas ses enfants, et une variable posee sur
     elle ne les atteindrait pas. Ecrite au mauvais endroit, la bande valait
     150px pour le padding et --pad (80px) pour les voiles : le flou s'arretait
     70px avant le bord. */
  .ba-car {
    --peek: 150px;                  /* ici la place existe : pas besoin d'aller
                                       la chercher dans la gouttiere */
    max-width: 1180px;
    margin-inline: auto;
  }
  .ba-track {
    grid-template-rows: auto;       /* une seule rangee : les 2 d'une page se
                                       regardent au lieu de s'empiler */
    grid-auto-columns: calc((100% - var(--s5)) / 2);
    gap: var(--s5);
  }
  .ba-track .ba { aspect-ratio: 4 / 5; }

  /* Bénéfices : trois colonnes, le chiffre au-dessus du texte. */
  .benefits {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0 clamp(24px, 3vw, 48px);
  }
  .benefit { grid-template-columns: 1fr; align-items: start; gap: 12px; padding: 22px 0 0; }
  .benefit__num, .blocker__num { font-size: 54px; }
  /* Le filet sous le dernier item fermait une liste verticale. En rangée, il ne
     souligne plus qu'une colonne sur trois : c'est le filet du haut qui coiffe
     désormais chaque colonne.
     `.blocker` n'est plus dans cette règle : il n'a plus de filet du tout, à
     aucune largeur, depuis qu'il est une carte dès le téléphone. `.benefit`,
     lui, est resté une liste à filets sur la plaque sombre. */
  .benefit:last-child { border-bottom: 0; }

  /* Études : les trois cartes d'argument tiennent sur une ligne. */
  .studies__tabs { max-width: 520px; margin-inline: auto; }
  /* Quatre arguments par onglet : 2 x 2. En trois colonnes, le quatrième
     restait seul sur sa ligne. */
  .studies__panel.is-active { grid-template-columns: repeat(2, 1fr); gap: clamp(16px, 1.8vw, 24px); }
  .studies__title { max-width: 24ch; margin-inline: auto; }
  .keyfig { max-width: 760px; margin-inline: auto; }

  /* ===================== PLAQUE CLAIRE ===================== */
  .proof { padding: clamp(64px, 6vw, 96px) var(--pad) var(--s11); }

  /* Listes numérotées (« ce qui bloque », « quatre étapes ») : autant de colonnes
     que d'entrées (trois d'un côté, quatre de l'autre), sans règle par bloc. */
  .blockers__list {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    /* Le `gap` est pose juste apres, quand la liste devient des cartes.
       L'ecrire ici aussi ne servait qu'a se faire ecraser. */
  }
  /* DE VRAIES CARTES, ET NON DES COLONNES SEPAREES PAR UN FILET.
     `align-content: start` n'est PAS cosmetique : la liste etire ses cellules
     a la hauteur de la plus haute, et une grille etiree redistribue le surplus
     a ses rangees automatiques. L'etape au texte le plus court recevait donc
     le plus de vide entre son chiffre et son titre : mesure, l'ecart allait
     de 66 a 97px et les 4 titres tombaient a 4 hauteurs differentes.
     Chrome de carte du site : blanc, rayon 16, ombre douce, comme .plan et
     .grt__item. Il n'est plus REPRIS ici, il est HERITE : la base le pose
     desormais des le telephone, ou les 2 blocs etaient restes sur une liste a
     filets. Ce qui reste dans cette regle est donc uniquement ce qui change
     avec la place : une colonne au lieu de deux (le chiffre passe sous le
     texte), et un ecart interne plus serre. */
  .blockers__list { gap: clamp(14px, 1.6vw, 22px); }
  .blocker {
    grid-template-columns: 1fr;
    align-items: start;
    align-content: start;
    gap: 10px;
  }

  /* --- LES 4 ETAPES : LA PROPORTION DU MODELE ---
     La carte de reference est HAUTE (rapport largeur/hauteur autour de 0,8) et
     son contenu ne la remplit pas : titre et texte en haut, un grand vide,
     puis un element court qui tient le bas. C'est ce vide qui donne son calme
     au bloc, et il ne tient que parce que quelque chose l'arrete en bas.

     D'ou le seul deplacement de cette regle : LE CHIFFRE PASSE EN BAS. Un
     numero d'etape est une donnee de reperage, exactement comme la source qui
     ancre la carte du modele ; en haut il occupait la place du titre et
     laissait le vide flotter sans fin. La lecture n'y perd rien, les cartes se
     suivent de gauche a droite.

     Ce modificateur ne touche QUE ce bloc : « Vous avez deja essaye » partage
     le meme chrome de carte mais pas cette proportion, ses 3 constats sont des
     phrases, pas des etapes numerotees. */
  /* --- LE CHEVRON ENTRE LES ETAPES ---
     Quatre cartes alignees se lisent comme 4 blocs, pas comme une SUITE : rien
     ne dit que la 02 vient apres la 01, sinon les chiffres, qui sont en bas et
     se lisent en dernier. Le chevron dit l'enchainement avant qu'on ait lu quoi
     que ce soit.

     UN CHEVRON, PAS UNE FLECHE. L'etat precedent tracait une vraie fleche en
     CSS : un filet de 1px sur toute la gouttiere, plus une pointe faite d'un
     carre tourne a 45 degres. Deux defauts, et le second est le vrai.
       1. Le filet valait exactement la gouttiere : il touchait la carte de
          gauche ET celle de droite. Les 4 cartes se retrouvaient soudees par
          une barre continue, alors que c'est l'air entre elles qui les tient
          en rangee.
       2. Un carre tourne borde de 2 cotes a une pointe a ONGLET, angle vif.
          Or tout le jeu d'icones de la page (#i-check, #i-cross, #i-arrow-ne,
          les chevrons du carrousel) est trace en bouts et angles ARRONDIS.
          Cette pointe-la etait le seul angle vif du site.
     Le filet est donc retire, la gouttiere redevient de l'air, et il ne reste
     que le signe, centre entre 2 cartes : #i-chev, qui est le trace exact du
     bouton « suivant » du carrousel.

     POURQUOI DU SVG EN LIGNE, ALORS QUE C'ETAIT EN CSS. L'ancien commentaire
     invoquait la CSP : elle est bien en img-src 'self', donc un pictogramme en
     data-URI (image de fond OU masque) ne s'afficherait pas. Mais un <svg>
     ecrit DANS le document n'est pas une requete d'image : il ne passe pas par
     img-src, et la page en sert deja des dizaines par <use href="#...">.
     L'autre reserve, le bruit pour un lecteur d'ecran, est levee par
     aria-hidden, la convention deja suivie par toutes les icones du site.
     Le CSS pur ne savait pas arrondir les bouts d'un trait ; le SVG si.

     Le chevron ne vit qu'a partir de 1024px, la ou les etapes sont une rangee.
     Empilees, elles se suivent de haut en bas et n'ont rien a relier. */
  .blockers--etapes { --gout: clamp(22px, 2.4vw, 34px); }
  .blockers--etapes .blockers__list { gap: var(--gout); }
  .blockers--etapes .blocker__chev {
    display: block;
    position: absolute;
    /* LES 2 REMISES A AUTO NE SONT PAS DECORATIVES. La regle telephone pose la
       fleche au-dessus de la carte, donc en `left` + `bottom` ; celle-ci la
       remet dans la gouttiere, donc en `right` + `top`. Sans les annuler, les 4
       cotes seraient poses en meme temps sur un element de largeur et de
       hauteur fixes : le navigateur en ignore alors 2, et ce sont `left` et
       `top` qu'il garde. La fleche du bureau serait repartie au milieu de la
       carte au lieu de la gouttiere. */
    left: auto;
    bottom: auto;
    top: 50%;
    /* Pose au MILIEU de la gouttiere : le bord droit du gabarit tombe sur le
       milieu, translate(50%) le ramene d'une demi-largeur. Le trace est centre
       dans son gabarit, donc le signe l'est dans la gouttiere. */
    right: calc(100% + var(--gout) / 2);
    width: 16px;
    height: 16px;
    transform: translate(50%, -50%);
    color: rgba(19, 19, 21, .3);
  }
  .blockers--etapes .blocker {
    position: relative;               /* ancre le chevron */
    display: flex;
    flex-direction: column;
    /* La hauteur se regle sur la PART DE VIDE, pas sur un rapport de cotes.
       Le modele laisse environ la moitie de sa carte vide sous le texte, et
       c'est ca qu'on lit comme du calme. Ses cartes font 385px de large ; les
       notres 261, donc un texte de 2 lignes y occupe proportionnellement plus
       de hauteur. A rapport de cotes egal (0,82) le vide ne serait que de
       31 % : il faut aller PLUS haut que le modele pour retrouver son vide. */
    min-height: clamp(320px, 28vw, 380px);
    padding: 26px 24px 22px;
  }
  .blockers--etapes .blocker__body { order: -1; }   /* le texte d'abord, le chiffre apres */
  .blockers--etapes .blocker__num {
    margin-top: auto;                               /* pousse le chiffre au pied de la carte */
    padding-top: 20px;
  }
  /* TITRE DE CARTE = .scard__title, AU CHIFFRE PRES, ET POUR LES 2 BLOCS.
     La page a deja une regle pour ce role exact, celle des 12 cartes d'etudes,
     et c'est d'elle que le modele donne l'equivalent clair.
     1re erreur : je l'avais approchee sans la respecter. 21px et -0.02em
     etaient bons, mais la graisse restait a 700 (heritee de .blocker__title)
     et l'interligne a 1,2. Or ce titre est en 500, Satoshi Medium, serre a
     1,05 : c'est ce qui lui donne son calme sur 2 lignes. Un titre de carte en
     700 se lit comme une alerte, pas comme un intitule.
     2e erreur : je ne l'avais appliquee qu'aux 4 etapes. « Vous avez deja
     essaye » gardait l'ancien reglage de liste, 16px en 700 avec 4px seulement
     avant son texte, ecrase entre un chiffre de 54px et sa phrase. Or les 2
     blocs sont le MEME composant et se suivent a l'ecran : le titre ne peut
     pas y avoir 2 regimes. Le selecteur n'est donc plus modifie.
     Ce qui reste propre a chaque bloc, c'est l'ANATOMIE : chiffre en bas pour
     les etapes, qui sont une suite ; en haut pour les constats, qui n'en sont
     pas une.
     Les 4 valeurs sont recopiees, pas reinventees : si .scard__title bouge un
     jour, celles-ci doivent bouger avec. */
  .blocker__title {
    margin: 0 0 10px;
    font-size: 21px;
    line-height: 1.05;
    font-weight: 500;
    letter-spacing: -0.02em;
  }
  /* Le texte suit .scard__claim : meme corps, meme interligne, meme graisse. */
  .blocker__text {
    font-size: 15px;
    line-height: 1.4;
    font-weight: 400;
  }

  /* Mesure de lecture. */
  .blockers__sub,
  .protocole__sub,
  .pricing__sub,
  .grt__sub,
  .tstm__title { max-width: var(--mesure); margin-inline: auto; }
  .blockers__title,
  .protocole__title,
  .fit__title,
  .pricing__title,
  .grt__title,
  .opts__title,
  .faq__title { max-width: 22ch; margin-inline: auto; }

  /* Le comparatif reprend son ampleur : la colonne fait 820px au lieu de 402,
     chaque cellule a la place de respirer et les intitulés tiennent sur une ou
     deux lignes au lieu de trois. Les valeurs de la base restent celles du
     mobile, où la même générosité serrait le tableau au lieu de l'aérer. */
  .cmp { max-width: 820px; margin-inline: auto; }
  .cmp__head { padding: 30px 12px 24px; font-size: 14px; }
  .cmp__head--hl { font-size: 20px; }
  .cmp__row  { padding: 22px 16px 22px 2px; font-size: 15px; }
  .cmp__cell { padding: 22px 12px; font-size: 15px; }
  .cmp tbody tr:last-child .cmp__cell,
  .cmp tbody tr:last-child .cmp__row { padding-bottom: 32px; }
  .cmp__ico { width: 22px; height: 22px; vertical-align: -5px; }
  .cmp__badge { padding: 5px 12px; font-size: 14px; }
  .objection { max-width: 820px; margin-inline: auto; }

  /* Carrousel : cartes plus grandes, la géométrie est recalculée par le JS. */
  /* LA SCÈNE S'ARRÊTE DANS LA COLONNE, ET ELLE Y COUPE FRANC.
     Elle s'arrêtait aux bords de l'ÉCRAN : sur un 1340, l'éventail courait de 0
     à 1324 alors que toutes les autres sections du site s'arrêtent à 110 et à
     1215. Le carrousel était le seul bloc de la page à ne pas respecter sa
     colonne, et les cartes lointaines s'étalaient dans un vide qui
     n'appartenait à rien. `margin-inline: 0` annule le débord de la base : la
     scène tient désormais dans la même colonne que « Ce n'est pas pour tout le
     monde » juste en dessous, et `overflow: hidden` coupe au même endroit.

     LE FONDU DE BORD EST COURT, ET LES 2 ERREURS QUI ONT MENÉ À CETTE VALEUR
     valent d'être écrites, parce qu'elles sont opposées.
     1er état : un fondu LONG, calé sur la gouttière (jusqu'à 300px). Il datait
     de l'époque où la scène s'arrêtait au bord de l'écran, là où une coupe
     franche n'est pas une limite mais un accident. Sur une scène désormais
     bornée à la colonne, il ne cachait plus la moitié de la carte du 2e rang :
     il la faisait DISPARAÎTRE en entier. Or ce qu'on veut, c'est qu'elle soit
     là, présente et illisible.
     2e état : pas de fondu du tout, coupe nette sur la colonne. La carte était
     bien là, mais l'arête était brutale — une carte floutée à 13px qui s'arrête
     sur un bord parfaitement net, les 2 ne vont pas ensemble.
     D'où celui-ci : 26px, et une valeur FIXE, pas un pourcentage.
     Le pourcentage a été essayé, il ne tient pas : dans un `clamp()` mêlé à des
     px, il ne peut pas être résolu au moment où la valeur est calculée, et la
     déclaration retombe sur sa borne basse. Mesuré, `clamp(20px, 2,5%, 36px)`
     rendait 20px sur une scène de 1345 là où 2,5 % en valent 34. Une valeur
     qu'on ne peut pas expliquer est une valeur qui dérivera sans qu'on la voie.
     Et le fixe est ici le bon choix de toute façon : ce fondu n'a pas à suivre
     la largeur, il n'adoucit qu'une arête. Sur les ~133px visibles de la carte
     du 2e rang, les 107 premiers restent pleins et seuls les derniers
     s'estompent. L'arête est mangée, la carte reste. */
  .tstm__stage {
    --tcard: 344px;
    margin-inline: 0;
    --fondu: 26px;
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 var(--fondu), #000 calc(100% - var(--fondu)), transparent);
            mask-image: linear-gradient(90deg, transparent, #000 var(--fondu), #000 calc(100% - var(--fondu)), transparent);
  }

  /* Adéquation : les deux cartes en vis-à-vis. L'œilleton et le titre gardent
     toute la largeur, les cartes se partagent la rangée suivante. */
  .fit {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: clamp(20px, 2.4vw, 36px);
  }
  .fit__eyebrow, .fit__title { grid-column: 1 / -1; }
  .fit__card { padding: 28px; }

  /* Citation de Daniel : elle peut respirer. */
  .quote { max-width: 620px; gap: 24px; padding: 20px; }

  /* Tarifs : le décompte de valeur reste une colonne lisible, les deux formats
     se mettent côte à côte. */
  .pricing {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    column-gap: clamp(18px, 2vw, 30px);
  }
  .pricing__eyebrow,
  .pricing__title,
  .pricing__sub,
  .value,
  .pricing__seats { grid-column: 1 / -1; }
  .value,
  .pricing__seats { max-width: 660px; margin-inline: auto; width: 100%; }
  /* Les deux cartes font la même hauteur et leurs boutons tombent sur la même
     ligne : c'est ce qui rend un tableau de prix comparable d'un coup d'œil.
     Cet alignement n'était pas tenable tant que le Protocole alignait treize
     puces contre 4 au Prestige (560 px de vide dans la carte de droite). À 4
     livrables de chaque côté l'écart tombe à ~160 px, que `margin-top: auto`
     sur le bouton renvoie proprement en bas de carte. */
  .plan {
    display: flex;
    flex-direction: column;
    margin-top: var(--s7);
    padding: 28px;
  }
  .plan__list { margin-bottom: var(--s6); }
  /* La carte est en flex ici, et le flex NE FUSIONNE PAS les marges : les 24 px
     de la liste et les 20 px du bloc offert s'additionnaient a 44 px, contre
     20 px sur telephone ou la fusion a lieu. Le bloc flottait donc loin de la
     liste tout en restant colle au bouton. On neutralise sa marge haute : c'est
     la liste qui donne l'ecart, comme partout ailleurs dans la carte. Les 44 px
     sont redistribues (24 dessus, 20 dessous), la carte ne change pas de
     hauteur, et les 2 boutons restent sur la meme ligne. */
  .plan__bonus { margin-top: 0; }
  .plan .btn { margin-top: auto; }

  /* LES CHERCHEURS N'ONT PLUS AUCUNE REGLE PROPRE ICI, ET C'EST LE BON SIGNE.
     Ce bloc portait la grille a 3 colonnes : `repeat(3, 1fr)`, une largeur
     bornee a 1100px, et un filet vertical pose au milieu de chaque gouttiere
     (avec son `nth-child(3n + 1)` pour sauter la 1re colonne de chaque rangee).
     Tout cela decrivait une grille qui n'existe plus a aucune largeur : la
     section est une rangee qui defile, identique du telephone au grand ecran.
     Les regles ont donc ete retirees plutot que neutralisees. La borne a 1100px
     etait d'ailleurs le piege : dans une piste, elle comprimait chaque
     exemplaire de la liste et les 2 copies se chevauchaient. */

  /* Garanties : deux promesses, deux cartes en vis-à-vis, de hauteur égale. */
  .grt__list {
    grid-template-columns: 1fr 1fr;
    gap: clamp(20px, 2.2vw, 28px);
    max-width: 880px;
    margin-inline: auto;
  }
  .grt__item { padding: 22px 24px; }
  .grt__name { font-size: 19px; }

  /* FAQ : une seule colonne, mais bornée : un accordéon large de 1 100 px oblige
     à balayer la ligne des yeux pour trouver le signe « + ». */
  .faq__list { max-width: 840px; margin-inline: auto; }

  /* Les trois issues, sur une ligne. */
  .opts {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    column-gap: clamp(20px, 2.4vw, 36px);
    align-items: start;
  }
  .opts__eyebrow, .opts__title { grid-column: 1 / -1; }
  /* Même marge haute pour les trois. Deux règles pensées pour une PILE la
     cassaient en rangée : l'écart entre cartes successives (.opt + .opt) et l'air
     réservé à la pastille de la dernière (.opt--do). */
  .opt,
  .opt + .opt,
  .opt--do { margin-top: var(--s7); padding: 24px; }

  .cta-band { max-width: 340px; margin-inline: auto; }

  /* ===================== PIED DE PAGE =====================
     Trois blocs sur une seule rangée, comme la référence : contact à gauche,
     appel au centre (le halo est déjà centré, il tombe donc juste derrière),
     réseaux à droite. Puis la barre fine et le wordmark, pleine largeur. */
  .ftr {
    display: grid;
    grid-template-columns: 1fr minmax(0, 1.5fr) 1fr;
    column-gap: clamp(24px, 3vw, 48px);
    align-items: start;
    padding-top: var(--s9);
  }
  .ftr__head   { grid-column: 1; grid-row: 1; padding: 0; }
  .ftr__pitch  { grid-column: 2; grid-row: 1; padding: 0 0 var(--s11); }
  .ftr__pitchline { font-size: clamp(30px, 2.6vw, 40px); }
  /* En colonne de droite, les réseaux perdent leur filet et leur rangée double :
     une entrée par ligne, comme les adresses de la référence. */
  .ftr__social { grid-column: 3; grid-row: 1; padding: 0; border-top: 0; }
  .ftr__socialrow { grid-template-columns: 1fr; gap: 10px; }
  .ftr__bar    { grid-column: 1 / -1; grid-row: 2; gap: var(--s6); }
  /* Deux colonnes de petits caractères : la ligne reste lisible (une mesure, pas
     une bande de 1 200 px) et le bloc tient en trois lignes au lieu de sept. */
  .ftr__fine   { columns: 2; column-gap: clamp(24px, 3vw, 48px); }
  .ftr__barrow { flex-direction: row; align-items: baseline;
                 justify-content: space-between; gap: var(--s6); }
  /* Le pied s'étale sur 1 200 px de large mais reste bas : le filigrane suit la
     largeur, plafonné pour ne pas se faire rogner en haut et en bas par
     l'overflow du bloc. */
  .ftr::after  { width: min(38vw, 520px); }
}

/* ===================== TRÈS GRAND ÉCRAN (≥ 1600 px) =====================
   La bande ≥ 1024 bloque la colonne à 1200 px : tout ce qui dépasse part dans la
   gouttière. Sur un moniteur de 2560 cela faisait 680 px de blanc de chaque côté,
   soit 53 % de la fenêtre vide, et la page se lisait comme une vignette posée au
   milieu de l'écran.

   Cette bande relâche le plafond. Deux précautions tiennent l'esthétique :

   1. TOUT EST CONTINU AU RACCORD. À 1600 px pile, `100vw - 400px` vaut exactement
      1200 px : la colonne reprend la valeur de la bande précédente, sans saut.
      Même logique pour les échelles typographiques et --s11 : leurs plafonds ont
      été remontés SUR PLACE dans la bande ≥ 1024 plutôt que redéclarés ici, si
      bien que la partie vw de leur clamp reprend la main d'elle-même à partir de
      1600 px (h1), 1667 px (h2), 1789 px (corps). En dessous, rien ne bouge :
      les bandes mobile, 480-1023 et 1024-1599 sont intactes au pixel.

   2. RIEN NE S'ÉTIRE SANS BORNE. La colonne s'arrête à 1600 px et les blocs de
      lecture (FAQ, comparateurs, garanties, décompte de valeur) ne gagnent
      qu'une dizaine de pour cent : ils gardent leur mesure. Un accordéon de
      1600 px de large resterait illisible, colonne large ou pas. */
@media (min-width: 1600px) {

  :root {
    /* La colonne reprend un peu d'air au-delà de 1600, sans repartir vers les
       1600px qu'elle atteignait avant : à ce format la page se lisait comme un
       agrandissement d'elle-même. Elle se fige à 1360 et c'est la gouttière qui
       absorbe le reste. Sur un 2560 : 600px de marge, contenu à 1360. */
    --contenu: min(1360px, calc(100vw - 400px));
  }

  /* --- HERO ---
     Rien à borner ici, et c'est volontaire. Les deux colonnes gardent leur
     partage 1,02 / 0,98 et l'image son 4/5 : à 1600 de colonne elle mesure
     739 x 924 au lieu de 536 x 669, soit exactement la proportion image/colonne
     réglée à 1440 (46 %). Un plafond sur l'image, ou une mesure sur le titre
     pour tenir une coupe en 3 lignes, creusait un vide de 440 px entre le texte
     et la photo : `text-wrap: balance` replie déjà le titre en 2 lignes à 1440,
     il faut le laisser faire ici aussi.
     Hauteur totale du hero à ce format : 924 + 184 de rembourrage = 1108 px,
     sous les ~1300 px utiles d'un moniteur 2560 x 1440. */

  /* --- Blocs à mesure bornée ---
     Ils restent centrés dans la colonne élargie. Sans ce rattrapage ils
     paraissent rétrécir : ce n'est pas leur taille qui change, c'est le cadre
     autour. Environ +10 %, assez pour tenir la proportion, trop peu pour
     entamer la lisibilité. */
  .keyfig            { max-width: 840px; }
  .cmp, .objection   { max-width: 900px; }
  .value,
  .pricing__seats    { max-width: 720px; }
  .grt__list         { max-width: 960px; }
  .faq__list         { max-width: 920px; }
  .quote             { max-width: 680px; }

  /* Les cartes gagnent en largeur : leur rembourrage suit, sinon le texte colle
     aux bords. */
  .fit__card, .plan, .opt, .opt + .opt, .opt--do { padding: 32px; }
  .grt__item { padding: 26px 28px; }

  /* Carrousel : la scène déborde volontairement dans les gouttières (marges
     négatives + overflow hidden), les cartes ne sont donc pas bornées par la
     colonne. Sans ce cran elles restaient à leur taille de 1200 au milieu d'un
     éventail deux fois plus large. Le JS déduit l'écart entre crans de la
     largeur de carte : rien d'autre à régler. */
  .tstm__stage { --tcard: 400px; }
}

/* ===================== ACCESSIBILITÉ MOTION ===================== */
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
  /* Exceptions voulues (choix explicite du client) : */
  /* FAQ : la bascule « + » -> « × » accompagne l'ouverture du panneau, qui est
     elle-même animée en JS. Sans elle, le signe sauterait tout seul. */
  .faq__sign { transition: transform .3s cubic-bezier(.22, 1, .36, 1), color .2s ease !important; }
  /* LE PORTRAIT DU HERO, ET SEULEMENT S'IL A LA DEROGATION NOMINATIVE. Sans
     `data-mur-mouvement="toujours"`, app.js ne change jamais son image et cette
     ligne ne s'applique a rien. Avec, il en change : il faut alors que ce soit
     en fondu et pas en coupe franche, sinon la regle generale ci-dessus
     transforme la transformation en clignotement, ce qui est plus agressif que
     ce qu'elle voulait empecher. */
  /* LES 2 COURBES SONT REPRISES ICI TELLES QUELLES, et il le faut : la regle
     generale ci-dessus a coupe la transition avec un `!important`, donc c'est
     cette declaration-la qui gouverne le fondu du portrait chez tous les
     visiteurs qui demandent moins d'animation - et le poste du client en fait
     partie. Ecrite en `linear`, elle ramenait a elle seule le clignotement que
     les 2 courbes corrigent (le raisonnement complet est au-dessus de
     `.hero__buste`). */
  [data-mur-mouvement="toujours"] .hero__buste {
    transition: opacity var(--mur-fondu, 1.1s) cubic-bezier(.68, 0, .83, .28) !important;
  }
  [data-mur-mouvement="toujours"] .hero__buste.is-vu {
    transition-timing-function: cubic-bezier(.17, .72, .32, 1) !important;
  }
  .authority__track--ltr { animation: authority-marquee 38s linear infinite !important; }
  /* LES 6 CHERCHEURS, DEPUIS QUE LE CLIENT A DEMANDE QUE CETTE BANDE DEFILE
     POUR TOUT LE MONDE (voir le commentaire au-dessus de `.auths-piste`).
     C'est le REPLI, pas le moteur : en temps normal app.js reprend la piste
     pour lui donner le ralentissement au survol, et pose alors
     `animation: none` dessus. Cette ligne sert au cas ou le script ne tourne
     pas. Sans elle, ce cas-la donnait une bande FIGEE, ou 2 chercheurs sur 6
     restaient hors d'atteinte : exactement le defaut que le depliage en
     grille corrigeait avant, et qui a ete retire avec lui.
     LE `:not(.bande--js)` N'EST PAS UNE PRECAUTION, IL EST INDISPENSABLE.
     app.js coupe l'animation CSS en posant `animation: none` en style en
     ligne, et un style en ligne NE PASSE PAS devant un `!important` de
     feuille. Sans ce selecteur, les 2 moteurs tourneraient ensemble et la
     bande partirait a double vitesse. La classe est posee par app.js a la
     premiere image reellement produite : tant qu'elle manque, c'est que
     personne d'autre ne fait defiler la bande. */
  .auths-piste:not(.bande--js) { animation: authority-marquee 58s linear infinite !important; }
  .auths-piste:not(.bande--js):hover { animation-play-state: paused !important; }
  /* La barre qui se détache en pilule : MÊME EXCEPTION QUE DANS LE TUNNEL, qui
     l'avait et que celle-ci n'avait pas. C'est pourtant le même composant, copié
     d'une feuille à l'autre : animations coupées, la pilule sautait sur la
     landing et glissait sur le tunnel, à deux clics d'écart. La copie conforme
     du header n'était donc conforme que hors reduced-motion.
     Le décollement n'est pas décoratif : c'est lui qui dit que la plaque sombre
     a atteint le haut. Coupé, le fond de la barre change de couleur d'un coup,
     sans qu'on comprenne pourquoi. La ligne suivante fait de même pour le logo,
     dont le disque s'inverse en même temps que la pilule et qui, seul à sauter,
     donnerait le même à-coup. */
  .siteheader::before { transition: inset .34s ease, border-radius .34s ease, background-color .34s ease, box-shadow .34s ease !important; }
  .logo svg circle, .logo svg path { transition: fill .34s ease !important; }
  /* Le menu garde son fondu d'apparition : c'est une variation d'OPACITÉ, pas un
     déplacement, et c'est désormais le seul geste de son ouverture (la plaque ne
     se déroule plus). Les retards en cascade, eux, portent leur propre
     `!important` là où ils sont définis, sinon le raccourci ci-dessous les
     remettrait tous à zéro et les douze liens surgiraient d'un bloc. */
  .menu__grid, .menu__grid i, .menu__nav a, .menu__sep, .menu__label, .menu__foot { transition: all .45s cubic-bezier(.2, .85, .25, 1) !important; }
  /* Agrandissement des boutons : conservé même en reduced-motion (mouvement
     subtil, jugé confortable). Boîte + libellé, même courbe. Vaut désormais pour
     TOUS les boutons, pas seulement ceux du hero. */
  .btn,
  .btn__label { transition: transform .42s var(--btn-ease) !important; }
  /* Poignée du comparateur : elle grossit légèrement quand on s'en approche.
     Sans cette exception la reprise serait un à-coup. */
  .ba__handle { transition: opacity .22s ease, transform .22s cubic-bezier(.33, 1, .68, 1) !important; }
  /* Pas d'apparition animée -> le contenu reste visible d'emblée. C'est bien
     `translate` qui est neutralisé, pas `transform` : ce dernier appartient au
     bouton révélé, dont l'agrandissement au survol est conservé juste au-dessus. */
  .js .reveal { opacity: 1 !important; translate: none !important; }
  /* Carrousel témoignages : le glissement EST le composant -> transition conservée. */
  .tcard { transition: transform .5s ease, opacity .5s ease, filter .5s ease, background-color .5s ease, box-shadow .5s ease, color .5s ease !important; }
  .tcard::before, .tcard::after { transition: opacity .5s ease !important; }
  .tcard__quote, .tcard__name, .tcard__meta { transition: color .5s ease !important; }
  /* Carrousel comparateurs : MEME EXCEPTION QUE .tcard, et pour la meme
     raison. Le recul d'un comparateur qui quitte la page (echelle, flou,
     opacite) est ce qui fait comprendre qu'on a change de page ; coupe, la
     piste saute d'un etat a l'autre sans qu'on suive. Et sans cette ligne, sur
     une machine aux animations coupees, l'eventail d'avis glisserait pendant
     que le carrousel de comparateurs sauterait, a 2 sections d'ecart. */
  .ba-track .ba { transition: transform .5s ease, opacity .5s ease, filter .5s ease !important; }
  /* Même effet « fond citation » sur les cartes séduction/relations/finances (.scard). */
  .scard { transition: transform .25s ease, box-shadow .25s ease !important; }
  .scard::before, .scard::after { transition: opacity .35s ease !important; }
}


/* ===================== IMPRESSION =====================
   Le site n'avait AUCUNE règle d'impression. Ce qui sortait de l'imprimante,
   ou du « Enregistrer au format PDF » que fait un visiteur qui veut relire
   l'offre au calme ou la montrer à quelqu'un, avait des SECTIONS ENTIÈREMENT
   BLANCHES : les blocs .reveal sont posés à opacity 0 par le script tant qu'ils
   ne sont pas entrés à l'écran, et l'impression fige la page telle quelle. Tout
   ce qui n'avait pas encore été déroulé s'imprimait vide.
   Ce bloc ne redessine pas la page pour le papier : il ne fait que rendre
   imprimable ce qui est déjà là. Trois choses, et rien de plus. */
@media print {
  /* 1. Tout le contenu est visible, quoi qu'ait fait le script.
        `!important` : il passe devant la règle .js .reveal, plus spécifique. */
  .js .reveal { opacity: 1 !important; translate: none !important; }
  *, *::before, *::after { animation: none !important; transition: none !important; }

  /* 2. Rien ne reste collé : un élément `sticky` se réimprime sur CHAQUE page.
        La barre du header et la plaque claire du hero se seraient répétées en
        tête de toutes les feuilles, par-dessus le texte. */
  .siteheader, .plate--one { position: static !important; }
  /* Le bouton du menu et son panneau plein écran n'ont aucun sens sur papier. */
  .menu, .hcta { display: none !important; }

  /* 3. Les blocs ne se coupent pas au milieu d'une carte, et les fonds sombres
        sont imprimés tels quels plutôt que blanchis par le navigateur (sans
        quoi le texte clair de la plaque sombre sort blanc sur blanc). */
  /* .cmp__badge est dans la liste pour la même raison que la plaque sombre :
     c'est du blanc sur fond noir. Sans fond imprimé, « Les 6 » sortirait en
     blanc sur blanc, c'est-à-dire nulle part. .cmp y est pour ne pas se couper
     en deux d'une page à l'autre, ce qui séparerait la carte de ses lignes. */
  .dark, .quote, .scard, .tcard, .plan, .faq__item, .cmp, .cmp__badge {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
    break-inside: avoid;
  }
}
