/* ═══════════════════════════════════════════════════════════════════════════
   landing-chapitres.css — le récit de la page d'accueil, et son défilement.

   Le principe est décrit en tête de `static/js/landing.js`. Cette feuille ne
   porte QUE ce qui est nouveau : l'ouverture, les chapitres épinglés, le rail
   et son point voyageur. Le reste de la page (barre, tarifs, FAQ, pied) garde
   ses styles `lp-*` d'origine.

   ⚠️ LA PAGE DOIT SE LIRE SANS LE SCRIPT. Rien n'est masqué par défaut ici :
   l'opacité de départ n'est posée QUE sous `html.lp-epingle` ou sur les blocs
   que l'observateur d'intersection prend en charge — c'est-à-dire seulement
   quand quelque chose est là pour les révéler. Une règle `opacity: 0` posée
   d'emblée aurait effacé la page entière au premier script en échec.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Le fond : nuances et grain ──────────────────────────────────────────
   Demandé le 2026-08-19 : « sur le fond dégradé lavande, ajoute des nuances
   dedans et de la texture, que ce soit plus joli ».

   Le fond de page vient de `--body-bg` (theme.css:127), un dégradé à trois
   arrêts. Un dégradé linéaire, même à trois arrêts, reste une surface plate :
   l'œil y lit une transition régulière et rien d'autre. On pose donc DEUX
   couches par-dessus, et pas une seule :

     · les NUANCES (::before) — trois voiles circulaires très pâles, dans des
       teintes voisines du lavande (lilas chaud, bleu pervenche, rose poudré).
       Ils décentrent la lumière : le fond n'a plus un seul sens de lecture.
     · le GRAIN (::after) — un bruit fractal SVG, sans fichier image. C'est
       lui qui enlève l'aspect « aplat numérique » : sans grain, les voiles se
       voient par bandes (banding) sur les grands écrans.
       Dosé à la mesure, pas à l'œil : sur une zone de fond unie, l'écart-type
       des pixels passe de 0,47 (dégradé nu) à 2,37 — un grain qui se voit
       quand on le cherche, et que le texte ne sent pas. Au-delà, la lavande
       se salit ; en dessous (essais à 5 % puis 14 %), on ne le voit pas.

   ⚠️ SOUS LE CONTENU, ET SANS L'INTERCEPTER : `z-index: -1` (comme
   `.lp-rexdots`) et `pointer-events: none`. Fixe, donc le grain ne défile
   pas — c'est ce qui le fait lire comme un papier plutôt que comme une image.

   Portée : le thème unique clair uniquement. TermOS a son propre fond (presque
   noir, pointillé) et sa plaque en image ; y verser du lavande le
   contredirait. Le mode nuit de Renew a été réglé exprès sur un gris très
   sombre (theme.css) — on n'y remet pas de couleur. */
.lp-fond { display: none; }
html[data-design="archiflow"][data-theme="light"] .lp-fond {
  display: block;
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}
html[data-design="archiflow"][data-theme="light"] .lp-fond::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image:
    radial-gradient(760px 620px at 14% 6%,   rgba(150, 118, 240, 0.17), transparent 62%),
    radial-gradient(900px 700px at 90% 26%,  rgba(112, 152, 236, 0.15), transparent 64%),
    radial-gradient(820px 640px at 26% 82%,  rgba(228, 172, 212, 0.13), transparent 62%),
    radial-gradient(700px 560px at 78% 96%,  rgba(126, 196, 226, 0.11), transparent 60%);
}
/* Bruit fractal en SVG : aucune image à charger, aucune requête, et il se
   redimensionne sans jamais pixeliser. `baseFrequency` haut = grain fin. */
html[data-design="archiflow"][data-theme="light"] .lp-fond::after {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0.24;
  /* Le filtre fait trois choses, et les trois comptent :
       feTurbulence     — le bruit lui-même, fin (baseFrequency haut) ;
       feColorMatrix    — le désature : brut, feTurbulence produit du bruit
                          COLORÉ, qui posait des points verts et roses sur le
                          lavande ;
       feComponentTransfer — remonte sa moyenne vers le clair et fixe l'alpha.
                          Sans lui, le gris moyen du bruit assombrissait le
                          fond (mesuré : −5,5 niveaux) et la lavande ternissait.
                          Avec, la perte tombe à −2,2 pour un grain 5× plus
                          marqué. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncR type='linear' slope='0.85' intercept='0.42'/%3E%3CfeFuncG type='linear' slope='0.85' intercept='0.42'/%3E%3CfeFuncB type='linear' slope='0.85' intercept='0.42'/%3E%3CfeFuncA type='linear' slope='0' intercept='1'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23g)'/%3E%3C/svg%3E");
  background-size: 220px 220px;
}
/* ── LE CALQUE ────────────────────────────────────────────────────────────
   Ce que les chapitres n'avaient pas : du décor. Mesuré le 2026-09-02, la
   moitié des écrans de la page étaient des aplats lavande sans un trait.
   L'ouverture, elle, a sa trame depuis le 2026-08-19.

   Le motif n'est PAS inventé pour l'occasion : c'est la trame de 30 px de la
   plaque, reprise ici en clair sur clair, plus quelques AXES verticaux —
   frères du rail, qui est déjà l'axe fort de la page à 66 %. Le vocabulaire
   est celui d'une feuille de dessin, ce qui est le métier de ceux à qui la
   page s'adresse.

   ⚠️ PORTÉE VOLONTAIREMENT IDENTIQUE À `.lp-fond` : Renew clair seulement.
   Elle en est l'enfant, donc `display: none` du parent suffit. TermOS porte
   déjà un plan filaire sur sa plaque et un semis de points sur sa page — une
   trame de plus y ferait un troisième quadrillage. Le mode nuit de Renew a
   été réglé exprès sur un gris très sombre : on n'y remet pas de dessin.

   ⚠️ TOUT EST DANS UNE COUCHE `fixed` EN z-index NÉGATIF. Rien de ce qui est
   ici ne peut passer devant une donnée, même si le script s'arrête. */
.lp-calque {
  position: absolute;
  inset: -40px 0;                 /* déborde : la dérive ne doit jamais
                                     découvrir un bord */
  pointer-events: none;
  /* La dérive est posée par landing.js (`--lp-derive`, en px). Sans script la
     valeur vaut 0 et la couche est simplement immobile — elle ne dépend de
     rien pour être visible. */
  transform: translate3d(0, calc(var(--lp-derive, 0) * 1px), 0);
  will-change: transform;
}
/* La trame — UN SEMIS DE POINTS, PLUS UN QUADRILLAGE (2026-09-10).
   Jérôme : « je n'aime pas les lignes sur la landing, plutôt une grille de
   points plus ou moins gros et plus ou moins opaques, sans trop être opaque ».
   Les deux `repeating-linear-gradient` d'avant traçaient un papier millimétré
   d'un bord à l'autre de l'écran.

   ⚠️⚠️ TOUS LES POINTS SONT SUR LA MÊME TRAME DE 26 px, ET C'EST LA LEÇON DE
   LA PREMIÈRE VERSION. Elle posait ses trois tailles à des pas et des décalages
   étrangers les uns aux autres (26/52/104 calés sur 13 et 39, plus un second
   plan à 37 px qui DÉRIVAIT par-dessus), en croyant casser la régularité. Le
   résultat, mesuré en capture ×3 : des points tombaient à deux ou trois pixels
   les uns des autres et se lisaient comme des taches doubles, des « 8 »
   éparpillés sur le fond clair. Jérôme, le même jour : « sur le fond blanc les
   points semblent être les uns sur les autres, c'est pas très beau ».

   La variation de taille ne vient donc PAS d'un décalage : elle vient du fait
   qu'un nœud sur trois, puis un nœud sur cinq, reçoit un point plus large AU
   MÊME ENDROIT. Deux points ne peuvent jamais se frôler — ils sont confondus
   ou distants de 26 px, jamais entre les deux.

   Les pas et les décalages doivent donc TOUS être des multiples de 26 :
     · fin    26 px, décalé de 0             → tous les nœuds
     · moyen  78 px (3×26), décalé de 26     → un nœud sur trois
     · gros  130 px (5×26), décalé de 52/78  → un nœud sur cinq
   Toucher l'une de ces six valeurs sans vérifier qu'elle reste un multiple de
   26 ramène les taches doubles.

   ⚠️ L'ordre compte : le PREMIER fond est celui du dessus. Les gros sont donc
   déclarés en premier, pour couvrir le petit point du même nœud au lieu d'en
   laisser dépasser un anneau.

   ⚠️ ET L'OPACITÉ MONTE À .07, alors que les lignes étaient à .03. Ce n'est pas
   une contradiction avec l'avertissement d'alors : un point de 1,1 px tous les
   26 px couvre ~0,2 % de la surface, un trait continu la traverse. À .03 le
   semis ne se voyait plus du tout — vérifié en capture. */
.lp-calque::before {
  content: '';
  position: absolute;
  inset: 0;
  /* Une seule encre, trois transparences : c'est le « plus ou moins opaque »
     demandé. Le mélange avec l'accent reste identique pour les trois, sinon un
     gros point et un petit point ne seraient pas de la même couleur. */
  --lp-encre: color-mix(in srgb, var(--acc, #6D46EC) 38%, #0B1030);
  background-image:
    /* gros, un nœud sur cinq — c'est lui qui donne le « plus ou moins gros » */
    radial-gradient(circle at center,
      color-mix(in srgb, var(--lp-encre) 100%, transparent) 0 3px, transparent 3.4px),
    /* moyen, un nœud sur trois */
    radial-gradient(circle at center,
      color-mix(in srgb, var(--lp-encre) 85%, transparent) 0 1.9px, transparent 2.2px),
    /* fin, tous les nœuds */
    radial-gradient(circle at center,
      color-mix(in srgb, var(--lp-encre) 70%, transparent) 0 1.1px, transparent 1.4px);
  background-size: 130px 130px, 78px 78px, 26px 26px;
  background-position: 52px 78px, 26px 26px, 0 0;
  /* ⚠️ .10, ET LES ALPHAS SE MULTIPLIENT AVEC. L'opacité de l'élément
     s'applique aux trois couches : à .07 avec un fin à 46 %, le petit point
     retombait à .032 — soit l'opacité des ANCIENNES lignes, et il disparaissait.
     Le fin doit rester autour de .07 effectif (.10 × 70 %), c'est la valeur
     mesurée comme lisible. La variation d'opacité demandée est volontairement
     ténue : 70 / 85 / 100 %. */
  opacity: .10;
}

/* ⚠️ IL N'Y A PLUS DE SECOND PLAN, ET C'EST VOULU. `::after` portait un second
   semis qui dérivait horizontalement par-dessus le premier — l'idée était de
   faire de la profondeur avec deux plans de vitesses différentes. Mais deux
   semis qui glissent l'un sur l'autre PRODUISENT les collisions décrites
   ci-dessus, en permanence et à des endroits qui changent au défilement : la
   profondeur ne valait pas la salissure. Le semis garde le mouvement de
   `.lp-calque`, qui dérive verticalement d'un bloc — donc rien n'est figé.
   Ne pas rétablir un plan qui se déplace RELATIVEMENT au semis. */

/* ⚠️ La dérive est un AGRÉMENT, jamais un porteur d'information : sous
   « animations réduites » la couche se fige, et rien n'est perdu. */
@media (prefers-reduced-motion: reduce) {
  .lp-calque { transform: none; }
}

/* ── Le rail et son point ────────────────────────────────────────────────── */

/* ⚠️ DERRIÈRE LE CONTENU, PAS DEVANT. Le rail passait par-dessus les cartes
   et les captures — un trait qui traverse une image la barre. `z-index: 0` le
   met au-dessus du fond de page et sous tout ce qui est écrit ou montré : les
   contenus de la page sont dans le flux et se peignent après. Demandé par
   Jérôme le 2026-08-18. */
.lp-rail-support {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
}
/* ⚠️ PAS AU MILIEU. À 50 %, le trait coupait la page en deux et traversait le
   titre comme les captures. Il est repoussé à droite, dans la bande où vivent
   les captures — il accompagne la lecture au lieu de la barrer. Demandé par
   Jérôme le 2026-08-18.
   C'est aussi la trajectoire par défaut du point : le décaler décale les deux,
   `landing.js` lisant la position réelle du rail. */
.lp-rail {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--lp-rail-x, 66%);
  width: 1px;
  background: linear-gradient(180deg,
    transparent 0%,
    rgba(20, 24, 58, 0.10) 12%,
    rgba(20, 24, 58, 0.10) 88%,
    transparent 100%);
  opacity: 0;
  transition: opacity 400ms ease;
}
.lp-pilote {
  position: absolute;
  top: 0;
  left: 0;
  /* ⚠️ DIAMETRE dans landing.js — les deux ensemble. Le point est dessiné
     GRAND puis réduit en voyage : un calque rastérisé à 10 px et monté en
     scale() pixelisait à l'atterrissage (relevé par Jérôme le 2026-08-18).
     28 px > la plus grande cible (~17 px), on ne fait donc que réduire. */
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--af-accent, #6D46EC);
  opacity: 0;
  will-change: transform;
}
/* Le rail et le point n'existent QUE dans le mode épinglé : en flux, le point
   n'a pas de trajectoire à suivre et resterait un rond immobile en travers de
   la page. */
html.lp-epingle .lp-rail { opacity: 1; }
html.lp-epingle .lp-pilote { opacity: 1; }
/* La marque rend son point INVISIBLE tant que le voyageur peut venir s'y
   poser : deux points au même endroit se verraient. En mode flux, chaque
   marque garde le sien.

   ⚠️ `.lp-groupe` AUSSI, pas seulement `.lp-chapitre` (corrigé le 2026-09-01).
   Le groupe final « Et concrètement » est une ÉTAPE du point (cf. la liste
   `etapes` dans landing.js) mais n'est pas un chapitre : il tombait donc hors
   de ce sélecteur, gardait son point fixe, et on en voyait deux — « le point
   est déjà présent ». Les deux listes du script doivent avoir leur pendant
   ici : ce qui reçoit le voyageur cache le sien. */
html.lp-epingle .lp-chapitre .af-marque__point,
html.lp-epingle .lp-groupe .af-marque__point { visibility: hidden; }

/* ── L'ouverture ─────────────────────────────────────────────────────────── */

.lp-ouverture {
  position: relative;
  z-index: 1;
  min-height: 100vh;
}
/* 200vh (et non 280) : la course utile est `height - 100vh`, et la scène a
   fini de se déployer à 74 % de cette course (cf. `reglerLEventail`). À 280vh
   elle restait donc immobile pendant 133vh avant de sortir — un écran et demi
   de défilement sans rien à voir. Mesuré le 2026-09-02. */
html.lp-epingle .lp-ouverture { height: 200vh; }

.lp-scene {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  padding: 0;
}
html.lp-epingle .lp-scene {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
}

/* ── LE PLATEAU ───────────────────────────────────────────────────────────
   Plein cadre, en retrait de 12 px des quatre bords : les valeurs sont
   RELEVÉES sur letters.app (panneau 1416 px de large dans une fenêtre de
   1440, rayon 28 px en haut et 48 px en bas, dégradé vertical du plus foncé
   vers le plus clair). Demandé par Jérôme le 2026-08-18 : « le cadre de
   couleur doit prendre toute la largeur ».

   Le dégradé descend du violet profond (titre en blanc dessus, 8,9:1) vers
   la teinte du canevas : le produit posé en bas se détache alors sur du
   clair, comme l'enveloppe de letters.app. */
.lp-plaque {
  position: absolute;
  inset: 12px;
  border-radius: 28px 28px 48px 48px;
  /* ⚠️ CONSTRUIT SUR L'ACCENT, PAS SUR LE VIOLET EN DUR. La landing bascule
     entre deux styles : avec des jetons --af-v-* figés, le panneau restait
     violet sous TermOS, dont l'accent est vert. Les quatre arrêts se
     déduisent de --acc, et le dernier rejoint le fond de page — le panneau
     se fond dans la page au lieu de s'y découper. */
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--acc, #6D46EC) 45%, #0B1030) 0%,
    var(--acc, #6D46EC) 38%,
    color-mix(in srgb, var(--acc, #6D46EC) 38%, var(--bg, #F4F1FC)) 72%,
    var(--bg, #F4F1FC) 100%);
  opacity: 1;
  transition: opacity 600ms ease;
  overflow: hidden;
}
/* ⚠️ TERMOS A SON PROPRE PANNEAU. La formule commune part de l'accent et le
   fonce : elle marche pour un violet, pas pour un citron. Mesuré le
   2026-08-18 : le blanc du sous-titre ne rendait plus que 1,61:1 sur le
   citron — illisible. TermOS est un thème SOMBRE ; son panneau est donc
   sombre, traversé d'une lueur citron, et le texte blanc y tient 12:1.
   Ce n'est pas une exception cosmétique : c'est ce que « deux thèmes
   délibérément différents » veut dire. */
/* ⚠️ CE N'EST PLUS UN DÉGRADÉ VERT — 2026-08-19, « le vert est moche, il faut
   plutôt mettre une image un peu technique qui fasse penser au thème ».
   Le panneau porte donc un DESSIN : plan filaire isométrique, cotes, courbes
   de niveau, sur un fond presque noir. Il est composé pour cet emploi — le
   centre et le haut sont volontairement VIDES, c'est là que le titre se pose.
   Le voile par-dessus n'est pas décoratif : il tient le contraste du texte
   quelle que soit la densité du dessin, et le dernier arrêt rejoint le fond
   de page pour que le produit posé en bas se détache sur la page, comme sous
   Renew. */
html[data-design="termos"] .lp-plaque {
  background:
    linear-gradient(180deg,
      rgba(11, 13, 16, .42) 0%,
      rgba(11, 13, 16, .30) 40%,
      color-mix(in srgb, var(--bg) 65%, transparent) 80%,
      var(--bg) 100%),
    url('/static/img/landing/lp-fond-termos.webp') center / cover no-repeat,
    #0B0D10;
}
/* Le grain de particules est fait pour un aplat : posé sur le dessin, il
   ajoute du bruit à du bruit. */
html[data-design="termos"] .lp-plaque::after { display: none; }

/* Le grain du champ : quelques particules, discrètes au point de ne se voir
   qu'en les cherchant. */
.lp-plaque::after {
  content: '';
  position: absolute;
  inset: 0;
  background-image:
    radial-gradient(2px 2px at 14% 24%, rgba(255, 255, 255, .30) 50%, transparent 51%),
    radial-gradient(1.5px 1.5px at 32% 48%, rgba(255, 255, 255, .22) 50%, transparent 51%),
    radial-gradient(2px 2px at 57% 14%, rgba(255, 255, 255, .18) 50%, transparent 51%),
    radial-gradient(1.5px 1.5px at 71% 34%, rgba(255, 255, 255, .26) 50%, transparent 51%),
    radial-gradient(2px 2px at 88% 22%, rgba(255, 255, 255, .20) 50%, transparent 51%),
    radial-gradient(1.5px 1.5px at 44% 8%,  rgba(255, 255, 255, .18) 50%, transparent 51%);
}

/* ── LA TRAME ─────────────────────────────────────────────────────────────
   Demandée le 2026-08-19 : « une fine trame carrée dégradée, dans la couleur
   de la landing page, au tout début ».

   Un quadrillage de 46 px, tracé à 1 px, dans une teinte prise SUR l'accent
   (blanc mêlé de violet) : c'est ce qui la fait tenir à la page plutôt que de
   ressembler à un papier millimétré posé dessus. Comme tout le reste du
   panneau, elle suit l'accent du thème et ne fige aucune couleur.

   ⚠️ ELLE S'EFFACE VERS LE BAS, et c'est tout l'intérêt. Une trame uniforme
   sur un panneau de 100 vh se lit comme une texture d'arrière-plan et entre
   en concurrence avec le titre. Le masque la laisse pleine sur le premier
   tiers — là où l'œil arrive — puis la dissout avant la zone où les captures
   se posent.

   Elle vit sur ::before, donc SOUS le texte (qui est en z-index au-dessus) et
   sous les particules de ::after. Renew seulement : le panneau TermOS porte
   déjà un plan technique, une trame par-dessus ferait deux quadrillages. */
html[data-design="archiflow"] .lp-plaque::before {
  content: '';
  position: absolute;
  inset: 0;
  /* UN SEMIS DE POINTS, PLUS UNE MAILLE (2026-09-10, même demande que pour
     `.lp-calque` : « je n'aime pas les lignes sur la landing »). C'est la
     trame LA PLUS VISIBLE de la page — elle court derrière le titre du héros.
     Le pas de 30 px est conservé (réglé le 2026-08-19 : « plus petite et
     légèrement plus transparente »), seule la forme change.

     ⚠️ Opacité .18 et non .11 : à surface égale un point couvre une fraction
     de ce que couvre un trait. Reprendre .11 tel quel effaçait la trame.

     ⚠️ LES DEUX TAILLES SONT SUR LA MÊME TRAME DE 30 px — même règle qu'au
     `.lp-calque`, et pour la même raison. La première version décalait les
     gros points de 15 px, soit une DEMI-maille : ils tombaient entre les nœuds
     et formaient des paires collées avec les petits. Pas et décalages doivent
     rester des multiples de 30 : 90 = 3×30, décalé de 30/60. Le gros point
     REMPLACE le petit sur un nœud sur trois, il ne se pose jamais à côté.
     Il est déclaré en premier — le premier fond est celui du dessus. */
  background-image:
    radial-gradient(circle at center,
      color-mix(in srgb, #FFFFFF 86%, var(--acc, #6D46EC)) 0 2.6px, transparent 3px),
    radial-gradient(circle at center,
      color-mix(in srgb, #FFFFFF 72%, var(--acc, #6D46EC)) 0 1.5px, transparent 1.8px);
  background-size: 90px 90px, 30px 30px;
  background-position: 30px 60px, 0 0;
  opacity: .18;
  -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 26%, rgba(0,0,0,.45) 52%, transparent 78%);
          mask-image: linear-gradient(180deg, #000 0%, #000 26%, rgba(0,0,0,.45) 52%, transparent 78%);
  pointer-events: none;
}

/* ── LE TEXTE, CENTRÉ ─────────────────────────────────────────────────────
   letters.app empile titre, sous-titre et un bouton, tout centré, dans le
   tiers haut du panneau. Le produit occupe le bas. Les proportions relevées
   (fenêtre 1440 × 900) : titre à 120 px du haut du panneau, sous-titre 28 px
   plus bas, bouton 104 px encore en dessous. */
.lp-ouverture__texte {
  position: relative;
  /* ⚠️ AU-DESSUS DE .lp-eventail (z-index 3). Les boutons et les onglets sont
     des ACTIONS : une capture qui passe devant les rend inatteignables, et
     rien ne le signale. Ils étaient recouverts par l'écran — mesuré. */
  z-index: 4;
  /* ⚠️ LE PLANCHER DE 110 px N'EST PAS UNE MARGE DE CONFORT : c'est la
     capsule d'en-tête. Elle est `fixed`, son bas tombe à 76 px (12 px de
     retrait + 64 px de hauteur), et le titre passait DESSOUS sur toutes les
     tailles en paysage — de 47 px sur un grand écran à 55 px sur un iPad Air.
     Relevé par Jérôme le 2026-09-02 sur iPad Pro.

     ⚠️ ET C'EST LE HAUT DES LETTRES QU'IL FAUT MESURER, PAS LA BOÎTE DU h1.
     Avec `line-height: 0.90`, les lettres DÉBORDENT de leur ligne : elles
     commencent 14 px AU-DESSUS du haut de la boîte. Mesurer la boîte fait
     conclure à un dégagement qu'on n'a pas. 110 = 76 (barre) + 20 (respiration)
     + 14 (le débord).

     Le défaut préexistait — à 7vh le dégagement était déjà de −27 px — mais la
     compaction du 2026-09-02 l'a doublé. La place rendue ici est reprise plus
     bas dans la pile (marges du titre, de l'action et de la surligne) et sur la
     position du produit, pas au titre. */
  padding: max(110px, clamp(30px, 4vh, 52px)) clamp(24px, 5vw, 64px) 0;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
}
/* ⚠️ SANS SERIF ICI. Le titre reprend la graisse et le serrage de
   letters.app : 80 px pour 1440 de large, interligne 0,90 (le titre y tient
   sur deux lignes serrées, pas un paragraphe), tracking -0,04 em. Une serif
   à cette taille et ce serrage se referme sur elle-même. */
/* ⚠️ PLAFONDS TYPOGRAPHIQUES RELEVÉS (2026-09-07) — vaut aussi pour
   `__sous`, `__marque`, `__phrase` et `__texte` plus bas. Les cinq butaient
   entre 1310 et 1430px de viewport : au-delà, la page grandissait et le texte
   restait FIXE. Le plateau était la signature du défaut, pas une intention —
   aucun commentaire ne le défendait, et aucune media query n'existait au-delà
   de 1000px pour prendre le relais.
   Conséquence assumée : la croissance reprend là où elle s'arrêtait, donc
   ENTRE ~1310 ET ~1600px le rendu bouge un peu (mesuré à 1440 : « Pilotage »
   42 → 46px, le titre du hero 80 → 80,6). C'est le prix de la continuité ;
   l'alternative — un palier `min-width: 1600px` — rendait le même écart d'un
   seul coup, en marche d'escalier au redimensionnement. */
.lp-ouverture__titre {
  font-family: var(--af-font, 'Satoshi', sans-serif);
  font-size: clamp(40px, 5.6vw, 104px);
  line-height: 0.90;
  letter-spacing: -0.04em;
  font-weight: 700;
  color: #FFFFFF;
  /* 20 et non 28 : la place reprise au titre finance le dégagement sous la
     capsule d'en-tête (cf. le plancher de `.lp-ouverture__texte`). */
  margin: 0 0 20px;
  max-width: 14ch;
  text-wrap: balance;
}
.lp-ouverture__sous {
  font-size: clamp(15px, 1.25vw, 23px);
  line-height: 1.45;
  color: rgba(255, 255, 255, 0.90);
  /* Marge basse réduite : les boutons qui la suivaient ont disparu, elle
     ouvrait donc un trou entre le texte et le produit. */
  margin: 0 0 18px;
  /* ⚠️ DEUX LIGNES, PAS TROIS (2026-09-01). 46ch coupait la phrase en trois,
     dont une dernière ligne d'un seul mot — « bâtiment. » tout seul. Élargi
     jusqu'à ce qu'elle tienne en deux, et `balance` répartit les deux. */
  max-width: 68ch;
  text-wrap: balance;
}
/* ── LE PRODUIT, ANCRÉ EN BAS ─────────────────────────────────────────────
   Les objets sont posés au bas du panneau et ROGNÉS par son bord — c'est ce
   qui donne la profondeur chez letters.app : on voit le haut de l'écran, le
   reste continue hors champ. `overflow: hidden` vit sur .lp-plaque, mais les
   objets sont au-dessus : c'est .lp-eventail qui les rogne. */
.lp-eventail {
  position: absolute;
  inset: 12px;
  border-radius: 28px 28px 48px 48px;
  pointer-events: none;
  overflow: hidden;
  z-index: 3;
}

.lp-objet {
  position: absolute;
  margin: 0;
  will-change: transform, opacity;
  /* L'arrivée est un fondu : la scène est composée dès p=0 (une entrée
     pilotée par le défilement ouvrait la page sur une dalle vide). */
  transition: opacity .55s ease;
}
.lp-flanc { transition-delay: .08s; }

/* ── L'ÉVENTAIL S'OUVRE ───────────────────────────────────────────────────
   LE moment de la page, et le seul qui soit mis en scène. Avant, les cinq
   chapitres jouaient tous la même apparition et l'ouverture se contentait
   d'un fondu : cinq répétitions du même effet n'en font pas un fort, elles
   l'annulent. Ici la composition FAIT CE QU'ELLE S'APPELLE — l'écran central
   se pose, puis les deux flancs s'écartent de derrière lui.

   ⚠️ ANIMER `transform`, JAMAIS `translate` NI `rotate`. Le script écrit ces
   deux propriétés INDIVIDUELLES à chaque image (dérive au défilement) ; elles
   se composent avec `transform` au lieu de l'écraser. Animer les mêmes
   propriétés que lui ferait clignoter la scène au premier geste.
   La rotation d'entrée s'AJOUTE donc à celle du balisage : un flanc à -11°
   qui part de +6° commence à -5° et s'ouvre jusqu'à -11°.

   ⚠️ PAS DE `fill-mode`. L'animation doit RENDRE LA MAIN au script quand elle
   finit : en `forwards` elle continuerait de battre l'opacité posée en ligne,
   et la scène ne s'effacerait plus en quittant l'ouverture. Sans fill, la
   valeur d'arrivée (opacité 1, transform nul) est exactement celle que le
   script écrit au même instant — la reprise ne se voit pas. */
@keyframes lpEventailCentre {
  from { opacity: 0; transform: translateY(42px) scale(.972); }
  to   { opacity: 1; transform: none; }
}
@keyframes lpEventailFlancG {
  from { opacity: 0; transform: translate(64px, 30px) rotate(6deg) scale(.95); }
  to   { opacity: 1; transform: none; }
}
@keyframes lpEventailFlancD {
  from { opacity: 0; transform: translate(-64px, 30px) rotate(-6deg) scale(.95); }
  to   { opacity: 1; transform: none; }
}
/* Décélération franche (`.16, 1, .3, 1`) : une arrivée sûre d'elle, sans
   rebond. Les durées disent la distance parcourue, pas le goût — le central
   vient de plus loin et de plus bas, il met plus longtemps.

   ⚠️ ET LE `fill-mode` SE MET DANS LE RACCOURCI, PAS DANS UNE RÈGLE À PART.
   Écrit séparément sur `.lp-flanc`, il était battu par le raccourci de
   `.lp-flanc--g` (0,3,0 contre 0,2,0), qui le remet à `none` en silence : les
   flancs seraient restés visibles à leur place finale pendant leur retard,
   puis auraient sauté à leur point de départ pour s'ouvrir. `backwards` les
   tient à l'état initial pendant l'attente. Le central part sans retard et
   n'en a pas besoin — et il ne doit RIEN garder à l'arrivée, donc pas de
   `forwards` non plus. */
.lp-eventail.est-pilote .lp-cadre {
  animation: lpEventailCentre 760ms cubic-bezier(.16, 1, .3, 1) 0ms none;
}
.lp-eventail.est-pilote .lp-flanc--g {
  animation: lpEventailFlancG 700ms cubic-bezier(.16, 1, .3, 1) 180ms backwards;
}
.lp-eventail.est-pilote .lp-flanc--d {
  animation: lpEventailFlancD 700ms cubic-bezier(.16, 1, .3, 1) 260ms backwards;
}

@media (prefers-reduced-motion: reduce) {
  .lp-eventail.est-pilote .lp-cadre,
  .lp-eventail.est-pilote .lp-flanc--g,
  .lp-eventail.est-pilote .lp-flanc--d { animation: none; }
}
/* `height: auto` n'est pas décoratif : les attributs width/height du balisage
   (utiles, ils réservent la place) deviennent des indications de présentation,
   et sans lui les images gardaient leur hauteur d'attribut quelle que soit
   leur largeur — déformation mesurée le 2026-08-18. */
.lp-objet img {
  display: block;
  width: 100%;
  height: auto;
}

/* ── Le visuel suit le STYLE choisi ───────────────────────────────────────
   Chaque capture existe en deux versions. Celle du style courant s'affiche,
   l'autre est retirée du flux. ⚠️ `display`, pas `opacity` : deux images
   superposées en opacité pèsent toutes les deux dans la mise en page, et
   celle du dessous restait sélectionnable et lue par les lecteurs d'écran.
   La version TermOS porte `aria-hidden` dans le balisage pour la même
   raison — le texte de remplacement ne doit être annoncé qu'une fois. */
/* ⚠️ `img.` DANS LE SÉLECTEUR, sinon `.lp-objet img { display: block }` gagne :
   élément + classe (0,1,1) bat une classe seule (0,1,0), et les DEUX versions
   s'affichaient l'une sous l'autre. Vu à l'écran le 2026-08-18. */
img.lp-vue--termos { display: none; }
html[data-design="termos"] img.lp-vue--renew { display: none; }
html[data-design="termos"] img.lp-vue--termos { display: block; }
/* Tant que le script n'a pas pris la main, la scène est effacée : sans ça,
   les objets se posent en travers du titre au premier rendu.

   ⚠️ MAIS SEULEMENT SI QUELQU'UN VIENT LES RÉVÉLER. Mesuré le 2026-09-02 :
   sous « animations réduites », landing.js sort AVANT d'installer quoi que ce
   soit (`if (moinsAnime.matches) return;`), `.est-pilote` n'est donc jamais
   posée — et les trois écrans du produit restaient à `opacity: 0`. La page de
   vente s'ouvrait SANS son produit pour quiconque a coché ce réglage
   d'accessibilité, en silence, depuis le 2026-08-18.

   C'est précisément la règle écrite en tête de ce fichier et de landing.js
   (« une donnée ne doit jamais dépendre d'un script pour être visible ») que
   la règle ci-dessous enfreignait. Elle est maintenant conditionnée à
   `no-preference` : si le script ne doit pas tourner, rien n'est caché. */
@media (prefers-reduced-motion: no-preference) {
  .lp-eventail:not(.est-pilote) .lp-objet { opacity: 0; }
}

/* L'écran central. Il n'a PLUS de monture de navigateur (pastilles +
   adresse) : retirée le 2026-09-01, « ne rajoute pas de bord sur les screen
   comme sur celle du milieu où tu as ajouté l'adresse, il faut pas ». Le
   chrome dessiné ajoutait une deuxième fenêtre autour d'une capture qui en
   montre déjà une — et il faisait du central un objet d'une autre nature que
   ses deux voisins.
   Il reste l'écran DE DEVANT : même traitement que les flancs, ombre plus
   portée. C'est la profondeur qui le distingue, plus une décoration. */
.lp-cadre img {
  border-radius: 16px;
  border: 1px solid rgba(20, 24, 58, .10);
  box-shadow:
    0 48px 100px -36px rgba(24, 14, 66, .45),
    0 16px 34px -20px rgba(24, 14, 66, .28);
}

/* Les écrans de flanc. Ils ne portent pas de chrome de navigateur : le cadre
   central est LE produit, eux ne sont là que pour donner de la profondeur —
   deux pages de plus, aperçues de biais. D'où le rayon simple et l'ombre plus
   basse que celle du cadre : ils sont derrière, ils doivent le paraître. */
.lp-flanc img {
  border-radius: 14px;
  border: 1px solid rgba(20, 24, 58, .10);
  box-shadow:
    0 34px 76px -34px rgba(24, 14, 66, .48),
    0 12px 28px -18px rgba(24, 14, 66, .26);
}

/* Les loupes. Le rayon et l'ombre vivent sur l'IMAGE, pas sur la figure :
   l'étiquette déborde du coin, un overflow:hidden sur la figure la couperait. */
/* L'icône est une police : taille imposée, sinon elle prend les 24 px du
   contexte et déborde de sa pastille. */

/* ⚠️ UN SEUL ACCENT SUR LA PAGE, SOUS TERMOS AUSSI. Mesuré le 2026-08-19 :
   `--acc` valait le citron (#A3E635, posé par la landing) pendant que
   `--af-accent` restait le violet des jetons — et le point du mot-symbole, qui
   lit `--af-accent`, restait violet dans une page verte. Même défaut que dans
   l'application, dans l'autre sens. Ici c'est la landing qui fait autorité sur
   `--acc` : on aligne donc `--af-*` dessus. */
html[data-design="termos"] {
  --af-accent: var(--acc);
  --af-accent-hover: color-mix(in srgb, var(--acc) 82%, #000);
  --af-accent-text: var(--acc);
}

/* ── LA SCÈNE SOUS TERMOS ─────────────────────────────────────────────────
   Les captures basculaient déjà (`img.lp-vue--termos`), mais tout ce qui les
   ENTOURE restait dessiné pour Renew : chrome de navigateur blanc cassé,
   pastilles d'étiquette blanches, liserés clairs, coins très arrondis. On
   voyait des écrans TermOS sombres dans une monture Renew.
   Demandé le 2026-08-19 : « change chaque élément et chaque screen quand le
   thème passe à TermOS pour que tout soit unifié ».
   Les valeurs suivent l'identité du thème : encre claire sur panneau sombre,
   angles courts (TermOS est carré), typo mono pour le peu de texte. */
html[data-design="termos"] .lp-cadre {
  background: #16171C;
  border: 1px solid rgba(255, 255, 255, .10);
  border-bottom: 0;
  border-radius: 8px 8px 0 0;
  box-shadow:
    0 48px 100px -36px rgba(0, 0, 0, .70),
    0 16px 34px -20px rgba(0, 0, 0, .55);
}
html[data-design="termos"] .lp-flanc img,
/* ⚠️ LE RAIL SE PERDAIT DANS LA GRILLE DE POINTS DE TERMOS. Signalé par
   Jérôme le 2026-08-31 : « je ne vois pas la ligne de guide du point ».
   MESURÉ avant de corriger, et la première explication était fausse : le
   contraste brut est le MÊME dans les deux thèmes (écart de 20 sur Renew,
   24 sur TermOS). Le trait n'est pas trop pâle — il est noyé dans le semis de
   points, qui donne à l'œil des dizaines d'autres marques de même intensité.
   Sur le fond lisse de Renew, la même ligne se détache seule.
   (Un premier correctif posait une ligne BLANCHE, en croyant TermOS sombre.
   Le fond de la landing y est #FAFAFA : elle aurait été invisible. D'où la
   mesure des pixels plutôt que la lecture d'une capture.)
   Donc : même gris, plus affirmé — 0.20 au lieu de 0.10, en encre NEUTRE
   (TermOS n'a pas le bleu de Renew). Assez pour faire une ligne continue au
   milieu des points, pas assez pour barrer la page. */
html[data-design="termos"] .lp-rail {
  background: linear-gradient(180deg,
    transparent 0%,
    rgba(22, 23, 28, 0.20) 12%,
    rgba(22, 23, 28, 0.20) 88%,
    transparent 100%);
}


/* L'écran est CENTRÉ et débordant par le bas : `top` le pose, le rognage du
   conteneur fait le reste. Les loupes le flanquent, comme les étiquettes
   « Before / After » de letters.app encadrent son enveloppe. */
/* ⚠️ CENTRÉ PAR `margin: auto`, JAMAIS PAR `translate: -50%`. Le script écrit
   `style.translate` à chaque image pour la dérive : une valeur de centrage
   posée là serait écrasée au premier défilement, et l'écran partirait d'un
   demi-écran vers la droite. Mesuré le 2026-08-18. */
/* ⚠️ RESSERRÉS, PAS ÉTALÉS (2026-09-01, choix de Jérôme sur trois options).
   Les flancs partaient à 13,5 vw du centre et penchaient de 9° : trois objets
   séparés, en éventail. Ils viennent maintenant à 9 vw et ne penchent plus que
   de 4° — un seul bloc, dont le central se détache par sa hauteur (63 contre
   67 vh) et par son plan, pas par la distance.
   « Moins d'éventail, plus de bloc. » */
/* ⚠️ PLUS GRANDS, PLUS DE TRAVERS, PLUS HAUT (2026-09-01, sur photo annotée).
   Le resserrement de la veille tenait les trois ensemble mais les rendait
   petits et plats. Les flancs reprennent de l'inclinaison (4° → 11°) et de la
   taille (25 → 33 vw), l'écran central aussi (45 → 52 vw), et l'ensemble monte
   de 10 vh — la place libérée par les deux boutons retirés.
   Ils restent UN BLOC : l'écart au centre ne bouge presque pas (9 → 10 vw),
   et comme ils sont plus larges, ils se chevauchent DAVANTAGE qu'avant. */
/* ⚠️ +3vh sur les TROIS objets le 2026-09-02, jamais sur un seul : c'est
   l'écart entre eux qui fait l'éventail. Le texte a dû descendre pour dégager
   la capsule d'en-tête, le produit descend d'autant. Il n'est pas rapetissé —
   il est rogné un peu plus par le bas du panneau, ce qui est déjà son
   traitement. */
/* ⚠️ PLAFONDS RELEVÉS, RAPPORT CONSERVÉ (2026-09-07). 720 et 470px étaient
   atteints dès ~1450px d'écran : au-delà, le `vw` ne servait plus à rien et
   les trois objets restaient figés pendant que l'écran doublait — mesuré, les
   flancs faisaient 518px à 1440 comme à 2560, soit 36 % de l'écran puis 20 %.
   Les nouveaux plafonds gardent le rapport flanc/cadre de la composition
   (470/720 = 0,653 ; 705/1080 = 0,653) : c'est le même bloc, plus grand, pas
   un éventail réétalé. Le rognage par le bas du panneau augmente avec la
   taille — c'est déjà le traitement voulu de ces objets (cf. plus haut). */
/* ⚠️ UN PLANCHER, PARCE QUE LE `vh` SEUL FAIT MONTER LE PRODUIT SOUS LES
   ONGLETS (2026-09-10, signalé par Jérôme : « les boutons chevauchent les
   images sur un écran plus petit »).

   LA CAUSE EST UN MÉLANGE D'UNITÉS, le même que celui déjà documenté pour le
   portrait, mais dans l'autre sens. Les objets sont posés en `vh` ; la pile de
   texte au-dessus d'eux est en PX ET EN VW — `padding: max(110px, …)`, titre
   en `clamp(40px, 5.6vw, 104px)`, sous-titre, action, onglets. Quand la
   fenêtre RACCOURCIT, `56vh` remonte alors que la pile, elle, ne bouge pas
   d'un pixel : à un moment les deux se croisent. Mesuré avant correctif, écart
   entre le bas des onglets et le haut du cadre :
     1280×650 → −88 px · 1600×760 et 1366×700 → −74 · 1440×780 → −42
     1366×768 → −39 · 1920×900 → −37 · 1280×800 → −10 · 1600×900 → −2
   Un nombre négatif = les onglets sont POSÉS SUR la capture.

   D'OÙ UN PLANCHER EN PX + VW, dans les unités de ce qui le provoque. Le bas
   des onglets suit la largeur, pas la hauteur : relevé à 440 px (1024), 464
   (1280), 496 (1440), 518 (1600), 553 (1920). Soit ≈ 304px + 13vw. Le `min()`
   plafonne à 250px parce que la typographie plafonne AUSSI (le titre bute à
   104px vers 1857px de large) : sans ce plafond, le plancher continuerait de
   descendre sur un écran 4K où le texte, lui, ne descend plus.
   Les 40px de plus tiennent la respiration.

   `max()` et non un palier `@media` : le croisement dépend de la largeur ET de
   la hauteur, deux paliers auraient dû être croisés. Ici, sur un écran haut le
   `vh` gagne et RIEN NE CHANGE (mesuré : 1920×1080 garde ses 605px) ; sur un
   écran court c'est le plancher qui prend la main.

   Le prix est assumé : plus bas = plus rogné par le bas du panneau. C'est déjà
   le traitement voulu de ces objets (cf. le commentaire du PRODUIT plus haut),
   et c'est la seule place disponible sur une fenêtre de 650px de haut. */
.lp-scene { --lp-plancher-objets: calc(344px + min(13vw, 250px)); }
/* Les flancs sont TOURNÉS de ±11° : leur boîte apparente démarre plus haut que
   leur `top` (de largeur/2 × sin 11°, soit ~67px à 1920). Les 40px de plus
   compensent une partie de ce relèvement — le reste est absorbé par la
   respiration commune. */
.lp-cadre       { left: 0; right: 0; margin: 0 auto; top: max(56vh, var(--lp-plancher-objets)); width: min(48vw, 1080px); z-index: 3; }
.lp-flanc--g    { right: calc(50% + 10vw); top: max(66vh, calc(var(--lp-plancher-objets) + 40px)); width: min(33vw, 705px); rotate: -11deg; z-index: 2; }
.lp-flanc--d    { left:  calc(50% + 10vw); top: max(66vh, calc(var(--lp-plancher-objets) + 40px)); width: min(33vw, 705px); rotate:  11deg; z-index: 2; }
/* ⚠️ DERRIÈRE LES TROIS ÉCRANS (z-index 1 < flancs 2 < cadre 3), demandé le
   2026-08-31. Elles étaient DEVANT (4) : une note de bas de page posée sur le
   texte qu'elle annote. Passer dessous fait le travail que l'opacité faisait
   à moitié — d'où le retrait ramené de .72 à .82 : masquées ET pâles, elles
   disparaissaient. Le repli CSS et `data-o` dans le balisage doivent dire la
   MÊME chose (landing.js réécrit l'opacité et gagnerait sur la feuille). */
/* ⚠️ POSITIONS DÉSACCORDÉES À DESSEIN. 78vh/96vh, -4°/+4°, 1vw/1vw : c'était
   un miroir, et un miroir ne se lit pas comme du hasard. Chaque loupe a
   maintenant sa hauteur, son angle et son retrait propres. L'écart vertical
   voulu le 2026-08-19 est PRÉSERVÉ (73 → 99vh, soit plus qu'avant). */
/* ⚠️ `right` RESTE ≥ 1vw : l'étiquette sort du coin de la figure, et à
   -1.5vw on lisait « Échéar ». Le débord porte sur l'IMAGE, jamais sur le mot
   qui la nomme (payé le 2026-08-18). */

/* ⚠️ LES TROIS OBJETS RESTENT SUR MOBILE. Les deux loupes étaient masquées
   sous 1100 px : le téléphone perdait la moitié de la scène. Demandé le
   2026-08-18 — « tout pareil ». Elles sont simplement plus grandes en
   proportion et débordent davantage, ce qui est le principe même de la
   composition (le produit est rogné par le cadre). */
@media (max-width: 1100px) {
  .lp-cadre       { width: min(80vw, 640px); top: max(62vh, var(--lp-plancher-objets)); }
  /* Les flancs se glissent DAVANTAGE derrière le cadre : à cette largeur ils
     n'ont plus la place de s'écarter, ils ne montrent donc qu'une tranche. */
  /* Même resserrement sur écran moyen : 22 vw les envoyait hors champ. */
  .lp-flanc--g    { right: calc(50% + 17vw); top: max(68vh, calc(var(--lp-plancher-objets) + 40px)); width: min(42vw, 300px); }
  .lp-flanc--d    { left:  calc(50% + 17vw); top: max(68vh, calc(var(--lp-plancher-objets) + 40px)); width: min(42vw, 300px); }
}
@media (max-width: 620px) {
  /* ⚠️ 66vh, pas 60 : à 60 il ne restait plus qu'UN pixel entre les onglets de
     style et le haut de l'écran de démonstration (mesuré sur 390 × 844). */
  .lp-cadre       { width: 92vw; top: max(66vh, var(--lp-plancher-objets)); }
  /* ⚠️ LES FLANCS DISPARAISSENT SOUS 620 px, ET C'EST LA SEULE EXCEPTION À
     « tout pareil sur mobile ». Le cadre y prend 92 % de la largeur : un
     écran de flanc n'aurait plus que quelques pixels visibles de chaque côté
     — pas une composition, une écharde. Les deux loupes, elles, restent. */
  .lp-flanc       { display: none; }
  /* Les étiquettes suivent la taille de leur loupe, sinon elles écrasent
     l'image qu'elles désignent. */
}

.lp-invite {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 0;
  font-size: 13px;
  color: var(--af-text-3, #666D93);
  text-decoration: none;
}
.lp-invite__fleche {
  /* ⚠️ LE CERCLE DOIT ÊTRE PLUS GRAND QUE SON ICÔNE. Il faisait 22 px pour une
     icône de 24 : elle débordait de tous les côtés, et le décentrage de 2 px
     mesuré n'était que la conséquence de ce débordement. Relevé par Jérôme le
     2026-08-18. 26 px de cercle pour 15 px d'icône laissent une marge égale
     tout autour. */
  width: 26px; height: 26px;
  flex: none;
  border-radius: 50%;
  display: grid; place-items: center;
  border: 1px solid var(--af-border-strong, rgba(20,24,58,.14));
  animation: lp-descend 1.8s ease-in-out infinite;
}
/* L'icône est une police : sans taille ni interligne imposés, elle prend ceux
   du contexte — 24 px ici — et le cercle ne peut plus la contenir. */
.lp-invite__fleche .lp-ico {
  font-size: 15px;
  line-height: 1;
  width: 15px;
  height: 15px;
  display: block;
}
@keyframes lp-descend {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(4px); }
}
@media (prefers-reduced-motion: reduce) {
  .lp-invite__fleche { animation: none; }
}

/* ── Les chapitres ───────────────────────────────────────────────────────── */

.lp-chapitre {
  position: relative;
  /* Positionné ET empilé : sans `z-index`, une section dans le flux ne passe
     pas forcément devant un élément `fixed`, et le rail réapparaîtrait
     par-dessus les captures. */
  z-index: 1;
  min-height: 100vh;
}
/* La hauteur immobilisée EST la durée de la scène : plus le chapitre est haut,
   plus on a de défilement pour dérouler son contenu.

   ⚠️ 155vh, et non 240 (2026-09-02). La course utile vaut `height - 100vh` ;
   à 240vh elle faisait 140vh, alors que le contenu avait fini d'arriver à 43 %
   de cette course. Les 80vh restants n'animaient plus rien : mesure de la
   surface occupée, écran par écran, 9 écrans sur 19 étaient vides à plus de
   85 %. À 155vh la course fait 55vh, le contenu se pose sur 40vh (le calendrier
   de `reglerBloc` a été retendu dans le même mouvement — les deux vont
   ENSEMBLE) et il reste 15vh de pause avant que le chapitre se décroche. */
html.lp-epingle .lp-chapitre { height: 155vh; }

.lp-chapitre__grille {
  /* Repère de l'indication de défilement (.lp-defiler, posée en absolu au bas
     du chapitre). En mode épinglé la grille est `sticky`, donc déjà un repère ;
     en mode flux elle ne l'était pas, et la flèche allait se caler sur la
     section entière — soit ailleurs. */
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: clamp(24px, 4vw, 64px);
  align-items: center;
  min-height: 100vh;
  padding: 96px 0 56px;
}
/* ⚠️ SÉLECTEUR À DEUX CLASSES, OBLIGATOIREMENT (2026-09-07). La grille est
   AUSSI un `.lp-wrap`, et `.lp-wrap{max-width:var(--lp-max)}` est déclaré
   APRÈS cette feuille dans les deux pages qui la chargent : dans le <style>
   inline de pricing.html (la feuille est liée avant), et dans
   landing-base.css pour /fonctionnalites (_lp_styles.html la charge après).
   À spécificité égale, c'est le dernier qui gagne — un simple
   `.lp-chapitre__grille` serait donc resté à 1180px sans rien signaler. */
.lp-wrap.lp-chapitre__grille { max-width: var(--lp-max-scene, 1180px); }
html.lp-epingle .lp-chapitre__grille {
  position: sticky;
  top: 0;
  height: 100vh;
  padding: 0;
}
/* Un chapitre sur deux inverse texte et capture — sinon la page bat la mesure
   comme un métronome.
   ⚠️ CLASSE EXPLICITE, PAS `nth-child`. Les chapitres ne sont pas des frères
   consécutifs : le rail, l'ouverture et la section mobile comptent aussi. Un
   `nth-child(even)` visait donc autre chose qu'un chapitre sur deux — mesuré,
   les cinq restaient du même côté. */
.lp-chapitre--inverse .lp-chapitre__grille { direction: rtl; }
.lp-chapitre--inverse .lp-chapitre__grille > * { direction: ltr; }

.lp-chapitre__marque {
  display: flex;
  align-items: center;
  font-size: clamp(28px, 3.2vw, 56px);
  margin: 0 0 var(--af-sp-3, 12px);
  color: var(--af-text-1, #14183A);
}
.lp-chapitre__sur {
  font-size: 12px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--af-accent-text, #6D46EC);
  margin: 0 0 var(--af-sp-2, 8px);
}
.lp-chapitre__phrase {
  font-family: var(--af-font-display, 'Playfair Display', Georgia, serif);
  font-size: clamp(20px, 2vw, 38px);
  line-height: 1.25;
  color: var(--af-text-1, #14183A);
  margin: 0 0 var(--af-sp-3, 12px);
  max-width: 24ch;
}
.lp-chapitre__texte {
  /* Le SEUL corps de la landing sans clamp : il restait à 15px sur un écran
     de 2560, dans une colonne qui, elle, s'élargit. Le plancher est l'ancienne
     valeur fixe — rien ne change en dessous de ~1765px de viewport. La borne
     `max-width` reste en `ch` juste dessous : c'est une largeur de LECTURE,
     elle suit la police et la ligne garde ses 46 caractères. */
  font-size: clamp(15px, 0.85vw, 20px);
  line-height: 1.65;
  color: var(--af-text-2, #4A5074);
  margin: 0 0 var(--af-sp-5, 20px);
  max-width: 46ch;
}

.lp-faits {
  display: grid;
  gap: 10px;
  margin: 0 0 var(--af-sp-5, 20px);
  padding: 0;
  list-style: none;
}
.lp-fait {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 14px;
  color: var(--af-text-2, #4A5074);
}
.lp-fait .material-symbols-outlined {
  font-size: 19px;
  color: var(--af-accent-text, #6D46EC);
  flex: none;
  font-variation-settings: 'wght' 300, 'opsz' 20;
}

/* ⚠️ Le cadre, la bordure et l'ombre ont DÉMÉNAGÉ sur `.lp-feuille`
   (2026-08-19). Deux captures posées de biais ne peuvent pas vivre dans un
   conteneur `overflow:hidden` : il leur couperait les coins qui dépassent.
   Ce conteneur ne fait plus que réserver la place. */
.lp-chapitre__vue {
  margin: 0;
  background: none;
}

/* ── Deux captures posées comme deux feuilles sur un bureau ──────────────
   Demande du 2026-08-19 : « de biais, qui se touchent légèrement, et pas au
   même niveau ». D'où trois écarts, et pas un seul :
     · l'inclinaison  — chaque feuille a la sienne, en sens contraire ;
     · la hauteur     — l'arrière remonte, l'avant descend ;
     · la profondeur  — l'avant recouvre l'arrière d'un tiers environ.
   Le conteneur garde une hauteur propre (padding-bottom en pourcentage) :
   les deux feuilles sont absolues, sans quoi le chapitre s'effondrerait. */
/* Les trois nombres ci-dessous tiennent ensemble — les changer séparément
   décolle les feuilles ou les fait déborder du conteneur. Mesuré à 1600 px,
   conteneur de 614 px de large :
     feuille       = 74 % de 614            = 454 px, soit 285 px de haut
                     (les captures font 16/10)
     conteneur     = 85 % de 614            = 522 px  (padding-bottom)
     décalage      = 45 % de 522            = 235 px
                     ⚠️ un `top` en pourcentage se calcule sur la HAUTEUR du
                     conteneur, pas sur sa largeur — c'est ce qui a fait
                     recouvrir les feuilles à 31 % au premier essai.
     recouvrement  = (285 − 235) / 285      = 17 %  → « elles se touchent »
   Tout est proportionnel à la largeur : les rapports tiennent à toute taille. */
/* ── LES VIGNETTES VIVANTES ───────────────────────────────────────────────
   Le seul endroit de la page où une donnée BOUGE vraiment. Les captures sont
   des WebP : leurs chiffres sont des pixels. Ici tout est du texte et du SVG.

   Elles se posent dans la colonne de texte, entre les faits et le bouton —
   c'est-à-dire dans le bas du chapitre, qui était vide. Ce n'est pas un
   hasard : la mesure d'encre du 2026-09-02 montrait que la moitié basse des
   chapitres ne portait rien.

   ⚠️ CE N'EST PAS UNE CARTE, et ça ne doit pas le devenir. `PRODUCT.md`
   proscrit « cards everywhere » et la tuile KPI répétée. Pas de fond plein,
   pas d'ombre portée : un filet, un fond à peine teinté, et le chiffre. */
.lp-vignette {
  display: flex;
  align-items: center;
  gap: 16px;
  margin: 0 0 var(--af-sp-5, 20px);
  padding: 14px 18px;
  max-width: 400px;
  border: 1px solid color-mix(in srgb, var(--acc, #6D46EC) 16%, transparent);
  border-radius: var(--radius-block, 14px);
  background: color-mix(in srgb, var(--af-surface, #fff) 62%, transparent);
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
}
.lp-vignette__quoi {
  display: block;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--af-text-3, #6B7191);
}
.lp-vignette__note {
  display: block;
  margin-top: 3px;
  font-size: 12px;
  color: var(--af-text-3, #6B7191);
}
.lp-vignette__valeur {
  margin: 2px 0 0;
  font-size: clamp(22px, 2.2vw, 30px);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--af-text-1, #171A2E);
  /* ⚠️ Les chiffres ne doivent pas CHANGER DE LARGEUR en défilant : sans
     `tabular-nums`, le texte autour sursaute à chaque image. */
  font-variant-numeric: tabular-nums;
}

/* ── La variante ANNEAU ── */
.lp-vignette__anneau { position: relative; flex: none; width: 56px; height: 56px; }
.lp-vignette__anneau svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.lp-vignette__piste,
.lp-vignette__arc {
  fill: none;
  stroke-width: 5;
  stroke-linecap: round;
}
.lp-vignette__piste { stroke: color-mix(in srgb, var(--acc, #6D46EC) 15%, transparent); }
/* ⚠️ L'ARC EST DESSINÉ COMPLET PAR DÉFAUT. `--arc` est le retrait qui laisse
   voir le pourcentage ; il est posé dans le balisage, calculé côté serveur.
   Sans script, l'anneau montre donc déjà la bonne valeur — l'animation ne
   fait que le REDESSINER, elle ne le révèle pas. */
.lp-vignette__arc {
  stroke: var(--acc, #6D46EC);
  stroke-dasharray: 138.23;
  stroke-dashoffset: var(--arc, 0);
}
.lp-vignette__pc {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 13px;
  font-weight: 700;
  color: var(--af-text-1, #171A2E);
  font-variant-numeric: tabular-nums;
}
.lp-vignette__legende { display: block; min-width: 0; }
.lp-vignette--anneau .lp-vignette__quoi { text-transform: none; letter-spacing: 0;
  font-size: 13.5px; color: var(--af-text-1, #171A2E); }

/* ── La variante COURBE ── */
.lp-vignette--courbe { display: block; max-width: 340px; }
.lp-vignette__trace {
  display: block;
  width: 100%;
  height: 46px;
  margin: 8px 0 4px;
  overflow: visible;
}
.lp-vignette__trace path {
  fill: none;
  stroke: var(--acc, #6D46EC);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ── La variante BARRE ── */
.lp-vignette--barre { display: block; max-width: 340px; }
.lp-vignette__tete {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.lp-vignette__pourcent {
  font-size: 20px;
  font-weight: 700;
  color: var(--af-text-1, #171A2E);
  font-variant-numeric: tabular-nums;
}
.lp-vignette__jauge {
  height: 6px;
  margin: 9px 0 6px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--acc, #6D46EC) 14%, transparent);
  overflow: hidden;
}
/* ⚠️ `transform: scaleX`, PAS `width`. Animer une largeur fait recalculer la
   mise en page à chaque image ; une transformation ne touche qu'au dessin.
   L'origine à gauche fait partir la jauge du bon côté. */
.lp-vignette__jauge i {
  display: block;
  height: 100%;
  width: var(--jauge, 0%);
  border-radius: inherit;
  background: var(--acc, #6D46EC);
  transform-origin: left center;
}

/* ── La variante MONTANT ── */
.lp-vignette--montant { justify-content: space-between; }
.lp-vignette__pastille {
  flex: none;
  align-self: flex-start;
  padding: 4px 10px;
  border-radius: var(--r-pill, 999px);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .03em;
  /* Statut, donc couleur de statut : `--ok` ne suit JAMAIS l'accent
     (DESIGN.md). Une relance partie est une bonne nouvelle. */
  color: var(--ok, #10B981);
  background: color-mix(in srgb, var(--ok, #10B981) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--ok, #10B981) 26%, transparent);
}

/* ── La variante TAUX ── */
.lp-vignette--taux { justify-content: space-between; }
.lp-vignette__jetons {
  display: flex;
  flex: none;
  align-self: flex-end;
  gap: 4px;
  padding-bottom: 3px;
}
.lp-vignette__jetons i {
  width: 5px;
  height: 20px;
  border-radius: 3px;
  background: var(--acc, #6D46EC);
}

/* ── Ce qui se joue, une fois ──
   L'anneau part de zéro et remonte à sa valeur ; la courbe se trace de gauche
   à droite. Décélération franche, la même que l'ouverture (`.16, 1, .3, 1`) :
   la page n'a qu'un vocabulaire de mouvement.
   ⚠️ Aucune de ces deux animations n'a de `fill-mode` : à la fin, l'élément
   retrouve l'état du balisage — complet et juste. */
@keyframes lpArcSeRemplit { from { stroke-dashoffset: 138.23; } }
@keyframes lpCourbeSeTrace { from { stroke-dashoffset: 620; } }
@keyframes lpJaugeSeRemplit { from { transform: scaleX(0); } }
@keyframes lpJetonSAllume { from { opacity: .18; transform: scaleY(.4); } }

.lp-vignette.est-jouee .lp-vignette__arc {
  animation: lpArcSeRemplit 1000ms cubic-bezier(.16, 1, .3, 1);
}
.lp-vignette.est-jouee .lp-vignette__trace path {
  /* 620 dépasse la longueur du tracé : un tiret plus long que le chemin
     garantit qu'il part entièrement caché, quelle que soit la largeur rendue. */
  stroke-dasharray: 620;
  animation: lpCourbeSeTrace 1100ms cubic-bezier(.16, 1, .3, 1);
}

.lp-vignette.est-jouee .lp-vignette__jauge i {
  animation: lpJaugeSeRemplit 900ms cubic-bezier(.16, 1, .3, 1);
}
/* Les jetons s'allument l'un après l'autre — c'est une LISTE, et une liste a
   le droit à sa cascade. Le retard total est plafonné : `--rang` monte, mais
   six jetons à 55 ms ne font que 275 ms, pas une attente. */
.lp-vignette.est-jouee .lp-vignette__jetons i {
  animation: lpJetonSAllume 420ms cubic-bezier(.16, 1, .3, 1) backwards;
  animation-delay: calc(var(--rang, 0) * 55ms);
}

@media (prefers-reduced-motion: reduce) {
  .lp-vignette.est-jouee .lp-vignette__arc,
  .lp-vignette.est-jouee .lp-vignette__jauge i,
  .lp-vignette.est-jouee .lp-vignette__jetons i { animation: none; }
  .lp-vignette.est-jouee .lp-vignette__trace path {
    animation: none;
    stroke-dasharray: none;
  }
}

.lp-feuilles {
  position: relative;
  width: 100%;
  padding-bottom: 85%;
}
.lp-feuille {
  position: absolute;
  margin: 0;
  width: 74%;
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid var(--af-border, rgba(20,24,58,.08));
  background: var(--af-surface, #fff);
  /* Ombre NEUTRE et portée : une feuille sur un bureau projette une ombre,
     elle ne rayonne pas. */
  box-shadow: 0 26px 60px -26px rgba(11, 16, 48, 0.45),
              0 2px 6px rgba(11, 16, 48, 0.06);
}
.lp-feuille--arriere {
  top: 0;
  left: 0;
  rotate: -2.4deg;
  z-index: 1;
}
.lp-feuille--avant {
  top: 45%;
  right: 0;
  rotate: 2deg;
  z-index: 2;
}

/* Sous 900 px la colonne devient étroite : deux feuilles décalées y seraient
   deux timbres. On les remet l'une sous l'autre, à plat. */
@media (max-width: 900px) {
  .lp-feuilles { padding-bottom: 0; display: grid; gap: 14px; }
  .lp-feuille { position: static; width: 100%; rotate: none; }
}
/* ⚠️ CLASSE PROPRE, ET C'EST DÉLIBÉRÉ. La macro rendait ses images en
   `.lp-shot__img`, dont la règle historique est
   `position:absolute; inset:0; display:none` — pensée pour empiler six
   captures et n'en montrer qu'une. Reprise ici, elle sortait l'image du flux
   et la figure retombait à 2 px de haut (mesuré). Une capture qui n'est plus
   empilée n'a rien à faire dans cette classe. */
.lp-vue__img {
  display: block;
  width: 100%;
  height: auto;
}

/* ══ ÉCRAN EN PORTRAIT — la page cesse de s'étirer ═══════════════════════
   Depuis que le site s'ouvre en version ordinateur (viewport figé à 1280 px,
   cf. templates/base.html), un téléphone tenu debout compose la page dans une
   fenêtre de 1280 × 2771 : deux fois plus haute que large. Toutes les sections
   font 100 vh, donc 2771 px — pour un contenu qui en occupe 528. Mesuré :
   2242 px de vide dans un chapitre. C'est le « trop allongé » du 2026-08-19.

   On ne touche NI au viewport figé, NI à la mise en scène épinglée (décision
   du 2026-08-18 : le téléphone voit la même chose que le bureau). On change
   seulement la DISPOSITION quand la fenêtre est plus haute que large :
     · le chapitre passe sur UNE colonne — texte au-dessus, captures dessous —
       et les captures prennent toute la largeur : le contenu grandit au lieu
       de flotter au milieu ;
     · ce qui reste de vide est réparti en HAUT ET EN BAS d'un bloc centré,
       pas accumulé d'un seul côté : une respiration se lit comme une
       intention, un trou comme un bug ;
     · dans l'ouverture, le texte descend et le produit remonte — ils étaient
       à 120 px et à 1745 px l'un de l'autre.

   Seuil : 4/5. Un écran d'ordinateur n'est jamais aussi haut que large ;
   une tablette debout (1280 × 1707, soit 0,75) l'est, et en profite. */
@media (max-aspect-ratio: 4/5) {
  .lp-chapitre__grille {
    grid-template-columns: minmax(0, 1fr);
    /* CENTRÉ, pas `space-evenly` : réparti, le vide se glissait ENTRE le texte
       et les captures et les séparait de 800 px — les deux ne se lisaient plus
       comme un même chapitre. Centré, le bloc reste d'un seul tenant et la
       respiration part en haut et en bas. */
    align-content: center;
    gap: clamp(28px, 4vh, 64px);
    padding: 6vh 0;
  }
  /* La capture repasse SOUS le texte quel que soit le côté : sur une colonne,
     `direction: rtl` n'inverse plus rien d'utile — il ne ferait que renvoyer
     un chapitre sur deux à l'envers. */
  .lp-chapitre--inverse .lp-chapitre__grille { direction: ltr; }
  .lp-chapitre__texte-col { max-width: 62ch; margin: 0 auto; text-align: center; }
  /* ⚠️ CENTRER LA LISTE, PAS CHAQUE PUCE (corrigé le 2026-09-02).
     `justify-items: center` centrait chaque puce INDIVIDUELLEMENT dans sa
     rangée : trois puces de longueurs différentes démarraient donc à trois
     abscisses différentes, et leurs trois icônes formaient un escalier. Mesuré
     sur mobile : icônes à 88, 66 et 133 px du bord.
     La liste est maintenant une boîte centrée dont les puces s'alignent toutes
     à gauche — une seule colonne d'icônes. `max-width` et non `width` : si la
     puce la plus large dépasse la place disponible, la boîte se réduit et le
     texte passe à la ligne, au lieu de déborder. */
  .lp-faits { justify-items: start; max-width: fit-content; margin-inline: auto; }
  .lp-fait { text-align: left; }
  /* Le texte grossit, pour deux raisons qui vont ensemble : il occupe la
     hauteur disponible, et il RESTE LISIBLE — la page est montrée à environ
     30 % sur un téléphone, où un titre de 41 px n'en fait plus que 12. */
  .lp-chapitre__marque { font-size: clamp(42px, 4.6vw, 62px); }
  .lp-chapitre__phrase { font-size: clamp(26px, 2.8vw, 38px); }
  .lp-chapitre__texte  { font-size: clamp(17px, 1.6vw, 22px); }
  .lp-fait { font-size: clamp(16px, 1.4vw, 20px); }
  .lp-ouverture__titre { font-size: clamp(56px, 7vw, 96px); }
  .lp-ouverture__sous  { font-size: clamp(18px, 1.8vw, 24px); }

  /* ── L'OUVERTURE : LE PRODUIT S'ACCROCHE AU BAS ────────────────────────
     « En portrait les éléments du début semblent flotter au milieu, alors
     qu'en paysage ils sont bien en place » — 2026-08-19.

     Le constat est juste, et la cause est un mélange d'unités. Les objets
     sont POSITIONNÉS en vh (top: 63vh) mais DIMENSIONNÉS en vw. Sur un écran
     large les deux se compensent : l'objet démarre bas et son bas dépasse le
     cadre, donc il est ROGNÉ — c'est ce rognage qui l'ancre, c'est le
     principe de la composition (letters.app). Sur un écran deux fois plus
     haut que large, 63 vh fait 1745 px pendant que l'objet n'en fait que
     600 : il s'arrête loin au-dessus du bord, plus rien ne le rogne, et il
     flotte.

     On cesse donc de le poser par le haut : en portrait il s'accroche au BAS
     (`bottom`, en vw — la même unité que sa taille), avec un dépassement qui
     reproduit le rognage du paysage. Les proportions relatives sont
     conservées : le cadre au-dessus, les flancs plus bas, les loupes encore
     en dessous et les plus rognées.

     Le texte, lui, descend au tiers : collé en haut d'un écran de 2771 px, il
     laissait mille pixels de vide sous lui. */
  /* 22vh et non 33 (2026-09-02) : même cause qu'en paysage, en pire. Mesuré en
     390×844, la pile de texte finissait à 805 px alors que la capture commence
     à 627 — le bouton d'action lui-même était recouvert, donc incliquable, et
     rien ne le signalait. */
  .lp-ouverture__texte { padding-top: 15vh; }
  /* Les objets grossissent aussi : plus larges, ils sont plus hauts, donc ils
     remontent vers le texte. C'est le second levier contre le vide — mesuré,
     l'écart texte↔produit tombe de 1147 px à moins de 700. */
  .lp-cadre       { top: auto; bottom: -5vw;  width: min(92vw, 1160px); }
  .lp-flanc--g    { top: auto; bottom: -8vw; right: calc(50% + 24vw); width: min(42vw, 520px); }
  .lp-flanc--d    { top: auto; bottom: -8vw; left:  calc(50% + 24vw); width: min(42vw, 520px); }
}

/* ── « ça défile » ───────────────────────────────────────────────────────
   Demandé le 2026-08-19 : une indication de défilement à chaque section, pour
   que le visiteur comprenne.

   Elle en a besoin plus qu'une page ordinaire : en mode épinglé, un chapitre
   s'immobilise le temps qu'on le traverse. Quelqu'un qui arrive dessus voit
   une page qui ne bouge pas et peut croire qu'elle est finie — c'est
   exactement le malentendu que ce chevron lève.

   Deux emplacements, et la raison est concrète :
     · dans les chapitres, en bas au centre, où la place est libre ;
     · dans l'ouverture (`--flux`), DANS LE FLUX sous les onglets de style :
       en bas, il se poserait sur l'écran de démonstration.

   ⚠️ DÉCORATIF, DONC INERTE. `aria-hidden` dans le balisage et
   `pointer-events: none` ici : ce n'est pas un bouton, et rien ne doit
   laisser croire qu'on peut cliquer dessus. L'information « il y a une suite »
   reste portée par la page elle-même, pas par cette flèche. */
.lp-defiler {
  position: absolute;
  left: 50%;
  bottom: clamp(14px, 3vh, 34px);
  translate: -50% 0;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--af-text-1, #14183A) 14%, transparent);
  color: var(--af-text-2, #4A5074);
  background: color-mix(in srgb, var(--af-surface, #fff) 62%, transparent);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  pointer-events: none;
  animation: lpDefiler 2s cubic-bezier(.4, 0, .2, 1) infinite;
}
.lp-defiler .lp-ico { font-size: 22px; line-height: 1; }

/* Dans l'ouverture, la flèche est posée sur le panneau violet : elle y passe
   en blanc, comme tout ce qui s'écrit dessus. Et elle reste dans le flux —
   d'où le retour à `position: static`. */
/* ⚠️ PLUS PETITE, ET SERRÉE SOUS LES ONGLETS. Mesuré à 1440 × 900 : entre le
   bas des onglets de style (536 px) et le haut de l'écran de démonstration
   (579 px), il n'y a que 43 px. À 38 px et 22 px de marge, la flèche se posait
   sur le bord du cadre — elle avait l'air d'un bouton de l'écran. À 30 px et
   8 px, elle tient dans le violet. */
.lp-defiler--flux {
  position: static;
  translate: none;
  margin-top: 8px;
  width: 30px;
  height: 30px;
  border-color: rgba(255, 255, 255, .30);
  background: rgba(255, 255, 255, .12);
  color: #FFFFFF;
}
.lp-defiler--flux .lp-ico { font-size: 18px; }

@keyframes lpDefiler {
  0%, 100% { transform: translateY(0);   opacity: .55; }
  50%      { transform: translateY(7px); opacity: 1; }
}

/* Un mouvement perpétuel est le premier à couper quand on demande moins
   d'animation. La flèche reste — c'est elle qui porte le sens. */
@media (prefers-reduced-motion: reduce) {
  .lp-defiler { animation: none; opacity: .8; }
}

/* ── Apparitions ─────────────────────────────────────────────────────────── */
/* ⚠️ SEULEMENT quand quelqu'un est là pour révéler. En mode épinglé, le script
   pose l'opacité en ligne ; en mode flux, c'est l'observateur d'intersection
   qui ajoute `is-la`. Sans script du tout, aucune de ces deux règles ne
   s'applique et la page reste entière. */
html.lp-epingle .lp-revele { opacity: 0; }

html:not(.lp-epingle) .lp-revele {
  transition: opacity 520ms var(--af-ease-out, cubic-bezier(.16,1,.3,1)),
              transform 520ms var(--af-ease-out, cubic-bezier(.16,1,.3,1));
}
html:not(.lp-epingle) .lp-revele.is-la { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html:not(.lp-epingle) .lp-revele { opacity: 1 !important; transform: none !important; }
}

/* ── Sous 900 px : plus d'épinglage, tout se lit à la suite ──────────────── */

/* ⚠️ CE BLOC N'ANNULE PLUS L'ÉPINGLAGE. Il posait `height: auto !important` et
   `position: static !important` sous 900 px : le téléphone perdait toute la
   mise en scène — panneau écrasé à la hauteur du texte, produit hors cadre,
   point voyageur supprimé. Jérôme a demandé le 2026-08-18 que le mobile soit
   IDENTIQUE. On ADAPTE donc les proportions au lieu de tout défaire.

   ⚠️ Ne pas y remettre `!important` : c'est ce qui rendait la règle
   imbattable depuis la feuille, et le défaut invisible au diagnostic. */
@media (max-width: 900px) {
  /* Une colonne : côte à côte, texte et capture seraient illisibles. */
  .lp-chapitre__grille { grid-template-columns: 1fr; direction: ltr; }
  /* ⚠️ PLUS DE HAUTEUR ÉPINGLÉE ICI (2026-09-02). Sous 900px le mode épinglé
     n'est plus installé du tout (cf. `assezLarge` dans landing.js) : ces deux
     règles ne s'appliqueraient jamais. Elles sont retirées plutôt que laissées
     mortes — une valeur qui ne sert plus finit toujours par être lue comme une
     valeur qui sert. */
}

/* ═══════════════════════════════════════════════════════════════════════════
   LE GROUPE FINAL — tarifs, questions, contact
   ═══════════════════════════════════════════════════════════════════════════ */

.lp-groupe {
  position: relative;
  z-index: 1;
}
.lp-groupe__grille {
  display: grid;
  grid-template-columns: minmax(0, 300px) minmax(0, 1fr);
  gap: clamp(24px, 4vw, 64px);
  align-items: start;
  padding: 80px 24px 40px;
}
/* La colonne d'annonce reste en place pendant qu'on parcourt les trois blocs.
   ⚠️ `sticky`, pas `fixed` : elle doit s'arrêter avec le groupe, sinon elle
   traverse le pied de page. */
.lp-groupe__aside {
  position: sticky;
  top: 116px;
}
.lp-groupe__marque {
  display: flex;
  align-items: center;
  font-size: clamp(26px, 2.8vw, 36px);
  color: var(--af-text-1, #14183A);
  margin: 0 0 var(--af-sp-3, 12px);
}
.lp-groupe__texte {
  font-size: 15px;
  line-height: 1.65;
  color: var(--af-text-2, #4A5074);
  margin: 0 0 var(--af-sp-5, 20px);
  max-width: 34ch;
}
.lp-groupe__nav { display: grid; gap: 4px; }
.lp-groupe__nav a {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border-radius: 10px;
  font-size: 14px;
  color: var(--af-text-2, #4A5074);
  text-decoration: none;
  transition: background 140ms ease, color 140ms ease;
}
.lp-groupe__nav a:hover {
  background: var(--af-accent-soft, rgba(109,70,236,.08));
  color: var(--af-accent-text, #6D46EC);
}
.lp-groupe__nav .lp-ico { font-size: 18px; }

/* Les trois blocs perdent leurs bandes de fond et leur largeur propre : c'est
   la grille du groupe qui les tient désormais. Sans ça, chacun reprenait toute
   la largeur de la page et sortait de la colonne. */
.lp-groupe__corps > .lp-section { padding-left: 0; padding-right: 0; max-width: none; }
.lp-groupe__corps > .lp-band { background: none; border: 0; }
.lp-groupe__corps .lp-section-head { text-align: left; }
.lp-groupe__corps .lp-lead { margin-left: 0; }
/* ⚠️ DEUX PAR DEUX, PAS QUATRE DE FRONT. La colonne fait ~770 px : quatre
   cartes y tombaient à 180 px et les libellés se cassaient en trois lignes
   (« Tout de / Starter , plus / : »). Mesuré à l'écran le 2026-08-18. */
.lp-groupe__corps .lp-plans { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 700px) {
  .lp-groupe__corps .lp-plans { grid-template-columns: 1fr; }
}

@media (max-width: 900px) {
  .lp-groupe__grille { grid-template-columns: 1fr; padding: 48px 20px 24px; }
  .lp-groupe__aside { position: static; }
  .lp-groupe__nav { grid-auto-flow: column; overflow-x: auto; }
}
