/* ==========================================================================
   L'Anglais en 24 h — Feuille de style
   Direction : « Oxford académique »
   Papier, encre, filets, petites capitales. Typographie de dictionnaire.
   ========================================================================== */

/* ---------- 1. Variables & thème ---------- */
:root{
  /* Fonds — base froide neutre */
  --bg1:#FAFAFA;
  --bg2:#F4F5F9;
  --bg3:#F7F4FC;
  --bg4:#F1F7F9;
  --paper:#FFFFFF;
  --paper-2:#F4F4F5;

  --surface:#FFFFFF;
  --surface-2:#F4F4F5;
  --stroke:rgba(0,0,0,.08);
  --stroke-2:rgba(0,0,0,.05);
  --rule-strong:rgba(0,0,0,.22);

  /* Texte */
  --ink:#18181B;
  --ink-2:#52525B;
  --ink-3:#A1A1AA;

  /* Accents — noms conservés pour compatibilité avec les styles en ligne du JS */
  --p:#6366F1;      /* indigo — primaire */
  --p-2:#4F46E5;
  --b:#06B6D4;      /* cyan */
  --a:#8B5CF6;      /* violet */
  --y:#FBBF24;      /* ambre clair */
  --o:#F59E0B;      /* ambre */
  --r:#F43F5E;      /* rose — erreur */
  --g:#10B981;      /* emeraude — succes */
  --ok:#10B981;
  --ko:#F43F5E;
  /* Accent lexical : une teinte unique dans les deux thèmes. #A64DFF garde
     pratiquement le même contraste sur le papier clair (4.10:1) et sombre
     (4.10:1), contrairement au jaune précédent qui disparaissait sur blanc. */
  --word-stress:#A64DFF;

  /* Accents de chapitre — 6 teintes en rotation + 2 complements */
  --acc-1:#6366F1; --acc-2:#06B6D4; --acc-3:#10B981; --acc-4:#F43F5E;

  /* Verrouillage — moutarde, en deux nuances.
     #F5E027 seul sur blanc ne donne que 1.35:1 : invisible, meme pour un
     pictogramme (seuil 3.0). On l'emploie donc en REMPLISSAGE, la forme etant
     definie par un contour fonce qui, lui, a le contraste :
       --lock-ic  #8C6A00 sur blanc   -> 5.03:1  (contour + texte)   OK
       --lock-fill #F5E027 sur #8C6A00 -> 3.73:1 (serrure lisible)   OK
     Volontairement distinct de --r (#F43F5E), qui reste la couleur d'erreur. */
  --lock-fill:#F5E027;   /* corps du cadenas — jaune moutarde vif */
  --lock-ic:#8C6A00;     /* contour et serrure — c'est LUI qui porte le contraste */
  --lock-tx:#8C6A00;
  --acc-5:#F59E0B; --acc-6:#8B5CF6; --acc-7:#0EA5E9; --acc-8:#EC4899;

  /* Mecanisme de teinte unique aux deux themes :
     fond teinte = accent melange a --tint-base a hauteur de (100% - --tint) */
  --tint:95%;
  --tint-base:#FFFFFF;
  --on-accent:#FFFFFF;   /* texte sur aplat d'accent */

  /* Profondeur */
  --shadow: 0 1px 2px rgba(0,0,0,.04);
  --shadow-sm: 0 1px 2px rgba(0,0,0,.04);
  --elev-in: none;

  /* Halo de survol — parametres valides le 27/07 : 13 / 36 / -23 / 54 % */
  --glow-y:13px; --glow-blur:36px; --glow-spread:-23px; --glow-a:54%;
  --shadow-lift:
    0 3px 6px rgba(0,0,0,.03),
    0 var(--glow-y) var(--glow-blur) var(--glow-spread)
      color-mix(in oklab, var(--c,var(--p)) var(--glow-a), transparent);

  --radius:12px; --radius-sm:8px;
  --blur: saturate(150%) blur(12px);

  --font: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  /* Police d'affichage — Nunito depuis le 06/08/2026, auparavant Bricolage
     Grotesque. Choisie pour être ronde ET lisible aux DEUX extrêmes : --font-d
     sert sur 20 règles, de .6rem (libellés de badge) à 3.5rem (titre du hero).
     C'est ce critère qui a écarté Poppins et Outfit, bonnes en grand titre et
     fragiles en petit corps.
     Conséquence à connaître : Bricolage Grotesque avait un axe optique (opsz)
     qui resserrait les titres en grand corps. Nunito n'en a pas — les dix
     déclarations font-variation-settings ont été retirées, et l'interlettrage
     négatif des titres a été réduit, celui d'avant ayant été réglé pour une
     grotesque étroite. Voir PROJET.md. */
  --font-d: 'Nunito', 'Inter', system-ui, sans-serif;
  --font-ui: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-m: ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, monospace;

  --t: .34s cubic-bezier(.22,1,.36,1);
  --t-slow: .62s cubic-bezier(.22,1,.36,1);
  --spring: cubic-bezier(.34,1.4,.5,1);

  /* Hauteur de la barre d'onglets mobile — 0 sur grand ecran */
  --tabbar:0px;
}

/* ---- Mode sombre — chaque valeur mesuree en ratio WCAG, aucune inversion ---- */
html[data-theme="dark"]{
  --bg1:#0E0F14;
  --bg2:#14161F;
  --bg3:#181528;
  --bg4:#0F1A20;
  /* Carte remontee de #171922 a #1A1D29 : a 1.09:1 de separation avec le
     fond, les cartes ne se detachaient pas — d'ou l'impression de platitude. */
  --paper:#1A1D29;
  --paper-2:#242838;
  --surface:#1A1D29;
  --surface-2:#242838;
  --stroke:rgba(255,255,255,.10);   /* 10 % : un filet blanc lit moins qu'un filet noir */
  --stroke-2:rgba(255,255,255,.06);
  --rule-strong:rgba(255,255,255,.26);

  --ink:#E9EAF0;    /* 14.59:1 */
  --ink-2:#A2A8B8;  /*  7.37:1 */
  --ink-3:#828899;  /*  4.95:1 — remonte depuis #6E7488 (3.77:1, insuffisant a 9,5 px) */

  /* accents eclaircis : a teinte egale l'indigo tombait a 3.92:1 */
  --p:#93A0FA; --p-2:#B0B9FD;   /* eclairci depuis #818CF8 : c'etait le seul
                                   accent qui empechait de monter la teinte */
  --b:#22D3EE;
  --a:#A78BFA;
  --y:#FCD34D;
  --o:#FBBF24;
  --r:#FB7185;
  --g:#34D399;
  --ok:#34D399;
  --ko:#FB7185;

  --acc-1:#93A0FA; --acc-2:#22D3EE; --acc-3:#34D399; --acc-4:#FB7185;

  /* En sombre le rapport s'inverse : corps profond, trait vif.
       --lock-ic #F5E027 sur la carte -> 12.44:1  AAA
       #F5E027 sur --lock-fill #5A4300 ->  6.96:1  serrure tres lisible
       --lock-tx #E3B341 sur la carte  ->  8.62:1  AAA */
  --lock-fill:#5A4300;   /* rapport inverse en sombre : corps profond, trait vif */
  --lock-ic:#F5E027;
  --lock-tx:#E3B341;
  --acc-5:#FBBF24; --acc-6:#A78BFA; --acc-7:#38BDF8; --acc-8:#F472B6;

  --tint:82%;              /* 18 % d'accent : la teinte a 14 % etait a peine
                              perceptible sur fond sombre */
  --tint-base:#1A1D29;
  --on-accent:#0E0F14;     /* blanc sur indigo clair = 2.98:1 -> echec. Texte sombre = 6.42:1 */

  /* sur fond sombre une ombre noire ne se voit pas :
     la profondeur vient d'un liseré lumineux en haut */
  --shadow: 0 2px 10px rgba(0,0,0,.55);
  --shadow-sm: 0 1px 3px rgba(0,0,0,.5);
  --elev-in: inset 0 1px 0 rgba(255,255,255,.055);
  --glow-a:62%;
}

/* ---------- 2. Base ---------- */
*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}

body{
  margin:0;
  font-family:var(--font);
  font-size:17px;
  font-optical-sizing:auto;
  color:var(--ink);
  background:var(--bg1);
  min-height:100vh;
  overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  text-rendering:optimizeLegibility;
  font-kerning:normal;
  font-variant-ligatures:common-ligatures contextual;
  hanging-punctuation:first last;
}

::selection{background:rgba(168,132,44,.28);color:var(--ink)}
html[data-theme="dark"] ::selection{background:rgba(210,177,94,.3)}

:focus-visible{outline:2px solid var(--p);outline-offset:3px;border-radius:6px}

/* Ascenseurs discrets */
*{scrollbar-width:thin;scrollbar-color:var(--stroke) transparent}
*::-webkit-scrollbar{width:9px;height:9px}
*::-webkit-scrollbar-thumb{background:var(--stroke);border-radius:99px;border:2px solid transparent;background-clip:content-box}
*::-webkit-scrollbar-thumb:hover{background:var(--rule-strong);background-clip:content-box}
*::-webkit-scrollbar-track{background:transparent}

/* Chiffres : elzéviriens dans le corps de texte, tabulaires dans les données */
p, li, .goals, .story-line .fr, .fld-help, .spk-fr{font-variant-numeric:oldstyle-nums}
.mini b, .stat .k, .timer, .ring .val, .pct, .score-pill, .res-count,
.gt td, .irr-table td, .diag, .stor-line{font-variant-numeric:tabular-nums lining-nums}

/* ---------- 3. Fond : lumieres froides + halo conique ----------
   Recalcule pour la base #FAFAFA. Ce n'est pas l'inversion de l'ancien
   grain sepia : le grain multiply et le vignettage brun ne fonctionnent
   pas sur un fond neutre froid, ils salissent. */
#bg{
  position:fixed;inset:0;z-index:-3;overflow:hidden;
  background:
    radial-gradient(1200px 620px at 88% -12%, color-mix(in oklab, var(--a) 9%, transparent), transparent 62%),
    radial-gradient(1000px 560px at 6% 108%, color-mix(in oklab, var(--b) 8%, transparent), transparent 62%),
    var(--bg1);
}
html[data-theme="dark"] #bg{
  background:
    radial-gradient(1200px 620px at 88% -12%, color-mix(in oklab, var(--a) 26%, transparent), transparent 64%),
    radial-gradient(1000px 560px at 6% 108%, color-mix(in oklab, var(--b) 20%, transparent), transparent 64%),
    radial-gradient(900px 500px at 50% 42%, color-mix(in oklab, var(--acc-6) 11%, transparent), transparent 70%),
    var(--bg1);
}

/* Halo conique lent — la seule animation permanente de la page.
   ATTENTION PERF : filter blur(90px) sur 420px tourne en continu.
   Desactive sous 700px et en reduced-motion (voir section 30). */
#bg::after{
  content:'';position:absolute;top:-16%;right:-8%;
  width:min(46vw,460px);aspect-ratio:1;border-radius:50%;
  background:conic-gradient(from 0deg,
    var(--acc-1),var(--acc-2),var(--acc-3),var(--acc-5),var(--acc-4),var(--acc-6),var(--acc-1));
  filter:blur(90px);opacity:.10;pointer-events:none;
  animation:spin 30s linear infinite;will-change:transform;
}
html[data-theme="dark"] #bg::after{opacity:.34;mix-blend-mode:screen}
@keyframes spin{to{transform:rotate(360deg)}}

/* Taches diffuses — conservees, retaillees sur la nouvelle palette */
.blob{position:absolute;border-radius:50%;filter:blur(90px);opacity:.09;animation:drift 46s ease-in-out infinite}
html[data-theme="dark"] .blob{opacity:.20}
.blob:nth-child(1){width:520px;height:460px;background:var(--acc-1);top:-160px;left:-120px}
.blob:nth-child(2){width:430px;height:420px;background:var(--acc-2);top:34%;right:-140px;animation-delay:-14s}
.blob:nth-child(3){width:400px;height:380px;background:var(--acc-6);bottom:-160px;left:22%;animation-delay:-27s}
.blob:nth-child(4){width:340px;height:330px;background:var(--acc-3);top:6%;left:48%;animation-delay:-7s;opacity:.06}
@keyframes drift{
  0%,100%{transform:translate(0,0) scale(1)}
  33%{transform:translate(46px,-38px) scale(1.09)}
  66%{transform:translate(-34px,30px) scale(.94)}
}

/* Glyphes phonetiques flottants — construits par oxford.js */
#stars{position:fixed;inset:0;z-index:-2;pointer-events:none}
.spark{
  position:absolute;font-family:var(--font-d);font-weight:500;
  color:var(--p);opacity:0;user-select:none;
  animation:ascend linear infinite;will-change:transform,opacity;
}
@keyframes ascend{
  from{transform:translateY(0) rotate(var(--rot,0deg));opacity:0}
  12%{opacity:.10}
  88%{opacity:.10}
  to{transform:translateY(-112vh) rotate(calc(var(--rot,0deg) + 14deg));opacity:0}
}
html[data-theme="dark"] .spark{color:var(--a);animation-name:ascendDark}
@keyframes ascendDark{
  from{transform:translateY(0) rotate(var(--rot,0deg));opacity:0}
  12%{opacity:.16}
  88%{opacity:.16}
  to{transform:translateY(-112vh) rotate(calc(var(--rot,0deg) + 14deg));opacity:0}
}

/* ---------- 4. Icônes SVG ---------- */
.oxi{
  width:1.05em;height:1.05em;display:inline-block;vertical-align:-.16em;
  flex-shrink:0;stroke-width:1.6;overflow:visible;
}
.oxi--lg{width:1.55em;height:1.55em;vertical-align:-.3em}
#ox-sprite{position:absolute;width:0;height:0;overflow:hidden}

/* ---------- 5. Surfaces ----------
   Le double encadrement « reliure ancienne » (.glass::before) est supprime :
   c'etait la signature Oxford, il jure avec des coins a 12 px. */
.glass{
  position:relative;
  background:var(--surface);
  border:1px solid var(--stroke);
  border-radius:var(--radius);
  box-shadow:var(--elev-in), var(--shadow);
}
.glass::before{display:none}
.glass-2{
  background:var(--surface-2);
  border:1px solid var(--stroke-2);
  border-radius:var(--radius-sm);
}
.hide{display:none !important}

/* ---------- 6. En-tête ---------- */
header{
  position:sticky;top:0;z-index:60;margin:0;padding:.5rem 1.15rem;
  display:flex;align-items:center;gap:1rem;
  background:color-mix(in srgb, var(--bg1) 86%, transparent);
  backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);
  border-bottom:1px solid var(--stroke);
}
/* Double filet sous l'en-tête — signature typographique */
header::after{
  content:'';position:absolute;left:0;right:0;bottom:-4px;height:1px;
  background:var(--stroke-2);
}
/* ---- Le fil : App'Ianaro › English 24 — 04/09/2026 ----
   Deux marques côte à côte, séparées par un chevron. La première ramène au
   portail, la seconde à l'accueil du cours. Elles remplacent le bouton
   « ← Portail », qui vivait à droite entre la navigation et le menu — la
   dernière place où l'on cherche une sortie.

   ⚠️ LE LOGO REÇOIT UN FOND BLANC EN THÈME SOMBRE, ET C'EST VOULU. Il est
   dessiné en marine sur fond clair ; posé tel quel sur le fond sombre du
   cours, on le devine au lieu de le lire. Le recolorer serait pire — une
   marque retouchée n'est plus la marque. On lui donne donc sa lumière, comme
   une étiquette. */
.fil-marque{display:flex;align-items:center;gap:.5rem;min-width:0;flex-shrink:1}
.marque-portail{display:inline-flex;align-items:center;flex:0 0 auto;text-decoration:none;transition:var(--t)}
.marque-portail img{display:block;height:38px;width:auto}
.marque-portail:hover{transform:scale(1.03)}
html[data-theme="dark"] .marque-portail{background:#fff;border-radius:10px;padding:.2rem .35rem}
.fil-sep{flex:0 0 auto;font-size:1.15rem;line-height:1;opacity:.35;user-select:none}

.brand{display:flex;align-items:center;gap:.7rem;cursor:pointer;user-select:none;flex-shrink:0}

/* ---- Le mot-symbole — 11/08/2026 ----
   Il remplace la tuile 🎓, le titre « L'Anglais en 24 h » et son sous-titre.

   LES DEUX DIMENSIONS SONT ÉCRITES, et la largeur n'est pas une valeur
   mesurée à l'œil : le fichier fait 828 × 200, soit 4,142:1, d'où 34 × 141.
   Un `aspect-ratio` aurait évité de les tenir à jour ensemble, mais son
   application à un élément de bloc dépend de la façon dont sa taille
   principale est résolue — ici un objet flex —, et une marque qui se
   redimensionne mal une fois sur dix ne vaut pas l'économie d'une ligne.

   `background-size:contain` est la vraie garantie : quoi qu'on écrive comme
   largeur, l'image garde ses proportions et se contente d'être calée à
   gauche. LE LOGO NE PEUT PAS SE DÉFORMER — au pire il flotte, ce qui se
   corrige, alors qu'un drapeau étiré se remarque et fait amateur. */
.brand .mot{
  margin:0;
  flex:0 0 auto;
  /* ⚠️ RÉDUIT DE 20 % LE 03/09/2026 : 141 × 34 → 113 × 27. Le mot-symbole
     dominait une barre qui porte maintenant un fil d'Ariane devant lui.
     Les trois tailles gardent le rapport 4,142 — sans lui, le logo paraît
     étiré, ce qui se remarque tout de suite. */
  width:113px;height:27px;
  background:url(../icons/english24-mot.webp) left center/contain no-repeat;
  transition:var(--t);
}
/* Version éclaircie pour le thème sombre. Le marine #133960 y tomberait à
   1,4:1 de contraste — un logo qu'on devine au lieu de le lire. Le drapeau,
   lui, n'est pas retouché : un Union Jack recoloré n'en est plus un.
   Un fond CSS et non deux <img> : voir le commentaire d'index.html. */
html[data-theme="dark"] .brand .mot{background-image:url(../icons/english24-mot-sombre.webp)}
.brand:hover .mot{transform:scale(1.03)}
/* `.brand small` — « MÉTHODE INTERACTIVE » — et `.brand .logo` ont disparu du
   HTML le 11/08/2026 avec le mot-symbole. Leurs règles sont retirées ici et
   aux deux points de rupture : une règle qui ne vise plus rien ne fait pas de
   dégât, elle fait perdre dix minutes à celui qui la lira en cherchant
   pourquoi le sous-titre ne s'affiche pas. */

header nav{display:flex;gap:.05rem;flex:1;overflow-x:auto;scrollbar-width:none}
header nav::-webkit-scrollbar{display:none}
.nav-btn{
  position:relative;border:0;background:transparent;color:var(--ink-2);
  font-family:var(--font-ui);font-weight:500;font-size:.795rem;letter-spacing:.005em;
  padding:.48rem .62rem;border-radius:var(--radius-sm);cursor:pointer;white-space:nowrap;
  transition:color var(--t), background var(--t);
  display:flex;align-items:center;gap:.4rem;
}
.nav-btn .oxi{width:15px;height:15px;opacity:.78;transition:var(--t)}
/* Soulignement qui se trace à la plume */
.nav-btn::after{
  content:'';position:absolute;left:.62rem;right:.62rem;bottom:.15rem;height:1.5px;
  background:currentColor;transform:scaleX(0);transform-origin:left;
  transition:transform var(--t);
}
.nav-btn:hover{color:var(--p)}
.nav-btn:hover::after{transform:scaleX(1)}
.nav-btn:hover .oxi{opacity:1}
.nav-btn.on{color:var(--p);font-weight:600}
.nav-btn.on::after{transform:scaleX(1);background:var(--p);height:2px}
.nav-btn.on .oxi{opacity:1}

/* ---- Entrees de navigation masquees ----
   !important est necessaire, pas decoratif : la regle UA `[hidden]{display:none}`
   a une specificite nulle et perdait contre `.nav-btn{display:flex}` et surtout
   contre `#moresheet .tb{display:flex}`, qui porte un id. Sans cela l'attribut
   hidden pose dans index.html n'aurait aucun effet visible. */
.nav-btn[hidden]{display:none !important}

/* ---- Entree en avant-premiere : visible, jamais cliquable ----
   L'etat doit se lire comme une annonce et non comme un onglet disponible.
   Meme intention que .feature-soon sur l'accueil : opacite reduite, aucun
   retour au survol, curseur par defaut. */
.nav-btn-soon{cursor:default;opacity:.55}
.nav-btn-soon:hover{color:var(--ink-2)}
.nav-btn-soon:hover::after{transform:scaleX(0)}
.nav-soon{
  padding:.1rem .34rem;border:1px solid var(--stroke);border-radius:999px;
  font-family:var(--font-ui);font-size:.52rem;font-weight:800;line-height:1.3;
  letter-spacing:.07em;text-transform:uppercase;white-space:nowrap;
}

.hdr-tools{display:flex;gap:.3rem;align-items:center;flex-shrink:0;position:relative;margin-left:auto}
.module-subscription{
  min-height:38px;padding:.42rem .72rem;border:1px solid var(--p);border-radius:12px;
  background:var(--p);color:#fff;font:700 .76rem/1 var(--font);white-space:nowrap;cursor:pointer
}
.module-subscription:hover{filter:brightness(1.06)}
.module-subscription.is-active{border-color:color-mix(in srgb,var(--ok) 55%,var(--stroke));background:color-mix(in srgb,var(--ok) 12%,var(--surface));color:var(--ok);cursor:default}
.icon-btn{
  width:34px;height:34px;border-radius:var(--radius-sm);border:1px solid var(--stroke);
  background:transparent;cursor:pointer;display:grid;place-items:center;
  transition:var(--t);color:var(--ink-2);
}
.icon-btn .oxi{width:16px;height:16px}
.icon-btn:hover{color:var(--p);border-color:var(--p);background:color-mix(in srgb,var(--p) 7%,transparent)}
.icon-btn:active{transform:translateY(1px)}
/* Bouton de compte en panne — 02/08/2026. Il ne disparaît plus quand le pont
   Firebase n'arrive pas : il change d'aspect et devient cliquable pour
   expliquer. Voir auth-ui.js, passerEnPanne(). */
.icon-btn.warn{color:var(--y);border-color:var(--y);background:color-mix(in srgb,var(--y) 10%,transparent)}
.icon-btn.warn:hover{color:var(--y);border-color:var(--y);background:color-mix(in srgb,var(--y) 18%,transparent)}


/* Menu unique de l'en-tête : les outils restent atteignables sans comprimer
   le titre ni multiplier les carrés d'icônes. */
.header-menu-wrap{position:relative}
.header-menu{
  position:absolute;z-index:80;top:calc(100% + .55rem);right:0;
  width:min(284px,calc(100vw - 1.25rem));padding:.55rem;
  box-shadow:0 16px 38px -22px rgba(0,0,0,.42);
}
.header-menu[hidden]{display:none}
.header-menu-group{padding:.28rem 0 .48rem}
.header-menu-group + .header-menu-group{padding-top:.72rem;border-top:1px solid var(--stroke-2)}
.header-menu-label{
  display:block;padding:0 .35rem .35rem;font-family:var(--font-ui);font-size:.61rem;
  font-weight:700;letter-spacing:.15em;text-transform:uppercase;color:var(--ink-3);
}
.menu-action{
  width:100%;min-height:38px;padding:.46rem .55rem;border:1px solid transparent;border-radius:var(--radius-sm);
  background:transparent;color:var(--ink);cursor:pointer;font:600 .82rem var(--font-ui);text-align:left;
  display:flex;align-items:center;gap:.5rem;transition:var(--t);
}
.menu-action[hidden]{display:none}
.menu-action:hover{background:var(--surface-2);border-color:var(--stroke);color:var(--p)}
.menu-action:active{transform:translateY(1px)}
.menu-action.auth-anon{color:var(--ok);background:color-mix(in srgb,var(--ok) 10%,transparent);border-color:color-mix(in srgb,var(--ok) 35%,transparent)}
.menu-action.auth-anon:hover{color:var(--ok);border-color:var(--ok);background:color-mix(in srgb,var(--ok) 17%,transparent)}
.menu-action.warn{color:var(--y);background:color-mix(in srgb,var(--y) 10%,transparent)}
.menu-action.warn:hover{color:var(--y);border-color:var(--y);background:color-mix(in srgb,var(--y) 18%,transparent)}
.header-menu .streak-chip{width:100%;justify-content:space-between;border-radius:var(--radius-sm)}
.header-menu-bottom{margin-top:.15rem;padding-top:.45rem;border-top:1px solid var(--stroke)}
.menu-action.menu-logout{color:var(--ko)}
.menu-action.menu-logout:hover{color:var(--ko);border-color:color-mix(in srgb,var(--ko) 45%,transparent);background:color-mix(in srgb,var(--ko) 8%,transparent)}

.streak-chip{
  display:flex;align-items:center;gap:.32rem;padding:.28rem .6rem;border-radius:var(--radius-sm);
  font-family:var(--font-ui);font-weight:600;font-size:.76rem;font-variant-numeric:tabular-nums;
  color:var(--o);border:1px solid color-mix(in srgb,var(--o) 40%,transparent);
  background:color-mix(in srgb,var(--o) 8%,transparent);
}
.streak-chip .oxi{width:13px;height:13px}
.streak-chip.alight .oxi{animation:flicker 2.6s ease-in-out infinite}
@keyframes flicker{0%,100%{opacity:1;transform:scale(1)}45%{opacity:.68;transform:scale(.93) rotate(-4deg)}}

/* ---------- 7. Mise en page ---------- */
main{max-width:1120px;margin:0 auto;padding:2rem 1.15rem 5rem}
.view{animation:leaf .5s cubic-bezier(.22,1,.36,1)}
@keyframes leaf{
  from{opacity:0;transform:translateY(10px);filter:blur(2px)}
  to{opacity:1;transform:none;filter:none}
}

.page-head{margin:.1rem 0 2rem;position:relative}
/* Titres de vue — « Flashcards », « Les 24 chapitres », « Quiz éclair »…
   Graisse 800 et non 700 alors que « gras » veut dire 700 : Bricolage Grotesque
   à 600 rendait déjà très dense, et Nunito à 700 aurait rendu ces titres PLUS
   LÉGERS qu'avant, à l'inverse de la demande. 800 conserve la présence de la
   capture d'origine. Une seule valeur à changer si c'est trop.
   Interlettrage ramené de -.025em à -.012em : le resserrage d'avant était réglé
   pour une grotesque étroite. Sur une ronde, dont les contreformes sont
   circulaires, -.025em fait se toucher les lettres. */
.page-head h2{
  font-family:var(--font-d);font-weight:800;
  font-size:clamp(1.9rem,4vw,2.85rem);margin:.15rem 0 .5rem;
  letter-spacing:-.012em;line-height:1.1;
  text-wrap:balance;
}
.page-head p{color:var(--ink-2);margin:.2rem 0;max-width:62ch;line-height:1.62;text-wrap:pretty}
/* Titre courant : filet + petites capitales, comme un en-tête de page imprimée */
.eyebrow{
  display:inline-flex;align-items:center;gap:.6rem;
  font-family:var(--font-ui);font-size:.635rem;font-weight:600;
  letter-spacing:.2em;text-transform:uppercase;color:var(--p);
}
.eyebrow::after{
  content:'';display:block;width:clamp(24px,5vw,64px);height:1px;background:currentColor;opacity:.42;
}

/* ---------- 8. Accueil ---------- */
.hero{
  padding:2.6rem 2.4rem;display:grid;grid-template-columns:1.3fr .7fr;
  gap:2.6rem;align-items:center;margin-bottom:2.4rem;
}
/* Titre du hero. Graisse laissée à 700 : seul .page-head h2 devait passer en
   gras. Interlettrage de -.033em à -.018em, même raison que ci-dessus — c'était
   la valeur la plus serrée du projet, la plus hostile à une ronde.
   line-height remonté de 1.02 à 1.08 : Nunito a des jambages plus longs que
   Bricolage, et 1.02 rognait les accents des capitales sur deux lignes. */
.hero h2{
  font-family:var(--font-d);font-weight:700;
  font-size:clamp(2.2rem,5.4vw,3.5rem);line-height:1.08;
  margin:.5rem 0 .8rem;letter-spacing:-.018em;
  text-wrap:balance;
}
/* L'accent : italique oxblood soulignée d'un trait tracé — pas un dégradé arc-en-ciel */
.grad{
  position:relative;font-style:normal;white-space:nowrap;
  background:linear-gradient(100deg,var(--p),var(--a) 45%,var(--r));
  -webkit-background-clip:text;background-clip:text;color:transparent;
}
/* Repli si background-clip:text n'est pas supporte */
@supports not ((-webkit-background-clip:text) or (background-clip:text)){
  .grad{background:none;color:var(--p)}
}
.grad::after{
  content:'';position:absolute;left:0;right:0;bottom:-.06em;height:.05em;
  background:linear-gradient(90deg,var(--p),var(--a));opacity:.5;border-radius:99px;
  transform:scaleX(0);transform-origin:left;
  animation:draw 1.1s .45s cubic-bezier(.22,1,.36,1) forwards;
}
@keyframes draw{to{transform:scaleX(1)}}
/* Bouton interactif « ici » dans le hero */
.grad-btn{
  appearance:none;-webkit-appearance:none;background:none;border:none;padding:0;margin:0;
  font:inherit;cursor:pointer;display:inline-block;vertical-align:baseline;
  transition:transform .2s ease,filter .2s ease;
}
.grad-btn:hover{
  transform:translateY(-2px);
  filter:drop-shadow(0 4px 12px color-mix(in oklab, var(--p) 35%, transparent));
}
.grad-btn:hover::after{
  opacity:.95;height:.07em;
}
.grad-btn:active{transform:translateY(0)}
.grad-btn:focus-visible{
  outline:2px solid var(--p);outline-offset:4px;border-radius:4px;
}
.hero p{color:var(--ink-2);font-size:1.055rem;line-height:1.68;max-width:50ch;text-wrap:pretty}
.hero-cta{display:flex;gap:.55rem;flex-wrap:wrap;margin-top:1.5rem}

/* ══════════════════════════════════════════════════════════════════════════
   ACCUEIL À ACTION UNIQUE — 30/08/2026
   Voir l'en-tête de vHome() dans app.js pour le pourquoi. Ici, le comment :
   un seul bouton assez grand pour ne pas se confondre avec ses voisins, trois
   pastilles d'étape en dessous, et plus rien d'autre au-dessus de la ligne de
   flottaison.
   ══════════════════════════════════════════════════════════════════════════ */

/* Le nom du chapitre visé, sous le titre. Il remplace le paragraphe de
   présentation générique : à la deuxième ouverture, personne ne relit
   « une méthode complète et progressive ». */
.hero-chap{
  font-size:1.02rem;font-weight:600;color:var(--ink);margin:.2rem 0 0;
}
.hero-chap span{font-weight:400;color:var(--ink-2)}

/* ⚠️ CETTE TAILLE EST LE MÉCANISME, PAS UNE COQUETTERIE. L'action primaire
   doit être reconnaissable AVANT d'être lue — c'est ce qui manquait quand
   trois boutons de même taille se disputaient le bandeau. */
.btn-xl{
  font-size:1rem;padding:.85rem 1.6rem;border-radius:var(--radius);
  box-shadow:0 1px 0 rgba(0,0,0,.06),0 10px 26px -16px var(--p);
}

.hero-etapes{display:flex;gap:.5rem;flex-wrap:wrap;margin-top:1.1rem}
.hero-etape{
  display:inline-flex;align-items:center;gap:.45rem;
  border:1px solid var(--stroke);background:var(--surface);
  border-radius:999px;padding:.4rem .8rem;cursor:pointer;
  font-family:var(--font-ui);color:var(--ink-2);
  transition:border-color var(--t),background var(--t),color var(--t);
}
.hero-etape:hover{border-color:var(--rule-strong);background:var(--surface-2)}
.hero-etape b{font-size:.8rem;font-weight:600}
.hero-etape small{font-size:.72rem;color:var(--ink-3);font-variant-numeric:tabular-nums}
.hero-etape.fait{border-color:color-mix(in oklab,var(--ok) 42%,transparent)}
.hero-etape.fait small{color:var(--ok)}

.hero-second{margin-top:1rem}

/* Les neuf cartes de fonctionnalités : un argumentaire, pas un outil. Elles
   descendent sous un dépliant fermé par défaut. Ne pas le rouvrir « pour
   faire riche » — c'est précisément ce qui rendait l'accueil illisible. */
.decouvrir{
  margin-top:1.6rem;border-top:1px solid var(--stroke-2);padding-top:1.2rem;
}
.decouvrir>summary{
  cursor:pointer;list-style:none;
  font-family:var(--font-ui);font-size:.82rem;font-weight:600;
  color:var(--ink-2);padding:.5rem 0;
  display:flex;align-items:center;gap:.5rem;
}
.decouvrir>summary::-webkit-details-marker{display:none}
.decouvrir>summary::before{
  content:'▸';color:var(--ink-3);transition:transform .18s var(--t);
  display:inline-block;
}
.decouvrir[open]>summary::before{transform:rotate(90deg)}
.decouvrir>summary:hover{color:var(--ink)}
.decouvrir .feature-grid{margin-top:.9rem}

@media (max-width:640px){
  .btn-xl{width:100%;justify-content:center}
  .hero-etape{flex:1 1 auto;justify-content:center}
}

/* ---------- 9. Boutons ---------- */
.btn{
  position:relative;border:1px solid var(--p);
  font-family:var(--font-ui);font-weight:600;font-size:.845rem;letter-spacing:.005em;
  padding:.62rem 1.15rem;border-radius:var(--radius-sm);cursor:pointer;
  background:var(--p);color:var(--on-accent);
  transition:background var(--t), color var(--t), border-color var(--t), transform .18s var(--t), box-shadow var(--t);
  display:inline-flex;align-items:center;gap:.45rem;
  box-shadow:0 1px 0 rgba(0,0,0,.06);
}
.btn .oxi{width:15px;height:15px}
.btn:hover{background:var(--p-2);border-color:var(--p-2);box-shadow:0 6px 16px -8px var(--p)}
.btn:active{transform:translateY(1px);box-shadow:none}
.btn:disabled{opacity:.38;cursor:default;box-shadow:none}
.btn.ghost{background:transparent;color:var(--ink);border-color:var(--stroke)}
.btn.ghost:hover{background:transparent;color:var(--p);border-color:var(--p);box-shadow:none}
.btn.sm{padding:.42rem .8rem;font-size:.775rem}
.btn.warm{background:var(--o);border-color:var(--o)}
.btn.warm:hover{background:color-mix(in srgb,var(--o) 85%, #000);border-color:transparent;box-shadow:0 6px 16px -8px var(--o)}
.btn.mint{background:var(--g);border-color:var(--g)}
.btn.mint:hover{background:color-mix(in srgb,var(--g) 85%, #000);border-color:transparent;box-shadow:0 6px 16px -8px var(--g)}

/* Retour à la table des matières : une pièce maîtresse de la navigation,
   donc une vraie action colorée plutôt qu'un petit bouton fantôme. */
.btn.navigation-maitresse{
  min-height:48px;margin:0 0 1rem;padding:.72rem 1.12rem;
  font-size:.95rem;font-weight:700;
  box-shadow:0 10px 24px -15px var(--p);
}
.btn.navigation-maitresse:hover{
  box-shadow:0 12px 28px -15px var(--p);
}

/* En sombre, l'action de lecture doit rester immédiatement repérable au fil
   des cartes. Le jaune est réservé à CE bouton ; le texte presque noir donne
   12,04:1 de contraste sur #FFD000. */
html[data-theme="dark"] .spk .btn.mic{
  background:#FFD000;border-color:#FFD000;color:#18181B;
  box-shadow:0 1px 0 rgba(0,0,0,.28);
}
html[data-theme="dark"] .spk .btn.mic:hover:not(:disabled){
  background:#E6BC00;border-color:#E6BC00;color:#18181B;
  box-shadow:0 6px 16px -8px #FFD000;
}

/* ---------- 10. Anneau de progression ---------- */
.hero-card{padding:1.7rem 1.3rem;text-align:center;position:relative}
.hero-card::after{
  content:'';position:absolute;inset:6px;border:1px solid var(--stroke-2);
  pointer-events:none;border-radius:6px;
}
.ring{position:relative;width:158px;height:158px;margin:0 auto .9rem}
.ring svg{transform:rotate(-90deg);overflow:visible}
.ring .val{
  position:absolute;inset:0;display:grid;place-items:center;
  font-family:var(--font-d);font-size:2.05rem;font-weight:500;
  font-variant-numeric:lining-nums tabular-nums;letter-spacing:-.02em;
}
.mini-stats{display:grid;grid-template-columns:repeat(3,1fr);gap:0;margin-top:.9rem;border-top:1px solid var(--stroke-2);padding-top:.85rem}
.mini{padding:.1rem .3rem;border-right:1px solid var(--stroke-2)}
.mini:last-child{border-right:0}
.mini b{display:block;font-family:var(--font-d);font-size:1.4rem;font-weight:500;line-height:1;font-variant-numeric:lining-nums tabular-nums}
.mini span{
  display:block;margin-top:.28rem;font-family:var(--font-ui);font-size:.585rem;
  color:var(--ink-3);font-weight:600;text-transform:uppercase;letter-spacing:.15em;
}
.hero-card > div[style*="font-weight"]{
  font-family:var(--font-ui) !important;font-size:.63rem;font-weight:600 !important;
  text-transform:uppercase;letter-spacing:.18em;color:var(--ink-3);
}

/* ---------- 11. Grille de fonctionnalités ---------- */
.feature-grid{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(238px,1fr));
  gap:0;margin-bottom:2.4rem;
  border-top:1px solid var(--stroke);border-left:1px solid var(--stroke);
  background:var(--surface);
}
/* Grille de colonnes de journal : filets partagés, pas de cartes flottantes */
.feature{
  padding:1.35rem 1.3rem;border-radius:0;cursor:pointer;
  border:0;border-right:1px solid var(--stroke);border-bottom:1px solid var(--stroke);
  background:transparent;box-shadow:none;
  transition:background var(--t);position:relative;overflow:hidden;
}
.feature::before{display:none}
.feature::after{
  content:'';position:absolute;left:0;top:0;bottom:0;width:2px;background:var(--p);
  transform:scaleY(0);transform-origin:top;transition:transform var(--t);opacity:1;
}
.feature:hover{background:color-mix(in srgb,var(--p) 4%,transparent);transform:none;box-shadow:none}
.feature:hover::after{transform:scaleY(1)}
.feature .ic{
  display:block;margin-bottom:.75rem;color:var(--p);filter:none;
  transition:transform var(--t);
}
.feature .ic .oxi{width:23px;height:23px;stroke-width:1.4}
.feature:hover .ic{transform:translateX(3px)}
/* Titres des cartes de fonctionnalité — « Exercices corrigés », « Répétition
   espacée », « Lecture à voix haute »…
   ATTENTION avant de « corriger » la graisse : 600 EST le semi-gras, et c'était
   déjà la valeur avant le 06/08/2026. Si ces titres paraissaient légers, ce
   n'était pas une erreur de valeur — le 600 de Nunito rend visuellement plus
   léger que celui de Bricolage Grotesque, à chiffre identique. D'où 700 ici :
   c'est la graisse qui DONNE l'effet demandé, pas celle qui porte le nom.
   Revenir à 600 si l'on préfère la fidélité au nom plutôt qu'à l'œil.
   line-height posé explicitement : sans lui, on hérite de `normal`, dont la
   valeur dépend des métriques de la police — donc changeante au prochain
   remplacement de --font-d. Les titres sur deux lignes sont fréquents ici, la
   grille descendant à 200 px de colonne. */
.feature h3{
  font-family:var(--font-d);font-weight:700;margin:0 0 .3rem;font-size:1.15rem;
  letter-spacing:-.012em;line-height:1.3;
}
/* ---- Icône et titre sur la même ligne — 06/08/2026 ----
   Demande explicite : NE RIEN TOUCHER d'autre. Ni police, ni couleur, ni effet,
   ni pastille de fond — contrairement aux cartes de chapitre. Ce bloc ne fait
   que de la disposition. Il ne redéclare aucune couleur, aucune graisse, aucune
   transition ; les règles de survol (.feature:hover .ic, .feature:hover h3) et
   l'atténuation de .feature-soon continuent de s'appliquer telles quelles,
   étant écrites en sélecteurs de descendance.

   Les deux surcharges portent trois classes (spécificité 0,3,0) et non deux :
   `.feature .ic` est déclaré DEUX fois dans ce fichier, dont une en section 32,
   plus bas. À spécificité égale, c'est l'ordre qui tranche, et une règle posée
   ici perdrait contre celle de la section 32. Ne pas « simplifier » en
   `.feature-head .ic`, la marge basse reviendrait sans erreur visible.

   `align-items:center` et non flex-start : dans les colonnes étroites (la
   grille descend à 200 px), « Lecture à voix haute » et « Répétition espacée »
   passent sur deux lignes. Centré, l'icône reste manifestement appariée au
   titre ; alignée en haut, elle a l'air d'avoir glissé.

   `min-width:0` sur le titre : un enfant de flex refuse par défaut de descendre
   sous la largeur de son mot le plus long. Sans cette ligne, un titre long
   élargit la carte au lieu de passer à la ligne, et casse la grille. */
/* Unité visée par un raccourci de parcours de l'accueil — phrase à lire ou
   exercice. Une seule classe pour les deux : le mécanisme est commun
   (ouvrirUniteParcours), la mise en évidence doit l'être aussi.
   Le défilement seul ne suffit pas : arriver au milieu de neuf blocs identiques
   ne dit pas LEQUEL on est venu faire. La surbrillance est retirée au bout de
   2,4 s — un état permanent finirait par être pris pour un statut du bloc.
   `animation` et non `transition` : l'élément reçoit la classe au moment où il
   apparaît, et une transition depuis un état jamais rendu ne se joue pas. */
.unite-visee{animation:uniteVisee 2.4s ease-out}
@keyframes uniteVisee{
  0%,55%{box-shadow:0 0 0 2px var(--p), var(--shadow-lift)}
  100%{box-shadow:0 0 0 0 transparent, var(--shadow)}
}
@media (prefers-reduced-motion:reduce){
  .unite-visee{animation:none;box-shadow:0 0 0 2px var(--p)}
}

.feature-head{
  display:flex;align-items:center;gap:.7rem;
  margin-bottom:.5rem;
}
.feature .feature-head .ic{margin-bottom:0}
.feature .feature-head h3{margin:0;min-width:0}

/* Le libellé « Bientôt disponible » est en position absolue à droite (top:1rem,
   right:1rem). Le titre occupant désormais cette bande, il faut décaler la
   ligne vers le bas — la réserver à droite ne laisserait qu'une quarantaine de
   pixels au titre dans une colonne de 230 px. Seule la carte en avant-première
   est concernée, et elle n'est visible que par un administrateur. */
.feature-soon .feature-head{padding-top:1.35rem}

.feature p{margin:0;font-size:.875rem;color:var(--ink-2);line-height:1.6;text-wrap:pretty}


/* ---------- 12. Liste des chapitres ---------- */
.chap-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(276px,1fr));gap:1.15rem}
.chap{
  padding:1.3rem 1.25rem 1.15rem;border-radius:var(--radius);cursor:pointer;
  transition:transform var(--t), box-shadow var(--t), border-color var(--t);
  position:relative;overflow:hidden;
  border-top:2px solid var(--c,var(--p));
}
.chap::before{inset:4px 4px 4px 4px}
/* Le folio : numéro de chapitre en très grand, en filigrane.
   Réduit de 3.6rem à 2.9rem le 06/08/2026 (−19 %) : le titre est passé sur la
   ligne de l'icône et doit lui laisser la place. C'est un compromis, pas un
   réglage esthétique — chaque dixième de rem rendu ici est de la largeur gagnée
   pour le titre. Voir .chap-head. */
.chap .n{
  position:absolute;top:.35rem;right:.85rem;
  font-family:var(--font-d);font-size:2.9rem;font-weight:500;line-height:1;
  color:var(--c,var(--p));opacity:.10;
  font-variant-numeric:lining-nums;letter-spacing:-.05em;
  transition:opacity var(--t), transform var(--t);
}
.chap:hover{transform:translateY(-3px);box-shadow:var(--shadow-lift)}
.chap:hover .n{opacity:.17;transform:translateY(-2px)}
.chap .ic{color:var(--c,var(--p));display:block;margin-bottom:.5rem}
.chap .ic .oxi{width:21px;height:21px;stroke-width:1.4}

/* ---- En-tête de carte : icône et titre sur la même ligne — 06/08/2026 ----
   Le titre était sous l'icône. Il partage maintenant sa ligne, et prend un fond
   teinté (--c-soft), la même couleur de remplissage que la pastille d'icône et
   que les puces de notion : un seul lavis d'accent par carte, pas trois teintes.

   `padding-right` réserve la place du folio. Deux valeurs, parce que le sceau
   « terminé » décale le folio vers la gauche (voir .chap:has(.done-badge) .n) :
   sans le second cas, le titre passerait SOUS le numéro sur les chapitres
   achevés — soit exactement les cartes que l'apprenant regarde le plus.

   `min-width:0` sur le titre n'est pas décoratif : un enfant de flex refuse par
   défaut de descendre sous sa largeur de contenu minimale, et un titre long
   ferait alors déborder la carte au lieu de passer à la ligne. */
.chap-head{
  display:flex;align-items:flex-start;gap:.55rem;
  margin-bottom:.3rem;padding-right:3.5rem;
}
.chap:has(.done-badge) .chap-head{padding-right:4.9rem}
.chap-head .ic{flex:0 0 auto;margin-bottom:0}
.chap h3{
  font-family:var(--font-d);font-weight:600;margin:0;min-width:0;
  /* .95rem et non 1.09rem : réduction limitée à CETTE carte, la largeur restante
     après l'icône et le folio ne permettant pas la taille des autres titres.
     Les titres les plus longs du contenu — « Let's talk about the weather! » et
     « Let's celebrate Thanksgiving! », 29 caractères — passeront sur deux ou
     trois lignes dans les colonnes étroites. C'est voulu, la pastille les
     enveloppe. */
  font-size:.95rem;letter-spacing:-.01em;line-height:1.32;
  padding:.28rem .58rem;border-radius:10px;
  background:var(--c-soft);
}
.chap .sub{color:var(--ink-3);font-size:.86rem;font-style:italic;margin-bottom:.7rem}
.chap .goals{
  font-size:.815rem;color:var(--ink-2);line-height:1.62;margin-bottom:.85rem;
  padding-top:.6rem;border-top:1px solid var(--stroke-2);
}
.bar{height:3px;border-radius:0;background:var(--stroke-2);overflow:hidden}
.bar i{
  display:block;height:100%;background:var(--c,var(--p));width:0;
  transition:width 1s cubic-bezier(.22,1,.36,1);
}
.chap .pct{
  font-family:var(--font-ui);font-size:.63rem;font-weight:600;text-transform:uppercase;
  letter-spacing:.12em;color:var(--ink-3);margin-top:.55rem;display:flex;justify-content:space-between;
}
.done-badge{
  position:absolute;top:.7rem;right:.85rem;z-index:2;
  color:var(--g);display:grid;place-items:center;
  animation:sealIn .5s cubic-bezier(.22,1,.36,1);
}
.done-badge .oxi{width:19px;height:19px;stroke-width:1.7}
@keyframes sealIn{from{transform:scale(.4) rotate(-14deg);opacity:0}to{transform:none;opacity:1}}

/* ---------- 13. Leçon ---------- */
.lesson-head{
  padding:2rem 2rem 1.7rem;border-radius:var(--radius);margin-bottom:1.6rem;
  position:relative;overflow:hidden;border-top:2px solid var(--c,var(--p));
}
.lesson-head::after{
  content:'';position:absolute;top:0;right:0;width:190px;height:190px;
  background:radial-gradient(circle at 100% 0%, color-mix(in srgb,var(--c,var(--p)) 12%,transparent), transparent 70%);
  pointer-events:none;
}
.lesson-head h2{
  font-family:var(--font-d);font-weight:600;
  font-size:clamp(1.7rem,3.8vw,2.5rem);margin:.35rem 0 .1rem;
  letter-spacing:-.028em;line-height:1.06;
  display:flex;align-items:center;gap:.7rem;flex-wrap:wrap;
}
.lesson-head h2 .oxi{width:.78em;height:.78em;color:var(--c,var(--p));stroke-width:1.3}
.lesson-head .fr{color:var(--ink-2);font-size:1.02rem;font-style:italic;margin-top:.2rem}
.chips{display:flex;gap:.4rem;flex-wrap:wrap;margin-top:1.1rem;padding-top:1rem;border-top:1px solid var(--stroke-2)}
.chip{
  padding:.22rem .6rem;border-radius:6px;font-family:var(--font-ui);
  font-size:.685rem;font-weight:500;letter-spacing:.02em;
  background:transparent;color:var(--ink-2);
  border:1px solid var(--stroke);
}
html[data-theme="dark"] .chip{background:transparent;color:var(--ink-2)}

/* Onglets : commandes compactes, aux quatre coins arrondis. */
.tabs{
  display:flex;flex-wrap:wrap;gap:.45rem;margin-bottom:1.7rem;padding:.1rem 0;
}
.tab{
  position:relative;border:1px solid var(--stroke);background:var(--surface);
  font-family:var(--font-ui);font-weight:500;font-size:.815rem;
  padding:.42rem .78rem;border-radius:999px;cursor:pointer;white-space:nowrap;
  transition:color var(--t),background var(--t),border-color var(--t);color:var(--ink-2);
  display:inline-flex;align-items:center;gap:.4rem;
}
.tab .oxi{width:14px;height:14px;opacity:.75;transition:var(--t)}
.tab::after{content:none;display:none}
.tab:hover{color:var(--ink-2);border-color:var(--rule-strong);background:var(--surface-2);transform:none}
.tab.on{color:var(--on-accent);font-weight:600;background:var(--p);border-color:var(--p)}
.tab.on .oxi{opacity:1}

/* ══════════════════════════════════════════════════════════════════════════
   ÉTAPES NUMÉROTÉES ET MATÉRIEL D'APPUI — 30/08/2026
   Deux barres au lieu d'une. La première porte les trois étapes qui valident
   le chapitre, numérotées ; la seconde, plus discrète et annoncée par un
   intertitre, porte les annexes. Voir ETAPES / AIDES dans app.js.

   ⚠️ LE NUMÉRO REMPLACE LA COULEUR, IL NE S'Y AJOUTE PAS. C'est ce qui rend
   la distinction lisible en thème sombre, en noir et blanc, et pour un œil
   daltonien. Ne pas « simplifier » en retirant .tab-n au profit d'une teinte.
   ══════════════════════════════════════════════════════════════════════════ */
.tabs.etapes{margin-bottom:.9rem}
/* La pastille dépasse du bouton : il faut de la place au-dessus. */
.tabs.etapes{padding-top:.35rem}

/* ══════════════════════════════════════════════════════════════════════════
   LA PASTILLE DE NUMÉRO DÉBORDE DU BOUTON — 30/08/2026

   Première version : un petit disque gris à l'intérieur du bouton. Il faisait
   son travail dans le code et pas à l'écran — un élève qui balaie la page ne
   le voyait pas, et le numéro était précisément ce qui devait remplacer la
   nuance de couleur que personne ne devinait.

   Deux décisions, toutes deux pour qu'on ne puisse PAS le rater :

   1. LA PASTILLE EST PLUS HAUTE QUE LE BOUTON. Elle déborde de quelques
      pixels en haut et en bas. C'est ce débordement qui la fait lire comme un
      objet posé sur le bouton plutôt que comme une décoration à l'intérieur.
      Les marges verticales NÉGATIVES sont ce qui rend cela possible : sans
      elles, la pastille pousserait la hauteur du bouton et ne dépasserait
      jamais — elle grandirait, le bouton aussi, et le rapport resterait le
      même. C'est le point à ne pas « simplifier ».

   2. JAUNE #FFCF00, CHIFFRE NOIR, DANS TOUS LES ÉTATS. Le même jaune sur
      l'étape en cours, sur les étapes à faire et sur celles qui sont
      validées. Une pastille qui change de couleur selon l'état redevient un
      code à déchiffrer ; ici elle ne dit qu'une chose, toujours la même :
      « voici l'ordre ». L'état, lui, est porté par le fond du bouton, sa
      bordure et la coche.

   Contraste noir sur #FFCF00 : environ 15:1 — très au-dessus du seuil, et
   identique dans les deux thèmes puisque les deux couleurs sont posées en
   dur, sans variable de thème.
   ══════════════════════════════════════════════════════════════════════════ */
:root{
  --num-fond:#FFCF00;
  --num-encre:#000000;
}

.tab-n{
  display:inline-flex;align-items:center;justify-content:center;
  width:2.4rem;height:2.4rem;border-radius:999px;
  /* ⚠️ Sans ces marges négatives, la pastille ne déborde pas : elle
     agrandit le bouton d'autant. Voir l'en-tête, point 1. */
  margin:-.62rem .1rem -.62rem -.15rem;
  position:relative;z-index:1;
  background:var(--num-fond);color:var(--num-encre);
  font-size:1.02rem;font-weight:800;line-height:1;
  font-variant-numeric:tabular-nums;
  box-shadow:0 2px 6px -2px rgba(0,0,0,.35);
}
/* Aucune surcharge par état : c'est le propos. Voir l'en-tête, point 2.
   L'état est porté par la bordure du bouton et par la coche ci-dessous. */
.tab.etape.fait{border-color:color-mix(in oklab,var(--ok) 42%,transparent)}
.tab-ok{margin-left:.35rem;color:var(--ok);font-weight:800}
.tab.etape.on .tab-ok{color:var(--on-accent)}

.aides-bloc{margin-bottom:1.7rem}
.aides-lbl{
  display:block;font-family:var(--font-ui);font-size:.63rem;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);
  margin-bottom:.45rem;
}
.tabs.aides{margin-bottom:0}
/* Les annexes sont volontairement plus légères que les étapes : elles ne
   réclament pas d'être faites. */
.tab.aide{font-size:.78rem;padding:.34rem .68rem;opacity:.88}
.tab.aide:hover{opacity:1}
.tab.aide.on{opacity:1}

/* Numéro d'étape dans les trois jauges du haut. Même chiffre que l'onglet
   correspondant : c'est ce qui relie les deux lectures. */
/* Même pastille, en plus petit : les jauges ne sont pas des boutons, elles
   n'ont donc rien à déborder. Mais elles portent le même chiffre que l'onglet
   correspondant, et c'est ce chiffre qui relie les deux lectures — les
   habiller différemment reviendrait à casser le lien qu'on vient d'établir. */
.axis-n{
  display:inline-flex;align-items:center;justify-content:center;
  width:1.35rem;height:1.35rem;border-radius:999px;margin-right:.45rem;
  background:var(--num-fond);color:var(--num-encre);
  font-size:.8rem;font-weight:800;letter-spacing:0;line-height:1;
  font-variant-numeric:tabular-nums;vertical-align:-.3em;
}
/* Le nom de l'étape n'est plus une étiquette de mesure en petites capitales
   (« ÉCOUTE ») mais un geste (« Écouter »). Les capitales et l'interlettrage
   large faisaient passer « Lire à voix haute » sur deux lignes dans une
   grille à trois colonnes. */
.axis-top>span:first-child{
  text-transform:none;letter-spacing:.01em;font-size:.74rem;
  display:inline-flex;align-items:center;
}

/* Les trois onglets qui décident de la complétion du chapitre — Texte,
   Exercices, Prononciation — portent encore .axe pour la logique de
   progression, mais n'ont plus de traitement visuel particulier. */

/* ---------- 14. Cartes de contenu ---------- */
.card{padding:1.75rem 1.85rem;border-radius:var(--radius);margin-bottom:1.15rem}
.card h3{
  font-family:var(--font-d);font-weight:600;margin:0 0 1.1rem;font-size:1.22rem;
  letter-spacing:-.015em;display:flex;align-items:center;gap:.55rem;
  padding-bottom:.7rem;border-bottom:1px solid var(--stroke-2);
}
.card h3 .oxi{width:17px;height:17px;color:var(--p);stroke-width:1.5}
.card h3.spk-title{flex-wrap:wrap;row-gap:.55rem}
.card h3 .spk-header-actions{margin-left:auto;display:flex;align-items:center;gap:.45rem;flex-wrap:wrap}
.card h3 .lecture-score{margin-left:.1rem;white-space:nowrap}
.lecture-score-count{font-weight:750}
.lecture-score.is-low .lecture-score-count{color:var(--ko)}
.lecture-score.is-near .lecture-score-count{color:var(--o)}
.lecture-score.is-complete .lecture-score-count{color:var(--ok)}
@media (max-width:560px){
  /* L'icône suffit sur téléphone ; aria-label et title gardent le bouton clair. */
  #spkReglagesBtn .spk-action-label{display:none}
}
.card h4{
  font-family:var(--font-ui);margin:1.5rem 0 .45rem;font-size:.7rem;color:var(--p);
  font-weight:600;text-transform:uppercase;letter-spacing:.15em;
}
.card p{line-height:1.72;margin:.6rem 0;text-wrap:pretty}
.card ul,.card ol{line-height:1.75;padding-left:1.25rem}
.card li{margin:.22rem 0}
.card li::marker{color:var(--ink-3)}
.card i,.card em{color:var(--b);font-style:italic}
html[data-theme="dark"] .card i,html[data-theme="dark"] .card em{color:var(--b)}
.card b,.card strong{color:var(--ink);font-weight:600}

/* ---------- 15. Texte bilingue ---------- */
.story-line{
  display:grid;grid-template-columns:1fr;gap:.15rem;
  padding:.62rem .9rem .62rem 1rem;border-radius:6px;
  cursor:pointer;transition:background var(--t), border-color var(--t), transform var(--t);
  border-left:2px solid transparent;position:relative;
}
.story-line:hover{background:color-mix(in srgb,var(--p) 4.5%,transparent);border-left-color:color-mix(in srgb,var(--p) 45%,transparent)}
.story-line .en{font-weight:500;line-height:1.7;font-size:1.045rem;letter-spacing:.002em}
.story-line .fr{
  color:var(--ink-3);font-size:.9rem;font-style:italic;line-height:1.55;
  transition:max-height var(--t), opacity var(--t);max-height:6em;overflow:hidden;
}
.story-line.hidefr .fr{max-height:0;opacity:0}
.story-line .spk{opacity:0;transition:var(--t);margin-left:.4rem;color:var(--p)}
.story-line .spk .oxi{width:14px;height:14px;vertical-align:-.14em}
.story-line:hover .spk{opacity:.7}
/* Ligne en cours de lecture : un doigt qui suit le texte */
.story-line.now{
  background:color-mix(in srgb,var(--a) 13%,transparent);
  border-left-color:var(--a);
}
.story-line.now::before{
  content:'';position:absolute;left:0;top:0;bottom:0;width:2px;background:var(--a);
  animation:readPulse 1.9s ease-in-out infinite;
}
@keyframes readPulse{0%,100%{opacity:1}50%{opacity:.35}}
.story-line.now .en{color:var(--ink)}

/* Lettrine sur la première phrase du texte — détail d'imprimeur */
.card .story-line:first-of-type .en::first-letter{
  font-family:var(--font-d);font-weight:500;
  font-size:3.1em;line-height:.82;float:left;
  margin:.05em .12em 0 0;color:var(--p);
}

/* ---------- 16. Grammaire ---------- */
.gt{
  width:100%;border-collapse:collapse;margin:1rem 0;font-size:.93rem;
  border-top:1.5px solid var(--rule-strong);border-bottom:1.5px solid var(--rule-strong);
}
.gt th{
  background:transparent;color:var(--ink-3);padding:.5rem .75rem .5rem 0;text-align:left;
  font-family:var(--font-ui);font-weight:600;font-size:.63rem;
  text-transform:uppercase;letter-spacing:.14em;
  border-bottom:1px solid var(--rule-strong);
}
.gt td{padding:.52rem .75rem .52rem 0;border-bottom:1px solid var(--stroke-2);background:transparent}
.gt tr:last-child td{border-bottom:0}
.gt tbody tr{transition:background var(--t)}
.gt tbody tr:hover td{background:color-mix(in srgb,var(--p) 4%,transparent)}

.formula{
  background:transparent;border:0;border-left:2px solid var(--a);
  padding:.7rem 1rem;border-radius:0;font-weight:500;display:block;margin:1.1rem 0;
  font-family:var(--font-m);font-size:.88rem;letter-spacing:-.01em;
  color:var(--ink);
}
.tip{
  background:color-mix(in srgb,var(--y) 9%,transparent);
  border:0;border-left:2px solid var(--y);
  padding:.85rem 1.1rem;border-radius:0;margin:1.1rem 0 !important;
  font-size:.93rem;line-height:1.68;
}
.method-card{background:var(--surface);border-left:2px solid var(--g)}
.culture-card{background:var(--surface);border-left:2px solid var(--o)}
.method-card h3 .oxi{color:var(--g)}
.culture-card h3 .oxi{color:var(--o)}

/* ---------- 17. Vocabulaire — entrées de dictionnaire ---------- */
.vocab-grid{
  display:grid;grid-template-columns:repeat(auto-fill,minmax(252px,1fr));
  gap:0;border-top:1px solid var(--stroke-2);
}
.word{
  display:flex;align-items:baseline;gap:.55rem;padding:.6rem .75rem .6rem .1rem;
  border-radius:0;background:transparent;
  border:0;border-bottom:1px solid var(--stroke-2);
  transition:background var(--t), padding-left var(--t);cursor:pointer;
}
.word:hover{
  background:color-mix(in srgb,var(--p) 4.5%,transparent);
  padding-left:.5rem;transform:none;box-shadow:none;
}
.word .w{font-weight:600;font-size:.98rem;letter-spacing:.004em}
.word .t{color:var(--ink-3);font-size:.855rem;font-style:italic;line-height:1.35}
/* Le point de conduite du dictionnaire */
.word .t::before{content:'·';margin-right:.45rem;font-style:normal;opacity:.5}
.word .sp{margin-left:auto;opacity:0;color:var(--p);align-self:center;transition:opacity var(--t)}
.word .sp .oxi{width:14px;height:14px}
.word:hover .sp{opacity:.85}

/* ---------- 18. Exercices ---------- */
.ex-block{padding:1.6rem 1.75rem;border-radius:var(--radius);margin-bottom:1.15rem}
.ex-block h3{
  font-family:var(--font-d);font-weight:600;margin:0 0 .15rem;font-size:1.08rem;
  border:0;padding:0;letter-spacing:-.012em;
}
.ex-kind{
  font-family:var(--font-ui);font-size:.615rem;font-weight:600;letter-spacing:.18em;
  text-transform:uppercase;color:var(--a);margin-bottom:1.1rem;
  padding-bottom:.7rem;border-bottom:1px solid var(--stroke-2);
}
.ex-item{
  display:flex;align-items:center;gap:.7rem;padding:.62rem 0;
  border-bottom:1px solid var(--stroke-2);flex-wrap:wrap;
}
.ex-item:last-child{border-bottom:0}
.ex-q{flex:1;min-width:210px;line-height:1.62;font-size:.96rem}
.ex-q .blank{
  display:inline-block;min-width:84px;border-bottom:1px solid var(--p);
  margin:0 .25rem;vertical-align:baseline;
}
input.ans,select.ans{
  font-family:var(--font);font-weight:500;font-size:.94rem;padding:.36rem .1rem;
  border-radius:0;border:0;border-bottom:1.5px solid var(--stroke);
  background:transparent;color:var(--ink);min-width:170px;
  transition:border-color var(--t), background var(--t);
}
select.ans{font-family:var(--font-ui);font-size:.86rem;padding:.36rem .3rem;border:1px solid var(--stroke);border-radius:var(--radius-sm)}
input.ans::placeholder{color:var(--ink-3);opacity:.6}
input.ans:focus,select.ans:focus{outline:0;border-color:var(--p);box-shadow:0 1px 0 var(--p)}

/* Champ posé DANS la phrase (texte à trous) */
input.ans.inline{
  display:inline-block;vertical-align:baseline;
  min-width:0;width:9ch;margin:0 .2rem;padding:.1rem .3rem;
  font-weight:600;text-align:center;border-bottom-color:var(--p);
}
/* Navigateurs récents : le champ grandit avec ce qu'on tape. */
@supports (field-sizing:content){
  input.ans.inline{field-sizing:content;width:auto;min-width:6ch;max-width:100%}
}
input.ans.inline::placeholder{opacity:.35}

/* Traduction / remise en ordre : champ SOUS la phrase */
.ex-item.stack{flex-direction:column;align-items:stretch;gap:.4rem}
.ex-item.stack .ex-q{min-width:0}
.ans-row{display:flex;align-items:center;gap:.6rem;flex-wrap:wrap}
.ans-row input.ans{flex:1;min-width:0}
input.ans.good{border-color:var(--ok);background:color-mix(in srgb,var(--ok) 8%,transparent);animation:settle .5s cubic-bezier(.22,1,.36,1)}
input.ans.bad{border-color:var(--ko);background:color-mix(in srgb,var(--ko) 7%,transparent);animation:nudge .42s}
@keyframes settle{0%{transform:translateY(3px);opacity:.55}100%{transform:none;opacity:1}}
@keyframes nudge{0%,100%{transform:translateX(0)}22%{transform:translateX(-5px)}44%{transform:translateX(5px)}66%{transform:translateX(-3px)}88%{transform:translateX(3px)}}
.fb{font-weight:600;min-width:20px;display:inline-flex;align-items:center}
.fb .oxi{width:15px;height:15px;stroke-width:2}
.fb.g{color:var(--ok)} .fb.b{color:var(--ko)}
.sol{font-size:.86rem;color:var(--ok);font-style:italic;display:inline-flex;align-items:center;gap:.25rem}
.qcm-opts{display:flex;gap:.4rem;flex-wrap:wrap}
.opt{
  border:1px solid var(--stroke);background:transparent;
  font-family:var(--font-ui);font-weight:500;font-size:.83rem;
  padding:.35rem .75rem;border-radius:var(--radius-sm);cursor:pointer;
  transition:var(--t);color:var(--ink-2);
}
.opt:hover{border-color:var(--p);color:var(--p);transform:none}
/* Réponse choisie, avant correction — il manquait ce style : le clic n'était pas visible. */
.opt.sel{
  border-color:var(--p);color:var(--p);font-weight:700;
  background:color-mix(in srgb,var(--p) 12%,transparent);
  box-shadow:0 0 0 2px color-mix(in srgb,var(--p) 22%,transparent);
}
/* Après correction, bon/faux priment sur la sélection. */
.opt.good,.opt.bad{box-shadow:none}
.opt.good{border-color:var(--ok);color:var(--ok);background:color-mix(in srgb,var(--ok) 9%,transparent)}
.opt.bad{border-color:var(--ko);color:var(--ko);background:color-mix(in srgb,var(--ko) 8%,transparent)}
.ex-actions{display:flex;gap:.5rem;flex-wrap:wrap;margin-top:1.2rem;align-items:center}
.score-pill{
  margin-left:auto;font-family:var(--font-ui);font-weight:600;font-size:.78rem;
  padding:.3rem .75rem;border-radius:var(--radius-sm);background:transparent;
  border:1px solid var(--stroke);color:var(--ink-2);
}

/* ---------- 19. Flashcards ---------- */
.fc-wrap{display:grid;place-items:center;gap:1.4rem;padding:1rem 0}
.flashcard{width:min(560px,100%);height:300px;perspective:1800px;cursor:pointer}
.fc-inner{
  position:relative;width:100%;height:100%;transform-style:preserve-3d;
  transition:transform .78s cubic-bezier(.5,.03,.2,1);
}
.flashcard.flip .fc-inner{transform:rotateY(180deg)}
.fc-face{
  position:absolute;inset:0;backface-visibility:hidden;-webkit-backface-visibility:hidden;
  border-radius:var(--radius);display:grid;place-items:center;text-align:center;padding:2.4rem;
  background:var(--surface);border:1px solid var(--stroke);box-shadow:var(--shadow);
}
.fc-face::after{content:'';position:absolute;inset:7px;border:1px solid var(--stroke-2);pointer-events:none;border-radius:6px}
.fc-face.back{transform:rotateY(180deg);background:var(--surface-2)}
.fc-face .big{
  font-family:var(--font-d);font-weight:500;
  font-size:clamp(1.6rem,4.6vw,2.5rem);line-height:1.18;letter-spacing:-.022em;
}
.fc-face .hint{
  color:var(--ink-3);font-family:var(--font-ui);font-size:.65rem;margin-top:1.1rem;
  font-weight:600;text-transform:uppercase;letter-spacing:.16em;
}
.fc-face .tagchap{
  position:absolute;top:1.3rem;left:1.5rem;font-family:var(--font-ui);
  font-size:.6rem;font-weight:600;color:var(--ink-3);text-transform:uppercase;letter-spacing:.17em;
}
.fc-controls{display:flex;gap:.4rem;flex-wrap:wrap;justify-content:center}
.grade{
  border:1px solid var(--stroke);font-family:var(--font-ui);font-weight:600;font-size:.8rem;
  padding:.48rem .95rem;border-radius:var(--radius-sm);cursor:pointer;color:var(--ink-2);
  background:transparent;transition:var(--t);
}
.grade:hover{transform:none;color:var(--on-accent)}
.g1{--gc:var(--r)} .g2{--gc:var(--o)} .g3{--gc:var(--b)} .g4{--gc:var(--g)}
.grade:hover{background:var(--gc);border-color:var(--gc)}
html[data-theme="dark"] .grade:hover{color:#14151C}
.fc-meta{
  display:flex;gap:1.4rem;justify-content:center;font-family:var(--font-ui);
  font-size:.72rem;color:var(--ink-3);font-weight:500;flex-wrap:wrap;letter-spacing:.03em;
}

/* ---------- 20. Quiz ---------- */
.quiz-top{display:flex;align-items:center;gap:1.2rem;margin-bottom:1.4rem;flex-wrap:wrap}
.timer{
  font-family:var(--font-d);font-size:2.1rem;font-weight:500;min-width:72px;
  font-variant-numeric:lining-nums tabular-nums;letter-spacing:-.03em;
}
.timer.warn{color:var(--r);animation:tick .9s ease-in-out infinite}
@keyframes tick{50%{opacity:.42}}
.quiz-q{padding:2.6rem 2rem;border-radius:var(--radius);text-align:center;margin-bottom:1.2rem}
.quiz-q .qt{
  font-family:var(--font-d);font-weight:500;
  font-size:clamp(1.25rem,3.2vw,1.85rem);line-height:1.32;margin-bottom:.6rem;
  letter-spacing:-.02em;
}
.quiz-q .qs{
  color:var(--ink-3);font-family:var(--font-ui);font-size:.63rem;font-weight:600;
  text-transform:uppercase;letter-spacing:.17em;
}
.quiz-opts{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:.55rem}
.qopt{
  padding:.85rem 1rem;border-radius:var(--radius-sm);border:1px solid var(--stroke);background:transparent;
  font-family:var(--font);font-size:1rem;font-weight:500;cursor:pointer;
  transition:var(--t);color:var(--ink);text-align:left;
}
.qopt:hover:not(:disabled){transform:none;border-color:var(--p);color:var(--p);box-shadow:none}
.qopt.good{border-color:var(--ok);color:var(--ok);background:color-mix(in srgb,var(--ok) 9%,transparent)}
.qopt.bad{border-color:var(--ko);color:var(--ko);background:color-mix(in srgb,var(--ko) 8%,transparent)}
.qopt:disabled{cursor:default}
.progress-dots{display:flex;gap:2px;flex:1}
.dot{width:100%;height:2px;border-radius:0;background:var(--stroke);transition:background var(--t)}
.dot.d{background:var(--g)} .dot.w{background:var(--r)} .dot.c{background:var(--p)}

/* ---------- 21. Cartes mentales ---------- */
.mm-bar{display:flex;gap:.4rem;flex-wrap:wrap;align-items:center;margin-bottom:1rem}
.mm-canvas{
  position:relative;width:100%;height:640px;border-radius:var(--radius);overflow:hidden;
  background:var(--surface);border:1px solid var(--stroke);box-shadow:var(--shadow);
}
.mm-canvas svg{position:absolute;inset:0;width:100%;height:100%}
/* Quadrillage de papier millimétré */
.mm-grid{
  position:absolute;inset:0;pointer-events:none;
  background-image:
    linear-gradient(to right, var(--stroke-2) 1px, transparent 1px),
    linear-gradient(to bottom, var(--stroke-2) 1px, transparent 1px);
  background-size:28px 28px;
}
.node{
  position:absolute;padding:.5rem .9rem;border-radius:var(--radius-sm);color:#fff;
  font-family:var(--font-ui);font-weight:600;font-size:.855rem;
  cursor:grab;user-select:none;box-shadow:0 4px 14px -8px rgba(0,0,0,.6);
  transition:box-shadow .2s, transform .12s;
  max-width:230px;text-align:center;border:1px solid rgba(255,255,255,.28);
}
.node:active{cursor:grabbing;transform:scale(1.04)}
.node.sel{outline:1.5px solid var(--ink);outline-offset:3px;box-shadow:0 8px 22px -10px rgba(0,0,0,.6)}
.node.root{font-size:.98rem;padding:.68rem 1.2rem;border-radius:4px}
.mm-hint{font-size:.83rem;color:var(--ink-3);font-style:italic;margin-top:.7rem}
.swatches{display:flex;gap:.28rem}
.sw{width:22px;height:22px;border-radius:6px;border:1px solid var(--stroke);cursor:pointer;transition:var(--t)}
.sw:hover{transform:scale(1.16)}

/* ---------- 22. Dictionnaire ---------- */
.search-box{display:flex;gap:.5rem;margin-bottom:1.3rem;flex-wrap:wrap}
.search-box input{
  flex:1;min-width:230px;font-family:var(--font);font-size:1.02rem;
  padding:.62rem .1rem;border-radius:0;
  border:0;border-bottom:1.5px solid var(--stroke);
  background:transparent;color:var(--ink);transition:border-color var(--t);
}
.search-box input::placeholder{color:var(--ink-3);font-style:italic;opacity:.75}
.search-box input:focus{outline:0;border-color:var(--p);box-shadow:0 1px 0 var(--p)}
.filters{display:flex;gap:.35rem;flex-wrap:wrap;margin-bottom:1.2rem}
.filt{
  border:1px solid var(--stroke);background:transparent;
  font-family:var(--font-ui);font-weight:500;font-size:.735rem;
  padding:.28rem .68rem;border-radius:var(--radius-sm);cursor:pointer;transition:var(--t);color:var(--ink-2);
  display:inline-flex;align-items:center;gap:.32rem;
}
.filt .oxi{width:13px;height:13px}
.filt:hover{transform:none;border-color:var(--p);color:var(--p)}
.filt.on{background:var(--p);color:var(--on-accent);border-color:var(--p)}
html[data-theme="dark"] .filt.on{color:#14151C}
.res-count{
  color:var(--ink-3);font-family:var(--font-ui);font-weight:500;font-size:.72rem;
  margin-bottom:.9rem;text-transform:uppercase;letter-spacing:.12em;
}
.irr-table{
  width:100%;border-collapse:collapse;font-size:.92rem;
  border-top:1.5px solid var(--rule-strong);
}
.irr-table th{
  background:var(--bg1);color:var(--ink-3);padding:.55rem .8rem .55rem 0;text-align:left;
  position:sticky;top:52px;z-index:2;
  font-family:var(--font-ui);font-weight:600;font-size:.63rem;
  text-transform:uppercase;letter-spacing:.14em;
  border-bottom:1px solid var(--rule-strong);
}
.irr-table td{padding:.5rem .8rem .5rem 0;border-bottom:1px solid var(--stroke-2);background:transparent}
.irr-table tr{transition:background var(--t)}
.irr-table tr:hover td{background:color-mix(in srgb,var(--p) 4%,transparent)}

/* ---------- 23. Progression ---------- */
.stat-grid{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(158px,1fr));gap:0;margin-bottom:2rem;
  border-top:1px solid var(--stroke);border-left:1px solid var(--stroke);background:var(--surface);
}
.stat{
  padding:1.35rem .9rem;border-radius:0;text-align:center;
  border:0;border-right:1px solid var(--stroke);border-bottom:1px solid var(--stroke);
  background:transparent;box-shadow:none;transition:background var(--t);
}
.stat::before{display:none}
.stat:hover{transform:none;background:color-mix(in srgb,var(--p) 4%,transparent)}
.stat .k{
  font-family:var(--font-d);font-size:2.05rem;font-weight:500;line-height:1;
  background:none;color:var(--ink);letter-spacing:-.03em;
  font-variant-numeric:lining-nums tabular-nums;
  -webkit-text-fill-color:currentColor;
}
.stat .l{
  font-family:var(--font-ui);font-size:.6rem;font-weight:600;text-transform:uppercase;
  letter-spacing:.16em;color:var(--ink-3);margin-top:.5rem;
}
.badges{display:grid;grid-template-columns:repeat(auto-fill,minmax(146px,1fr));gap:.6rem}
.badge{
  padding:1.1rem .7rem;border-radius:var(--radius-sm);text-align:center;
  background:transparent;border:1px solid var(--stroke-2);
  opacity:.45;filter:grayscale(1);transition:var(--t);
}
.badge.won{
  opacity:1;filter:none;border-color:color-mix(in srgb,var(--a) 45%,transparent);
  background:color-mix(in srgb,var(--a) 6%,transparent);
  animation:sealIn .5s cubic-bezier(.22,1,.36,1);
}
.badge .bi{display:block;color:var(--a);margin-bottom:.4rem}
.badge .bi .oxi{width:24px;height:24px;stroke-width:1.4}
.badge .bn{font-family:var(--font-d);font-weight:600;font-size:.88rem;margin-top:.2rem;letter-spacing:-.01em}
.badge .bd{font-size:.73rem;color:var(--ink-3);line-height:1.42;margin-top:.28rem;font-style:italic}

/* ---------- 24. Messages & confettis ---------- */
#toasts{position:fixed;bottom:1.3rem;right:1.3rem;z-index:200;display:flex;flex-direction:column;gap:.5rem;align-items:flex-end}
.toast{
  padding:.68rem 1.05rem;border-radius:var(--radius-sm);font-family:var(--font-ui);
  font-weight:500;font-size:.83rem;color:var(--bg1);
  background:var(--ink);border-left:2px solid var(--a);
  box-shadow:var(--shadow-lift);max-width:min(400px,86vw);
  animation:slidein .42s cubic-bezier(.22,1,.36,1), fadeout .4s 2.6s forwards;
}
html[data-theme="dark"] .toast{background:var(--paper-2);color:var(--ink);border:1px solid var(--stroke);border-left:2px solid var(--a)}
.toast.win{border-left-color:var(--g)}
.toast.warn{border-left-color:var(--y)}
@keyframes slidein{from{transform:translateX(18px);opacity:0}}
@keyframes fadeout{to{opacity:0;transform:translateY(6px)}}

#confetti{position:fixed;inset:0;pointer-events:none;z-index:190}
/* Éclats de feuille d'or plutôt que des confettis de fête foraine */
.conf{position:absolute;width:5px;height:9px;animation:fall linear forwards;opacity:.85}
@keyframes fall{to{transform:translateY(105vh) rotate(680deg);opacity:0}}

/* ---------- Synchronisation du compte ---------- */
.sync-overlay{
  position:fixed;inset:0;z-index:500;display:grid;place-items:center;padding:1.25rem;
  background:color-mix(in srgb,var(--bg1) 82%,transparent);
  backdrop-filter:blur(9px);-webkit-backdrop-filter:blur(9px);
  opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .2s ease,visibility 0s linear .2s;
}
.sync-overlay.visible{
  opacity:1;visibility:visible;pointer-events:all;transition-delay:0s;
}
.sync-panel{
  display:flex;align-items:center;gap:.72rem;padding:.9rem 1.05rem;
  border:1px solid var(--stroke);border-radius:var(--radius-sm);
  background:var(--surface);color:var(--ink);box-shadow:var(--shadow);
  font-family:var(--font-ui);font-size:.84rem;font-weight:650;
}
.sync-spinner{
  width:1.05rem;height:1.05rem;border:2px solid color-mix(in srgb,var(--p) 24%,transparent);
  border-top-color:var(--p);border-radius:50%;animation:spin .8s linear infinite;
}
@media (prefers-reduced-motion:reduce){.sync-spinner{animation-duration:1.8s}}

/* ---------- 25. Modales ---------- */
.modal-back{
  position:fixed;inset:0;z-index:300;display:grid;place-items:center;padding:1rem;
  background:color-mix(in srgb, var(--ink) 45%, transparent);
  backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);animation:fadein .24s;
}
@keyframes fadein{from{opacity:0}}
.modal{
  width:min(640px,100%);max-height:88vh;display:flex;flex-direction:column;
  border-radius:var(--radius);background:var(--surface);border:1px solid var(--stroke);
  box-shadow:0 32px 70px -30px rgba(0,0,0,.5);
  animation:modalIn .42s cubic-bezier(.22,1,.36,1);
}
@keyframes modalIn{from{opacity:0;transform:translateY(14px) scale(.985)}}
.modal-head{display:flex;align-items:center;gap:.6rem;padding:1.15rem 1.4rem .85rem;border-bottom:1px solid var(--stroke)}
.modal-head h3{
  font-family:var(--font-d);font-weight:600;margin:0;flex:1;font-size:1.16rem;letter-spacing:-.015em;
}
.modal-body{padding:1.3rem 1.4rem 1.4rem;overflow-y:auto}
.modal-foot{display:flex;gap:.5rem;justify-content:flex-end;margin-top:1.4rem;padding-top:1rem;border-top:1px solid var(--stroke)}
.fld-lbl{
  display:block;font-family:var(--font-ui);font-weight:600;font-size:.635rem;
  text-transform:uppercase;letter-spacing:.16em;color:var(--ink-3);margin:1.5rem 0 .5rem;
  padding-bottom:.3rem;border-bottom:1px solid var(--stroke-2);
}
.fld-lbl:first-child{margin-top:0}
.fld-row{display:flex;gap:.4rem;align-items:center}
.fld-help{font-size:.8rem;color:var(--ink-3);margin:.4rem 0 0;line-height:1.6;font-style:italic}
.fld-help a{color:var(--p);font-weight:500}
.warn-box{
  font-size:.815rem;line-height:1.62;margin:.7rem 0 0;padding:.7rem .95rem;border-radius:0;
  background:color-mix(in srgb,var(--y) 9%,transparent);border-left:2px solid var(--y);
}
.warn-box[hidden]{display:none}
.spk-settings{margin:.95rem 0 0;padding-top:.95rem;border-top:1px solid var(--stroke-2)}
.spk-settings[hidden]{display:none}
.eng-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(132px,1fr));gap:.45rem}
.eng{
  display:flex;flex-direction:column;align-items:center;gap:.3rem;padding:.85rem .5rem;
  border-radius:var(--radius-sm);border:1px solid var(--stroke);background:transparent;cursor:pointer;
  transition:var(--t);color:var(--ink-2);font:inherit;
}
.eng:hover:not(:disabled){transform:none;border-color:var(--p);color:var(--p)}
.eng.on{border-color:var(--p);color:var(--p);background:color-mix(in srgb,var(--p) 6%,transparent);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--p) 22%,transparent)}
.eng.soon{opacity:.42;cursor:not-allowed;filter:grayscale(.8)}
.eng-ic{font-size:1.25rem;line-height:1}
.eng-ic .oxi{width:20px;height:20px}
.eng-n{font-family:var(--font-ui);font-weight:600;font-size:.795rem;text-align:center;line-height:1.25}
.eng-b{
  font-family:var(--font-ui);font-size:.555rem;font-weight:600;text-transform:uppercase;
  letter-spacing:.13em;padding:.08rem .4rem;border-radius:6px;
  background:transparent;border:1px solid var(--stroke);color:var(--ink-3);
}
.eng-b.live{border-color:var(--g);color:var(--g)}
.eng-b.free{border-color:var(--b);color:var(--b)}
.eng-desc{font-size:.85rem;color:var(--ink-2);line-height:1.62;margin:.8rem 0 0}
.seg{display:flex;gap:0;border:1px solid var(--stroke);border-radius:var(--radius-sm);overflow:hidden}
.seg-b{
  flex:1;padding:.48rem;border:0;border-right:1px solid var(--stroke);background:transparent;
  font-family:var(--font-ui);font-weight:500;font-size:.8rem;cursor:pointer;
  transition:var(--t);color:var(--ink-2);
}
.seg-b:last-child{border-right:0}

/* Table des raccourcis clavier, dans la modale qui remplace l'ancien alert(). */
.kbd-table{width:100%;border-collapse:collapse;font-size:.9rem}
.kbd-table td{padding:.42rem .5rem .42rem 0;border-bottom:1px solid var(--stroke-2);color:var(--ink-2)}
.kbd-table tr:last-child td{border-bottom:0}
.kbd-table td:first-child{width:5.4rem}
.kbd-table kbd{
  display:inline-block;min-width:2.6rem;text-align:center;
  font-family:var(--font-ui);font-size:.74rem;font-weight:700;
  padding:.18rem .45rem;border-radius:5px;
  border:1px solid var(--stroke);border-bottom-width:2px;
  background:var(--surface-2);color:var(--ink);
}

/* ══════════════════════════════════════════════════════════════════════════
   ÉCRANS DE BIENVENUE — 30/08/2026
   Trois écrans, une seule fois, sur un compte neuf. Voir montrerBienvenue()
   dans app.js. Le voile est opaque : c'est le seul moment de la vie de
   l'application où l'on demande de lire avant d'agir, autant que ce soit net.
   ══════════════════════════════════════════════════════════════════════════ */
#bienvenue{
  position:fixed;inset:0;z-index:200;
  display:flex;align-items:center;justify-content:center;padding:1.2rem;
  background:color-mix(in srgb,var(--bg1) 78%,transparent);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  animation:bvFond .28s ease both;
}
@keyframes bvFond{from{opacity:0}to{opacity:1}}

.bv-carte{
  max-width:430px;width:100%;
  padding:2rem 1.9rem 1.6rem;border-radius:var(--radius);
  text-align:center;
  box-shadow:0 24px 60px -30px rgba(0,0,0,.5);
  animation:bvCarte .34s var(--spring) both;
}
@keyframes bvCarte{from{opacity:0;transform:translateY(14px) scale(.985)}to{opacity:1;transform:none}}

.bv-ic{font-size:2.4rem;line-height:1;display:block;margin-bottom:.9rem}
.bv-carte h2{
  font-family:var(--font-d);font-weight:700;font-size:1.42rem;
  line-height:1.2;letter-spacing:-.015em;margin:0 0 .7rem;text-wrap:balance;
}
.bv-carte p{
  margin:0;color:var(--ink-2);font-size:.95rem;line-height:1.62;
  text-wrap:pretty;
}
.bv-carte p b{color:var(--ink);font-weight:700}

/* Trois points : on sait combien il en reste. Sans eux, « Suivant » peut
   laisser croire à une file sans fin, et on passe. */
.bv-points{display:flex;gap:.35rem;justify-content:center;margin:1.3rem 0 1.1rem}
.bv-points i{
  width:6px;height:6px;border-radius:99px;background:var(--stroke);
  transition:background var(--t),width var(--t);
}
.bv-points i.on{width:18px;background:var(--p)}

.bv-actions{display:flex;gap:.5rem;justify-content:center;align-items:center}

@media (max-width:480px){
  .bv-carte{padding:1.6rem 1.3rem 1.3rem}
  .bv-carte h2{font-size:1.26rem}
  .bv-actions{flex-direction:column-reverse}
  .bv-actions .btn{width:100%;justify-content:center}
}

/* Dépliant « Réglages avancés » de la boîte de voix — 30/08/2026.
   Voir le commentaire dans tts.js : ce qui est ici n'a de sens que pour qui
   sait déjà ce qu'est une clé API. Fermé par défaut, et nettement séparé des
   trois réglages qui, eux, s'adressent à l'apprenant. */
.tts-avance{
  margin:1.4rem 0 .4rem;
  border-top:1px solid var(--stroke);
  padding-top:.9rem;
}
.tts-avance>summary{
  cursor:pointer;list-style:none;
  font-family:var(--font-ui);font-size:.82rem;font-weight:600;
  color:var(--ink-2);padding:.35rem 0;
  display:flex;align-items:center;gap:.5rem;
}
.tts-avance>summary::-webkit-details-marker{display:none}
.tts-avance>summary::before{
  content:'▸';color:var(--ink-3);display:inline-block;
  transition:transform .18s var(--t);
}
.tts-avance[open]>summary::before{transform:rotate(90deg)}
.tts-avance>summary:hover{color:var(--ink)}
.tts-avance[open]{padding-bottom:.3rem}

/* Sous-barre d'un groupe de navigation (Réviser, Ressources, Ma progression).
   Elle reprend le segmenté existant, avec deux réglages : de l'air avant le
   titre de page, et une largeur bornée — étirée sur 1 280 px, une barre de
   deux boutons ressemblait à un bandeau plutôt qu'à un choix. */
.sous-barre{margin-bottom:1.5rem;max-width:620px}
@media (max-width:900px){.sous-barre{max-width:none}}
.seg-b:hover{color:var(--p);background:color-mix(in srgb,var(--p) 5%,transparent)}
.seg-b.on{background:var(--p);color:var(--on-accent);border-color:var(--p)}
html[data-theme="dark"] .seg-b.on{color:#14151C}
.chip.cbtn{border:1px solid var(--stroke);font:inherit;font-family:var(--font-ui);cursor:pointer;transition:var(--t)}
.chip.cbtn:hover{transform:none;background:var(--p);color:var(--on-accent);border-color:var(--p)}
html[data-theme="dark"] .chip.cbtn:hover{color:#14151C}

.switch{position:relative;display:inline-block;width:40px;height:22px;flex-shrink:0}
.switch input{opacity:0;width:0;height:0}
.switch span{position:absolute;inset:0;border-radius:99px;background:transparent;border:1px solid var(--stroke);transition:var(--t);cursor:pointer}
.switch span::before{
  content:'';position:absolute;width:14px;height:14px;left:3px;top:3px;border-radius:50%;
  background:var(--ink-3);transition:var(--t);
}
.switch input:checked + span{background:var(--p);border-color:var(--p)}
.switch input:checked + span::before{transform:translateX(18px);background:var(--paper)}
input[type=range]{accent-color:var(--p);height:24px}

.voice-pill{font-family:var(--font-ui);font-size:.68rem;font-weight:600;color:var(--p);cursor:pointer}
.diag{
  margin:.7rem 0 0;padding:.85rem 1rem;border-radius:6px;background:var(--paper-2);
  border:1px solid var(--stroke-2);font-family:var(--font-m);font-size:.735rem;
  line-height:1.7;white-space:pre-wrap;word-break:break-word;max-height:220px;overflow:auto;
  color:var(--ink-2);
}

.preload-pill{
  position:fixed;bottom:1.4rem;left:50%;transform:translateX(-50%);z-index:180;cursor:pointer;
  padding:.48rem 1rem;border-radius:var(--radius-sm);font-family:var(--font-ui);font-size:.775rem;font-weight:500;
  color:var(--ink);background:var(--surface);border:1px solid var(--stroke);
  box-shadow:var(--shadow-lift);display:flex;align-items:center;gap:.45rem;
  animation:slideup .38s cubic-bezier(.22,1,.36,1);white-space:nowrap;max-width:92vw;overflow:hidden;
}
@keyframes slideup{from{opacity:0;transform:translate(-50%,10px)}}
.preload-pill:hover{border-color:var(--p)}
.preload-pill b{color:var(--p);font-weight:600}
.preload-pill::before{
  content:'';position:absolute;left:0;bottom:0;height:2px;width:var(--pct,0%);
  background:var(--p);transition:width .45s cubic-bezier(.22,1,.36,1);
}
.pl-x{border:0;background:transparent;cursor:pointer;font-size:.85rem;opacity:.45;padding:0 0 0 .35rem;color:inherit}
.pl-x:hover{opacity:1;color:var(--r)}
.pl-err{border:0;background:transparent;cursor:pointer;font:inherit;font-weight:700;font-size:.8rem;
  color:var(--r);text-decoration:underline;text-underline-offset:2px;padding:0}
.pl-err:hover{opacity:.7}
.preload-pill.has-err{border-color:var(--r)}
.err-row{display:flex;gap:.6rem;align-items:flex-start;padding:.45rem .7rem;margin-bottom:.3rem;
  border-radius:8px;background:var(--surface);border:1px solid var(--stroke-2);
  font-family:ui-monospace,'SF Mono',Menlo,monospace;font-size:.76rem;line-height:1.55;word-break:break-word}
.err-row b{color:var(--r);flex-shrink:0}
.resume-bar{
  position:fixed;bottom:1.4rem;left:50%;transform:translateX(-50%);z-index:185;
  display:flex;align-items:center;gap:.7rem;flex-wrap:wrap;justify-content:center;
  padding:.75rem 1.15rem;border-radius:var(--radius);font-size:.85rem;
  max-width:min(620px,94vw);animation:slideup .4s cubic-bezier(.22,1,.36,1);
}
.resume-bar b{color:var(--p);font-weight:600}
.el-models{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:.5rem}
.el-models label{display:block;font-family:var(--font-ui);font-size:.72rem;font-weight:600;color:var(--ink-2)}
.el-models select{width:100%;margin-top:.25rem;font-size:.8rem}
.el-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:.5rem .9rem}
.el-grid label{display:block;font-family:var(--font-ui);font-size:.71rem;font-weight:500;color:var(--ink-2)}
.el-grid label b{color:var(--p);float:right;font-variant-numeric:tabular-nums}
.el-grid input[type=range]{width:100%;margin-top:.1rem}
.rate-marks{display:flex;gap:.28rem;flex-wrap:wrap;margin-top:.4rem}
.rate-m{
  border:1px solid var(--stroke);background:transparent;font-family:var(--font-ui);
  font-weight:500;font-size:.7rem;padding:.2rem .55rem;border-radius:6px;cursor:pointer;
  transition:var(--t);color:var(--ink-3);
}
.rate-m:hover{transform:none;border-color:var(--p);color:var(--p)}
.rate-m.on{background:var(--p);color:var(--on-accent);border-color:var(--p)}
html[data-theme="dark"] .rate-m.on{color:#14151C}
.par-reset{
  border:1px solid var(--stroke);background:transparent;font-family:var(--font-ui);font-weight:500;
  font-size:.66rem;padding:.12rem .5rem;border-radius:6px;cursor:pointer;color:var(--p);
  text-transform:none;letter-spacing:0;
}
.par-reset:hover{background:var(--p);color:var(--on-accent)}
.stor-box{margin-top:.8rem;padding:.8rem 1rem;border-radius:6px;background:var(--paper-2);border:1px solid var(--stroke-2);font-size:.83rem}
.stor-line{display:flex;justify-content:space-between;align-items:center;gap:.6rem;flex-wrap:wrap;font-weight:500;padding:.15rem 0}
.stor-tag{
  font-family:var(--font-ui);font-size:.6rem;font-weight:600;text-transform:uppercase;letter-spacing:.13em;
  padding:.1rem .5rem;border-radius:6px;background:transparent;border:1px solid var(--y);color:var(--o);
}
.stor-tag.on{border-color:var(--g);color:var(--g)}
.prof{
  display:flex;align-items:center;gap:.5rem;padding:.55rem .8rem;border-radius:6px;margin-bottom:.3rem;
  background:transparent;border:1px solid var(--stroke-2);
}
.prof.cur{border-color:var(--p);background:color-mix(in srgb,var(--p) 5%,transparent)}
.pl-ic{display:inline-flex;align-items:center}
.pl-ic .oxi{width:14px;height:14px}
.pl-ic.spin .oxi{animation:sp 1.1s linear infinite}
@keyframes sp{to{transform:rotate(360deg)}}

/* ---------- 26. Prononciation ---------- */
.spk{padding:1.15rem 1.35rem}
.spk-head{display:flex;gap:.85rem;align-items:flex-start;margin-bottom:.8rem}
.spk-n{
  width:24px;height:24px;flex-shrink:0;border-radius:50%;display:grid;place-items:center;
  font-family:var(--font-ui);font-weight:600;font-size:.72rem;
  border:1px solid var(--stroke);color:var(--ink-3);transition:var(--t);
  font-variant-numeric:lining-nums;
}
.spk-n .oxi{width:12px;height:12px}
.spk-n.ok{border-color:var(--g);color:var(--g);background:color-mix(in srgb,var(--g) 9%,transparent)}
.spk-target{font-weight:500;font-size:1.05rem;line-height:1.6}
.spk-fr{color:var(--ink-3);font-size:.87rem;font-style:italic;margin-top:.15rem}

/* ---------- Accent de phrase — 02/08/2026 ----------
   TROIS niveaux visuels, parce qu'il y a trois niveaux réels : mot faible,
   temps fort, sommet du groupe. Deux ne suffiraient pas — on perdrait la
   distinction entre « accentué » et « le plus accentué », qui est justement ce
   qui donne son rythme à l'anglais.

   On ne touche NI aux lettres NI à la casse. Mettre le sommet en capitales
   serait la convention des manuels, mais l'apprenant doit lire le mot tel qu'il
   s'écrit : il le retrouvera dans les exercices et la dictée. */
.spk-target.ac-on{color:var(--ink-3)}                 /* les mots-outils reculent */
.spk-target .ac{font-weight:700;color:var(--ink)}     /* temps fort */
.spk-target .ac.nu{                                    /* sommet du groupe */
  box-shadow:inset 0 -0.38em 0 color-mix(in srgb,var(--p) 22%,transparent);
}
.ac-bar{display:flex;flex-wrap:wrap;align-items:center;gap:.6rem;margin-top:.7rem}
.ac-leg{font-size:.78rem;color:var(--ink-3);line-height:1.5}
.ac-leg .ac{font-weight:700;color:var(--ink)}
.ac-leg .ac.nu{box-shadow:inset 0 -0.38em 0 color-mix(in srgb,var(--p) 22%,transparent)}
.ac-leg .ac-off{color:var(--ink-3)}
/* Pas de gras ici : la couleur désigne uniquement la syllabe principale.
   Si le mot est aussi un temps fort, le gras vient de la couche .ac.
   +8 % suffit à créer une seconde saillance. line-height:1 empêche cette
   légère hausse de gonfler les lignes ou les cartes. */
.spk-target .ws,.ac-leg .ws{
  color:var(--word-stress);font-weight:inherit;font-size:1.08em;line-height:1;
}

.spk-tries{font-family:var(--font-ui);font-size:.68rem;font-weight:500;color:var(--ink-3);align-self:center;text-transform:uppercase;letter-spacing:.1em}
.spk-out{margin-top:.7rem;border-radius:0;font-size:.92rem;line-height:1.65}
.spk-out:empty{display:none}
.spk-out.live{padding:.75rem 1rem;background:color-mix(in srgb,var(--b) 7%,transparent);border-left:2px solid var(--b)}
.spk-out.good{padding:.75rem 1rem;background:color-mix(in srgb,var(--g) 8%,transparent);border-left:2px solid var(--g)}
.spk-out.bad{padding:.75rem 1rem;background:color-mix(in srgb,var(--r) 7%,transparent);border-left:2px solid var(--r)}
.spk-out.coach{padding:.95rem 1.1rem;background:color-mix(in srgb,var(--p) 5%,transparent);border-left:2px solid var(--p)}
.spk-score{font-family:var(--font-ui);font-weight:600;font-size:.88rem}
.spk-score .muted{font-family:var(--font);font-weight:400;color:var(--ink-3);font-size:.84rem;font-style:italic}
.spk-marked{margin:.5rem 0;font-size:1.04rem;line-height:1.95}
.w-ok{color:var(--ok);font-weight:500}
.w-ko{color:var(--ko);font-weight:500;text-decoration:underline wavy var(--ko) 1px;text-underline-offset:5px}
.spk-heard{font-size:.84rem;color:var(--ink-3);font-style:italic}
.spk-hint{font-size:.86rem;color:var(--ink-2);margin-top:.4rem}
.spk-escape{
  margin-top:.7rem;padding-top:.7rem;border-top:1px solid var(--stroke-2);
  display:flex;gap:.6rem;align-items:center;flex-wrap:wrap;font-size:.88rem;
}
.coach-head{font-family:var(--font-ui);font-weight:600;font-size:.68rem;text-transform:uppercase;letter-spacing:.15em;color:var(--p);margin-bottom:.5rem}
.coach-body{line-height:1.78}
.listening{display:flex;align-items:center;gap:.6rem;font-weight:500}
.wave{display:inline-flex;gap:2px;align-items:flex-end;height:16px}
.wave i{width:2px;background:var(--b);border-radius:0;animation:wv .95s ease-in-out infinite}
.wave i:nth-child(1){height:5px;animation-delay:0s} .wave i:nth-child(2){height:12px;animation-delay:.12s}
.wave i:nth-child(3){height:16px;animation-delay:.24s} .wave i:nth-child(4){height:10px;animation-delay:.36s}
.wave i:nth-child(5){height:6px;animation-delay:.48s}
@keyframes wv{0%,100%{transform:scaleY(.35)}50%{transform:scaleY(1)}}

/* ---------- 27. Discussion ---------- */
.live-stage{padding:2.6rem 1.4rem 1.7rem;text-align:center;border-radius:var(--radius)}
.orb-wrap{position:relative;width:150px;height:150px;margin:0 auto 1.3rem;display:grid;place-items:center}
.orb{
  width:96px;height:96px;border-radius:50%;display:grid;place-items:center;
  position:relative;z-index:2;color:var(--paper);
  background:var(--p);border:1px solid var(--p);
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--paper) 35%,transparent);
  transition:var(--t);
}
.orb .oxi{width:30px;height:30px;stroke-width:1.3}
.orb.connecting{animation:tick 1.1s infinite}
.orb.listening{background:var(--g);border-color:var(--g)}
.orb.talking{background:var(--o);border-color:var(--o);animation:breathe 1.9s ease-in-out infinite}
@keyframes breathe{0%,100%{transform:scale(1)}50%{transform:scale(1.055)}}
.orb-ring{position:absolute;inset:0;border-radius:50%;border:1px solid var(--a);opacity:.4;transition:transform .12s ease-out;pointer-events:none}
.live-status{font-family:var(--font-d);font-weight:500;font-size:1.18rem;letter-spacing:-.015em}
.live-meta{
  color:var(--ink-3);font-family:var(--font-ui);font-size:.68rem;font-weight:500;
  margin-top:.4rem;min-height:1.2em;text-transform:uppercase;letter-spacing:.13em;
}
.transcript{max-height:380px;overflow-y:auto;display:flex;flex-direction:column;gap:.6rem;padding:.2rem}
.tl{
  position:relative;padding:.65rem .9rem;border-radius:4px;font-size:.94rem;line-height:1.62;max-width:88%;
}
.tl-who{
  display:block;font-family:var(--font-ui);font-size:.58rem;font-weight:600;
  text-transform:uppercase;letter-spacing:.16em;opacity:.55;margin-bottom:.25rem;
}
.tl.user{align-self:flex-end;background:var(--p);color:var(--on-accent);border-bottom-right-radius:1px}
html[data-theme="dark"] .tl.user{color:#14151C}
.tl.bot{align-self:flex-start;background:transparent;border:1px solid var(--stroke);border-bottom-left-radius:1px}
.tl.partial{opacity:.6;font-style:italic}
.tl-say{position:absolute;right:-28px;top:50%;transform:translateY(-50%);border:0;background:transparent;cursor:pointer;opacity:.3;transition:var(--t);color:var(--ink-2)}
.tl-say .oxi{width:14px;height:14px}
.tl:hover .tl-say{opacity:1;color:var(--p)}

/* ---------- 28. Divers ---------- */
.empty{text-align:center;padding:4rem 1rem;color:var(--ink-3);font-style:italic}
.empty .e{display:block;margin:0 auto .9rem;color:var(--ink-3);opacity:.5}
.empty .e .oxi{width:34px;height:34px;stroke-width:1.2}
.fab{position:fixed;bottom:1.4rem;left:1.4rem;z-index:70;display:flex;flex-direction:column;gap:.4rem}
.fab .icon-btn{background:var(--surface);box-shadow:var(--shadow)}
kbd{
  background:var(--paper-2);border:1px solid var(--stroke);border-bottom-width:2px;border-radius:var(--radius-sm);
  padding:.08rem .35rem;font-family:var(--font-m);font-size:.74rem;font-weight:500;
}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}
/* (pied de page retire) */

/* ---------- 29. Mouvement ---------- */

/* 29.1 Révélation au défilement, en cascade */
[data-reveal]{opacity:0;transform:translateY(14px)}
[data-reveal].shown{
  opacity:1;transform:none;
  transition:opacity .68s cubic-bezier(.22,1,.36,1) var(--rd,0ms), transform .68s cubic-bezier(.22,1,.36,1) var(--rd,0ms);
}

/* 29.2 « Encrage » : le texte se pose ligne à ligne, comme une composition
   qui sèche. Le décalage --i est posé par oxford.js avant le premier rendu. */
@keyframes inkIn{
  from{opacity:0;transform:translateY(7px);filter:blur(2px)}
  to{opacity:1;transform:none;filter:blur(0)}
}
.card .story-line,
.vocab-grid .word,
.ex-block .ex-item,
.transcript .tl{
  animation:inkIn .52s cubic-bezier(.22,1,.36,1) backwards;
  animation-delay:calc(var(--i,0) * 36ms);
}

/* 29.3 Filet de lecture — la progression dans la page en cours */
#ox-progress{
  position:fixed;top:0;left:0;height:2px;width:0;z-index:100;
  background:var(--p);opacity:0;pointer-events:none;
  transition:width .1s linear, opacity .3s;
}
#ox-progress.on{opacity:.9}

/* 29.4 Anneau de progression — la couleur suit le thème, pas un dégradé figé */
.ring svg circle:nth-of-type(1){stroke:var(--stroke)}
.ring svg circle:nth-of-type(2){stroke:var(--p)}

/* 29.5 Numérotation des lignes du texte, dans la marge — édition d'étude */
.card{counter-reset:sl}
.card .story-line{counter-increment:sl}
/* (deplace en 30.2) */

/* 29.6 Le folio se décale quand le sceau « terminé » occupe le coin */
.chap:has(.done-badge) .n{right:2.7rem}

/* 29.7 Entrée du dictionnaire : le mot se souligne à la lecture */
.word .w{
  background-image:linear-gradient(currentColor,currentColor);
  background-repeat:no-repeat;background-position:0 100%;
  background-size:0 1px;transition:background-size var(--t);
  padding-bottom:1px;
}
.word:hover .w{background-size:100% 1px}

/* 29.8 Le bouton principal se remplit depuis la gauche */
.btn::after{
  content:'';position:absolute;inset:0;border-radius:inherit;
  background:currentColor;opacity:0;transition:opacity var(--t);pointer-events:none;
}
.btn:active::after{opacity:.09}

/* ==========================================================================
   30. ADAPTATIONS — systeme de points de rupture
   Remplace les 3 media queries precedentes (max-900 / max-520 / max-640),
   qui laissaient 1 366 lignes de CSS sans strategie mobile.

   Points de rupture :
     1120  fin de la marge exterieure
      900  bascule vers la barre d'onglets basse
      720  colonne unique, densite reduite
      560  petit telephone
      380  tres petit telephone
   ========================================================================== */

/* ---- 30.1 Fluidite generale (aucun media query : ca vaut partout) ---- */
main{
  max-width:1120px;margin:0 auto;
  padding:clamp(1rem,3.5vw,2rem) clamp(.9rem,3.5vw,1.15rem)
          calc(clamp(2.5rem,8vw,5rem) + var(--tabbar));
}
img,svg,canvas,video{max-width:100%;height:auto}
pre,code,.mono{overflow-x:auto;word-break:break-word}
table{display:block;max-width:100%;overflow-x:auto}

/* Zones tactiles : 44 px est le minimum utilisable au doigt.
   ATTENTION — la technique classique du pseudo-element etendu est ICI
   INAPPLICABLE : ::after est deja pris sur .icon-btn (halo), .tab et .filt
   (soulignement actif), .grade (remplissage) et .nav-btn (soulignement).
   On agrandit donc la cible par la taille reelle, ce qui ne collisionne rien. */
@media (hover:none) and (pointer:coarse){
  .icon-btn{min-width:44px;min-height:44px}
  .btn,.btn.sm{min-height:44px;padding-top:.6rem;padding-bottom:.6rem}
  .nav-btn,.tab{min-height:44px;padding-top:.7rem;padding-bottom:.7rem}
  .filt,.grade{min-height:40px;padding-top:.55rem;padding-bottom:.55rem}
  /* la puce est un libelle, pas une commande : elle reste petite */
}

/* ---- 30.2 Grand ecran : numerotation des lignes dans la marge ---- */
@media (min-width:880px){
  .card .story-line{padding-left:2.9rem}
  .card .story-line::after{
    content:counter(sl);position:absolute;left:.5rem;top:.78rem;
    font-family:var(--font-ui);font-size:.63rem;font-weight:500;
    font-variant-numeric:tabular-nums;color:var(--ink-3);
    opacity:0;transition:opacity var(--t);
  }
  .card:hover .story-line::after{opacity:.5}
  .card .story-line.now::after{opacity:.9;color:var(--a)}
}

/* ---- 30.3 Tablette ---- */
@media (max-width:1024px){
  .hero{padding:2rem 1.8rem;gap:2rem}
  .chap-grid{grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:.9rem}
  .mm-canvas{height:520px}
}

/* ---- 30.4 Bascule mobile : la barre d'onglets remplace la nav d'en-tete ---- */
@media (max-width:900px){
  :root{--tabbar:calc(58px + env(safe-area-inset-bottom,0px))}

  header{padding:.45rem .8rem;gap:.6rem}
  header > nav#nav{display:none}          /* remplacee par #tabbar */
  .brand .mot{width:96px;height:23px}       /* 23 × 4,142 */
  .marque-portail img{height:30px}          /* le fil doit tenir avec le menu */
  .hdr-tools{gap:.25rem}

  .hero{grid-template-columns:1fr;padding:1.6rem 1.3rem;gap:1.5rem}
  .ring{width:132px;height:132px}

  .feature-grid{grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}
  .chap-grid{grid-template-columns:repeat(auto-fill,minmax(230px,1fr))}
  .card,.ex-block{padding:1.2rem 1.1rem}
  .lesson-head{padding:1.4rem 1.2rem 1.2rem}
  .mm-canvas{height:440px}

  /* le bouton flottant remonte au-dessus de la barre d'onglets */
  .fab{bottom:calc(var(--tabbar) + .8rem);left:.9rem;flex-direction:row}
  #toasts{bottom:calc(var(--tabbar) + .8rem);right:.8rem;left:.8rem;align-items:stretch}
  .toast{max-width:100%}
}

/* ---- 30.5 Telephone ---- */
@media (max-width:720px){
  body{font-size:16px}
  .hero{padding:1.3rem 1.05rem}
  .hero p{font-size:1rem}
  .hero-cta{gap:.45rem}
  .hero-cta .btn{flex:1 1 auto;justify-content:center}

  .feature-grid,.chap-grid,.vocab-grid,.quiz-opts,.el-models{grid-template-columns:1fr}
  .stat-grid{grid-template-columns:repeat(2,1fr)}
  .badges{grid-template-columns:repeat(auto-fill,minmax(120px,1fr))}
  .eng-grid,.el-grid{grid-template-columns:repeat(auto-fit,minmax(120px,1fr))}
  .axes{grid-template-columns:1fr}
  .mini-stats{grid-template-columns:repeat(3,1fr)}

  .flashcard{height:260px}
  .mm-canvas{height:360px}
  .orb-wrap{width:120px;height:120px}
  .transcript{max-height:52vh}

  /* Les onglets de lecon debordent : on les fait defiler, avec accroche */
  .tabs{scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch}
  .tab{scroll-snap-align:start;font-size:.78rem;padding:.6rem .8rem}

  /* Le folio geant des cartes de chapitre ecrase le titre sur petit ecran */
  /* Réécrit le 06/08/2026 avec le passage du titre sur la ligne de l'icône.
     L'ancienne règle posait ici `padding-right:2.2rem` et `font-size:1.02rem` :
     le padding n'a plus de sens sur le titre (il est passé sur .chap-head, qui
     seul connaît la place du folio), et 1.02rem AUGMENTAIT le titre par rapport
     au .95rem de bureau — dans la colonne la plus étroite du site. À l'envers. */
  .chap-head{padding-right:2.9rem;gap:.45rem}
  .chap:has(.done-badge) .chap-head{padding-right:4.1rem}
  .chap h3{font-size:.9rem;padding:.24rem .5rem}
  .chap .n{font-size:2.3rem;top:.25rem;right:.7rem}
}

/* ---- 30.6 Petit telephone ---- */
@media (max-width:560px){
  .stat-grid{grid-template-columns:1fr}
  .flashcard{height:230px}
  .hero h2{font-size:clamp(1.75rem,8.5vw,2.3rem)}
  .page-head h2{font-size:clamp(1.55rem,7.5vw,2rem)}
  .chips{gap:.3rem}
  .chip{font-size:.66rem;padding:.2rem .5rem}
  .ex-q{min-width:0}
  .ex-block input:not(.inline),.ex-block select{min-width:0;width:100%}
  main{padding-left:.75rem;padding-right:.75rem}
}

@media (max-width:380px){
  .mini-stats{grid-template-columns:1fr;gap:.4rem}
  .mini{border-right:0;border-bottom:1px solid var(--stroke-2);padding-bottom:.4rem}
  .mini:last-child{border-bottom:0}
  .hero-cta .btn{width:100%}
}

/* ---- 30.7 Perf : les effets lourds sautent sur petit ecran ----
   Le halo conique tourne en continu avec un blur de 90 px. Sur un mobile
   d'entree de gamme c'est le premier poste de consommation. Non mesure sur
   appareil reel — a verifier avant de considerer ce reglage comme bon. */
@media (max-width:700px){
  #bg::after{animation:none;opacity:.06;filter:blur(60px)}
  html[data-theme="dark"] #bg::after{opacity:.16}
  .blob{animation:none;filter:blur(70px)}
  .blob:nth-child(2),.blob:nth-child(4){display:none}
  #stars{display:none}                 /* glyphes flottants : pur decor */
  header{backdrop-filter:none;-webkit-backdrop-filter:none;background:var(--surface)}
}

/* ---- 30.8 Barre d'onglets basse ---- */
/* Masque par defaut : sans cette ligne, la barre s'affiche en bloc normal en
   bas de page sur grand ecran.
   La feuille « Plus » et son voile ont ete retires le 30/08/2026 en meme temps
   que leurs regles : la barre porte desormais les cinq memes entrees que
   l'en-tete, il n'y a plus rien a loger ailleurs. */
#tabbar{display:none}
@media (max-width:900px){
  #tabbar{
    /* CINQ colonnes, plus six. Laisser repeat(6,1fr) apres le retrait du
       bouton « Plus » aurait garde une sixieme colonne vide : la barre
       paraissait decalee vers la gauche, sans qu'aucune regle ne soit
       visiblement fausse. */
    display:grid;grid-template-columns:repeat(5,1fr);
    position:fixed;left:0;right:0;bottom:0;z-index:80;
    background:color-mix(in srgb,var(--surface) 92%,transparent);
    backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);
    border-top:1px solid var(--stroke);
    padding-bottom:env(safe-area-inset-bottom,0px);
  }
  #tabbar .tb{
    appearance:none;border:0;background:transparent;cursor:pointer;
    display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.15rem;
    padding:.42rem .1rem .38rem;min-height:58px;
    font-family:var(--font-ui);font-size:.58rem;font-weight:600;
    letter-spacing:.02em;color:var(--ink-3);
    transition:color var(--t);
    -webkit-tap-highlight-color:transparent;
  }
  #tabbar .tb .oxi,#tabbar .tb .ic{width:20px;height:20px;font-size:18px;line-height:1;transition:transform .38s var(--spring)}
  #tabbar .tb.on{color:var(--p)}
  #tabbar .tb.on .ic{transform:translateY(-2px) scale(1.1)}
  #tabbar .tb:active .ic{transform:scale(.9)}
  /* pastille active */
  #tabbar .tb.on::before{
    content:'';position:absolute;top:0;width:26px;height:2.5px;border-radius:0 0 99px 99px;
    background:var(--p);
  }
  #tabbar .tb{position:relative}

}

/* ---- 30.9 Mouvement reduit ---- */
@media (prefers-reduced-motion:reduce){
  *{animation-duration:.01ms !important;animation-iteration-count:1 !important;transition-duration:.01ms !important}
  [data-reveal]{opacity:1;transform:none}
  #bg::after,.blob{animation:none}
  #moresheet{transition:none}
}

/* ---- 30.10 Impression ---- */
@media print{
  header,nav,#tabbar,#moresheet,#morescrim,.tabs,.fab,#bg,#stars,#toasts,.preload-pill{display:none !important}
  body{background:#fff;color:#000;font-size:11pt}
  main{padding-bottom:0}
  .card,.glass{box-shadow:none;border:1px solid #ccc;background:#fff}
}

/* ---------- 30. Complétion : trois axes, écoute, exercices ----------
   Un chapitre n'est complet que si écoute, exercices et oral atteignent
   tous les trois le seuil. Le CSS ci-dessous rend cette règle visible :
   trois jauges, un repère au seuil, un verdict explicite. */
.axes{
  display:grid;grid-template-columns:repeat(3,1fr);gap:1rem 1.4rem;
  margin-top:1.3rem;padding-top:1.1rem;border-top:1px solid var(--stroke-2);
}
/* La règle mobile « .axes{grid-template-columns:1fr} » du bloc
   @media (max-width:720px) plus haut n'a jamais pris effet : elle est écrite
   AVANT cette règle-ci, qui la recouvrait. Sur téléphone, « Lire à voix
   haute » était écrasé contre le bord de la carte (09/10/2026). */
@media (max-width:720px){ .axes{grid-template-columns:1fr;gap:.8rem} }
.axes .axis-verdict{
  grid-column:1/-1;font-family:var(--font-ui);font-size:.74rem;font-weight:500;
  color:var(--ink-3);letter-spacing:.01em;
}
.axes.ok .axis-verdict{color:var(--ok);font-weight:600}
.axis-top{
  display:flex;justify-content:space-between;align-items:baseline;gap:.5rem;
  font-family:var(--font-ui);font-size:.63rem;font-weight:600;
  letter-spacing:.16em;text-transform:uppercase;color:var(--ink-3);
  margin-bottom:.42rem;
}
.axis-top b{font-size:.82rem;letter-spacing:0;color:var(--ink-2);font-variant-numeric:tabular-nums}
.axis.ok .axis-top,.axis.ok .axis-top b{color:var(--ok)}
.axis .bar{position:relative;overflow:visible}
.axis .bar i{background:var(--p)}
.axis.ok .bar i{background:var(--ok)}
/* Repère du seuil : une graduation, pas une décoration */
.axis .bar u{
  position:absolute;top:-3px;bottom:-3px;width:1px;
  background:var(--ink-3);opacity:.55;text-decoration:none;
}

/* Bandeau de compteur en tête d'onglet */
.axis-bar{
  display:flex;align-items:center;gap:.8rem;flex-wrap:wrap;
  padding:.75rem 1.1rem;border-radius:var(--radius);margin-bottom:1.15rem;
}
.axis-l{
  font-family:var(--font-ui);font-size:.66rem;font-weight:600;
  letter-spacing:.16em;text-transform:uppercase;color:var(--ink-3);
}
.score-pill.ok{border-color:var(--ok);color:var(--ok)}

/* Phrase du texte : numéro à gauche, coche une fois entendue en entier */
.story-line{padding-left:2.5rem}
.line-mark{
  position:absolute;left:.55rem;top:.72rem;
  width:1.25rem;height:1.25rem;border-radius:50%;
  display:grid;place-items:center;
  font-family:var(--font-ui);font-size:.62rem;font-weight:600;
  color:var(--ink-3);border:1px solid var(--stroke-2);
  transition:var(--t);font-variant-numeric:tabular-nums;
}
.story-line.heard .line-mark{
  color:var(--ok);border-color:var(--ok);
  background:color-mix(in srgb,var(--ok) 10%,transparent);
}
.story-line.heard .en{color:var(--ink-2)}
/* La lettrine ne doit pas se glisser sous la pastille */
.card .story-line:first-of-type .en::first-letter{margin-top:.02em}

/* Exercice déjà validé */
.ex-block.done{border-left:2px solid var(--ok)}
.ex-tick{
  display:inline-grid;place-items:center;width:1.15rem;height:1.15rem;
  margin-right:.45rem;border-radius:50%;vertical-align:.02em;
  font-size:.7rem;color:var(--ok);border:1px solid var(--ok);
  background:color-mix(in srgb,var(--ok) 10%,transparent);
}
.ex-block.done .ex-kind{color:var(--ok)}

/* Liste des chapitres qui bloquent une demande d'examen */
ul.blockers{list-style:none;margin:.6rem 0 0;padding:0}
ul.blockers li{
  display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap;
  padding:.42rem 0;border-bottom:1px solid var(--stroke-2);font-size:.88rem;
}
ul.blockers li:last-child{border-bottom:0}
ul.blockers a{color:var(--p);text-decoration:none;font-weight:500}
ul.blockers a:hover{text-decoration:underline}
ul.blockers span{
  font-family:var(--font-ui);font-size:.72rem;font-weight:500;color:var(--ink-3);
  font-variant-numeric:tabular-nums;
}

/* ---------- 31. Verrou séquentiel ----------
   Un chapitre verrouillé doit rester lisible : on l'estompe, on ne le cache
   pas. L'élève doit voir où il va, pas seulement qu'on lui refuse l'entrée. */
.chap.locked{opacity:.5;filter:saturate(.35)}
.chap.locked:hover{transform:none;opacity:.62}
.chap.locked .goals{opacity:.7}
.lock-badge{
  position:absolute;top:.7rem;right:.85rem;z-index:2;
  font-size:.9rem;line-height:1;opacity:.75;
}
.chap.locked .done-badge{display:none}
.filt.locked{opacity:.45}
.filt.locked:hover{border-color:var(--stroke);color:var(--ink-2)}
.btn.locked,.btn.locked:disabled{
  opacity:1;background:transparent;color:var(--ink-3);
  border:1px dashed var(--stroke);cursor:not-allowed;
  font-size:.76rem;font-weight:500;letter-spacing:0;text-transform:none;
  max-width:min(100%,30rem);white-space:normal;text-align:left;line-height:1.4;
}

/* ==========================================================================
   32. DIRECTION A — ajustements de composants
   Le remplacement des jetons fait 80 % du travail. Ce qui suit corrige les
   endroits ou l'ancienne identite « Oxford » etait ecrite en dur dans une
   regle plutot que dans une variable.
   ========================================================================== */

/* 32.1 Cartes de chapitre : le liseré de 3 px devient une carte pleine.
   La couleur ne travaillait que sur le bord — elle porte maintenant
   l'icone, le folio, la barre et le halo de survol. */
.chap{
  border-top:1px solid var(--stroke);
  border-left:3px solid var(--c,var(--p));
  box-shadow:var(--elev-in), var(--shadow);
}
.chap:hover{transform:translateY(-4px);box-shadow:var(--elev-in), var(--shadow-lift);border-color:var(--c,var(--p))}
.chap .ic{
  display:grid;place-items:center;width:34px;height:34px;border-radius:var(--radius-sm);
  background:color-mix(in oklab, var(--c,var(--p)) calc(100% - var(--tint)), var(--tint-base));
  color:var(--c,var(--p));
  transition:transform .5s var(--spring);
}
.chap:hover .ic{animation:pop .55s var(--spring)}
@keyframes pop{38%{transform:scale(1.18) rotate(-9deg)}72%{transform:scale(.98) rotate(2deg)}}
.chap .n{opacity:.18;font-weight:700}
.chap:hover .n{opacity:.38}
.bar{position:relative;height:6px;border-radius:99px;background:var(--surface-2);cursor:pointer}
.bar i{display:block;height:100%;border-radius:99px;background:linear-gradient(90deg,var(--c,var(--p)),color-mix(in oklab,var(--c,var(--p)) 55%,var(--tint-base)))}
.bar-scrubber{
  position:absolute;top:50%;
  left:clamp(5px, var(--pct, 0%), calc(100% - 5px));
  transform:translate(-50%,-50%);
  width:12px;height:12px;border-radius:50%;
  background:var(--c,var(--p));
  box-shadow:0 0 0 2px var(--surface), 0 1px 4px rgba(0,0,0,.35);
  transition:transform .2s cubic-bezier(.2,.9,.3,1.2),box-shadow .2s;
  pointer-events:none;
}
.bar:hover .bar-scrubber{
  transform:translate(-50%,-50%) scale(1.3);
  box-shadow:0 0 0 3px color-mix(in oklab, var(--c,var(--p)) 30%, transparent), 0 2px 6px rgba(0,0,0,.45);
}

/* 32.2 Grille de fonctionnalites : colonnes de journal -> cartes */
.feature-grid{
  border:0;background:transparent;gap:.85rem;
  grid-template-columns:repeat(auto-fit,minmax(230px,1fr));
}
.feature{
  border:1px solid var(--stroke);border-radius:var(--radius);
  background:var(--surface);box-shadow:var(--elev-in);
  transition:transform .38s var(--spring),box-shadow var(--t),border-color var(--t);
}
.feature::after{display:none}
.feature:hover{
  background:var(--surface);transform:translateY(-4px);
  border-color:var(--p);box-shadow:var(--elev-in), var(--shadow-lift);
}
.feature .ic{
  display:grid;place-items:center;width:34px;height:34px;border-radius:var(--radius-sm);
  background:color-mix(in oklab, var(--p) calc(100% - var(--tint)), var(--tint-base));
  color:var(--p);
}
.feature:hover .ic{transform:none;animation:pop .55s var(--spring)}

/* 32.3 Puces : formes arrondies. Les onglets sont deja definis plus haut. */
.chip{border-radius:99px;padding:.24rem .68rem;font-weight:600}

/* 32.4 En-tete : le double filet typographique n'a plus lieu d'etre */
header::after{display:none}
/* La tuile degradee indigo/violet qui portait le 🎓 vivait ici. Elle est
   partie avec lui le 11/08/2026 — le mot-symbole est desormais la marque. */

/* 32.5 Pastille de serie */
.streak-chip{
  border-radius:99px;border:1px solid transparent;
  background:color-mix(in oklab, var(--o) calc(100% - var(--tint)), var(--tint-base));
  color:var(--o);
}
html[data-theme="dark"] .streak-chip{color:var(--o)}

/* 32.6 Boutons d'icone */
.icon-btn{border-radius:var(--radius-sm);width:36px;height:36px}
.icon-btn:hover{background:color-mix(in oklab, var(--p) calc(100% - var(--tint)), var(--tint-base))}

/* 32.7 Focus visible — plus epais et arrondi, il doit se voir au clavier */
:focus-visible{outline:2px solid var(--p);outline-offset:2px;border-radius:6px}

/* 32.8 Les boutons de la barre d'onglets portent .nav-btn (pour qu'app.js les
   câble seul) : on neutralise le soulignement hérité, qui n'a pas de sens ici. */
#tabbar .nav-btn::after,#moresheet .nav-btn::after{content:none;display:none}
#tabbar .nav-btn,#moresheet .nav-btn{font-family:var(--font-ui)}

/* ==========================================================================
   33. COULEUR ET RELIEF
   --------------------------------------------------------------------------
   Constat sur les captures du 27/07 : le systeme etait juste, mais la couleur
   ne travaillait qu'a UN endroit — les dix icones de fonctionnalite etaient
   toutes indigo, les puces toutes grises, les statistiques toutes noires.
   Une palette de six accents dont un seul est employe rend un ecran monotone.

   Regle appliquee ici : tout ensemble d'elements comparables (fonctionnalites,
   statistiques, badges, filtres de chapitre) parcourt les huit accents en
   rotation. La couleur devient un reperage, pas une decoration.
   ========================================================================== */

/* ---- 33.1 Rotation d'accent : un seul mecanisme, reutilise partout ---- */
.feature-grid > :nth-child(8n+1),.mini-stats > :nth-child(8n+1),
.stat-grid > :nth-child(8n+1),.badges > :nth-child(8n+1){--c:var(--acc-1)}
.feature-grid > :nth-child(8n+2),.mini-stats > :nth-child(8n+2),
.stat-grid > :nth-child(8n+2),.badges > :nth-child(8n+2){--c:var(--acc-2)}
.feature-grid > :nth-child(8n+3),.mini-stats > :nth-child(8n+3),
.stat-grid > :nth-child(8n+3),.badges > :nth-child(8n+3){--c:var(--acc-3)}
.feature-grid > :nth-child(8n+4),.mini-stats > :nth-child(8n+4),
.stat-grid > :nth-child(8n+4),.badges > :nth-child(8n+4){--c:var(--acc-4)}
.feature-grid > :nth-child(8n+5),.mini-stats > :nth-child(8n+5),
.stat-grid > :nth-child(8n+5),.badges > :nth-child(8n+5){--c:var(--acc-5)}
.feature-grid > :nth-child(8n+6),.mini-stats > :nth-child(8n+6),
.stat-grid > :nth-child(8n+6),.badges > :nth-child(8n+6){--c:var(--acc-6)}
.feature-grid > :nth-child(8n+7),.mini-stats > :nth-child(8n+7),
.stat-grid > :nth-child(8n+7),.badges > :nth-child(8n+7){--c:var(--acc-7)}
.feature-grid > :nth-child(8n+8),.mini-stats > :nth-child(8n+8),
.stat-grid > :nth-child(8n+8),.badges > :nth-child(8n+8){--c:var(--acc-8)}

/* raccourci : le fond teinte de l'accent courant */
.feature,.chap,.stat,.badge,.lesson-head,.axis{--c-soft:color-mix(in oklab,var(--c,var(--p)) calc(100% - var(--tint)),var(--tint-base))}

/* ---- 33.2 Fonctionnalites : chacune sa teinte ---- */
.feature .ic{background:var(--c-soft);color:var(--c,var(--p))}
.feature:hover{border-color:var(--c,var(--p))}
.feature h3{transition:color var(--t)}
.feature:hover h3{color:var(--c,var(--p))}

/* Discussion en direct : avant-première réservée aux administrateurs.
   L'état doit se lire comme une annonce, jamais comme une carte cliquable. */
.feature.feature-soon{
  cursor:default;
  background:var(--surface-2);
  box-shadow:none;
}
.feature.feature-soon .ic,
.feature.feature-soon h3,
.feature.feature-soon p{opacity:.58}
.feature.feature-soon:hover{
  transform:none;
  background:var(--surface-2);
  border-color:var(--stroke);
  box-shadow:none;
}
.feature.feature-soon:hover .ic{transform:none;animation:none}
.feature.feature-soon:hover h3{color:var(--ink)}
.feature-soon-badge{
  position:absolute;
  top:1rem;
  right:1rem;
  z-index:1;
  padding:.22rem .58rem;
  border:1px solid var(--o);
  border-radius:999px;
  background:color-mix(in srgb,var(--o) 9%,var(--surface));
  color:var(--o);
  font-family:var(--font-ui);
  font-size:.58rem;
  font-weight:800;
  line-height:1.3;
  letter-spacing:.08em;
  text-transform:uppercase;
}

/* ---- 33.3 Statistiques : le chiffre porte la couleur, pas le libelle ---- */
.mini b,.stat .k{color:var(--c,var(--p))}
.stat{border-left:3px solid var(--c,var(--p));background:var(--c-soft)}
.badge{border-color:color-mix(in oklab,var(--c,var(--p)) 45%,transparent)}
.badge.on{background:var(--c-soft);color:var(--c,var(--p));border-color:var(--c,var(--p))}

/* ---- 33.4 Puces de notion : elles suivent l'accent du chapitre ----
   C'etait le plus visible sur ta capture 1 : trois puces grises sous un
   titre indigo, alors que la maquette les teintait. */
.lesson-head .chip,.chap .chip{
  background:var(--c-soft);
  color:var(--c,var(--p));
  border-color:color-mix(in oklab,var(--c,var(--p)) 28%,transparent);
  font-weight:600;
}
html[data-theme="dark"] .lesson-head .chip,html[data-theme="dark"] .chap .chip{background:var(--c-soft)}

/* ---- 33.5 En-tete de lecon : le lavis d'accent etait a 12 %, invisible ---- */
.lesson-head{
  border-top:0;border-left:3px solid var(--c,var(--p));
  background:
    radial-gradient(680px 240px at 100% -20%, color-mix(in oklab,var(--c,var(--p)) 16%,transparent), transparent 68%),
    var(--surface);
}
.lesson-head::after{
  width:280px;height:280px;
  background:radial-gradient(circle at 100% 0%, color-mix(in oklab,var(--c,var(--p)) 22%,transparent), transparent 72%);
}

/* ---- 33.6 Les trois axes de completion : une couleur par axe ---- */
.axes > .axis:nth-of-type(1){--c:var(--acc-2)}   /* ecoute    */
.axes > .axis:nth-of-type(2){--c:var(--acc-6)}   /* exercices */
.axes > .axis:nth-of-type(3){--c:var(--acc-5)}   /* oral      */
.axis .bar i{background:linear-gradient(90deg,var(--c,var(--p)),color-mix(in oklab,var(--c,var(--p)) 55%,var(--tint-base)))}
.axis.ok .bar i{background:linear-gradient(90deg,var(--ok),color-mix(in oklab,var(--ok) 55%,var(--tint-base)))}

/* ---- 33.7 Flashcards : la carte etait blanche sur blanc ---- */
.fc-face{
  background:
    radial-gradient(420px 200px at 15% 0%, color-mix(in oklab,var(--acc-6) 12%,transparent), transparent 70%),
    radial-gradient(420px 200px at 90% 100%, color-mix(in oklab,var(--acc-1) 11%,transparent), transparent 70%),
    var(--surface);
}
.fc-face::after{display:none}    /* le double filet de reliure, encore */
.fc-face.back{
  background:linear-gradient(140deg,var(--acc-1),var(--acc-6) 60%,var(--acc-4));
  color:var(--on-accent);border-color:transparent;
}
.fc-face.back .big,.fc-face.back *{color:inherit}

/* ---- 33.8 Filtres de chapitre : ils reprennent l'accent du chapitre ---- */
.filt:nth-child(8n+1){--c:var(--acc-1)} .filt:nth-child(8n+2){--c:var(--acc-2)}
.filt:nth-child(8n+3){--c:var(--acc-3)} .filt:nth-child(8n+4){--c:var(--acc-4)}
.filt:nth-child(8n+5){--c:var(--acc-5)} .filt:nth-child(8n+6){--c:var(--acc-6)}
.filt:nth-child(8n+7){--c:var(--acc-7)} .filt:nth-child(8n+8){--c:var(--acc-8)}
.filt.on{
  color:var(--c,var(--p));border-color:var(--c,var(--p));
  background:color-mix(in oklab,var(--c,var(--p)) calc(100% - var(--tint)),var(--tint-base));
}
.filt:hover:not(.locked){border-color:var(--c,var(--p));color:var(--c,var(--p))}

/* ---- 33.9 Relief au survol : le lavis interne passe de 7 % a 11 % ---- */
.chap::before,.feature::before{
  content:'';position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  opacity:0;transition:opacity var(--t);display:block;
  background:radial-gradient(360px 140px at 50% -10%, var(--c,var(--p)), transparent 70%);
}
.chap:hover::before,.feature:hover::before{opacity:.11}

/* ==========================================================================
   34. CORRECTIFS MOBILE — mesures au banc a 320 / 360 / 375 / 390 / 414 / 430
   ========================================================================== */

/* ---- 34.1 En-tete : il debordait de 37 px a 320 px ----
   .brand et .hdr-tools etaient tous deux en flex-shrink:0 : rien ne pouvait
   ceder, donc le bouton de theme sortait de l'ecran. */
@media (max-width:900px){
  header{gap:.4rem}
  .brand{flex-shrink:1;min-width:0}          /* min-width:0 : sans lui, un enfant
                                                flex refuse de passer sous sa
                                                largeur de contenu */
  /* Un mot-symbole ne s'abrege pas : il n'y a pas de « ENGLISH 2… ». A 320 px
     il cede donc de la largeur au lieu d'etre tronque, et `contain` le fait
     retrecir entier plutot que de le rogner. */
  .brand .mot{flex-shrink:1;min-width:0}
  .hdr-tools{flex-shrink:0;gap:.2rem}
  .icon-btn{width:34px;height:34px}
}
@media (max-width:400px){
  .streak-chip{padding:.24rem .45rem;font-size:.7rem}
  .brand .mot{width:83px;height:20px}       /* 20 × 4,142 */
  .marque-portail img{height:26px}
  .fil-marque{gap:.35rem}
  header{padding:.4rem .55rem}
}
@media (max-width:340px){
  .streak-chip{display:none}                 /* l'information reste dans Progres */
}

/* ---- 34.2 Carte de progression : 395 px de haut sur un ecran de 844 ----
   Elle consommait la moitie du premier ecran avant tout contenu utile. */
@media (max-width:900px){
  .hero-card{padding:1.1rem .9rem}
  .hero-card::after{inset:4px}
  .ring{width:104px;height:104px;margin-bottom:.5rem}
  .ring .val{font-size:1.5rem}
  .mini-stats{margin-top:.6rem;padding-top:.6rem}
  .mini b{font-size:1.15rem}
  .mini span{font-size:.54rem;letter-spacing:.12em}
  .hero-card > div[style*="font-weight"]{font-size:.56rem}
}

/* ---- 34.3 Boutons flottants : ils recouvraient le bouton « Reviser » ----
   Mesure a 390 px : chevauchement confirme avec .hero-cta. Les deux fonctions
   sont deja accessibles autrement — Flashcards est dans la barre d'onglets, et
   la liste des raccourcis clavier n'a aucun sens sur un ecran tactile. */
@media (max-width:900px){
  .fab{display:none}
}

/* ---- 34.4 Barre d'onglets : garde-fous ----
   #tabbar est un <nav> ; il heritait de overflow-x:auto et flex:1 de la regle
   d'element, desormais restreinte a « header nav ». On verrouille tout de meme. */
@media (max-width:900px){
  #tabbar{
    overflow:visible;flex:none;
    /* filet de securite si un ancetre venait a creer un contexte de
       transformation, ce qui casserait position:fixed */
    contain:none;
  }
  #tabbar .tb{padding-left:.05rem;padding-right:.05rem;min-width:0}
  #tabbar .tb{font-size:.55rem}
}
@media (max-width:340px){
  #tabbar .tb{font-size:.5rem}
}

/* ---- 34.5 Respiration : marges laterales egales et contenu vraiment plein ---- */
@media (max-width:720px){
  .hero{padding:1.15rem 1rem;gap:1.1rem}
  .hero h2{margin-top:.2rem}
  .hero p{font-size:.97rem;line-height:1.55;max-width:none}
  .hero-cta{margin-top:1.1rem;gap:.5rem}
  .hero-cta .btn{flex:1 1 calc(50% - .25rem);justify-content:center;white-space:nowrap}
  .hero-cta .btn:first-child{flex-basis:100%}
  .page-head{margin-bottom:1.4rem}
  .card,.ex-block,.panel,.glass{padding-left:1rem;padding-right:1rem}
}

/* ==========================================================================
   35. MODALES — debordement mesure de 55 px a 390 px
   --------------------------------------------------------------------------
   Cause : .modal-back est en `display:grid; place-items:center`. Avec
   justify-items:center, l'element ne s'etire pas, donc la colonne implicite
   est dimensionnee sur le CONTENU. Le `width:min(640px,100%)` de .modal
   resolvait alors son 100 % contre une largeur derivee de son propre
   contenu — reference circulaire, que le navigateur tranche en prenant
   max-content. Resultat : 424 px de large dans un ecran de 389.

   Correctif : une colonne explicite `minmax(0,1fr)`, contre laquelle le
   pourcentage a une reference stable.
   ========================================================================== */
.modal-back{grid-template-columns:minmax(0,1fr)}
.modal{max-width:100%;justify-self:center;min-width:0}

/* `min-width:auto` est la valeur par defaut des enfants flex et grid : ils
   refusent de passer sous leur largeur de contenu. Il faut l'annuler tout au
   long de la chaine, sinon un seul descendant suffit a repousser le conteneur. */
.modal-head,.modal-body,.modal-foot,.fld-row,.eng-grid,.el-grid,.el-models{min-width:0}
.modal-head h3{min-width:0;overflow-wrap:anywhere}
.fld-row > *{min-width:0}
.fld-row input,.fld-row select,.modal input,.modal select,.modal textarea{
  min-width:0;max-width:100%;
}
.fld-help,.warn-box,.eng-desc{overflow-wrap:anywhere}
.fld-help a{word-break:break-all}     /* les URL de cles d'API sont longues */

/* ---- 35.1 Sur telephone, la modale devient une feuille basse ----
   Centrer une boite de 88 vh sur un ecran de 844 px laisse deux bandes
   inutiles ; et le pouce n'atteint pas le haut de l'ecran. */
@media (max-width:560px){
  .modal-back{padding:0;place-items:end stretch;align-content:end}
  .modal{
    width:100%;max-width:100%;
    max-height:92dvh;                       /* dvh : tient compte de la barre
                                               d'adresse mobile, contrairement a vh */
    border-radius:var(--radius) var(--radius) 0 0;
    border-bottom:0;
    animation:sheetIn .38s cubic-bezier(.22,1,.36,1);
  }
  @keyframes sheetIn{from{transform:translateY(100%)}}

  /* poignee de prehension */
  .modal-head{padding:1rem 1.05rem .7rem;position:relative}
  .modal-head::before{
    content:'';position:absolute;top:.4rem;left:50%;transform:translateX(-50%);
    width:34px;height:3.5px;border-radius:99px;background:var(--stroke);
  }
  .modal-head h3{font-size:1.05rem}
  .modal-body{padding:1rem 1.05rem calc(1.1rem + env(safe-area-inset-bottom,0px))}
  .modal-foot{flex-wrap:wrap;margin-top:1.1rem}
  .modal-foot .btn{flex:1 1 auto;justify-content:center}

  .fld-lbl{margin-top:1.1rem}
  .eng-grid{grid-template-columns:repeat(auto-fit,minmax(104px,1fr));gap:.4rem}
  .eng{padding:.65rem .35rem;font-size:.9rem}
  .eng-ic{font-size:1.1rem}
  .el-grid,.el-models{grid-template-columns:1fr}
}
@media (max-width:380px){
  .eng-grid{grid-template-columns:1fr 1fr}
  .modal-body{padding-left:.85rem;padding-right:.85rem}
}

/* ==========================================================================
   36. CHAPITRE VERROUILLÉ — voile central
   --------------------------------------------------------------------------
   L'ancien traitement (opacity .5 + saturate .35 + cadenas de 14 px dans le
   coin) rendait le texte illisible sans pour autant signaler clairement le
   verrou. On inverse : la carte garde sa lisibilité, et un voile la recouvre
   avec un cadenas franc et la consigne exacte.
   ========================================================================== */
.chap.locked{opacity:1;filter:none}
.chap.locked:hover{transform:none;box-shadow:var(--elev-in),var(--shadow)}
.chap.locked .goals{opacity:1}
.chap.locked .done-badge,.lock-badge{display:none}

.lock-veil{
  position:absolute;inset:0;z-index:4;border-radius:inherit;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:.75rem;padding:1.1rem;text-align:center;
  background:color-mix(in srgb,var(--surface) 84%,transparent);
  backdrop-filter:blur(2.5px) saturate(.55);
  -webkit-backdrop-filter:blur(2.5px) saturate(.55);
  /* le clic doit continuer d'atteindre la carte : app.js affiche alors
     l'alerte détaillée et redirige vers le chapitre bloquant */
  pointer-events:none;
}
/* Repli si backdrop-filter n'est pas supporté : on opacifie le voile */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .lock-veil{background:color-mix(in srgb,var(--surface) 93%,transparent)}
}

.lock-ic{
  width:clamp(44px,17%,62px);height:auto;color:var(--lock-ic);
  filter:drop-shadow(0 4px 12px color-mix(in srgb,var(--lock-ic) 34%,transparent));
}
.lock-ic rect{fill:var(--lock-fill)}
.lock-ic circle{fill:var(--lock-ic)}       /* serrure : lisible sur le corps */
.lock-ic path{fill:none}                   /* l'anse reste un simple trait */
.chap.locked:hover .lock-ic{animation:lockShake .5s cubic-bezier(.36,.07,.19,.97)}
@keyframes lockShake{
  20%{transform:rotate(-7deg)} 45%{transform:rotate(6deg)}
  70%{transform:rotate(-3deg)} 100%{transform:none}
}

.lock-txt{
  margin:0;font-family:var(--font-ui);font-size:.83rem;line-height:1.45;
  font-weight:500;color:var(--ink-2);max-width:24ch;text-wrap:balance;
}
.lock-txt b{color:var(--lock-tx);font-weight:700}

/* ══════════════════════════════════════════════════════════════════════════
   PAYANT ≠ PAS ENCORE DÉBLOQUÉ — 30/08/2026
   Voir le commentaire de vChapters dans app.js. Deux verrous, deux mondes
   visuels : le cadenas moutarde pour ce qui s'ouvre en travaillant, l'étoile
   de la marque pour ce qui s'achète. Le premier promet un effort, le second
   une transaction — les confondre décourageait dans les deux sens.
   ══════════════════════════════════════════════════════════════════════════ */
.premium-ic{
  width:clamp(38px,15%,54px);height:auto;color:var(--p);
  filter:drop-shadow(0 4px 14px color-mix(in srgb,var(--p) 38%,transparent));
}
.chap.locked:hover .premium-ic{transform:scale(1.06);transition:transform .3s var(--t)}
/* Le voile payant tire vers l'accent plutôt que vers le gris : il invite,
   il ne barre pas. */
.lock-veil.premium{
  background:color-mix(in srgb,var(--surface) 82%,transparent);
}
.lock-veil.premium .lock-txt b{color:var(--p)}

/* Le reste à faire, sous la consigne du verrou séquentiel : c'est ce qui
   transforme « c'est fermé » en « voilà quoi faire ». */
.lock-sous{
  display:inline-block;margin-top:.25rem;
  font-size:.76rem;font-weight:600;color:var(--lock-tx);
}

/* Pastilles du parcours, sur l'accueil. */
.filt.premium{
  opacity:.72;
  border-color:color-mix(in srgb,var(--p) 34%,var(--stroke));
  color:var(--p);
}
.filt.premium:hover{opacity:1;border-color:var(--p);color:var(--p)}

@media (max-width:720px){
  .lock-ic{width:52px}
  .lock-txt{font-size:.86rem}
}

/* ==========================================================================
   37. RACCOURCI FLOTTANT « REPRENDRE »
   --------------------------------------------------------------------------
   Couleur : celle du chapitre vise (--c, pose par renderResume()).
   Le fond est l'accent ECLAIRCI DE 10 % vers le blanc, et le libelle est
   sombre. Mesure a l'appui : avec l'accent brut, l'indigo du mode clair ne
   donnait que 4.47 en blanc et 4.29 en sombre — aucun des deux n'atteignait
   4.5. Eclairci de 10 %, le pire des 16 cas (8 accents x 2 themes) remonte
   a 5.06. Une regle uniforme vaut mieux qu'une exception sur un accent.
   ========================================================================== */
#resume{
  position:fixed;right:1rem;bottom:calc(var(--tabbar) + 1.1rem);z-index:75;
  display:flex;align-items:center;gap:.32rem;
  animation:resumeIn .5s cubic-bezier(.22,1,.36,1) both;
}
#resume[hidden]{display:none}
@keyframes resumeIn{from{opacity:0;transform:translateY(16px) scale(.94)}}

.resume-go{
  display:flex;align-items:center;gap:.55rem;min-width:0;
  border:0;cursor:pointer;font:inherit;text-align:left;
  padding:.45rem 1rem .45rem .45rem;border-radius:99px;
  background:color-mix(in oklab, var(--c,var(--p)) 90%, #FFFFFF);
  color:#0E0F14;
  box-shadow:0 8px 24px -10px var(--c,var(--p)), 0 2px 5px rgba(0,0,0,.14);
  transition:transform .32s var(--spring), box-shadow var(--t), background var(--t);
}
.resume-go:hover{transform:translateY(-2px);box-shadow:0 15px 32px -12px var(--c,var(--p)), 0 2px 5px rgba(0,0,0,.14)}
.resume-go:active{transform:translateY(0) scale(.98)}

.resume-ic{
  width:32px;height:32px;flex-shrink:0;border-radius:50%;
  display:grid;place-items:center;font-size:16px;line-height:1;
  background:rgba(255,255,255,.6);
  transition:transform .45s var(--spring);
}
.resume-go:hover .resume-ic{transform:rotate(-8deg) scale(1.08)}

.resume-txt{display:flex;flex-direction:column;align-items:flex-start;line-height:1.16;min-width:0;overflow:hidden}
.resume-txt b{font-family:var(--font-ui);font-size:.82rem;font-weight:700;white-space:nowrap}
.resume-txt small{font-size:.66rem;opacity:.75;white-space:nowrap;font-variant-numeric:tabular-nums;font-weight:600}

/* La fleche de repli n'existe que sur mobile — sur grand ecran la place
   ne manque pas, et un controle de plus serait du bruit. */
.resume-fold{display:none}

@media (max-width:900px){
  .resume-fold{
    display:grid;place-items:center;width:30px;height:30px;flex-shrink:0;
    border-radius:50%;border:1px solid var(--stroke);background:var(--surface);
    color:var(--ink-2);cursor:pointer;box-shadow:var(--shadow);padding:0;
    -webkit-tap-highlight-color:transparent;
  }
  .resume-fold svg{width:15px;height:15px;transition:transform .34s var(--spring)}
  #resume.folded .resume-fold svg{transform:rotate(180deg)}

  .resume-txt{
    max-width:220px;opacity:1;
    transition:max-width .34s var(--spring), opacity .22s;
  }
  #resume.folded .resume-txt{max-width:0;opacity:0}
  #resume.folded .resume-go{padding:.45rem;gap:0}
}
@media (max-width:340px){
  .resume-txt{max-width:150px}
  .resume-txt b{font-size:.78rem}
}

/* Les notices remontent : elles occupaient le meme coin. */
#toasts{bottom:5.4rem}
@media (max-width:900px){
  #toasts{bottom:calc(var(--tabbar) + 4.6rem)}
}

/* ==========================================================================
   Abonnement — écran de paiement et file d'administration (30/07/2026)
   --------------------------------------------------------------------------
   Ces classes sont les SEULES nouvelles de js/paiement.js ; toute la structure
   de modale réutilise .modal-back / .modal / .modal-head / .modal-body, comme
   auth-ui.js. Ne pas inventer de classe dans le module : une modale aux classes
   inconnues s'affiche sans style, et rien ne le signale à l'exécution.
   ========================================================================== */

.pay-steps{margin:1rem 0 1.1rem;padding-left:1.35rem;font-size:.9rem;line-height:1.75;color:var(--ink-2)}
.pay-steps li{margin-bottom:.55rem}
.pay-nums{display:flex;flex-wrap:wrap;gap:.5rem;margin:.5rem 0 .2rem}

/* Le numéro est un bouton et non du texte : un chiffre recopié de travers
   envoie l'argent chez un inconnu, sans recours possible. */
.pay-num{
  display:inline-flex;align-items:baseline;gap:.5rem;
  padding:.45rem .7rem;border:1px solid var(--stroke);border-radius:var(--radius-sm);
  background:var(--surface-2);color:var(--ink);
  font-family:var(--font-m);font-size:.9rem;font-variant-numeric:tabular-nums;
  cursor:pointer;transition:border-color .18s,background .18s
}
.pay-num:hover{border-color:var(--p)}
.pay-num span{font-family:var(--font-ui);font-size:.62rem;text-transform:uppercase;letter-spacing:.12em;color:var(--ink-3)}
.pay-num.ok{border-color:var(--ok);background:color-mix(in srgb,var(--ok) 9%,transparent)}
.pay-num.ok span{color:var(--ok)}

.pay-cash{display:flex;align-items:center;gap:.5rem;margin:.8rem 0 0;font-size:.87rem;color:var(--ink-2);cursor:pointer}

.pay-out{margin-top:.9rem;font-size:.88rem;line-height:1.65}
.pay-out:empty{display:none}
.pay-out.live{padding:.6rem .85rem;background:color-mix(in srgb,var(--b) 7%,transparent);border-left:2px solid var(--b)}
.pay-out.good{padding:.6rem .85rem;background:color-mix(in srgb,var(--g) 8%,transparent);border-left:2px solid var(--g)}
.pay-out.bad{padding:.6rem .85rem;background:color-mix(in srgb,var(--r) 7%,transparent);border-left:2px solid var(--r)}

.pay-hist{margin-top:1.2rem}
.pay-hist:empty{display:none}
.pay-hist h4{font-family:var(--font-ui);font-weight:600;font-size:.66rem;text-transform:uppercase;letter-spacing:.15em;color:var(--ink-3);margin:0 0 .5rem}
.pay-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:.5rem .75rem;padding:.5rem 0;border-top:1px solid var(--stroke);font-size:.83rem}
.pay-pill{font-family:var(--font-ui);font-size:.7rem;font-weight:600;letter-spacing:.04em}
.pay-row.valide .pay-pill{color:var(--ok)}
.pay-row.refuse .pay-pill{color:var(--ko)}
.pay-row.en_attente .pay-pill{color:var(--o)}
.pay-ref{font-family:var(--font-m);font-variant-numeric:tabular-nums;color:var(--ink)}
.pay-date{color:var(--ink-3);font-size:.78rem;margin-left:auto}
.pay-motif{flex-basis:100%;color:var(--ko);font-size:.8rem}

.adm-liste{margin-top:.4rem}
.adm-row{display:flex;flex-wrap:wrap;align-items:center;gap:.7rem;padding:.8rem 0;border-top:1px solid var(--stroke)}
.adm-main{flex:1;min-width:230px;display:flex;flex-direction:column;gap:.2rem}
.adm-ref{font-family:var(--font-m);font-size:1rem;font-variant-numeric:tabular-nums;color:var(--ink);letter-spacing:.02em}
.adm-meta{font-size:.78rem;color:var(--ink-3)}

/* L'alerte de doublon est délibérément voyante : c'est le seul garde-fou contre
   deux comptes revendiquant le même paiement, et il ne sert à rien s'il se lit
   comme une note de bas de page. */
.adm-alerte{margin-top:.3rem;padding:.4rem .6rem;font-size:.79rem;line-height:1.55;
  color:var(--ko);background:color-mix(in srgb,var(--r) 8%,transparent);border-left:2px solid var(--r)}
.adm-actions{display:flex;gap:.4rem}
.adm-out{flex-basis:100%;font-size:.83rem}
.adm-out:empty{display:none}
.adm-out.live{color:var(--ink-3)}
.adm-out.good{color:var(--ok);font-weight:600}
.adm-out.bad{color:var(--ko);font-weight:600}

/* Affordance sur le voile du cadenas payant : la carte entière est déjà
   cliquable et go() ouvre l'écran d'abonnement, mais rien ne l'annonçait —
   « Inclus dans la version complète » se lisait comme une fin de non-recevoir. */
.lock-cta{
  display:inline-block;margin-top:.45rem;padding:.2rem .55rem;
  font-family:var(--font-ui);font-size:.68rem;font-weight:600;
  text-transform:uppercase;letter-spacing:.11em;
  color:var(--lock-tx);border:1px solid currentColor;border-radius:999px
}
/* Sur le voile payant, l'appel à l'action prend l'accent de la marque : la
   moutarde du cadenas dit « fermé », or ce bouton dit exactement l'inverse.
   Deux messages contraires dans un même bloc de 3 cm, c'est ce qui rendait la
   distinction illisible même après avoir changé l'icône. */
.lock-veil.premium .lock-cta{
  color:var(--on-accent);background:var(--p);border-color:var(--p);
}

/* Adresse non vérifiée dans la file d'administration. Volontairement discret :
   c'est un avertissement, pas un refus — et il ne doit pas se confondre avec
   l'alerte de doublon, qui, elle, signale un risque de double validation. */
.adm-nonverif{
  margin-top:.25rem;font-size:.76rem;color:var(--o);
  font-family:var(--font-ui);letter-spacing:.01em
}
