/* ═══════════════════════════════════════════════════════════════════════════
   v2.css — feuille de la PRÉVERSION `/v2` (landing v2, port du pack Lovable)

   ⚠️ TEMPORAIRE ET ISOLÉE. Chargée UNIQUEMENT par `v2.html`, APRÈS `style.css`.
   Tout est scopé sous `.kv2` (porté par le <main> de v2.html) : rien ne peut
   fuir vers les pages existantes. `style.css` n'est pas touché.
   Si la v2 est retenue, ce fichier est fusionné dans `style.css` et supprimé.

   Traduction à la main des utilitaires Tailwind v4 du pack
   (`docs/design/landing-lovable/src/styles.css` + les 3 composants).
   Choix de portage :
   • Les tokens du pack sont DÉJÀ ceux de `style.css:59-98` (#5B6CF9, #4353E8,
     #6B6B7E, #FFD166, #00B37D, #E8E6F0) → on réutilise les variables
     existantes, on n'en redéclare aucune dans :root.
   • Les `oklch()` / `color-mix(in oklab, …)` du pack sont PRÉCALCULÉS en
     hex/rgba : rendu identique, zéro dépendance à une CSS moderne.
   • Les sections neuves utilisent `.container` (1100px, comme tout le site) et
     non `max-w-6xl` (1152px) : deux largeurs de contenu sur une même page se
     verraient au raccord avec les tarifs / la FAQ / Swiss made.
   • Fredoka est chargée en 400-700 : le `font-black` (900) du pack est déjà
     ramené à 700 par le navigateur, on l'écrit donc 700.
   ═══════════════════════════════════════════════════════════════════════════ */

.kv2 {
  /* Compléments du pack absents de style.css */
  --kv2-soft: #EEEEFF;          /* --primary-soft */
  --kv2-muted: #F3F3F8;         /* --muted */
  --kv2-shadow-soft: 0 10px 40px -12px rgba(91, 108, 249, 0.25);
  --kv2-shadow-pop: 0 20px 60px -20px rgba(91, 108, 249, 0.40);
  --kv2-shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.06);
  --kv2-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.10), 0 2px 4px -2px rgba(0, 0, 0, 0.10);
  /* Couloir RÉSERVÉ à la bulle du Kwiix : hauteur FIXE, dimensionnée pour la
     plus longue réplique de la démo. C'est ce qui garantit que la mascotte ne
     bouge JAMAIS quand la bulle change de longueur — elle grandit dans le
     couloir, pas en poussant le Kwiix. Deux valeurs car les deux implantations
     n'ont ni la même largeur de bulle ni la même orientation.
     Valeurs MESURÉES sur toutes les répliques de la démo (la plus longue fait
     88px en desktop, 86px en mobile) — pas devinées. Une réplique plus longue
     que le couloir le ferait grandir et le Kwiix rebougerait : re-mesurer si on
     en ajoute une. */
  --kv2-coach-slot-desk: 104px;  /* bulle AU-DESSUS du Kwiix (≥ 1024px) */
  --kv2-coach-slot-mob: 96px;    /* bulle À DROITE du Kwiix (< 1024px) */
  /* Écrans du jeu (codes exacts du pack) */
  --kv2-night: #1B1D3B;
  --kv2-ok: #22B573;
  --kv2-ko: #D64545;
  --kv2-warn: #E8A93D;
  --kv2-body-bg: #F6F7FB;
  --kv2-explain-bg: #FFF8E7;
  /* ⚠️ BORDS PARASITES DES CAPTURES — mesurés sur les 10 fichiers, à 3 instants
     chacun, et IDENTIQUES partout : 8 px noirs en haut, 10 px noirs en bas,
     8 px blancs à droite (le bord du cadre enregistré). Ils sont rognés en CSS,
     faute de pouvoir réencoder les fichiers ici.
     Le rognage précédent était faux de deux façons : il ne traitait que le bas
     (`object-position: top center` PRÉSERVE le haut — la bande noire du haut
     restait donc affichée) et ignorait la bande blanche de droite.
     Géométrie EXACTE plutôt qu'un pourcentage approché : le cadre montre
     1272 × 702 d'une image de 1280 × 720. Ne pas remplacer par un `object-fit`
     seul : aucune valeur ne sait rogner ASYMÉTRIQUEMENT. */
  /* ⚠️ On rogne 1 à 2 px DE PLUS que la bande mesurée, volontairement. Au pixel
     exact, le bord du cadre tombait pile sur la première ligne de la bande du
     bas : l'arrondi au pixel de l'écran en laissait paraître un FILET NOIR (vu
     en capture réelle : une ligne à luminance 0 en densité ×2). Deux pixels
     d'image utile en moins ne se voient pas ; un filet noir, si. */
  --kv2-vid-nat-w: 1280;
  --kv2-vid-nat-h: 720;
  --kv2-vid-w: 1270;    /* 1280 − 0 à gauche − 10 à droite (bande de 8 + 2 de marge) */
  --kv2-vid-h: 699;     /* 720 − 9 en haut − 12 en bas (bandes de 8 et 10 + marge) */
  --kv2-vid-top: 9;
  --kv2-vid-ratio: calc(var(--kv2-vid-w) / var(--kv2-vid-h));   /* 1.8120 */
}

/* ─── Cadre d'une capture vidéo : rognage EXACT des bords parasites ───────────
   Le cadre expose exactement l'image utile (1272 × 702) ; la vidéo, agrandie
   dans cette proportion et remontée de ses 8 px de bande noire, laisse les
   bandes du haut, du bas et de la droite tomber hors du cadre, qui les coupe.
   ⚠️ `object-fit: fill` est VOLONTAIRE et ne déforme rien : la boîte affichée
   garde exactement le format natif 16/9 (vérifié : 1.8120 × 1280/1272 × 702/720
   = 1.7778). C'est aussi pourquoi l'image d'attente doit rester une image
   PLEINE (1024 × 576) — une affiche déjà rognée ne se superposerait plus à la
   vidéo, et on verrait un saut au démarrage de la lecture.
   Une SEULE définition pour toutes les surfaces (aperçu desktop, plein écran) :
   les trois copies précédentes avaient déjà divergé. */
.kv2-vidbox {
  position: relative; width: 100%; aspect-ratio: var(--kv2-vid-ratio);
  overflow: hidden; background: #000;
}
.kv2-vidbox > video,
.kv2-vidbox > img {
  position: absolute; left: 0;
  top: calc(var(--kv2-vid-top) / var(--kv2-vid-h) * -100%);
  width: calc(var(--kv2-vid-nat-w) / var(--kv2-vid-w) * 100%);
  height: calc(var(--kv2-vid-nat-h) / var(--kv2-vid-h) * 100%);
  object-fit: fill; background: #000;
}
/* Filigrane Kwiiz sur les captures de TYPES (aperçu desktop ET plein écran, que
   `.kv2-vidbox` désigne justement — les captures de session, elles, portent le
   filigrane DANS leurs pixels et passent en `is-clean`). RÉPLIQUE EXACTE du
   filigrane incrusté des vidéos flow, MESURÉ sur flow-1-prof : wordmark
   `assets/logo.svg` (le même dessin), largeur 5 % du cadre, marges 2,55 %
   à droite / 3,15 % en bas, opacité 0,5 (accent sur blanc → violet clair
   mesuré 174,182,255). Jamais sur un emplacement « capture à venir » (:has). */
.kv2-vidbox:has(> video)::after {
  content: ''; position: absolute; z-index: 2; pointer-events: none;
  right: 2.55%; bottom: 3.15%; width: 5%; aspect-ratio: 469.5 / 225;
  background: url('assets/logo.svg') no-repeat center / contain;
  opacity: 0.5;
}

/* ─── Keyframes (préfixées : `float` et `fade-up` existent déjà dans style.css) ── */
@keyframes kv2-pop {
  0%   { transform: scale(0.6); opacity: 0; }
  60%  { transform: scale(1.08); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}
/* Pop d'une étoile GAGNÉE : elle naît de rien, dépasse franchement sa taille,
   puis se pose avec un léger contre-rebond — le sur-dépassement est ce qui rend
   le pop lisible quand les étoiles s'enchaînent. `both` + délai JS : l'étoile
   est INVISIBLE tant que son tour n'est pas venu. */
@keyframes kv2-star-pop {
  0%   { transform: scale(0) rotate(-20deg); opacity: 0; }
  8%   { opacity: 1; }
  55%  { transform: scale(1.32) rotate(6deg); opacity: 1; }
  76%  { transform: scale(0.94) rotate(-2deg); }
  100% { transform: scale(1) rotate(0deg); opacity: 1; }
}
/* Les étoiles VIDES se contentent d'un fondu : ce sont des emplacements. */
@keyframes kv2-star-fade {
  0%   { opacity: 0; }
  100% { opacity: 1; }
}
@keyframes kv2-confetti-fall {
  0%   { transform: translateY(-20px) rotate(0); opacity: 1; }
  100% { transform: translateY(320px) rotate(720deg); opacity: 0; }
}
@keyframes kv2-sparkle {
  0%   { transform: scale(0); opacity: 0; }
  40%  { transform: scale(1.2); opacity: 1; }
  100% { transform: scale(0.4); opacity: 0; }
}
@keyframes kv2-jump {
  0%, 100% { transform: translateY(0) rotate(-4deg) scale(1); }
  25%      { transform: translateY(-18px) rotate(-10deg) scale(1.08); }
  50%      { transform: translateY(0) rotate(0deg) scale(1); }
  75%      { transform: translateY(-12px) rotate(8deg) scale(1.05); }
}
@keyframes kv2-shake {
  0%, 100% { transform: translateX(0) rotate(0deg); }
  20%      { transform: translateX(-7px) rotate(-10deg); }
  40%      { transform: translateX(7px) rotate(10deg); }
  60%      { transform: translateX(-5px) rotate(-6deg); }
  80%      { transform: translateX(5px) rotate(6deg); }
}
/* L'apparition de la flèche n'est plus une animation mais une transition portée
   par son slot (cf. `.kv2-arrow-slot`) : elle monte du bas UNE fois, quand le
   corrigé s'affiche, et reste en place ensuite. */
@keyframes kv2-arrow-bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-4px); }
}

/* `hidden` doit gagner contre nos `display:flex` (la feuille du navigateur ne
   pose qu'un `display:none` de spécificité nulle) */
.kv2 [hidden] { display: none !important; }

/* ─── Fonds décoratifs (les 3 @utility du pack) ─────────────────────────────── */
.kv2-glow {
  background:
    radial-gradient(60% 50% at 15% 10%, rgba(91, 108, 249, 0.18), transparent 70%),
    radial-gradient(50% 40% at 90% 20%, rgba(255, 209, 102, 0.25), transparent 70%),
    radial-gradient(40% 40% at 60% 90%, rgba(0, 179, 125, 0.15), transparent 70%);
}
.kv2-dots {
  background-image: radial-gradient(rgba(91, 108, 249, 0.20) 1px, transparent 1px);
  background-size: 22px 22px;
}

/* ═══════════════════════════ HERO ═══════════════════════════════════════════ */
.kv2-hero { position: relative; overflow: hidden; }
.kv2-hero > .kv2-glow,
.kv2-hero > .kv2-dots { position: absolute; inset: 0; pointer-events: none; }
.kv2-hero > .kv2-dots { opacity: 0.4; }

.kv2-hero-inner { position: relative; padding-top: 64px; padding-bottom: 32px; }
.kv2-hero-grid { display: grid; gap: 40px; align-items: center; }

.kv2-hero-copy { text-align: center; }

/* Les pills du hero réutilisent `.lp-hero-badges`/`.lp-badge` de `style.css`
   (même rangée que la landing officielle) — rien à styler ici. On centre juste
   la rangée tant que la colonne est centrée. */
.kv2-hero-copy .lp-hero-badges { justify-content: center; }

.kv2-hero h1 {
  margin-top: 0;
  font-size: 3rem; line-height: 1.02; letter-spacing: -0.02em; font-weight: 700;
}
.kv2-hero h1 em { font-style: normal; color: var(--accent); }

.kv2-sub {
  margin: 24px auto 0; max-width: 36rem;
  font-size: 1.125rem; color: var(--text-secondary);
}
.kv2-sub strong { color: var(--text); font-weight: 700; }

.kv2-actions {
  margin-top: 32px; display: flex; flex-wrap: wrap;
  align-items: center; justify-content: center; gap: 12px;
}
.kv2-cta, .kv2-ghost {
  display: inline-flex; align-items: center; gap: 8px; border-radius: 999px;
  font-family: 'Plus Jakarta Sans', sans-serif; font-weight: 700; font-size: 1rem;
  transition: transform .2s ease, background .2s ease, border-color .2s ease, color .2s ease;
}
.kv2-cta {
  background: var(--accent); color: #fff; padding: 16px 28px;
  box-shadow: var(--kv2-shadow-pop);
}
.kv2-cta:hover { transform: scale(1.05); }
.kv2-cta span { transition: transform .2s ease; }
.kv2-cta:hover span { transform: translateX(4px); }
.kv2-ghost {
  background: #fff; color: var(--text); padding: 13px 20px;
  border: 2px solid var(--border);
}
.kv2-ghost:hover { border-color: var(--accent); color: var(--accent); }

.kv2-hero-checks {
  margin-top: 24px; display: flex; flex-wrap: wrap;
  align-items: center; justify-content: center; column-gap: 16px; row-gap: 8px;
  font-size: 13.5px; color: var(--text-secondary);
}
.kv2-hero-checks span { display: inline-flex; align-items: center; gap: 6px; }
.kv2-hero-checks svg { width: 15px; height: 15px; color: var(--accent2); flex: none; }

/* Colonne démo. ⚠️ Le petit Kwiix qui flottait au coin haut-gauche de la
   tablette a été RETIRÉ (2026-07-30) : deux mascottes dans le même hero se
   parasitaient, et celle-là ne disait rien — le Kwiix commentateur, lui, parle. */
.kv2-hero-visual { position: relative; display: flex; flex-direction: column; }

/* ─── Bande de réassurance + 4 cartes de stats ──────────────────────────────── */
.kv2-stats { margin-top: 56px; }
.kv2-trust {
  margin-bottom: 24px; display: flex; flex-wrap: wrap;
  align-items: center; justify-content: center; column-gap: 32px; row-gap: 8px;
  font-size: 0.875rem; font-weight: 600; color: rgba(45, 45, 58, 0.72);
}
.kv2-trust span { display: inline-flex; align-items: center; gap: 8px; }
.kv2-trust svg { width: 17px; height: 17px; flex: none; color: var(--accent); }
.kv2-trust .kv2-flag { width: 15px; height: 15px; border-radius: 3px; }

.kv2-stat-grid { display: grid; gap: 16px; }
.kv2-stat {
  border: 1px solid var(--border); border-radius: 28px;
  background: rgba(255, 255, 255, 0.8); backdrop-filter: blur(8px);
  padding: 24px; text-align: center; box-shadow: var(--kv2-shadow-soft);
  opacity: 0; transform: translateY(24px);
  transition: opacity .7s ease, transform .7s ease;
}
.kv2-stat.in { opacity: 1; transform: none; }
/* Chiffres : MÊME traitement typographique que `.lp-lib-stat` de la landing
   officielle (Fredoka 600, même échelle, même violet) — la v2 ne doit pas
   inventer une deuxième façon d'écrire un chiffre clé. */
.kv2-stat b {
  display: block; font-family: 'Fredoka', sans-serif; font-weight: 600;
  font-size: clamp(26px, 3vw, 34px); line-height: 1.1;
  color: var(--accent); font-variant-numeric: tabular-nums;
}
.kv2-stat span {
  display: block; margin-top: 8px;
  font-size: 12.5px; font-weight: 600; color: var(--text-secondary);
}

/* ═══════════════════════ DÉMO JOUABLE (iPad) ════════════════════════════════ */
/* 328px : un peu moins que les 352px de la landing officielle (`.lp-stage`),
   la différence étant rendue au Kwiix pour qu'il respire. C'est la SEULE
   largeur de tablette : les styles internes du jeu sont calibrés pour elle, une
   seule fois (cf. la note dans le bloc ≥768px). */
.kv2-demo { position: relative; margin: 0 auto; width: 100%; max-width: 328px; }

.kv2-pad {
  position: relative; border-radius: 42px; background: var(--kv2-night);
  padding: 12px; aspect-ratio: 3 / 4;
  box-shadow: 0 25px 60px -15px rgba(27, 29, 59, 0.5), inset 0 0 0 1px rgba(0, 0, 0, 0.2);
}
.kv2-pad-cam {
  position: absolute; left: 50%; top: 10px; z-index: 2;
  width: 6px; height: 6px; margin-left: -3px; border-radius: 999px;
  background: rgba(0, 0, 0, 0.6); box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.1);
}
.kv2-pad-home {
  position: absolute; bottom: 6px; left: 50%; z-index: 2;
  width: 64px; height: 3px; margin-left: -32px; border-radius: 999px;
  background: rgba(255, 255, 255, 0.25);
}
.kv2-screen {
  position: relative; display: flex; flex-direction: column;
  height: 100%; width: 100%; overflow: hidden; border-radius: 26px;
  background: #fff; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.05);
}

/* En-tête du jeu — la couleur porte la phase */
.kv2-gtop {
  position: relative; color: #fff; background: var(--kv2-night);
  transition: background-color .3s ease;
}
.kv2-screen[data-phase="verdict"][data-verdict="correct"] .kv2-gtop { background: var(--kv2-ok); }
.kv2-screen[data-phase="verdict"][data-verdict="wrong"]   .kv2-gtop { background: var(--kv2-ko); }
.kv2-screen[data-phase="explain"] .kv2-gtop { background: var(--kv2-warn); }
.kv2-screen[data-phase="end"]     .kv2-gtop { background: var(--kv2-ok); }

.kv2-gtop-row { display: flex; align-items: center; gap: 8px; padding: 8px 12px; }
.kv2-gtop-kwiix {
  display: grid; place-items: center; flex: none;
  width: 32px; height: 32px; border-radius: 16px; background: rgba(255, 255, 255, 0.1);
}
.kv2-gtop-kwiix img { width: 24px; height: 24px; }
.kv2-gtop-title {
  flex: 1; min-width: 0; text-align: center;
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 12px; font-weight: 800;
  letter-spacing: 0.02em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.kv2-gtop-icons { display: flex; flex: none; align-items: center; gap: 4px; }
.kv2-gtop-icons button {
  display: grid; place-items: center; width: 28px; height: 28px;
  border: 0; border-radius: 14px; background: rgba(255, 255, 255, 0.1);
  color: rgba(255, 255, 255, 0.8); cursor: default;
}
.kv2-gprog { display: flex; gap: 6px; padding: 0 12px 8px; }
.kv2-gprog i {
  flex: 1; height: 6px; border-radius: 999px;
  border: 1px solid rgba(0, 0, 0, 0.7); background: rgba(255, 255, 255, 0.2);
}
.kv2-gprog i[data-s="current"] { background: #fff; }
.kv2-gprog i[data-s="correct"] { background: #34d399; }
.kv2-gprog i[data-s="wrong"]   { background: #fb7185; }

/* Ligne degré · discipline · objectif */
.kv2-gmeta {
  background: var(--kv2-body-bg); padding: 8px 8px 4px; text-align: center;
  transition: background-color .3s ease;
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 12px; font-weight: 800;
  text-transform: uppercase; letter-spacing: 0.1em; color: var(--accent);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.kv2-screen[data-phase="explain"] .kv2-gmeta { background: var(--kv2-explain-bg); }

/* Corps + scène glissante */
.kv2-gbody {
  position: relative; flex: 1; min-height: 0;
  background: var(--kv2-body-bg); transition: background-color .3s ease;
}
.kv2-screen[data-phase="explain"] .kv2-gbody { background: var(--kv2-explain-bg); }

.kv2-stage { position: absolute; inset: 0; overflow: hidden; }
.kv2-stage-rail {
  display: flex; height: 100%; width: 200%;
  transition: transform 600ms cubic-bezier(0.65, 0, 0.35, 1);
  will-change: transform;
}
.kv2-stage-rail.go { transform: translateX(-50%); }
.kv2-stage-rail > div { position: relative; height: 100%; width: 50%; flex: none; }
.kv2-stage-rail > div.out { pointer-events: none; }
/* Écran unique (hors transition) */
.kv2-stage > .kv2-panel { position: absolute; inset: 0; }

/* ── Écran QUESTION ─────────────────────────────────────────────────────────── */
.kv2-panel { height: 100%; }
.kv2-play { display: flex; height: 100%; flex-direction: column; padding: 12px; }
.kv2-qprompt {
  text-align: center; font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 14px; font-weight: 800; line-height: 1.2; color: var(--text);
}
.kv2-play-qcm .kv2-qprompt-wrap,
.kv2-verdict-qcm .kv2-qprompt-wrap {
  display: flex; flex: 1; align-items: center; justify-content: center;
}

/* QCM — 4 cartes en relief */
.kv2-opts {
  display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr;
  gap: 10px; height: 160px; padding-bottom: 8px;
}
.kv2-opt {
  position: relative; border: 0; border-radius: 24px; padding: 4px 8px;
  text-align: center; color: #fff; cursor: pointer;
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 13px; font-weight: 800;
  box-shadow: 0 5px 0 rgba(0, 0, 0, 0.18);
  transition: transform .15s ease, box-shadow .15s ease;
}
.kv2-opt:hover { transform: translateY(-2px); }
.kv2-opt:active,
.kv2-opt.picked { transform: translateY(3px); box-shadow: 0 2px 0 rgba(0, 0, 0, 0.18); }
.kv2-opt.picked { outline: 4px solid #fff; outline-offset: 2px; }
.kv2-opt[data-tone="rose"]  { background: #f43f5e; }
.kv2-opt[data-tone="blue"]  { background: #3B5BE0; }
.kv2-opt[data-tone="amber"] { background: #f59e0b; }
.kv2-opt[data-tone="green"] { background: #059669; }

/* Catégorisation */
.kv2-play-cat .kv2-qprompt { font-size: 12px; font-weight: 700; }
.kv2-pool {
  margin-top: 8px; border: 1px solid var(--border); border-radius: 20px;
  background: rgba(255, 255, 255, 0.7); padding: 8px;
}
.kv2-pool-row { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; }
.kv2-pool-empty {
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 10px; font-weight: 700;
  color: var(--accent2);
}
.kv2-chip {
  border: 1px solid var(--border); border-radius: 14px; background: #fff;
  padding: 7px 11px; color: var(--text); cursor: grab;
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 11.5px; font-weight: 700;
  /* ⚠️ `touch-action: none` : sans lui, le navigateur interprète le glissement du
     doigt comme un défilement de page et le drag ne démarre jamais. C'est LA
     raison pour laquelle la question était injouable au doigt. */
  touch-action: none; user-select: none; -webkit-user-select: none;
  transition: border-color .2s ease, box-shadow .2s ease, transform .2s ease, background .2s ease;
}
.kv2-chip:active { cursor: grabbing; }
/* L'étiquette d'origine s'efface pendant qu'on déplace son fantôme */
.kv2-chip.dragging, .kv2-bin-item.dragging { opacity: .28; }
/* Fantôme suivant le doigt/curseur : hors flux, au-dessus de tout */
.kv2-chip-ghost {
  position: fixed; z-index: 320; pointer-events: none; margin: 0;
  border-color: var(--accent); background: var(--accent); color: #fff;
  box-shadow: 0 12px 26px rgba(17, 24, 39, 0.28); transform: scale(1.06);
}
.kv2-chip:hover { border-color: var(--accent); box-shadow: var(--kv2-shadow-sm); }
.kv2-chip.picked {
  border-color: var(--accent); background: var(--accent); color: #fff;
  box-shadow: var(--kv2-shadow-md); transform: scale(1.05);
}
.kv2-chip .kv2-grip { margin-right: 4px; opacity: 0.4; }

.kv2-bins { margin-top: 8px; display: grid; flex: 1; grid-template-columns: 1fr 1fr; gap: 8px; }
.kv2-bin {
  display: flex; flex-direction: column; text-align: left; cursor: pointer;
  border: 2px dashed rgba(91, 108, 249, 0.6); border-radius: 20px; padding: 8px;
  background: var(--kv2-soft); transition: background .2s ease, border-color .2s ease, box-shadow .2s ease;
}
.kv2-bin[data-tone="ust"] { border-color: rgba(251, 191, 36, 0.7); background: #fffbeb; }
.kv2-bin.over { border-color: var(--accent); background: rgba(91, 108, 249, 0.15); box-shadow: 0 0 0 2px rgba(91, 108, 249, 0.4); }
.kv2-bin[data-tone="ust"].over { border-color: #f59e0b; background: #fef3c7; box-shadow: 0 0 0 2px rgba(251, 191, 36, 0.5); }
.kv2-bin-head {
  display: flex; align-items: center; justify-content: space-between;
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 12px; font-weight: 800;
  color: var(--accent-deep);
}
.kv2-bin[data-tone="ust"] .kv2-bin-head { color: #b45309; }
.kv2-bin-head b {
  display: grid; place-items: center; width: 20px; height: 20px; border-radius: 999px;
  background: var(--accent); color: #fff; font-size: 10px; font-weight: 800;
}
.kv2-bin[data-tone="ust"] .kv2-bin-head b { background: #f59e0b; }
.kv2-bin-items { margin-top: 6px; display: flex; flex-wrap: wrap; gap: 5px; align-content: flex-start; flex: 1; }
.kv2-bin-hint {
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 10px; font-weight: 600;
  opacity: 0.6; color: var(--accent);
}
.kv2-bin[data-tone="ust"] .kv2-bin-hint { color: #b45309; }
.kv2-bin-item {
  border: 0; border-radius: 14px; background: #fff; padding: 5px 9px; cursor: grab;
  touch-action: none; user-select: none; -webkit-user-select: none;
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 11px; font-weight: 700;
  color: var(--text); box-shadow: var(--kv2-shadow-sm);
  transition: box-shadow .2s ease;
}
.kv2-bin-item:hover { box-shadow: 0 0 0 2px rgba(91, 108, 249, 0.4); }

/* Association */
.kv2-play-match { display: flex; height: 100%; flex-direction: column; padding: 8px; }
.kv2-play-match .kv2-qprompt { font-size: 12px; font-weight: 700; }
.kv2-match {
  position: relative; margin-top: 4px; display: grid; flex: 1;
  grid-template-columns: minmax(0, 0.92fr) 56px minmax(0, 0.92fr);
  align-items: stretch; gap: 4px;
}
.kv2-match-col { display: grid; gap: 6px; }
.kv2-mbtn {
  display: flex; align-items: center; justify-content: center;
  border: 2px solid #e2e8f0; border-radius: 16px; background: #fff; padding: 2px 8px;
  text-align: center; color: #334155; cursor: grab; touch-action: none;
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 10px; font-weight: 800;
  box-shadow: var(--kv2-shadow-sm);
  transition: border-color .2s ease, background .2s ease, transform .2s ease, box-shadow .2s ease;
}
.kv2-mbtn:hover { border-color: rgba(91, 108, 249, 0.6); background: rgba(91, 108, 249, 0.05); }
.kv2-mbtn.active {
  border-color: var(--accent); background: var(--accent); color: #fff;
  transform: scale(1.03); box-shadow: 0 0 0 4px rgba(91, 108, 249, 0.3); cursor: grabbing;
}
.kv2-mbtn.paired { border-color: transparent; color: #fff; cursor: pointer; }
.kv2-mbtn.paired:hover { filter: brightness(1.1); }
.kv2-mbtn[data-pair="0"].paired { background: #6366f1; }
.kv2-mbtn[data-pair="1"].paired { background: #f59e0b; }
.kv2-mbtn[data-pair="2"].paired { background: #10b981; }
.kv2-mbtn[data-pair="3"].paired { background: #d946ef; }
/* ⚠️ Police plus grande QUE la colonne de droite : ses étiquettes sont courtes
   (CaCO₃, AgCl…) et flottaient en 10px dans des cartes presque vides. Les 10px
   de `.kv2-mbtn` restent calibrés pour la colonne de GAUCHE, dont les énoncés
   longs passeraient sur une ligne de plus et désaligneraient les traits. */
.kv2-mright { color: #475569; cursor: pointer; font-size: 14px; }
.kv2-mright.droppable { border-style: dashed; border-color: var(--accent); color: var(--accent-deep); }
.kv2-mright.droppable:hover { transform: scale(1.03); background: rgba(91, 108, 249, 0.05); }
.kv2-mright:disabled { cursor: default; }
.kv2-match-wires { position: relative; }
.kv2-match-wires svg { position: absolute; inset: 0; width: 100%; height: 100%; }
/* ⚠️ `width`/`height` EXPLICITES. Un <svg> sans dimensions garde sa taille
   intrinsèque par défaut (300x150) malgré `inset: 0` : le tracé des cartes 3 et 4
   (centres à y=170 et y=239) était dessiné HORS du SVG, donc invisible. Le path
   existait pourtant — un test « le tracé est-il créé ? » aurait répondu oui. */
.kv2-match-drag {
  position: absolute; inset: 0; width: 100%; height: 100%;
  z-index: 3; pointer-events: none;
}

/* ── Écran VERDICT ──────────────────────────────────────────────────────────── */
.kv2-verdict {
  position: relative; display: flex; height: 100%; flex-direction: column;
  padding: 12px 12px 64px;
}
.kv2-verdict-mid { margin-top: 12px; flex: 1; display: flex; align-items: center; justify-content: center; }
.kv2-verdict-qcm .kv2-verdict-mid { margin-top: 0; display: block; flex: none; }
.kv2-vopt {
  position: relative; display: flex; align-items: center; justify-content: center;
  border-radius: 24px; padding: 4px 12px; text-align: center;
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 13px; font-weight: 800;
  background: #fff; color: #94a3b8;
  box-shadow: 0 3px 0 rgba(0, 0, 0, 0.06), inset 0 0 0 1px #e2e8f0;
}
.kv2-vopt.ok { background: var(--kv2-ok); color: #fff; box-shadow: 0 5px 0 rgba(0, 0, 0, 0.18); }
.kv2-vtag {
  position: absolute; left: -4px; top: -8px; border-radius: 14px;
  background: var(--text); color: #fff; padding: 3px 8px;
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 9px; font-weight: 800;
  letter-spacing: 0.05em; box-shadow: var(--kv2-shadow-sm); white-space: nowrap;
}
.kv2-vmark {
  position: absolute; right: -8px; top: -8px; display: grid; place-items: center;
  width: 24px; height: 24px; border-radius: 999px; color: #fff;
  box-shadow: var(--kv2-shadow-md), 0 0 0 2px #fff;
}
.kv2-vmark.ok { background: var(--kv2-ok); }
.kv2-vmark.ko { background: #f43f5e; }
.kv2-vopt > span:last-child { position: relative; z-index: 2; }

/* Verdict — catégorisation */
.kv2-vbins { display: grid; width: 100%; grid-template-columns: 1fr 1fr; gap: 8px; }
.kv2-vbin { position: relative; display: flex; flex-direction: column; border: 2px solid; border-radius: 20px; padding: 8px; }
.kv2-vbin.ok { border-color: #34d399; background: #ecfdf5; }
.kv2-vbin.ko { border-color: #fda4af; background: #fff1f2; }
.kv2-vbin-head { font-family: 'Plus Jakarta Sans', sans-serif; font-size: 11px; font-weight: 800; }
.kv2-vbin.ok .kv2-vbin-head { color: #047857; }
.kv2-vbin.ko .kv2-vbin-head { color: #e11d48; }
.kv2-vbin-items { margin-top: 4px; display: flex; flex-wrap: wrap; gap: 4px; }
.kv2-vbin-item {
  border: 1px solid #e2e8f0; border-radius: 14px; background: #fff; padding: 4px 8px;
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 11px; font-weight: 700; color: #64748b;
}
.kv2-vbin-item.ok { border-color: #6ee7b7; color: #047857; }
.kv2-vbin-item.ko { border-color: #fda4af; color: #e11d48; }
.kv2-vbin-none { font-family: 'Plus Jakarta Sans', sans-serif; font-size: 9px; font-style: italic; color: var(--text-secondary); }

/* Verdict — association */
.kv2-vmatch {
  display: grid; height: 100%; width: 100%;
  grid-template-columns: minmax(0, 0.92fr) 56px minmax(0, 0.92fr);
  align-items: stretch; gap: 6px;
}
.kv2-vtile {
  display: flex; align-items: center; justify-content: center;
  border: 2px solid; border-radius: 16px; padding: 2px 8px; color: #fff;
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 9px; font-weight: 800;
}
.kv2-vtile.ok { background: #10b981; border-color: #059669; }
.kv2-vtile.ko { background: #f43f5e; border-color: #e11d48; }
.kv2-vtile.left { justify-content: flex-start; text-align: left; }

/* ─── Flèche jaune « continuer » ───────────────────────────────────────────────
   DEUX niveaux, et c'est indispensable : le SLOT porte l'apparition (il monte du
   bas), le BOUTON porte le balancement. Deux `transform` sur le même élément se
   seraient écrasés l'un l'autre.
   ⚠️ L'apparition est une TRANSITION, plus une animation à délai. Une animation
   `both` avec délai laisse l'élément à `opacity: 0` avant de démarrer : combiné à
   un `animation-play-state: paused` au survol, la flèche naissait SOUS le curseur
   (on venait de cliquer au même endroit) et restait figée, invisible. C'était la
   cause du « elle apparaît, disparaît, revient » sur desktop, et de son absence
   totale sur mobile, où le survol reste collé après un tap. */
.kv2-arrow-slot {
  position: absolute; bottom: 12px; left: 50%; z-index: 3;
  transform: translate(-50%, 22px); opacity: 0; pointer-events: none;
  transition: transform .34s cubic-bezier(0.22, 1, 0.36, 1), opacity .26s ease;
}
.kv2-arrow-slot[data-on="1"] { transform: translate(-50%, 0); opacity: 1; pointer-events: auto; }
.kv2-arrow {
  display: grid; place-items: center; width: 40px; height: 40px;
  border: 0; border-radius: 999px; background: var(--gold); color: var(--text);
  cursor: pointer; box-shadow: 0 6px 0 rgba(0, 0, 0, 0.15), 0 0 0 2px rgba(255, 255, 255, 0.6);
  animation: kv2-arrow-bob 1.4s ease-in-out infinite;
  transition: background .2s ease, box-shadow .2s ease, filter .2s ease;
}
/* Le survol et l'enfoncement N'UTILISENT PAS `transform` : le balancement est une
   animation en cours, elle l'emporterait sur la transition et l'effet serait
   invisible. On agit donc sur la couleur et l'ombre, toujours perceptibles. */
.kv2-arrow:hover { background: #ffc94a; filter: brightness(1.05); box-shadow: 0 6px 0 rgba(0, 0, 0, 0.2), 0 0 0 3px rgba(255, 255, 255, 0.85); }
.kv2-arrow:active { box-shadow: 0 2px 0 rgba(0, 0, 0, 0.15), 0 0 0 2px rgba(255, 255, 255, 0.6); }
.kv2-arrow:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }

/* ── Écran EXPLICATION ──────────────────────────────────────────────────────── */
.kv2-explain {
  position: relative; display: flex; height: 100%; flex-direction: column;
  align-items: center; justify-content: center; gap: 8px; padding: 12px 12px 64px;
}
.kv2-explain-card {
  width: 100%; max-width: 28rem; border-radius: 24px; background: #fff;
  padding: 12px; box-shadow: var(--kv2-shadow-sm);
}
.kv2-explain-ic {
  display: grid; place-items: center; margin: 0 auto;
  width: 32px; height: 32px; border-radius: 999px; background: #fef3c7; color: #d97706;
}
.kv2-explain-card p {
  margin-top: 8px; text-align: center; font-size: 11px; line-height: 1.4; color: var(--text);
}
.kv2-explain-card .kv2-answer {
  margin-top: 4px; display: inline-block;
  font-family: 'Plus Jakarta Sans', sans-serif; font-weight: 800; color: #059669;
}
.kv2-explain-img {
  width: 100%; max-width: 28rem; overflow: hidden; border-radius: 20px;
  background: rgba(0, 0, 0, 0.05);
}
.kv2-explain-img img { display: block; width: 100%; max-height: 160px; object-fit: cover; }

/* ── Écran BILAN ────────────────────────────────────────────────────────────── */
/* ⚠️ Le bilan doit tenir ENTIÈREMENT dans l'écran de la tablette (~352px de haut) :
   une célébration ne scrolle jamais (règle du projet). Tous les espacements sont
   donc serrés et exprimés en `clamp` pour absorber les petites tablettes.
   Ne pas ajouter d'élément ici sans vérifier qu'il reste dans le cadre. */
.kv2-end {
  display: flex; height: 100%; flex-direction: column; align-items: center;
  justify-content: center; gap: clamp(4px, 1.2vh, 9px);
  padding: 10px 14px 12px; text-align: center;
}
.kv2-end-eyebrow {
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.1em; color: #059669;
}
.kv2-end-score { font-family: 'Fredoka', sans-serif; font-size: 1.375rem; font-weight: 700; line-height: 1.1; color: var(--text); }
.kv2-stars { display: flex; justify-content: center; gap: 4px; overflow: visible; }
.kv2-star { display: grid; place-items: center; width: 32px; height: 32px; color: #cbd5e1; }
.kv2-star svg { width: 100%; height: 100%; overflow: visible; }
/* ⚠️ `both` + délai posé en JS : chaque étoile gagnée attend SON tour (650 ms
   après l'arrivée de l'écran, puis 340 ms entre deux), les vides fondent
   ensemble. Le rythme est volontairement posé : un enchaînement plus court
   redevenait un seul mouvement illisible. */
.kv2-star.off { filter: grayscale(1); animation: kv2-star-fade 420ms ease-out both; }
.kv2-star.on {
  color: var(--gold); filter: drop-shadow(0 7px 10px rgba(255, 209, 102, 0.35));
  transform-origin: center;
  animation: kv2-star-pop 560ms cubic-bezier(0.34, 1.4, 0.64, 1) both;
}
/* Le Kwiix de l'ÉLÈVE (bot-student), au centre de SON bilan — distinct du coach
   qui commente à côté de la tablette. */
.kv2-end-kwiix { position: relative; width: 62px; height: 62px; flex: none; }
.kv2-end-kwiix img { width: 100%; height: 100%; filter: drop-shadow(0 8px 5px rgba(0, 0, 0, 0.08)); }
.kv2-end-title { font-family: 'Fredoka', sans-serif; font-size: 1.125rem; font-weight: 700; line-height: 1.15; color: var(--text); }
.kv2-end-rewards { display: flex; align-items: center; gap: 8px; }
.kv2-end-rewards span {
  border-radius: 999px; padding: 5px 11px; box-shadow: var(--kv2-shadow-sm);
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 11.5px; font-weight: 800;
  white-space: nowrap;
}
/* ⚠️ XP et pièces sur le MÊME or : ce sont deux gains de la même gamification,
   deux couleurs en faisaient deux systèmes. L'or est la couleur des récompenses
   partout (chapitre « ce qui le fait revenir », étoiles, carte gamification) —
   et le violet restait la couleur des ACTIONS (Rejouer), plus lisible ainsi. */
.kv2-end-xp,
.kv2-end-coins { background: var(--gold); color: var(--text); }
.kv2-end-ctas { margin-top: 2px; display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: 8px; }
.kv2-end-ctas > * {
  display: inline-flex; align-items: center; gap: 6px; border: 0; border-radius: 999px;
  padding: 9px 15px; cursor: pointer; box-shadow: var(--kv2-shadow-soft);
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 0.8125rem; font-weight: 800;
  white-space: nowrap; transition: transform .2s ease;
}
.kv2-end-ctas > *:hover { transform: scale(1.05); }
.kv2-end-ctas > *:active { transform: translateY(2px); }
/* ⚠️ Deux REGISTRES, pas deux boutons jumeaux : le bilan est le pic
   d'intention de toute la page. « Créer mon compte » est le seul bouton plein
   (vert = l'action), « Rejouer » redevient un bouton discret. Avant, les deux
   avaient exactement le même poids et « Rejouer » passait en premier.
   Ne pas les réaligner : leur différence de poids EST le message. */
.kv2-end-signup {
  background: var(--accent2); color: #fff;
  padding: 11px 20px; font-size: 0.875rem;
}
.kv2-end-replay {
  background: transparent; color: var(--text-secondary);
  box-shadow: none; border: 1.5px solid var(--border);
  font-weight: 700; padding: 8px 14px;
}
.kv2-end-replay:hover { color: var(--text); border-color: var(--text-secondary); }

/* ── Confettis / étincelles ─────────────────────────────────────────────────── */
.kv2-confetti, .kv2-sparkles { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.kv2-confetti { z-index: 4; }
.kv2-sparkles { z-index: 3; }
.kv2-confetti i { position: absolute; top: -20px; border-radius: 2px; }
.kv2-sparkles i {
  position: absolute; border-radius: 50%;
  background: radial-gradient(circle, #FFF6C2 0%, #FFD166 45%, transparent 70%);
  filter: drop-shadow(0 0 6px rgba(255, 209, 102, 0.9));
}

/* ── Kwiix commentateur ───────────────────────────────────────────────────────
   Deux implantations, une seule visible à la fois :
   • < 1024px : SOUS la tablette, bulle à droite (`.kv2-coach-mob`).
   • ≥ 1024px : À GAUCHE de la tablette, DANS LE FLUX (`.kv2-coach-desk`), bulle
     au-dessus — géométrie reprise de `.lp-hero-visual` de la landing officielle.
   ⚠️ Ne JAMAIS repasser le coach desktop en `position: absolute` avec un décalage
   négatif : c'était la solution du pack Lovable, et elle fait mordre la bulle sur
   le titre puis sur le sous-titre (mesuré : 133px de chevauchement à 1024px). En
   flux, le débordement est structurellement impossible. */
.kv2-coach-desk { display: none; }
.kv2-coach-mob {
  /* ⚠️ `align-items: center` : la bulle est centrée VERTICALEMENT sur le Kwiix,
     et sa queue est posée à 50 % de sa hauteur (voir ci-dessous). En
     `flex-start` + `margin-top`, la queue tombait ~50px AU-DESSUS de la tête et
     pointait dans le vide.
     ⚠️ `min-height` : la rangée a une hauteur FIXE, réservée pour la plus longue
     réplique. Sans elle, une bulle qui passe de 2 à 5 lignes grandissait la
     rangée et faisait DESCENDRE le Kwiix d'un demi-écart : la mascotte sautait
     d'une position à l'autre au fil de la démo. Ici, la bulle grandit dans un
     couloir de hauteur constante et le Kwiix ne bouge JAMAIS. */
  margin-top: 18px; display: flex; align-items: center; gap: 10px;
  min-height: var(--kv2-coach-slot-mob);
  /* ⚠️ `flex-start`, PAS `center` : la paire Kwiix + bulle était centrée en bloc,
     donc chaque changement de longueur de réplique recentrait le tout et le
     Kwiix GLISSAIT horizontalement à chaque bulle. Ancré à gauche (sous le bord
     gauche de la tablette), il ne bouge plus jamais ; seule la bulle s'allonge
     vers la droite. */
  justify-content: flex-start;
}
/* La scène du Kwiix a une largeur FIXE : c'est elle qui garantit l'ancrage. */
.kv2-coach-mob .kv2-coach-stage { flex: 0 0 auto; }
/* La bulle occupe le reste de la rangée et n'en sort jamais. */
.kv2-coach-mob .kv2-bubble { flex: 0 1 auto; min-width: 0; }
.kv2-coach-mob img {
  /* `display: block` : une image `inline` traîne l'espace de sa ligne de base
     sous elle, ce qui décalait la bulle de 4px vers le haut. */
  display: block; width: 100%; height: auto;
}
/* Scène du Kwiix = repère de l'ombre au sol. La figure flotte DANS cette scène,
   l'ombre est posée au fond : l'une monte, l'autre reste par terre. */
.kv2-coach-stage { position: relative; flex: none; }
.kv2-coach-mob .kv2-coach-stage { width: 76px; }
/* Ombre au sol — valeurs IDENTIQUES à `.lp-coach-shadow` de la landing
   officielle (et à FloatingKwiixMascot côté app) : 58 % de large, rgba(45,45,58,.34),
   flou 5px. Une seule ombre partout, jamais une variante locale.
   ⚠️ Elle remplace le `drop-shadow` qui était posé sur l'image : deux ombres
   pour un même objet, c'est une de trop — et une ombre collée à la mascotte ne
   dit pas qu'elle flotte. */
.kv2-coach-shadow {
  position: absolute; left: 21%; bottom: -9px; width: 58%; height: 9px;
  border-radius: 50%; background: rgba(45, 45, 58, 0.34); filter: blur(5px);
}
.kv2-bubble {
  position: relative; border-radius: 24px; background: #fff; padding: 8px 12px;
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 13px; font-weight: 700;
  line-height: 1.35; color: var(--text); box-shadow: var(--kv2-shadow-soft);
}
/* ⚠️ Police RÉDUITE sur mobile (12px contre 13) : décision du 31.07.2026 — le
   couloir reste à sa taille (`--kv2-coach-slot-mob`), c'est le texte qui s'y
   adapte. La plus longue réplique (explain q2, corrigée) faisait 104px en 13px
   dans un couloir de 96 : le Kwiix aurait bougé. Si une réplique s'allonge
   encore, re-mesurer AVANT de toucher au couloir. */
.kv2-coach-mob .kv2-bubble { max-width: 244px; font-size: 12px; }
/* Queue = carré pivoté centré sur la HAUTEUR de la bulle, donc face à la tête du
   Kwiix quel que soit le nombre de lignes du texte. Même forme que la queue
   desktop et que `.lp-bubble::after` de la landing officielle. */
.kv2-coach-mob .kv2-bubble::after {
  content: ''; position: absolute; left: -5px; top: 50%;
  width: 12px; height: 12px; background: #fff; border-radius: 2px;
  transform: translateY(-50%) rotate(45deg);
}
/* ⚠️ Flottement sur le WRAPPER `.kv2-coach-fig`, réactions (jump/shake) sur
   l'IMG : les deux animations vivent sur des éléments SÉPARÉS, donc rejouer une
   réaction — le JS retire puis remet la classe — ne redémarre pas le flottement
   et l'ombre au sol reste EN PHASE. (Même leçon que `.lp-coach-*` de la landing
   officielle, où le déphasage avait fait battre l'ombre à contre-sens.) */
.kv2-coach-img.jump { animation: kv2-jump .7s ease-in-out infinite; }
.kv2-coach-img.shake { animation: kv2-shake .5s ease-in-out 2; }
@media (prefers-reduced-motion: no-preference) {
  .kv2-coach-fig { animation: kv2-coach-float 3.4s ease-in-out infinite; }
  .kv2-coach-shadow { animation: kv2-coach-shadow 3.4s ease-in-out infinite; }
  /* La bulle « POPE » à chaque changement de réplique (même ressort que la page
     « Lancer un Kwiiz ») : c'est le seul signal que le Kwiix vient de parler,
     puisqu'il ne bouge plus de sa place. */
  .kv2-bubble.pop { animation: kv2-bubble-pop .32s cubic-bezier(0.34, 1.56, 0.64, 1); }
}
/* Timings et amplitudes repris tels quels de `.lp-coach-*` : le Kwiix flotte de
   la même façon sur les deux landings et dans l'app. */
@keyframes kv2-coach-float  { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } }
@keyframes kv2-coach-shadow { 0%, 100% { transform: scaleX(1.06); opacity: .8; } 50% { transform: scaleX(.5); opacity: .18; } }
@keyframes kv2-bubble-pop {
  0%   { opacity: 0; transform: scale(.72); }
  60%  { opacity: 1; transform: scale(1.05); }
  100% { opacity: 1; transform: scale(1); }
}

/* ═══════════════════════ CARROUSEL « Pourquoi Kwiiz » ═══════════════════════ */
.kv2-car { position: relative; overflow: hidden; padding: 80px 0; }
.kv2-car-bg { position: absolute; inset: 0; transition: background 700ms ease; }
.kv2-car-bg[data-tone="indigo"]  { background: linear-gradient(to bottom right, #567bf7, #5358ee); }
.kv2-car-bg[data-tone="amber"]   { background: linear-gradient(to bottom right, #ffb113, #fb7c00); }
.kv2-car-bg[data-tone="emerald"] { background: linear-gradient(to bottom right, #20b46b, #009662); }
.kv2-car-bg[data-tone="rose"]    { background: linear-gradient(to bottom right, #f83e54, #d30046); }
.kv2-car > .kv2-dots { position: absolute; inset: 0; opacity: 0.2; pointer-events: none; }
.kv2-car-inner { position: relative; }

.kv2-car-head { margin-bottom: 32px; text-align: center; color: #fff; }
.kv2-car-head .kv2-eyebrow {
  font-family: 'Plus Jakarta Sans', sans-serif; font-weight: 700;
  font-size: clamp(12px, 0.9vw, 14px);
  text-transform: uppercase; letter-spacing: 0.15em; opacity: 0.8;
}
.kv2-car-head h2 { margin-top: 12px; font-size: 1.875rem; letter-spacing: -0.02em; }

.kv2-car-deck {
  position: relative; height: 470px; cursor: grab; outline: none;
  /* ⚠️ `pan-y` : LE point qui rend le glissement utilisable au doigt. Sans lui
     (`auto` par défaut), le navigateur s'autorise à faire défiler la page dans
     les DEUX axes pendant le geste — on croyait faire glisser une carte et la
     page montait en même temps. `pan-y` lui laisse le défilement VERTICAL (on ne
     doit jamais emprisonner le doigt dans un carrousel) et nous confie
     l'horizontal. `none` serait excessif : la page ne défilerait plus du tout au
     doigt dans cette zone. */
  touch-action: pan-y;
}
.kv2-car-deck:focus-visible { outline: 3px solid #fff; outline-offset: 6px; border-radius: 34px; }
.kv2-car-deck.dragging { cursor: grabbing; }
/* Pendant le glissement, la carte suit le doigt SANS transition : sinon elle
   traîne d'un demi-tempo derrière le curseur. */
.kv2-car-deck.dragging .kv2-card { transition: none; }
/* Les images ne doivent pas être « attrapées » par le navigateur pendant un
   glissement à la souris — sinon c'est le drag-and-drop natif qui démarre. */
.kv2-car-deck img { user-select: none; -webkit-user-drag: none; }
.kv2-card {
  position: absolute; inset: 0; display: grid; grid-template-columns: 1fr;
  grid-template-rows: 9rem 1fr; gap: 16px;
  border: 1px solid rgba(255, 255, 255, 0.4); border-radius: 32px; background: #fff;
  padding: 16px; box-shadow: var(--kv2-shadow-pop);
  transition: transform 700ms ease, opacity 700ms ease;
}
.kv2-card[data-pos="hidden"] { opacity: 0; pointer-events: none; z-index: 1; }
.kv2-card[data-pos="active"] { z-index: 30; opacity: 1; transform: none; }
.kv2-card[data-pos="next"]   { z-index: 20; opacity: 0.4; transform: translateX(32px) rotate(2deg) scale(0.95); pointer-events: none; }
.kv2-card[data-pos="prev"]   { z-index: 10; opacity: 0.4; transform: translateX(-32px) rotate(-2deg) scale(0.95); pointer-events: none; }
/* ⚠️ PAS de rectangle de fond : le cadre est TRANSPARENT et c'est l'IMAGE qui
   porte son propre contour + son ombre. Avec `object-fit: contain`, un fond
   coloré laissait des bandes vides autour du visuel ; là, le liseré épouse
   exactement l'image, quel que soit son format. */
.kv2-card-media {
  position: relative; display: flex; align-items: center; justify-content: center;
  background: transparent;
  /* ⚠️ PAS de `overflow: hidden`. L'image fait EXACTEMENT la largeur du cadre
     (mesuré : 481 px dans 481) : tout clip rognait son ombre portée sur les
     côtés, et la feuille arrière de la pile dépassait de 5 px en bas — son
     ombre était coupée net. Le rembourrage réserve la place de l'ombre À
     L'INTÉRIEUR du cadre : rien ne bave sur la colonne de texte, rien n'est
     tronqué. Le bas est plus généreux, c'est là que tombe l'ombre. */
  padding: 10px 14px 26px;
}
/* Image agrandissable. ⚠️ AUCUN anneau de couleur au survol : l'image touchant
   les bords du cadre, l'anneau se confondait avec lui et se faisait rogner.
   L'affordance est une pastille « + » posée sur le coin du visuel — elle dit
   « ça s'ouvre en grand » sans rien ajouter autour de l'image. */
.kv2-zoomable { cursor: zoom-in; outline: none; }
/* Enveloppe qui épouse le visuel ET le CADRE de découpe.
   ⚠️ L'image occupe toute la LARGEUR disponible et garde son format ; si elle est
   trop haute (un document en portrait), son bas est COUPÉ ici plutôt que réduit.
   Réduire une page de rapport pour la faire tenir entière la rendait minuscule et
   illisible ; coupée en bas, on lit son en-tête et ses chiffres, et l'on comprend
   qu'il y a une suite. C'est l'enveloppe qui porte le liseré et l'ombre, pour
   qu'ils épousent la zone RÉELLEMENT visible.
   `overflow: hidden` ne rogne que les enfants : l'ombre de l'enveloppe elle-même
   reste entière (elle tombe dans le rembourrage du cadre). */
.kv2-fit {
  position: relative; display: block; width: 100%; max-height: 100%; overflow: hidden;
  border-radius: 12px; border: 1px solid rgba(45, 45, 58, 0.10);
  box-shadow: 0 14px 34px -12px rgba(45, 45, 58, 0.30), 0 2px 6px rgba(45, 45, 58, 0.06);
}
/* Sélecteur volontairement plus spécifique que `.kv2-card-media img` (qui garde,
   lui, le rendu ENTIER des feuilles de la pile papier) : sans ça l'ordre des
   règles décidait, et l'image reprenait son `max-height`. */
.kv2-card-media .kv2-fit img {
  width: 100%; height: auto; max-width: none; max-height: none;
  border: 0; border-radius: 0; box-shadow: none;
}
.kv2-zoom-plus {
  position: absolute; z-index: 4; top: 8px; right: 8px;
  width: 30px; height: 30px; border-radius: 999px; border: 0;
  display: grid; place-items: center; padding: 0;
  background: rgba(255, 255, 255, 0.94); color: #2D2D3A;
  box-shadow: 0 2px 10px rgba(45, 45, 58, 0.22);
  /* Toujours visible : sans survol au doigt, une pastille qui n'apparaît qu'au
     hover n'existe pas sur mobile. Elle s'affirme au survol, sans surgir. */
  opacity: 0.9; transition: opacity .16s ease, transform .16s ease, background .16s ease;
  pointer-events: none;
}
.kv2-zoomable:hover .kv2-zoom-plus { opacity: 1; transform: scale(1.08); background: #fff; }
.kv2-zoom-plus svg { width: 17px; height: 17px; display: block; }
/* Dans la pastille « 2 documents » de la pile, le « + » n'est plus une pastille
   à part : il fait corps avec l'étiquette (une seule cible, un seul message). */
.kv2-stack-badge .kv2-zoom-plus {
  position: static; width: 15px; height: 15px; opacity: 1;
  background: transparent; box-shadow: none; color: #fff;
}
.kv2-stack-badge .kv2-zoom-plus svg { width: 15px; height: 15px; }
.kv2-zoomable:hover .kv2-stack-badge .kv2-zoom-plus { transform: none; background: transparent; }
/* Le focus CLAVIER garde un indicateur : c'est une exigence d'accessibilité,
   distincte de l'anneau de survol qu'on vient de retirer. */
.kv2-zoomable:focus-visible { outline: 3px solid var(--accent); outline-offset: 4px; border-radius: 14px; }
.kv2-card-media img {
  display: block; width: auto; height: auto; max-width: 100%; max-height: 100%;
  border-radius: 12px; border: 1px solid rgba(45, 45, 58, 0.10);
  box-shadow: 0 14px 34px -12px rgba(45, 45, 58, 0.30), 0 2px 6px rgba(45, 45, 58, 0.06);
  /* ⚠️ `contain`, PAS `cover`. Le cadre passe de 2.14 (mobile) à 0.68 (tablette)
     à 1.06 (desktop), et les visuels de 0.71 (fiche papier) à 2.05 (référentiel).
     En `cover`, jusqu'à 48 % de l'image était rognée — les réponses du QCM
     étaient coupées. En `contain`, le format des visuels n'a plus d'importance :
     rien n'est amputé, le fond doux sert de cadre. Ne pas revenir à `cover` sans
     avoir uniformisé tous les visuels ET figé le ratio du cadre. */
  object-fit: contain;
}
.kv2-card-body { display: flex; min-width: 0; flex-direction: column; justify-content: center; }
.kv2-card-tag {
  display: inline-flex; width: fit-content; align-items: center; border-radius: 999px;
  background: var(--kv2-soft); padding: 4px 12px; color: var(--accent);
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 11px; font-weight: 800;
  text-transform: uppercase; letter-spacing: 0.15em;
}
.kv2-card-body h3 { margin-top: 12px; font-size: 1.5rem; line-height: 1.15; letter-spacing: -0.02em; font-weight: 800; }
.kv2-card-body p { margin-top: 12px; font-size: 1rem; color: var(--text-secondary); }
/* Indicateur de position : le numéro COURANT est mis en avant (violet, grand) et
   la barre se remplit — un « 01 —— 08 » gris ne disait ni où on est ni combien il
   reste à voir. */
.kv2-card-count {
  margin-top: 22px; display: flex; align-items: center; gap: 10px;
  font-family: 'Plus Jakarta Sans', sans-serif; font-variant-numeric: tabular-nums;
}
.kv2-card-now { font-size: 1.125rem; font-weight: 800; color: var(--accent); line-height: 1; }
.kv2-card-track {
  position: relative; flex: 1; height: 4px; border-radius: 999px;
  background: var(--border); overflow: hidden;
}
.kv2-card-track i {
  position: absolute; inset: 0 auto 0 0; display: block; border-radius: 999px;
  background: var(--accent); transition: width .5s ease;
}
.kv2-card-tot { font-size: 12px; font-weight: 700; color: var(--text-secondary); }

.kv2-car-ctrl { margin-top: 24px; display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.kv2-car-dots { display: flex; gap: 8px; }
.kv2-car-dots button {
  height: 8px; width: 8px; border: 0; border-radius: 999px; padding: 0; cursor: pointer;
  background: rgba(255, 255, 255, 0.5); transition: all .3s ease;
}
.kv2-car-dots button:hover { background: rgba(255, 255, 255, 0.8); }
.kv2-car-dots button[aria-current="true"] { width: 32px; background: #fff; }
.kv2-car-arrows { display: flex; gap: 8px; }
.kv2-car-arrows button {
  display: grid; place-items: center; width: 44px; height: 44px; border-radius: 999px;
  font-size: 1.125rem; font-weight: 700; cursor: pointer; transition: all .2s ease;
}
.kv2-car-prev { border: 2px solid rgba(255, 255, 255, 0.7); background: rgba(255, 255, 255, 0.1); color: #fff; backdrop-filter: blur(4px); }
.kv2-car-prev:hover { background: #fff; color: var(--text); }
.kv2-car-next { border: 2px solid #fff; background: #fff; color: var(--text); }
.kv2-car-next:hover { transform: scale(1.05); }

/* ═══════════════════════ TYPES DE QUESTIONS ═════════════════════════════════ */
.kv2-qt { position: relative; overflow: hidden; background: rgba(238, 238, 255, 0.5); padding: 64px 0; }
.kv2-qt-head { margin: 0 auto; max-width: 42rem; text-align: center; }
.kv2-qt-head .kv2-eyebrow {
  font-family: 'Plus Jakarta Sans', sans-serif; font-weight: 700;
  font-size: clamp(12px, 0.9vw, 14px);
  text-transform: uppercase; letter-spacing: 0.15em; color: var(--accent);
}
/* Le surtitre officiel (Tarifs, et desormais « Une session… ») suit la meme
   echelle DANS la v2 — sans toucher style.css, partage avec la prod. */
.kv2 .section-eyebrow { font-size: clamp(12px, 0.9vw, 14px); }
.kv2-qt-head h2 { margin-top: 12px; font-size: 1.875rem; letter-spacing: -0.02em; }
.kv2-qt-head p { margin-top: 16px; font-size: 1rem; color: var(--text-secondary); }
.kv2-qt-head .kv2-only-desk { display: none; }

/* ── Grille des cartes : UNE seule, responsive ─────────────────────────────
   Mobile : les cartes s'empilent en 3 colonnes, l'aperçu est masqué (un tap
   ouvre la feuille du bas). Desktop : cartes à gauche, aperçu à droite. */
.kv2-qt-body { margin-top: 28px; display: grid; gap: 14px; }
.kv2-qt-side { display: contents; }
.kv2-qt-panel { display: none; }
.kv2-qt-list { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.kv2-qt-card {
  display: flex; flex-direction: column; align-items: center; justify-content: flex-start;
  gap: 9px; text-align: center; cursor: pointer;
  border: 1.5px solid var(--border); border-radius: 18px;
  background: #fff; padding: 14px 8px 12px;
  box-shadow: var(--kv2-shadow-sm);
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.kv2-qt-card:active { transform: translateY(2px); }
.kv2-qt-ic {
  display: grid; place-items: center; flex: none;
  width: 38px; height: 38px; border-radius: 13px;
  background: var(--kv2-soft); color: var(--accent);
  transition: background .18s ease, color .18s ease;
}
.kv2-qt-ic svg { width: 20px; height: 20px; }
.kv2-qt-card b {
  /* Deux lignes RÉSERVÉES (2 × la hauteur de ligne) : « Remise en ordre » se plie
     en deux, « QCM » non — sans cette réserve les cartes n'avaient pas la même
     hauteur d'une rangée à l'autre. Exprimé en `em` : vrai à toutes les tailles. */
  display: flex; align-items: center; justify-content: center; min-height: 2.4em;
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 0.8125rem; font-weight: 800;
  line-height: 1.2; color: var(--text);
}
/* Carte GAMIFICATION : hors de la grille, pleine largeur, teintée or */
.kv2-qt-bonus {
  display: flex; align-items: center; gap: 13px; text-align: left; cursor: pointer;
  border: 1.5px solid var(--gold); border-radius: 20px;
  background: linear-gradient(180deg, #FFFCF2, #fff);
  padding: 13px 15px; box-shadow: var(--kv2-shadow-sm);
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.kv2-qt-bonus:active { transform: translateY(2px); }
.kv2-qt-bonus-ic {
  display: grid; place-items: center; flex: none;
  width: 42px; height: 42px; border-radius: 15px;
  background: rgba(255, 209, 102, 0.26); color: var(--gold-deep);
}
.kv2-qt-bonus-ic svg { width: 22px; height: 22px; }
.kv2-qt-bonus-txt { min-width: 0; }
.kv2-qt-bonus-tag {
  display: block; font-family: 'Plus Jakarta Sans', sans-serif; font-size: 10px;
  font-weight: 800; text-transform: uppercase; letter-spacing: 0.15em; color: var(--gold-deep);
}
.kv2-qt-bonus b {
  display: block; margin-top: 1px;
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 0.9375rem; font-weight: 800; color: var(--text);
}
.kv2-qt-bonus p { margin-top: 2px; font-size: 12.5px; color: var(--text-secondary); }

/* ─── Vue agrandie (clic sur un aperçu ou une image du carrousel) ───────────── */
.kv2-zoom {
  position: fixed; inset: 0; z-index: 310; display: flex;
  align-items: center; justify-content: center; padding: 24px 20px;
  background: rgba(17, 17, 24, 0.86); backdrop-filter: blur(6px);
  cursor: zoom-out; animation: kv2-pop .2s ease-out;
}
.kv2-zoom-inner { width: min(1120px, 100%); max-height: 100%; }
/* Croix EN HAUT À DROITE de l'écran, pas de la carte : elle reste au même endroit
   quelle que soit la taille du média. Cible de 44px (WCAG 2.5.5). */
.kv2-zoom-x {
  position: absolute; top: 16px; right: 16px; z-index: 2;
  display: grid; place-items: center; width: 44px; height: 44px;
  border: 0; border-radius: 999px; cursor: pointer;
  background: rgba(255, 255, 255, 0.16); color: #fff;
  transition: background .2s ease, transform .15s ease;
}
.kv2-zoom-x:hover { background: rgba(255, 255, 255, 0.3); }
.kv2-zoom-x:active { transform: scale(0.94); }
.kv2-zoom-x:focus-visible { outline: 3px solid #fff; outline-offset: 3px; }
.kv2-zoom-media {
  width: 100%; overflow: hidden; background: #000;
  box-shadow: 0 40px 90px -20px rgba(0, 0, 0, 0.7);
}
/* Une VIDÉO est rognée de ses bords parasites par `.kv2-vidbox` ; une IMAGE du
   carrousel garde SON format (on ne rogne pas un document). */
.kv2-zoom-media.is-img { background: transparent; box-shadow: none; }
.kv2-zoom-media.is-img img {
  display: block; width: auto; height: auto;
  max-width: 100%; max-height: calc(100vh - 160px); margin: 0 auto;
  border-radius: 4px; box-shadow: 0 40px 90px -20px rgba(0, 0, 0, 0.7);
}
/* Légende SOUS le média — c'est ce qu'on regarde, décrit ; pas une étiquette. */
.kv2-zoom-cap {
  margin: 14px auto 0; max-width: 62ch; text-align: center;
  font-size: 0.9375rem; line-height: 1.5; color: rgba(255, 255, 255, 0.92);
}

/* ─── Galerie du plein écran : où l'on est, et comment changer ────────────────
   Même langage que le compteur du carrousel : une bille par élément, l'ACTIVE
   s'allonge en barre. On lit sa position sans compter les billes.
   Placée SOUS la description (on montre, on décrit, puis on situe) — jamais en
   surimpression de la capture, qui est ce qu'on est venu regarder. */
.kv2-zoom-nav {
  margin: 16px auto 0; display: flex; align-items: center; justify-content: center; gap: 14px;
}
.kv2-zoom-nav[hidden] { display: none; }
.kv2-zoom-step {
  display: grid; place-items: center; width: 40px; height: 40px; flex: none;
  border: 0; border-radius: 999px; cursor: pointer;
  background: rgba(255, 255, 255, 0.12); color: #fff;
  transition: background .16s ease, transform .16s ease;
}
.kv2-zoom-step:hover { background: rgba(255, 255, 255, 0.24); }
.kv2-zoom-step:active { transform: scale(0.94); }
.kv2-zoom-step:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }
/* Les flèches sont un CONFORT au pointeur. Au doigt, on glisse : on les masque
   pour laisser toute la largeur aux billes sur un écran étroit. */
@media (max-width: 767px) { .kv2-zoom-step { display: none; } }
.kv2-zoom-dots { display: flex; align-items: center; gap: 7px; }
.kv2-zoom-dot {
  width: 9px; height: 9px; padding: 0; border: 0; border-radius: 999px; cursor: pointer;
  background: rgba(255, 255, 255, 0.34);
  transition: width .22s ease, background .22s ease;
}
.kv2-zoom-dot[data-on="1"] { width: 30px; background: #fff; }
.kv2-zoom-dot:hover { background: rgba(255, 255, 255, 0.6); }
.kv2-zoom-dot:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }
/* Une bille ne mesure que 9px : sa cible TACTILE est étendue par un
   pseudo-élément, sans changer ce qu'on voit (WCAG 2.5.5). */
.kv2-zoom-dot { position: relative; }
.kv2-zoom-dot::before { content: ''; position: absolute; inset: -13px -5px; }
/* La capture suit le doigt pendant le glissement, puis reprend sa place.
   ⚠️ AUCUNE transition PENDANT le geste : elle traînerait d'un demi-tempo
   derrière le doigt. Elle ne sert qu'au retour en place. */
.kv2-zoom-media { transition: transform .18s ease; }
.kv2-zoom[data-drag="1"] .kv2-zoom-media { transition: none; }
/* ⚠️ `touch-action: none` UNIQUEMENT sur une capture vidéo. Posé sur toute la
   vue, il tuait le glissement de la PAIRE de fiches papier, qui repose sur un
   défilement horizontal NATIF (`overflow-x` + scroll-snap). */
.kv2-zoom-media.is-video { touch-action: none; }

/* ─── Deux documents empilés (version papier) ───────────────────────────────── */
.kv2-stack { position: relative; }
/* ⚠️ Feuilles CENTRÉES EXPLICITEMENT (`top/left` + `translate(-50%,-50%)`), pas
   laissées à leur position statique. Une image en absolu dans un conteneur flex
   tire sa place du placement statique ET ses pourcentages de la boîte de
   REMBOURRAGE (pas de la boîte de contenu) : deux bases différentes de celles du
   reste du cadre, ce qui faisait sortir la feuille arrière par le haut à 390 px
   et par la gauche à 768 px. Avec un centre explicite, la géométrie est la même
   à toutes les largeurs et se calcule de tête.
   ⚠️ 74 % de haut, pas 94 % : une feuille INCLINÉE occupe plus de place que sa
   hauteur (à 9°, une feuille de 336 px dessine une boîte de 369 px). La marge
   restante est ce qui laisse l'ombre portée s'afficher entièrement. */
/* ⚠️ Pas de `left` ici : `.kv2-stack img` (0,1,1) battrait le `left` de
   `.kv2-stack-back` (0,1,0) et les deux feuilles resteraient superposées. */
.kv2-stack img {
  position: absolute; top: 50%;
  max-width: 62%; max-height: 78%;
}
/* Les deux feuilles sont franchement DÉCALÉES : la fiche du dessous doit se lire
   comme un second document, pas comme l'ombre du premier. À -13 %/+9 %, il n'en
   dépassait qu'une bande de 61 px sur 287.
   ⚠️ Le décalage se règle par `left`, donc en % du CADRE — pas par un
   `translateX(%)`, qui compte en % de la FEUILLE. La nuance n'est pas
   cosmétique : à 768 et 1024 px la carte passe en deux colonnes égales, le cadre
   se resserre de 481 à 308 px alors que la feuille, contrainte en largeur, garde
   presque sa taille. Un décalage indexé sur la feuille sortait donc du cadre de
   18 px exactement là où la place manquait. Indexé sur le cadre, il se réduit
   avec lui. */
.kv2-stack-back {
  left: 40%; transform: translate(-50%, -50%) rotate(-6deg);
  filter: saturate(.85) brightness(.98);
  z-index: 1;
}
.kv2-stack-front { left: 60%; transform: translate(-50%, -50%) rotate(2.5deg); z-index: 2; }
/* Au survol, l'écart NE bouge PAS : seule l'inclinaison s'accentue. Écarter
   davantage au survol demandait une marge que les cadres étroits n'ont pas. */
.kv2-zoomable:hover .kv2-stack-back { transform: translate(-50%, -50%) rotate(-9deg); }
.kv2-zoomable:hover .kv2-stack-front { transform: translate(-50%, -50%) rotate(3.5deg) translateY(-3px); }
.kv2-stack-badge {
  position: absolute; z-index: 3; bottom: -4px; left: 50%; transform: translateX(-50%);
  display: inline-flex; align-items: center; gap: 6px;
  border-radius: 999px; background: rgba(45, 45, 58, 0.82); color: #fff;
  padding: 4px 11px; backdrop-filter: blur(4px);
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 10.5px; font-weight: 800;
  text-transform: uppercase; letter-spacing: 0.12em; white-space: nowrap;
}

/* ─── Vue agrandie : PAIRE de documents (élève + corrigé) ────────────────────
   Desktop : côte à côte. Mobile : une rangée qu'on fait glisser, avec accroche
   (scroll-snap) — deux pages A4 côte à côte sur 390px seraient illisibles. */
.kv2-zoom-media.is-pair {
  display: flex; gap: 16px; background: transparent; box-shadow: none;
  overflow-x: auto; scroll-snap-type: x mandatory; padding-bottom: 6px;
}
.kv2-zoom-media.is-pair figure {
  margin: 0; flex: 0 0 100%; scroll-snap-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
}
.kv2-zoom-media.is-pair img {
  display: block; width: auto; height: auto;
  max-width: 100%; max-height: calc(100vh - 230px);
  border-radius: 4px; box-shadow: 0 30px 70px -18px rgba(0, 0, 0, 0.7);
}
.kv2-zoom-media.is-pair figcaption {
  max-width: 44ch; text-align: center; font-size: 0.875rem; line-height: 1.45;
  color: rgba(255, 255, 255, 0.9);
}
@media (min-width: 860px) {
  .kv2-zoom-media.is-pair { overflow: visible; }
  .kv2-zoom-media.is-pair figure { flex: 1 1 50%; }
}

/* ─── Emplacement média à venir ─────────────────────────────────────────────── */
.kv2-ph {
  display: flex; height: 100%; width: 100%; flex-direction: column;
  align-items: center; justify-content: center; gap: 8px; text-align: center;
  border: 2px dashed rgba(91, 108, 249, 0.4); border-radius: 24px;
  background: rgba(91, 108, 249, 0.05); padding: 16px;
}
.kv2-ph-ic { display: grid; place-items: center; width: 40px; height: 40px; border-radius: 20px; background: rgba(91, 108, 249, 0.1); color: var(--accent); }
.kv2-ph-ic svg { width: 20px; height: 20px; }
.kv2-ph b {
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 12px; font-weight: 800;
  text-transform: uppercase; letter-spacing: 0.15em; color: var(--accent);
}
.kv2-ph p { max-width: 22ch; font-size: 11px; font-weight: 600; color: var(--text-secondary); }
.kv2-ph code {
  border-radius: 8px; background: rgba(255, 255, 255, 0.8); padding: 4px 8px;
  font-size: 10px; font-weight: 700; color: var(--text);
}

/* ═══════════════════════════ RESPONSIVE ═════════════════════════════════════ */
@media (min-width: 640px) {
  .kv2-stat-grid { grid-template-columns: 1fr 1fr; }
  .kv2-car-deck { height: 520px; }
  .kv2-card { grid-template-rows: 12rem 1fr; }
  .kv2-card-body h3 { font-size: 1.875rem; }
  .kv2-car-head h2 { font-size: 2.25rem; }
  .kv2-qt-head h2 { font-size: 2.25rem; }
}

@media (min-width: 768px) {
  .kv2-hero-inner { padding-top: 96px; padding-bottom: 56px; }
  .kv2-hero h1 { font-size: 3.25rem; }
  .kv2-sub { font-size: 1.25rem; }
  .kv2-stats { margin-top: 80px; }

  /* ⚠️ PAS de surcharge « grande tablette » ici. La tablette a UNE seule
     largeur (352px max, cf. `.kv2-demo`) : ses styles internes sont donc
     calibrés une seule fois, dans les règles de base. Une 2ᵉ calibration pour
     un format de 420px a existé et elle a fini par mentir : quand la tablette
     est passée à 352px pour aligner les marges, les réponses du QCM se sont
     retrouvées à l'étroit (3 lignes par carte). Une taille, une calibration. */

  .kv2-car { padding: 112px 0; }
  .kv2-car-head { margin-bottom: 40px; }
  .kv2-car-head h2 { font-size: 3rem; }
  /* ⚠️ `minmax(0, 1fr)` et NON `1fr`. Un `1fr` vaut `minmax(auto, 1fr)` : sa
     taille MINIMALE est celle de son contenu, il ne descend donc jamais en
     dessous. Une capture en hauteur (la page de rapport, 1118 × 1400) étirait
     ainsi la cellule à 603 px dans une carte de 520, et débordait par le bas sur
     le fond bleu. Avec `minmax(0, …)` la rangée est bornée par la carte, et le
     `max-height: 100%` des enfants a enfin une hauteur définie à laquelle se
     référer. */
  .kv2-card { grid-template-columns: 1fr 1fr; grid-template-rows: minmax(0, 1fr); gap: 24px; padding: 32px; }
  .kv2-card-body h3 { margin-top: 16px; font-size: 2.25rem; }
  .kv2-card-body p { margin-top: 16px; font-size: 1.125rem; }
  .kv2-qt { padding: 112px 0; }
  .kv2-qt-head h2 { font-size: 3rem; }
  .kv2-qt-head p { font-size: 1.125rem; }

}

@media (min-width: 1024px) {
  /* Ratio de la landing officielle (`.lp-hero-inner`) : les marges du hero
     tombent EXACTEMENT sur le logo à gauche et sur le CTA de la navbar à droite,
     puisque tout partage le même `.container`.
     ⚠️ `--kv2-gutter` est une SOURCE UNIQUE, utilisée à la fois par la gouttière
     de la grille (texte ↔ visuel) et par celle du flex (Kwiix ↔ tablette). C'est
     ce qui met le Kwiix EXACTEMENT au centre entre les deux blocs. Deux valeurs
     séparées donnaient 48px d'un côté et 38px de l'autre : le Kwiix était
     visiblement décalé vers la tablette. Ne pas les redissocier. */
  .kv2-hero-grid { --kv2-gutter: clamp(28px, 3.4vw, 48px); grid-template-columns: 1.05fr .95fr; gap: var(--kv2-gutter); }
  .kv2-hero-copy { text-align: left; }
  .kv2-hero-copy .kv2-sub { margin-left: 0; margin-right: 0; }
  .kv2-actions, .kv2-hero-checks, .kv2-trust { justify-content: flex-start; }
  .kv2-hero-copy .lp-hero-badges { justify-content: flex-start; }
  .kv2-trust { justify-content: center; }
  .kv2-hero h1 { font-size: 3.5rem; }
  .kv2-stat-grid { grid-template-columns: repeat(4, 1fr); }

  /* ── Kwiix + tablette CÔTE À CÔTE, en flux ─────────────────────────────────
     La tablette est collée au bord DROIT du contenu (donc alignée sur le CTA de
     la navbar) et le Kwiix occupe la gauche de la colonne. Largeurs reprises de
     la landing officielle : tablette 352px, Kwiix 112-148px. */
  .kv2-hero-visual { flex-direction: row; align-items: center; justify-content: flex-end; gap: var(--kv2-gutter); }
  .kv2-coach-mob { display: none; }
  /* ⚠️ La COLONNE du Kwiix (176px) est plus large que le Kwiix lui-même (148px,
     la taille de la landing officielle, inchangée). Les 28px de plus vont à la
     BULLE : à 131px de large, les répliques tenaient sur 3 lignes et la bulle
     devenait plus haute que la mascotte — or une bulle de dialogue se lit d'un
     coup d'œil. La figure reste donc plafonnée et centrée dans sa colonne. */
  .kv2-coach-desk {
    display: flex; flex-direction: column; align-items: center; gap: 12px;
    width: clamp(132px, 13vw, 176px); min-width: 120px; flex: 0 0 auto;
    align-self: center; pointer-events: none;
  }
  /* La bulle ÉPOUSE son texte (une réplique courte donne une petite bulle, comme
     sur la landing officielle) et peut DÉBORDER dans les gouttières de part et
     d'autre du Kwiix : elle est centrée, donc elle déborde symétriquement.
     ⚠️ C'est ce qui permet de garder les répliques LONGUES du pack Lovable
     (« Chaque quiz est aligné sur le PER et le plan d'études gymnasial… ») sans
     les réécrire. La marge de 18px garantit qu'elle ne touche ni la colonne de
     texte ni la tablette. Ne pas ramener ce plafond à 100 %. */
  .kv2-coach-desk .kv2-bubble-wrap {
    width: max-content;
    max-width: calc(100% + 2 * var(--kv2-gutter) - 18px);
    /* Couloir de hauteur FIXE, bulle ancrée EN BAS : elle pousse vers le HAUT
       quand la réplique s'allonge, et la mascotte en dessous ne bouge pas d'un
       pixel. Sans ça, la colonne grandissait et — `align-self: center` oblige —
       le Kwiix sautait d'une position à l'autre à chaque réplique. */
    min-height: var(--kv2-coach-slot-desk);
    display: flex; align-items: flex-end; justify-content: center;
  }
  .kv2-coach-desk .kv2-bubble { text-align: center; font-size: 13px; padding: 9px 12px; }
  /* Queue de bulle : carré pivoté centré sous la bulle — donc pile au-dessus de
     la tête du Kwiix, les deux étant centrés dans la même colonne flex. */
  .kv2-coach-desk .kv2-bubble::after {
    content: ''; position: absolute; bottom: -5px; left: 50%;
    width: 12px; height: 12px; background: #fff; border-radius: 2px;
    transform: translateX(-50%) rotate(45deg);
  }
  .kv2-coach-desk .kv2-coach-stage { width: 100%; max-width: 148px; margin: 0 auto; }
  .kv2-coach-desk .kv2-coach-fig { width: 100%; }
  .kv2-coach-desk .kv2-coach-fig img { display: block; width: 100%; height: auto; }
  /* ⚠️ `flex: 0 0 <largeur>` — NON compressible. C'est le mécanisme de la landing
     officielle : une piste `fr` ne descend pas sous son min-content, donc la
     colonne visuelle IMPOSE sa largeur (Kwiix + gouttière + tablette) et la
     colonne texte absorbe le reste. Avec un `flex-shrink` de 1, c'est l'inverse
     qui se produisait : la tablette se faisait rogner à ~310px. */
  .kv2-demo { flex: 0 0 328px; max-width: 328px; margin: 0; }

  /* Types de questions : grille + panneau, la bento disparaît */
  .kv2-qt-head .kv2-only-mob { display: none; }
  .kv2-qt-head .kv2-only-desk { display: inline; }
  .kv2-qt-desk {
    margin-top: 48px; display: grid; grid-template-columns: 1.08fr 1fr;
    gap: 24px; align-items: start;
  }
  /* Desktop : les cartes à gauche, l'aperçu à droite, la gamification sous lui. */
  /* ⚠️ `stretch`, plus `start` : les deux colonnes font la MEME hauteur, et le
     panneau d'apercu pousse sa capture EN BAS (`space-between`) — le bas de la
     video s'aligne donc sur le bas de la 3e rangee de cartes. Le `sticky`
     n'avait plus de sens a hauteurs egales. */
  .kv2-qt-body { margin-top: 48px; grid-template-columns: 1.08fr 1fr; gap: 24px; align-items: stretch; }
  .kv2-qt-side { display: flex; flex-direction: column; gap: 14px; }
  .kv2-qt-panel { display: block; }
  .kv2-qt-list { gap: 12px; }
  .kv2-qt-card { padding: 16px 10px 14px; gap: 10px; }
  .kv2-qt-ic { width: 40px; height: 40px; border-radius: 14px; }
  .kv2-qt-ic svg { width: 21px; height: 21px; }
  .kv2-qt-card b { font-size: 0.9375rem; }
  .kv2-qt-card:hover { border-color: rgba(91, 108, 249, 0.45); transform: translateY(-2px); }
  .kv2-qt-card[aria-pressed="true"] {
    border-color: var(--accent); box-shadow: var(--kv2-shadow-pop); transform: translateY(-2px);
  }
  .kv2-qt-card[aria-pressed="true"] .kv2-qt-ic { background: var(--accent); color: #fff; }
  .kv2-qt-bonus { padding: 14px 16px; gap: 14px; }
  .kv2-qt-bonus:hover { border-color: var(--gold-deep); transform: translateY(-2px); }
  .kv2-qt-bonus[aria-pressed="true"] {
    border-color: var(--gold-deep);
    box-shadow: 0 18px 50px -18px rgba(255, 209, 102, 0.6); transform: translateY(-2px);
  }
  .kv2-qt-bonus[aria-pressed="true"] .kv2-qt-bonus-ic { background: var(--gold); color: #7A5200; }
  .kv2-qt-bonus b { font-size: 1rem; }
  .kv2-qt-panel {
    overflow: hidden; border: 1px solid var(--border);
    border-radius: 32px; background: #fff; padding: 24px; box-shadow: var(--kv2-shadow-soft);
    flex: 1; display: flex; flex-direction: column; justify-content: space-between; gap: 16px;
  }
  .kv2-qt-panel-head { display: flex; align-items: flex-start; gap: 14px; }
  .kv2-qt-panel-ic {
    display: grid; place-items: center; width: 46px; height: 46px; flex: none;
    border-radius: 14px; background: var(--kv2-soft); color: var(--accent);
  }
  .kv2-qt-panel-ic svg { width: 24px; height: 24px; }
  .kv2-qt-panel-txt { min-width: 0; }
  .kv2-qt-panel-txt .kv2-eyebrow {
    font-family: 'Plus Jakarta Sans', sans-serif; font-size: 11px; font-weight: 800;
    text-transform: uppercase; letter-spacing: 0.14em; color: var(--text-secondary);
  }
  .kv2-qt-panel-txt h3 {
    margin-top: 3px; font-family: 'Plus Jakarta Sans', sans-serif;
    font-size: 1.125rem; font-weight: 800; letter-spacing: -0.01em;
  }
  /* ⚠️ TAILLE FIXE de la carte aperçu : la description a DEUX lignes réservées
     ET bornées (min-height + line-clamp). Sans ça, passer d'une description
     d'une ligne à deux faisait respirer toute la carte — et la grille de
     gauche avec (les rangées s'alignent sur la hauteur du panneau). */
  .kv2-qt-panel-txt p {
    margin-top: 5px; font-size: 0.9375rem; line-height: 1.5; color: var(--text-secondary);
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
    min-height: calc(2 * 1.5em);
  }
  /* Le rognage vient de `.kv2-vidbox` (posée sur cet élément) : ici, seulement
     ce qui est propre à l'aperçu. */
  .kv2-qt-panel-media { cursor: zoom-in; }
  .kv2-qt-panel-media > img { animation: kv2-pop .35s cubic-bezier(0.34, 1.56, 0.64, 1) both; }
}

/* ─── Kwiix commentateur : à GAUCHE de la tablette seulement s'il y a la place ──
   Le pack basculait dès 768px (`md:block`). Avec notre largeur de contenu
   (`.container`, 1100px), la bulle de 190px pendue à -140px du bord de la
   tablette VIENT MORDRE sur le titre entre 1024 et 1199px (mesuré : 133px de
   chevauchement à 1024). Sous 1200px, le Kwiix reste donc SOUS la tablette —
   la mise en page mobile, qui a de la place. */

/* ─── FAQ : ouverture fluide et repères visuels ───────────────────────────────
   On reste dans le REGISTRE de l'accordéon du projet (carte blanche unique,
   filets de 1px, chevron rotatif — cf. `FaqAccordion` côté app) : ce bloc ne
   redessine rien, il ajoute les repères qui manquaient.
   ⚠️ L'animation d'ouverture est portée par `faq-smooth.js` : un `<details>`
   natif passe de 0 à sa hauteur finale sans état intermédiaire, aucune
   transition CSS ne peut s'y accrocher. Ici, seulement l'habillage.
   ⚠️ Si la v2 est retenue, porter ces repères dans `FaqAccordion` ET dans
   `.faq-item` de `style.css`, pour que les deux registres ne divergent pas. */
.kv2 .faq-item { position: relative; transition: background .18s ease; }
/* Barre d'accent sur la question OUVERTE : on retrouve d'un coup d'œil où on en
   est dans une liste de sept questions. */
.kv2 .faq-item::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--accent); transform: scaleY(0); transform-origin: center;
  transition: transform .22s ease; pointer-events: none;
}
.kv2 .faq-item[open]::before { transform: scaleY(1); }
.kv2 .faq-item[open] { background: rgba(91, 108, 249, 0.035); }
/* Fermeture EN COURS : les repères s'éteignent en même temps que la boîte se
   referme, et non après (cf. `data-closing` dans faq-smooth.js). */
.kv2 .faq-item[data-closing="1"]::before { transform: scaleY(0); }
.kv2 .faq-item[data-closing="1"] { background: transparent; }
.kv2 .faq-item[data-closing="1"] > summary { color: var(--text); }
.kv2 .faq-item[data-closing="1"] .faq-icon { background: var(--kv2-muted); color: var(--text-secondary); transform: none; }
/* `ACCENT_DEEP` et non `ACCENT` : du texte violet en petite taille n'atteint pas
   le contraste AA avec le violet clair (règle du projet, theme.js). */
.kv2 .faq-item[open] > summary { color: #4353E8; }
/* Le chevron gagne une pastille : il devient une cible lisible, et se teinte
   quand la question est ouverte. */
.kv2 .faq-icon {
  display: grid; place-items: center; width: 26px; height: 26px; border-radius: 999px;
  background: var(--kv2-muted); color: var(--text-secondary);
  transition: transform .22s ease, background .18s ease, color .18s ease;
}
.kv2 .faq-item[open] .faq-icon { background: rgba(91, 108, 249, 0.14); color: #4353E8; }
/* Le paragraphe est animé en HAUTEUR : sans `overflow: hidden`, le texte
   déborderait de la boîte pendant le trajet au lieu d'être découvert. */
.kv2 .faq-item p { overflow: hidden; }

/* ─── « Une session, des deux côtés » ─────────────────────────────────────────
   UNE étape à la fois, qui occupe toute la section, et les trois étapes toujours
   visibles dans le sélecteur au-dessus.
   ⚠️ La version précédente empilait les trois étapes et leurs six vidéos : six
   vignettes trop petites pour être lues, et beaucoup de défilement pour un seul
   argument. Ne pas y revenir.
   ⚠️ Le PANNEAU garde une hauteur STABLE d'une étape à l'autre : la zone média a
   un format fixe et la phrase est plafonnée à deux lignes. Sans ça, changer
   d'étape faisait sauter la page sous le doigt. */
.kv2-flow { padding: clamp(56px, 8vw, 104px) 0; background: #fff; }
.kv2-flow-head { max-width: 40rem; margin: 0 auto clamp(24px, 4vw, 40px); text-align: center; }
.kv2-flow-head h2 { margin-top: 12px; font-size: clamp(1.5rem, 4.2vw, 3rem); letter-spacing: -0.02em; }
.kv2-flow-head > p:last-child { margin-top: 14px; color: var(--text-secondary); font-size: clamp(1rem, 2.4vw, 1.125rem); }

/* ── Scrollytelling : rail d'étapes + panneau média COLLANT ──────────────────
   Décision du 01.08 (remplace onglets d'étapes + sélecteur de vue) : le
   défilement pilote l'étape active — rail à gauche, panneau sticky à droite.
   Une étape = UNE composition : vue enseignant en grand (cadre navigateur),
   vue élève incrustée en vignette (cadre tablette) ; cliquer la vignette
   intervertit les deux (data-focus). Sous 900 px : rail masqué, scènes
   empilées, chacune avec son propre en-tête (.kv2-flowsy-scenehead). */
.kv2-flowsy {
  display: grid; grid-template-columns: minmax(280px, 5fr) 7fr;
  gap: clamp(32px, 5vw, 64px); align-items: start;
  margin-top: clamp(10px, 2vw, 24px);
}

/* Rail d'étapes : chaque étape est haute (≈ un demi-écran) pour donner au
   défilement la place de raconter ; l'inactive est éteinte, pas cachée. */
.kv2-flowsy-rail { display: flex; flex-direction: column; }
.kv2-flowsy-step {
  display: flex; flex-direction: column; justify-content: center; gap: 10px;
  min-height: clamp(280px, 46vh, 420px); margin: 0; border: 0; background: none;
  padding: 24px 8px 24px 26px; text-align: left; cursor: pointer;
  border-left: 2px solid var(--border);
  opacity: 0.38; transition: opacity 0.3s ease, border-color 0.3s ease;
}
.kv2-flowsy-step.on { opacity: 1; border-left-color: var(--accent); }
.kv2-flowsy-step:hover { opacity: 0.75; }
.kv2-flowsy-step.on:hover { opacity: 1; }
.kv2-flowsy-step:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; border-radius: 8px; }
.kv2-flowsy-kick {
  display: flex; align-items: center; gap: 10px;
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 11.5px; font-weight: 800;
  text-transform: uppercase; letter-spacing: 0.12em; color: var(--text-secondary);
}
.kv2-flowsy-step.on .kv2-flowsy-kick { color: var(--accent-deep); }
.kv2-flowsy-num {
  display: grid; place-items: center; width: 28px; height: 28px; flex: none;
  border-radius: 999px; background: var(--kv2-muted); color: var(--text-secondary);
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 13.5px; font-weight: 800;
  letter-spacing: 0; transition: background 0.25s ease, color 0.25s ease;
}
.kv2-flowsy-step.on .kv2-flowsy-num,
.kv2-flowsy-scenehead .kv2-flowsy-num { background: var(--accent); color: #fff; }
.kv2-flowsy-step h3 { margin: 0; font-size: clamp(19px, 2vw, 23px); letter-spacing: -0.01em; }
.kv2-flowsy-step p { margin: 0; max-width: 42ch; font-size: 15px; line-height: 1.55; color: var(--text-secondary); }

/* Panneau média : collant, les trois scènes empilées dans la même cellule de
   grille (le conteneur prend la hauteur de la plus haute), seule l'active est
   visible — fondu + léger glissement, du CONTENU (jamais gelé). */
.kv2-flowsy-media { position: sticky; top: clamp(72px, 10vh, 110px); display: grid; }
/* ⚠️ `visibility` EN PLUS de l'opacité : les scènes sont empilées dans la même
   cellule, et un enfant en `pointer-events: auto` (la vue au premier plan d'une
   scène invisible) gagnerait contre le `none` du parent — la vidéo d'une scène
   cachée interceptait les clics de la scène affichée (attrapé au banc).
   `visibility: hidden` se propage, elle ; le délai la fait tomber APRÈS le
   fondu de sortie. */
.kv2-flowsy-scene {
  grid-area: 1 / 1; opacity: 0; transform: translateY(18px);
  visibility: hidden; pointer-events: none;
  transition: opacity 0.4s ease, transform 0.4s ease, visibility 0s linear 0.4s;
}
.kv2-flowsy-scene[data-active="1"] {
  opacity: 1; transform: none; visibility: visible; pointer-events: auto;
  transition-delay: 0s;
}

/* En-tête de scène : MOBILE uniquement (le rail est masqué, chaque scène porte
   alors son numéro, son titre et sa description). */
.kv2-flowsy-scenehead { display: none; align-items: flex-start; gap: 12px; margin-bottom: 12px; }
.kv2-flowsy-scenehead b {
  display: block; font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 16px; font-weight: 800; letter-spacing: -0.01em;
}
.kv2-flowsy-scenehead i { font-style: normal; font-size: 13px; line-height: 1.45; color: var(--text-secondary); }

/* Sélecteur de vue : segmented control SOUS le player (décision du 01.08),
   deux segments à LARGEUR ÉGALE et pastille blanche GLISSANTE (::before piloté
   par data-on) — le fond ne saute plus d'un segment à l'autre, il glisse.
   Une seule vue à l'écran à la fois. */
.kv2-flowsy-switch {
  position: relative; display: grid; grid-template-columns: 1fr 1fr;
  width: min(320px, 100%); margin: 14px auto 0; padding: 4px;
  border-radius: 999px; background: var(--kv2-muted);
  border: 1px solid var(--border);
  box-shadow: inset 0 1px 2px rgba(45, 45, 58, 0.05);
}
.kv2-flowsy-switch::before {
  content: ''; position: absolute; top: 4px; bottom: 4px; left: 4px;
  width: calc(50% - 4px); border-radius: 999px; background: #fff;
  box-shadow: 0 2px 8px rgba(45, 45, 58, 0.16), 0 1px 2px rgba(45, 45, 58, 0.08);
  transition: transform 0.25s ease;
}
.kv2-flowsy-switch[data-on="eleve"]::before { transform: translateX(100%); }
.kv2-flowsy-switch button {
  position: relative; z-index: 1; border: 0; border-radius: 999px;
  padding: 9px 12px; cursor: pointer; white-space: nowrap; background: transparent;
  color: var(--text-secondary);
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 13px; font-weight: 800;
  transition: color 0.2s ease;
}
.kv2-flowsy-switch button:hover { color: var(--text); }
.kv2-flowsy-switch button[aria-selected="true"] { color: var(--accent-deep); }
.kv2-flowsy-switch button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Les deux vues empilées dans la même cellule, FONDU de l'une à l'autre. Les
   deux vidéos tournent en parallèle (paires exportées à la même durée) :
   switcher montre le même instant sous l'autre angle, rien ne redémarre. */
.kv2-flowsy-stage { display: grid; }
.kv2-shot {
  grid-area: 1 / 1; width: 100%;
  overflow: hidden; border-radius: 16px; background: #fff;
  box-shadow: var(--kv2-shadow-soft);
  opacity: 0; transform: translateY(8px) scale(0.985); pointer-events: none;
  transition: opacity 0.35s ease, transform 0.35s ease;
}
.kv2-flowsy-scene[data-focus="prof"] .kv2-shot[data-role="prof"],
.kv2-flowsy-scene[data-focus="eleve"] .kv2-shot[data-role="eleve"] {
  opacity: 1; transform: none; pointer-events: auto;
}
/* Le cadre porte l'ombre et le rayon ; la capture interne est nue. */
.kv2-shot .kv2-flow-media { border-radius: 0; box-shadow: none; }
/* Barre de navigateur : le MÊME chrome pour les deux vues (décision du 01.08 —
   la lunette tablette de la vue élève a été retirée), seule l'URL change
   (teacher.kwiiz.ch / go.kwiiz.ch) + l'étiquette d'étape à droite. */
.kv2-devbar { display: flex; align-items: center; gap: 6px; padding: 9px 12px; background: #fff; border-bottom: 1px solid var(--border); }
.kv2-devbar i { width: 9px; height: 9px; border-radius: 50%; background: #E5E4EF; }
.kv2-devbar span {
  margin-left: 8px; padding: 3px 12px; border-radius: 999px; background: var(--kv2-muted);
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 11px; font-weight: 700; color: var(--text-secondary);
}
.kv2-devbar .kv2-devbar-step {
  margin-left: auto; padding: 0; border-radius: 0; background: none;
  font-size: 10.5px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.08em;
}

/* Bac des barres de progression, sous l'écran : une barre par vidéo branchée,
   taguée par rôle — seule celle de la vue AFFICHÉE se voit. */
.kv2-flowsy-bars { width: 100%; margin-top: 2px; }
.kv2-flowsy-scene[data-focus="prof"] .kv2-flowsy-bars .kv2-seek[data-role="eleve"],
.kv2-flowsy-scene[data-focus="eleve"] .kv2-flowsy-bars .kv2-seek[data-role="prof"] { display: none; }

/* ⚠️ PAS de `kv2-vidbox` ici : ce cadre rogne les bandes parasites des DIX
   anciennes captures (8/10/0/8 px). Les captures de CETTE section sont de la
   nouvelle génération Camtasia, mesurées PROPRES sur les quatre bords
   (flow-1-prof : 0/0/0/0 aux trois instants sondés) — les rogner amputerait de
   la vraie image. Cadre 16:9 natif, la vidéo le remplit exactement. */
.kv2-flow-media {
  position: relative; overflow: hidden; aspect-ratio: 16 / 9;
  border-radius: 16px; box-shadow: var(--kv2-shadow-soft); background: var(--kv2-muted);
}
.kv2-flow-media video { display: block; width: 100%; height: 100%; object-fit: cover; }
/* Recadrage gauche d'une capture imparfaite (`data-cropl`, posé par v2-flow.js) :
   la vidéo est décalée et élargie de la fraction rognée — bande parasite hors
   cadre, étirement horizontal < 1 % invisible. Vaut en page ET en plein écran. */
.kv2-flow-media video.kv2-cropl,
.kv2-zoom-media video.kv2-cropl {
  position: absolute; top: 0; max-width: none; height: 100%;
  width: calc(100% / (1 - var(--cropf)));
  left: calc(-100% * var(--cropf) / (1 - var(--cropf)));
  object-fit: fill;
}
/* Emplacement en attente : on nomme le fichier attendu, comme les cartes de
   types. Pas d'image bouche-trou qui ferait croire à une vraie capture. */
.kv2-flow-media[data-slot]:empty::after {
  content: 'Capture à venir · ' attr(data-slot);
  position: absolute; inset: 0; display: grid; place-items: center; padding: 12px;
  background: var(--kv2-muted); color: var(--text-secondary); text-align: center;
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 13px; font-weight: 700;
}
.kv2-flow-cta { margin-top: clamp(28px, 4vw, 44px); text-align: center; }
.kv2-flow-cta p { margin-top: 12px; font-size: 0.875rem; color: var(--text-secondary); }

/* ── Sous 900 px : le rail disparaît, les scènes s'empilent ────────────────── */
@media (max-width: 899px) {
  .kv2-flowsy { display: block; }
  .kv2-flowsy-rail { display: none; }
  .kv2-flowsy-media { position: static; display: block; }
  .kv2-flowsy-scene { opacity: 1; transform: none; visibility: visible; pointer-events: auto; margin-bottom: 40px; }
  .kv2-flowsy-scene:last-child { margin-bottom: 0; }
  .kv2-flowsy-scenehead { display: flex; }
}

/* ─── « Côté élève » sur le CIEL ÉTOILÉ ───────────────────────────────────────
   Cette section montre ce que voit l'ÉLÈVE : elle prend donc l'univers visuel de
   l'élève, celui de go.kwiiz.ch et du lobby. L'argument se fait alors sans un
   mot, et les captures, qui sont des écrans clairs, ressortent enfin au lieu de
   se noyer dans du blanc.
   ⚠️ Dégradé REPRIS À L'IDENTIQUE de `NIGHT_SKY_GRADIENT`
   (`client/src/components/StarrySky.jsx`) : c'est le même ciel que le produit, pas
   une teinte inventée. Si l'un change, changer l'autre.
   Les étoiles sont en CSS pur (trois couches de `radial-gradient`) et non en DOM :
   le produit les génère en React, ce que la landing ne peut pas faire, et 60
   éléments décoratifs ne valent pas une requête de plus. */
.kv2-qt {
  background: linear-gradient(170deg, hsl(222 47% 11%) 0%, hsl(230 40% 16%) 50%, hsl(222 47% 11%) 100%);
  color: #fff;
}
.kv2-qt::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background-image:
    radial-gradient(1.6px 1.6px at 18% 12%, rgba(255,255,255,.95) 50%, transparent 51%),
    radial-gradient(1.2px 1.2px at 72% 8%,  rgba(255,255,255,.75) 50%, transparent 51%),
    radial-gradient(1.8px 1.8px at 88% 34%, rgba(255,255,255,.9)  50%, transparent 51%),
    radial-gradient(1.1px 1.1px at 34% 46%, rgba(255,255,255,.6)  50%, transparent 51%),
    radial-gradient(1.5px 1.5px at 8%  62%, rgba(255,255,255,.85) 50%, transparent 51%),
    radial-gradient(1.2px 1.2px at 56% 78%, rgba(255,255,255,.7)  50%, transparent 51%),
    radial-gradient(1.7px 1.7px at 92% 88%, rgba(255,255,255,.9)  50%, transparent 51%),
    radial-gradient(1.1px 1.1px at 44% 22%, rgba(255,255,255,.55) 50%, transparent 51%);
  background-repeat: repeat;
  background-size: 380px 300px, 460px 340px, 300px 260px, 520px 380px, 340px 290px, 420px 320px, 360px 280px, 480px 360px;
  animation: kv2-twinkle 5.5s ease-in-out infinite;
}
@keyframes kv2-twinkle { 0%, 100% { opacity: .55; } 50% { opacity: 1; } }
/* Le contenu passe AU-DESSUS du ciel. */
.kv2-qt > .container { position: relative; z-index: 1; }

/* ── Les enfants en version nuit ───────────────────────────────────────────── */
.kv2-qt .kv2-eyebrow { color: rgba(255, 255, 255, 0.66); }
.kv2-qt-head h2 { color: #fff; }
/* `--text-secondary` (#6B6B7E) n'atteint pas le contraste AA sur fond nuit :
   on passe à un blanc atténué, jamais au gris de la version claire. */
.kv2-qt-head p { color: rgba(255, 255, 255, 0.78); }

.kv2-qt .kv2-qt-card,
.kv2-qt .kv2-qt-panel {
  background: rgba(255, 255, 255, 0.07);
  border-color: rgba(255, 255, 255, 0.16);
  backdrop-filter: blur(6px);
}
.kv2-qt .kv2-qt-card b { color: #fff; }
.kv2-qt .kv2-qt-card:hover { border-color: rgba(255, 255, 255, 0.38); background: rgba(255, 255, 255, 0.12); }
.kv2-qt .kv2-qt-card[aria-pressed="true"] {
  border-color: #fff; background: rgba(255, 255, 255, 0.16);
  box-shadow: 0 14px 40px -16px rgba(0, 0, 0, 0.6);
}
.kv2-qt .kv2-qt-ic { background: rgba(255, 255, 255, 0.14); color: #fff; }
.kv2-qt .kv2-qt-card[aria-pressed="true"] .kv2-qt-ic { background: var(--accent); color: #fff; }

/* La carte gamification garde sa teinte OR : c'est sa nature, et l'or sur ciel
   nuit est précisément le registre de la boutique du Kwiix côté élève. */
.kv2-qt .kv2-qt-bonus {
  background: rgba(255, 209, 102, 0.10);
  border-color: rgba(255, 209, 102, 0.42);
}
.kv2-qt .kv2-qt-bonus:hover { border-color: var(--gold); background: rgba(255, 209, 102, 0.16); }
.kv2-qt .kv2-qt-bonus b { color: #fff; }
.kv2-qt .kv2-qt-bonus p { color: rgba(255, 255, 255, 0.76); }
.kv2-qt .kv2-qt-bonus-tag { color: var(--gold); }
.kv2-qt .kv2-qt-bonus-ic { background: rgba(255, 209, 102, 0.20); color: var(--gold); }

.kv2-qt .kv2-qt-panel-head p { color: rgba(255, 255, 255, 0.74); }
.kv2-qt .kv2-qt-panel-txt h3 { color: #fff; }
.kv2-qt .kv2-qt-panel-txt .kv2-eyebrow { color: rgba(255, 255, 255, 0.6); }
.kv2-qt .kv2-qt-panel-ic { background: rgba(255, 255, 255, 0.14); color: #fff; }
/* L'encart « capture à venir » : sur nuit, un gris clair ferait un trou blanc. */
.kv2-qt .kv2-ph { background: rgba(255, 255, 255, 0.06); color: rgba(255, 255, 255, 0.72); }
.kv2-qt .kv2-ph b { color: #fff; }


/* ─── Player des captures de session : barre + fin de lecture ─────────────────
   Barre = MIROIR du SeekBar du produit (client/src/components/MediaPrompt.jsx) :
   zone de saisie 24 px (WCAG 2.5.5), piste visible fine 5 → 7 px au survol ou
   pendant le glissé, remplissage accent, tête ronde 12 → 16 px bordée de blanc.
   Toute évolution du player produit se répercute ici (et inversement). */
.kv2-seek {
  position: relative; height: 24px; margin-top: 8px;
  display: flex; align-items: center; cursor: pointer; touch-action: none;
}
.kv2-seek:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 999px; }
.kv2-seek-track {
  position: relative; width: 100%; height: 5px; border-radius: 999px;
  background: rgba(91, 108, 249, 0.18); transition: height 0.12s ease;
}
.kv2-seek:hover .kv2-seek-track, .kv2-seek.scrub .kv2-seek-track { height: 7px; }
/* ⚠️ AUCUNE transition sur width/left du remplissage et de la tête : la
   position est peinte à 60 fps en requestAnimationFrame côté JS (v2-flow.js).
   Une transition par-dessus ne ferait qu'ajouter du retard — c'est elle,
   combinée au `timeupdate` à ~4 Hz, qui donnait une barre saccadée. */
.kv2-seek-fill {
  position: absolute; left: 0; top: 0; bottom: 0; width: 0;
  background: var(--accent); border-radius: 999px;
}
.kv2-seek-head {
  position: absolute; top: 50%; left: 0; transform: translate(-50%, -50%);
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--accent); border: 2px solid #fff;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
  transition: width 0.12s ease, height 0.12s ease;
}
.kv2-seek:hover .kv2-seek-head, .kv2-seek.scrub .kv2-seek-head {
  width: 16px; height: 16px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
}

/* Pause choisie (voile léger + ▶) et fin de lecture (voile sombre + ↻).
   Un seul bouton central `.kv2-replay`, deux visages : le CSS montre le bon SVG
   selon data-paused / data-ended. Ni la pause ni la fin ne se relancent seules.
   `.kv2-playerframe` est posée par attachPlayer (v2-flow.js) sur le cadre —
   la capture EN PAGE comme la vue PLEIN ÉCRAN : mêmes règles partout. */
.kv2-playerframe { position: relative; overflow: hidden; }
.kv2-playerframe::before {
  content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: rgba(15, 17, 32, 0.5); opacity: 0; transition: opacity 0.25s ease;
}
.kv2-playerframe[data-paused]::before { opacity: 0.5; }
.kv2-playerframe[data-ended]::before { opacity: 1; }
.kv2-replay {
  position: absolute; z-index: 2; top: 50%; left: 50%;
  transform: translate(-50%, -50%) scale(0.8);
  display: grid; place-items: center; width: 56px; height: 56px;
  border: 0; border-radius: 999px; cursor: pointer;
  background: #fff; color: var(--accent-deep);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
  opacity: 0; pointer-events: none;
  transition: opacity 0.25s ease, transform 0.25s ease;
}
.kv2-replay svg { width: 26px; height: 26px; display: none; }
.kv2-playerframe[data-paused] .kv2-ic-play { display: block; }
.kv2-playerframe[data-ended] .kv2-ic-play { display: none; }
.kv2-playerframe[data-ended] .kv2-ic-replay { display: block; }
.kv2-playerframe[data-paused] .kv2-replay,
.kv2-playerframe[data-ended] .kv2-replay { opacity: 1; pointer-events: auto; transform: translate(-50%, -50%) scale(1); }
.kv2-replay:hover { transform: translate(-50%, -50%) scale(1.08); }
.kv2-replay:focus-visible { outline: 3px solid #fff; outline-offset: 3px; }

/* ── Carte de fin (EN PAGE : frames avec kv2-has-endcard) ────────────────────
   À la fin, la question du visiteur est « et ensuite ? » : la carte y répond —
   « Étape suivante » en principal (défilement doux AU CLIC, jamais d'auto-scroll)
   + « Revoir » discret. Dernière étape : le CTA d'inscription. Elle REMPLACE le
   ↻ central ; l'état pause (▶) reste inchangé. */
.kv2-has-endcard[data-ended] .kv2-replay { opacity: 0; pointer-events: none; }
.kv2-endcard {
  position: absolute; inset: 0; z-index: 2; display: grid; place-items: center;
  opacity: 0; pointer-events: none; transition: opacity 0.25s ease;
}
.kv2-playerframe[data-ended] .kv2-endcard { opacity: 1; pointer-events: auto; }
.kv2-endcard > div { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.kv2-endcard-next {
  display: inline-flex; align-items: center; gap: 8px;
  border: 0; border-radius: 999px; padding: 12px 24px; cursor: pointer;
  background: #fff; color: var(--accent-deep); text-decoration: none;
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 15px; font-weight: 800;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
  transition: transform 0.15s ease;
}
.kv2-endcard-next svg { width: 17px; height: 17px; }
.kv2-endcard-next:hover { transform: scale(1.05); }
.kv2-endcard-next:focus-visible { outline: 3px solid #fff; outline-offset: 3px; }
/* Dernière étape : le CTA d'inscription, en vert action de la landing. */
.kv2-endcard-next.is-go { background: var(--accent2); color: #fff; }
.kv2-endcard-replay {
  display: inline-flex; align-items: center; gap: 6px;
  border: 0; background: none; cursor: pointer; padding: 4px 8px;
  color: rgba(255, 255, 255, 0.85);
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 13px; font-weight: 700;
  transition: color 0.15s ease;
}
.kv2-endcard-replay svg { width: 14px; height: 14px; }
.kv2-endcard-replay:hover { color: #fff; }
.kv2-endcard-replay:focus-visible { outline: 2px solid #fff; outline-offset: 2px; border-radius: 6px; }

/* Plein écran : bouton de coin dédié, en HAUT à droite (le bas accueille la
   barre de progression ; le clic sur la capture fait pause). */
.kv2-expand {
  position: absolute; z-index: 2; right: 10px; top: 10px;
  display: grid; place-items: center; width: 34px; height: 34px;
  border: 0; border-radius: 10px; cursor: pointer;
  background: rgba(15, 17, 32, 0.55); color: #fff; opacity: 0.85;
  transition: opacity 0.15s ease, transform 0.15s ease, background 0.15s ease;
}
.kv2-expand svg { width: 18px; height: 18px; }
.kv2-expand:hover { opacity: 1; background: rgba(15, 17, 32, 0.75); transform: scale(1.06); }
.kv2-expand:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* Player en PLEIN ÉCRAN (`is-player`, posé par v2-flow.js) : la barre se pose
   PAR-DESSUS la vidéo, en bas — piste blanchie pour rester lisible sur l'image. */
.kv2-zoom-media.is-player { cursor: pointer; }
.kv2-zoom-media.is-player .kv2-seek {
  position: absolute; left: 14px; right: 14px; bottom: 4px; z-index: 3; margin-top: 0;
}
.kv2-zoom-media.is-player .kv2-seek-track { background: rgba(255, 255, 255, 0.4); }

/* ═══════════════════ POLITIQUE DE MOUVEMENT — SOURCE UNIQUE ═════════════════
   ⚠️ `prefers-reduced-motion` ne gèle PLUS tout. Sur Windows, ce signal vient
   souvent d'un réglage d'usine ou d'un mode économie, pas d'un choix : une page
   entièrement figée paraissait EN PANNE (constaté sur machine réelle :
   compteurs morts, carrousel bloqué, vidéos muettes). La règle, décidée UNE
   fois ici et nulle part ailleurs :
   • CONTENU et FONCTIONNEL (compteurs, glissades d'écrans et de cartes,
     dépliage de la FAQ, apparition de la flèche, entrée d'un panneau) :
     TOUJOURS animés, sur toutes les machines.
   • ORNEMENTS (confettis, étincelles, flottement du Kwiix et son ombre, pop de
     bulle — déjà gérés par le bloc `no-preference` plus haut — balancement de
     la flèche, scintillement du ciel, rebond des étoiles) : coupés ci-dessous.
   • VIDÉOS : lecture sur DEMANDE toujours honorée, lecture automatique coupée
     (règle « explicit » dans v2-qtypes.js / v2-flow.js).
   Côté JS, SEULS les ornements consultent encore prefers-reduced-motion
   (confettis, étincelles de v2-demo.js) ; tout le reste ne le lit plus.
   ➤ Ajouter un ornement = l'ajouter ICI. Ne jamais réintroduire un gel `.kv2 *`
   à exceptions : c'est lui qui a produit trois bugs « en panne » de suite.
   ⚠️ CE BLOC RESTE EN FIN DE FICHIER : une politique doit avoir le dernier mot
   dans la cascade — posée plus haut, la règle du ciel étoilé (déclarée après
   elle) la battait déjà à l'ordre d'apparition. */
@media (prefers-reduced-motion: reduce) {
  .kv2-confetti, .kv2-sparkles { display: none; }
  .kv2-qt::before { animation: none; opacity: .8; }   /* scintillement du ciel */
  .kv2-arrow { animation: none; }                      /* balancement de la flèche */
  .kv2-star.on { animation-name: kv2-star-fade; }      /* pop → fondu, cascade gardée */
}

/* Capture de la section « des deux côtés » : agrandissable au clic dès qu'elle a
   sa vidéo. En plein écran, cadre 16:9 natif SANS le rognage des anciennes
   captures (fichiers mesurés propres — cf. .kv2-flow-media). */
/* Le clic sur la capture fait PAUSE (player), plus zoom : curseur standard. */
.kv2-flow-media[data-video] { cursor: pointer; }
.kv2-zoom-media.is-video.is-clean { aspect-ratio: 16 / 9; }
.kv2-zoom-media.is-video.is-clean video { display: block; width: 100%; height: 100%; object-fit: cover; }

/* ─── Carte tarifaire « Gratuit » : puces à deux lignes ────────────────────────
   `.lp-free-card-list li span` (style.css) est un flex COLONNE : chacun de ses
   enfants devient une RANGÉE. Une première ligne qui mêle du gras et du texte
   normal — « <strong>309 Kwiiz libres</strong>, lançables en classe » — s'y
   serait donc cassée en deux lignes empilées (le défaut déjà rencontré sur la
   puce des sessions). Ce conteneur la rassemble en une rangée unique.
   `<b>` et non `<span>`, car le sélecteur ci-dessus reprendrait un span imbriqué. */
.kv2 .lp-free-line { display: block; font-weight: 400; }
.kv2 .lp-free-line strong { font-weight: 700; }
/* ⚠️ Le sélecteur de style.css n'est pas limité aux enfants DIRECTS : il attrape
   aussi le <span data-kwiiz> qui porte le compteur, au fond de la puce. Sans
   cette remise à `inline`, le nombre passait à la ligne tout seul — « 309 » puis
   « Kwiiz libres, lançables en classe ». Vérifié dans le navigateur. */
.kv2 .lp-free-card-list li span span { display: inline; }

/* ─── MIGRATION « Importer mes quiz » ─────────────────────────────────────────
   Bande claire de transition entre la section « types de questions » (fond
   indigo profond) et les tarifs (dégradé lavande) : le bleu très clair sépare
   les deux sans introduire une 3ᵉ ambiance. Contrairement à `index.html`, qui
   porte ses styles en inline pour survivre à l'heure de cache de style.css,
   la v2 a sa feuille propre versionnée (`?v=`) — pas besoin de bricoler. */
.kv2-import {
  padding: 72px 0;
  background: #F0F9FF;
  border-top: 1px solid #E0F2FE;
  border-bottom: 1px solid #E0F2FE;
}
.kv2-import-inner { max-width: 840px; text-align: center; }
.kv2-import h2 { margin: 0 0 14px; }
.kv2-import h2 em { font-style: normal; color: #0284C7; }
.kv2-import-lead {
  max-width: 620px; margin: 0 auto 26px;
  color: var(--text-secondary); font-size: 16.5px; line-height: 1.65;
}
.kv2-import-actions {
  display: flex; gap: 14px; justify-content: center; align-items: center; flex-wrap: wrap;
}
.kv2-import-link { font-weight: 700; color: var(--accent-deep, #4353E8); font-size: 15px; }
@media (min-width: 768px) { .kv2-import { padding: 96px 0; } }

/* ─── « Nouveautés de la bibliothèque » ───────────────────────────────────────
   Rail horizontal à accroche (scroll-snap) plutôt qu'un carrousel scripté : la
   fraîcheur du catalogue se PARCOURT, elle ne se feuillette pas une carte à la
   fois. Au doigt c'est le geste naturel, à la souris la barre reste visible, et
   il n'y a aucun état à piloter en JS. */
.kv2-fresh { padding: 64px 0; background: #fff; }
.kv2-fresh[hidden] { display: none; }
.kv2-fresh-head { text-align: center; max-width: 42rem; margin: 0 auto 28px; }
.kv2-fresh-head h2 { margin: 0 0 10px; }
.kv2-fresh-head p { margin: 0; color: var(--text-secondary); }

/* Débord volontaire jusqu'aux bords de l'écran : une carte coupée à droite dit
   « ça continue » mieux qu'une flèche. Le padding réaligne la 1ʳᵉ carte sur la
   colonne de contenu. */
.kv2-fresh-rail {
  display: flex; gap: 16px;
  overflow-x: auto; scroll-snap-type: x mandatory;
  padding: 4px 24px 18px; margin: 0 -24px;
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
}
.kv2-fresh-card { flex: 0 0 232px; scroll-snap-align: start; }
.kv2-fresh-link {
  display: flex; flex-direction: column; height: 100%;
  border: 1px solid var(--border); border-radius: 16px; overflow: hidden;
  background: #fff; color: inherit; text-decoration: none;
  transition: border-color .2s ease, box-shadow .2s ease, transform .2s ease;
}
.kv2-fresh-link:hover, .kv2-fresh-link:focus-visible {
  border-color: var(--accent);
  box-shadow: 0 8px 22px rgba(91, 108, 249, .14);
  transform: translateY(-2px);
}
.kv2-fresh-cover {
  position: relative; display: block; aspect-ratio: 16 / 9;
  background: var(--surface, #F3F4F6);
}
.kv2-fresh-img { width: 100%; height: 100%; object-fit: cover; display: block; }
.kv2-fresh-ph {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-family: 'Plus Jakarta Sans', sans-serif; font-weight: 800; font-size: 26px;
  letter-spacing: .04em;
}
.kv2-fresh-deg {
  position: absolute; right: 8px; bottom: 8px;
  background: rgba(17, 17, 27, .72); color: #fff;
  font-size: 11px; font-weight: 700; padding: 3px 8px; border-radius: 999px;
}
.kv2-fresh-body { display: flex; flex-direction: column; gap: 6px; padding: 12px 13px 14px; }
.kv2-fresh-disc {
  align-self: flex-start; font-size: 11px; font-weight: 700;
  padding: 3px 8px; border-radius: 999px;
}
.kv2-fresh-title {
  font-family: 'Plus Jakarta Sans', sans-serif; font-weight: 700; font-size: 14.5px;
  line-height: 1.3; color: var(--text);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
/* ⚠️ La date est le CŒUR de la section : sans elle, ce n'est plus une preuve
   d'activité, juste une rangée de Kwiiz. Ne pas la masquer pour gagner de la
   place — retirer plutôt autre chose. */
.kv2-fresh-date { margin-top: auto; font-size: 12px; color: var(--text-secondary); }

@media (min-width: 768px) {
  .kv2-fresh { padding: 96px 0; }
  .kv2-fresh-card { flex-basis: 258px; }
}

/* ── Écran QUESTION — remise en ordre ────────────────────────────────────────
   Les lignes s'étirent pour remplir la scène (`flex: 1` + `grid` à parts
   égales) : la tablette a une hauteur FIXE, une liste courte y laisserait un
   grand vide et une liste longue déborderait. */
.kv2-play-order .kv2-qprompt { font-size: 12px; font-weight: 700; }
.kv2-order-list {
  flex: 1; display: grid; gap: 6px; align-content: stretch;
  margin: 8px 0 0; padding: 0; list-style: none;
}
.kv2-order-row {
  display: flex; align-items: center; gap: 7px;
  padding: 6px 8px; border: 1.5px solid var(--border); border-radius: 14px;
  background: #fff; cursor: grab;
  /* ⚠️ Sans `touch-action: none`, le doigt qui commence un glisser fait
     DÉFILER la page : les pointermove ne nous parviennent plus et la ligne
     reste collée. C'est ce qui rend le geste utilisable au doigt. */
  touch-action: none;
  -webkit-user-select: none; user-select: none;
  transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.kv2-order-row:hover { border-color: var(--accent); }
.kv2-order-row[data-drag] {
  cursor: grabbing; border-color: var(--accent);
  box-shadow: 0 10px 22px rgba(91, 108, 249, .22);
  transform: scale(1.02);
}
.kv2-order-grip { display: flex; color: #C3C6D4; flex-shrink: 0; }
.kv2-order-num {
  flex-shrink: 0; width: 17px; height: 17px; border-radius: 999px;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent); color: #fff;
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 10px; font-weight: 800;
}
.kv2-order-label {
  flex: 1; min-width: 0; font-size: 11.5px; font-weight: 600; line-height: 1.25;
  color: var(--text); hyphens: auto;
}
.kv2-order-moves { display: flex; flex-direction: column; gap: 2px; flex-shrink: 0; }
.kv2-order-moves button {
  display: flex; align-items: center; justify-content: center;
  width: 20px; height: 15px; padding: 0;
  border: 1px solid var(--border); border-radius: 5px;
  background: #fff; color: var(--text-secondary); cursor: pointer;
}
.kv2-order-moves button:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.kv2-order-moves button:disabled { opacity: .32; cursor: default; }
.kv2-order-go {
  margin-top: 8px; padding: 9px 14px; border: none; border-radius: 999px;
  background: var(--accent2, #00B37D); color: #fff; cursor: pointer;
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 13px; font-weight: 700;
}
.kv2-order-go:hover { filter: brightness(1.08); }

/* ── Écran CORRIGÉ — remise en ordre ─────────────────────────────────────── */
.kv2-vorder { display: grid; gap: 5px; margin: 0; padding: 0; list-style: none; }
.kv2-vorder-row {
  display: flex; align-items: center; gap: 7px;
  padding: 6px 8px; border-radius: 12px; border: 1.5px solid transparent;
}
.kv2-vorder-row.ok { background: rgba(16, 185, 129, .10); border-color: rgba(16, 185, 129, .38); }
.kv2-vorder-row.ko { background: rgba(244, 63, 94, .08); border-color: rgba(244, 63, 94, .30); }
.kv2-vorder-num {
  flex-shrink: 0; width: 17px; height: 17px; border-radius: 999px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(17, 17, 27, .10); color: var(--text);
  font-family: 'Plus Jakarta Sans', sans-serif; font-size: 10px; font-weight: 800;
}
.kv2-vorder-label { flex: 1; min-width: 0; font-size: 11px; font-weight: 600; line-height: 1.25; }
.kv2-vorder-mark { display: flex; flex-shrink: 0; }
.kv2-vorder-mark.ok { color: #10B981; }
.kv2-vorder-mark.ko { color: #F43F5E; }
.kv2-vorder-was { flex-shrink: 0; font-size: 9.5px; font-weight: 700; color: #F43F5E; }

/* ─── Démo jouable montée dans le hero de la page Parents ────────────────────
   ⚠️ `parents.html` réutilise la coquille de la démo (mêmes ids, même moteur)
   mais DANS SON PROPRE hero (`.lp-hero.kv2`), qui n'a pas la grille
   `.kv2-hero-grid`. Or c'est elle qui déclare `--kv2-gutter`, dont dépendent la
   gouttière du coach ET la largeur max de sa bulle
   (`max-width: calc(100% + 2 * var(--kv2-gutter) - 18px)`). Variable absente =
   `calc()` invalide = bulle sans largeur maximale : elle passait DERRIÈRE la
   tablette et son texte était coupé. On redéclare donc la variable ici.
   La colonne visuelle est aussi élargie : coach (148) + gouttière + tablette
   (352) ne tenait pas dans les 504 px que lui laissait `.lp-hero-inner`. */
.lp-hero.kv2 { --kv2-gutter: clamp(18px, 2vw, 32px); }
@media (min-width: 1024px) {
  .lp-hero.kv2 .lp-hero-inner { grid-template-columns: minmax(0, 1fr) minmax(0, 580px); }
}
