/* ============================================================================
   SURFACES D'ACHAT — fenêtre des formules, feuille de téléchargement, mur de
   quota, encart de vente.
   ----------------------------------------------------------------------------
   Mesuré le 07/09 avant intervention : aucune de ces quatre surfaces n'avait la
   moindre règle. La fenêtre des formules rendait un bloc de 1 280 × 1 215 px
   avec un voile de fond de 0 px de haut — ce n'était pas une fenêtre, c'était
   une pile de texte poussant la page vers le bas.

   CE QUE CES QUATRE SURFACES ONT EN COMMUN : ce sont des zones de DÉCISION. On
   n'y navigue pas, on y choisit. D'où trois règles tenues partout :

   1. Elles sont CLAIRES quel que soit le thème du site. Les jetons sont donc
      figés en clair sur la racine de chaque surface, et tout le reste continue
      de s'écrire en jetons — aucune valeur en dur au-delà de ce bloc.
   2. UN SEUL aplat bleu par surface. Le bleu dit « l'action est ici » ; deux
      aplats rendent l'endroit du clic incertain, ce qui est exactement le
      défaut qu'on ne peut pas se permettre au moment de payer.
   3. Le PRIX est le seul grand caractère. Chiffres à chasse fixe : un prix qui
      change au basculement mensuel/annuel ne doit pas faire sauter la carte.

   Le violet (--c-premium) reste réservé au marqueur Studio, une fois par écran.
   Aucun vert, conformément à la charte.
   ========================================================================== */

/* Palette figée en clair — reprise EXACTE des jetons clairs du socle. C'est le
   seul endroit de ce fichier où une couleur est écrite. */
.klpm-panel,
.klsheet,
.klc-offer,
.kloffre,
.tho-errbox.is-offre{
  --c-bg-2:#f5f6f8;
  --c-surface:#ffffff;
  --c-surface-2:#eef0f3;
  --c-ink:#111417;
  --c-ink-2:#5b6470;
  --c-ink-3:#8a919c;
  --c-line:#e1e4e9;
  --c-line-strong:#8a919c;
  --c-action:#1f55e6;
  --c-action-hover:#1746c4;
  --c-action-soft:#e9efff;
  --c-on-action:#ffffff;
  --c-premium:#6d28d9;
  --c-premium-soft:#f1eaff;
  color:var(--c-ink);
}

/* ══════════════════════════════════════════════════════════════════════════
   0 — CONTENEUR COMMUN DES FEUILLES (.kfeuille) — chantier D
   Markup de référence : templates/partials/feuille.html. Contrat vérifié par
   tests/test_feuilles_animees.py : les CINQ feuilles du site portent
   `.kfeuille` sur leur voile, `.kfeuille-panneau` sur le panneau qui glisse,
   et appellent `klFeuille($el, <état>, $refs.<panneau>)` (app.js).

   CE QUE CETTE SECTION AJOUTE, ET RIEN D'AUTRE : la SORTIE.
   L'entrée était déjà animée et validée — `klpm-in` centré, `klpm-up` en bas
   d'écran, `modal-sheet-up` pour la connexion — et elle n'est pas touchée :
   elle repart d'elle-même à chaque passage de `display:none` à visible. La
   fermeture, elle, était INSTANTANÉE : `x-show` pose `display:none` au moment
   même du clic (mesuré le 12/09/2026 à 390 px : panneau peint à t=0, disparu
   à t=11 ms, aucune animation en cours). `app.js::klFeuille` défait ce
   `display:none` le temps d'une animation de sortie, marque le voile
   `kf-sort`, et le repose à `animationend` — plafonné à 220 ms, pour qu'une
   animation avortée ne laisse jamais une feuille collée à l'écran.

   La sortie est le MIROIR de l'entrée de la même feuille : fondu + 10 points
   là où la feuille est centrée (ordinateur), glissement vers le bas là où
   elle est ancrée au bas de l'écran. Le choix se fait dans les médias-requêtes
   DÉJÀ écrites par chaque famille (719 px pour la fenêtre des formules, 639 px
   pour les feuilles de vente, 640 px pour la connexion) : ces seuils sont
   validés, ce n'est pas ce chantier qui les déplace.

   `opacity` et `transform` seulement — règle de design du projet. */

@keyframes kf-sortie-fondu{from{opacity:1;transform:none}to{opacity:0;transform:translateY(10px)}}
@keyframes kf-sortie-bas{from{transform:none}to{transform:translateY(100%)}}

.kfeuille.kf-sort > .kfeuille-panneau{animation:kf-sortie-fondu 180ms var(--ease) both}
/* Mouvement refusé : la feuille s'en va sans glisser. `klFeuille` lit la même
   préférence et ne perd alors aucun temps à attendre une animation. */
@media (prefers-reduced-motion:reduce){
  .kfeuille.kf-sort > .kfeuille-panneau{animation:none}
}

/* ══════════════════════════════════════════════════════════════════════════
   1 — FENÊTRE DES FORMULES (.klpm) — le CTA universel
   ══════════════════════════════════════════════════════════════════════════ */

.klpm[style*="display: none"]{display:none}
/* ZONE RÉELLEMENT VUE — voir app.js. Sur iPhone un élément fixé se place dans le
   cadre de mise en page, qui passe sous la barre d'adresse en haut et sous la
   barre d'outils en bas : une couche à `inset:0` glisse dessous, et le bouton de
   fermeture avec elle. Les deux mesures valent 0 partout ailleurs. */
/* `safe center` : centré tant que ça tient, ferré en haut sinon — `center` seul
   rend le haut d'un contenu trop grand INATTEIGNABLE, même en défilant, et c'est
   là que se trouve la fermeture. */
.klpm{position:fixed;top:var(--klat-vue-haut,0px);bottom:var(--klat-dock-bas,0px);
  left:0;right:0;z-index:9600;display:grid;place-items:center;place-items:safe center;
  padding:var(--s-4);overflow-y:auto;overscroll-behavior:contain}
.klpm-scrim{position:fixed;inset:0;background:var(--c-scrim);
  backdrop-filter:blur(2px)}
.klpm-panel{position:relative;z-index:1;width:min(64rem,100%);overscroll-behavior:contain;
  /* 100vh vaut la fenêtre BARRES REPLIÉES : la carte dépassait de ce qui est vu.
     Le cadre étant borné à la zone vue, 100 % de celui-ci est la mesure juste. */
  max-height:100%;overflow-y:auto;
  background:var(--c-surface);border-radius:var(--r-3);
  box-shadow:0 24px 64px rgba(9,12,18,.32);
  animation:klpm-in 220ms var(--ease) both}
@keyframes klpm-in{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.klpm-panel{animation:none}}

.klpm-close{position:absolute;top:var(--s-4);right:var(--s-4);z-index:2;
  display:grid;place-items:center;width:var(--control-h-sm);height:var(--control-h-sm);
  border:0;border-radius:var(--r-pill);background:var(--c-surface-2);
  color:var(--c-ink-2);cursor:pointer}
.klpm-close:hover{background:var(--c-line);color:var(--c-ink)}
.klpm-close:focus-visible{outline:2px solid var(--c-focus);outline-offset:2px}

.klpm-body{padding:var(--s-7) var(--s-5) var(--s-6)}
@media (min-width:720px){.klpm-body{padding:var(--s-7) var(--s-7) var(--s-6)}}

.klpm-head{text-align:center;max-width:36rem;margin-inline:auto}
/* La marque en tête : elle dit de qui vient l'offre, sans occuper la place du
   titre. L'icône et le logo du site, les mêmes fichiers que l'en-tête (4.11),
   à la hauteur de l'ancien carré pour que l'en-tête ne grandisse pas ; la
   largeur découle des attributs width/height des images (rapport conservé,
   aucune déformation, espace réservé avant le chargement). Les sources font
   512 et 2145 px de large : nettes à toute densité d'écran. */
.klpm-brand{display:inline-flex;align-items:center;gap:var(--s-2);
  margin-bottom:var(--s-4)}
.klpm-brand img{display:block;height:1.5rem;width:auto}
.klpm-h2{margin:0;font-family:var(--f-display);font-size:var(--fs-5);
  font-weight:var(--fw-title);line-height:var(--lh-tight);color:var(--c-ink)}
.klpm-h2 .g{color:var(--c-action)}
.klpm-sub{margin:var(--s-3) 0 0;font-size:var(--fs-2);color:var(--c-ink-2);
  line-height:var(--lh-body)}

/* Bascule mensuel / annuel — même contrôle segmenté que le tableau de bord. */
.klpm-billing{display:flex;flex-wrap:wrap;align-items:center;
  justify-content:center;gap:var(--s-3);margin:var(--s-6) 0 var(--s-5)}
.klpm-seg{display:inline-flex;gap:var(--s-1);padding:var(--s-1);
  border:1px solid var(--c-line);border-radius:var(--r-pill);
  background:var(--c-bg-2)}
.klpm-seg button{min-height:var(--control-h-sm);padding:0 var(--s-4);border:0;
  border-radius:var(--r-pill);background:transparent;font-family:inherit;
  font-size:var(--fs-1);font-weight:var(--fw-ui);color:var(--c-ink-2);
  cursor:pointer;transition:background-color var(--t-fast) var(--ease)}
.klpm-seg button.on{background:var(--c-surface);color:var(--c-ink);
  box-shadow:var(--sh-1)}
.klpm-seg button:focus-visible{outline:2px solid var(--c-focus);outline-offset:2px}
.klpm-save{font-size:var(--fs-1);font-weight:var(--fw-ui);color:var(--c-action)}

/* Les formules sont le composant « offre » (.kloffre, section 2 bis) : la
   carte Pro recommandée, la carte Studio derrière elle (règle 4 du plan CRO,
   décision du propriétaire du 11/09 : les deux y figurent toujours), puis le
   gratuit en une ligne. Trois cartes de front demandaient 64 rem ; une seule
   carte se lisait à 36 rem. Deux cartes côte à côte demandent 46 rem : 640 px
   utiles entre les marges de 48 px, soit deux cartes de 312 px — plus que le
   plancher de 18 rem de la page tarifs, moins que la carte seule d'avant
   (31 rem), où le prix se perdait à gauche d'un vide. Empilées à 36 rem, les
   deux cartes auraient forcé un défilement interne dès 720 px de haut. Le
   comparatif replié (30 rem au moins) tient dedans. */
.klpm-panel{width:min(46rem,100%)}
.klpm-total-note{margin:var(--s-5) 0 0;text-align:center;font-size:var(--fs-0);
  color:var(--c-ink-2);line-height:var(--lh-body)}
/* Dans la fenêtre, dès que la feuille n'est plus ancrée en bas (720 px) : Pro à
   gauche, Studio à droite, le gratuit sous les deux sur toute la largeur.
   Chaque carte est une colonne flexible dont la liste prend le reste : les deux
   boutons — l'aplat bleu de Pro, le contour de Studio — s'alignent sur la même
   ligne quel que soit le nombre de lignes de la tête (l'annuel en ajoute une à
   chacune). La liste étirée garde ses rangées serrées en haut : sans
   `align-content:start`, la grille répartit le surplus entre les promesses et
   la carte la plus courte espaçait ses coches irrégulièrement (mesuré le
   11/09 à 1280 px : 28/46/28 px contre 18/36/18). Sous 720 px, les cartes
   s'empilent, Pro d'abord : elle reste visible sans défiler, Studio se rejoint
   en faisant glisser la feuille. */
@media (min-width:720px){
  .kloffre--fenetre{grid-template-columns:1fr 1fr;gap:var(--s-3) var(--s-4)}
  /* Même dégagement en haut des deux cartes : seule la recommandée en a
     besoin pour son badge, mais côte à côte, 8 px d'écart décalaient les deux
     noms et les deux prix (mesuré le 11/09 : 353 contre 346). */
  .kloffre--fenetre .kloffre-carte{display:flex;flex-direction:column;
    padding-top:calc(var(--s-4) + var(--s-2))}
  .kloffre--fenetre .kloffre-avantages{flex:1;align-content:start}
  .kloffre--fenetre .kloffre-ligne{grid-column:1 / -1}
}

/* Le comparatif outil par outil : replié par défaut, il double la hauteur de
   la fenêtre une fois ouvert. */
.klpm-toolwrap{margin-top:var(--s-6);border-top:1px solid var(--c-line);
  padding-top:var(--s-5)}
.klpm-tools-toggle{display:flex;align-items:center;justify-content:center;
  gap:var(--s-2);width:100%;min-height:var(--control-h-sm);border:0;
  background:none;font-family:inherit;font-size:var(--fs-1);
  font-weight:var(--fw-ui);color:var(--c-action);cursor:pointer}
.klpm-tools-toggle:hover{text-decoration:underline}
.klpm-tools-toggle:focus-visible{outline:2px solid var(--c-focus);outline-offset:2px}
.klpm-chev{display:inline-block;line-height:1;
  transition:transform var(--t-fast) var(--ease)}
.klpm-tools-toggle.open .klpm-chev{transform:rotate(180deg)}
.klpm-table{margin-top:var(--s-4)}
.klpm-tscroll{overflow-x:auto}
.klpm-tinner{min-width:30rem}
.klpm-trow{display:grid;grid-template-columns:2fr 1fr 1fr 1fr;gap:var(--s-3);
  align-items:center;padding:var(--s-3) 0;border-bottom:1px solid var(--c-line)}
.klpm-thead{border-bottom:1px solid var(--c-line-strong)}
.klpm-th{font-size:var(--fs-0);font-weight:var(--fw-ui);color:var(--c-ink-2)}
.klpm-th.pro{color:var(--c-action)}
.klpm-th.studio{color:var(--c-premium)}
.klpm-tcat{margin-top:var(--s-5);padding-bottom:var(--s-2);
  font-size:var(--fs-0);font-weight:var(--fw-ui);color:var(--c-ink)}
.klpm-tname{font-size:var(--fs-1);color:var(--c-ink-2)}
.klpm-tcell{text-align:center}
.klpm-bdg{font-size:var(--fs-0);color:var(--c-ink-2);
  font-variant-numeric:tabular-nums}
.klpm-bdg.on{color:var(--c-ink)}

/* Sous 720 px la fenêtre devient une feuille ancrée en bas : le pouce y arrive,
   et le haut de l'écran reste visible pour comprendre d'où l'on vient. */
@media (max-width:719px){
  .klpm{padding:0;place-items:end stretch}
  /* TÉLÉPHONE : la fenêtre devient une feuille posée en bas. Son plafond valait
     92vh — 92 % de la fenêtre BARRES REPLIÉES, donc plus haut que ce qu'on voit
     réellement : la feuille dépassait par le haut et emportait sa fermeture sous
     la barre d'adresse. Plus aucune issue que de quitter la page (signalé le
     09/09/2026). La couche est désormais bornée à la zone vue : 92 % d'elle est
     la seule mesure qui garde la poignée de fermeture sous les yeux. */
  .klpm-panel{width:100%;max-height:92%;
    border-radius:var(--r-3) var(--r-3) 0 0;
    animation-name:klpm-up}
  @keyframes klpm-up{from{transform:translateY(100%)}to{transform:none}}
  /* Ancrée en bas : elle s'en va par le bas (section 0). */
  .klpm.kf-sort > .kfeuille-panneau{animation-name:kf-sortie-bas}
  .klpm-body{padding:var(--s-6) var(--s-4) var(--s-5)}
}

/* ══════════════════════════════════════════════════════════════════════════
   2 — FEUILLE DE TÉLÉCHARGEMENT (.klsheet) et MUR DE QUOTA (.klq-pop)
   Une seule coquille pour les deux : c'est la forme de toutes les fenêtres
   d'achat du parcours, elle n'est pas réinventée d'un écran à l'autre.
   ══════════════════════════════════════════════════════════════════════════ */

/* ZONE RÉELLEMENT VUE — voir app.js. Sur iPhone un élément fixé se place dans le
   cadre de mise en page, qui passe sous la barre d'adresse en haut et sous la
   barre d'outils en bas : une couche à `inset:0` glisse dessous, et le bouton de
   fermeture avec elle. Les deux mesures valent 0 partout ailleurs. */
.klsheet-ov{position:fixed;top:var(--klat-vue-haut,0px);bottom:var(--klat-dock-bas,0px);
  left:0;right:0;z-index:9400;display:grid;place-items:center;place-items:safe center;
  padding:var(--s-4);background:var(--c-scrim);overscroll-behavior:contain}
/* 520 px sur ordinateur (fiche du composant « offre », plan CRO §3) : assez
   pour un prix en grand et trois avantages sur une ligne, pas assez pour que
   la feuille ressemble à une page. */
/* `overscroll-behavior:contain` sur la FEUILLE elle-même, pas seulement sur son
   voile : c'est elle qui défile (12/09/2026, constat du propriétaire). Sans cela,
   le geste arrivé en bout de course pousse l'écran du dessous, et l'on croit que
   la feuille ne défile pas. */
.klsheet{position:relative;width:min(32.5rem,100%);
  max-height:100%;overflow-y:auto;overscroll-behavior:contain;
  padding:var(--s-5);background:var(--c-surface);border-radius:var(--r-3);
  box-shadow:0 24px 64px rgba(9,12,18,.32);
  animation:klpm-in 200ms var(--ease) both}
@media (prefers-reduced-motion:reduce){.klsheet{animation:none}}
/* La poignée n'existe que sur la variante ancrée en bas ; sur ordinateur elle
   annoncerait un geste qui n'a pas cours. */
.klsheet-grip{display:none}

.klsheet-h{display:flex;align-items:flex-start;justify-content:space-between;
  gap:var(--s-3);margin-bottom:var(--s-5)}
/* Le titre est le GAIN, affirmatif (« Cette vidéo en 2160p ») : 22 px, une ou
   deux lignes — la fourchette 20–22 px de la fiche du composant. */
.klsheet-h p{margin:0;font-family:var(--f-display);font-size:var(--fs-4);
  font-weight:var(--fw-title);color:var(--c-ink);line-height:var(--lh-snug)}
.klsheet-x{display:grid;place-items:center;flex:none;
  width:var(--control-h-sm);height:var(--control-h-sm);border:0;
  border-radius:var(--r-pill);background:var(--c-surface-2);color:var(--c-ink-2);
  cursor:pointer}
.klsheet-x svg{width:1.05rem;height:1.05rem}
.klsheet-x:hover{background:var(--c-line);color:var(--c-ink)}
.klsheet-x:focus-visible{outline:2px solid var(--c-focus);outline-offset:2px}

/* Les choix : des rangées pleine largeur, pas des boutons alignés. Chacune est
   une décision complète — ce qu'on obtient, à quelle condition, à quel prix. */
.klsheet-rows{display:grid;gap:var(--s-3)}
.klsheet-row{display:grid;grid-template-columns:auto 1fr auto;gap:var(--s-4);
  align-items:center;width:100%;padding:var(--s-4);text-align:left;
  border:1px solid var(--c-line);border-radius:var(--r-2);
  background:var(--c-surface);font-family:inherit;cursor:pointer;
  transition:border-color var(--t-fast) var(--ease),
             background-color var(--t-fast) var(--ease)}
.klsheet-row:hover{border-color:var(--c-line-strong);background:var(--c-bg-2)}
.klsheet-row:focus-visible{outline:2px solid var(--c-focus);outline-offset:2px}
.klsheet-row:disabled{opacity:.5;cursor:default}
.klsheet-row-ic{display:grid;place-items:center;width:2.25rem;height:2.25rem;
  border-radius:var(--r-pill);background:var(--c-surface-2);color:var(--c-ink-2)}
.klsheet-row-ic svg{width:1.15rem;height:1.15rem}
.klsheet-row-b{display:grid;gap:var(--s-1);min-width:0}
.klsheet-row-t{font-size:var(--fs-2);font-weight:var(--fw-ui);color:var(--c-ink);
  line-height:var(--lh-snug)}
.klsheet-row-s{font-size:var(--fs-1);color:var(--c-ink-2);
  line-height:var(--lh-snug)}
.klsheet-price{font-size:var(--fs-2);font-weight:var(--fw-title);
  color:var(--c-ink);white-space:nowrap;font-variant-numeric:tabular-nums}
.klsheet-price small{display:block;font-size:var(--fs-0);font-weight:400;
  color:var(--c-ink-2)}
/* UNE SEULE rangée mise en avant : trait bleu et pastille bleue. Pas d'aplat
   plein — le fond bleu ferait de la feuille une réclame.
   Laquelle ? Celle qui correspond à ce que la personne vient de faire. Sur le
   téléchargeur, la formule Téléchargement est présente et prend la mise en
   avant ; Pro redevient alors une rangée ordinaire, sans quoi deux propositions
   à deux prix se disputeraient le même regard. Partout ailleurs, Pro garde la
   mise en avant puisqu'il est seul.
   Ces rangées ne servent plus qu'à l'état « rien à vendre » de la feuille (une
   seule action, le fichier) ; les états de vente passent par le composant
   « offre » ci-dessous. La tâche 1.5 du plan CRO supprime cet état : ce bloc
   part avec elle. */
.klsheet-row.is-pro,.klsheet-row.is-dl{border-color:var(--c-action);
  background:var(--c-action-soft)}
.klsheet-row.is-pro:hover,.klsheet-row.is-dl:hover{background:#dfe8ff}
.klsheet-row.is-pro .klsheet-row-ic,.klsheet-row.is-dl .klsheet-row-ic{
  background:var(--c-action);color:var(--c-on-action)}
.klsheet-row.is-pro .klsheet-price,.klsheet-row.is-dl .klsheet-price{
  color:var(--c-action)}
.klsheet-rows:has(.is-dl) .is-pro{border-color:var(--c-line);
  background:var(--c-surface)}
.klsheet-rows:has(.is-dl) .is-pro:hover{background:var(--c-bg-2);
  border-color:var(--c-line-strong)}
.klsheet-rows:has(.is-dl) .is-pro .klsheet-row-ic{background:var(--c-surface-2);
  color:var(--c-ink-2)}
.klsheet-rows:has(.is-dl) .is-pro .klsheet-price{color:var(--c-ink)}

/* Mur de quota : même coquille, contenu argumenté. */
.klq-body{margin:0 0 var(--s-4);font-size:var(--fs-1);color:var(--c-ink-2);
  line-height:var(--lh-body)}
.klq-args{list-style:none;margin:0 0 var(--s-5);padding:0;display:grid;
  gap:var(--s-3)}
.klq-args li{display:grid;grid-template-columns:auto 1fr;gap:var(--s-3);
  align-items:start;font-size:var(--fs-1);color:var(--c-ink);
  line-height:var(--lh-body)}
.klq-args svg{width:1rem;height:1rem;margin-top:.15em;color:var(--c-action)}
.klq-cta{display:flex;align-items:center;justify-content:center;width:100%;
  min-height:var(--control-h);padding:0 var(--s-5);border:0;
  border-radius:var(--r-1);background:var(--c-action);color:var(--c-on-action);
  font-family:inherit;font-size:var(--fs-2);font-weight:var(--fw-ui);
  cursor:pointer;text-align:center}
.klq-cta:hover{background:var(--c-action-hover)}
.klq-cta:focus-visible{outline:2px solid var(--c-focus);outline-offset:2px}
.klq-second{display:block;width:100%;margin-top:var(--s-3);padding:var(--s-2) 0;
  border:0;background:none;font-family:inherit;font-size:var(--fs-1);
  font-weight:var(--fw-ui);color:var(--c-action);cursor:pointer}
.klq-second:hover{text-decoration:underline}
.klq-reassure{margin:var(--s-4) 0 0;text-align:center;font-size:var(--fs-0);
  color:var(--c-ink-2);line-height:var(--lh-body)}

/* ══════════════════════════════════════════════════════════════════════════
   2 bis — COMPOSANT « OFFRE » (.kloffre) — une décision, deux choix, un prix
   Fiche : docs/rapport-cro-feuilles-de-vente-2026-09.md §3 et §3 bis, deuxième
   version (propriétaire, 11/09). Dessiné UNE fois, posé à l'identique dans la
   feuille de téléchargement, puis dans le mur de quota, la fenêtre des formules
   et la page tarifs. Ordre, de haut en bas : titre (porté par la coquille,
   .klsheet-h) → carte 1, l'offre à l'unité (nom, prix + unité, trois promesses,
   son bouton au contour) → carte 2, l'abonnement de l'audience, MÊME gabarit
   (nom, prix mensuel, trois promesses propres à cette offre, puis le bouton
   bleu plein dans la carte, libellé = l'action seule) → bouton secondaire du
   gratuit → réassurance. Pas de lien discret dans une feuille ; jamais Studio.
   Ce qui fait la hiérarchie : le bouton plein est le SEUL aplat bleu, le prix
   le seul grand caractère ; le bouton de la carte 1 pèse moins (contour,
   44 px contre 48). Les promesses portent une coche bleue — jamais verte, la
   charte l'interdit — et restent COMPACTES : trois au plus, 14 px, interligne
   serré, une ligne chacune autant que possible, pour que deux cartes et le
   bouton gratuit tiennent sur 390 × 844 sans défilement interne (mesuré).
   « Pas de prix, pas d'offre » : une carte dont le prix manque n'est pas
   rendue, il n'existe donc pas d'état « indisponible » à dessiner.
   ══════════════════════════════════════════════════════════════════════════ */

.kloffre{display:grid;gap:var(--s-3)}
/* La carte : bordure bleue de 2 px et fond bleu très clair. Le fond seul
   (sans bordure) se lisait comme une rangée survolée ; la bordure seule
   (sans fond) ne la séparait pas assez des boutons blancs. */
.kloffre-carte{padding:var(--s-4);border:2px solid var(--c-action);
  border-radius:var(--r-2);background:var(--c-action-soft)}
.kloffre-tete{display:flex;flex-wrap:wrap;align-items:baseline;
  justify-content:space-between;gap:var(--s-2) var(--s-3)}
.kloffre-nom{font-size:var(--fs-2);font-weight:var(--fw-ui);color:var(--c-ink);
  line-height:var(--lh-snug)}
/* Le prix : plancher du jeton d'h2 (26 px sur téléphone), plafonné à 28 px sur
   ordinateur — la fourchette 24–28 px de la fiche, sans nombre hors échelle.
   Chiffres à chasse fixe : un prix qui change ne fait pas sauter la carte. */
.kloffre-prix{display:inline-flex;align-items:baseline;gap:var(--s-1);
  white-space:nowrap;font-family:var(--f-display);
  font-size:min(var(--fs-5),1.75rem);font-weight:var(--fw-title);
  color:var(--c-ink);line-height:1;font-variant-numeric:tabular-nums}
.kloffre-prix small{font-family:var(--f-sans);font-size:var(--fs-1);
  font-weight:var(--fw-text);color:var(--c-ink-2)}
.kloffre-avantages{list-style:none;margin:var(--s-3) 0 0;padding:0;
  display:grid;gap:var(--s-1)}
.kloffre-avantages li{display:grid;grid-template-columns:auto 1fr;gap:var(--s-2);
  align-items:start;font-size:var(--fs-1);color:var(--c-ink);
  line-height:var(--lh-snug)}
/* La promesse qui porte le CHIFFRE (heures par mois, exports sans logo) : en
   graisse d'interface, juste sous le nom — c'est elle qui rend « quasi
   illimité » honnête, elle ne peut pas être la moins visible de la liste. */
.kloffre-avantages li.is-fort{font-weight:var(--fw-ui)}
.kloffre-avantages svg{width:1rem;height:1rem;margin-top:.15em;
  color:var(--c-action)}
/* Les trois boutons sont ceux du socle (.k-btn) ; le composant ne leur ajoute
   que la hauteur, le retour à la ligne (quinze langues ne tiennent pas en un
   mot) et, pour celui de la carte, un contour bleu.
   Bouton de la carte (offre à l'unité) : secondaire du socle, 44 px, contour et
   texte bleus sur fond blanc — il se lit comme une action, mais un cran sous
   l'aplat plein qui suit. Bleu sur blanc : 6,0:1. */
.kloffre-carte-cta{margin-top:var(--s-3);border-color:var(--c-action);
  color:var(--c-action);white-space:normal;text-align:center;
  line-height:var(--lh-snug)}
.kloffre-carte-cta:hover{border-color:var(--c-action-hover);
  color:var(--c-action-hover)}
/* Bouton principal (abonnement de l'audience), DANS sa carte, sous les
   promesses : l'unique aplat bleu, 48 px au moins — un cran au-dessus des
   44 px des contrôles courants, c'est le moment de payer. Son libellé est
   l'action seule ; la promesse et le chiffre vivent dans la carte, au-dessus. */
.kloffre-cta{margin-top:var(--s-3);min-height:3rem;white-space:normal;
  text-align:center;line-height:var(--lh-snug)}
.kloffre-libre{min-height:3rem;white-space:normal;text-align:center;
  line-height:var(--lh-snug)}
/* Ouverture du paiement : le bouton qui a été cliqué se verrouille et le dit —
   celui de la carte (unité) comme le bouton plein (abonnement, tâche 1.10). Plus
   opaque que le désactivé du socle (.5) pour ne pas se lire comme une panne ;
   à .9, le bleu du texte sur le blanc éclairci reste au-dessus de 5:1, et le
   blanc sur l'aplat bleu éclairci au-dessus de 4,5:1. */
.kloffre-carte-cta.is-busy,.kloffre-cta.is-busy{opacity:.9}
/* Lien discret : plus employé dans les feuilles (§3 bis) ; réservé à la
   fenêtre des formules (tâche 4.1, « Commencer gratuitement »). Cible tactile
   de 44 px malgré le corps de 14 px. */
.kloffre-lien{display:flex;align-items:center;justify-content:center;
  width:100%;min-height:var(--control-h);padding:0 var(--s-3);border:0;
  background:none;font-family:inherit;font-size:var(--fs-1);
  font-weight:var(--fw-ui);color:var(--c-action);cursor:pointer;
  text-align:center;line-height:var(--lh-snug);text-decoration:none}
.kloffre-lien:hover{text-decoration:underline}
.kloffre-lien:focus-visible{outline:2px solid var(--c-focus);outline-offset:2px}
.kloffre-reassurance{margin:0;text-align:center;font-size:var(--fs-0);
  color:var(--c-ink-2);line-height:var(--lh-body)}

/* Le composant hors d'une feuille (fenêtre des formules, page tarifs, mur de
   crédits, convertisseur, extraits IA) : mêmes cartes, mêmes boutons, mêmes
   distances. Ce qui suit n'ajoute que ce qu'une feuille n'a pas — un titre
   quand la coquille n'en porte pas, le badge « Recommandé », la note de
   facturation sous le prix, la ligne du gratuit, et la grille de la page. */
.kloffre-titre{margin:0 0 var(--s-3);font-family:var(--f-display);
  font-size:var(--fs-4);font-weight:var(--fw-title);color:var(--c-ink);
  line-height:var(--lh-snug)}
.kloffre-carte{position:relative}
/* Le badge chevauche le trait haut de la carte, comme sur les cartes du site ;
   la carte recommandée dégage la place au-dessus de son nom. Le violet est le
   jeton « premium », rare : c'est sa seule occurrence dans ces surfaces. Blanc
   sur #6d28d9 : 7,1:1. */
.kloffre-carte.is-reco{padding-top:calc(var(--s-4) + var(--s-2))}
.kloffre-badge{position:absolute;top:0;left:var(--s-4);transform:translateY(-50%);
  max-width:calc(100% - 2*var(--s-4));padding:var(--s-1) var(--s-3);
  border-radius:var(--r-pill);background:var(--c-premium);color:var(--c-on-action);
  font-size:var(--fs-0);font-weight:var(--fw-ui);line-height:1.3;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* Nom porté par un <h2> sur la page tarifs : même corps que le <span> des
   feuilles, sans la marge de titre. */
h2.kloffre-nom{margin:0;font-family:var(--f-sans);letter-spacing:0}
/* Pastille « Plan actuel » — dans la tête, après le nom. */
.kloffre-etat{padding:2px var(--s-2);border-radius:var(--r-pill);
  background:var(--c-surface);border:1px solid var(--c-line);
  font-size:var(--fs-0);font-weight:var(--fw-ui);color:var(--c-ink-2);
  line-height:1.3;white-space:nowrap}
/* Note de facturation sous le prix (mensuel / annuel) : elle occupe la
   rangée entière sous la tête, en 13 px gris. */
.kloffre-note{flex-basis:100%;margin:0;font-size:var(--fs-0);color:var(--c-ink-2);
  line-height:var(--lh-body)}
.kloffre-note.is-action{color:var(--c-action);font-weight:var(--fw-ui)}
/* Le gratuit en une ligne (fenêtre des formules, page tarifs — tâches 4.1 et
   4.8) : nom, prix, ce qu'il contient, et le lien d'entrée. Un cadre fin et
   blanc, jamais le fond bleu des cartes : il ne se vend pas, il se prend. */
.kloffre-ligne{display:grid;gap:var(--s-2);padding:var(--s-3) var(--s-4);
  border:1px solid var(--c-line);border-radius:var(--r-2);
  background:var(--c-surface)}
.kloffre-ligne-tete{display:flex;flex-wrap:wrap;align-items:baseline;
  gap:var(--s-2)}
.kloffre-ligne-tete .kloffre-prix{font-size:var(--fs-3)}
.kloffre-ligne-txt{margin:0;font-size:var(--fs-1);color:var(--c-ink-2);
  line-height:var(--lh-snug)}
.kloffre-ligne .kloffre-lien{justify-content:flex-start;padding:0;
  min-height:var(--control-h-sm)}
@media (min-width:600px){
  .kloffre-ligne{grid-template-columns:1fr auto;align-items:center}
  .kloffre-ligne-tete{grid-column:1}
  .kloffre-ligne-txt{grid-column:1}
  .kloffre-ligne .kloffre-lien{grid-column:2;grid-row:1 / span 2;
    justify-content:flex-end;width:auto}
}
/* Page tarifs : les cartes payantes côte à côte dès qu'elles tiennent, la
   ligne du gratuit sous elles, sur toute la largeur. */
.kloffre--page{gap:var(--s-5);
  grid-template-columns:repeat(auto-fit,minmax(min(100%,18rem),1fr));
  align-items:start}
.kloffre--page .kloffre-ligne{grid-column:1 / -1}
/* Posé dans un écran de résultat (extraits IA) : un bloc, à sa place dans le
   flux, à la même distance que l'ancien encart. */
.kloffre--bloc{margin:0 0 var(--s-5)}
/* Encart de résultat (encart_vente.html, colonne .klr-side des écrans de
   résultat) : la colonne est un flex à 12 px d'écart, et l'encart n'y avait
   aucune marge propre — il touchait le bloc « et ensuite » (tâche 2.7, mesuré
   le 11/09 : 12 px). 12 px de plus font 24 px, la distance de .kloffre--bloc. */
.klr-offer{margin-top:var(--s-3)}
/* Sur une planche large, les deux cartes se placent côte à côte : empilées à
   896 px, le prix partait à 60 caractères du nom. Titre et note gardent la
   largeur entière. */
@media (min-width:720px){
  .kloffre--bloc{grid-template-columns:1fr 1fr;gap:var(--s-3) var(--s-4);
    align-items:start}
  .kloffre--bloc .kloffre-titre,.kloffre--bloc .kloffre-reassurance{
    grid-column:1 / -1}
}

/* ── Mur de crédits (shell-haut.html, errorCta === 'credits') ─────────────
   La boîte d'erreur du gabarit reçoit `is-offre` : elle cesse d'être rouge,
   car ce n'est pas une panne, c'est une offre — la carte Pro, son bouton,
   « Plus tard ». Deux classes contre une : la règle prime sur .k-alert--error
   quel que soit l'ordre des feuilles. La palette claire est figée ci-dessus. */
.tho-errbox.is-offre{background:var(--c-surface);border-color:var(--c-line)}
.tho-errbox.is-offre .tho-errbox-ic{stroke:var(--c-action)}
.tho-errbox.is-offre .kloffre{width:100%;margin-top:var(--s-2)}

@media (max-width:639px){
  .klsheet-ov{padding:0;place-items:end stretch}
  /* Même règle que la fenêtre des formules : la feuille se borne à la zone
     RÉELLEMENT vue, pas à la fenêtre barres repliées. */
  .klsheet{width:100%;max-height:92%;padding:var(--s-3) var(--s-4) var(--s-6);
    border-radius:var(--r-3) var(--r-3) 0 0;animation-name:klpm-up}
  /* Ancrée en bas : elle s'en va par le bas (section 0). */
  .klsheet-ov.kf-sort > .kfeuille-panneau{animation-name:kf-sortie-bas}
  .klsheet-grip{display:block;width:2.25rem;height:4px;margin:0 auto var(--s-4);
    border-radius:2px;background:var(--c-line-strong);opacity:.5}
}

/* ══════════════════════════════════════════════════════════════════════════
   3 — ENCART DE VENTE (.klc-offer) — posé sous un résultat, jamais en travers
   ══════════════════════════════════════════════════════════════════════════ */

.klc-offer{display:grid;grid-template-columns:auto 1fr;gap:var(--s-4);
  align-items:start;margin-top:var(--s-5);padding:var(--s-5);
  border:1px solid var(--c-line);border-left:3px solid var(--c-action);
  border-radius:var(--r-2);background:var(--c-bg-2)}
.klc-offer-ic{display:grid;place-items:center;width:2.25rem;height:2.25rem;
  border-radius:var(--r-pill);background:var(--c-action-soft);
  color:var(--c-action)}
.klc-offer-body{min-width:0}
.klc-offer-title{margin:0;font-size:var(--fs-2);font-weight:var(--fw-ui);
  color:var(--c-ink);line-height:var(--lh-snug)}
.klc-offer-sub{margin:var(--s-2) 0 0;font-size:var(--fs-1);color:var(--c-ink-2);
  line-height:var(--lh-body)}
.klc-offer-cta{grid-column:1 / -1;display:flex;flex-wrap:wrap;
  align-items:center;gap:var(--s-4);margin-top:var(--s-2)}
.klc-offer-cta .btn{display:inline-flex;align-items:center;
  justify-content:center;min-height:var(--control-h);padding:0 var(--s-5);
  border:1px solid transparent;border-radius:var(--r-1);background:var(--c-action);
  color:var(--c-on-action);font-family:inherit;font-size:var(--fs-1);
  font-weight:var(--fw-ui);cursor:pointer;text-decoration:none}
.klc-offer-cta .btn:hover{background:var(--c-action-hover)}
.klc-offer-cta .btn:disabled{opacity:.55;cursor:default}
.klc-offer-pro{font-size:var(--fs-1);font-weight:var(--fw-ui);
  color:var(--c-action);text-decoration:none}
.klc-offer-pro:hover{text-decoration:underline}
/* La note de bas d'encart n'avait pas de place assignee : elle tombait en
   COLONNE 1 de la deuxieme rangee, et comme cette colonne est en `auto`, un
   paragraphe entier la dilatait — mesure : 674 px pour la colonne de l'icone,
   0 px pour le texte de l'offre, dont chaque mot passait a la ligne. Elle
   occupe toute la largeur, ce qu'elle a toujours ete visuellement. */
.klc-offer-note{grid-column:1 / -1;margin:var(--s-2) 0 0;font-size:var(--fs-1);
  line-height:var(--lh-body);color:var(--c-ink-2)}
@media (min-width:600px){
  .klc-offer{grid-template-columns:auto 1fr auto;align-items:center}
  .klc-offer-cta{grid-column:auto;margin-top:0}
}

/* ══════════════════════════════════════════════════════════════════════════
   4 — PORTE HD APRÈS REFUS (.klr-porte) — une ligne, pas une offre
   Plan CRO 2.2 (reprise du 11/09) ; décidée par porteHd(), libellée par
   porteHdLibelle(), menée par porteHdGo() (download.js). Elle vit dans la
   colonne d'action de l'écran de résultat, sous le bouton de téléchargement.
   La personne a déjà dit non à la HD : rien ne se représente, le chemin
   reste ouvert. D'où la forme : le LIEN DISCRET du composant « offre »
   (plan §3 : lien texte, 14 px, centré, cible tactile de 44 px) — mêmes
   corps, graisse et couleur d'action que .kloffre-lien, et rien de plus.
   Ni carte, ni cadre, ni aplat : le bouton plein au-dessus reste le seul
   aplat bleu de l'écran, la ligne se lit après lui, comme une note.
   Elle ne prend pas la palette figée des surfaces d'achat : la colonne suit
   le thème du site, et une ligne posée dedans le suit aussi (jetons vifs).
   ══════════════════════════════════════════════════════════════════════════ */
.klr-porte{display:flex;align-items:center;justify-content:center;gap:var(--s-1);
  width:100%;min-height:var(--control-h);padding:0 var(--s-3);border:0;
  background:none;font-family:inherit;font-size:var(--fs-1);
  font-weight:var(--fw-ui);color:var(--c-action);cursor:pointer;
  text-align:center;line-height:var(--lh-snug)}
.klr-porte:hover{color:var(--c-action-hover);text-decoration:underline}
.klr-porte:focus-visible{outline:2px solid var(--c-focus);outline-offset:2px}
/* Ouverture du paiement : verrouillée et elle le dit — même retenue que les
   boutons du composant (.is-busy, .9) : pas une panne, une attente. */
.klr-porte:disabled{cursor:default;text-decoration:none;opacity:.9}
.klr-porte-a{flex:none;width:var(--s-4);height:var(--s-4)}
/* La colonne range ses enfants par rang (atelier.css : téléchargement 0,
   suite 1, « nouveau fichier » 2, tout le reste 3). Sans rang propre, la
   ligne partait sous le filet, au milieu du contexte, loin du bouton
   qu'elle prolonge. Même rang que lui, et posée après lui dans le gabarit :
   elle le suit. La spécificité (0,6,1) bat la règle générale (0,5,1) quel
   que soit l'ordre de chargement des feuilles — aucun !important. */
body.atelier-active .feature-hero.tool-hero [data-result-unified] .klr-side .klr-porte{order:0}

.progress-card h2{font-family:var(--f-sans);font-size:var(--fs-3);letter-spacing:0;font-variation-settings:normal}
