/*
 * LA LANDING DU TUNNEL.
 *
 * Sortie telle quelle de la maquette : on ne retouche pas le style ici,
 * on le deplace. Toute correction visuelle se fait dans ce fichier, pas
 * dans le gabarit, pour que la page reste cachable.
 */

/* Tout ce qui suit est releve dans public/css/{jetons,portal,vitrine}.css.
       Les blocs existants sont repris a l'identique ; les blocs nouveaux
       empruntent leur vocabulaire au lieu d'en inventer un. */
    :root {
      --lv-large: 1240px; --lv-marge: 36px; --lv-rythme: 80px; --lv-ecart: 52px;
      --lv-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
      --white-rgb: 255, 255, 255; --black-rgb: 0, 0, 0;
      --surface-sombre: #0a0f1a; --surface-sombre-rgb: 10, 15, 26;
      --texte-sur-sombre: rgba(255, 255, 255, 0.94);
      --texte-discret-sur-sombre: rgba(255, 255, 255, 0.68);
      /* L'ENCRE SOURDE, MESUREE ET NON CHOISIE A L'OEIL. Sur `--surface-sombre`,
         0,42 rendait 4,09 pour un seuil de 4,5, sur du texte de 10 et 12,5 px.
         0,45 passerait d'un centieme et retomberait au premier ajustement de
         fond ; 0,47 rend 4,84. Elle ne sert QUE d'encre : les voiles de fond a
         0,42 gardent la leur, ils ne font pas le meme travail. */
      --lv-mention: rgba(var(--white-rgb), 0.47);
      --slate-mid: #1e293b;
      --portal-accent-rgb: 0, 207, 234;
      --portal-gold-rgb: 242, 190, 99; --portal-gold-clair-rgb: 255, 232, 159;
      --portal-blue-rgb: 95, 168, 255; --portal-purple-rgb: 169, 139, 255;
      --portal-green-rgb: 110, 214, 148; --portal-orange-rgb: 247, 152, 94;
      --portal-red-rgb: 248, 113, 113; --portal-rose-rgb: 240, 132, 196;
      --portal-anis-rgb: 188, 214, 106;
      /* jetons.css : les six canaux de la demonstration les emploient. */
      --red-mid: #991b1b; --couleur-danger: #ef4444; --amber-bright: #facc15;
      --couleur-succes: #22c55e; --portal-accent: #00cfea; --blue-rgb: 59, 130, 246;
    }
    * { box-sizing: border-box; }
    html, body { margin: 0; background: var(--surface-sombre); }
    body { font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
           color: var(--texte-discret-sur-sombre); -webkit-font-smoothing: antialiased; overflow-x: hidden; }
    a { color: rgb(var(--portal-accent-rgb)); text-decoration: none; }
    a:hover { color: var(--texte-sur-sombre); }

    /* --- Le fond vivant --------------------------------------------------- */
    .lv-fond { position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 0; }
    /* LA GRILLE EST FIXE, donc a la taille de l ECRAN. En absolu sur une
       enveloppe de douze mille pixels, son masque circulaire ne la laissait
       vivre que dans une ellipse au milieu du document : on ne la croisait
       jamais. Alpha 0,055 pour 0,041 d effectif, un filet qu on voit sans le
       regarder. */
    .lv-grille { position: fixed; inset: 0; pointer-events: none; z-index: 0; opacity: 0.55;
      background-image: linear-gradient(rgba(var(--white-rgb),0.036) 1px, transparent 1px),
                        linear-gradient(90deg, rgba(var(--white-rgb),0.036) 1px, transparent 1px);
      background-size: 54px 54px;
      mask-image: radial-gradient(circle at 50% 40%, rgba(0,0,0,1) 20%, transparent 96%);
      -webkit-mask-image: radial-gradient(circle at 50% 40%, rgba(0,0,0,1) 20%, transparent 96%); }
    /* LE DECALAGE EST PORTE PAR LE PLAN, PAS PAR CHAQUE HALO. Quatorze halos
       flous de 658 px promus en calques, c est une vingtaine de mega-octets et
       quatorze flous re-rasterises a chaque image : la page se figeait. Trois
       plans suffisent, et les halos ne portent plus aucune transformation. */
    .lv-plan { position: absolute; inset: 0; translate: 0 var(--lv-parallaxe, 0px); }
    .lv-orbe { position: absolute; width: 68vw; height: 68vw; min-width: 520px; min-height: 520px;
      border-radius: 50%; opacity: 0.46; animation: lvFlotte 18s ease-in-out infinite alternate; }
    /* Les halos du corps de page : plus petits, immobiles, juste assez pour
       qu aucun ecran ne soit du noir plat. Seuls ceux de l ouverture bougent. */
    .lv-orbe--calme { width: 52vw; height: 52vw; min-width: 420px; min-height: 420px;
      opacity: 0.34; animation: none; }
    /* Le grain. Sans lui le noir est une surface morte : c est ce qui donnait
       a la page son air de vide. Fixe, derriere le contenu, jamais sur le texte. */
    .lv-grain { position: fixed; inset: 0; pointer-events: none; z-index: 0; opacity: 0.035;
      background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='170' height='170'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='170' height='170' filter='url(%23g)'/%3E%3C/svg%3E"); }
    /* Une vignette tres douce : les bords de l ecran se ferment, le regard
       reste au centre de la colonne de lecture. */
    .lv-vignette { position: fixed; inset: 0; pointer-events: none; z-index: 0;
      background: radial-gradient(132% 96% at 50% 28%, transparent 66%, rgba(0,0,0,0.13) 100%); }
    @keyframes lvFlotte { from { transform: translate3d(0,0,0) scale(1); } to { transform: translate3d(5vw,-4vh,0) scale(1.12); } }
    @media (prefers-reduced-motion: reduce) {
      .lv-orbe { animation: none; }
      .lv-plan { translate: none; }
    }
    .lv { position: relative; z-index: 1; }

    /* PAS DE RESERVE POUR UN EN-TETE QUI N'EST PAS FIXE.

       `vitrine.css` pose 88 px de padding sur `.lv` : la landing en place a un
       en-tete fixe, et sans cette reserve le contenu passerait dessous. Ici
       l'en-tete est dans le flux, donc la reserve ne reserve rien -- elle
       ouvrait un vide de 88 px entre le bord de la fenetre et le bandeau. */
    .lv { padding-top: 0; }
    @media (max-width: 700px) { .lv { padding-top: 0; } }

    /* --- LES TRAITS QUI COURENT SUR LA GRILLE ------------------------------
       La tete est un arret de degrade, pas une ombre portee : un `box-shadow`
       sur un element anime en permanence se re-rasterise a chaque image, et
       c est exactement ce qu on vient de retirer des halos.
       Les lignes sont des multiples de 54 px, le pas de `.lv-fond::after`. */
    .lv-traits { position: fixed; inset: 0; overflow: hidden; pointer-events: none; z-index: 0; }
    /* La trainee est ecrite UNE fois, ici et pas sur `:root` : un `var()`
       imbrique se resout la ou la variable est DECLAREE, et `--lv-teinte`
       n existe pas sur la racine. Pose la-haut, le degrade devenait
       invalide et les traits rendaient `none`, sans erreur visible. */
    .lv-trait { position: absolute; left: 0; height: 1px; width: var(--lv-long, 220px);
      --lv-trainee: rgba(var(--lv-teinte), 0) 0%, rgba(var(--lv-teinte), 0.02) 34%,
        rgba(var(--lv-teinte), 0.11) 74%, rgba(var(--lv-teinte), 0.18) 92%,
        rgba(var(--white-rgb), 0.17) 99%, rgba(var(--white-rgb), 0) 100%;
      transform: translateX(-320px); opacity: 0;
      animation: lvTrait var(--lv-tempo, 19s) linear infinite var(--lv-attente, 0s);
      background: linear-gradient(90deg, var(--lv-trainee)); }
    /* Le trajet occupe le premier tiers du cycle ; le reste est une attente,
       sinon les traits se suivent sans respiration. */
    @keyframes lvTrait {
      0%   { transform: translateX(-320px); opacity: 0; }
      3%   { opacity: 1; }
      28%  { opacity: 1; }
      33%  { transform: translateX(calc(100vw + 320px)); opacity: 0; }
      100% { transform: translateX(calc(100vw + 320px)); opacity: 0; }
    }
    /* La variante descendante. `width` et `height` s echangent, le degrade
       tourne d un quart de tour, et la course se fait sur la hauteur. */
    .lv-trait--bas { width: 1px; height: var(--lv-long, 220px);
      transform: translateY(-320px); animation-name: lvTraitBas;
      background: linear-gradient(180deg, var(--lv-trainee)); }
    @keyframes lvTraitBas {
      0%   { transform: translateY(-320px); opacity: 0; }
      3%   { opacity: 1; }
      28%  { opacity: 1; }
      33%  { transform: translateY(calc(100vh + 320px)); opacity: 0; }
      100% { transform: translateY(calc(100vh + 320px)); opacity: 0; }
    }
    @media (prefers-reduced-motion: reduce) { .lv-trait { animation: none; opacity: 0; } }

    /* --- Le gabarit -------------------------------------------------------- */
    .lv-conteneur { max-width: var(--lv-large); margin: 0 auto; padding-left: var(--lv-marge); padding-right: var(--lv-marge); }
    .lv-section { padding-top: var(--lv-rythme); padding-bottom: var(--lv-rythme); }
    /* LE SPECTRE DE L APPAREIL, de 4,0e14 a 7,5e14 Hz : du rouge au violet.
       C est la matiere de la therapie, pas un degrade decoratif. Il ouvre
       chaque bande et ferme le bandeau : la page porte sa propre signature. */
    .lv-bande { border-top: 0; background: rgba(var(--white-rgb), 0.035); position: relative; }
    /* Le spectre, ecrit une fois : le rail des bandes et celui du bandeau y
       puisent tous les deux. */
    :root {
      --lv-spectre: linear-gradient(90deg,
        rgba(var(--portal-red-rgb), 0) 0%, rgba(var(--portal-red-rgb), 0.55) 9%,
        rgba(var(--portal-orange-rgb), 0.55) 24%, rgba(var(--portal-anis-rgb), 0.55) 39%,
        rgba(var(--portal-green-rgb), 0.55) 54%, rgba(var(--portal-accent-rgb), 0.55) 68%,
        rgba(var(--portal-blue-rgb), 0.55) 80%, rgba(var(--portal-purple-rgb), 0.55) 92%,
        rgba(var(--portal-purple-rgb), 0) 100%);
      --lv-lueur: linear-gradient(90deg, rgba(var(--portal-red-rgb),0.05) 0%,
        rgba(var(--portal-orange-rgb),0.05) 25%, rgba(var(--portal-green-rgb),0.05) 52%,
        rgba(var(--portal-accent-rgb),0.05) 72%, rgba(var(--portal-purple-rgb),0.05) 100%);
    }
    /* LES DEUX TRAITS D UNE BANDE, portes par un seul pseudo-element : deux
       couches de fond, l une calee en haut, l autre en bas. */
    .lv-bande::before { content: ""; position: absolute; inset: 0; pointer-events: none; opacity: 0.9;
      background-image: var(--lv-spectre), var(--lv-spectre);
      background-size: 100% 2px, 100% 2px;
      background-position: left top, left bottom;
      background-repeat: no-repeat; }
    /* LES DEUX LUEURS, et elles pointent VERS L INTERIEUR : le masque est
       opaque aux deux extremites et transparent au milieu, donc celle du haut
       descend et celle du bas remonte. La bande se lit comme une zone tenue
       entre deux bords, pas comme deux lignes posees la. */
    .lv-bande::after { content: ""; position: absolute; inset: 0; pointer-events: none;
      background-image: var(--lv-lueur), var(--lv-lueur);
      background-size: 100% 90px, 100% 90px;
      background-position: left top, left bottom;
      background-repeat: no-repeat;
      mask-image: linear-gradient(180deg, rgba(0,0,0,1) 0, transparent 90px,
        transparent calc(100% - 90px), rgba(0,0,0,1) 100%);
      -webkit-mask-image: linear-gradient(180deg, rgba(0,0,0,1) 0, transparent 90px,
        transparent calc(100% - 90px), rgba(0,0,0,1) 100%); }
    .lv-entete::after { content: ""; position: absolute; left: 0; right: 0; bottom: -2px; height: 2px;
      background: var(--lv-spectre); opacity: 0.75; }

    /* --- La typographie ---------------------------------------------------- */
    .lv-etiquette { display: block; margin: 0 0 14px; font-family: var(--lv-mono); font-size: 10px;
      font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(var(--portal-gold-rgb), 0.9); }
    .lv-etiquette--sourde { color: var(--lv-mention); }
    .lv-titre { margin: 0 0 16px; font-size: clamp(26px, 2.4vw, 30px); line-height: 1.14; font-weight: 900;
      letter-spacing: -0.01em; color: var(--texte-sur-sombre); text-wrap: balance; }
    /* 62ch FAISAIT 484 PX POUR 853 DISPONIBLES.

       L'ADMIN, LE 30/10/2026 : « les sous-titres comme ca ou des textes sont
       tous compresses », puis « corrige et applique » apres le parcours.

       CE QUE LA MESURE DONNE : le chapeau rendait 68 signes par ligne, donc
       il etait LISIBLE -- la fourchette va de 60 a 75. Ce qui n'allait pas
       est ailleurs : il occupait 39 % de la largeur offerte, et ses coupures
       tombaient mal. Celui de l'offre cassait « vos propres / clients ».

       78ch MONTE A ENVIRON 555 PX, soit 78 signes : juste au-dessus de la
       fourchette, et c'est volontaire pour un chapeau. Ces textes font deux a
       quatre lignes, pas des pavés : la longueur de ligne y compte moins que
       sur un paragraphe long, et les coupures ont de la place pour tomber
       juste. Le corps de texte, lui, ne bouge pas. */
    .lv-chapo { margin: 0 0 26px; max-width: 78ch; font-size: 14.5px; line-height: 1.6; color: var(--texte-discret-sur-sombre); }
    .lv-chapo:last-child { margin-bottom: 0; }
    .lv-chapo--lignes { white-space: pre-line; }

    /* --- Les colonnes ------------------------------------------------------ */
    .lv-duo { display: grid; gap: var(--lv-ecart); align-items: start; }
    @media (min-width: 900px) {
      .lv-duo { grid-template-columns: 1fr 1fr; }
      .lv-duo--hero { grid-template-columns: 1.35fr 1fr; align-items: center; }
      .lv-duo--lecture { grid-template-columns: 1.15fr 0.85fr; }
      .lv-duo--origine { grid-template-columns: 1.08fr 1fr; }
      .lv-duo--demande { grid-template-columns: 0.9fr 1.1fr; }
      .lv-duo--regulation { grid-template-columns: 1.25fr 0.75fr; align-items: center; }
      .lv-duo--serre { gap: 20px; }
    }
    .lv-quatre { display: grid; gap: 16px; grid-template-columns: repeat(2, minmax(0, 1fr)); }
    @media (max-width: 520px) { .lv-quatre { grid-template-columns: minmax(0, 1fr); } }
    /* PAS DE RANGEE DE QUATRE : ELLE N A JAMAIS DE QUOI L ETRE.

       L'ADMIN, LE 30/10/2026 : « la grande majorite des sous-titres comme ca
       ou des textes sont tous compresses », puis « regarde VISUELLEMENT ».

       CE QUE L IMAGE MONTRAIT, et que les chiffres confirment : sur une
       fenetre de 1600 px, les quatre cartes rendaient 280 px chacune et leur
       texte tombait a 36 SIGNES PAR LIGNE. Un paragraphe de 187 signes y
       faisait six lignes hautes de trois mots. Les autres grilles de la page
       sont saines au meme moment : 376 px pour la rangee de trois, 641 pour
       le duo.

       ET LE PALIER NE POUVAIT PAS MIEUX FAIRE : le conteneur plafonne a
       1240 px. Quatre colonnes y valent 280 px sur un ecran de 1000 comme sur
       un ecran de 2000 -- il n'existe aucune largeur ou cette rangee
       respirait. Le palier ne faisait donc que passer de 2x2 a 1x4 sans rien
       gagner.

       EN 2x2 : 612 px par carte, et le meme paragraphe tient en deux lignes
       et demie. C'est la disposition que le bloc a deja en dessous de
       1000 px ; il la garde maintenant partout. */
    /* (le palier a quatre colonnes est retire, voir ci-dessus) */
    .lv-trois { display: grid; gap: 20px; grid-template-columns: minmax(0, 1fr); }
    @media (min-width: 860px) { .lv-trois { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
    @media (min-width: 860px) {
      .lv-trois--tarifs { column-gap: 20px; row-gap: 0; grid-template-rows: repeat(6, auto); }
      .lv-trois--tarifs > .lv-carte { display: grid; grid-template-rows: subgrid; grid-row: span 6;
        row-gap: 0; align-content: start; }
    }
    /* Les trois actions prennent la meme largeur : les bas de carte s alignent
       aussi, et la hierarchie reste portee par la couleur, pas par la taille. */
    .lv-trois--tarifs .lv-actions { display: block; }
    .lv-trois--tarifs .lv-actions > * { display: flex; width: 100%; justify-content: center; }

    /* --- L'ouverture -------------------------------------------------------- */
    .lv-hero { padding-top: 70px; padding-bottom: 60px; }
    .lv-hero__titre { margin: 0 0 20px; font-size: clamp(34px, 4.4vw, 56px); line-height: 1.06; font-weight: 900;
      letter-spacing: -0.015em; color: var(--texte-sur-sombre); text-wrap: balance; }
    /* L EMPHASE DU TITRE D OUVERTURE, reprise de vitrine.css:1070.
       L or plat manquait de corps a 56 px. Un degrade dans le sens de la
       lecture lui donne le comportement d un metal : plus clair la ou la
       lumiere arrive, plus cuivre a la fin du mot. Trois arrets et pas deux,
       sinon le milieu s affaisse. */
    .lv-or { font-style: normal;
      /* Le repli, et il doit rester lisible seul : un navigateur sans
         `background-clip: text` affiche cette couleur et rien d autre. */
      color: rgb(var(--portal-gold-rgb));
      background-image: linear-gradient(100deg, #FBE0A6 0%, #F2BE63 42%, #C08A3C 100%);
      -webkit-background-clip: text; background-clip: text;
      -webkit-text-fill-color: transparent;
      /* Chaque fragment reprend le degrade complet : sans cela, un syntagme
         coupe en fin de ligne recevrait une moitie de degrade sur chaque bout. */
      -webkit-box-decoration-break: clone; box-decoration-break: clone;
      /* Un halo tres bas, juste de quoi decoller les lettres du bleu nuit. */
      filter: drop-shadow(0 0 18px rgba(var(--portal-gold-rgb), 0.28)); }
    /* Le second accent, vitrine.css:1171. Le logo va du cyan a l or ; le titre
       refait ce trajet. Ce n est pas une couleur de plus, c est la meme paire,
       dans le meme ordre. Modificateur de `.lv-or` : il ne change que la rampe
       et le halo. */
    .lv-cyan { color: rgb(var(--portal-accent-rgb));
      background-image: linear-gradient(100deg, #8BE9FF 0%, var(--portal-accent) 42%, #0F8FA6 100%);
      filter: drop-shadow(0 0 18px rgba(var(--portal-accent-rgb), 0.26)); }
    .lv-hero__lead { margin: 0 0 14px; max-width: 56ch; font-size: 16px; line-height: 1.58; color: rgba(var(--white-rgb), 0.82); }
    .lv-hero__precision { margin: 0 0 28px; max-width: 56ch; font-size: 14.5px; line-height: 1.6; color: var(--texte-discret-sur-sombre); }
    .lv-actions { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; }
    /* La ligne de reassurance sous un appel a l action. A 12,5 px c est du
       petit texte : le seuil est 4,5:1, et 0,46 tient 4,66:1 sur notre sol.
       0,44 tombe a 4,39, donc c est le plancher, pas un choix d oeil. */
    /* 48ch FAISAIT 323 PX, ET LA NOTE EN AVAIT 641 DE DISPONIBLES.

       L'ADMIN, LE 30/10/2026, capture a l'appui : « la grande majorite des
       sous-titres comme ca ou des textes sont tous compresses, ca ne va
       pas ». Mesure sur une fenetre de 1600 px : la note rendait 52 signes
       par ligne dans 323 px, alors que son conteneur lui en offrait 641.
       Quatre lignes la ou deux suffisent.

       48ch VENAIT D UN AUTRE BESOIN, et le commentaire d'un bloc voisin le
       raconte : c'etait « une ligne sous un bouton centre ». Les notes de
       cette page portent desormais deux a trois phrases.

       68ch, PARCE QUE C EST LA FOURCHETTE DE LECTURE : entre 60 et 75 signes
       par ligne, l'oeil retrouve le debut de la ligne suivante sans la
       chercher. En dessous il saute trop souvent, au-dessus il se perd. */
    .lv-note { margin: 18px 0 0; max-width: 68ch; font-size: 12.5px; line-height: 1.5; color: var(--lv-mention); }

    /* UN LIEN DANS UNE NOTE EST DU TEXTE, PAS UN BOUTON.

       Mesure du 30/10/2026, capture a l'appui : le prix pose en lien avec la
       classe des liens secondaires rendait un cadre de 115 px au milieu d'une
       phrase, coupant la ligne en deux. `lv-lien-second` est un bouton -- il a
       un filet, un fond et du remplissage -- et c'est juste au bas d'une
       section, pas au milieu d'une note de 12,5 px.

       IL GARDE L ACCENT ET PREND UN SOULIGNEMENT : c'est ce qui dit « lien »
       sans rien dessiner autour. L'epaisseur du trait vient de la teinte, pas
       d'un filet, donc le texte ne bouge pas quand on le survole. */
    .lv-note a { color: rgb(var(--portal-gold-rgb)); font-weight: 600;
      text-decoration: underline; text-underline-offset: 2px;
      text-decoration-thickness: 1px; text-decoration-color: rgba(var(--portal-gold-rgb), 0.45); }
    .lv-note a:hover, .lv-note a:focus-visible { text-decoration-color: rgb(var(--portal-gold-rgb)); }

    /* --- Les boutons -------------------------------------------------------- */
    .portal-cta, .portal-btn { display: inline-flex; align-items: center; justify-content: center;
      border: 1px solid rgba(var(--portal-gold-rgb), 0.36);
      background: linear-gradient(135deg, rgba(var(--portal-gold-rgb), 0.96), rgba(var(--portal-gold-clair-rgb), 0.82));
      color: var(--slate-mid); border-radius: 12px; padding: 15px 34px; font-weight: 600; font-size: 16px;
      line-height: 1; text-decoration: none;
      box-shadow: 0 14px 32px rgba(var(--black-rgb),0.22), inset 0 1px 0 rgba(var(--white-rgb), 0.26);
      transition: transform .18s ease, box-shadow .18s ease, filter .18s ease; }
    .portal-cta:hover { transform: translateY(-1px); filter: brightness(1.04); color: var(--slate-mid); }
    .portal-cta--petit { padding: 10px 18px; font-size: 14px; border-radius: 10px; box-shadow: none; }
    /* portal.css : `.portal-btn` partage le fond dore, avec sa propre mesure. */
    .portal-btn { appearance: none; padding: 13px 26px; font-size: 15px; cursor: pointer; font-family: inherit; }
    .portal-btn:hover { transform: translateY(-2px); filter: brightness(1.04);
      box-shadow: 0 18px 40px rgba(var(--black-rgb), 0.30), 0 0 0 4px rgba(var(--portal-gold-rgb), 0.10),
                  inset 0 1px 0 rgba(var(--white-rgb), 0.34); }
    .portal-btn:focus-visible { outline: 3px solid rgba(var(--portal-accent-rgb), 0.44); outline-offset: 3px; }
    /* Un libelle de bouton ne se coupe pas. Sous 420 px le retrait lateral
       tombe a 12 px, sans quoi les libelles longs deborderaient de leur
       carte au lieu de passer a la ligne. */
    .portal-cta, .lv-lien-second { white-space: nowrap; }
    .lv-lien-second { display: inline-flex; align-items: center; min-height: 44px; padding: 0 18px; border-radius: 10px;
      border: 1px solid rgba(var(--white-rgb), 0.14); background: rgba(var(--white-rgb), 0.04);
      color: var(--texte-sur-sombre); font-size: 14.5px; text-decoration: none;
      transition: transform .18s ease, background .18s ease, border-color .18s ease; }
    .lv-lien-second:hover { transform: translateY(-1px); background: rgba(var(--white-rgb), 0.08);
      border-color: rgba(var(--white-rgb), 0.28); color: var(--texte-sur-sombre); }
    /* Ces deux paliers viennent APRES le raccourci `padding: 0 18px` :
       a specificite egale, c est la derniere regle de la feuille qui
       gagne. Poses plus haut, ils ne faisaient rien. */
    @media (max-width: 420px) {
      .portal-cta, .lv-lien-second { padding-left: 12px; padding-right: 12px; }
    }
    @media (max-width: 359px) {
      .portal-cta, .lv-lien-second { padding-left: 8px; padding-right: 8px; }
    }

    /* --- Les cartes, et la lueur de bordure ---------------------------------- */
    .lv-carte { padding: 22px 20px 24px; border: 1px solid rgba(var(--white-rgb), 0.10); border-radius: 16px;
      background: rgba(var(--white-rgb), 0.04); }
    .lv-carte__titre { margin: 0 0 8px; font-size: 14.5px; font-weight: 700; line-height: 1.3; color: var(--texte-sur-sombre); }

    .lv-carte__texte { margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--texte-discret-sur-sombre); }
    .lv-carte__point { display: block; width: 8px; height: 8px; border-radius: 50%; margin: 0 0 14px;
      background: rgb(var(--lv-teinte, var(--portal-blue-rgb)));
      box-shadow: 0 0 0 4px rgba(var(--lv-teinte, var(--portal-blue-rgb)), 0.14); }
    .lv-carte--domaine { display: block; width: 100%; text-align: left; font: inherit; cursor: pointer;
      transition: transform .18s ease, border-color .18s ease, background .18s ease; }
    .lv-carte--domaine .lv-carte__titre, .lv-carte--domaine .lv-carte__texte { display: block; }

    /* LE POINT REVIENT SUR LA LIGNE DU TITRE.

       L'ADMIN, LE 30/10/2026 : « les points sont devenus avec un retour a la
       ligne au lieu d'etre au meme niveau ».

       CE N EST PAS UNE REGLE QUI A CHANGE, C EST LA CARTE QUI A GRANDI. Le
       point est empile par conception (`margin: 0 0 14px`), et ca ne se
       remarquait pas tant que la carte faisait 280 px : haute et etroite,
       l'empilement point / titre / texte se lisait comme une colonne. Passee
       a 576 px, la carte est basse et large, et le point seul sur sa ligne
       ouvre un vide de 22 px au-dessus du titre.

       UNE GRILLE A DEUX COLONNES plutot qu'un `inline-block` : le texte de la
       seconde ligne doit s'aligner sur le TITRE, pas repasser sous le point.
       La premiere colonne fait la largeur du point, la seconde prend le
       reste.

       `align-items: start` ET UNE MARGE HAUTE SUR LE POINT : centrer la
       rangee ferait descendre le point sur un titre de deux lignes. Pose a
       6 px du haut, il tombe sur la premiere ligne quelle que soit la
       suite. */
    /* ET CA VAUT POUR TOUTE CARTE A POINT, pas seulement les domaines.

       L'ADMIN, LE 30/10/2026, apres un premier correctif limite aux cartes de
       domaine : « il reste des points colores avec retour a la ligne aussi ».

       MESURE SUR LA PAGE : vingt et une cartes portent un point en enfant
       direct. Sept etaient alignees -- celles que le premier correctif
       visait -- et QUATORZE ne l'etaient pas : « Ce que la sequence donne a
       lire », « Les six questions », et les autres rangees du meme motif.
       Toutes ont la meme structure, point puis intitule puis texte.

       `:has()` PLUTOT QU UNE LISTE DE CLASSES : c'est la PRESENCE du point
       qui fait le motif, pas le nom de la carte. Une rangee ajoutee demain
       avec un point est alignee sans qu'on y pense ; une liste de classes
       aurait demande de s'en souvenir.

       ET LE SECOND ENFANT N EST PAS TOUJOURS UN TITRE : les objections
       portent `lv-objection__q`. D'ou `> *:not(.lv-carte__point)`, qui prend
       tout ce qui n'est pas le point, quel que soit son nom. */
    /* `align-content: start` N EST PAS UN DETAIL : SANS LUI LE TEXTE FLOTTE.

       L'ADMIN, LE 30/10/2026, sur les cartes des objections : « centrage ?
       position sous le titre ».

       MESURE A L ECRAN, en 1440 de large : l'ecart entre la question et sa
       reponse valait 10, 32, 42 ou 53 px d'une carte a l'autre, pour une
       marge ecrite de 10. Les cartes d'une rangee s'etirent a la hauteur de
       la plus haute ; une grille etiree repartit ce surplus entre ses
       rangees AUTO, et c'est la grille posee ici qui l'a rendu possible --
       en flux normal, le surplus restait en bas.

       `align-items: start` ne suffit pas : il range le contenu DANS sa
       rangee, pas les rangees dans la carte. */
    .lv-carte:has(> .lv-carte__point) { display: grid;
      grid-template-columns: 8px minmax(0, 1fr); column-gap: 11px;
      align-items: start; align-content: start; }
    .lv-carte:has(> .lv-carte__point) > .lv-carte__point { margin: 6px 0 0; }
    .lv-carte:has(> .lv-carte__point) > *:not(.lv-carte__point) { grid-column: 2; }
    .lv-carte:has(> .lv-carte__point) > .lv-carte__texte { margin-top: 6px; }
    .lv-carte--domaine:hover { transform: translateY(-2px); border-color: rgba(var(--lv-teinte), 0.45); }
    .lv-carte--domaine.is-choisi { border-color: rgba(var(--lv-teinte), 0.62);
      background: linear-gradient(rgba(var(--lv-teinte), 0.10), rgba(var(--white-rgb), 0.02)); }
    .lv-carte--invite { display: flex; flex-direction: column; justify-content: flex-end;
      background: linear-gradient(rgba(var(--portal-gold-rgb), 0.14), rgba(var(--portal-gold-rgb), 0.05));
      border-color: rgba(var(--portal-gold-rgb), 0.3); }
    .lv-carte--invite p { margin: 0 0 12px; font-size: 14.5px; line-height: 1.5; color: rgba(var(--white-rgb), 0.86); }
    .lv-carte--invite a:not(.portal-cta) { font-size: 14.5px; font-weight: 700; color: rgb(var(--portal-gold-rgb)); }
    /* Plus de `min-height` : il ne couvrait pas les textes longs en colonne
       etroite (110 px de saut a 375 px) et en reservait trop sur grand ecran.
       Ce sont les sept textes empiles qui reservent la hauteur, exactement. */
    .lv-domaine__pile { display: grid; }
    .lv-domaine__pile > * { grid-area: 1 / 1; }
    /* `visibility: hidden` et non `display: none` : le fantome doit occuper sa
       place, c est tout son role. */
    .lv-domaine__texte--fantome { visibility: hidden; pointer-events: none; }
    .lv-domaine__texte { margin: 26px 0 0; max-width: 92ch; font-size: 13.5px; line-height: 1.6;
      color: rgba(var(--white-rgb), 0.5); }
    .lv-domaine__texte strong { color: var(--texte-sur-sombre); font-weight: 700; }
    /* Les demandes du domaine choisi, sur leur propre ligne. Plus petites que
       le texte du domaine : elles le precisent, elles ne le remplacent pas. */
    .lv-demandes { display: inline-block; margin-top: 8px; font-size: .86em; opacity: .78; }

    /* Un bouton qui se lit comme un lien. « Voir un exemple en pleine taille »
       ouvre une fenetre, donc c'est un bouton, et il doit garder l'allure du
       lien qu'il etait. Le raccourci `font` remettrait aussi la TAILLE, celle
       du parent : seule la famille se reprend. */
    button.lv-lien-second { background: none; border: 0; cursor: pointer;
      font-family: inherit; font-style: inherit; }

    /* Les chiffres du hero menent a la section qui les etablit, sans changer
       d'allure : c'est la ou le doute nait qu'on l'emmene. */
    .lv-chiffres--lien { text-decoration: none; color: inherit; }
    .lv-chiffres--lien:hover .lv-chiffre__quoi { color: rgba(var(--white-rgb), 0.82); }
    .lv-carte[data-lueur] { position: relative; --lueur-x: 50%; --lueur-y: 50%; }
    .lv-carte[data-lueur]::after { content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1px;
      opacity: 0; transition: opacity .26s ease; pointer-events: none;
      background: radial-gradient(240px circle at var(--lueur-x) var(--lueur-y),
        rgba(var(--lv-teinte, var(--portal-accent-rgb)), 1),
        rgba(var(--lv-teinte, var(--portal-accent-rgb)), 0.38) 44%, transparent 74%);
      filter: saturate(1.25);
      -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
      mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
      -webkit-mask-composite: xor; mask-composite: exclude; }
    .lv-carte[data-lueur]:hover::after { opacity: 1; }
    .lv-carte--invite[data-lueur] { --lv-teinte: var(--portal-gold-rgb); }
    @media (prefers-reduced-motion: reduce) { .lv-carte--domaine, .lv-carte[data-lueur]::after { transition: none; } }

    /* --- Les rangees a marqueur ---------------------------------------------- */
    .lv-rang { display: grid; grid-template-columns: 12px 1fr; gap: 11px; align-items: start; font-size: 13.5px;
      line-height: 1.55; color: var(--texte-discret-sur-sombre); }
    .lv-rang + .lv-rang { margin-top: 12px; }
    .lv-rang__point { width: 8px; height: 8px; margin-top: 6px; border-radius: 50%; background: rgb(var(--lv-teinte, var(--portal-blue-rgb))); }
    /* LE TITRE DU RANG PREND SA LIGNE.
    
       L'ADMIN, LE 30/10/2026, capture a l'appui : « un retour a la ligne et
       majuscule ? », puis « ici aussi » sur le second bloc.
    
       CE QUE CA DONNAIT : le titre en gras et la phrase qui le suit couraient
       sur la meme ligne, et la phrase commencait en minuscule. « La seance ne
       s'arrete plus au constat vous avez quelque chose a proposer » se lit comme
       une seule phrase, et elle ne veut rien dire. Les deux sont pourtant deux
       choses : un intitule, puis ce qu'il recouvre.
    
       `display: block` SUFFIT, et c'est tout ce qu'on change : le rang est deja
       une grille a deux colonnes dont la seconde porte le texte, le bloc y prend
       la largeur et pousse la suite a la ligne. Les majuscules, elles, sont dans
       les catalogues -- le style ne peut pas les poser sans `text-transform`,
       qui toucherait tout le reste de la phrase.
    
       CETTE FEUILLE-CI, ET PAS `vitrine.css`, et c'est une mesure qui l'a
       tranche. Les deux portent la regle ; `landing-tunnel.css` sert cette
       page et `ecoles`, dont les quatre rangs ont exactement la meme forme.
       `vitrine.css` sert en plus `pour-qui` et la landing precedente, et
       `pour-qui` N'A PAS cette forme : son terme en gras est decoupe sur le
       deux-points, donc il FINIT par « : » et la suite le prolonge. Mis en
       bloc, il laisserait un deux-points seul en bout de ligne.

       `display` NE SE REDECLARE PAS PLUS BAS, donc `ecoles`, qui charge les
       deux feuilles, garde bien le bloc : la cascade remplace une propriete,
       elle n'en retire pas une qui n'est pas redite. */
    .lv-rang__quoi { display: block; color: var(--texte-sur-sombre); font-weight: 700; }
    .lv-cadre { display: grid; grid-template-columns: 14px 1fr; gap: 13px; align-items: start; }
    .lv-cadre + .lv-cadre { margin-top: 12px; }
    .lv-cadre__signe { font-size: 13px; line-height: 1.5; margin-top: 1px; }
    .lv-cadre__texte { font-size: 13.5px; line-height: 1.55; color: var(--texte-discret-sur-sombre); }
    .lv-etape { display: grid; grid-template-columns: 38px 1fr; gap: 18px; align-items: start; }

    /* --- LES ETAPES EN RAIL -------------------------------------------------
       Elles tenaient dans le tiers haut de leur colonne et laissaient le reste
       vide a cote d une demonstration deux fois plus haute. Elles se
       repartissent sur toute la hauteur, accrochees a un rail, et le numero
       devient un noeud sur ce rail au lieu d un chiffre pose a cote.
       La classe est sur le CONTENEUR : `.lv-etape` sert ailleurs. */
    .lv-etapes { display: flex; flex-direction: column; justify-content: space-between;
      height: 100%; position: relative; gap: 8px; }
    .lv-etapes::before { content: ""; position: absolute; left: 15px; top: 22px; bottom: 22px; width: 1px;
      background: linear-gradient(180deg,
        rgba(var(--portal-accent-rgb), 0) 0%, rgba(var(--portal-accent-rgb), 0.34) 14%,
        rgba(var(--portal-accent-rgb), 0.34) 86%, rgba(var(--portal-accent-rgb), 0) 100%); }
    .lv-etapes .lv-etape { display: block; margin: 0; padding: 14px 18px 14px 46px; position: relative;
      border-radius: 14px; border: 1px solid transparent;
      transition: background-color .24s ease, border-color .24s ease; }
    .lv-etapes .lv-etape + .lv-etape { margin-top: 0; }
    .lv-etapes .lv-etape:hover { background: rgba(var(--white-rgb), 0.04);
      border-color: rgba(var(--white-rgb), 0.09); }
    /* Le noeud porte le fond de la page pour DECOUPER le rail : sans ce fond,
       le trait passerait derriere le chiffre et le traverserait. */
    .lv-etapes .lv-etape__rang { position: absolute; left: 6px; top: 15px;
      width: 20px; height: 20px; border-radius: 50%; display: inline-flex;
      align-items: center; justify-content: center; font-size: 9.5px; letter-spacing: 0;
      background: var(--surface-sombre); border: 1px solid rgba(var(--portal-accent-rgb), 0.42);
      color: rgb(var(--portal-accent-rgb)); transition: border-color .24s ease, box-shadow .24s ease; }
    .lv-etapes .lv-etape:hover .lv-etape__rang { border-color: rgba(var(--portal-accent-rgb), 0.85);
      box-shadow: 0 0 14px rgba(var(--portal-accent-rgb), 0.28); }
    @media (prefers-reduced-motion: reduce) {
      .lv-etapes .lv-etape, .lv-etapes .lv-etape__rang { transition: none; }
    }
    .lv-etape + .lv-etape { margin-top: 20px; }
    .lv-etape__rang { font-family: var(--lv-mono); font-size: 12px; font-weight: 700; letter-spacing: 0.06em;
      color: rgba(var(--portal-accent-rgb), 0.9); padding-top: 2px; }
    .lv-etape__titre { margin: 0 0 4px; font-size: 14.5px; font-weight: 700; color: var(--texte-sur-sombre); }
    .lv-etape__texte { margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--texte-discret-sur-sombre); }

    /* --- Le panneau ------------------------------------------------------------ */
    .lv-panneau { padding: 22px 20px 24px; border: 1px solid rgba(var(--white-rgb), 0.14); border-radius: 16px;
      background: rgba(var(--surface-sombre-rgb), 0.55); }
    .lv-panneau__ligne { display: grid; grid-template-columns: 112px 1fr; gap: 13px; align-items: start;
      font-size: 13.5px; line-height: 1.5; }
    .lv-panneau__ligne + .lv-panneau__ligne { margin-top: 14px; padding-top: 14px; border-top: 1px solid rgba(var(--white-rgb), 0.08); }
    .lv-panneau__quoi { font-family: var(--lv-mono); font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase;
      color: var(--lv-mention); padding-top: 3px; }
    .lv-panneau__valeur { color: var(--texte-discret-sur-sombre); }

    /* --- Les chiffres ----------------------------------------------------------- */
    .lv-chiffres { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; margin-top: 26px;
      padding-top: 26px; }
    .lv-chiffre__valeur { display: block; font-size: 26px; font-weight: 900; line-height: 1; color: rgb(var(--portal-accent-rgb)); }
    .lv-chiffre__quoi { display: block; margin-top: 6px; font-family: var(--lv-mono); font-size: 9.5px;
      letter-spacing: 0.08em; text-transform: uppercase; color: rgba(var(--white-rgb), 0.55); }
    @media (max-width: 520px) { .lv-chiffres { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px 10px; } }

    /* --- Entetes de colonne, observations, these ---------------------------------- */
    /* 0,50 et non 0,42 : sur le sol ardoise de l application, un blanc a 0,42
       tombe a 3,84 contre le fond de carte. Mesure : 0,50 rend 4,81. */
    .lv-colonne__entete { display: block; margin: 0 0 18px; font-family: var(--lv-mono); font-size: 10px;
      letter-spacing: 0.16em; text-transform: uppercase; color: rgba(var(--white-rgb), 0.50); }
    .lv-colonne__entete--accent { color: rgba(var(--portal-accent-rgb), 0.9); }
    .lv-observation__note { margin: 18px 0 0; font-size: 13px; line-height: 1.55; color: rgba(var(--white-rgb), 0.5); }
    /* Une phrase est une BOITE : elle passe a la ligne entiere quand elle ne
       tient pas dans la place restante, au lieu de laisser un mot seul
       accroche a la ligne d avant. Elle se coupe quand meme si elle ne tient
       pas sur une ligne pleine, donc rien ne peut deborder. */
    .lv-phrase { display: inline-block;
      /* Et la matiere se repartit entre les lignes de la boite, pour ne jamais
         laisser un mot seul en bas. Mesure : de 6 a 23 phrases finissaient sur
         un mot unique selon la largeur, zero desormais, sans qu une seule
         phrase change de hauteur. */
      text-wrap: balance; }
    .lv-these { margin: 32px 0 0; max-width: 72ch; font-size: 14.5px; line-height: 1.6; color: rgba(var(--white-rgb), 0.82); }

    /* --- Les six ecrans du decodage ------------------------------------------------ */
    .lv-pages { display: flex; flex-direction: column; gap: 12px; }
    /* Le rayon vit ICI, pas dans le dessin : la boite porte la bordure, l anneau
       et le decoupage des six pastilles, et son rayon est celui de `.lv-demo`.
       Le rectangle de fond des six ecrans, lui, a perdu son `rx` : deux chassis
       arrondis l un dans l autre, a deux rayons differents, se voyaient. */
    .lv-pages__boite { border-radius: 16px; overflow: hidden; border: 1px solid rgba(var(--white-rgb), 0.14);
      background: rgba(var(--surface-sombre-rgb), 0.55);
      box-shadow: 0 0 0 4px rgba(var(--portal-accent-rgb), 0.10); }
    .lv-pages__cadre { position: relative; aspect-ratio: 480 / 300; }
    .lv-pages__vue { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; opacity: 0; transition: opacity .7s ease; }
    .lv-pages__vue.est-vue { opacity: 1; }
    .lv-pages__nom { font-size: 13px; font-weight: 600; color: rgba(var(--white-rgb), 0.86); }
    .lv-pages__palette { display: grid; grid-template-columns: repeat(6, 1fr); gap: 5px; padding: 8px;
      background: rgba(var(--black-rgb), 0.42); border-top: 1px solid rgba(var(--white-rgb), 0.10); }
    .lv-pages__canal { height: 10px; padding: 0; border-radius: 8px; border: 1px solid rgba(var(--white-rgb), 0.16);
      background: linear-gradient(135deg, #0f766e, rgb(var(--portal-accent-rgb)));
      box-shadow: inset 0 1px 0 rgba(var(--white-rgb), 0.14); opacity: .34; cursor: pointer;
      transition: opacity .4s ease, transform .4s ease, box-shadow .4s ease; }
    .lv-pages__canal:hover { opacity: .68; }
    .lv-pages__canal.est-vue { opacity: 1; transform: scale(1.06);
      box-shadow: inset 0 1px 0 rgba(var(--white-rgb), 0.22), 0 0 14px rgba(var(--portal-accent-rgb), 0.5); }
    /* Plus de `min-height` : il plafonnait a deux lignes alors que le nombre
       de lignes depend de la largeur de la colonne. Ce sont les six legendes
       empilees qui reservent la hauteur, exactement. */
    .lv-pages__note { margin: 0; font-size: 12.5px; line-height: 1.55; color: rgba(var(--white-rgb), 0.52); }
    .lv-pages__legende { display: grid; }
    .lv-pages__legende > * { grid-area: 1 / 1; }
    .lv-pages__ligne { display: grid; gap: 12px; align-content: start; }
    /* `visibility: hidden` et non `display: none` : le fantome doit occuper
       sa place, c est tout son role. Il sort quand meme de l arbre
       d accessibilite et du parcours au clavier. */
    .lv-pages__ligne--fantome { visibility: hidden; pointer-events: none; }
    @media (prefers-reduced-motion: reduce) { .lv-pages__vue, .lv-pages__canal { transition: none; } }

    /* --- Le jeu des six pages empilees --------------------------------------------- */
    .lv-apercu { display: flex; flex-direction: column; gap: 14px; }
    .lv-deck { position: relative; width: 100%; max-width: 420px; margin: 0 auto; aspect-ratio: 1 / 0.94; }
    .lv-deck__page { position: absolute; top: 50%; left: 50%; width: 47%; height: auto; transform-origin: 50% 50%;
      transition: transform .28s ease, opacity .28s ease; }
    /* SIX CARTES, TROIS DE CHAQUE COTE. Les rangs impairs partent a gauche,
       les pairs a droite, et chaque paire se rapproche du centre : la derniere
       est posee a plat devant, c'est l'etat de ressource. Les ecarts sont en
       pourcentage de la CARTE et non du jeu, donc l'eventail garde sa forme a
       toutes les largeurs. A 420 px de large, la carte fait 197 px : l'ecart le
       plus grand, 52 %, laisse 9 px entre son bord et celui du jeu. */
    .lv-deck__page--1 { transform: translate(-50%, -50%) translate(-52%, 5%) rotate(-16deg); opacity: .64; z-index: 1; }
    .lv-deck__page--2 { transform: translate(-50%, -50%) translate( 52%, 5%) rotate( 15deg); opacity: .70; z-index: 1; }
    .lv-deck__page--3 { transform: translate(-50%, -50%) translate(-33%, 3%) rotate(-10deg); opacity: .80; z-index: 2; }
    .lv-deck__page--4 { transform: translate(-50%, -50%) translate( 33%, 3%) rotate(  9deg); opacity: .86; z-index: 3; }
    .lv-deck__page--5 { transform: translate(-50%, -50%) translate(-15%, 1%) rotate( -5deg); opacity: .94; z-index: 4; }
    .lv-deck__page--6 { transform: translate(-50%, -50%) translate(  3%, 0%) rotate(  2deg); opacity: 1;   z-index: 5; }

    /* LA CARTE EST UN BOUTON, ET ELLE MONTRE LE HAUT DE SA PAGE.
       Les cinq pages reelles vont de 1,24 a 0,27 de proportion : posees telles
       quelles, la plus courte ferait un carre et la plus longue un ruban. La
       carte impose donc SA proportion et cadre le haut ; la page entiere se lit
       dans la loupe, ou c'est la hauteur qui defile. */
    .lv-deck__page { padding: 0; border: 1px solid rgba(var(--white-rgb), 0.14);
      border-radius: 10px; overflow: hidden; background: rgba(var(--black-rgb), 0.5);
      cursor: pointer; box-shadow: 0 18px 44px rgba(var(--black-rgb), 0.5); }
    .lv-deck__page > img { display: block; width: 100%; aspect-ratio: 222 / 300;
      object-fit: cover; object-position: top; }
    .lv-deck__page:hover { filter: brightness(1.12); }
    .lv-deck__page:focus-visible { outline: 2px solid var(--lv-accent, #2dd4e8); outline-offset: 3px; }

    /* --- La loupe : la page entiere, en 16:9, qu on fait defiler ------------------- */
    /* LA FENETRE EST EN 16:9 ET LA HAUTEUR DEFILE. Une planche de resultat fait
       jusqu'a 5 400 px de haut : aucun cadre ne la contient, et la reduire pour
       qu'elle tienne la rendrait illisible. On lui donne donc la largeur et on
       laisse la hauteur courir. */
    .lv-loupe { width: min(1180px, 94vw); max-width: none; padding: 0; border: 0;
      border-radius: 14px; background: var(--lv-carte, #0d141d);
      color: rgba(var(--white-rgb), 0.92); box-shadow: 0 40px 110px rgba(var(--black-rgb), 0.7); }
    .lv-loupe::backdrop { background: rgba(var(--black-rgb), 0.72); backdrop-filter: blur(3px); }
    .lv-loupe__tete { display: flex; align-items: center; justify-content: space-between;
      gap: 16px; padding: 12px 18px; border-bottom: 1px solid rgba(var(--white-rgb), 0.10); }
    .lv-loupe__nom { margin: 0; font-size: 15px; font-weight: 600; }
    .lv-loupe__fermer { border: 0; background: none; cursor: pointer; font-size: 26px;
      line-height: 1; padding: 0 6px; color: rgba(var(--white-rgb), 0.6); }
    .lv-loupe__fermer:hover { color: rgba(var(--white-rgb), 0.95); }
    .lv-loupe__fermer:focus-visible { outline: 2px solid var(--lv-accent, #2dd4e8); outline-offset: 2px; }
    /* LE 16:9 EST UNE FORME, PAS UNE FATALITE. Sur un ecran large il donne la
       fenetre voulue ; sur un telephone il la reduit a 206 px de haut -- 26 %
       de l'ecran -- pour une planche qui en fait sept. On lirait par une fente,
       avec 271 px inutilisES en dessous. `min-height` releve le cadre quand la
       proportion le rend trop court, `max-height` l'empeche de sortir de la
       fenetre. Aucun seuil de largeur : c'est la place disponible qui decide.
       Mesure a 1440 : 664 px, le 16:9 inchange. A 390 : 560 au lieu de 206. */
    /* LA PROPORTION SE CALCULE, ELLE NE SE DECLARE PAS ICI.
       `aspect-ratio` avec un `min-height` ne raccourcit pas la boite : il
       l'ELARGIT pour tenir la proportion. Mesure : cadre de 996 px de large
       dans une fenetre de 390. Le remede du premier defaut en fabriquait un
       second, plus visible que lui.
       La hauteur est donc calculee depuis la largeur de la loupe -- la meme
       expression que sa `width`, divisee par 16/9 -- et bornee : jamais moins
       de 70 % de la fenetre, jamais plus de 82 %. La largeur, elle, n'est plus
       touchee. A 1440 : 656 px, le 16:9. A 390 : 560, soit 70 %. */
    .lv-loupe__cadre { height: clamp(70svh, calc(min(1180px, 94vw) * 0.5625), 82svh);
      overflow-y: auto; overscroll-behavior: contain; }
    .lv-loupe__cadre img { display: block; width: 100%; height: auto; }

    @media (prefers-reduced-motion: reduce) { .lv-deck__page { transition: none; } }
    .lv-apercu__ligne { display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
      font-family: var(--lv-mono); font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase;
      color: var(--lv-mention); }
    .lv-apercu__texte { margin: 0; font-size: 13px; line-height: 1.55; color: rgba(var(--white-rgb), 0.5); }

    /* --- Les vignettes de capture ------------------------------------------------------ */
    .lv-vignette__image { display: block; width: 100%; height: auto; border-radius: 10px;
      border: 1px solid rgba(var(--white-rgb), 0.10); background: rgba(var(--surface-sombre-rgb), 0.55); }
    .lv-vignette__rang { display: block; margin-top: 10px; font-family: var(--lv-mono); font-size: 10px;
      letter-spacing: 0.1em; text-transform: uppercase; color: rgba(var(--white-rgb), 0.55); }

    /* --- La FAQ, en `details` natif ------------------------------------------------------ */
    .lv-faq { margin-top: 30px; padding-top: 26px; }
    .lv-faq__item { border-bottom: 1px solid rgba(var(--white-rgb), 0.08); }
    .lv-faq__item > summary { display: flex; align-items: baseline; gap: 10px; padding: 13px 0; font-size: 14.5px;
      font-weight: 700; line-height: 1.4; color: var(--texte-sur-sombre); cursor: pointer; list-style: none;
      transition: color .18s ease; }
    .lv-faq__item > summary::-webkit-details-marker { display: none; }
    .lv-faq__item > summary::before { content: ""; flex: 0 0 auto; width: 7px; height: 7px; margin-top: 4px;
      border-right: 1.6px solid rgba(var(--portal-accent-rgb), 0.85);
      border-bottom: 1.6px solid rgba(var(--portal-accent-rgb), 0.85);
      transform: rotate(-45deg); transition: transform .18s ease; }
    .lv-faq__item[open] > summary::before { transform: rotate(45deg); }
    .lv-faq__item > summary:hover { color: rgb(var(--portal-accent-rgb)); }
    .lv-faq__item > p { margin: 0 0 15px 17px; font-size: 13.5px; line-height: 1.6; color: var(--texte-discret-sur-sombre); }

    /* --- Le formulaire : les regles de portal.css, telles quelles ------------
       Un champ doit se voir AVANT d etre rempli : bordure a 0,24 et fond
       creuse a 0,34 de noir, mesures pour passer les 3,0 de la norme sur la
       limite d un controle. Le cadre du parrainage porte le cyan du produit. */
    .lv-formulaire .portal-access__inner { padding: 28px 26px 30px; border: 1px solid rgba(var(--white-rgb), 0.10);
      border-radius: 18px; background: rgba(var(--white-rgb), 0.04); }
    .portal-access__form { display: grid; gap: 14px; }
    .portal-field { display: grid; gap: 7px; }
    .portal-field label, .portal-checkbox { color: rgba(var(--white-rgb), 0.78); font-size: 14px; line-height: 1.35; }
    .portal-field input, .portal-field select { width: 100%; min-height: 42px; border-radius: 12px;
      border: 1px solid rgba(var(--white-rgb), 0.24); background-color: rgba(var(--black-rgb), 0.34);
      color: #ffffff; padding: 9px 12px; outline: none; font: inherit;
      transition: border-color .18s ease, box-shadow .18s ease, background .18s ease; }
    .portal-field select { color-scheme: dark; }
    .portal-field input:focus, .portal-field select:focus { border-color: rgba(var(--portal-accent-rgb), 0.44);
      background-color: rgba(var(--white-rgb), 0.08); box-shadow: 0 0 0 4px rgba(var(--portal-accent-rgb), 0.10); }
    .portal-access__form textarea { width: 100%; min-height: 96px; border-radius: 12px;
      border: 1px solid rgba(var(--white-rgb), 0.24); background: rgba(var(--black-rgb), 0.34);
      color: #ffffff; padding: 10px 12px; font: inherit; outline: none; resize: vertical;
      transition: border-color .18s ease, box-shadow .18s ease, background .18s ease; }
    .portal-access__form textarea:focus { border-color: rgba(var(--portal-accent-rgb), 0.55);
      background: rgba(var(--white-rgb), 0.09); box-shadow: 0 0 0 3px rgba(var(--portal-accent-rgb), 0.14); }
    .portal-access__referral { display: grid; gap: 12px; margin: 0; padding: 16px; border-radius: 16px;
      border: 1px solid rgba(var(--portal-accent-rgb), 0.26); background: rgba(var(--portal-accent-rgb), 0.06); }
    .portal-access__referral legend { padding: 0 6px; font-size: 13px; letter-spacing: .04em;
      color: rgba(var(--portal-accent-rgb), 0.92); }
    .portal-access__referral small { color: rgba(var(--white-rgb), 0.52); font-size: 12.5px; line-height: 1.4; }
    .portal-checkbox { display: flex; align-items: flex-start; gap: 9px; cursor: pointer; }
    .portal-checkbox input { flex: none; width: 16px; height: 16px; margin-top: 2px;
      accent-color: rgb(var(--portal-gold-rgb)); min-height: 0; }
    .portal-btn--full { width: 100%; }
    /* L indicatif et le numero sur une ligne : 112 px au selecteur, le reste
       au numero, qui est ce qu on saisit. */
    .champ-telephone { display: grid; grid-template-columns: minmax(0, 112px) minmax(0, 1fr); gap: 8px; align-items: stretch; }
    .champ-telephone select, .champ-telephone input { width: 100%; min-height: 42px; margin-bottom: 0; }
    .champ-telephone__pays { position: relative; min-width: 0; }
    .champ-telephone__apercu { position: absolute; inset: 0; display: flex; align-items: center; gap: 8px;
      padding: 0 30px 0 12px; color: #ffffff; font-size: 16px; pointer-events: none; }
    .champ-telephone__apercu img, .champ-telephone__drapeau { flex: none; width: 20px; height: 15px;
      border-radius: 3px; box-shadow: 0 0 0 1px rgba(var(--white-rgb), 0.28); }
    /* Deux classes, pas une : une classe seule se fait battre par la regle de
       champ de `.portal-access__form select`, et le texte du selecteur
       reapparait sous l apercu. */
    .champ-telephone .champ-telephone__pays select { appearance: none; -webkit-appearance: none;
      color: transparent; padding-right: 30px;
      /* La taille a zero en plus de la couleur : en contraste eleve le
         navigateur REIMPOSE la couleur, une taille nulle ne se reimpose pas. */
      font-size: 0; }
    /* Le menu deroulant, lui, se lit : il garde sa couleur. */
    .champ-telephone .champ-telephone__pays select option { font-size: 15px; color: var(--texte-sur-sombre);
      background: var(--slate-mid); }
    /* La fleche du systeme se dessine avec la couleur du texte : la rendre
       transparente l effacerait aussi. L apercu porte donc la sienne. */
    .champ-telephone__apercu::after { content: ""; position: absolute; right: 12px; width: 8px; height: 8px;
      border-right: 2px solid rgba(var(--white-rgb), 0.6); border-bottom: 2px solid rgba(var(--white-rgb), 0.6);
      transform: translateY(-2px) rotate(45deg); }
    /* Sous cette largeur l indicatif et le numero ne tiennent plus cote a cote :
       le pays passe au-dessus plutot que d ecraser le champ qu on remplit. */
    @media (max-width: 520px) { .champ-telephone { grid-template-columns: 1fr; } }

    /* --- L'offre ------------------------------------------------------------------------------ */
    .lv-prix { display: block; font-size: 34px; font-weight: 900; line-height: 1; letter-spacing: -0.015em;
      color: var(--texte-sur-sombre); white-space: nowrap; }
    .lv-prix__quoi { display: block; margin-top: 8px; font-family: var(--lv-mono); font-size: 9.5px;
      letter-spacing: 0.08em; text-transform: uppercase; color: rgba(var(--white-rgb), 0.55); }
    .lv-liste { margin: 16px 0 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 9px; }
    .lv-liste li { font-size: 13.5px; line-height: 1.5; color: var(--texte-discret-sur-sombre);
      display: grid; grid-template-columns: 12px 1fr; gap: 11px; }
    .lv-liste li::before { content: "·"; color: var(--lv-mention); }

    /* --- L'objection en vue ----------------------------------------------------------------------
       Meme carte que partout, mais la question porte le poids d'un titre : c'est
       elle qu'on vient chercher, la reponse se lit apres. */
    .lv-objection__q { margin: 0 0 10px; font-size: 16px; font-weight: 700; line-height: 1.32; color: var(--texte-sur-sombre); }
    .lv-objection__r { margin: 0; font-size: 13.5px; line-height: 1.6; color: var(--texte-discret-sur-sombre); }

    /* --- L'entete et le pied ------------------------------------------------------------------------ */
    /* Pas de filet gris ici : le rail spectral ferme deja le bandeau. */
    .lv-entete { position: relative; padding-top: 15px; padding-bottom: 15px;
      background: rgba(var(--surface-sombre-rgb), 0.72); backdrop-filter: blur(10px) saturate(1); -webkit-backdrop-filter: blur(10px) saturate(1); }

    /* ====================================================================
       LE BANDEAU SUIT LA LECTURE : il s'efface en descendant, il revient en
       remontant.
       ====================================================================
       IL NE FLOTTE QUE SI LE SCRIPT EST LA. `a-bandeau-flottant` est posee sur
       la racine par `bandeau-flottant.js`, APRES qu'il a mesure la hauteur du
       bandeau et publie `--lv-entete-h`. Sans lui, l'en-tete reste dans le
       flux comme avant : un en-tete fixe sans reserve cacherait le premier
       ecran, et une reserve ecrite en dur serait fausse -- la hauteur releve
       86,8 px a 1440, 140,8 a 760, 128,8 a 390.

       FIXE, PAS COLLANT. `position: sticky` ne tient pas sur cette page :
       `body` porte `overflow-x: hidden`, ce qui en fait un conteneur de
       defilement, et le bandeau repart alors avec la page. Mesure a 1186 px de
       descente : le haut du bandeau a -1308, c'est-a-dire nulle part.

       HORS DE `.lv`, et c'est le flou qui l'exige. `.lv` porte
       `position: relative; z-index: 1`, donc une racine d'arriere-plan :
       dedans, `backdrop-filter` ne filtre que `.lv` et jamais la page, on voit
       l'aplat de couleur et pas le flou. Le gabarit le sort donc du conteneur.
       C'est la meme raison qui l'a sorti sur la landing precedente.

       LE MOUVEMENT ET LES TROIS PRECAUTIONS sont dans `vitrine.css` et dans le
       script : `.is-effacee` remonte de sa propre hauteur (`translateY(-100%)`
       et non des pixels, parce que la hauteur change), la transition dure
       0,34 s, rien ne bouge dans les 240 premiers pixels, les mouvements de
       moins de 8 px sont du bruit, et le bandeau ne se cache jamais quand le
       clavier est dedans. En `prefers-reduced-motion`, il ne se cache pas du
       tout. */
    .a-bandeau-flottant .lv-entete {
      position: fixed; top: 0; left: 0; right: 0; z-index: 60;
    }

    /* LA PLACE QU IL NE PREND PLUS. Le nombre vient de la mesure du bandeau
       lui-meme, pas d'une valeur ecrite : c'est le seul moyen qu'il suive le
       repli du menu et la longueur des libelles traduits. */
    .a-bandeau-flottant .lv { padding-top: var(--lv-entete-h, 0px); }

    /* LES ANCRES DU MENU VISENT SOUS LE BANDEAU. Les sept entrees mènent a des
       sections de la page : sans cette marge, chaque saut posait le titre vise
       DERRIERE le bandeau, et c'est le menu lui-meme qui cachait ce qu'il
       venait de montrer. */
    /* LA RESERVE EST TOMBEE A ZERO LE 30/10/2026.

       L'ADMIN : « le bandeau n'est pas visible quand on rejoint une ancre,
       seulement quand on remonte. Tu peux ne pas garder l'espacement et
       faire remonter l'ancre. »

       Le bandeau se retire en descente et ne revient qu'a la remontee :
       reserver sa hauteur pour un saut vers le bas, c'est reserver la place
       de quelque chose qui n'est pas la. La section visee arrive donc en
       haut de la vue, et non 99 px plus bas. */
    .a-bandeau-flottant { scroll-padding-top: 0; }

    /* ET UNE SEULE DES DEUX RESERVES, SINON ELLES S ADDITIONNENT.

       L'ADMIN, LE 30/10/2026 : « l'ancre est atteinte en la mettant au milieu
       de la page, c'est mieux si le haut de la section atteinte est en haut
       de la vue », puis « toutes les ancres du site ».

       CE QUE LA MESURE DONNE, dans Chrome, sur la page en ligne : l'ancre
       `#offre` arrivait a 203 px du haut d'une vue de 730. Deux reglages
       reservent la place du MEME bandeau, poses a deux endroits :
       `scroll-padding-top: 99px` ici (87 px de bandeau plus 12), et
       `scroll-margin-top: 104px` dans `jetons.css`, sur `[id]`, pour tout le
       produit. 99 + 104 = 203, au pixel.

       ON GARDE LE PADDING, PAS LA MARGE : celui-ci suit la hauteur REELLE du
       bandeau, que `bandeau-flottant.js` publie dans `--lv-entete-h` ; l'autre
       est un 104 ecrit en dur. Mesure apres : 99 px, soit le bandeau plus
       douze.

       SEULES LES PAGES A BANDEAU FLOTTANT SONT VISEES. `jetons.css` sert tout
       le produit, et sa marge reste juste partout ou ce padding n'existe
       pas. */
    html.a-bandeau-flottant :target,
    html.a-bandeau-flottant [id] { scroll-margin-top: 0; }
    /* `1fr auto 1fr` et non `space-between` : la piste du milieu est centree
       sur l ECRAN, quelles que soient les largeurs de la marque et des actions.
       En flex, la nav se decale des que les deux cotes different. */
    /* LES COLONNES DE COTE NE DESCENDENT PAS SOUS LEUR CONTENU.
       `1fr auto 1fr` donne aux deux bords la MEME largeur, celle qui centre la
       nav dans la fenetre. Or la marque (280 px en francais) est plus large
       que les actions (209) : la colonne de gauche recevait la moitie du
       reste, et comme `.lv-marque` porte `min-width: 0`, elle se laissait
       comprimer sous son contenu au lieu de pousser. « STRANNIK ONLINE »
       passait alors PAR-DESSUS « Les gains ». Avec le centrage strict il
       aurait fallu 2 x 280 + 504 + 104 = 1168 px pour que rien ne se touche.
       `minmax(max-content, 1fr)` rend sa largeur a chaque bord : la nav reste
       centree tant qu il y a du mou, et se decale au lieu de recouvrir quand
       il n y en a plus. Il ne faut plus que 1097 px. */
    .lv-entete__dedans { display: grid;
      grid-template-columns: minmax(max-content, 1fr) auto minmax(max-content, 1fr);
      align-items: center;
      gap: 22px; min-height: 56px; max-width: none; padding-left: 30px; padding-right: 30px; }
    /* Chaque enfant a SA colonne, en dur. Le placement automatique ne suffit
       pas : entre 721 et 1240 px la nav est masquee, donc elle sort de la
       grille, les actions remontent en colonne 2 et se calaient a la fin du
       MILIEU. Mesure a 1100 px : 344 px de vide a droite. */
    .lv-entete__dedans > .lv-marque { grid-column: 1; justify-self: start; }
    .lv-entete__dedans > .lv-nav { grid-column: 2; justify-self: center; }
    .lv-entete__dedans > .lv-entete__actions { grid-column: 3; justify-self: end; }
    .lv-marque { display: inline-flex; align-items: center; gap: 12px; color: inherit; text-decoration: none; min-width: 0; flex: 0 0 auto; }
    .lv-marque__signe { width: 56px; height: 56px; flex: 0 0 56px; display: inline-flex; align-items: center; justify-content: center; }
    .lv-marque img { width: 48px; height: 48px; display: block; object-fit: contain; }
    .lv-marque__texte { display: grid; gap: 2px; min-width: 0; }
    .lv-marque__nom { font-size: 20px; font-weight: 900; text-transform: uppercase; letter-spacing: 0.08em; line-height: 1.15; color: var(--texte-sur-sombre); }
    .lv-marque__sous { font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; font-size: 11.5px; letter-spacing: 0.06em; line-height: 1.25; color: rgba(var(--white-rgb), 0.55); white-space: nowrap; }
    /* Une seule ligne : la nav ne se replie pas, elle disparait sous 1120 px.

       LE CHIFFRE A ETE MESURE DEUX FOIS, ET LA PREMIERE MESURE PORTAIT SUR LA
       MAUVAISE QUANTITE. Elle lisait la largeur de la NAV SEULE -- 980 px --
       et en tirait un seuil de 1000. Mais la nav ne tient pas seule dans le
       bandeau : elle partage la rangee avec la marque et les actions. Mesure
       de la RANGEE ENTIERE, le 22/10/2026, en forcant les trois colonnes a
       leur largeur naturelle sur la page en ligne :

         fr  marque 280 + nav 504 + actions 209 + 2 gouttieres + 60 de marge = 1097
         en  249 + 493 + 169 = 1015
         ru  221 + 520 + 169 = 1014
         de  215 + 509 + 194 = 1022

       Le francais est le pire des quatre : son sous-titre de marque et son
       « Se connecter » sont les plus longs. Entre 1001 et 1096 px la rangee
       ne tenait donc pas, et comme `.lv-marque` porte `min-width: 0`, sa
       colonne se laissait comprimer sous son contenu au lieu de pousser :
       « STRANNIK ONLINE » passait PAR-DESSUS « Les gains ». Mesure a 1024 px
       avant correction : 60 px de recouvrement.

       1140 et non 1097 : la largeur de mise en page est celle du document,
       donc la fenetre MOINS la barre de defilement (17 px sous Windows), et
       un repli de police elargit les libelles le temps du chargement. A 1140
       la rangee dispose de 1123 px pour 1097 de contenu.

       En dessous, la page se parcourt au defilement : il n y a pas de menu de
       remplacement, ici comme sur la landing en place. */
    .lv-nav { display: flex; align-items: center; gap: 18px; font-size: 13.5px; flex-wrap: nowrap; flex: 0 0 auto; }
    /* 0,78 comme `portal-page .lv-nav a` sur la landing en place, et non le
       0,68 du jeton discret : les deux barres doivent se lire pareil. */
    .lv-nav a { color: rgba(var(--white-rgb), 0.78); white-space: nowrap; }
    .lv-nav a:hover { color: var(--texte-sur-sombre); }
    @media (max-width: 1139px) { .lv-nav { display: none; } }
    .lv-entete__actions { display: flex; align-items: center; gap: 16px; flex: 0 0 auto; }
    /* L'ONGLET DES LANGUES, DANS LE BANDEAU.

       Le vrai selecteur (partials/locale-switcher) porte `position: fixed` :
       il est fait pour flotter dans le coin des pages sans bandeau. Ici il vit
       ENTRE la navigation et le bouton de connexion ; sorti du flux, il se
       posait par-dessus ce bouton.

       Meme correctif que `portal.css` pour son propre bandeau. Les regles de
       la maquette ont ete retirees : elles habillaient ses boutons inertes,
       qui n'existent plus, et sa regle de conteneur imposait une rangee de
       pastilles a un objet qui n'en est plus une. */
    .lv-entete__actions .locale-switcher {
      /* RELATIVE, ET SURTOUT PAS STATIC.

         Le panneau des langues est en position absolue avec right:0 : il
         s ancre sur le premier ancetre POSITIONNE. En passant le conteneur en
         static, on lui retire ce repere, et le panneau va chercher la page :
         il s etale alors sur toute la largeur. Relative le sort du flux fixe
         tout en lui rendant son role d ancre. */
      position: relative;
      top: auto;
      right: auto;
      z-index: 60;
      flex: 0 0 auto;
    }
    /* ==================================================================
       SOUS 760 PX, LE BANDEAU RESTE UNE LIGNE, ET C EST LE TEXTE QUI CEDE.

       L'ADMIN, LE 30/10/2026 : « tablette/mobile, la landing laisser sur une
       seule ligne, logo/titre a gauche, langue/bouton a droite, premiere
       chose a disparaitre c'est le titre si trop petit ».

       CE QU IL Y AVAIT : une colonne centree, marque au-dessus, actions en
       dessous. Trois rangees la ou le bandeau en demande une, et un bloc de
       150 px de haut avant la premiere phrase de la page.

       CE QUI CEDE, ET DANS CET ORDRE. La ligne ne tient que si quelque chose
       accepte de partir ; on retire le texte, jamais le geste. Mesures sur la
       page reelle, largeur du contenu du bandeau :

         marque entiere + actions   539 px   (56 de signe, 278 de texte)
         sans la baseline           441 px   (le nom seul fait 212)
         le signe seul + actions    249 px

       LES DEUX PALIERS SORTENT DE CES TROIS NOMBRES, pas d'un choix rond,
       ET IL FAUT Y AJOUTER LES RETRAITS DU BANDEAU : 30 px de chaque bord,
       donc la place utile vaut la fenetre moins 60. Premier essai a 580 et
       460 : mesure a 500 px, le nom finissait a 266 et le selecteur de
       langue commencait a 265. Un pixel de recouvrement, invisible dans un
       releve de presence, visible a l'oeil.

         tout            539 + 60 -> la fenetre doit faire 599
         sans baseline   441 + 60 -> 501

       Les paliers sont donc 660 et 540, qui laissent de quoi respirer de
       part et d'autre de ces deux bascules. Sous 540 il ne reste que le
       signe, qui tient jusqu'a 249.

       LA BASELINE PART AVANT LE NOM parce qu'elle est la plus large des deux
       (278 contre 212) et la moins necessaire : le nom dit de qui est la
       page, la baseline dit ce qu'elle fait, et le titre juste dessous le
       redit.

       `.lv-nav` N A PAS DE RANGEE A ELLE : elle est deja `display: none` sous
       760 px, mesure a l'appui. La declarer ici fabriquerait une rangee vide
       avec son ecart.
       ================================================================== */
    @media (max-width: 760px) {
      .lv-entete__dedans { grid-template-columns: auto 1fr; justify-items: stretch;
        text-align: left; align-items: center; gap: 12px; }
      .lv-entete__dedans > .lv-marque { grid-column: 1; justify-self: start; }
      .lv-entete__dedans > .lv-entete__actions { grid-column: 2; justify-self: end;
        width: auto; justify-content: flex-end; flex-wrap: nowrap; gap: 12px; }
      .lv-marque__sous { font-size: 12px; }
    }
    /* LA BASELINE EN PREMIER : 539 px de contenu plus 60 de retraits ne
       tiennent plus. */
    @media (max-width: 660px) { .lv-marque__sous { display: none; } }
    /* PUIS LE NOM : 441 plus 60 ne tiennent plus non plus, il reste le
       signe. */
    @media (max-width: 540px) { .lv-marque__texte { display: none; } }
    @media (max-width: 640px) {
      .lv-marque__signe { width: 44px; height: 44px; flex: 0 0 44px; }
      .lv-marque img { width: 40px; height: 40px; }
      .lv-marque__nom { font-size: 17px; }
    }
    @media (max-width: 420px) { .lv-marque__nom { font-size: 15px; } }
    .lv-pied { display: grid; grid-template-columns: 1.4fr 1fr 1fr; gap: 44px; padding-top: 36px; }
    @media (max-width: 900px) { .lv-pied { grid-template-columns: 1fr; gap: 30px; } }
    .lv-pied__marque { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
    .lv-pied__marque img { width: 32px; height: 32px; }
    .lv-pied__marque span { font-size: 14px; font-weight: 700; color: var(--texte-sur-sombre); }
    .lv-pied__mention { margin: 0; font-size: 13px; line-height: 1.55; color: rgba(var(--white-rgb), 0.5); }
    /* Le credit de realisation n est pas un appel a l action : il prend
       l encre du pied, pas le cyan des liens. Valeurs de vitrine.css. */
    .lv-pied__mention a { color: rgba(var(--white-rgb), 0.62); text-decoration: none; transition: color .18s ease; }
    .lv-pied__mention a:hover, .lv-pied__mention a:focus-visible { color: rgba(var(--white-rgb), 0.95);
      text-decoration: underline; text-underline-offset: 3px; }
    .lv-pied__liens { display: flex; flex-direction: column; gap: 9px; }
    /* Les quatre liens legaux en deux paires : la colonne LEGAL faisait
       quatre lignes quand CONTACT en faisait deux, et le pied descendait
       plus bas a droite qu au milieu. Deux rangees et un remplissage en
       colonne : les deux premiers restent en place, les deux suivants se
       posent a leur droite. */
    .lv-pied__liens--paire { display: grid; grid-auto-flow: column;
      grid-template-rows: repeat(2, auto); justify-content: start;
      column-gap: 28px; row-gap: 9px; }
    .lv-pied__liens a { font-size: 13.5px; color: var(--texte-discret-sur-sombre); }

    /* LE BLOC « DEMANDEZ A L IA », une rangee pleine largeur SOUS les trois
       colonnes. La grille du pied est a `1.4fr 1fr 1fr` : une quatrieme
       colonne serait passee a la ligne de travers, donc le bloc sort de la
       grille au lieu de s y ajouter.

       Les liens gardent la classe `lv-pied__liens` pour heriter de la couleur
       et de la taille des autres liens du pied ; seule la direction change,
       parce que celle-la s empile en colonne. */
    .lv-pied-ia { margin-top: 30px; padding-top: 22px;
      border-top: 1px solid rgba(var(--white-rgb), 0.08); }
    .lv-pied-ia__entete { display: block; margin-bottom: 11px; }
    .lv-pied-ia__liens { flex-direction: row; flex-wrap: wrap;
      gap: 10px 20px; align-items: center; }
    .lv-pied__copyright { margin: 16px 0 0; font-size: 12.5px; line-height: 1.55; color: var(--lv-mention); }

    /* --- LA DEMONSTRATION DU TEST, reprise de vitrine.css ------------------- */
    .lv-demo { position: relative; border-radius: 16px; overflow: hidden;
      border: 1px solid rgba(var(--white-rgb), 0.14); background: rgba(var(--surface-sombre-rgb), 0.55);
      /* Plus d ombre portee : un flou de soixante pixels effacait la grille
         autour du cadre. Il ne reste que l anneau, qui n a pas de flou. */
      box-shadow: 0 0 0 4px rgba(var(--portal-accent-rgb), 0.10); }
    /* Le format de la SOURCE : les images du test sont en 16/9. */
    .lv-demo__cadre { position: relative; aspect-ratio: 16 / 9; overflow: hidden; }
    .lv-demo__image { position: absolute; inset: 0; background-size: cover; background-position: center; }
    .lv-demo__voile { position: absolute; inset: 0; mix-blend-mode: multiply; opacity: 0; pointer-events: none; }
    /* La seconde couche porte l image a venir et monte par-dessus la premiere :
       le fondu se fait d une image a l autre, jamais par le noir. */
    .lv-demo__image--suivante { opacity: 0; transition: opacity .7s ease; }
    .lv-demo__palette { display: grid; grid-template-columns: repeat(6, 1fr); gap: 5px; padding: 8px;
      background: rgba(var(--black-rgb), 0.42); border-top: 1px solid rgba(var(--white-rgb), 0.10); }
    .lv-demo__canal { height: 20px; border-radius: 8px; border: 1px solid rgba(var(--white-rgb), 0.16);
      box-shadow: inset 0 1px 0 rgba(var(--white-rgb), 0.14); opacity: .42;
      transition: opacity .5s ease, transform .5s ease, box-shadow .5s ease; }
    .lv-demo__canal.is-active { opacity: 1; transform: scale(1.08);
      box-shadow: inset 0 1px 0 rgba(var(--white-rgb), 0.22), 0 0 0 2px rgba(var(--white-rgb), 0.72),
                  0 0 16px rgba(var(--white-rgb), 0.32); }
    .lv-demo__canal--r { background: linear-gradient(135deg, var(--red-mid), var(--couleur-danger)); }
    .lv-demo__canal--j { background: linear-gradient(135deg, #a16207, var(--amber-bright)); }
    .lv-demo__canal--v { background: linear-gradient(135deg, #166534, var(--couleur-succes)); }
    .lv-demo__canal--c { background: linear-gradient(135deg, #0f766e, var(--portal-accent)); }
    .lv-demo__canal--b { background: linear-gradient(135deg, #1d4ed8, rgb(var(--blue-rgb))); }
    .lv-demo__canal--m { background: linear-gradient(135deg, #a21caf, #e879f9); }
    /* La legende passe DEVANT l ombre du cadre : l ombre de 60 px de flou
       retombait sur cette ligne et la ternissait. */
    /* 52ch CASSAIT LA LEGENDE EN QUATRE LIGNES COURTES dans une colonne qui
       en porte 76. Mesure du 30/10 en 1440 de large : 378 px de texte pour
       558 px de colonne. 72ch la remplit sans la laisser courir sur un
       ecran large. */
    .lv-demo__legende { position: relative; z-index: 1; max-width: 72ch; margin: 14px 0 0;
      font-size: 13.5px; line-height: 1.55; color: rgba(var(--white-rgb), 0.5); }
    @media (prefers-reduced-motion: reduce) {
      .lv-demo__image--suivante, .lv-demo__canal { transition: none; }
    }

    /* --- LA NEURO-REGULATION MONTREE, reprise de vitrine.css -------------- */
    /* ===== La neuro-regulation, montree =====

       LE RYTHME EST CELUI DU PRODUIT, pas un effet. L'alternance noir/couleur
       entre 1 et 4 Hz EST le geste de regulation ; ici elle est posee a 0,5 Hz,
       soit un battement toutes les deux secondes. C'est la borne basse, adoucie
       par rapport a la seance : sur une page publique, personne n'a depose la
       declaration de contre-indications que le produit exige avant un programme,
       et l'epilepsie en fait partie. On montre le geste, on ne le pratique pas.

       DEUX ANIMATIONS SUR LE MEME ELEMENT, et c'est ce qui rend la chose lisible
       a la lecture. `battement` tient le rythme, `teinte` tient la couleur, et
       elles ne se melangent jamais : la teinte change toutes les six secondes,
       soit exactement trois battements, donc TOUJOURS pendant un noir. Le
       changement de couleur ne se voit pas, on ne voit que la couleur suivante
       arriver au battement d'apres.

       Ecrites en une seule animation de vingt-quatre etapes, il aurait fallu
       recompter tout le tableau a chaque reglage du rythme. */
    .lv-neuro {
        display: flex;
        align-items: center;
        justify-content: center;
    }

    /* 480 et non 340 : la boite du dessin a grandi pour laisser vivre le halo,
       mais le portable, lui, n'a pas change de taille. Sans cette compensation il
       aurait retreci d'un tiers a la premiere correction du flou.

       Les marges negatives reprennent la place que le halo occupe autour de
       l'objet : elle est transparente, et sans elles la section se serait ouverte
       de soixante-dix pixels de vide de chaque cote. */
    .lv-neuro svg {
        width: 100%;
        max-width: 480px;
        height: auto;
        margin: -46px -44px;
    }

    /* Le halo et la dalle partagent leurs deux animations : c'est la meme
       lumiere, l'une dans l'ecran et l'autre autour. */
    .lv-neuro__dalle,
    .lv-neuro__halo {
        animation:
            lv-neuro-battement 2s ease-in-out infinite,
            lv-neuro-teinte 18s linear infinite;
    }

    .lv-neuro__halo { opacity: 0; }

    /* LE CHASSIS EST NEUTRE. Il etait dore, par report de l'icone dont ce trace
       est parti. L'or est la couleur du bouton d'action sur cette page : un objet
       qui la porte en entier en prend le poids sans le meriter. Et un cadre dore
       se bat avec le vert et le rouge qu'il encadre, alors que sa fonction est de
       les laisser parler.

       Legerement chaud plutot que gris pur : c'est ce qui le fait lire comme de
       l'aluminium et non comme un fil de fer. */
    .lv-neuro__coque,
    .lv-neuro__socle {
        stroke: rgba(214, 224, 238, 0.40);
        stroke-width: 2.2;
        stroke-linejoin: round;
    }

    .lv-neuro__coque { fill: #070C15; }
    .lv-neuro__socle { fill: #0B1626; }

    .lv-neuro__camera { fill: rgba(214, 224, 238, 0.34); }

    .lv-neuro__pave {
        fill: none;
        stroke: rgba(214, 224, 238, 0.22);
        stroke-width: 1.4;
        stroke-linejoin: round;
    }

    /* Les touches ne s'allument pas : elles sont dans l'ombre de l'ecran, et un
       clavier qui battrait avec la dalle ferait un objet clignotant au lieu d'un
       ecran allume dans une piece sombre. */
    .lv-neuro__touches rect {
        fill: rgba(214, 224, 238, 0.07);
        stroke: rgba(214, 224, 238, 0.18);
        stroke-width: 0.8;
    }

    @keyframes lv-neuro-battement {
        /* Une montee et une descente adoucies, pas un creneau. Le geste garde sa
           frequence mais perd son arete : c'est la seule liberte prise ici. */
        0%   { opacity: 0; }
        22%  { opacity: 1; }
        50%  { opacity: 1; }
        72%  { opacity: 0; }
        100% { opacity: 0; }
    }

    /* Le halo suit le meme rythme, plus faible : une lumiere d'ecran n'eclaire
       pas la piece autant qu'elle eclaire le visage. */
    .lv-neuro__halo { animation-name: lv-neuro-halo, lv-neuro-teinte; }

    @keyframes lv-neuro-halo {
        0%   { opacity: 0; }
        22%  { opacity: 0.34; }
        50%  { opacity: 0.34; }
        72%  { opacity: 0; }
        100% { opacity: 0; }
    }

    /* Trois battements de bleu, trois de vert, trois de rouge, puis on
       recommence. Les bornes sont doublees a un centieme de pour cent l'une de
       l'autre : c'est ce qui fait un changement net sans passer par un degrade
       qui melangerait les trois. */
    @keyframes lv-neuro-teinte {
        0%, 33.32%      { fill: #2D7DF6; }
        33.33%, 66.65%  { fill: #34C77B; }
        66.66%, 100%    { fill: #E2453D; }
    }

    /* Un battement lumineux ne se force a personne. Sans mouvement, la dalle
       reste allumee sur sa premiere couleur : l'objet se lit toujours comme un
       ecran, il ne bat simplement plus. */
    @media (prefers-reduced-motion: reduce) {
        .lv-neuro__dalle {
            animation: none;
            fill: #2D7DF6;
            opacity: 0.9;
        }

        .lv-neuro__halo {
            animation: none;
            fill: #2D7DF6;
            opacity: 0.28;
        }
    }
    .lv-duo--regulation { align-items: center; }
    @media (min-width: 900px) { .lv-duo--regulation { grid-template-columns: 1.25fr 0.75fr; } }

    /* --- Les deux schemas --------------------------------------------------- */
    .lv-schema { margin: 30px 0 0; }
    .lv-schema svg { display: block; width: 100%; height: auto; }
    .lv-schema figcaption { margin: 14px 0 0; font-size: 13.5px; line-height: 1.55;
      color: rgba(var(--white-rgb), 0.6); max-width: 78ch; }
    .lv-schema__texte { font-size: 12px; fill: rgba(255, 255, 255, 0.62); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; letter-spacing: .06em; }
    .lv-schema__fort { font-size: 13px; font-weight: 700; fill: rgba(255, 255, 255, 0.92); font-family: inherit; letter-spacing: 0; }
    .lv-schema__annee { font-size: 12.5px; font-weight: 700; fill: rgb(var(--portal-gold-rgb)); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }

    /* Ce qui reste a fournir : signale, jamais invente. */
    .lv-attente { color: rgba(var(--portal-gold-rgb), 0.92); border-bottom: 1px dashed rgba(var(--portal-gold-rgb), 0.5); }

/* ==========================================================================
 * LA TABLE DES TARIFS
 * ==========================================================================
 * TROIS RANGEES PARTAGEES, ET TROIS SEULEMENT : le titre, le corps, le
 * bouton. Ce sont les trois choses qui se lisent d'une colonne a l'autre.
 * Tout le reste -- prix, mention, description, puces -- coule DANS le corps,
 * donc une carte qui met deux lignes de remise sous son prix ne fait pas
 * payer la place a celle qui n'en met aucune.
 *
 * CE QUI A ETE APPRIS EN CHEMIN, le 02/10/2026, et qui tient en une phrase :
 * une rangee partagee ne cesse pas de l'etre parce qu'on met son contenu dans
 * une boite, c'est la BOITE qui devient la rangee. Avec le prix dans sa propre
 * rangee, le decaler dans une colonne poussait le depart du corps pour les
 * trois, et rouvrait cinquante pixels de trou chez les deux autres.
 *
 * DEUX BASCULES, DEUX ROLES. Celle du haut change le RYTHME et vaut pour
 * toute la table ; celle de la troisieme carte change le PRODUIT et ne vaut
 * que pour elle. Un seul dessin pour les deux, sinon la page a l'air d'en
 * porter deux especes ; ce qui les distingue est leur PLACE.
 * ========================================================================== */

/* --- la bascule, un dessin pour deux usages -------------------------------
 * LES CINQ PIECES QUI FONT SA HAUTEUR SONT NOMMEES, parce qu'elles servent a
 * la DESSINER et a RESERVER SA PLACE dans la carte professionnelle. Une seule
 * saisie pour les deux : voir `--lv-bascule-h`.
 *
 * Elles vivent sur `.lv-corps` et non sur `.lv-bascule`, et c'est la seule
 * place possible : une variable posee sur la bascule ne remonterait pas a sa
 * tete, les proprietes personnalisees descendent. */
.lv-corps {
  --bascule-cadre: 4px;      /* le creux de la pilule autour des boutons */
  --bascule-filet: 1px;      /* son contour */
  --bascule-creux: 8px;      /* le creux vertical d'un bouton */
  --bascule-police: 10.5px;
  --bascule-ligne: 13px;     /* la hauteur d'une ligne, en longueur */
  --bascule-ecart: 10px;     /* entre le bas du titre et le haut de la pilule */

  --bascule-hauteur: calc(2 * var(--bascule-cadre) + 2 * var(--bascule-filet)
                          + 2 * var(--bascule-creux) + var(--bascule-ligne));
}

.lv-bascule { display: inline-flex; padding: var(--bascule-cadre); gap: 4px;
  border-radius: 999px;
  border: var(--bascule-filet) solid rgba(var(--white-rgb), 0.14);
  background: rgba(var(--white-rgb), 0.04); }

/* L INTERLIGNE EST UNE LONGUEUR, pas un rapport : laisse a `normal`, il depend
   des metriques de la fonte, donc du systeme. */
.lv-bascule__choix { appearance: none; border: 0; cursor: pointer;
  padding: var(--bascule-creux) 16px; line-height: var(--bascule-ligne);
  border-radius: 999px; background: none; font-family: var(--lv-mono);
  font-size: var(--bascule-police);
  letter-spacing: 0.12em; text-transform: uppercase; color: rgba(var(--white-rgb), 0.58);
  transition: color .18s ease, background .18s ease; }

.lv-bascule__choix:hover { color: rgba(var(--white-rgb), 0.88); }

.lv-bascule__choix[aria-selected="true"] {
  background: rgba(var(--lv-teinte, var(--portal-accent-rgb)), 0.18);
  color: var(--texte-sur-sombre);
  box-shadow: inset 0 0 0 1px rgba(var(--lv-teinte, var(--portal-accent-rgb)), 0.42); }

/* `display: flex` seul la rendrait bloc, donc large de tout le conteneur, et
   `margin: auto` n'aurait plus rien a centrer. Mesure : 1 168 px dans 1 240. */
.lv-bascule--rythme { --lv-teinte: var(--portal-gold-rgb); margin: 26px auto 0;
  display: flex; width: max-content; max-width: 100%; }

/* L'economie se dit SUR le choix : posee a cote, elle devient une chose de
   plus a lire ; ici elle est l'argument du bouton qu'on hesite a prendre. */
.lv-bascule__gain { margin-left: 8px; padding: 2px 7px; border-radius: 999px;
  background: rgba(var(--portal-gold-rgb), 0.18); color: rgb(var(--portal-gold-rgb));
  font-size: 9.5px; letter-spacing: 0.06em; }

/* --- la tete de carte ----------------------------------------------------- */
/* `--lv-bascule-h` est la place reservee sous le titre ET le retrait du corps
   de cette carte. Une seule valeur pour les deux : separees, elles se
   desynchronisent au premier ajustement de police. */
/* LA TETE RESPIRE SOUS ELLE, et pas au-dessus du prix : la marge est portee
   par la rangee partagee, donc les trois colonnes la prennent ensemble. Posee
   sur le prix, elle se serait ajoutee au retrait de la carte professionnelle
   et aurait decale celle-la seule.

   LA PLACE DE LA BASCULE SE DEDUIT DE SA TAILLE. `47px` etait un nombre
   magique : sa hauteur mesuree un jour, recopiee ici a la main. Changer la
   police ne demande plus de se souvenir du second endroit, il n'y en a plus. */
.lv-tarif__tete {
  position: relative;
  margin-bottom: 14px;
  --lv-bascule-h: calc(var(--bascule-ecart) + var(--bascule-hauteur)); }
.lv-tarif__tete .lv-colonne__entete { margin: 0; }

/* HORS DU FLUX, SINON ELLE GROSSIT LA RANGEE DES TITRES, qui est partagee :
   les deux autres colonnes paieraient sa hauteur sans rien y mettre. Mesure
   avant correction : 67 px entre le titre et le prix, dans les trois. */
.lv-tarif__tete .lv-bascule--produit {
  position: absolute; top: calc(100% + var(--bascule-ecart));
  /* A gauche, sur la ligne que tiennent le titre, le prix, le texte et les
     puces. Centree, elle etait le seul element de la colonne a ne pas la
     tenir. */
  left: 0; right: auto; margin: 0;
  width: max-content; max-width: 100%;
  --lv-teinte: var(--portal-blue-rgb); }

.lv-tarif__tete .lv-bascule__choix { flex: 0 0 auto; padding: var(--bascule-creux) 14px;
  letter-spacing: 0.10em; }

/* --- le corps, et le retrait de la carte qui porte une bascule ------------ */
.lv-tarif__corps { display: flex; flex-direction: column; }
/* La tete porte le calcul ; le corps, qui est son frere, ne l'herite pas.
   On le refait ici depuis les memes jetons plutot que de dupliquer une
   valeur : les jetons, eux, sont a un seul endroit. */
.lv-trois--tarifs > .lv-carte:has(.lv-bascule--produit) > .lv-tarif__corps {
  margin-top: calc(var(--bascule-ecart) + var(--bascule-hauteur)); }

@media (min-width: 860px) {
  .lv-trois--tarifs { grid-template-rows: auto 1fr auto; }
  .lv-trois--tarifs > .lv-carte { grid-row: span 3; }
}

/* --- la pile : rien ne bouge quand on change de produit -------------------
 * Toutes les variantes sont POSEES, superposees dans la meme cellule : la
 * cellule prend la taille de la plus haute, quelle qu'elle devienne. Un
 * `min-height` choisi a la main serait juste aujourd'hui et faux au premier
 * mot ajoute, en silence.
 *
 * `visibility` et NON `display: none` : le second retirerait la place avec la
 * boite. Et une CLASSE, pas l'attribut `hidden` : le defaire par
 * `display: revert` rend la valeur du NAVIGATEUR, pas celle de l'auteur -- une
 * liste en `flex` y repassait a `block` et perdait ses gouttieres.
 *
 * LE RYTHME, LUI, A LE DROIT DE DECALER (`--hors`). Reserver la place de la
 * ligne d'economie au mois y ferait un trou qu'aucun contenu n'occupera
 * jamais. On compare deux PRODUITS en basculant de l'un a l'autre ; un
 * rythme, on le choisit une fois. */
.lv-pile { display: grid; }
.lv-pile > * { grid-area: 1 / 1; }
.lv-pile__variante--cachee { visibility: hidden; pointer-events: none; }
.lv-pile__variante--hors { display: none; }

/* --- ce qui suit le prix -------------------------------------------------- */
.lv-prix__gain { display: block; margin-top: 10px; font-size: 12.5px; line-height: 1.4;
  color: rgb(var(--portal-gold-rgb)); }

/* Le prix mensuel barre, quand on regarde l'annee : un repere, pas une
   promotion. */
.lv-prix__avant { display: inline-block; margin-left: 10px; font-size: 15px; font-weight: 700;
  color: rgba(var(--white-rgb), 0.38); text-decoration: line-through; }

/* Les chiffres qui comptent, en chasse fixe : en chasse proportionnelle, un 1
   plus etroit qu'un 8 fait trembler tout ce qui suit pendant l'animation. */
.pnum { font-variant-numeric: tabular-nums; }
/* --- LA FLECHE DE LA COLONNE D ESSAI --------------------------------------
 * Elle remplit la place que cette colonne paie sans l'occuper -- trois points
 * contre six -- et elle montre le bouton.
 *
 * `margin-top: auto` LA POUSSE CONTRE LE BOUTON, et c'est ce qu'elle doit
 * faire : une fleche qui designe se tient pres de ce qu'elle designe. Centree
 * dans le vide, elle montrait le bouton de loin et le blanc se repartissait
 * de part et d'autre d'elle ; collee en bas, le blanc se rassemble au-dessus,
 * la ou il se lit comme de l'air apres la liste.
 *
 * Et `auto` plutot qu'une hauteur : elle suit le contenu, au lieu d'etre calee
 * a une valeur qui serait fausse des qu'une ligne change.
 *
 * ELLE EST DEJA BLANCHE ET DEJA TOURNEE : le fichier porte le trait en blanc
 * et la pointe vers le bas. Un `filter: invert(1)` coute une passe de
 * composition a chaque peinture, et un `rotate(90deg)` tournerait le dessin
 * sans tourner sa BOITE, laissant la mise en page reserver une place large
 * pour une image devenue haute.
 *
 * ELLE DISPARAIT DES QUE LES COLONNES S EMPILENT : sous 860 px il n'y a plus
 * de vide a remplir, et une fleche qui montre un bouton deja colle a elle ne
 * montre plus rien. */
.lv-tarif__fleche {
  display: block;
  width: 104px;
  height: auto;
  margin: auto auto 0;
  opacity: 0.3;
  pointer-events: none;
}

@media (max-width: 859px) { .lv-tarif__fleche { display: none; } }


/* ===========================================================================
   LES PAGES PUBLIQUES SECONDAIRES : /demandes et /tarifs
   ---------------------------------------------------------------------------
   Elles portent la meme coquille que la landing depuis le 20/10/2026. Ce qui
   suit ne concerne QUE leur contenu ; la coquille, elle, n'a besoin de rien de
   nouveau, c'est tout l'interet de l'avoir partagee.

   LES NOMS EVITENT `lv-demande`, DEJA PRIS. `.lv-demandes` existe plus haut et
   designe la ligne de noms sous l'accroche d'un domaine, sur la landing : deux
   regles du meme nom pour deux choses auraient fait gagner la derniere ecrite,
   c'est-a-dire celle-ci, et casse l'accroche. D'ou `lv-fiche`.
   ========================================================================= */

/* --- Le catalogue des demandes, par domaine ------------------------------ */

/* Les trois regles de `.lv-fiche` vivaient ICI et plus bas, avec des valeurs
   differentes. A selecteur et poids egaux, la derniere ecrite gagne : ce bloc
   ne s'appliquait nulle part, et quiconque l'aurait ajuste n'aurait rien vu
   changer. Les valeurs qui servent sont celles du bloc d'en bas, sous « le
   catalogue par domaine ». Retire le 22/10/2026. */


/* --- Le simulateur de la page des tarifs --------------------------------- */

.lv-simu__ligne {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 10px 16px;
    margin-bottom: 18px;
}

.lv-simu__valeur {
    font-variant-numeric: tabular-nums;
    font-size: clamp(26px, 3.4vw, 34px);
    font-weight: 600;
    line-height: 1;
    color: rgba(var(--portal-gold-rgb), 0.95);
}

/* Le curseur : la piste du portail, la poignee en or. On redessine les deux
   moteurs (WebKit et Gecko) parce qu'aucun ne partage le pseudo-element de
   l'autre ; une seule des deux regles laisserait un curseur natif bleu. */
.lv-simu__curseur {
    -webkit-appearance: none;
    appearance: none;
    width: 100%;
    max-width: 460px;
    height: 24px;
    margin: 0;
    background: transparent;
    cursor: pointer;
}

.lv-simu__curseur::-webkit-slider-runnable-track {
    height: 4px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.14);
}

.lv-simu__curseur::-moz-range-track {
    height: 4px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.14);
}

.lv-simu__curseur::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 18px;
    height: 18px;
    /* `margin-top` recentre la poignee sur une piste de 4 px : (4 − 18) / 2. */
    margin-top: -7px;
    border: 0;
    border-radius: 50%;
    background: rgba(var(--portal-gold-rgb), 0.95);
    box-shadow: 0 0 0 4px rgba(var(--portal-gold-rgb), 0.16);
}

.lv-simu__curseur::-moz-range-thumb {
    width: 18px;
    height: 18px;
    border: 0;
    border-radius: 50%;
    background: rgba(var(--portal-gold-rgb), 0.95);
    box-shadow: 0 0 0 4px rgba(var(--portal-gold-rgb), 0.16);
}

/* LE CONTOUR DU FOCUS SE RECOLORE, IL NE SE RETIRE PAS. Le defaut du
   navigateur dessinait un cadre bleu autour de la piste, hors de la palette ;
   `outline: none` aurait rendu le curseur inutilisable au clavier. */
.lv-simu__curseur:focus-visible {
    outline: 2px solid rgba(var(--portal-gold-rgb), 0.45);
    outline-offset: 3px;
    border-radius: 999px;
}

.lv-simu__curseur:focus-visible::-webkit-slider-thumb {
    box-shadow: 0 0 0 4px rgba(var(--portal-gold-rgb), 0.32);
}

.lv-simu__curseur:focus-visible::-moz-range-thumb {
    box-shadow: 0 0 0 4px rgba(var(--portal-gold-rgb), 0.32);
}

/* Les trois reponses, cote a cote : c'est la comparaison qui porte le sens. */
.lv-simu__reponses {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 16px;
    margin: 26px 0 8px;
}

.lv-simu__reponse {
    padding: 16px 18px;
    border-radius: 14px;
    border: 1px solid var(--portal-border);
    /* LA TEINTE EST CELLE DE LA COURBE, et c'est ce qui fait la legende : sans
       elle, trois boites grises ne disent pas quel trace leur correspond.
       Le repli `--portal-border` sert aux boites qui n'en portent pas, comme
       les montants des cartes de formule. */
    border-left: 3px solid rgba(var(--lv-teinte, 255, 255, 255), 0.75);
    background: rgba(255, 255, 255, 0.02);
}

.lv-simu__nom {
    display: block;
    margin-bottom: 8px;
    font-size: 12px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--portal-muted);
}

.lv-simu__nombre {
    font-variant-numeric: tabular-nums;
    font-size: clamp(30px, 4vw, 40px);
    font-weight: 600;
    line-height: 1;
    color: var(--portal-text);
}

.lv-simu__unite {
    display: block;
    margin-top: 6px;
    font-size: 13px;
    color: var(--portal-muted);
}

/* La courbe. Hauteur fixe en ratio pour que le trace ne saute pas pendant que
   la page finit de charger ses polices. */
.lv-simu__courbe {
    width: 100%;
    /* `height: auto` SEUL NE SUFFIT PAS sur un SVG en ligne sans attributs de
       dimension : mesure du 20/10/2026, la boite rendait 0 px de haut et la
       courbe etait invisible alors qu'elle etait bien tracee. Le rapport
       reprend celui du `viewBox`, et c'est lui qui donne la hauteur. */
    aspect-ratio: 720 / 300;
    height: auto;
    margin-top: 26px;
    overflow: visible;
}

.lv-simu__reserve {
    margin: 18px 0 0;
    font-size: 13px;
    line-height: 1.5;
    color: var(--portal-muted);
    opacity: 0.85;
}

/* SANS JAVASCRIPT, LA COURBE N'A AUCUN SENS : elle est vide. On la cache donc
   par defaut et le script la montre. Les trois nombres, eux, sont rendus par
   le serveur et restent lisibles. */
.lv-simu__courbe[hidden] { display: none; }

/* --- Le glyphe devant les assistants, dans le pied ----------------------- */

.lv-pied-ia__glyphe {
    /* `em` et pas `px` : le glyphe suit la taille du lien, quel que soit le
       palier d'ecran qui la fixe. */
    width: 1em;
    height: 1em;
    margin-right: 7px;
    /* Un glyphe aligne sur sa ligne de base flotte au-dessus du texte : on le
       descend du quart de son corps pour le centrer optiquement. */
    vertical-align: -0.15em;
    opacity: 0.72;
}

.lv-pied-ia__liens a:hover .lv-pied-ia__glyphe {
    opacity: 1;
}

/* --- Les cartes des pages secondaires, aux proportions de la maison ------- */

/* MESURE DU 20/10/2026 : la carte la plus large de la landing fait 558 px, et
   ses titres de section 30 px. Les pages secondaires rendaient des cartes de
   1 168 px avec des titres de 14,5 px, c'est-a-dire deux fois trop large et
   deux fois trop petit. Une grille remet les cartes a la largeur du site. */
.lv-grille-cartes {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: 22px;
    /* `start` et pas l'etirement par defaut : sinon la carte la plus courte
       prend la hauteur de la plus longue et se remplit de vide. */
    align-items: start;
}

/* --- Les etapes d'un parcours : DEUX pistes, jamais trois ---------------- */

/* MESURE DU 28/10/2026, page des possesseurs en 1440 px : les quatre etapes
   heritaient de `lv-grille-cartes` et se posaient 3 + 1, la derniere seule sur
   sa ligne. Une suite d'etapes qui se lit 3 + 1 perd ce qu'elle veut montrer,
   c'est-a-dire l'ordre.
   Deux pistes fixes, et non `auto-fit` : c'est le NOMBRE d'etapes qui commande
   ici, pas la largeur disponible. */
.lv-grille-parcours {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (max-width: 700px) {
    .lv-grille-parcours { grid-template-columns: 1fr; }
}

/* Le titre de section des pages secondaires, pris sur `lv-titre` de la
   landing. Il s'ecrit ici parce que `lv-titre` y porte aussi des marges de
   section que ces pages n'ont pas. */
/* 24 px et non 30. A 30, ce titre de section arrivait a 1,29 fois le titre de
   la page une fois celui-ci ramene a 38 px : deux rangs d'importance qui se
   lisent comme un seul, et une page qui crie partout. L'accueil tient 1,87
   (56 contre 30), et c'est ce rapport-la qu'on retrouve ici avec 38 contre
   24. Mesure du 22/10/2026. */
.lv-titre-page {
    margin: 0 0 18px;
    font-size: clamp(19px, 1.9vw, 24px);
    font-weight: 900;
    line-height: 1.2;
    letter-spacing: -0.01em;
    text-wrap: balance;
    color: var(--portal-text);
}

/* LA COURBE NE DEPASSE PAS SA TAILLE DE DESSIN. Son `viewBox` fait 720 px de
   large ; etiree a 1 126 px elle rendait 469 px de haut, soit la moitie d'un
   ecran pour un graphique de lecture. Au-dela de 720 elle se centre. */
.lv-simu__courbe {
    max-width: 720px;
    margin-inline: auto;
    display: block;
}

/* LA CARTE DU SIMULATEUR SE RESSERRE SUR SON CONTENU. Pleine largeur, elle
   laissait la courbe (720 px de dessin) flotter au milieu de 1 168 px de vide.
   A 820 px la courbe touche presque les bords, les trois reponses font 250 px
   chacune, et le bloc se lit comme un outil plutot que comme un panneau. */
.lv-carte--outil {
    max-width: 820px;
    margin-inline: auto;
}

/* --- Le calculateur de rentabilite, section de /tarifs ------------------- */

/* EN DEUX COLONNES, parce qu'on compare : le curseur et la courbe doivent
   tenir dans le meme regard. Empiles, on reglait un prix en haut et on allait
   chercher son effet en bas. En dessous de 900 px la grille se replie seule,
   `auto-fit` sur un minimum de 300 px. */
.lv-calcul {
    display: grid;
    grid-template-columns: minmax(280px, 0.85fr) minmax(300px, 1.15fr);
    gap: 26px 34px;
    align-items: start;
    margin-top: 26px;
}

@media (max-width: 860px) {
    .lv-calcul { grid-template-columns: 1fr; }
}

.lv-calcul__intitule {
    display: block;
    font-size: 13px;
    color: var(--portal-muted);
}

.lv-calcul__prix {
    display: block;
    margin: 2px 0 12px;
    font-variant-numeric: tabular-nums;
    font-size: clamp(30px, 3.6vw, 40px);
    font-weight: 700;
    line-height: 1.05;
    color: rgba(var(--portal-gold-rgb), 0.95);
}

/* Le curseur : la piste du portail, la poignee en or. On redessine les deux
   moteurs (WebKit et Gecko) parce qu'aucun ne partage le pseudo-element de
   l'autre ; une seule des deux regles laisserait un curseur natif bleu. */
.lv-calcul__curseur {
    -webkit-appearance: none;
    appearance: none;
    width: 100%;
    height: 22px;
    margin: 0 0 18px;
    background: transparent;
    cursor: pointer;
}

.lv-calcul__curseur::-webkit-slider-runnable-track {
    height: 4px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.14);
}

.lv-calcul__curseur::-moz-range-track {
    height: 4px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.14);
}

.lv-calcul__curseur::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 17px;
    height: 17px;
    /* `margin-top` recentre la poignee sur une piste de 4 px : (4 − 17) / 2. */
    margin-top: -6.5px;
    border: 0;
    border-radius: 50%;
    background: rgba(var(--portal-gold-rgb), 0.95);
    box-shadow: 0 0 0 4px rgba(var(--portal-gold-rgb), 0.16);
}

.lv-calcul__curseur::-moz-range-thumb {
    width: 17px;
    height: 17px;
    border: 0;
    border-radius: 50%;
    background: rgba(var(--portal-gold-rgb), 0.95);
    box-shadow: 0 0 0 4px rgba(var(--portal-gold-rgb), 0.16);
}

/* LE CONTOUR DU FOCUS SE RECOLORE, IL NE SE RETIRE PAS : le defaut du
   navigateur dessine un cadre bleu hors palette, et `outline: none` rendrait
   le curseur inutilisable au clavier. */
.lv-calcul__curseur:focus-visible {
    outline: 2px solid rgba(var(--portal-gold-rgb), 0.45);
    outline-offset: 3px;
    border-radius: 999px;
}

/* Les trois reponses en colonne sous le curseur : c'est leur ordre de prix,
   et il ne change jamais. */
.lv-calcul__reponses {
    display: grid;
    gap: 10px;
}

.lv-calcul__reponse {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: baseline;
    gap: 4px 12px;
    padding: 10px 14px;
    border-radius: 12px;
    border: 1px solid var(--portal-border);
    /* LA TEINTE EST CELLE DE SA COURBE, et c'est ce qui fait la legende :
       sans elle, trois lignes grises ne disent pas quel trace leur repond. */
    border-left: 3px solid rgba(var(--lv-teinte, 255, 255, 255), 0.75);
    background: rgba(255, 255, 255, 0.02);
}

.lv-calcul__nom {
    grid-column: 1;
    font-size: 12px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--portal-muted);
}

.lv-calcul__nombre {
    grid-column: 2;
    grid-row: 1 / span 2;
    font-variant-numeric: tabular-nums;
    font-size: 30px;
    font-weight: 700;
    line-height: 1;
    color: var(--portal-text);
}

.lv-calcul__unite {
    grid-column: 1;
    font-size: 12px;
    color: var(--portal-muted);
    opacity: 0.8;
}

/* `aspect-ratio` ET PAS `height: auto` seul : un SVG en ligne sans attributs
   de dimension rend 0 px de haut. Le rapport reprend celui du `viewBox`. */
.lv-calcul__courbe {
    display: block;
    width: 100%;
    aspect-ratio: 560 / 300;
    height: auto;
    overflow: visible;
}

/* Sans JavaScript la courbe est vide : elle reste cachee, les trois chiffres
   rendus par le serveur restent lisibles. La reprise est explicite parce que
   `[hidden]` vient de la feuille du navigateur, en (0,1,0), et perdrait
   contre la regle de classe ci-dessus. */
.lv-calcul__courbe[hidden] { display: none; }

/* Les lots de credits, en ligne : quatre paliers courts se lisent cote a cote
   et n'ont pas besoin d'une colonne chacun. */
.lv-calcul__lots {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 22px;
    margin: 10px 0 0;
    padding: 0;
    list-style: none;
    font-size: 13px;
    color: var(--portal-muted);
}

.lv-calcul__lots strong { color: var(--portal-text); }

/* --- Les sept domaines de /demandes, a plat ------------------------------ */

/* PAS DE CARTES. Sept panneaux en colonnes faisaient sept boites a ouvrir du
   regard, alors qu'on vient chercher UN mot : la demande qu'on entend tous
   les jours. Un filet suffit a separer deux domaines. */
/* PAS DE FILET ENTRE DEUX DOMAINES : depuis le 22/10/2026 c'est la bande qui
   les separe, un sur deux, comme la landing separe ses sections. Deux
   separateurs pour une seule frontiere font un bricolage, et le trait
   survivait en plus a l'interieur d'une bande, ou il n'a rien a delimiter. */

.lv-domaine__titre {
    margin: 0 0 6px;
    font-size: clamp(19px, 2vw, 23px);
    font-weight: 800;
    line-height: 1.25;
    color: rgba(var(--portal-gold-rgb), 0.92);
}

.lv-domaine__chapo {
    max-width: 68ch;
    margin: 0 0 22px;
    font-size: 14px;
    line-height: 1.6;
    color: var(--portal-muted);
}

/* Trois colonnes de texte, qui se replient seules. 280 px est la largeur
   au-dessous de laquelle une description de trois lignes en fait six. */
.lv-fiches {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 20px 32px;
}

.lv-fiche__titre {
    margin: 0 0 5px;
    font-size: 15px;
    font-weight: 600;
    line-height: 1.3;
    color: var(--portal-text);
}

.lv-fiche__texte {
    margin: 0;
    font-size: 13.5px;
    line-height: 1.55;
    color: var(--portal-muted);
}


/* --- Le point de bascule, sous la courbe --------------------------------- */

/* UNE LIGNE PAR FORMULE, pas une seconde courbe : le seul vrai croisement de
   l'offre doit se voir sans alourdir la page. En or, parce que c'est ce qu'on
   vient chercher, et discret parce que ce n'est pas une promesse. */
.lv-calcul__bascules {
    margin: 20px 0 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: 6px;
}

.lv-calcul__bascules li {
    padding-left: 16px;
    position: relative;
    font-size: 14px;
    line-height: 1.5;
    color: rgba(var(--portal-gold-rgb), 0.9);
}

/* Le chevron est pose par la feuille, pas ecrit dans le gabarit : une puce
   n'est pas du contenu, et un lecteur d'ecran n'a pas a l'entendre. */
.lv-calcul__bascules li::before {
    content: "›";
    position: absolute;
    left: 0;
    opacity: 0.7;
}


/* La note du calculateur : prix du credit et paliers.

   PAS `lv-note`, qui vient de la landing avec un `max-width` de 323 px taille
   pour une ligne sous un bouton centre. Ici la note court sous une section en
   deux colonnes : a 323 px elle rendait trois lignes dont la derniere portait
   deux mots. Mesure du 22/10/2026. */
.lv-calcul__note {
    max-width: 72ch;
    margin: 22px 0 0;
    font-size: 13px;
    line-height: 1.6;
    color: var(--portal-muted);
}

/* --- Le corps de texte des pages secondaires ----------------------------- */

/* UNE MESURE DE LECTURE, et c'est tout ce que ces deux regles font.

   Mesure du 22/10/2026 sur la page « du logiciel a la version en ligne » :
   ses paragraphes portaient `lv-chapo`, plafonne a 484 px -- juste sous un
   titre de hero, beaucoup trop etroit pour un corps de texte, qui se coupait
   en lignes de six mots dans une section de 1 240 px. Et ses puces n'avaient
   aucun plafond : 1 168 px par ligne, soit le double de ce qu'un oeil suit
   sans perdre le debut de la ligne suivante.

   68ch tient autour de 70 caracteres, la mesure usuelle d'un texte courant. */
.lv-texte-page {
    max-width: 68ch;
    margin: 0 0 14px;
    font-size: 15px;
    line-height: 1.65;
    color: var(--portal-muted);
}

/* --- Deux points secondaires, cote a cote -------------------------------- */

/* Ils tenaient chacun une section entiere : un titre de 30 px et deux lignes
   dans une bande pleine hauteur, soit beaucoup de vide pour peu de texte et
   une importance qu'ils n'ont pas. Cote a cote, ils se lisent en un regard et
   rendent la place au reste. */
.lv-deux-colonnes {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 26px 44px;
    align-items: start;
}

/* Un titre de rang secondaire : il annonce sans peser. */
.lv-titre-mineur {
    margin: 0 0 10px;
    font-size: clamp(17px, 1.6vw, 20px);
    font-weight: 800;
    line-height: 1.3;
    color: rgba(var(--portal-gold-rgb), 0.92);
}

/* --- Le pied a quatre colonnes ------------------------------------------ */

/* La colonne des pages s'ajoute aux trois d'origine (marque, contact, legal).
   La regle vit ICI et non dans `vitrine.css` : la landing precedente partage
   `.lv-pied` sans porter cette colonne, et une quatrieme piste lui aurait
   laisse un vide a droite. `landing-tunnel.css` est chargee apres, donc elle
   gagne, et seulement sur les pages qui la chargent. */
.lv-pied {
    grid-template-columns: 1.3fr 1fr 1fr 1fr;
}

@media (max-width: 900px) {
    .lv-pied { grid-template-columns: 1fr; }
}

/* --- Le titre d'une page secondaire ------------------------------------- */

/* MEME TAILLE, DEUX POIDS TRES DIFFERENTS. `.lv-hero__titre` monte a 56 px,
   et c'est juste sur l'accueil : il y vit dans la colonne gauche d'une
   ouverture a deux colonnes, soit 641 px de large, ou il se replie sur
   quatre lignes. Pose seul sur une page secondaire, le meme reglage s'etale
   sur 1 168 px d'une seule traite : ce n'est plus un titre, c'est une
   banniere, et elle ecrase les 29 px des titres de section juste en dessous.
   Mesure du 22/10/2026, relevee par l'Admin avant moi.

   On ramene donc deux choses : la taille, et surtout la JUSTIFICATION. Un
   titre qui se replie sur deux lignes retrouve le rythme de l'accueil sans
   lui emprunter sa hauteur. */
.lv-hero--page .lv-hero__titre {
    font-size: clamp(27px, 3vw, 38px);
    max-width: 24ch;
    line-height: 1.12;
}

/* Le chapo suit, sinon il devient aussi large que le titre est court. */
.lv-hero--page .lv-chapo {
    max-width: 62ch;
}

/* --- Les cadres des captures suivent le format des captures -------------- */

/* LE 1,6 VENAIT DES IMAGES DE SEPTEMBRE, et elles ne sont plus la. Pose dans
   un cadre qui n'est pas au sien, l'image se range au milieu avec
   `object-fit: contain` et laisse une bande vide. Mesure sur la production
   avant correction : 473 x 296 de cadre pour une image rendue en 473 x 266,
   soit trente pixels de vide, et 334 x 209 contre 334 x 188 sur les
   vignettes.

   DEUX SERIES, DONC DEUX RAPPORTS. Le carrousel du hero porte les DECOUPES
   (1617 x 1004, soit 1,611) : ni rail ni barre du haut, comme l'Admin l'a
   demande. Les vignettes montrent l'INTERFACE entiere (1920 x 1080, soit
   1,778). Un seul rapport pour les deux remettrait des bandes sur l'une ou
   sur l'autre.

   Les deux regles vivent ICI et non dans `vitrine.css` : la landing
   precedente partage ces classes et garde, elle, les images de 1,6. */
.lv-pages__cadre {
    aspect-ratio: 1617 / 1004;
}

.lv-vignette__image {
    aspect-ratio: 16 / 9;
}
