/* ═══ maquette_base.css ═══ */

:root{
  --bul:url("bulles.png");
  --navy:#092D59; --navy-d:#061D39; --navy-l:#1B4A85;
  --crimson:#C0093A; --crimson-d:#A91236;
  --paper:#CFE4FA;     /* fond de page — bleu ciel clair, teinte #1477d2 */
  --surf:#DEEBFB;      /* entre le papier et le blanc : l'étage intermédiaire */
  --surf2:#ECF4FD;     /* l'étage le plus haut du thème clair */ --blue:#D3E5FA; --rose:#F9ECF0; --brd:#B9D3EF; --brd2:#CBDFF5;
  --ink:#15273D; --soft:#4B5A6B; --soft2:#4E5A68; --green:#357946; --amber:#9B5F08;
  --sand:#F2E9DB; --sand2:#E7DAC3;
  --a1:#B00836; --a2:#0C6E7A; --b1:#1B6E48; --b2:#9B5F08; --c1:#5F3891;
  --sh:0 1px 2px rgba(9,45,89,.10), 0 4px 12px -2px rgba(9,45,89,.07); --sh2:0 2px 4px rgba(9,45,89,.09), 0 18px 40px -12px rgba(9,45,89,.16);
}
.bulles{background:var(--bul) center/contain no-repeat;display:inline-block;aspect-ratio:1403/1042;height:22px}
*{box-sizing:border-box}
html,body{margin:0}
body{background:var(--paper);color:var(--ink);margin:0;
  font-family:Inter,-apple-system,"Helvetica Neue",Segoe UI,Roboto,sans-serif;
  font-size:15px;line-height:1.6;-webkit-font-smoothing:antialiased}

/* ══════════ NAVIGATEUR DE MAQUETTE ══════════ */
#nav{width:246px;flex:0 0 246px;background:var(--navy-d);color:#fff;height:100vh;
  overflow-y:auto;position:sticky;top:0;padding:16px 0 40px}
#nav .brand{display:flex;align-items:center;gap:8px;padding:0 12px 16px;border-bottom:1px solid rgba(255,255,255,.12)}
#nav .brand{border-bottom:1px solid rgba(255,255,255,.12)}
#nav .brand .bulles{height:22px}
#nav .brand b{font-size:10px;letter-spacing:.7px;white-space:nowrap}
#nav .brand span{display:block;font-size:10px;letter-spacing:1px;color:#A8C0DC;font-weight:600}
#nav h4{margin:20px 16px 8px;font-size:10px;letter-spacing:1.4px;color:#6E8BB0;font-weight:800}
#nav a{display:flex;align-items:center;gap:8px;padding:8px 16px;color:#C6D6E8;
  text-decoration:none;font-size:13px;cursor:pointer;border-left:3px solid transparent}
#nav a:hover{background:rgba(255,255,255,.05);color:#fff}
#nav a.on{background:rgba(192,9,58,.18);border-left-color:var(--crimson);color:#fff;font-weight:600}
#nav a i{font-style:normal;width:16px;text-align:center;opacity:.75;font-size:12px}
#nav .note{margin:20px 16px 0;padding:12px 12px;background:rgba(255,255,255,.06);
  border-radius:7px;font-size:11px;line-height:1.55;color:#B4C8E0}

/* ══════════ SCÈNE ══════════ */
#stage{flex:1;height:100vh;overflow-y:auto;padding:20px 24px 70px}
.screenwrap{max-width:1180px;margin:0 auto}
.screenhead{display:flex;align-items:baseline;gap:12px;margin-bottom:12px;flex-wrap:wrap}
.screenhead h2{margin:0;font-size:17px;color:var(--navy);font-weight:800}
.screenhead .url{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;
  color:var(--soft);background:#fff;border:1px solid var(--brd);padding:2px 8px;border-radius:20px}
.screenhead .who{font-size:11px;font-weight:700;letter-spacing:.6px;padding:2px 8px;border-radius:20px}
.who.pub{background:#E3EEFB;color:var(--navy)}
.who.eleve{background:#E6F3EA;color:var(--green)}
.who.prof{background:#F4EAF7;color:#6B3FA0}
.who.app{background:#FBEAF0;color:var(--crimson-d)}
.screenhead .cmt{font-size:13px;color:var(--soft);font-style:italic;flex-basis:100%}
.browser{background:#fff;border-radius:11px;box-shadow:var(--sh2);overflow:hidden;border:1px solid #C4D3E4}
.chrome{background:#F2F5F9;border-bottom:1px solid var(--brd);padding:8px 12px;display:flex;align-items:center;gap:8px}
.dot{width:10px;height:10px;border-radius:50%}
.bar{flex:1;background:#fff;border:1px solid var(--brd);border-radius:20px;padding:4px 12px;
  font-size:12px;color:var(--soft);font-family:ui-monospace,Menlo,monospace}
.screen{display:none}
.screen.on{display:block}

/* ══════════ SITE ══════════ */
.site{background:var(--paper);font-size:14px}
.topnav{background:#fff;border-bottom:1px solid var(--brd);padding:12px 20px;
  display:flex;align-items:center;gap:16px;row-gap:8px;flex-wrap:wrap;
  position:relative;white-space:nowrap;z-index:30}
.topnav .lg{display:flex;align-items:center;gap:8px}
.topnav .lg .bulles{height:23px}
.topnav .lg{flex:0 0 auto}
.topnav .lg b{font-size:11px;letter-spacing:.8px;color:var(--navy);white-space:nowrap}
.topnav .lk{font-size:12px;color:var(--ink);cursor:pointer;font-weight:500;white-space:nowrap}
.topnav .lk:hover{color:var(--crimson)}
.topnav .lk.act{color:var(--crimson);font-weight:700}
.topnav .rt{margin-left:auto;display:flex;align-items:center;gap:12px;flex:0 0 auto}
/* ══ LE BOUTON N'EST DÉFINI QU'UNE FOIS, ET CE N'EST PAS ICI ══
   Ce bloc déclarait font-size 13px, border-radius 7px, padding 8/16 et
   transition .15s. Aucune de ces quatre valeurs n'atteignait jamais
   l'écran : la couche design les redéfinit toutes avec une spécificité
   supérieure (`.site .btn`). Elles n'étaient pas « la base » — elles
   étaient du texte mort que le navigateur analyse puis jette, et surtout
   le premier endroit où l'on va quand on veut changer un bouton, pour
   constater que rien ne bouge. On ne garde ici que ce qui vit encore. */
.btn{display:inline-block;font-weight:700;border:0;
  background:var(--crimson);color:#fff;cursor:pointer;text-decoration:none;
  line-height:1.4}
.btn:hover{background:var(--crimson-d)}
.btn.nv{background:var(--navy)} .btn.nv:hover{background:var(--navy-d)}
.btn.gh{background:transparent;color:var(--navy);border:1.5px solid var(--brd)}
.btn.gh:hover{border-color:var(--navy)}
.btn.w{background:#fff;color:var(--navy)}

.hero{background:linear-gradient(160deg,var(--navy) 0%,var(--navy-d) 100%);color:#fff;
  padding:52px 24px 56px;position:relative;overflow:hidden}
.hero .circ{position:absolute;border-radius:50%;background:rgba(255,255,255,.04)}
.heroin{max-width:1000px;margin:0 auto;display:grid;grid-template-columns:1.15fr .85fr;
  gap:32px;align-items:center;position:relative;z-index:2}
.hero .kick{display:inline-block;background:rgba(255,255,255,.11);border:1px solid rgba(255,255,255,.2);
  font-size:11px;font-weight:700;letter-spacing:1px;padding:4px 12px;border-radius:20px;margin-bottom:16px}
.hero h1{font-size:37px;line-height:1.1;margin:0 0 12px;font-weight:900;letter-spacing:-1px}
.hero h1 em{color:#FFB8C9;font-style:normal}
.hero p{color:#C6D6E8;font-size:16px;margin:0 0 20px;max-width:460px}
.hero .cta{display:flex;gap:12px;flex-wrap:wrap}
.hero .tiny{font-size:12px;color:#8FA8C4;margin-top:12px}
.mascots{background:rgba(255,255,255,.05);border:1.5px dashed rgba(255,255,255,.22);
  border-radius:13px;height:246px;display:grid;place-items:center;text-align:center;
  color:#A8C0DC;font-size:12px;padding:16px}
.mascots b{display:block;font-size:11px;letter-spacing:1.3px;color:#B4C8E0;margin-bottom:8px}

section.blk{padding:44px 24px}
.in{max-width:1000px;margin:0 auto}
.eyebrow{font-size:11px;font-weight:800;letter-spacing:1.8px;color:var(--crimson);margin-bottom:8px}
h2.sh,h1.sh{font-size:26px;font-weight:900;color:var(--navy);margin:0 0 8px;letter-spacing:-.6px}
p.lead{color:var(--soft);font-size:15px;max-width:620px;margin:0 0 24px}
.grid3{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}
.grid2{display:grid;grid-template-columns:repeat(2,1fr);gap:16px}
.grid4{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}
.card{background:#fff;border:1px solid var(--brd);border-radius:11px;padding:20px;box-shadow:var(--sh)}
.card h3{margin:0 0 8px;font-size:16px;color:var(--navy);font-weight:800}
.card p{margin:0;color:var(--soft);font-size:14px}
.card .ico{width:38px;height:38px;border-radius:9px;background:var(--blue);display:grid;
  place-items:center;font-size:18px;margin-bottom:12px}
.card.hi{border-color:var(--crimson);border-width:1.5px;position:relative}
.card.hi::after{content:"LE PLUS CHOISI";position:absolute;top:-9px;right:14px;background:var(--crimson);
  color:#fff;font-size:9px;font-weight:800;letter-spacing:.8px;padding:4px 8px;border-radius:20px}
.price{font-size:29px;font-weight:900;color:var(--navy);letter-spacing:-1px;margin:8px 0 2px;white-space:nowrap}
.price small{font-size:13px;font-weight:600;color:var(--soft2);white-space:nowrap}
ul.ck{list-style:none;padding:0;margin:12px 0 0;font-size:13px;color:var(--ink)}
ul.ck li{padding:4px 0 4px 20px;position:relative}
ul.ck li::before{content:"✓";position:absolute;left:0;color:var(--green);font-weight:800}
ul.ck li.no{color:var(--soft2)} ul.ck li.no::before{content:"—";color:var(--soft2)}


.mrow{display:grid;grid-template-columns:34px 1fr;gap:12px;margin-bottom:20px;align-items:start}
.mnum{width:34px;height:34px;border-radius:50%;background:var(--crimson);color:#fff;
  display:grid;place-items:center;font-weight:800;font-size:14px}
.mrow h4{margin:4px 0 4px;font-size:15px;color:var(--navy)}
.mrow p{margin:0;color:var(--soft);font-size:14px}
.samplebox{background:var(--rose);border-left:3px solid var(--crimson);border-radius:0 8px 8px 0;
  padding:12px 16px;font-size:14px}
.samplebox b{color:var(--crimson-d)}

.books{display:grid;grid-template-columns:repeat(5,1fr);gap:12px}
.book{background:#fff;border:1px solid var(--brd);border-radius:10px;overflow:hidden;
  box-shadow:var(--sh);cursor:pointer;transition:.15s}
.book:hover{transform:translateY(-3px);box-shadow:var(--sh2)}
.book .cv{aspect-ratio:1/1.414;background:linear-gradient(165deg,var(--navy),var(--navy-d));
  display:grid;place-items:center;position:relative;color:#fff;text-align:center;padding:12px}
.book .cv .lvl{position:absolute;top:9px;right:9px;font-size:10px;font-weight:800;
  padding:4px 8px;border-radius:20px;color:#fff}
.book .cv h5{font-size:14px;font-weight:900;margin:0;line-height:1.15;letter-spacing:-.3px}
.book .cv span{font-size:9px;letter-spacing:1.2px;color:#8FA8C4;display:block;margin-top:4px}
.book .ft{padding:8px 12px;font-size:12px;display:flex;justify-content:space-between;align-items:center}
.book .ft b{color:var(--navy)}
.book .ft em{font-style:normal;color:var(--soft2);font-size:11px}

.b2b{background:linear-gradient(120deg,var(--sand),var(--sand2));border-radius:12px;
  padding:24px 32px;display:grid;grid-template-columns:1fr auto;gap:20px;align-items:center}
.b2b h3{margin:0 0 8px;font-size:19px;color:var(--navy);font-weight:900}
.b2b p{margin:0;color:#6B5A42;font-size:14px;max-width:520px}

.waitlist{background:var(--navy);color:#fff;border-radius:12px;padding:24px 32px;
  display:grid;grid-template-columns:1fr auto;gap:24px;align-items:center}
.waitlist h3{margin:0 0 4px;font-size:19px;font-weight:900}
.waitlist p{margin:0;color:#B9CBE2;font-size:14px;max-width:520px}
.wlform{display:flex;gap:8px}
.wlform input{border:0;border-radius:7px;padding:12px 12px;font:inherit;font-size:13px;width:210px}
.counter{display:inline-flex;align-items:center;gap:8px;background:rgba(255,255,255,.1);
  border-radius:20px;padding:4px 12px;font-size:12px;margin-top:12px}
.counter b{color:#fff}
.dotlive{width:7px;height:7px;border-radius:50%;background:#4ADE80;box-shadow:0 0 0 3px rgba(74,222,128,.25)}

footer.site{background:var(--navy-d);color:#8FA8C4;padding:32px 24px 24px;font-size:13px}
footer.site .cols{max-width:1000px;margin:0 auto;display:grid;grid-template-columns:1.4fr 1fr 1fr 1fr;gap:24px}
footer.site h5{color:#fff;font-size:11px;letter-spacing:1.2px;margin:0 0 12px}
footer.site a{display:block;color:#8FA8C4;text-decoration:none;padding:2px 0}
footer.site .bot{max-width:1000px;margin:24px auto 0;padding-top:16px;
  border-top:1px solid rgba(255,255,255,.09);display:flex;gap:12px;font-size:12px}
footer.site .bot em{margin-left:auto;font-style:italic}

/* ── chapitre ── */
.chaphero{background:linear-gradient(160deg,var(--navy),var(--navy-d));color:#fff;padding:32px 24px}
.chaphero .chip{background:var(--crimson);font-size:11px;font-weight:800;letter-spacing:.9px;
  padding:4px 12px;border-radius:5px;display:inline-block}
.chaphero h1{font-size:31px;font-weight:900;color:#FFB8C9;margin:12px 0 4px;letter-spacing:-.8px}
.chaphero .hk{color:#C6D6E8;font-style:italic;font-size:14px;margin:0}
.videobox{aspect-ratio:16/9;background:#0B1D33;border-radius:11px;display:grid;place-items:center;
  color:#93AECD;position:relative;overflow:hidden;border:1px solid #1B3A5E}
.play{width:58px;height:58px;border-radius:50%;background:var(--crimson);display:grid;place-items:center;
  color:#fff;font-size:19px;box-shadow:0 6px 22px rgba(192,9,58,.4)}
.exdemo{background:#fff;border:1px solid var(--brd);border-radius:10px;padding:16px 16px;box-shadow:var(--sh)}
.exhd{display:flex;align-items:center;gap:12px;margin-bottom:8px}
.pill{background:var(--crimson);color:#fff;font-size:10px;font-weight:800;letter-spacing:.8px;padding:4px 12px;border-radius:5px}
.exhd b{color:var(--navy);font-size:14px}
.exhd .tg{margin-left:auto;font-size:11px;font-weight:700;color:var(--soft2);
  background:var(--blue);border:1px solid var(--brd);padding:2px 8px;border-radius:20px}
.exli{display:grid;grid-template-columns:20px 1fr auto;gap:8px;align-items:center;padding:4px 0;font-size:14px}
.exli .n{color:var(--crimson);font-weight:800;font-size:12px;text-align:right}
.fld{display:inline-block;min-width:88px;border-bottom:1.5px dotted #9FB0C2;padding:2px 8px;
  font-weight:600;color:var(--navy)}
.fld.ok{border-bottom:2px solid var(--green);background:#F1F8F3;color:var(--green);border-radius:3px 3px 0 0}
.fld.ko{border-bottom:2px solid var(--crimson);background:#FDF2F5;color:var(--crimson);border-radius:3px 3px 0 0}
.paywall{background:linear-gradient(180deg,rgba(237,243,249,0),var(--paper) 55%);margin-top:-80px;
  padding-top:80px;position:relative;text-align:center}
.pwcard{background:#fff;border:1.5px solid var(--crimson);border-radius:12px;padding:24px;
  max-width:520px;margin:0 auto;box-shadow:var(--sh2)}

/* ── cours ── */
.profcard{display:grid;grid-template-columns:96px 1fr;gap:16px;align-items:start}
.avatar{width:96px;height:96px;border-radius:14px;background:linear-gradient(150deg,var(--navy),var(--navy-l));
  display:grid;place-items:center;color:#fff;font-weight:900;font-size:26px;letter-spacing:-1px}
.badge{display:inline-block;font-size:11px;font-weight:700;background:var(--blue);color:var(--navy);
  border:1px solid var(--brd);padding:2px 8px;border-radius:20px;margin:0 4px 4px 0}
.cal{display:grid;grid-template-columns:repeat(7,1fr);gap:8px}
.day{text-align:center}
.day .dn{font-size:11px;font-weight:800;color:var(--soft2);letter-spacing:.6px;margin-bottom:8px}
.slot{background:#fff;border:1px solid var(--brd);border-radius:7px;padding:8px 2px;font-size:12px;
  font-weight:600;color:var(--navy);margin-bottom:4px;cursor:pointer}
.slot:hover{border-color:var(--crimson);color:var(--crimson)}
.slot.full{background:#F4F6F9;color:#65707C;border-style:dashed;cursor:not-allowed;text-decoration:line-through}
.slot.sel{background:var(--crimson);color:#fff;border-color:var(--crimson)}

/* ── tableau de bord ── */
.dashgrid{display:grid;grid-template-columns:1.5fr 1fr;gap:16px}
.kpi{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:16px}
.kpicard{background:#fff;border:1px solid var(--brd);border-radius:10px;padding:12px 16px;box-shadow:var(--sh)}
.kpicard .lb{font-size:11px;font-weight:700;letter-spacing:.7px;color:var(--soft2);margin-bottom:4px}
.kpicard .vl{font-size:25px;font-weight:900;color:var(--navy);letter-spacing:-1px;line-height:1.1}
.kpicard .vl small{font-size:12px;font-weight:600;color:var(--soft2);letter-spacing:0}
.kpicard .sub{font-size:12px;color:var(--soft);margin-top:2px}
.meter{margin:12px 0}
.meter .lab{display:flex;justify-content:space-between;align-items:baseline;font-size:13px;
  color:var(--soft);margin-bottom:4px}
.meter .lab b{color:var(--ink);font-weight:700}
.meter .lab .v{font-variant-numeric:tabular-nums;font-weight:800;color:var(--navy)}
.track{height:8px;background:var(--blue);border-radius:5px;overflow:hidden}
.fill{height:100%;border-radius:5px;background:var(--navy)}
.fill.weak{background:var(--crimson)}
.flag{font-size:11px;font-weight:700;color:var(--crimson);margin-left:8px}
.reco{background:var(--rose);border-left:3px solid var(--crimson);border-radius:0 9px 9px 0;padding:12px 16px}
.reco>b:first-child{display:block;font-size:11px;letter-spacing:1px;color:var(--crimson-d);margin-bottom:4px}
.reco p b,.reco .ritem b{color:var(--crimson-d)}
.reco p{margin:0 0 12px;font-size:14px}
.rlist{display:grid;gap:8px}
.ritem{background:#fff;border:1px solid var(--brd);border-radius:8px;padding:8px 12px;
  display:flex;align-items:center;gap:12px;font-size:13px;cursor:pointer}
.ritem:hover{border-color:var(--crimson)}
.ritem .ic{width:26px;height:26px;border-radius:6px;background:var(--blue);display:grid;place-items:center;font-size:13px}
.ritem .ar{margin-left:auto;color:var(--soft2)}
.next{background:linear-gradient(135deg,var(--navy),var(--navy-l));color:#fff;border-radius:11px;padding:16px}
.next .lb{font-size:11px;letter-spacing:1.1px;color:#B4C8E0;font-weight:800}
.next h4{margin:8px 0 4px;font-size:18px;font-weight:800}
.next p{margin:0 0 12px;color:#C6D6E8;font-size:13px}
.streak{display:flex;gap:4px;margin-top:8px}
.sday{width:26px;height:26px;border-radius:7px;background:var(--blue);display:grid;place-items:center;
  font-size:11px;font-weight:700;color:var(--soft2)}
.sday.on{background:var(--green);color:#fff}
table.tb{width:100%;border-collapse:separate;border-spacing:0;font-size:13px}
table.tb th{text-align:left;font-size:11px;letter-spacing:.7px;color:var(--soft2);
  font-weight:800;padding:8px 12px;border-bottom:1px solid var(--brd)}
table.tb td{padding:8px 12px;border-bottom:1px solid var(--brd2)}
.st{font-size:11px;font-weight:700;padding:2px 8px;border-radius:20px}
.st.ok{background:#E6F3EA;color:var(--green)} .st.wt{background:#FDF0E1;color:var(--amber)}
.st.dn{background:var(--blue);color:var(--soft)}

/* ── app mobile ── */
.phones{display:flex;gap:20px;flex-wrap:wrap;justify-content:center;padding:24px;background:var(--paper)}
.phone{width:265px;flex:0 0 265px;background:#101B2A;border-radius:32px;padding:8px;box-shadow:var(--sh2)}
.pscreen{background:var(--paper);border-radius:25px;overflow:hidden;height:540px;
  display:flex;flex-direction:column;position:relative}
.pnotch{height:24px;background:#fff;display:flex;align-items:center;justify-content:space-between;
  padding:0 16px;font-size:10px;font-weight:700;color:var(--navy)}
.pbody{flex:1;overflow:hidden;padding:12px}
.ptab{background:#fff;border-top:1px solid var(--brd);display:grid;grid-template-columns:repeat(4,1fr);
  padding:8px 0 8px}
.ptab div{text-align:center;font-size:9px;color:var(--soft2);font-weight:600}
.pscreen .ptab[style*="0B1B30"] div{color:#A8C0DC}
.ptab div i{display:block;font-style:normal;font-size:16px;margin-bottom:2px;opacity:.55}
.ptab div.on{color:var(--crimson)} .ptab div.on i{opacity:1}
.pcap{text-align:center;font-size:12px;color:var(--soft);margin-top:8px;font-weight:600}
.pcard{background:#fff;border:1px solid var(--brd);border-radius:10px;padding:12px 12px;margin-bottom:8px}
.pcard h5{margin:0 0 4px;font-size:13px;color:var(--navy);font-weight:800}
.pcard p{margin:0;font-size:12px;color:var(--soft)}
.psmall{font-size:10px;letter-spacing:.9px;font-weight:800;color:var(--soft2);margin:12px 0 8px}

/* ── architecture ── */
.arch{background:#fff;border-radius:12px;padding:32px;border:1px solid var(--brd)}
.archrow{display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-bottom:20px}
.archbox{border:2px solid var(--navy);border-radius:11px;padding:16px;text-align:center;background:var(--blue)}
.archbox.core{border-color:var(--crimson);background:var(--rose);grid-column:1/-1}
.archbox h4{margin:0 0 4px;font-size:15px;color:var(--navy);font-weight:900}
.archbox p{margin:0;font-size:13px;color:var(--soft)}
.archbox .tech{display:inline-block;background:#fff;border:1px solid var(--brd);border-radius:20px;
  padding:2px 12px;font-size:11px;font-weight:700;color:var(--navy);margin:8px 4px 0}
.arrow{text-align:center;font-size:22px;color:var(--crimson);margin:-8px 0 8px}
.sharedtbl{width:100%;border-collapse:collapse;font-size:13px;margin-top:8px}
.sharedtbl th{background:var(--navy);color:#fff;font-size:11px;letter-spacing:.7px;
  padding:8px 12px;text-align:left}
.sharedtbl th:nth-child(2){background:var(--crimson)}
.sharedtbl td{padding:8px 12px;border-bottom:1px solid var(--brd2);background:var(--blue)}
.sharedtbl td:nth-child(2){background:var(--rose)}
.sharedtbl td:nth-child(3){background:#fff}

.legend{background:#fff;border:1px dashed var(--brd);border-radius:9px;padding:12px 16px;
  font-size:13px;color:var(--soft);margin-top:16px;line-height:1.65}
.legend b{color:var(--navy)}





.tvico{width:14px;height:14px;vertical-align:-2px;margin-right:4px;display:inline-block}
.ptab .tvico{width:16px;height:16px;margin:0 auto 2px;display:block}
.qimg{border-radius:12px;overflow:hidden;position:relative;aspect-ratio:16/10;max-width:430px;margin:0 auto 16px;
  border:1.5px dashed rgba(9,45,89,.18);background:
  radial-gradient(circle at 38% 40%,rgba(27,74,133,.16),transparent 62%),
  radial-gradient(circle at 70% 66%,rgba(192,9,58,.13),transparent 58%),
  linear-gradient(155deg,#E7EFF9,#F9ECF0)}
.qimg .lbl2{position:absolute;inset:0;display:grid;place-items:center;text-align:center;color:var(--soft2);
  font-size:12px;line-height:1.65;padding:16px}
.qimg .lbl2 b{display:block;font-size:10px;letter-spacing:1.4px;color:var(--soft);margin-bottom:4px}
.qimg .zoom{position:absolute;right:10px;bottom:10px;background:rgba(9,45,89,.82);color:#fff;
  font-size:11px;font-weight:700;padding:4px 8px;border-radius:20px}
.starnote{background:var(--sand);border:1px solid var(--sand2);border-radius:10px;padding:12px 16px;
  font-size:13px;color:#6B5A42;margin-bottom:20px;line-height:1.75}
.starnote b{color:var(--navy)}
.starnote .st2{color:var(--crimson);font-weight:800;margin-right:4px}
.fmtgrid{display:grid;grid-template-columns:repeat(5,1fr);gap:12px}
.fmt{background:#fff;border:1px solid var(--brd);border-radius:11px;padding:12px;box-shadow:var(--sh)}
.fmt .n2{width:24px;height:24px;border-radius:7px;background:var(--crimson);color:#fff;display:grid;
  place-items:center;font-size:11px;font-weight:800;margin-bottom:8px}
.fmt h5{margin:0 0 8px;font-size:13px;color:var(--navy);font-weight:800}
.fmt .ex2{background:var(--blue);border-radius:7px;padding:8px 12px;font-size:12px;color:var(--ink);line-height:1.5}
.fmt .ex2 em{font-style:normal;color:var(--crimson);font-weight:700}
.fmt .tr{font-size:11px;color:var(--soft2);margin-top:8px;font-style:italic}
.serthumb{width:44px;height:44px;border-radius:9px;flex:0 0 44px;position:relative;overflow:hidden;
  border:1px dashed rgba(9,45,89,.2)}

/* S ENTRAINER */
.quickband{background:linear-gradient(120deg,var(--navy),var(--navy-l));color:#fff;border-radius:13px;
  padding:24px 28px;display:grid;grid-template-columns:1fr auto;gap:24px;align-items:center;margin-bottom:24px}
.quickband .lb{font-size:11px;letter-spacing:1.1px;color:#B4C8E0;font-weight:800}
.quickband h3{margin:8px 0 4px;font-size:23px;font-weight:900;letter-spacing:-.6px}
.quickband p{margin:0;color:#C6D6E8;font-size:14px}
.qbtns{display:flex;gap:8px;align-items:center}
.qbig{background:#fff;color:var(--navy);border-radius:9px;padding:12px 24px;font-weight:800;font-size:14px;cursor:pointer}
.qsm{border:1.5px solid rgba(255,255,255,.4);border-radius:9px;padding:12px 16px;font-weight:700;font-size:13px;cursor:pointer}
.qsm:hover{background:rgba(255,255,255,.14)}
.tcard{background:#fff;border:1px solid var(--brd);border-radius:12px;padding:16px;box-shadow:var(--sh);
  cursor:pointer;transition:.15s;position:relative;display:flex;flex-direction:column}
.tcard:hover{border-color:var(--crimson);transform:translateY(-2px);box-shadow:var(--sh2)}
.tcard .ti{width:40px;height:40px;border-radius:11px;background:var(--blue);display:grid;place-items:center;
  font-size:18px;margin-bottom:12px}
.tcard.hot2 .ti{background:var(--rose)}
.tcard h4{margin:0 0 4px;font-size:16px;color:var(--navy);font-weight:800}
.tcard p{margin:0 0 12px;font-size:13px;color:var(--soft);flex:1}
.tcard .foot{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--soft2);font-weight:700}
.tcard .foot .go{margin-left:auto;color:var(--crimson);font-weight:800}
.lock{position:absolute;top:14px;right:14px;background:var(--blue);border:1px solid var(--brd);
  border-radius:20px;padding:2px 8px;color:var(--soft);font-weight:700;font-size:11px}
.qwrap{max-width:720px;margin:0 auto}
.qtop{display:flex;align-items:center;gap:12px;font-size:12px;color:var(--soft);margin-bottom:8px}
.qtop b{color:var(--navy)}
.qtop .tmr{margin-left:auto;font-family:ui-monospace,Menlo,monospace;background:#fff;border:1px solid var(--brd);
  border-radius:20px;padding:2px 12px;font-weight:700;color:var(--navy)}
.qprog{height:7px;background:var(--blue);border-radius:5px;overflow:hidden;margin-bottom:20px}
.qprog i{display:block;height:100%;background:var(--crimson);border-radius:5px}
.qtext{font-size:23px;font-weight:800;color:var(--navy);letter-spacing:-.5px;margin:0 0 4px;line-height:1.25}
.qsub{font-size:13px;color:var(--soft);margin:0 0 20px}
.opts{display:grid;gap:8px}
.opt{background:#fff;border:1.5px solid var(--brd);border-radius:10px;padding:12px 16px;font-size:15px;
  display:flex;align-items:center;gap:12px;cursor:pointer;transition:.13s}
.opt:hover{border-color:var(--navy)}
.opt .ltr{width:26px;height:26px;border-radius:7px;background:var(--blue);display:grid;place-items:center;
  font-size:12px;font-weight:800;color:var(--navy);flex:0 0 26px}
.opt .mk{margin-left:auto;font-size:12px;font-weight:800}
.opt.ok{border-color:var(--green);background:#F1F8F3}
.opt.ok .ltr{background:var(--green);color:#fff}
.opt.ok .mk{color:var(--green)}
.opt.ko{border-color:var(--crimson);background:#FDF2F5}
.opt.ko .ltr{background:var(--crimson);color:#fff}
.opt.ko .mk{color:var(--crimson)}
.expl{background:var(--blue);border-left:3px solid var(--navy);border-radius:0 10px 10px 0;
  padding:12px 16px;margin-top:16px;font-size:14px}
.expl b.t{display:block;font-size:11px;letter-spacing:1px;color:var(--navy);font-weight:800;margin-bottom:4px}
.exsent{background:#fff;border-radius:7px;padding:8px 12px;margin-top:12px;font-style:italic;
  font-size:13px;color:var(--ink);display:flex;align-items:center;gap:8px}
.exsent .src{margin-left:auto;font-style:normal;font-size:11px;color:var(--soft2);font-weight:700;white-space:nowrap}
.qfoot{display:flex;align-items:center;gap:12px;margin-top:20px;padding-top:16px;border-top:1px solid var(--brd)}
.qscore{font-size:13px;color:var(--soft)}
.qscore b{color:var(--navy);font-weight:800}
.resulthead{text-align:center;padding:8px 0 20px}
.ring{width:132px;height:132px;border-radius:50%;margin:0 auto 12px;display:grid;place-items:center;
  background:conic-gradient(var(--green) 0 85%, var(--blue) 85% 100%);position:relative}
.ring::after{content:"";position:absolute;inset:11px;border-radius:50%;background:#fff}
.ring div{position:relative;z-index:2;text-align:center}
.ring .big{font-size:31px;font-weight:900;color:var(--navy);letter-spacing:-1.5px;line-height:1}
.ring .sm2{font-size:11px;color:var(--soft2);font-weight:700}
.mistake{background:#fff;border:1px solid var(--brd);border-left:3px solid var(--crimson);border-radius:0 9px 9px 0;
  padding:12px 16px;margin-bottom:8px;font-size:14px}
.mistake .q{font-weight:700;color:var(--navy);margin-bottom:4px}
.mistake .a{color:var(--soft)}
.mistake .a b{color:var(--green)}
.mistake .a s{color:var(--crimson)}



/* ══════════ JAMAIS DE FOND BLANC NU — rappel de marque discret ══════════ */
.blk.wt{position:relative;overflow:hidden;background:
  radial-gradient(circle at 10% 12%, rgba(9,45,89,.055), transparent 42%),
  radial-gradient(circle at 90% 88%, rgba(192,9,58,.048), transparent 44%),
  linear-gradient(180deg,#FFFFFF 0%,#FBFCFE 55%,#F7FAFD 100%)}
.blk.wt::before{content:"";position:absolute;right:-58px;top:-46px;width:250px;height:250px;
  background:var(--bul) center/contain no-repeat;opacity:.05;pointer-events:none}
.blk.wt::after{content:"";position:absolute;left:-70px;bottom:-64px;width:200px;height:200px;
  background:var(--bul) center/contain no-repeat;opacity:.035;
  transform:rotate(-14deg);pointer-events:none}
.blk.wt .in{position:relative;z-index:2}

/* bandeau tarifs — dégradé de marque */
.blk.pricing{position:relative;overflow:hidden;background:
  linear-gradient(180deg, transparent 66%, var(--paper) 100%),
  radial-gradient(circle at 82% 8%, rgba(192,9,58,.10), transparent 46%),
  radial-gradient(circle at 6% 88%, rgba(9,45,89,.10), transparent 48%),
  linear-gradient(160deg,#F4F8FC 0%,#EDF3F9 48%,#F9ECF0 100%)}
.blk.pricing::before{content:"";position:absolute;left:50%;top:-90px;transform:translateX(-50%);
  width:520px;height:520px;border-radius:50%;background:radial-gradient(circle,rgba(255,255,255,.85),transparent 62%);
  pointer-events:none}
.blk.pricing .in{position:relative;z-index:2}

/* cartes tarifaires colorées */
.pm{overflow:hidden;padding-top:0}
.pm .cap2{height:5px;margin:0 -12px 12px;display:block}
.pm h4{margin-top:0}
.pm .p2{color:var(--acc,var(--navy))}
.pm ul li::before{content:"✓";position:absolute;left:0;color:var(--acc,var(--green));font-weight:900;font-size:11px}
.pm ul li{padding-left:16px}
.card .cap2{height:5px;margin:-20px -20px 16px;display:block;border-radius:11px 11px 0 0}
.card .price{color:var(--acc,var(--navy))}
ul.ck li::before{color:var(--acc,var(--green))}



/* ══════════ SÉLECTEUR D'APPARENCE (côté visiteur) ══════════ */
.thpick{position:relative;width:30px;height:30px;border-radius:50%;border:1px solid var(--brd);
  display:grid;place-items:center;font-size:15px;line-height:1;color:var(--navy);cursor:pointer;
  transition:.15s;background:var(--blue);flex:0 0 30px}
.thpick .thico{font-style:normal;display:block;margin-top:-2px}
.thpick:hover{border-color:var(--crimson);color:var(--crimson)}
.thpick .tip{position:absolute;top:36px;right:-6px;background:var(--navy);color:#fff;font-size:11px;
  font-weight:700;letter-spacing:.3px;padding:4px 12px;border-radius:6px;white-space:nowrap;
  opacity:0;pointer-events:none;transition:.15s;z-index:40}
.thpick:hover .tip{opacity:1}
body.dark .thpick{background:var(--surf2);border-color:var(--brd);color:#FFD8E2}
body.dark .thpick .tip{background:#461421}

/* ══════════ BASCULE MENSUEL / ANNUEL ══════════ */
.billrow{display:flex;align-items:center;justify-content:center;gap:12px;margin:0 0 24px;flex-wrap:wrap}
.billsw{display:inline-flex;align-items:center;gap:12px;background:rgba(9,45,89,.06);
  border:1px solid var(--brd);border-radius:30px;padding:4px 8px}
.billsw span{font-size:13px;font-weight:700;color:var(--soft);cursor:pointer;padding:4px 12px;border-radius:20px;transition:.15s}
.billsw span.on{background:var(--navy);color:#fff}
.billsw .knob{width:42px;height:22px;border-radius:20px;background:var(--brd);position:relative;
  cursor:pointer;transition:.2s;padding:0;flex:0 0 42px}
.billsw .knob::after{content:"";position:absolute;top:3px;left:3px;width:16px;height:16px;border-radius:50%;
  background:#fff;transition:.2s;box-shadow:0 1px 3px rgba(0,0,0,.25)}
body.annual .billsw .knob{background:var(--crimson)}
body.annual .billsw .knob::after{left:23px}
.billbadge{background:var(--crimson);color:#fff;font-size:11px;font-weight:800;letter-spacing:.4px;
  padding:4px 12px;border-radius:20px}
.by{display:none}
body.annual .bm{display:none}
body.annual .by{display:inline}
.savenote{font-size:12px;color:var(--green);font-weight:700;display:none}
body.annual .savenote{display:block}

/* ══════════ ACCÈS RAPIDE / TEST DE NIVEAU / BASCULE KIDS ══════════ */
.audsw{display:inline-flex;background:var(--blue);border:1px solid var(--brd);border-radius:20px;padding:2px;gap:2px}
.audsw b{font-size:12px;font-weight:700;padding:4px 12px;border-radius:20px;color:var(--soft);cursor:pointer;transition:.15s}
.audsw b:hover{color:var(--navy)}
.audsw b.on{background:var(--navy);color:#fff}
.audsw b.kid.on{background:var(--crimson)}

.quickrow{display:grid;grid-template-columns:repeat(6,1fr);gap:12px;margin-top:-40px;position:relative;z-index:6}
.qcard2{background:#fff;border:1px solid var(--brd);border-radius:12px;padding:16px 12px;text-align:center;
  box-shadow:0 6px 22px rgba(9,45,89,.13);cursor:pointer;transition:.16s}
.qcard2:hover{transform:translateY(-3px);border-color:var(--crimson);box-shadow:0 10px 28px rgba(9,45,89,.18)}
.qcard2 .i2{width:36px;height:36px;border-radius:10px;background:var(--blue);display:grid;place-items:center;
  font-size:16px;margin:0 auto 8px}
.qcard2.hi2 .i2{background:var(--rose)}
.qcard2 b{display:block;font-size:14px;color:var(--navy);font-weight:800;margin-bottom:2px}
.qcard2 span{font-size:12px;color:var(--soft2)}

.leveltest{background:linear-gradient(125deg,var(--navy),var(--navy-l));color:#fff;border-radius:14px;
  padding:32px 32px;display:grid;grid-template-columns:1.05fr .95fr;gap:32px;align-items:center}
.leveltest h2{margin:0 0 8px;font-size:27px;font-weight:900;letter-spacing:-.8px;line-height:1.12}
.leveltest h2 em{color:#FFB8C9;font-style:normal}
.leveltest p{margin:0 0 16px;color:#C6D6E8;font-size:15px;max-width:420px}
.ltfacts{display:flex;gap:16px;margin-bottom:20px;flex-wrap:wrap}
.ltfacts div{font-size:12px;color:#B4C8E0}
.ltfacts div b{display:block;font-size:19px;color:#fff;font-weight:900;letter-spacing:-.5px}
.ladder{background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.14);border-radius:12px;padding:16px}
.ladder .st3{display:flex;align-items:center;gap:12px;padding:8px 0}
.ladder .dotl{width:11px;height:11px;border-radius:50%;background:rgba(255,255,255,.22);flex:0 0 11px}
.ladder .st3.hit .dotl{background:#F2436E;box-shadow:0 0 0 4px rgba(242,67,110,.22)}
.ladder .st3 b{font-size:13px;width:26px}
.ladder .st3 span{font-size:13px;color:#B4C8E0}
.ladder .st3.hit span{color:#fff}
.ladder .st3.hit b{color:#FFB8C9}
.ladder .res{margin-top:12px;padding-top:12px;border-top:1px solid rgba(255,255,255,.14);
  font-size:12px;color:#C3D5EC}

.kidsband{background:linear-gradient(120deg,#F2E9DB,#F9ECF0);border:1px solid var(--sand2);border-radius:14px;
  padding:24px 32px;display:grid;grid-template-columns:auto 1fr auto;gap:24px;align-items:center}
.kidsband .kf{width:78px;height:78px;border-radius:18px;background:linear-gradient(150deg,var(--navy),var(--crimson));
  display:grid;place-items:center;font-size:32px;color:#fff;flex:0 0 78px}
.kidsband h3{margin:0 0 4px;font-size:21px;font-weight:900;color:var(--navy);letter-spacing:-.5px}
.kidsband p{margin:0;color:#6B5A42;font-size:14px;max-width:540px}
.kidsband .tags2{margin-top:8px}
.pricemini{display:grid;grid-template-columns:repeat(5,1fr);gap:12px}
.pm{background:#fff;border:1px solid var(--brd);border-radius:12px;padding:16px 12px;box-shadow:var(--sh);
  display:flex;flex-direction:column;cursor:pointer;transition:.15s}
.pm:hover{border-color:var(--navy);transform:translateY(-2px)}
.pm.best{border:1.5px solid var(--crimson);position:relative}
.pm.best::after{content:"LE PLUS CHOISI";position:absolute;top:-9px;left:50%;transform:translateX(-50%);
  background:var(--crimson);color:#fff;font-size:9px;font-weight:800;letter-spacing:.7px;padding:4px 12px;border-radius:20px;white-space:nowrap}
.pm h4{margin:0 0 8px;font-size:14px;color:var(--navy);font-weight:800}
.pm .p2{font-size:23px;font-weight:900;color:var(--navy);letter-spacing:-1px;line-height:1;white-space:nowrap}
.pm .p2 small{font-size:12px;font-weight:600;color:var(--soft2);letter-spacing:0}
.pm .u{font-size:11px;color:var(--soft2);margin:2px 0 12px}
.pm ul{list-style:none;margin:0 0 12px;padding:0;font-size:12px;color:var(--soft);flex:1}
.pm ul li{padding:2px 0 2px 12px;position:relative;font-size:12px}
.pm ul li::before{content:"·";position:absolute;left:3px;color:var(--crimson);font-weight:900}

/* ══════════ BANDEAU D'ACCUEIL — image pleine largeur ══════════ */
.hero2{position:relative;height:470px;overflow:hidden;background:#08152A}
.heroimg{position:absolute;inset:-24px;background:
  radial-gradient(circle at 26% 42%,rgba(27,74,133,.85),transparent 58%),
  radial-gradient(circle at 74% 58%,rgba(150,20,55,.62),transparent 56%),
  linear-gradient(150deg,#0E3A6B 0%,#08152A 52%,#2A0A1A 100%);
  animation:kenburns 26s ease-in-out infinite alternate;
  transition:transform .5s cubic-bezier(.22,.61,.36,1)}
@keyframes kenburns{from{transform:scale(1)}to{transform:scale(1.07)}}
.heroimg .ph{position:absolute;left:44px;bottom:96px;max-width:298px;text-align:left;background:rgba(6,18,34,.62);border-radius:9px;padding:12px 12px 12px;backdrop-filter:blur(2px);
  border-left:2px solid rgba(255,255,255,.22);padding-left:12px;
  color:rgba(255,255,255,.66);font-size:11px;line-height:1.65;z-index:2}
.heroimg .ph b{display:block;font-size:10px;letter-spacing:1.5px;color:rgba(255,255,255,.82);margin-bottom:4px}
.heroimg .ph em{font-style:normal;font-size:10px;color:rgba(255,255,255,.78)}
/* silhouettes indicatives des deux mascottes — remplacées par l'image finale */
.figs{position:absolute;inset:0;z-index:1;pointer-events:none}
.fig{position:absolute;bottom:0;border-radius:50% 50% 12% 12%/62% 62% 8% 8%;filter:blur(1.5px);
  animation:floaty 11s ease-in-out infinite alternate}
.fig::after{content:"";position:absolute;left:50%;top:-13%;transform:translateX(-50%);
  width:52%;aspect-ratio:1;border-radius:50%}
.fig.t{left:15%;width:190px;height:300px;background:linear-gradient(180deg,rgba(27,74,133,.62),rgba(9,45,89,.16))}
.fig.t::after{background:rgba(31,86,155,.66)}
.fig.f{right:16%;width:172px;height:272px;background:linear-gradient(180deg,rgba(150,20,55,.55),rgba(120,10,40,.14));
  animation-delay:-4s}
.fig.f::after{background:rgba(175,25,66,.62)}
.heroscrim{position:absolute;inset:0;background:linear-gradient(0deg,rgba(6,17,33,.92) 4%,rgba(6,17,33,.30) 46%,rgba(6,17,33,.55) 100%)}
.heroctn{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;
  text-align:center;padding:0 32px;z-index:3;color:#fff}
.heroctn .kick2{font-size:11px;font-weight:700;letter-spacing:4.5px;color:#C6D6E8;margin-bottom:16px}
.heroctn h1{font-size:44px;font-weight:900;letter-spacing:-1.4px;line-height:1.06;margin:0 0 12px;max-width:760px}
.heroctn h1 em{color:#FFB8C9;font-style:normal}
.heroctn p{color:#C6D6E8;font-size:16px;max-width:520px;margin:0 0 24px;line-height:1.6}
.heroctn .cta{display:flex;gap:12px;flex-wrap:wrap;justify-content:center}
.hbtn{display:inline-block;font-size:14px;font-weight:700;border-radius:8px;padding:12px 32px;
  background:var(--crimson);color:#fff;text-decoration:none;cursor:pointer;transition:.18s;border:1.5px solid var(--crimson)}
.hbtn:hover{background:var(--crimson-d);border-color:var(--crimson-d)}
.hbtn.o{background:rgba(255,255,255,.10);border-color:rgba(255,255,255,.55);backdrop-filter:blur(6px)}
.hbtn.o:hover{background:rgba(255,255,255,.2)}
.heroctn .counter{margin-top:16px}
.scrollhint{position:absolute;left:50%;bottom:16px;transform:translateX(-50%);z-index:4;color:rgba(255,255,255,.74);
  font-size:16px;animation:bob 2.4s ease-in-out infinite}
@keyframes bob{0%,100%{transform:translateX(-50%) translateY(0)}50%{transform:translateX(-50%) translateY(6px)}}

/* ── figure mascottes « presque animee » ── */
.masc{position:relative;border-radius:14px;overflow:hidden;background:
  radial-gradient(circle at 40% 35%,rgba(27,74,133,.9),transparent 62%),
  radial-gradient(circle at 68% 66%,rgba(150,20,55,.6),transparent 58%),
  linear-gradient(160deg,#12365F,#0A1C33);
  border:1.5px dashed rgba(255,255,255,.18)}
.masc .inner{position:absolute;inset:0;animation:floaty 9s ease-in-out infinite alternate}
@keyframes floaty{from{transform:translateY(0) scale(1)}to{transform:translateY(-9px) scale(1.025)}}
.masc .glow{position:absolute;inset:0;background:linear-gradient(112deg,transparent 34%,rgba(255,255,255,.09) 50%,transparent 66%);
  background-size:250% 100%;animation:sweep 5.5s linear infinite}
.masc .lbl{position:absolute;inset:0;display:grid;place-items:center;text-align:center;
  color:rgba(255,255,255,.74);font-size:12px;line-height:1.7;padding:16px}
.masc .lbl b{display:block;font-size:11px;letter-spacing:1.5px;color:rgba(255,255,255,.86);margin-bottom:4px}
.masc .lbl em{font-style:normal;font-size:11px;color:rgba(255,255,255,.62)}
.masc .wave{position:absolute;right:14px;top:14px;font-size:19px;animation:hand 2.8s ease-in-out infinite;transform-origin:70% 80%}
@keyframes hand{0%,72%,100%{transform:rotate(0)}78%{transform:rotate(15deg)}84%{transform:rotate(-9deg)}90%{transform:rotate(12deg)}}

/* ══════════ TRULY FLUENT TV — surface sombre ══════════ */
.tv{background:#08152A;color:#fff;overflow:hidden}
.tv .topnav{background:rgba(6,17,33,.92);border-bottom:1px solid rgba(255,255,255,.08);backdrop-filter:blur(8px)}
.tv .topnav b{color:#fff}
.tv .topnav .lk{color:#B9CBE2}
.tv .topnav .lk.act{color:#FFB8C9}
.tv .topnav .lk:hover{color:#fff}

.tvhero{position:relative;height:340px;display:flex;align-items:flex-end;padding:0 32px 24px;overflow:hidden}
.tvhero .bgv{position:absolute;inset:0;background:linear-gradient(125deg,#0E3A6B,#08152A 60%,#3A0E23)}
.tvhero .bgv::after{content:"";position:absolute;inset:0;
  background:radial-gradient(circle at 72% 38%,rgba(242,67,110,.30),transparent 58%),
             radial-gradient(circle at 22% 72%,rgba(27,74,133,.55),transparent 62%);
  animation:drift 14s ease-in-out infinite alternate}
@keyframes drift{from{transform:scale(1) translate(0,0)}to{transform:scale(1.12) translate(-2.5%,-2%)}}
.tvhero .scrim{position:absolute;inset:0;background:linear-gradient(90deg,#08152A 8%,rgba(8,21,42,.72) 46%,transparent 78%),
  linear-gradient(0deg,#08152A 2%,transparent 42%)}
.tvhero .in2{position:relative;z-index:2;max-width:540px}
.tvhero .tag{display:inline-flex;align-items:center;gap:8px;font-size:11px;font-weight:800;letter-spacing:1.2px;
  color:#FFB8C9;margin-bottom:8px}
.tvhero h1{font-size:33px;font-weight:900;letter-spacing:-1px;margin:0 0 8px;line-height:1.08}
.tvhero p{color:#C6D6E8;font-size:14px;margin:0 0 16px;line-height:1.55}
.tvhero .meta{display:flex;gap:8px;align-items:center;margin-bottom:16px;font-size:12px;color:#C3D5EC}
.lvlchip{border:1px solid rgba(255,255,255,.35);border-radius:4px;padding:2px 8px;font-weight:700;font-size:11px;color:#fff}
.tvbtn{display:inline-flex;align-items:center;gap:8px;font-size:14px;font-weight:800;border:0;border-radius:7px;
  padding:12px 20px;background:#fff;color:#08152A;cursor:pointer;text-decoration:none}
.tvbtn.gh{background:rgba(255,255,255,.16);color:#fff;backdrop-filter:blur(4px)}
.tvhero .mute{position:absolute;right:30px;bottom:28px;z-index:3;width:34px;height:34px;border-radius:50%;
  border:1px solid rgba(255,255,255,.4);display:grid;place-items:center;color:#fff;font-size:13px;cursor:pointer}

.tvrow{margin:0 0 32px;position:relative}
.tvrow h3{font-size:15px;font-weight:800;margin:0 0 12px;padding:0 32px;color:#fff;letter-spacing:-.2px;
  display:flex;align-items:center;gap:8px}
.tvrow h3 span{font-size:11px;font-weight:600;color:#A8C0DC;letter-spacing:0}
.tvviewport{position:relative;overflow:visible}
.tvtrack{display:flex;gap:12px;padding:32px 32px;transition:transform .45s cubic-bezier(.22,.61,.36,1);will-change:transform}
.tvnav{position:absolute;top:34px;bottom:34px;width:38px;background:rgba(6,17,33,.78);border:0;color:#fff;
  font-size:17px;cursor:pointer;z-index:20;display:grid;place-items:center;opacity:0;transition:.2s}
.tvviewport:hover .tvnav{opacity:1}
.tvnav.l{left:0}.tvnav.r{right:0}
.tvnav:hover{background:rgba(6,17,33,.95)}

.tvcard{flex:0 0 208px;width:208px;cursor:pointer;position:relative;
  transition:transform .3s cubic-bezier(.22,.61,.36,1);transform-origin:center bottom}
.tvcard .thumb{aspect-ratio:16/9;border-radius:7px;overflow:hidden;position:relative;
  box-shadow:0 3px 12px rgba(0,0,0,.4)}
.tvcard .thumb .g{position:absolute;inset:0}
.tvcard .thumb .dur{position:absolute;right:6px;bottom:6px;background:rgba(0,0,0,.72);font-size:10px;
  padding:2px 8px;border-radius:3px;font-weight:600}
.tvcard .thumb .lk2{position:absolute;left:6px;top:6px;background:rgba(9,45,89,.9);font-size:9px;
  font-weight:800;letter-spacing:.5px;padding:2px 8px;border-radius:20px}
.tvcard .thumb .prog{position:absolute;left:0;right:0;bottom:0;height:3px;background:rgba(255,255,255,.22)}
.tvcard .thumb .prog i{display:block;height:100%;background:#F2436E}
.tvcard .cap{font-size:12px;color:#C6D6E8;margin-top:8px;line-height:1.35;font-weight:600}

/* état survolé — aperçu */
.tvcard.hot{transform:scale(1.24);z-index:30}
.tvcard .pop{position:absolute;left:0;right:0;top:0;background:#0E1F38;border-radius:7px;overflow:hidden;
  box-shadow:0 14px 40px rgba(0,0,0,.62);opacity:0;pointer-events:none;transition:opacity .18s}
.tvcard.hot .pop{opacity:1;pointer-events:auto}
.pop .prev{aspect-ratio:16/9;position:relative;overflow:hidden}
.pop .prev .anim{position:absolute;inset:0;animation:zoomslow 7s ease-out forwards}
@keyframes zoomslow{from{transform:scale(1)}to{transform:scale(1.16)}}
.pop .prev .shine{position:absolute;inset:0;
  background:linear-gradient(115deg,transparent 30%,rgba(255,255,255,.13) 50%,transparent 70%);
  background-size:260% 100%;animation:sweep 2.6s linear infinite}
@keyframes sweep{from{background-position:180% 0}to{background-position:-80% 0}}
.pop .prev .live{position:absolute;left:8px;top:8px;display:flex;align-items:center;gap:4px;font-size:9px;
  font-weight:800;letter-spacing:.8px;background:rgba(0,0,0,.5);padding:2px 8px;border-radius:20px}
.pop .prev .live i{width:5px;height:5px;border-radius:50%;background:#F2436E;animation:blink 1.1s infinite}
@keyframes blink{50%{opacity:.25}}
.pop .prev .tc{position:absolute;right:8px;bottom:11px;font-size:10px;font-family:ui-monospace,Menlo,monospace;
  background:rgba(0,0,0,.55);padding:2px 8px;border-radius:3px}
.pop .prev .mut{position:absolute;right:8px;top:8px;width:24px;height:24px;border-radius:50%;
  border:1px solid rgba(255,255,255,.45);display:grid;place-items:center;font-size:10px}
.pop .prev .pb{position:absolute;left:0;right:0;bottom:0;height:3px;background:rgba(255,255,255,.2)}
.pop .prev .pb i{display:block;height:100%;background:#F2436E;width:0}
.pop .info{padding:8px 12px 12px}
.pop .info .acts{display:flex;align-items:center;gap:8px;margin-bottom:8px}
.rndbtn{width:26px;height:26px;border-radius:50%;display:grid;place-items:center;font-size:11px;cursor:pointer}
.rndbtn.play{background:#fff;color:#08152A;font-size:10px}
.rndbtn.gh2{border:1.5px solid rgba(255,255,255,.45);color:#fff}
.pop .info h5{margin:0 0 4px;font-size:12px;font-weight:800;color:#fff;line-height:1.3}
.pop .info .mt{font-size:10px;color:#8FA8C4;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.pop .info .mt b{color:#4ADE80;font-weight:800}
.pop .info .tags{margin-top:4px;font-size:10px;color:#C6D6E8}
.tvrow:last-child{margin-bottom:96px}
.tvfoot{padding:24px 32px 32px;border-top:1px solid rgba(255,255,255,.07);color:#A8C0DC;font-size:12px}
.tvchips{display:flex;gap:8px;flex-wrap:wrap;padding:0 32px 8px}
.tvchip{border:1px solid rgba(255,255,255,.18);border-radius:20px;padding:4px 12px;font-size:12px;
  color:#C6D6E8;cursor:pointer;font-weight:600}
.tvchip:hover{border-color:#fff;color:#fff}
.tvchip.on{background:#fff;color:#08152A;border-color:#fff;font-weight:800}

/* ── espace abonnements (membre) ── */
.member{background:linear-gradient(135deg,var(--navy),var(--navy-l));color:#fff;border-radius:12px;padding:20px 24px;margin-bottom:24px}
.member .lb{font-size:11px;letter-spacing:1.1px;color:#B4C8E0;font-weight:800}
.member h3{margin:8px 0 4px;font-size:22px;font-weight:900}
.member .row{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-top:16px;padding-top:16px;border-top:1px solid rgba(255,255,255,.16)}
.member .row div span{display:block;font-size:11px;letter-spacing:.8px;color:#B4C8E0;font-weight:700;margin-bottom:2px}
.member .row div b{font-size:15px}
.inv{width:100%;border-collapse:separate;border-spacing:0;font-size:13px}
.inv th{text-align:left;font-size:11px;letter-spacing:.7px;color:var(--soft2);font-weight:800;padding:8px 12px;border-bottom:1px solid var(--brd)}
.inv td{padding:8px 12px;border-bottom:1px solid var(--brd2)}

/* ── TFA KIDS ── */
.kidshero{background:linear-gradient(155deg,#0E3A6B,var(--navy-d));color:#fff;padding:48px 24px;position:relative;overflow:hidden}
.kidshero .blob{position:absolute;border-radius:50%}
.kidshero h1{font-size:36px;font-weight:900;letter-spacing:-1px;margin:12px 0 12px;line-height:1.1}
.kidshero h1 em{color:#FFB8C9;font-style:normal}
.kidshero p{color:#C6D6E8;font-size:16px;max-width:470px;margin:0 0 20px}
.agegrid{display:grid;grid-template-columns:repeat(6,1fr);gap:12px}
.age{background:#fff;border:1px solid var(--brd);border-radius:13px;padding:16px 12px;text-align:center;
  box-shadow:var(--sh);cursor:pointer;transition:.15s}
.age:hover{transform:translateY(-3px);box-shadow:var(--sh2);border-color:var(--crimson)}
.age .cl{font-size:19px;font-weight:900;color:var(--navy);letter-spacing:-.5px}
.age .ag{font-size:11px;color:var(--soft2);font-weight:600;margin-top:2px}
.age .bar2{height:5px;border-radius:4px;background:var(--blue);margin-top:8px;overflow:hidden}
.age .bar2 i{display:block;height:100%;background:var(--crimson);border-radius:4px}
.kcard{background:#fff;border:1px solid var(--brd);border-radius:14px;padding:16px;box-shadow:var(--sh)}
.kcard .ki{width:44px;height:44px;border-radius:12px;background:var(--rose);display:grid;place-items:center;
  font-size:20px;margin-bottom:12px}
.kcard h4{margin:0 0 4px;font-size:15px;color:var(--navy);font-weight:800}
.kcard p{margin:0;font-size:13px;color:var(--soft)}
.noteedit{background:var(--sand);border:1px solid var(--sand2);border-radius:11px;padding:16px 16px;font-size:13px;color:#6B5A42}
.noteedit b{color:var(--navy)}
.badgewall{display:flex;gap:8px;flex-wrap:wrap}
.bdg{width:58px;height:58px;border-radius:50%;background:var(--blue);border:2px solid var(--brd);
  display:grid;place-items:center;font-size:20px;color:var(--soft2)}
.bdg.on{background:var(--rose);border-color:var(--crimson);color:var(--crimson)}
.childtab{display:flex;gap:8px;margin-bottom:16px}
.child{background:#fff;border:1.5px solid var(--brd);border-radius:11px;padding:8px 16px;display:flex;
  align-items:center;gap:12px;cursor:pointer;font-size:14px}
.child.on{border-color:var(--crimson);background:var(--rose)}
.child .av{width:30px;height:30px;border-radius:9px;background:var(--navy);color:#fff;display:grid;
  place-items:center;font-weight:800;font-size:12px}
.rgpd{background:#fff;border:1px dashed var(--crimson);border-radius:10px;padding:12px 16px;font-size:13px;color:var(--soft)}
.rgpd b{color:var(--crimson-d)}

.site{position:relative}
.site:not(footer)::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;opacity:.035;
  background-image:var(--bul),var(--bul);
  background-repeat:no-repeat;
  background-position:-60px 9%, calc(100% + 80px) 31%;
  background-size:330px,270px}
.site > *{position:relative;z-index:1}
.site > .topnav{z-index:30}
.sep{height:1px;background:var(--brd);margin:24px 0}
.mini{font-size:12px;color:var(--soft2)}

/* ── surcharges finales (doivent passer après les règles de base) ── */
.pm{overflow:visible;padding-top:0}
.pm .cap2{height:5px;margin:0 -12px 12px;display:block;border-radius:11px 11px 0 0}
.pm .p2{color:var(--acc,var(--navy))}
.pm ul li{padding:2px 0 2px 16px;position:relative;font-size:12px}
.pm ul li::before{content:"✓";position:absolute;left:1px;top:2.5px;color:var(--acc,var(--green));
  font-weight:900;font-size:11px}
.pm ul li.no{color:var(--soft2)}
.pm ul li.no::before{content:"✗";color:var(--crimson)}
.card .cap2{height:5px;margin:-20px -20px 16px;display:block;border-radius:11px 11px 0 0}
.card .price{color:var(--acc,var(--navy))}
.card ul.ck li::before{content:"✓";color:var(--acc,var(--green));font-weight:900}
.card ul.ck li.no::before{content:"—";color:var(--soft2)}
.blk.pricing .pm{box-shadow:0 3px 14px rgba(9,45,89,.10)}
.blk.pricing .card{box-shadow:0 3px 14px rgba(9,45,89,.10)}

/* ══════════════════════════════════════════════════════════════
   THÈME SOMBRE CHAUD — activé par body.dark
   Navy et crimson restent la marque ; seules les surfaces changent.
   ══════════════════════════════════════════════════════════════ */
body.dark{
  --paper:#11161F;      /* fond de page — sombre chaud */
  --navy:#DCE4F2;       /* devient l'encre claire des titres */
  --navy-d:#080C12;
  --navy-l:#2C3A5E;
  --crimson:#F2436E;    /* crimson éclairci, lisible sur sombre */
  --crimson-d:#C0093A;  /* crimson d'origine, réservé aux fonds */
  --blue:#1A222E;
  --rose:#2E181E;
  --brd:#2E394A;
  --brd2:#232C3A;
  --ink:#E9EEF6;
  --soft:#B0B9C8;
  --soft2:#8692A4;
  --green:#4FBE7B;
  --sand:#2B2318;
  --sand2:#3D3324;
  --sh:0 1px 2px rgba(0,0,0,.50), 0 5px 14px -3px rgba(0,0,0,.35);
  --sh2:0 2px 5px rgba(0,0,0,.50), 0 24px 48px -14px rgba(0,0,0,.55);
  --nvb:#22345C;        /* navy utilisable comme fond */
  --surf:#182130;       /* surface des cartes */
  --surf2:#1E293A;      /* surface surélevée */
}
body.dark{background:#0B0F16}
body.dark #stage{background:#0B0F16}
body.dark .screenhead h2{color:#E4EBF5}
body.dark .screenhead .cmt{color:#8692A4}
body.dark .browser{border-color:#242F40}
body.dark .chrome{background:#1C2636;border-bottom-color:#2B374A}

/* surfaces claires → surfaces sombres */
body.dark .screenhead .url,body.dark .bar,body.dark .card,body.dark .exdemo,body.dark .pwcard,
body.dark .slot,body.dark .kpicard,body.dark .ritem,body.dark .pcard,body.dark .arch,
body.dark .legend,body.dark .fmt,body.dark .tcard,body.dark .qtop .tmr,body.dark .opt,
body.dark .exsent,body.dark .mistake,body.dark .qcard2,body.dark .pm,body.dark .age,
body.dark .kcard,body.dark .child,body.dark .rgpd,body.dark .archbox .tech,
body.dark .sharedtbl td:nth-child(3),body.dark .browser{background:var(--surf);border-color:var(--brd)}
body.dark .topnav{background:#151C28;border-bottom-color:var(--brd)}
body.dark .pnotch{background:#151C28;color:var(--ink)}
body.dark .ptab{background:#151C28;border-top-color:var(--brd)}
body.dark .ring::after{background:var(--surf)}
body.dark .billsw .knob::after{background:#E9EEF6}
body.dark .book{background:var(--surf);border-color:var(--brd)}
body.dark .site{background:var(--paper)}

/* fonds « blancs » des sections → dégradé sombre chaud */
body.dark .blk.wt{background:
  radial-gradient(circle at 10% 12%, rgba(90,120,190,.10), transparent 44%),
  radial-gradient(circle at 90% 88%, rgba(192,9,58,.13), transparent 46%),
  linear-gradient(180deg,#131922 0%,#11161F 60%,#101620 100%)}
body.dark .blk.wt::before,body.dark .blk.wt::after{opacity:.07}
body.dark .blk.pricing{background:
  radial-gradient(circle at 82% 8%, rgba(192,9,58,.20), transparent 48%),
  radial-gradient(circle at 6% 88%, rgba(43,74,133,.26), transparent 50%),
  linear-gradient(160deg,#151C28 0%,#11161F 50%,#141B26 100%)}
body.dark .blk.pricing::before{background:radial-gradient(circle,rgba(255,255,255,.05),transparent 62%)}

/* fonds navy conservés en vrai navy */
body.dark .btn.nv{background:#2C4E86}
body.dark .btn.nv:hover{background:#38609F}
body.dark .waitlist{background:linear-gradient(135deg,#1C3357,#14203A)}
body.dark .sharedtbl th{background:var(--nvb)}
body.dark .billsw span.on,body.dark .audsw b.on,body.dark .child .av,
body.dark .avatar{background:var(--nvb);color:#fff}
body.dark .fill{background:#6E8FD6}
body.dark .track{background:#1E2838}
body.dark .badge{background:var(--blue);color:var(--ink);border-color:var(--brd)}

/* fonds crimson : garder le crimson d'origine sous le texte blanc */
body.dark .btn,body.dark .hbtn,body.dark .pill,body.dark .chip,body.dark .billbadge,
body.dark .mnum,body.dark .fmt .n2,body.dark .opt.ko .ltr,body.dark .slot.sel,
body.dark .audsw b.kid.on,body.dark .card.hi::after,body.dark .pm.best::after,
body.dark .chaphero .chip,body.dark .play,body.dark .qprog i,body.dark .age .bar2 i,
body.dark .fill.weak,body.dark body.annual .billsw .knob{background:var(--crimson-d);color:#fff}
body.dark .btn:hover,body.dark .hbtn:hover{background:#8E0A2E}
body.dark .btn.gh{background:transparent;color:var(--ink);border-color:var(--brd)}
body.dark .btn.ghost{background:transparent;color:var(--soft);border-color:var(--brd)}
body.dark .hbtn.o{background:rgba(255,255,255,.10);border-color:rgba(255,255,255,.42)}
body.dark .btn.w{background:#E9EEF6;color:#11161F}
body.dark .tvbtn{background:#E9EEF6;color:#0B0F16}
body.dark .tvchip.on{background:#E9EEF6;color:#0B0F16}
body.dark .rndbtn.play{background:#E9EEF6;color:#0B0F16}
body.dark .qbig{background:#E9EEF6;color:#11161F}

/* tableaux */
body.dark th{background:var(--nvb)}
body.dark th:nth-child(2){background:var(--crimson-d)}
body.dark td{border-bottom-color:var(--brd2)}
body.dark table.tb th{background:transparent;color:var(--soft2);border-bottom-color:var(--brd)}
body.dark table.tb td{border-bottom-color:var(--brd2)}
body.dark .inv th{background:transparent;color:var(--soft2)}

/* encadrés */
body.dark .examples{background:var(--surf2);border-left-color:#6E8FD6;box-shadow:none}
body.dark .watchout{background:#2E181E;border-left-color:var(--crimson)}
body.dark .tbody{background:var(--surf2);border-color:var(--brd)}
body.dark .nw{background:var(--surf);border-left-color:var(--crimson)}
body.dark .expl{background:var(--surf2);border-left-color:#6E8FD6}
body.dark .reco{background:#2E181E;border-left-color:var(--crimson)}
body.dark .starnote{background:#2B2318;border-color:#3D3324;color:#D6C8A8}
body.dark .starnote b{color:#E9EEF6}
body.dark .noteedit{background:#2B2318;border-color:#3D3324;color:#D6C8A8}
body.dark .b2b{background:linear-gradient(120deg,#2B2318,#3A2A22)}
body.dark .b2b p{color:#CDBFA6}
body.dark .kidsband{background:linear-gradient(120deg,#2B2318,#332025);border-color:#3D3324}
body.dark .kidsband p{color:#CDBFA6}
body.dark .samplebox{background:#2E181E}
body.dark .qimg{background:linear-gradient(155deg,#1B2433,#2C181D);border-color:#313D50}
body.dark .illus{border-color:#313D50}
body.dark .opt.ok{background:#16301F;border-color:var(--green)}
body.dark .opt.ko{background:#33151D;border-color:var(--crimson)}
body.dark .fld.ok{background:#16301F}
body.dark .fld.ko{background:#33151D}
body.dark .st.ok{background:#16301F;color:#69D394}
body.dark .st.wt{background:#332612;color:#E5A83E}
body.dark .st.dn{background:var(--blue);color:var(--soft)}
body.dark .mini,body.dark .lead,body.dark p{color:var(--soft)}
body.dark .cap,body.dark .pcap{color:var(--soft)}
body.dark footer.site{background:#080C12}
body.dark .sep{background:var(--brd)}
body.dark .heroctn p,body.dark .hero p{color:#C6D6E8}
body.dark .exfoot{border-top-color:var(--brd)}
body.dark .qfoot{border-top-color:var(--brd)}
body.dark input[type=text],body.dark .wlform input{background:var(--surf2);color:var(--ink);border-color:var(--brd)}
body.dark .wlform input::placeholder{color:var(--soft2)}
body.dark .serthumb,body.dark .qimg{border-color:#313D50}
body.dark .dotl{background:rgba(255,255,255,.22)}
body.dark .bdg{background:var(--surf2);border-color:var(--brd)}
body.dark .bdg.on{background:#33151D;border-color:var(--crimson)}
body.dark .sday{background:var(--surf2);color:var(--soft2)}
body.dark .sday.on{background:#2E7D50;color:#fff}

/* bascule de thème dans le navigateur de maquette */
.themesw{display:flex;gap:4px;margin:12px 16px 0;background:rgba(255,255,255,.07);
  border-radius:20px;padding:4px}
.themesw b{flex:1;text-align:center;font-size:11px;font-weight:800;letter-spacing:.6px;
  padding:4px 0;border-radius:20px;color:#B4C8E0;cursor:pointer;transition:.15s}
.themesw b.on{background:#fff;color:#0B2542}
body.dark .themesw b.on{background:var(--crimson-d);color:#fff}


/* dégradés navy : forcés en vrai navy sombre (— navy sert d'encre en mode sombre) */
body.dark .hero{background:linear-gradient(160deg,#183258,#0B1526)}
body.dark .chaphero{background:linear-gradient(160deg,#183258,#0B1526)}
body.dark .book .cv{background:linear-gradient(165deg,#1B3355,#0C1728)}
body.dark .avatar{background:linear-gradient(150deg,#22406E,#16294A)}
body.dark .next{background:linear-gradient(135deg,#1D3559,#2A3F66)}
body.dark .quickband{background:linear-gradient(120deg,#1D3559,#2A3F66)}
body.dark .leveltest{background:linear-gradient(125deg,#1D3559,#27364E)}
body.dark .member{background:linear-gradient(135deg,#1D3559,#27364E)}
body.dark .kidsband .kf{background:linear-gradient(150deg,#22406E,var(--crimson-d))}
body.dark .ladder{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.13)}
body.dark .who.pub{background:#22345C;color:#CBD9EE}
body.dark .who.eleve{background:#1B3A29;color:#8FDCAC}
body.dark .who.prof{background:#24334A;color:#A8BCDC}
body.dark .who.app{background:#3A1A23;color:#E7ABBB}
body.dark .heroimg .ph{border-left-color:rgba(255,255,255,.24)}
body.dark .leveltest p,body.dark .quickband p,body.dark .next p,body.dark .member p{color:#C6D6E8}
body.dark .leveltest h2,body.dark .quickband h3,body.dark .next h4,body.dark .member h3{color:#fff}
body.dark .ltfacts div b{color:#fff}
body.dark .waitlist h3{color:#fff}
body.dark .waitlist p{color:#B9CBE2}
body.dark .b2b h3,body.dark .kidsband h3{color:#F0E6D2}
body.dark .qbtns .qsm{border-color:rgba(255,255,255,.38);color:#fff}

/* ══════════════════════════════════════════════════════════════
   THÈME SOMBRE — version 2 : moins sombre, plus de bulles,
   barre latérale rouge translucide.
   ══════════════════════════════════════════════════════════════ */
body.dark{
  --paper:#1D2533;      /* fond de page — remonté, moins sombre */
  --navy:#E4EAF6;
  --navy-d:#131B27;
  --navy-l:#3A4770;
  --crimson:#FF5C87;
  --crimson-d:#C0093A;
  --blue:#253042;
  --rose:#3B2229;
  --brd:#3C4A61;
  --brd2:#2F3C52;
  --ink:#EEF2F9;
  --soft:#BDC6D4;
  --soft2:#939FB2;
  --green:#5FCB8A;
  --sand:#372D1F;
  --sand2:#4A3D2B;
  --nvb:#2C4470;
  --surf:#242F40;
  --surf2:#2C384C;
  --sh:0 1px 3px rgba(0,0,0,.4);
  --sh2:0 10px 30px rgba(0,0,0,.45);
}
body.dark{background:#171E29}
body.dark #stage{background:#171E29}

/* ── champ de bulles en fond de site ── */
body.dark .site{position:relative;background:var(--paper)}
body.dark .site:not(footer)::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;opacity:.085;
  background-image:var(--bul),var(--bul);
  background-repeat:no-repeat;
  background-position:-60px 8%, calc(100% + 80px) 29%;
  background-size:340px,280px}
body.dark .site > *{position:relative;z-index:1}
body.dark .site > .topnav{z-index:30}
.site > .topnav{z-index:30}

/* filigranes plus présents */
body.dark .blk.wt::before{opacity:.10;width:300px;height:300px}
body.dark .blk.wt::after{opacity:.075;width:250px;height:250px}
body.dark .blk.pricing::after{content:"";position:absolute;right:-40px;bottom:60px;width:240px;height:240px;
  background:var(--bul) center/contain no-repeat;opacity:.09;pointer-events:none}
body.dark .blk.wt{background:
  radial-gradient(circle at 10% 12%, rgba(110,140,215,.13), transparent 44%),
  radial-gradient(circle at 90% 88%, rgba(255,92,135,.12), transparent 46%),
  linear-gradient(180deg,#242F40 0%,#1F2938 60%,#202938 100%)}
body.dark .blk.pricing{background:
  /* fondu du bas vers le fond de page : sans lui, le bord bas du panneau
     (plus clair) tranchait net sur le fond sombre, et le bloc Club posé
     juste dessous paraissait coincé entre deux fonds */
  linear-gradient(180deg, transparent 66%, #11161F 100%),
  radial-gradient(circle at 82% 8%, rgba(255,92,135,.18), transparent 48%),
  radial-gradient(circle at 6% 88%, rgba(80,115,195,.22), transparent 50%),
  linear-gradient(160deg,#263246 0%,#1F2938 50%,#232E40 100%)}
body.dark .blk.pricing::before{background:radial-gradient(circle,rgba(255,255,255,.045),transparent 62%)}

/* ── barre latérale rouge translucide (thème sombre) ── */
body.dark #nav{background:
  linear-gradient(180deg, rgba(120,18,48,.82) 0%, rgba(88,16,42,.86) 46%, rgba(58,14,34,.92) 100%),
  #1B2028;
  border-right:1px solid rgba(255,255,255,.07)}
body.dark #nav::before{content:"";position:absolute;left:-50px;top:-30px;width:230px;height:230px;
  background:var(--bul) center/contain no-repeat;opacity:.07;pointer-events:none}
body.dark #nav::after{content:"";position:absolute;right:-60px;bottom:40px;width:190px;height:190px;
  background:var(--bul) center/contain no-repeat;opacity:.05;pointer-events:none}
body.dark #nav{position:relative;overflow-x:hidden}
body.dark #nav .brand{border-bottom-color:rgba(255,255,255,.16)}
body.dark #nav .brand span{color:#E6A9B9}
body.dark #nav h4{color:#E29CAF}
body.dark #nav a{color:#F0DCE1}
body.dark #nav a:hover{background:rgba(255,255,255,.09)}
body.dark #nav a.on{background:rgba(255,255,255,.16);border-left-color:#FFB3C7;color:#fff}
body.dark #nav .note{background:rgba(0,0,0,.22);color:#E3C3CC}
body.dark .themesw{background:rgba(0,0,0,.25)}
body.dark .themesw b{color:#EDCAD3}
body.dark .themesw b.on{background:#FFD8E2;color:#511727}

/* surfaces remontées */
body.dark .browser{border-color:#3C4A61}
body.dark .chrome{background:#2C384C;border-bottom-color:#3C4A61}
body.dark .topnav{background:#273346;border-bottom-color:var(--brd)}
body.dark .pnotch,body.dark .ptab{background:#273346}
body.dark .track{background:#334055}
body.dark footer.site{background:#192230}
body.dark .fill{background:#8AA6E4}

/* mode automatique : indicateur */
.themesw{display:flex;gap:4px;margin:12px 16px 0;background:rgba(255,255,255,.07);border-radius:20px;padding:4px}
.themesw b{flex:1;text-align:center;font-size:10px;font-weight:800;letter-spacing:.5px;
  padding:4px 0;border-radius:20px;color:#B4C8E0;cursor:pointer;transition:.15s}
.themesw b.on{background:#fff;color:#0B2542}
.thnote{margin:8px 16px 0;font-size:10px;color:#6E8BB0;line-height:1.5}
body.dark .thnote{color:#D3A6B2}

/* ══════════════════ LE CLUB & RENCONTRES NATIVES ══════════════════ */
.clubband{display:grid;grid-template-columns:1.35fr 1fr;gap:24px;align-items:center;
  background:linear-gradient(118deg,#07182C 0%,#0D2E56 48%,#16406F 100%);
  border-radius:14px;padding:24px 28px;color:#fff;margin-bottom:16px;position:relative;overflow:hidden}
.clubband::after{content:"";position:absolute;right:-40px;bottom:-70px;width:280px;height:280px;
  background:var(--bul) center/contain no-repeat;opacity:.07;pointer-events:none}
.clubband .lb{font-size:11px;font-weight:800;letter-spacing:1.7px;color:#FFB8C9;margin-bottom:8px}
.clubband h3,.clubband h1{margin:0 0 8px;font-size:25px;font-weight:900;letter-spacing:-.4px;line-height:1.15}
.clubband p{margin:0;font-size:14px;line-height:1.65;color:#D4E0F2;max-width:52ch}
.clubkpi{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;position:relative;z-index:1}
.clubkpi div{background:rgba(255,255,255,.12);border:1px solid rgba(255,255,255,.2);
  border-radius:10px;padding:12px 12px;text-align:center}
.clubkpi b{display:block;font-size:21px;font-weight:900;letter-spacing:-.5px}
.clubkpi span{display:block;font-size:10px;font-weight:700;letter-spacing:.8px;color:#C7D6EC;margin-top:2px}

.accessbar{display:flex;align-items:center;gap:16px;flex-wrap:wrap;
  background:var(--surf,#fff);border:1px solid var(--brd);border-left:4px solid var(--green);
  border-radius:11px;padding:12px 16px;margin-bottom:20px}
.acbadge{flex:0 0 auto;font-size:11px;font-weight:800;letter-spacing:.6px;
  background:#E6F3EA;color:var(--green);border-radius:20px;padding:4px 12px}
body.dark .acbadge{background:#16301F;color:#8FDCAC}
.accessbar .txt{flex:1;min-width:260px}
.accessbar .txt b{display:block;font-size:14px}
.accessbar .txt span{display:block;font-size:12px;color:var(--soft);line-height:1.6;margin-top:2px}
.acnote{font-size:11px;font-weight:700;color:var(--soft);background:var(--blue);
  border-radius:7px;padding:8px 12px}

.clubwrap{display:grid;grid-template-columns:266px 1fr;gap:16px;align-items:start}
.roomcol{background:var(--surf,#fff);border:1px solid var(--brd);border-radius:12px;overflow:hidden}
.roomhead{padding:12px 16px 12px;border-bottom:1px solid var(--brd2)}
.roomhead b{font-size:11px;font-weight:800;letter-spacing:1.1px;color:var(--soft)}
.roomsearch{display:block;width:100%;margin-top:8px;font:inherit;font-size:12px;
  border:1px solid var(--brd);border-radius:7px;padding:8px 12px;background:var(--surf2,#F7FAFD);color:var(--ink)}
.roomgrp{padding:12px 12px 4px;font-size:10px;font-weight:800;letter-spacing:1.2px;color:var(--soft2)}
.room{display:flex;align-items:center;gap:12px;padding:8px 12px;cursor:pointer;border-left:3px solid transparent}
.room:hover{background:var(--surf2,#F3F7FC)}
.room.on{background:var(--blue);border-left-color:var(--crimson)}
.room .rl{width:30px;height:30px;flex:0 0 30px;border-radius:8px;display:grid;place-items:center;
  font-size:10px;font-weight:800;color:#fff;letter-spacing:.3px}
.room .rt{flex:1;min-width:0}
.room .rt b{display:block;font-size:13px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.room .rt span{display:block;font-size:11px;color:var(--soft)}
.room .rn{font-size:11px;font-weight:800;color:var(--soft);white-space:nowrap}
.online{display:inline-block;width:6px;height:6px;border-radius:50%;background:var(--green);margin-right:4px}

.chatcol{background:var(--surf,#fff);border:1px solid var(--brd);border-radius:12px;overflow:hidden;
  display:flex;flex-direction:column}
.chathead{display:flex;align-items:center;gap:12px;padding:12px 16px;border-bottom:1px solid var(--brd2);flex-wrap:wrap}
.chathead h4{margin:0;font-size:15px;font-weight:800}
.chathead .sub{font-size:12px;color:var(--soft)}
.chathead .rt2{margin-left:auto;display:flex;align-items:center;gap:8px}
.mini2{font-size:11px;font-weight:800;letter-spacing:.5px;border-radius:20px;padding:4px 12px;
  background:var(--blue);color:var(--navy)}
body.dark .mini2{background:var(--surf2);color:var(--ink)}

.livebar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  background:linear-gradient(100deg,#7A1030,#B00836);color:#fff;padding:12px 16px}
.livebar .ld{width:8px;height:8px;border-radius:50%;background:#FFC9D6;animation:bob 1.6s ease-in-out infinite}
.livebar b{font-size:13px;font-weight:800}
.livebar span{font-size:12px;color:#FFD6E1}
.livebar .join{margin-left:auto;background:#fff;color:#7A1030;font-size:11px;font-weight:800;
  border-radius:7px;padding:8px 12px;cursor:pointer}

.thread{padding:16px;display:flex;flex-direction:column;gap:12px;background:var(--surf2,#FAFCFE)}
.msg{display:flex;gap:8px;max-width:76%}
.msg .av{width:28px;height:28px;flex:0 0 28px;border-radius:8px;display:grid;place-items:center;
  font-size:10px;font-weight:900;color:#fff;background:linear-gradient(150deg,var(--navy-l),var(--navy))}
.msg .bb{background:var(--surf,#fff);border:1px solid var(--brd);border-radius:3px 11px 11px 11px;
  padding:8px 12px;font-size:13px;line-height:1.6}
.msg .nm{display:block;font-size:11px;font-weight:800;color:var(--soft);margin-bottom:4px}
.msg .tm{font-size:10px;color:var(--soft2);margin-top:4px;display:block}
.msg.me{align-self:flex-end;flex-direction:row-reverse}
.msg.me .bb{background:var(--blue);border-color:#BFD3EC;border-radius:11px 3px 11px 11px}
body.dark .msg.me .bb{background:#22345C;border-color:#31477A}
.msg.me .av{background:linear-gradient(150deg,#7A1030,var(--crimson-d))}
.msg.mentor .bb{background:#EDF3FB;border-color:#C8DAF0}
body.dark .msg.mentor .bb{background:#16263D;border-color:#2A3F5E}
.msg.mentor .av{background:linear-gradient(150deg,#123A66,#08213F)}
.mtag{display:inline-block;font-size:9px;font-weight:800;letter-spacing:.9px;border-radius:4px;
  padding:2px 8px;background:#123A66;color:#fff;margin-left:8px;vertical-align:1px}
.fixit{margin-top:8px;padding-top:8px;border-top:1px dashed var(--brd);font-size:12px}
.fixit s{color:var(--crimson);text-decoration-thickness:1.5px}
.fixit b{color:var(--green)}

.voice{display:flex;align-items:center;gap:8px;min-width:190px}
.voice .pl{width:26px;height:26px;flex:0 0 26px;border-radius:50%;background:var(--navy);color:#fff;
  display:grid;place-items:center;font-size:9px}
.wave{display:flex;align-items:flex-end;gap:2px;height:20px;flex:1}
.wave i{display:block;width:3px;border-radius:2px;background:var(--navy-l);opacity:.55}
.voice .dur{font-size:11px;font-weight:700;color:var(--soft)}

.composer{display:flex;align-items:center;gap:12px;padding:12px 16px;border-top:1px solid var(--brd2);
  background:var(--surf,#fff);flex-wrap:wrap}
.composer .fld2{flex:1;min-width:220px;border:1px solid var(--brd);border-radius:9px;padding:8px 12px;
  font-size:13px;color:var(--soft);background:var(--surf2,#FAFCFE)}
.cbtn{width:36px;height:36px;border-radius:9px;display:grid;place-items:center;font-size:14px;
  background:var(--blue);color:var(--navy);cursor:pointer}
body.dark .cbtn{background:var(--surf2);color:var(--ink)}
.cbtn.send{background:var(--crimson);color:#fff}
.enonly{width:100%;font-size:11px;color:var(--soft);display:flex;align-items:center;gap:8px}
.enonly b{color:var(--crimson)}

.charte{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-top:20px}
.chit{background:var(--surf,#fff);border:1px solid var(--brd);border-radius:11px;padding:12px 16px}
.chit .ci{font-size:17px;color:var(--crimson);margin-bottom:8px}
.chit b{display:block;font-size:13px;margin-bottom:4px}
.chit span{font-size:12px;color:var(--soft);line-height:1.6}

/* ── rencontres natives ── */
.ntband{background:linear-gradient(112deg,#0B2038,#123A5E 52%,#1B4A85);border-radius:14px;
  padding:24px 28px;color:#fff;margin-bottom:16px;position:relative;overflow:hidden}
.ntband::after{content:"";position:absolute;right:-30px;top:-60px;width:250px;height:250px;
  background:var(--bul) center/contain no-repeat;opacity:.07}
.ntband .lb{font-size:11px;font-weight:800;letter-spacing:1.7px;color:#8FD6E3;margin-bottom:8px}
.ntband h3,.ntband h1{margin:0 0 8px;font-size:25px;font-weight:900;letter-spacing:-.4px}
.ntband p{margin:0;font-size:14px;color:#CFE0F0;max-width:62ch;line-height:1.65}
.incl{display:inline-flex;align-items:center;gap:8px;margin-top:12px;background:rgba(255,255,255,.14);
  border:1px solid rgba(255,255,255,.26);border-radius:9px;padding:8px 12px;font-size:13px;position:relative;z-index:1}
.incl b{font-weight:800}

.natgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-bottom:16px}
.nat{background:var(--surf,#fff);border:1px solid var(--brd);border-radius:12px;padding:16px;position:relative}
.nat .top{display:flex;align-items:center;gap:12px;margin-bottom:12px}
.nat .ini{width:42px;height:42px;flex:0 0 42px;border-radius:11px;display:grid;place-items:center;
  font-size:14px;font-weight:900;color:#fff;background:linear-gradient(150deg,var(--navy-l),var(--navy))}
.nat h5{margin:0;font-size:15px;font-weight:800}
.nat .acc{font-size:12px;color:var(--soft)}
.nat p{margin:0 0 12px;font-size:13px;color:var(--soft);line-height:1.6}
.nat .slots{display:flex;gap:8px;flex-wrap:wrap}
.nslot{font-size:11px;font-weight:700;border:1px solid var(--brd);border-radius:7px;padding:4px 8px;
  background:var(--surf2,#F7FAFD);cursor:pointer}
.nslot.on{background:var(--navy);color:#fff;border-color:var(--navy)}
body.dark .nslot.on{background:#8AA6E4;color:#080C12;border-color:#8AA6E4}
.nat .tagf{position:absolute;top:14px;right:14px;font-size:10px;font-weight:800;letter-spacing:.6px;
  border-radius:20px;padding:4px 8px;background:var(--blue);color:var(--navy)}
body.dark .nat .tagf{background:var(--surf2);color:var(--ink)}

.report{display:grid;grid-template-columns:1fr 1.15fr;gap:16px;align-items:start;
  background:var(--surf,#fff);border:1px solid var(--brd);border-radius:12px;padding:20px 20px}
.report h4{margin:0 0 8px;font-size:16px;font-weight:800}
.report p{margin:0 0 12px;font-size:13px;color:var(--soft);line-height:1.65}
.rline{display:flex;align-items:center;gap:12px;margin-bottom:8px}
.rline .rn2{width:112px;flex:0 0 112px;font-size:12px;font-weight:700;color:var(--soft)}
.rbar{flex:1;height:9px;border-radius:5px;background:var(--brd2);overflow:hidden}
.rbar i{display:block;height:100%;border-radius:5px;background:var(--navy)}
body.dark .rbar i{background:#8AA6E4}
.rline .rv{width:78px;text-align:right;font-size:12px;font-weight:800}
.gain{font-size:11px;font-weight:800;color:var(--green)}

/* ══════════════════ CONNEXION & COMPTE (haut à droite) ══════════════════ */
.authbtns{display:flex;align-items:center;gap:8px}
.lgin{font-size:13px;font-weight:700;color:var(--navy);border:1px solid var(--brd);
  border-radius:8px;padding:8px 12px;cursor:pointer;white-space:nowrap;background:var(--surf,#fff)}
.lgin:hover{border-color:var(--navy);background:var(--blue)}
.sgup{font-size:13px;font-weight:800;color:#fff;background:var(--crimson);border-radius:8px;
  padding:8px 16px;cursor:pointer;white-space:nowrap;box-shadow:0 2px 8px rgba(192,9,58,.28)}
.sgup:hover{background:var(--crimson-d)}

.acct{position:relative;display:flex;align-items:center;gap:8px;padding:4px 8px 4px 4px;color:var(--ink);
  border:1px solid var(--brd);border-radius:9px;cursor:pointer;background:var(--surf,#fff)}
.acct:hover{border-color:var(--navy-l)}
.acct .avatar{width:30px;height:30px;font-size:12px;border-radius:7px;letter-spacing:0}
.acct .idn{line-height:1.25;text-align:left}
.acct .idn b{display:block;font-size:12px;font-weight:800;white-space:nowrap;color:var(--ink)}
.acct .idn span{display:block;font-size:10px;font-weight:700;color:var(--soft);white-space:nowrap}
.acct .chev{font-size:9px;color:var(--soft);margin-left:2px}
.dotlive2{display:inline-block;width:5px;height:5px;border-radius:50%;background:var(--green);
  margin-right:4px;vertical-align:1px}

.acctmenu{position:absolute;top:calc(100% + 8px);right:0;width:242px;z-index:40;
  background:var(--surf,#fff);border:1px solid var(--brd);border-radius:11px;
  box-shadow:var(--sh2);padding:8px;opacity:0;visibility:hidden;transform:translateY(-4px);
  transition:.16s;text-align:left;cursor:default}
.acct:hover .acctmenu,.acct.open .acctmenu{opacity:1;visibility:visible;transform:none}
.acctmenu .hd{padding:8px 12px 12px;border-bottom:1px solid var(--brd2);margin-bottom:4px}
.acctmenu .hd b{display:block;font-size:13px}
.acctmenu .hd span{display:block;font-size:11px;color:var(--soft);margin-top:2px}
.acctmenu .pl{display:inline-block;margin-top:8px;font-size:10px;font-weight:800;letter-spacing:.5px;
  background:var(--blue);color:var(--navy);border-radius:20px;padding:4px 8px}
.acctmenu a{display:flex;align-items:center;gap:8px;font-size:13px;font-weight:600;
  color:var(--ink);padding:8px 12px;border-radius:7px;text-decoration:none}
.acctmenu a i{font-style:normal;font-size:13px;color:var(--soft);width:15px;text-align:center}
.acctmenu a:hover{background:var(--blue)}
.acctmenu a .kb{margin-left:auto;font-size:10px;font-weight:700;color:var(--soft)}
.acctmenu .sp{height:1px;background:var(--brd2);margin:4px 0}
.acctmenu a.out{color:var(--crimson)}
.acctmenu a.out i{color:var(--crimson)}
.acctmenu a.out:hover{background:var(--rose)}

/* onglets de famille de la collection — alimentés par le catalogue */
.famtabs{display:flex;gap:8px;flex-wrap:wrap;margin-top:16px}
.ftab{display:inline-flex;align-items:center;gap:8px;font-size:13px;font-weight:700;
  border:1px solid var(--brd);border-radius:20px;padding:8px 12px;cursor:pointer;
  background:var(--surf,#fff);color:var(--ink);transition:.14s}
.ftab:hover{border-color:var(--navy-l)}
.ftab.on{background:var(--navy);color:#fff;border-color:var(--navy)}
body.dark .ftab.on{background:#22406E;color:#fff;border-color:#3A5F9E}
.ftab b{font-size:11px;font-weight:800;background:var(--blue);color:var(--navy);
  border-radius:20px;padding:2px 8px}
.ftab.on b{background:rgba(255,255,255,.22);color:#fff}
body.dark .ftab b{background:var(--surf2);color:var(--ink)}
.books{grid-template-columns:repeat(auto-fill,minmax(min(168px,100%),1fr))}
.code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:1.75;
  background:var(--surf,#fff);border:1px solid var(--brd);border-radius:8px;
  padding:12px 12px;margin-top:8px;color:var(--ink)}
.code i{font-style:normal;color:var(--navy-l);font-weight:700}
body.dark .code i{color:#9CBDF0}

/* ══════════ CORRECTIONS DE CONTRASTE — vérifiées par contrast_check.py ══════════
   Chaque règle ci-dessous répare un couple texte/fond mesuré sous 4.5:1
   (3:1 pour le grand texte) dans l'un des deux thèmes.                          */

body.dark{--soft2:#9FACC0; --amber:#E7A63C}

/* surfaces de contenu restées blanches en thème sombre */
body.dark .browser,body.dark .card,body.dark .book,body.dark .exdemo,body.dark .pwcard,
body.dark .slot,body.dark .kpicard,body.dark .ritem,body.dark .pcard,body.dark .arch,
body.dark .legend,body.dark .fmt,body.dark .tcard,body.dark .opt,body.dark .exsent,
body.dark .mistake,body.dark .qcard2,body.dark .pm,body.dark .age,body.dark .kcard,
body.dark .child,body.dark .rgpd,body.dark .archbox .tech,body.dark .sharedtbl td:nth-child(3),
body.dark .qtop .tmr,body.dark .screenhead .url{background:var(--surf);border-color:var(--brd)}
body.dark .slot.full{background:var(--surf2);color:#96A2B4}
body.dark .opt.ok,body.dark .fld.ok{background:#16301F}
body.dark .opt.ko{background:#3A151F}
body.dark .expl{background:var(--surf2)}
body.dark .qbig{background:var(--surf2);color:var(--ink)}

/* crimson foncé employé comme encre : illisible sur fond sombre */
body.dark .who.app,body.dark .samplebox b,body.dark .reco>b:first-child,
body.dark .reco p b,body.dark .reco .ritem b,body.dark .rgpd b,
body.dark .tag,body.dark .lk.act,body.dark .eyebrow{color:#FF8AA8}

/* pastilles claires en thème sombre : l'encre repasse en foncé */
body.dark .opt.ok .ltr,body.dark .opt.ko .ltr{color:#080C12}
body.dark .sday.on{color:#fff}
body.dark .lvl,body.dark .lvlchip{color:#fff}

/* textes de repérage posés sur les blocs image */
body.dark .ph{color:rgba(255,255,255,.66)}
body.dark .ph em{color:rgba(255,255,255,.55)}
body.dark .scrollhint{color:rgba(255,255,255,.74)}

/* accents tarifaires codés en dur sur les cartes : version claire en thème sombre */
body.dark [style*="--acc:#092D59"]{--acc:#A9C4EE}
body.dark [style*="--acc:#1B4A85"]{--acc:#9CBDF0}
body.dark [style*="--acc:#5A6B7E"]{--acc:#BCC6D4}
body.dark [style*="--acc:#C0093A"]{--acc:#FF8AA8}
body.dark [style*="--acc:#1B4A85"]{--acc:#5CD2E0}
body.dark [style*="--acc:#092D59"]{--acc:#63D093}

/* le crimson de marque reste lisible quand il est posé sur un fond navy */
.leveltest .eyebrow,.hero .eyebrow,.chaphero .eyebrow{color:#FFB8C9}

/* inline styles : la déclaration en attribut l'emporte, il faut !important */
body.dark [style*="--acc:#092D59"]{--acc:#A9C4EE!important}
body.dark [style*="--acc:#1B4A85"]{--acc:#9CBDF0!important}
body.dark [style*="--acc:#5A6B7E"]{--acc:#BCC6D4!important}
body.dark [style*="--acc:#C0093A"]{--acc:#FF8AA8!important}
body.dark [style*="--acc:#5F3891"]{--acc:#C4A5F0!important}
body.dark [style*="--acc:#1B4A85"]{--acc:#5CD2E0!important}
body.dark [style*="--acc:#092D59"]{--acc:#63D093!important}
body.dark [style*="crimson-d"]{color:#FF8AA8!important}
body.dark .pbody[style*="#fff"]{background:var(--surf)!important}
body.dark .pcard[style*="linear-gradient"]{background:linear-gradient(135deg,#22345C,#324A7C)!important}
body.dark .room .rl[style*="--crimson"]{color:#260B12}

/* rail de la maquette : fond navy, l'encre secondaire doit s'éclaircir */
#nav .mini{color:#B4C8E0}

/* réserves d'images en fond clair : l'étiquette doit rester lisible */
.qimg .lbl2,.qimg .lbl2 b{color:#4B5A6B}

body.dark .qimg .lbl2,body.dark .qimg .lbl2 b{color:#B2BDCE}
body.dark .opt.ko .ltr{color:#fff}
body.dark [style*="background:#fff"]{background:var(--surf)!important;color:var(--ink)}

/* ══════════ RAIL DE MAQUETTE — navy de la charte, crimson pour l'actif ══════════ */
body.dark #nav{background:#08111F}
body.dark #nav .brand{border-bottom-color:rgba(255,255,255,.13)}
body.dark #nav .brand span{color:#93ADCB}
body.dark #nav h4{color:#8AA5C4}
body.dark #nav a{color:#DCE6F3}
body.dark #nav .mini{color:#9DB6D2}
body.dark #nav a:hover{background:rgba(255,255,255,.07)}
body.dark #nav a.on{background:rgba(192,9,58,.26);border-left-color:#FF6E92;color:#fff}
body.dark #nav .note{background:rgba(255,255,255,.05);color:#AFC4DB}
body.dark .themesw{background:rgba(255,255,255,.08)}
body.dark .themesw b{color:#A7BDD6}
body.dark .themesw b.on{background:#E9F0FA;color:#0B2542}
body.dark .thnote{color:#93ADCB}
body.dark .thpick .tip{background:#0B2542}
body.dark .thpick{background:rgba(255,255,255,.1)}

/* accents tarifaires : deux teintes navy et le crimson, rien d'autre */
body.dark [style*="--acc:#092D59"]{--acc:#A9C4EE!important}
body.dark [style*="--acc:#1B4A85"]{--acc:#9CBDF0!important}
body.dark [style*="--acc:#5A6B7E"]{--acc:#BCC6D4!important}
body.dark [style*="--acc:#C0093A"]{--acc:#FF8AA8!important}
body.dark [style*="--acc:#5F3891"]{--acc:#C4A5F0!important}

body.dark .sgup{background:#C0093A;color:#fff;box-shadow:none}
body.dark .sgup:hover{background:#8E0A2E}
body.dark .ptab .on,body.dark .ptab .on i{color:#FF9BB4}

/* le pied de page passe au-dessus du filigrane : il doit rester net */
footer.site{position:relative;z-index:2}

/* variante neutre du tableau : pas de colonne mise en avant */
.sharedtbl.plain th:nth-child(2){background:var(--navy)}
.sharedtbl.plain td:nth-child(2),.sharedtbl.plain td:nth-child(3){background:var(--blue)}
body.dark .sharedtbl.plain th:nth-child(2){background:var(--nvb)}
body.dark .sharedtbl.plain td:nth-child(2),body.dark .sharedtbl.plain td:nth-child(3){background:var(--surf)}


/* ═══ site.css ═══ */
/* ══════════════════════════════════════════════════════════════════════════
   TRULY FLUENT ACADEMY — ce que le site ajoute PAR-DESSUS la maquette.
   L'apparence de référence vit dans maquette_base.css ; ici seulement :
   la barre collante, le tiroir, le pied transparent, la page de connexion,
   la page de chapitre, et l'étiquette Premium.
   ══════════════════════════════════════════════════════════════════════════ */

/* évite l'éclair blanc avant que le script pose la classe dark */
html.pre-dark{background:#0E0B16}
html.pre-dark body{visibility:hidden}

/* variables de compatibilité pour les pages connexion / chapitre */
:root{--card:#F6FBFF;--surf2:#ECF4FD;--brd2:#CBDFF5;--soft2:#4E5A68;--green:#357946;--amber:#9B5F08}
body.dark{--card:var(--surf);--green:#5FCB8A;--amber:#E7A63C}

/* la barre du haut devient réelle : collante, et ses liens sont des liens */
.topnav.collante{position:sticky;top:0;z-index:80}
.topnav a.lk{text-decoration:none}
.topnav .lg b{white-space:nowrap}
.tiroirbtn{width:36px;height:34px;border-radius:9px;border:1px solid var(--brd);
  background:transparent;color:var(--ink);cursor:pointer;display:grid;place-items:center;
  padding:0;flex:0 0 auto}
.tiroirbtn:hover{border-color:var(--navy-l)}
.thpick{cursor:pointer}
.audsw a{text-decoration:none;color:inherit}
.authbtns .lgin a,.authbtns .sgup a{text-decoration:none;color:inherit}
@media (max-width:980px){
  .topnav .lk{display:none}
  .audsw,.topnav .rt .btn.sm{display:none}
}

/* ── le tiroir ☰ : navy, les bulles en fond, comme le rail de la maquette ── */
.voile{position:fixed;inset:0;background:rgba(4,10,20,.55);z-index:180;opacity:0;
  visibility:hidden;transition:.2s;backdrop-filter:blur(2px)}
.voile.ouvert{opacity:1;visibility:visible}
.tiroir{position:fixed;top:0;bottom:0;left:0;width:286px;z-index:190;overflow-y:auto;
  overflow-x:hidden;background:var(--navy-d);color:#DCE6F3;padding:16px 0 24px;
  transform:translateX(-100%);transition:transform .22s ease;
  box-shadow:4px 0 30px rgba(0,0,0,.4)}
body.dark .tiroir{background:#080C12}
.tiroir::before,.tiroir::after{content:"";position:absolute;pointer-events:none;
  background:var(--bul) center/contain no-repeat;opacity:.07}
.tiroir::before{left:-50px;top:-30px;width:230px;height:230px}
.tiroir::after{right:-60px;bottom:40px;width:190px;height:190px;opacity:.05}
.tiroir.ouvert{transform:none}
.tiroir .thead{display:flex;align-items:center;gap:8px;padding:2px 16px 12px;
  border-bottom:1px solid rgba(255,255,255,.13);position:relative;z-index:1}
.tiroir .thead .bulles{height:22px}
.tiroir .thead b{font-size:10px;letter-spacing:.7px;color:#fff}
.tfermer{margin-left:auto;width:30px;height:30px;border-radius:8px;border:0;cursor:pointer;
  background:rgba(255,255,255,.08);color:#DCE6F3;font-size:13px}
.tiroir h4{margin:20px 16px 8px;font-size:10px;letter-spacing:1.6px;color:#8AA5C4;
  font-weight:800;position:relative;z-index:1}
.tiroir a{display:flex;align-items:center;gap:12px;padding:8px 16px;font-size:14px;
  font-weight:600;color:#DCE6F3;text-decoration:none;border-left:3px solid transparent;
  position:relative;z-index:1}
.tiroir a i{font-style:normal;width:16px;text-align:center;font-size:12px;color:#93ADCB}
.tiroir a:hover{background:rgba(192,9,58,.22);border-left-color:#FF6E92;color:#fff}
.tiroir .tnote{margin:16px 16px 0;padding:12px 12px;border-radius:8px;font-size:11px;
  line-height:1.55;background:rgba(255,255,255,.06);color:#AFC4DB;position:relative;z-index:1}

/* ── le pied de page : transparent, deux bulles de part et d'autre, épuré ── */
footer.site{background:transparent!important;border-top:1px solid var(--brd);
  color:var(--soft);position:relative;overflow:hidden}
footer.site::before,footer.site::after{content:"";position:absolute;top:50%;width:250px;
  height:190px;background:var(--bul) center/contain no-repeat;opacity:.05;
  pointer-events:none;transform:translateY(-50%)}
footer.site::before{left:-70px}
footer.site::after{right:-70px;transform:translateY(-50%) scaleX(-1)}
footer.site .cols,footer.site .bot{position:relative;z-index:1}
footer.site h5{color:var(--ink)}
footer.site a{color:var(--soft)}
footer.site a:hover{color:var(--ink)}
footer.site .bot{border-top:1px solid var(--brd2);color:var(--soft2)}
footer.site [style*="color:#fff"]{color:var(--ink)!important}

/* ── l'étiquette Premium — épurée, transparente, à la place des cadenas ── */
.prem{position:absolute;top:8px;right:8px;font-size:9px;font-weight:800;
  letter-spacing:1.3px;text-transform:uppercase;color:#fff;
  border:1px solid rgba(255,255,255,.55);background:rgba(8,21,42,.38);
  backdrop-filter:blur(3px);border-radius:5px;padding:2px 8px;z-index:2}
.lock{background:transparent!important;border:1px solid var(--brd);
  color:var(--soft)!important;font-size:9px!important;font-weight:800;
  letter-spacing:1.2px;text-transform:uppercase;border-radius:5px;padding:2px 8px}

/* la note « bientôt » */
.authnote{display:none;margin-top:12px;background:var(--rose);
  border-left:3px solid var(--crimson);border-radius:0 9px 9px 0;
  padding:12px 12px;font-size:13px;color:var(--ink)}

/* installation sur téléphone */
#installer{position:fixed;left:50%;bottom:18px;transform:translateX(-50%);z-index:200;
  display:none;align-items:center;gap:12px;background:var(--navy);color:#fff;
  border-radius:12px;padding:12px 16px;box-shadow:0 10px 30px rgba(0,0,0,.4);
  max-width:calc(100% - 28px)}
body.dark #installer{background:#22406E}
#installer b{font-size:13px}
#installer span{font-size:12px;color:#C6D9F0;display:block}
#installer button{font:inherit;font-size:13px;font-weight:800;border:0;border-radius:8px;
  padding:8px 12px;cursor:pointer;background:#fff;color:var(--navy)}
#installer .fermer{background:transparent;color:#C6D9F0;padding:8px}

/* pages génériques (404, gabarits simples) */
.blk2{padding:54px 20px;max-width:1120px;margin:0 auto}
.sur{font-size:11px;font-weight:800;letter-spacing:1.9px;color:var(--crimson);margin-bottom:8px}
h2.t,h1.t{font-size:30px;font-weight:900;margin:0 0 8px;letter-spacing:-.4px}
p.lead2{font-size:16px;color:var(--soft);margin:0 0 16px}

/* ─────────────────────────── connexion & inscription ─────────────────────────── */
.authwrap{display:grid;grid-template-columns:1.15fr 1fr;gap:20px;align-items:start;
  max-width:940px;margin:0 auto}
.authcarte{background:var(--card);border:1px solid var(--brd);border-radius:15px;
  padding:24px 28px;box-shadow:var(--sh2)}
.authtabs{position:relative;isolation:isolate;display:flex;gap:0;
  background:var(--surf2);border:1px solid var(--brd2);
  border-radius:var(--r-pill);padding:4px;margin-bottom:20px}
.atab{position:relative;z-index:1;flex:1;font:inherit;font-size:14px;font-weight:800;
  border:0;border-radius:var(--r-pill);padding:9px 0;cursor:pointer;background:none;
  color:var(--soft);transition:color var(--t-app) var(--e)}
.atab.on{color:#fff}
.authtabs:hover .atab.on{color:var(--soft)}
.atab:hover{color:#fff}
/* la pastille glissante, mêmes couleurs de marque que le sélecteur Adulte/Kids */
.authpuce{position:absolute;z-index:0;top:4px;bottom:4px;left:0;border-radius:var(--r-pill);
  background:var(--teinte,var(--navy));
  box-shadow:0 4px 14px -4px color-mix(in srgb, var(--teinte,var(--navy)) 60%, transparent);
  transition:transform var(--t-app) var(--e),width var(--t-app) var(--e),
             background-color var(--t-app) var(--e),box-shadow var(--t-app) var(--e)}
body.dark .authpuce{background:var(--teinte,#23477B)}
/* le fondu d'entrée d'un volet quand on change d'onglet */
.avin{animation:avfond var(--t-app) var(--e) both}
@keyframes avfond{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.avin{animation:none}}
/* la marque des champs obligatoires, et la mention facultative */
.req{color:var(--crimson);font-weight:900;margin-left:1px}
body.dark .req{color:#FF9BB4}
.afac{font-weight:400;color:var(--soft2)}
.atitre{font-size:23px;font-weight:900;margin-bottom:4px}
.asous{font-size:14px;color:var(--soft);margin:0 0 16px}
.social{display:flex;align-items:center;justify-content:center;gap:12px;width:100%;
  font:inherit;font-size:14px;font-weight:700;border:1px solid var(--brd);
  border-radius:var(--r-pill);padding:12px 0;cursor:pointer;background:var(--card);
  color:var(--ink);margin-bottom:9px;
  transition:transform var(--t-etat) var(--e),box-shadow var(--t-etat) var(--e),
             border-color var(--t-etat) var(--e),background-color var(--t-etat) var(--e)}
.social:hover{border-color:var(--navy-l);background:var(--surf2);
  transform:translateY(-1.5px);box-shadow:0 10px 24px -12px rgba(9,45,89,.5)}
.social:active{transform:translateY(0) scale(.99)}
.asep{display:flex;align-items:center;gap:12px;margin:16px 0 12px;
  font-size:12px;color:var(--soft2)}
.asep::before,.asep::after{content:"";flex:1;height:1px;background:var(--brd2)}
.alab{display:block;font-size:12px;font-weight:700;color:var(--soft);margin:12px 0 4px}
.ain{display:block;width:100%;font:inherit;font-size:15px;color:var(--ink);
  background:var(--surf2);border:1px solid var(--brd);border-radius:9px;padding:12px 12px}
.ain:focus{outline:2px solid var(--crimson);outline-offset:1px;border-color:transparent}
.ain::placeholder{color:var(--soft2)}
.aoubli{text-align:right;margin-top:8px;font-size:12px}
.aoubli a{color:var(--navy-l);font-weight:700;text-decoration:none}
body.dark .aoubli a{color:#9CBDF0}
/* la ligne « se rappeler de moi » + « mot de passe oublié » */
.arem{display:flex;align-items:center;justify-content:space-between;gap:12px;
  margin-top:12px;font-size:12.5px}
.aoublia{color:var(--navy-l);font-weight:700;text-decoration:none;white-space:nowrap;
  padding:8px 2px;line-height:1.15}
.aoublia:hover{text-decoration:underline}
body.dark .aoublia{color:#9CBDF0}
.arembox{display:inline-flex;align-items:center;gap:8px;cursor:pointer;padding:6px 0;
  font-weight:600;color:var(--soft);user-select:none}
.arembox input{position:absolute;opacity:0;width:0;height:0}
.aremmark{width:19px;height:19px;flex:0 0 auto;border-radius:6px;
  border:1.5px solid var(--brd);background:var(--surf2);position:relative;
  transition:background-color var(--t-etat) var(--e),border-color var(--t-etat) var(--e)}
.aremmark::after{content:"";position:absolute;left:6px;top:2px;width:5px;height:10px;
  border:solid #fff;border-width:0 2.5px 2.5px 0;transform:rotate(45deg) scale(0);
  transition:transform var(--t-etat) var(--e)}
.arembox:hover .aremmark{border-color:var(--crimson)}
.arembox input:checked + .aremmark{background:var(--crimson);border-color:var(--crimson)}
.arembox input:checked + .aremmark::after{transform:rotate(45deg) scale(1)}
.arembox input:focus-visible + .aremmark{outline:2px solid var(--crimson);outline-offset:2px}
.alarge{display:block;width:100%;margin-top:16px;padding:13px 0;font-size:15px;
  font-weight:700;box-shadow:0 8px 22px -10px rgba(192,9,58,.55)}
.abas{margin:12px 0 0;text-align:center}
.abas a{color:var(--crimson);text-decoration:none}
.authnote{display:none;margin-top:12px;background:var(--rose);border-left:3px solid var(--crimson);
  border-radius:0 9px 9px 0;padding:12px 12px;font-size:13px}
.authnote.ok{background:rgba(60,180,110,.12);border-left-color:var(--green)}
.alarge:disabled{opacity:.6;cursor:default}
.authcote{background:linear-gradient(125deg,#07182C,#0D2E56 55%,#16406F);border-radius:15px;
  padding:24px 24px;color:#fff;position:sticky;top:76px}
.authcote ul{list-style:none;padding:0;margin:12px 0 16px}
.authcote li{position:relative;padding:8px 0 8px 24px;font-size:14px;line-height:1.55;color:#DCE7F5}
.authcote li::before{content:"✓";position:absolute;left:0;top:7px;color:#8FDCAC;font-weight:900}
.authcote li b{color:#fff}
@media (max-width:820px){
  .authwrap{grid-template-columns:1fr}
  .authcote{position:static}
}

/* ─────────────────────────── sélecteur Adultes / Enfants ─────────────────────────── */
.audsw{display:inline-flex;background:var(--surf2);border:1px solid var(--brd);
  border-radius:20px;padding:4px;gap:2px}
.audsw a{font-size:12px;font-weight:800;letter-spacing:.3px;text-decoration:none;
  color:var(--soft);border-radius:20px;padding:4px 12px}
.audsw a.on{background:var(--navy);color:var(--card)}
body.dark .audsw a.on{background:#22406E;color:#fff}
.audsw a.kid:hover{color:var(--crimson)}

/* ─────────────────────────── séries d'entraînement ─────────────────────────── */
.serfam{font-size:16px;font-weight:900;margin:24px 0 12px}
.sergrille{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(230px,100%),1fr));gap:12px}
.serie{position:relative;display:block;background:var(--card);border:1px solid var(--brd);
  border-radius:12px;padding:16px 16px 12px;box-shadow:var(--sh);transition:.15s}
a.serie:hover{transform:translateY(-2px);box-shadow:var(--sh2);border-color:var(--navy-l)}
.serie b{display:block;font-size:14px;margin:8px 0 4px}
.serie .smeta{display:block;font-size:12px;color:var(--soft2)}
.sniv{display:inline-block;font-size:10px;font-weight:800;color:#fff;
  border-radius:20px;padding:2px 8px}
.niv-a1{background:var(--a1)} .niv-a2{background:var(--a2)}
.niv-b1{background:var(--b1)} .niv-b2{background:var(--b2)} .niv-c1{background:var(--c1)}
.slibre{display:inline-block;margin-top:8px;font-size:11px;font-weight:800;color:var(--green)}
.slock{display:inline-block;margin-top:8px;font-size:11px;font-weight:700;color:var(--soft2)}
.serie.verrou{opacity:.82}

/* ─────────────────────────── TFA TV ─────────────────────────── */
.tvfond{background:linear-gradient(165deg,#07182C 0%,#0D2E56 60%,#132A47 100%);color:#fff}
.tvfond .sur{color:#8FD6E3}
.tvfond h2.t,.tvfond h1.t{color:#fff}
.tvfond p.lead{color:#C6D9F0}
.tvrangee{font-size:16px;font-weight:900;margin:24px 0 12px;color:#fff}
.tvrail{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(min(200px,100%),240px);gap:12px;
  overflow-x:auto;padding-bottom:12px;scrollbar-width:thin}
.tvcarte{cursor:pointer;transition:.16s}
.tvcarte:hover{transform:translateY(-3px) scale(1.02)}
.tvvig{aspect-ratio:16/9;border-radius:10px;position:relative;overflow:hidden;
  display:grid;place-items:center;margin-bottom:8px;border:1px solid rgba(255,255,255,.14)}
.tvvig.v0{background:linear-gradient(130deg,#12365F,#0A1E38)}
.tvvig.v1{background:linear-gradient(130deg,#5E1230,#2A0918)}
.tvvig.v2{background:linear-gradient(130deg,#1B4A85,#0D2347)}
.tvvig.v3{background:linear-gradient(130deg,#123F49,#081E24)}
.tvvig.v4{background:linear-gradient(130deg,#3D2263,#1B0F30)}
.tvcode{position:absolute;top:8px;left:9px;font-size:10px;font-weight:800;letter-spacing:.8px;
  background:rgba(0,0,0,.42);border-radius:5px;padding:2px 8px;color:#E8F0FA}
.tvplay{width:40px;height:40px;border-radius:50%;background:rgba(255,255,255,.94);color:#08152A;
  display:grid;place-items:center;font-size:13px;padding-left:4px}
.tvlock{font-size:19px;opacity:.95}
.tvcarte b{display:block;font-size:13px;color:#fff;line-height:1.35}
.tvcarte .tvmeta{display:block;font-size:11px;color:#9DB6D2;margin-top:2px}
.tvcarte.verrou .tvvig{opacity:.66}

/* champs du formulaire d'inscription en deux colonnes */
.arang{display:grid;grid-template-columns:1fr 1fr;gap:0 12px}
@media (max-width:520px){ .arang{grid-template-columns:1fr} }
.apk{font-size:11px;color:var(--soft2);margin:4px 0 0;line-height:1.5}

/* ── les cartes Femme / Homme : sélection soignée, couleur au survol ── */
.asexe{display:flex;gap:8px;margin-top:2px}
.asexe .asx{flex:1;position:relative;margin:0;cursor:pointer}
.asexe .asx input{position:absolute;opacity:0;width:0;height:0}
.asxin{display:flex;align-items:center;justify-content:center;gap:8px;
  border:1px solid var(--brd);border-radius:var(--r-pill);padding:11px 0;
  font-size:14px;font-weight:700;color:var(--soft);background:var(--surf2);
  transition:border-color var(--t-etat) var(--e),color var(--t-etat) var(--e),
             background-color var(--t-etat) var(--e),box-shadow var(--t-etat) var(--e),
             transform var(--t-etat) var(--e)}
/* la pastille de couleur, abstraite (aucune figure) : rose pour Femme, bleu nuit pour Homme */
.asxp{width:11px;height:11px;border-radius:50%;flex:0 0 auto;
  transition:transform var(--t-etat) var(--e),box-shadow var(--t-etat) var(--e)}
.asxf{background:var(--crimson)}
.asxh{background:var(--navy)}
body.dark .asxh{background:#4E7BC4}
.asexe .asx:hover .asxin{transform:translateY(-1.5px);
  border-color:color-mix(in srgb,var(--crimson) 55%, var(--brd));
  box-shadow:0 10px 24px -12px rgba(192,9,58,.5)}
.asexe .asx:hover .asxp{transform:scale(1.18)}
.asexe .asx.on .asxin{border-color:var(--crimson);color:var(--ink);
  background:color-mix(in srgb,var(--crimson) 9%, var(--surf2));
  box-shadow:0 0 0 1px var(--crimson) inset,0 8px 22px -12px rgba(192,9,58,.6)}
.asexe .asx.on .asxp{box-shadow:0 0 0 3px color-mix(in srgb,var(--crimson) 22%, transparent)}
.asexe .asx input:focus-visible + .asxin{outline:2px solid var(--crimson);outline-offset:2px}

/* ── la date en trois menus déroulants, faciles à faire défiler ── */
.adate{display:grid;grid-template-columns:0.92fr 1.3fr 1.15fr;gap:7px}
.adsel{margin:0;cursor:pointer;-webkit-appearance:none;appearance:none;
  padding-left:10px;padding-right:22px;text-overflow:ellipsis;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' fill='none' stroke='%2394A6BD' stroke-width='1.7' stroke-linecap='round'/></svg>");
  background-repeat:no-repeat;background-position:right 7px center}
.adsel:focus{outline:2px solid var(--crimson);outline-offset:1px;border-color:transparent}

/* ══════════ FIDÉLITÉ À LA MAQUETTE — dégradés, transparences, filigranes ══════════ */

/* le filigrane de fond : deux bulles, de part et d'autre, épuré */
body::before{content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;opacity:.05;
  background:var(--bul) no-repeat -90px 16% / 360px,
             var(--bul) no-repeat calc(100% + 100px) 72% / 320px}
body.dark::before{opacity:.06}

/* le grand bandeau d'accueil retrouve ses lueurs radiales navy et crimson */
.hero{background:
  radial-gradient(circle at 20% 38%, rgba(27,74,133,.85), transparent 56%),
  radial-gradient(circle at 78% 62%, rgba(150,20,55,.55), transparent 54%),
  linear-gradient(118deg,#07182C 0%,#0D2E56 48%,#16406F 100%)}

/* le pied de page : transparent, deux bulles de part et d'autre, épuré */
footer.pied{background:transparent;border-top:1px solid var(--brd);
  color:var(--soft);position:relative;overflow:hidden}
body.dark footer.pied{background:transparent}
footer.pied::before,footer.pied::after{content:"";position:absolute;top:50%;width:250px;height:190px;
  background:var(--bul) center/contain no-repeat;opacity:.05;pointer-events:none;
  transform:translateY(-50%)}
footer.pied::before{left:-70px}
footer.pied::after{right:-70px;transform:translateY(-50%) scaleX(-1)}
footer.pied h5{color:var(--ink)}
footer.pied a{color:var(--soft)}
footer.pied a:hover{color:var(--ink)}
footer.pied .tag{color:var(--soft2)}
footer.pied .bas{border-top:1px solid var(--brd2);color:var(--soft2)}
footer.pied .in{position:relative;z-index:1}

/* ══════════ le tiroir ☰ ══════════ */
.tiroirbtn{width:36px;height:34px;border-radius:9px;border:1px solid var(--brd);
  background:var(--surf2);color:var(--ink);cursor:pointer;display:grid;place-items:center;padding:0}
.tiroirbtn:hover{border-color:var(--navy-l)}
.voile{position:fixed;inset:0;background:rgba(4,10,20,.55);z-index:180;opacity:0;
  visibility:hidden;transition:.2s;backdrop-filter:blur(2px)}
.voile.ouvert{opacity:1;visibility:visible}
.tiroir{position:fixed;top:0;bottom:0;left:0;width:284px;z-index:190;overflow-y:auto;
  background:#08111F;color:#DCE6F3;padding:16px 0 24px;
  transform:translateX(-100%);transition:transform .22s ease;box-shadow:4px 0 30px rgba(0,0,0,.4)}
.tiroir.ouvert{transform:none}
.tiroir .thead{display:flex;align-items:center;gap:8px;padding:2px 16px 12px;
  border-bottom:1px solid rgba(255,255,255,.13)}
.tiroir .thead b{font-size:11px;letter-spacing:.8px;color:#fff}
.tfermer{margin-left:auto;width:30px;height:30px;border-radius:8px;border:0;cursor:pointer;
  background:rgba(255,255,255,.08);color:#DCE6F3;font-size:13px}
.tiroir h4{margin:16px 16px 8px;font-size:10px;letter-spacing:1.6px;color:#8AA5C4;font-weight:800}
.tiroir a{display:flex;align-items:center;gap:12px;padding:8px 16px;font-size:14px;
  font-weight:600;color:#DCE6F3;text-decoration:none;border-left:3px solid transparent}
.tiroir a i{font-style:normal;width:16px;text-align:center;font-size:12px;color:#93ADCB}
.tiroir a:hover{background:rgba(192,9,58,.18);border-left-color:#FF6E92;color:#fff}
.tiroir .tnote{margin:16px 16px 0;padding:12px 12px;border-radius:8px;font-size:11px;
  line-height:1.55;background:rgba(255,255,255,.06);color:#AFC4DB}

/* ══════════ bandes de la page d'accueil (reprises de la maquette) ══════════ */
.bande{border-radius:15px;padding:28px 32px;color:#fff;position:relative;overflow:hidden;
  background:linear-gradient(118deg,#0B2542 0%,#123A66 60%,#16406F 100%)}
.bande::after{content:"";position:absolute;right:-50px;bottom:-80px;width:270px;height:270px;
  background:var(--bul) center/contain no-repeat;opacity:.07;pointer-events:none}
.bande .sur{color:#FF97B0}
.bande h3{font-size:23px;font-weight:900;color:#fff;margin-bottom:8px}
.bande p{color:#CFDEF2;font-size:14px;line-height:1.7;margin:0}
.bande .in2{position:relative;z-index:1}

.exres{background:rgba(255,255,255,.09);border:1px solid rgba(255,255,255,.2);
  border-radius:12px;padding:16px 16px;backdrop-filter:blur(3px)}
.exres .lb{font-size:10px;font-weight:800;letter-spacing:1.6px;color:#B4C8E0;margin-bottom:12px}
.exres div{display:flex;align-items:center;gap:12px;padding:4px 0;font-size:14px;color:#DCE7F5}
.exres i{font-style:normal;width:9px;height:9px;border-radius:50%;background:rgba(255,255,255,.28);flex:0 0 9px}
.exres .on i{background:#FF6E92}
.exres .on{color:#fff;font-weight:800}
.exres .nivtag{margin-left:auto;font-size:10px;font-weight:800;border-radius:20px;padding:2px 8px;
  background:rgba(255,255,255,.14)}

.kidsband{border-radius:15px;padding:24px 28px;display:flex;gap:20px;align-items:center;
  flex-wrap:wrap;background:linear-gradient(120deg,var(--sand),var(--rose));
  border:1px solid var(--sand2)}
.kidsband .kf{width:74px;height:74px;flex:0 0 74px;border-radius:20px;display:grid;place-items:center;
  font-size:30px;color:#fff;background:linear-gradient(150deg,#C0093A,#5F3891);
  box-shadow:0 8px 22px rgba(95,56,145,.3)}
.kidsband h3{font-size:20px;font-weight:900}
.kidsband p{margin:4px 0 0;font-size:14px;color:var(--soft);max-width:56ch}
.kidsband .kbtn{margin-left:auto}
body.dark .kidsband{border-color:#4A3D2B}
body.dark .kidsband p{color:#D6C8A8}
body.dark .kidsband h3{color:#F0E6D2}

.attente{border-radius:15px;padding:24px 32px;color:#fff;position:relative;overflow:hidden;
  background:linear-gradient(118deg,#0D2E56,#16406F);display:grid;
  grid-template-columns:1.4fr 1fr;gap:20px;align-items:center}
.attente h3{color:#fff;font-size:21px;font-weight:900;margin-bottom:8px}
.attente p{color:#CFDEF2;font-size:14px;margin:0}
.attente .aform{display:flex;gap:8px;flex-wrap:wrap}
.attente input{flex:1;min-width:180px;font:inherit;font-size:14px;border:1px solid rgba(255,255,255,.3);
  border-radius:9px;padding:12px 12px;background:rgba(255,255,255,.1);color:#fff}
.attente input::placeholder{color:#B7CCE6}
.attente .compteur{margin-top:12px}
@media (max-width:820px){ .attente{grid-template-columns:1fr} }


/* ─────────────────────────── page de chapitre ─────────────────────────── */
.chaphero{color:#fff;background:linear-gradient(125deg,#07182C,#0D2E56 55%,#16406F);
  position:relative;overflow:hidden}
.chaphero::after{content:"";position:absolute;right:-60px;bottom:-110px;width:340px;height:340px;
  background:var(--bul) center/contain no-repeat;opacity:.07}
.chaphero .in{position:relative;z-index:1;padding:48px 20px}
.chaphero .sur{color:#8FD6E3}
.chaphero h1{font-size:clamp(26px,4.4vw,38px);font-weight:900;margin-bottom:8px}
.chaphero .fr{font-size:15px;color:#CFDEF2}
.chaphero .hook{margin-top:12px;font-size:15px;color:#E4EDF8;font-style:italic;max-width:62ch}
.chapmeta{display:flex;gap:8px;flex-wrap:wrap;margin-top:16px}
.puce{font-size:11px;font-weight:800;letter-spacing:.6px;background:rgba(255,255,255,.13);
  border:1px solid rgba(255,255,255,.24);border-radius:20px;padding:4px 12px}

.doc{max-width:800px;margin:0 auto;padding:0 20px}
.sec{display:flex;align-items:center;gap:12px;margin:36px 0 12px;font-size:19px;font-weight:900}
.sec i{font-style:normal;width:27px;height:27px;flex:0 0 27px;border-radius:8px;background:var(--navy);
  color:var(--card);display:grid;place-items:center;font-size:12px;font-weight:800}
body.dark .sec i{background:#22406E;color:#fff}
.doc p{font-size:15px;line-height:1.75}
.doc table{width:100%;border-collapse:collapse;margin:12px 0;font-size:14px}
.doc th{background:var(--navy);color:var(--card);font-size:11px;letter-spacing:.7px;
  padding:8px 12px;text-align:left}
body.dark .doc th{background:#22406E;color:#fff}
.doc th.fr{background:var(--crimson);color:#fff}
.doc td{padding:8px 12px;border-bottom:1px solid var(--brd2);background:var(--card)}
.doc td.fr{background:var(--rose)}
.exemples{background:var(--card);border:1px solid var(--brd);border-left:3px solid var(--navy);
  border-radius:0 10px 10px 0;padding:12px 16px;margin:12px 0;font-size:15px}
.exemples .et{font-size:10px;font-weight:800;letter-spacing:2px;color:var(--soft2);
  display:block;margin-bottom:8px}
.exemples div+div{margin-top:4px}
.attention{background:var(--rose);border-left:3px solid var(--crimson);border-radius:0 10px 10px 0;
  padding:12px 16px;margin:16px 0;font-size:14px}
.attention .at{font-weight:800;color:var(--crimson);display:block;margin-bottom:8px}
.attention div+div{margin-top:4px}
.txtblk{border:1px solid var(--brd);border-radius:12px;overflow:hidden;margin:16px 0;
  background:var(--card)}
.txtblk .bande{background:var(--navy);color:var(--card);padding:8px 16px;display:flex;
  gap:12px;align-items:center;flex-wrap:wrap}
body.dark .txtblk .bande{background:#22406E;color:#fff}
.txtblk .bande b{font-size:11px;letter-spacing:1.3px;background:rgba(255,255,255,.16);
  border-radius:20px;padding:2px 12px}
.txtblk .bande span{font-size:12px;opacity:.92}
.txtblk .corps{padding:16px 16px;font-size:15px;line-height:1.8}
.txtblk .corps .truly{color:var(--navy);font-weight:800}
.txtblk .corps .fluent{color:var(--crimson);font-weight:800}
body.dark .txtblk .corps .truly{color:#9CBDF0}
.nmots{background:var(--blue);padding:12px 16px;font-size:13px}
.nmots b{font-size:10px;letter-spacing:1.6px;color:var(--soft);display:block;margin-bottom:4px}
.brit{padding:12px 16px;font-size:13px;color:var(--soft);border-top:1px dashed var(--brd)}
.illus{border:1.5px dashed var(--brd);border-radius:12px;padding:20px;text-align:center;
  margin:16px 0;background:var(--surf2)}
.illus b{display:block;font-size:11px;letter-spacing:1.4px;color:var(--soft);margin-bottom:8px}
.illus span{font-size:13px;color:var(--soft)}

/* exercices */
.ex{background:var(--card);border:1px solid var(--brd);border-radius:13px;padding:16px 20px;
  margin:20px 0;box-shadow:var(--sh)}
.exhead{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:8px}
.exhead .yt{font-size:10px;font-weight:800;letter-spacing:1.2px;background:var(--crimson);
  color:#fff;border-radius:20px;padding:4px 12px}
.exhead .lb{font-size:15px;font-weight:800}
.exhead .tag{margin-left:auto;font-size:11px;font-weight:800;letter-spacing:.5px;
  background:var(--blue);color:var(--navy);border-radius:20px;padding:4px 12px}
body.dark .exhead .tag{background:var(--surf2);color:var(--ink)}
.ex .cons{font-size:14px;color:var(--soft);margin:0 0 12px}
.ex ol{list-style:none;counter-reset:it;padding:0;margin:0}
.ex li{counter-increment:it;display:flex;gap:12px;align-items:flex-start;
  padding:8px 0;border-bottom:1px dashed var(--brd2);font-size:15px}
.ex li::before{content:counter(it);flex:0 0 21px;height:21px;border-radius:6px;background:var(--blue);
  color:var(--navy);font-size:11px;font-weight:800;display:grid;place-items:center;margin-top:2px}
body.dark .ex li::before{background:var(--surf2);color:var(--ink)}
.ex .q{flex:1}
.ex input,.ex select{font:inherit;font-size:14px;color:var(--ink);background:var(--surf2);
  border:0;border-bottom:2px solid var(--navy-l);border-radius:4px 4px 0 0;
  padding:2px 8px;min-width:96px;max-width:100%}
.ex input:focus,.ex select:focus{outline:2px solid var(--crimson);outline-offset:1px}
.ex .indice{color:var(--soft2);font-size:13px}
.ex .fb{font-size:13px;font-weight:800;white-space:nowrap;margin-top:4px}
.ex .fb.ok{color:var(--green)}
.ex .fb.ko{color:var(--crimson)}
.ex input.ok{border-bottom-color:var(--green);background:rgba(53,121,70,.1)}
.ex input.ko{border-bottom-color:var(--crimson);background:rgba(192,9,58,.09)}
.expied{display:flex;gap:12px;align-items:center;flex-wrap:wrap;margin-top:12px}
.score{font-size:13px;font-weight:800;margin-left:auto}
.oral{font-size:13px;color:var(--soft);font-style:italic}
.bareme{margin-top:8px;font-size:13px;color:var(--soft2)}



/* ══════════ CORRECTIONS DE CONTRASTE (mesurées) ══════════ */

/* la page TFA TV garde son fond navy même en thème clair :
   le pied de page transparent doit y rester en encre claire */
.site.tv footer.site{border-top-color:rgba(255,255,255,.14)}
.site.tv footer.site,.site.tv footer.site a,.site.tv footer.site .tag{color:#B4C8E0}
.site.tv footer.site h5,.site.tv footer.site a:hover{color:#fff}
.site.tv footer.site [style*="color:#fff"]{color:#fff!important}
.site.tv footer.site .bot{border-top-color:rgba(255,255,255,.12);color:#A8C0DC}
.site.tv footer.site .bot em,.site.tv footer.site .bot span{color:#A8C0DC}

/* la page chapitre en sombre : les en-têtes de tableau et l'encre des cartes */
body.dark .doc th{color:#fff}
body.dark .doc th.fr{background:#8E2246;color:#fff}
body.dark .exhead .yt{background:#8E2246;color:#fff}
body.dark .aoubli a{color:#9CBDF0}


/* ═══ responsive.css ═══ */
/* ══════════════════════════════════════════════════════════════════════════
   RESPONSIVE — téléphone et tablette.

   La maquette a été dessinée pour un écran d'ordinateur : maquette_base.css
   ne contient aucune media query et fixe ses colonnes en dur, jusqu'à sept.

   Le repli des grilles n'est PAS écrit ici : il est généré depuis la maquette
   par `outils/generer_responsive.py` dans `grilles_mobile.css`. Énumérer les
   grilles à la main avait laissé passer .b2b, .waitlist, .kidsband et
   .leveltest — dont la colonne de texte s'écrasait à une lettre de large,
   ce qui écrivait les phrases verticalement. On ne recommence pas.

   Ce fichier ne garde que ce qu'aucun script ne peut deviner : la barre du
   haut, les bandeaux, le défilement tactile, les cas à styles en ligne.

   Chargé APRÈS site.css : à spécificité égale, c'est lui qui gagne. Aucun
   !important, sauf face aux styles en ligne du HTML (signalés sur place).
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 1. Socle ─────────────────────────────────────────────────────────────
   Pas de `* { min-width: 0 }` global : cette règle, dans une grille à deux
   colonnes non repliée, laisse la colonne de texte tomber à un caractère de
   large. C'est ce qui écrivait les phrases une lettre par ligne. On répare
   la cause (les grilles se replient) au lieu du symptôme. */
img, svg, video, canvas, iframe { max-width: 100%; }

/* `[hidden]` est une règle du navigateur, sans spécificité : une simple classe
   qui déclare un `display` la neutralise. C'est ce qui faisait réapparaître le
   compteur de liste d'attente à zéro. */
[hidden] { display: none !important; }

.site h1, .site h2, .site h3, .site p, .site li,
.site td, .site th, .site .cap, .site .lb {
  overflow-wrap: break-word;
}

/* Un bouton ne se comprime jamais : sans cela, une rangée serrée empile ses
   lettres à la verticale (« G é r e r »). */
.site .btn, .site .hbtn, .site .tvbtn, .site .rndbtn,
.site button:not(.tiroirbtn):not(.tfermer) {
  flex-shrink: 0;
  white-space: nowrap;
}
.site .btn.alarge { white-space: normal; }

/* Le logo et le nom ramènent à l'accueil — le réflexe attendu sur tout site.
   Devenus un lien, ils héritaient du soulignement et de la couleur des liens :
   on les remet exactement comme avant. */
.topnav a.lg {
  text-decoration: none;
  color: inherit;
  cursor: pointer;
}
.topnav a.lg b { color: var(--navy); }
body.dark .topnav a.lg b, .tv .topnav a.lg b { color: #fff; }
.topnav a.lg:hover b { color: var(--crimson); }
/* Sur téléphone le mot-symbole est masqué : il ne reste que l'emblème, soit
   26 × 19 px de zone cliquable. On élargit la cible sans déplacer l'emblème. */
@media (hover: none) {
  .topnav a.lg { min-height: 38px; padding:4px 8px; margin:-4px -8px; }
}

/* Les deux liens de la barre sont enveloppés dans une pastille : c'est la
   pastille qui a la taille, pas le lien. On étend le lien à toute la
   pastille, sinon la zone réellement cliquable ne fait que 72 × 12 px. */
.authbtns .lgin, .authbtns .sgup { display: inline-flex; align-items: stretch; }
.authbtns .lgin a, .authbtns .sgup a {
  display: flex; align-items: center; justify-content: center; width: 100%;
}

/* Confort tactile : pas de cible en dessous de 40 px sur écran sans souris */
@media (hover: none) {
  /* les hauteurs tactiles (40 px ici, 36 px pour les étiquettes) sont
     désormais posées une seule fois dans la couche design, section 54 :
     trois valeurs différentes pour « la taille minimale d'une cible au
     doigt » n'était pas une progression, c'était trois avis. */
  /* les liens discrets — mot de passe oublié, liens de pied de carte — sont
     hauts de 14 px : on les épaissit sans changer leur apparence */
  .site .aoubli a, .site .abas a, .site .go, .site .lk2,
  .site p a, .site li a {
    display: inline-block; padding:8px 2px;
  }
  /* la hauteur se pose sur le LIEN, pas sur la pastille : c'est le lien qui
     reçoit le doigt, et il ne s'étire pas tout seul dans un conteneur centré */
  .authbtns .lgin a, .authbtns .sgup a { min-height: 34px; }
}

/* ── 2. Rangées souples ───────────────────────────────────────────────────
   Ces rangées mêlent un texte extensible et un élément de largeur fixe. Sur
   un écran étroit elles doivent passer à la ligne, jamais se comprimer. */
@media (max-width: 760px) {
  .site .wlform { flex-wrap: wrap; gap:8px; }
  .site .wlform input { width: auto; flex: 1 1 190px; min-width: 0; }
  .site .accessbar .txt { min-width: 0; flex: 1 1 100%; }
  .site .book .ft,
  .site .exhd,
  .site .tvrow h3,
  .site .nat .top,
  .site .chathead .rt2 { flex-wrap: wrap; }
  .site .rline .rn2 { flex: 0 0 auto; width: auto; }

  /* les trois choix de série (10 / 20 / 40 questions) sont alignés en ligne :
     à 320 px la dernière pastille sort de l'écran. On les laisse passer à la
     ligne et occuper toute la largeur — plus lisible, et plus facile à viser. */
  .site .qbtns { flex-wrap: wrap; gap:8px; }
  .site .qbtns .qsm, .site .qbtns .qbig { flex: 1 1 auto; text-align: center; }
}

/* ── 3. La barre du haut ──────────────────────────────────────────────────
   Le tiroir ☰ porte déjà toute la navigation : sur mobile la barre ne garde
   que l'essentiel, sur une seule ligne, sans jamais rien couper. */
@media (max-width: 980px) {
  .topnav             { padding:8px 12px; gap:12px; row-gap:8px; }
  .topnav .lk         { display: none; }
  .audsw              { display: none; }
  .topnav .rt .btn.sm { display: none; }
  .topnav .rt         { gap:8px; }
  section.blk         { padding:32px 16px; }
  .hero               { padding:40px 16px 44px; }
}

@media (max-width: 560px) {
  section.blk { padding:24px 12px; }
  .hero       { padding:32px 12px 36px; }

  .topnav             { padding:8px 12px; gap:8px; flex-wrap: nowrap; }
  .topnav .lg b       { display: none; }   /* l'emblème suffit, le nom est dans le tiroir */
  .topnav .lg .bulles { height: 19px; }
  .topnav .rt         { gap:8px; }
  /* .btn.sm était redéclaré ici : `.site .btn.sm` gagne toujours. Supprimé. */
  .authbtns           { display: flex; gap:8px; flex: 0 0 auto; }
  .lgin, .sgup        { font-size:12px; }

  h2.sh, h1.sh { font-size:19px; }
  p.lead   { font-size:14px; }
  .hero h1 { font-size:27px; letter-spacing: -.6px; }
}

@media (max-width: 380px) {
  .topnav      { padding:8px 8px; gap:8px; }
  .lgin, .sgup { font-size:12px; }
}

@media (max-width: 720px) {
  h2.sh, h1.sh { font-size:21px; }
  p.lead { font-size:14px; }
  .cal   { gap:4px; font-size:11px; }
  .avatar     { width: 64px; height: 64px; font-size:22px; }
  .acct .avatar { width: 30px; height: 30px; font-size:12px; }
}

/* ── 4. Le bandeau d'accueil ──────────────────────────────────────────────
   Hauteur fixe de 470 px et contenu en position absolue : sur téléphone le
   texte dépasse le cadre et passe sous les cartes suivantes. On remet le
   contenu dans le flux.

   `relative` et non `static` : le z-index:3 de la maquette n'agit que sur un
   élément positionné. En static, le voile sombre se peint par-dessus le
   titre et le fait disparaître — vérifié, et corrigé. */
@media (max-width: 820px) {
  .hero2   { height: auto; min-height: 400px; }
  .heroctn { position: relative; inset: auto; padding:52px 16px 40px; }
  .heroimg { inset: 0; }

  .heroctn h1     { font-size: clamp(26px, 8vw, 38px); letter-spacing: -.8px; }
  .heroctn p      { font-size:15px; }
  .heroctn .kick2 { letter-spacing: 2.6px; font-size:10px; }
  .heroctn .cta   { width: 100%; flex-direction: column; align-items: stretch; }
  .heroctn .cta .hbtn { width: 100%; text-align: center; padding:12px 16px; }

  .fig.t { left: 4%;  width: 120px; height: 195px; }
  .fig.f { right: 5%; width: 108px; height: 176px; }
}
@media (max-width: 480px) {
  .hero2 { min-height: 360px; }
  .figs  { opacity: .55; }
}

/* ── 5. Le bandeau TFA TV ─────────────────────────────────────────────────
   L'emplacement image y est positionné en absolu par un STYLE EN LIGNE du
   HTML (right:30px; top:40px; width:300px). Un style en ligne bat toutes les
   feuilles : c'est l'un des deux seuls endroits du site où `!important` est
   justifié. Sans cela, l'encadré se pose sur le titre. */
@media (max-width: 820px) {
  .tvhero { height: auto; flex-direction: column; align-items: stretch;
            padding:20px 16px 24px; }
  .tvhero .masc {
    position: relative !important;
    right: auto !important; top: auto !important; bottom: auto !important;
    width: 100% !important;
    height: 176px; margin:0 0 16px;
    order: -1;                        /* l'image d'abord, le texte ensuite */
  }
  .tvhero .in2  { max-width: none; }
  .tvhero h1    { font-size: clamp(22px, 7vw, 30px); }
  .tvhero .mute { display: none; }    /* aucun son à couper tant qu'il n'y a pas de vidéo */
}

/* ── 6. LE CARROUSEL TFA TV — défilement au doigt ─────────────────────────
   La maquette fait défiler les rangées avec `transform: translateX()`, animé
   par deux flèches qui n'apparaissent qu'AU SURVOL. Sur un téléphone il n'y
   a pas de survol : les flèches n'existent pas, le transform ne bouge jamais,
   et les vidéos hors cadre sont simplement inaccessibles.

   On rend donc la rangée nativement défilable au doigt, avec inertie et
   accrochage par vignette, et on neutralise le transform hérité. */
@media (max-width: 900px), (hover: none) {
  .tvviewport {
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
    overscroll-behavior-x: contain;
  }
  .tvviewport::-webkit-scrollbar { display: none; }

  .tvtrack {
    transform: none !important;       /* neutralise la pagination par flèches */
    padding:12px 16px 16px;
    width: max-content;
  }
  .tvcard { scroll-snap-align: start; }

  .tvnav { display: none; }           /* inutile : on fait défiler au doigt */
  .tvcard .pop { display: none; }     /* l'aperçu au survol n'existe pas au doigt */
}

/* ── 7. Tableaux : ils défilent dans leur cadre, pas la page ─────────────── */
@media (max-width: 900px) {
  table.tb, table.inv, .inv table, .doc table {
    display: block;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    width: 100%;
  }
  table.tb td, table.tb th { white-space: nowrap; }
}

/* ── 8. Les grilles écrites en ligne dans le HTML ─────────────────────────
   Second et dernier endroit où `!important` est nécessaire : plusieurs blocs
   portent leur nombre de colonnes en attribut style, ce qu'aucune feuille ne
   peut surcharger autrement. */
@media (max-width: 1000px) {
  .site [style*="grid-template-columns"] {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
  }
}
@media (max-width: 760px) {
  .site [style*="grid-template-columns"] {
    grid-template-columns: minmax(0, 1fr) !important;
  }
}

/* ── 9. Les tarifs : comparaison au doigt ─────────────────────────────────
   Empiler trois formules l'une sous l'autre oblige à mémoriser la première
   pour la comparer à la troisième. On les garde côte à côte, en laissant
   dépasser la suivante pour que le geste soit évident. */
@media (max-width: 760px) {
  .pricing .grid4[style] {
    grid-template-columns: none !important;
    display: flex;
    gap:12px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x mandatory;
    scroll-padding-left:12px;
    padding:4px 12px 12px;
    margin:0 -12px;                 /* la rangée touche les bords de l'écran */
    scrollbar-width: none;
  }
  .pricing .grid4[style]::-webkit-scrollbar { display: none; }
  .pricing .grid4[style] > .card {
    flex: 0 0 82%;                   /* 18 % de la suivante restent visibles */
    scroll-snap-align: start;
    margin:0;
  }
}

/* ── 10. Le tiroir et la pastille de compte sur petit écran ─────────────── */
@media (max-width: 340px) { .tiroir { width: 88vw; } }

@media (max-width: 480px) {
  .acctmenu       { width: min(242px, calc(100vw - 24px)); right: 0; }
  .acct .idn b,
  .acct .idn span { max-width: 96px; overflow: hidden; text-overflow: ellipsis; }
}

/* ══════════════════════════════════════════════════════════════════════════
   11. NOTES DE TRAVAIL — INVISIBLES POUR LE PUBLIC

   La maquette porte des encadrés « EMPLACEMENT IMAGE · OPENART 16:9 » qui
   décrivent l'illustration à produire. C'étaient des repères de conception ;
   sur un site en ligne, ce sont des chantiers apparents. On les masque, en
   gardant les cadres et les dégradés — qui, eux, ont l'air voulus.

   Rien n'est supprimé du HTML : le jour où les images arrivent, elles
   viennent remplir exactement ces cadres.
   ══════════════════════════════════════════════════════════════════════════ */
.heroimg .ph,
.masc .lbl,
.masc .wave,
.mascots,
.doc .illus { display: none !important; }

/* le cadre en pointillés devient un cadre net, comme une affiche en attente */
.masc { border-style: solid !important; border-color: rgba(255,255,255,.13) !important; }

/* ══════════════════════════════════════════════════════════════════════════
   12. TRULY ET FLUENT — les visages du site
   ══════════════════════════════════════════════════════════════════════════ */
/* Sélecteur volontairement long : la maquette contient `body.dark .site > *`
   qui impose `position:relative; z-index:1` à tout enfant direct de `.site`.
   Avec un simple `.mascotte-coin`, la vignette repassait dans le flux et
   tombait tout en bas de la page. */
.site > .mascotte-coin,
body.dark .site > .mascotte-coin {
  position: absolute; top: 62px; right: 18px; width: 132px; z-index: 4;
  opacity: .42; pointer-events: none; transition: opacity .4s ease;
  filter: drop-shadow(0 6px 18px rgba(0,0,0,.28));
}
.mascotte-coin .mc-img { display: block; width: 100%; height: auto; }
.site:hover > .mascotte-coin { opacity: .62; }
body.dark .site > .mascotte-coin { opacity: .34; }
body.dark .site:hover > .mascotte-coin { opacity: .52; }

.mascotte-grande {
  position: absolute; inset: 0; overflow: hidden;
  z-index: 1; pointer-events: none;
}
/* L'image porte TRULY à l'extrême gauche et FLUENT à l'extrême droite, le
   centre volontairement vide pour le titre. Elle doit donc occuper toute la
   largeur du bandeau : la contraindre à une largeur fixe ramènerait les deux
   personnages vers le milieu, sous le texte. Ancrée en bas, le haut vide est
   ce qui déborde. */
.mascotte-grande .mg-img {
  position: absolute; left: 0; top: 0; width: 100%; height: auto;
  filter: drop-shadow(0 18px 46px rgba(0,0,0,.45));
}
/* Ancrage EN HAUT, et non en bas : l'image est plus haute que le bandeau, il
   faut donc en couper une partie. Les têtes portent toute l'identité de la
   marque — on coupe les jambes, jamais les têtes. */

.mascotte-tv { position: absolute; inset: 0; overflow: hidden; border-radius: 13px; }
.mascotte-tv .mtv-img { width: 100%; height: 100%; object-fit: cover;
                        display: block; transform: scale(1.02); }
.mascotte-tv::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(ellipse at 50% 42%, transparent 42%, rgba(4,10,22,.55) 100%),
    linear-gradient(180deg, transparent 62%, rgba(4,10,22,.72) 100%);
}

.acct .avatar { position: relative; overflow: hidden; }
.acct .avatar .av-img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 22%; display: block;
}
.acct .avatar.a-photo { color: transparent; }

@media (max-width: 820px) {
  .site > .mascotte-coin { width: 84px; top: 56px; right: 10px; opacity: .3; }
  /* Pleine largeur, et rien d'autre. Agrandir l'image sur un écran étroit
     ramène mécaniquement les deux personnages vers le centre — donc derrière
     le titre, ce que toute la composition cherche justement à éviter. */
  .mascotte-grande .mg-img { width: 100%; left: 0; }
  .mascotte-grande { opacity: .85; }
}
@media (max-width: 480px) {
  .site > .mascotte-coin { width: 62px; top: 52px; right: 7px; opacity: .26; }
}


/* ══════════════════════════════════════════════════════════════════════════
   13. DÉTAILS DE LISIBILITÉ ET D'ÉTAT

   Deux défauts relevés par le contrôle de contraste automatique :
   · les liens des pages légales prenaient le bleu par défaut du navigateur
     (#0000EE), soit 1,64:1 sur fond sombre — illisible ;
   · un bouton désactivé gardait sa couleur de marque atténuée, ce qui donnait
     un texte à 3,28:1 et laissait croire qu'il était encore cliquable.
   ══════════════════════════════════════════════════════════════════════════ */
.site p a, .site li a, .site .attention a {
  color: var(--crimson);
  text-decoration: underline;
  text-underline-offset: 2px;
}
body.dark .site p a,
body.dark .site li a,
body.dark .site .attention a { color: #FF9DB6; }

/* un bouton indisponible doit le dire : gris franc, curseur neutre */
.site .btn:disabled, .site .btn[disabled],
.site button:disabled {
  opacity: 1;
  background: var(--brd);
  color: var(--soft);
  border-color: transparent;
  cursor: not-allowed;
}
body.dark .site .btn:disabled,
body.dark .site button:disabled { background: #2A3446; color: #93A6BF; }


/* ── le bandeau de réponse des fonctions à venir ──────────────────────────
   Il apparaît en bas, au-dessus de tout, se lit en une phrase et disparaît.
   Sur téléphone il occupe toute la largeur ; sur ordinateur il reste discret
   dans le coin. */
#tfa-avis {
  position: fixed; z-index: 400;
  left: 14px; right: 14px; bottom: 16px;
  display: flex; align-items: flex-start; gap:12px;
  background: #14243D; color: #EAF1FA;
  border: 1px solid rgba(255,255,255,.14);
  border-left: 3px solid var(--crimson);
  border-radius: 11px; padding:12px 12px;
  font-size:14px; line-height: 1.55;
  box-shadow: 0 14px 40px rgba(0,0,0,.45);
  opacity: 0; visibility: hidden; transform: translateY(12px);
  transition: opacity .22s ease, transform .22s ease, visibility .22s;
}
#tfa-avis.vu { opacity: 1; visibility: visible; transform: none; }
#tfa-avis span { flex: 1; }
#tfa-avis button {
  flex: 0 0 auto; background: transparent; border: 0; color: #9FB4CE;
  font-size:15px; line-height: 1; cursor: pointer; padding:2px 4px;
}
#tfa-avis button:hover { color: #fff; }

@media (min-width: 760px) {
  #tfa-avis { left: auto; right: 22px; bottom: 22px; max-width: 420px; }
}


/* ═══ grilles_mobile.css ═══ */
/* ══════════════════════════════════════════════════════════════════════════
   REPLI DES GRILLES — FICHIER GÉNÉRÉ, NE PAS MODIFIER À LA MAIN

       python3 outils/generer_responsive.py

   Écrit à partir de assets/maquette_base.css : toute grille de la maquette
   qui déclare plusieurs colonnes se replie ici quand l'écran rétrécit. Le
   sélecteur est recopié à l'identique, donc à spécificité égale c'est cette
   feuille — chargée en dernier — qui l'emporte. Pas un seul !important.

   26 grilles détectées, dont 14 à trois colonnes ou plus.
   ══════════════════════════════════════════════════════════════════════════ */

/* `minmax(0, 1fr)` et non `1fr` : une piste `1fr` vaut `minmax(auto, 1fr)`,
   elle refuse donc de descendre sous la largeur de son contenu. Un tableau
   large ou un mot long élargit alors la colonne au-delà de l'écran, et toute
   la page part de travers. `minmax(0, …)` autorise la piste à se réduire ;
   le contenu, lui, se replie ou défile dans son propre cadre. */

/* Trois colonnes et plus → deux, dès la tablette */
@media (max-width: 1000px) {
.agegrid,
.quickrow,
.books,
.fmtgrid,
.pricemini,
.charte,
.grid4,
.kpi,
.member .row,
footer.site .cols,
.clubkpi,
.grid3,
.kidsband,
.natgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Sur téléphone, une seule colonne : c'est la seule mise en page lisible */
@media (max-width: 760px) {
.agegrid,
.quickrow,
.books,
.fmtgrid,
.pricemini,
.charte,
.grid4,
.kpi,
.member .row,
footer.site .cols,
.clubkpi,
.grid3,
.kidsband,
.natgrid,
.archrow,
.b2b,
.clubband,
.clubwrap,
.dashgrid,
.grid2,
.heroin,
.leveltest,
.profcard,
.quickband,
.report,
.waitlist { grid-template-columns: minmax(0, 1fr); }
}


/* ═══ matiere.css ═══ */
/* ══════════════════════════════════════════════════════════════════════════
   LA MATIÈRE DU TIROIR, ÉTENDUE AU SITE

   Le tiroir ☰ a une matière que le reste du site n'avait pas : un navy très
   profond (#080C12), presque noir, sur lequel l'emblème apparaît en filigrane
   à peine perceptible. C'est ce qui lui donne son aspect posé et coûteux.

   Le reste du site, lui, flottait sur un gris-bleu clair (#171E29 pour le
   fond, #273346 pour la barre du haut) — une couleur d'interface, pas une
   couleur de marque. On l'aligne ici sur le tiroir.

   Deux principes tenus :
   · La transparence est réelle, pas simulée. La barre du haut laisse passer
     ce qui défile dessous, floutée. C'est ce qui distingue une interface
     soignée d'un aplat opaque posé par-dessus.
   · Le filigrane reste RARE. Deux par page au maximum, jamais derrière un
     texte long, jamais à plus de 4 % d'opacité. Un motif répété partout
     n'est pas une signature, c'est un papier peint.

   Chargée en dernier : à spécificité égale, c'est elle qui l'emporte.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 1. LE FOND ──────────────────────────────────────────────────────────
   #0A0E15 : la teinte du tiroir, éclaircie de deux points pour que les
   cartes (#1B2231) s'en détachent encore. Un fond strictement identique
   aurait fait disparaître leurs bords. */
body.dark { background: #0A0E15; }
body.dark .site { background: transparent; }

/* ── 2bis. LA BARRE DU HAUT N'ÉTAIT PAS COLLANTE ─────────────────────────
   `site.css` la déclare `position:sticky` via `.topnav.collante`, soit deux
   classes. Mais la maquette contient `body.dark .site > *` — un élément et
   deux classes — qui impose `position:relative` à tout enfant direct de
   `.site`. Plus spécifique, donc gagnant : en thème sombre, c'est-à-dire par
   défaut, la barre défilait avec la page depuis le début.

   On la reprend ici avec la spécificité qu'il faut. Le défaut ne se voyait
   pas au chargement — il fallait défiler pour s'en apercevoir. */
.site > .topnav.collante,
body.dark .site > .topnav.collante {
  position: sticky;
  top: 0;
  z-index: 80;
}

/* ── 2. LA BARRE DU HAUT ─────────────────────────────────────────────────
   Vraiment translucide : le contenu défile visiblement dessous. Le flou et
   la saturation légère évitent que le texte de la page ne rende la barre
   illisible quand une image passe derrière. */
body.dark .topnav,
body.dark .topnav.collante {
  background: rgba(9, 13, 20, .78);
  -webkit-backdrop-filter: blur(16px) saturate(130%);
  backdrop-filter: blur(16px) saturate(130%);
  border-bottom: 1px solid rgba(255, 255, 255, .07);
}
/* TFA TV a sa propre barre, déjà translucide : on l'aligne sur la même teinte */
body.dark .tv .topnav,
.tv .topnav {
  background: rgba(9, 13, 20, .78);
  -webkit-backdrop-filter: blur(16px) saturate(130%);
  backdrop-filter: blur(16px) saturate(130%);
  border-bottom: 1px solid rgba(255, 255, 255, .07);
}

/* Un seul filigrane dans la barre, à gauche, derrière le logo. Il ne se voit
   pas ; il se sent. */
body.dark .topnav::before {
  content: "";
  position: absolute;
  left: -34px; top: -46px;
  width: 168px; height: 168px;
  background: var(--bul) center/contain no-repeat;
  opacity: .05;
  pointer-events: none;
  z-index: 0;
}
.topnav > * { position: relative; z-index: 1; }

/* ── 3. LES DEUX FILIGRANES DE PAGE ──────────────────────────────────────
   Un en haut à gauche, un en bas à droite. C'est tout. Ils sont posés sur le
   conteneur de page, donc ils ne suivent pas le défilement des sections et
   ne viennent jamais se coller à un paragraphe. */
body.dark div.site::before,
body.dark div.site::after {
  content: "";
  position: absolute;
  background: var(--bul) center/contain no-repeat;
  pointer-events: none;
  z-index: 0;
  opacity: .035;
}
/* Celui de gauche déborde : un débordement À GAUCHE n'allonge pas la page,
   il est simplement masqué. Celui de droite, lui, reste collé au bord (right:0)
   — le faire dépasser allongeait la page de 140 px et faisait glisser tout le
   site latéralement sur téléphone.

   Première tentative : `overflow-x: clip` sur `.site` pour rogner le
   débordement. Erreur — cela a supprimé l'adhérence de la barre du haut, qui
   ne suivait plus le défilement. Un élément ne peut pas rogner ses enfants et
   laisser l'un d'eux se coller au bord de l'écran. */
body.dark div.site::before { left: -120px; top: 180px; width: 440px; height: 440px; }
body.dark div.site::after  { right: 0; bottom: 340px; width: 480px; height: 480px; opacity: .028; }

/* sur un écran étroit ils n'apportent plus rien : deux taches de plus dans un
   espace déjà contraint */
@media (max-width: 700px) {
  body.dark div.site::before,
  body.dark div.site::after { display: none; }
}

/* ── 4. LES SURFACES SOMBRES DE LA MAQUETTE ──────────────────────────────
   Plusieurs bandeaux étaient posés sur le gris-bleu d'interface. On les
   ramène sur la teinte du tiroir, en gardant leurs dégradés de marque. */
body.dark .tv { background: #0A0E15; }
/* `.tv` portait `overflow:hidden`, qui fait d'elle un conteneur de défilement
   et annule l'adhérence de sa barre. `clip` rogne pareil sans cet effet de
   bord ; `overflow-y:visible` laisse la barre se coller au bord de l'écran. */
.site.tv, body.dark .site.tv { overflow: visible; overflow-x: clip; overflow-y: visible; }
body.dark .tvhero .bgv { background: linear-gradient(125deg, #0C2544, #080C12 58%, #2A0A1A); }
body.dark .hero2 { background: #080C12; }

/* les cartes gagnent un filet clair : sur un fond plus profond, un bord
   franc vaut mieux qu'une ombre qui ne se voit plus */
body.dark .card,
body.dark .kpicard { border-color: rgba(255, 255, 255, .07); }

/* ── 5. LE PIED DE PAGE ──────────────────────────────────────────────────
   Il portait déjà deux filigranes : on les aligne sur la même discrétion. */
body.dark footer.site { background: #080C12; }
body.dark footer.site::before,
body.dark footer.site::after { opacity: .04; }

/* ── 6. LA VIGNETTE TRULY & FLUENT ───────────────────────────────────────
   Elle flottait comme un autocollant découpé aux genoux, par-dessus les
   cartes. Trois corrections : elle passe DERRIÈRE le contenu (z-index 0,
   sous les sections qui sont en 1), son bas se fond dans la page par un
   dégradé de masque — c'est ce qui la faisait paraître « coupée » — et son
   opacité descend pour qu'elle appartienne au fond, pas au premier plan. */
.site > .mascotte-coin,
body.dark .site > .mascotte-coin {
  top: 54px;
  right: 26px;
  width: 148px;
  z-index: 0;
  opacity: .30;
  filter: none;
  -webkit-mask-image: linear-gradient(180deg, #000 52%, rgba(0,0,0,.35) 78%, transparent 100%);
  mask-image: linear-gradient(180deg, #000 52%, rgba(0,0,0,.35) 78%, transparent 100%);
}
.site:hover > .mascotte-coin,
body.dark .site:hover > .mascotte-coin { opacity: .30; }

@media (max-width: 820px) {
  .site > .mascotte-coin { width: 96px; top: 50px; right: 12px; opacity: .22; }
}
@media (max-width: 480px) {
  .site > .mascotte-coin { width: 72px; top: 48px; right: 8px; opacity: .18; }
}


/* ══════════════════════════════════════════════════════════════════════════
   7. LES COUVERTURES DES MANUELS

   Les cinq couvertures remplacent les cartes de remplacement. Le cadre était
   déjà au format A4 (`aspect-ratio:1/1.414`) et les fichiers le sont aussi :
   l'image remplit donc exactement, sans recadrage ni déformation.

   Le titre écrit disparaît quand une couverture est là — il y figure déjà,
   composé. Le laisser derrière l'image n'aurait servi qu'à doubler le poids
   du texte pour les lecteurs d'écran.
   ══════════════════════════════════════════════════════════════════════════ */
.book .cv { overflow: hidden; }
.book .cvimg {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
/* la pastille de niveau reste lisible par-dessus la couverture */
.book.avec-couv .cv .lvl {
  z-index: 2;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .45);
}
/* la couverture porte déjà le dégradé : celui de la maquette ferait double */
.book.avec-couv .cv,
body.dark .book.avec-couv .cv { background: #0A0E15; padding:0; }

/* ── les manuels encore à écrire ──
   Assombris et désaturés plutôt que masqués : la collection se lit d'un coup
   d'œil, et l'on voit où l'on va. L'étiquette dit clairement ce qu'il en est,
   plutôt que de laisser deviner pourquoi la carte est plus terne. */
.book.a-venir .cvimg { filter: grayscale(.55) brightness(.5); }
.book.a-venir .cv::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(10,14,21,.20), rgba(10,14,21,.72));
}
.book .cv .bientot {
  position: absolute; left: 50%; bottom: 12px; transform: translateX(-50%);
  z-index: 2;
  font-size:10px; font-weight: 800; letter-spacing: 1.4px; text-transform: uppercase;
  color: #fff;
  background: rgba(8, 12, 18, .55);
  border: 1px solid rgba(255, 255, 255, .34);
  backdrop-filter: blur(4px);
  border-radius: 5px; padding:4px 8px;
  white-space: nowrap;
}

/* La maquette réservait `.book .cv span` au sous-titre « BOOK 1 », en petit et
   en gris. L'étiquette « Bientôt » est un span elle aussi : sans cette reprise
   elle héritait de ce style et devenait illisible sur la couverture. */
.book .cv span.bientot { color: #fff; font-size:10px; margin-top:0; display: block; }


/* Une couverture est une affiche : elle se lit très bien à demi-largeur. Le
   repli automatique des grilles la passait à une seule colonne sous 760 px,
   ce qui donnait des cartes de 500 px de haut — cinq écrans de défilement pour
   voir la collection. Deux colonnes partout, jusqu'aux plus petits écrans :
   à 320 px cela fait encore 145 px par couverture, largement lisible. */
@media (max-width: 760px) {
  .books { grid-template-columns: repeat(2, minmax(0, 1fr)); gap:12px; }
}
@media (max-width: 380px) {
  .books { gap:8px; }
  .book .ft { padding:8px 8px; font-size:11px; }
}


/* ══════════════════════════════════════════════════════════════════════════
   8. TFA TV — L'EXTRAIT ET LE MOT-SYMBOLE
   ══════════════════════════════════════════════════════════════════════════ */

/* ── LE FOND DU BANDEAU TFA TV ────────────────────────────────────────────
   La vidéo occupe tout le bandeau, comme sur les plateformes de diffusion.
   Elle démarre invisible et se fond une fois réellement jouable : on ne voit
   jamais de rectangle noir en attendant le décodage — l'affiche d'attente
   (le poster) tient la place, puis le mouvement prend le relais. */
.tvhero .tvfond {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* 28 % et non 50 % : mesuré sur l'affiche, le haut des têtes se trouve à
     14,8 % de la hauteur de la vidéo. Un cadrage centré ouvrait la fenêtre à
     14,9 % — soit exactement sur les crânes, qui se retrouvaient coupés. À
     28 %, la fenêtre commence à 10 % et laisse de l'air au-dessus. Ce sont
     les jambes qu'on perd, et c'est le bon choix pour un bandeau large. */
  object-position: 50% 28%;
  display: block;
  opacity: 0;
  transition: opacity 1.1s ease;
  pointer-events: none;

  /* Empilement déclaré explicitement. Le bandeau contient déjà `.bgv`, le
     dégradé de la maquette, lui aussi en position absolue. Deux éléments
     positionnés sans z-index se départagent par l'ordre du DOM : `.bgv`
     venant après, il recouvrait entièrement la vidéo — qui jouait, sans que
     rien ne se voie. On le laisse derrière comme fond de secours si la vidéo
     ne se charge pas, et on ordonne le reste. */
  z-index: 1;
}
.tvhero .tvfond.pret { opacity: 1; }

/* Le petit cadre de la maquette n'a plus lieu d'être : la vidéo y est passée.
   Il porte ses positions en style en ligne, d'où le !important. */
.tvhero .masc { display: none !important; }

/* Le voile. Sans lui, le texte blanc passerait sur un ciel clair ou sur une
   dalle réfléchissante et deviendrait illisible par endroits. Deux dégradés :
   un latéral qui protège la colonne de texte, un vertical qui raccroche le
   bandeau à la page en dessous. */
.tvhero .scrim {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  /* Opacités calculées, pas choisies à l'œil. La luminance de la vidéo sous
     la colonne de texte a été relevée sur les 121 images : elle monte à 0,36.
     Il faut au moins 55 % de voile pour tenir le rapport de 4,5:1 exigé sur
     du texte blanc ; on prend 74 % au bord droit de la colonne, ce qui laisse
     de la marge et garde la moitié droite de l'image bien lisible. */
  background:
    linear-gradient(90deg, rgba(8,12,19,.92) 0%, rgba(8,12,19,.86) 28%,
                           rgba(8,12,19,.74) 44%, rgba(8,12,19,.26) 68%,
                           rgba(8,12,19,.06) 100%),
    linear-gradient(0deg, rgba(10,14,21,.90) 0%, rgba(10,14,21,.24) 30%,
                          rgba(10,14,21,0) 58%, rgba(10,14,21,.40) 100%);
}
/* le texte et les boutons passent devant le voile */
.tvhero .in2 { position: relative; z-index: 3; }
.tvhero .mute { z-index: 3; }

/* Un bandeau de 340 px pour 1920 de large ne montrerait qu'une bande étroite
   de l'image. On lui donne de la hauteur : la scène respire, et le rognage
   redevient raisonnable. */
.tvhero { height: auto; min-height: clamp(420px, 58vh, 620px); }

@media (max-width: 820px) {
  /* Sur téléphone le bandeau est presque carré : c'est la LARGEUR qui est
     rognée, pas la hauteur. Le cadrage vertical n'a donc plus d'effet, et
     le centrage horizontal suffit — les deux personnages sont mesurés à
     47 % et 49 % de la largeur, ils restent entiers. */
  .tvhero .tvfond { object-position: 50% 50%; }
  .tvhero { min-height: 0; }
  /* Sur téléphone le texte couvre toute la largeur, et le panneau lumineux de
     la scène passe derrière lui : la luminance mesurée y atteint 0,99, le pire
     cas possible. Il faut 82 % de voile pour tenir 4,5:1 ; on prend 87 %. La
     vidéo reste parfaitement lisible — mouvement, silhouettes, lumières — mais
     elle passe résolument au second plan, ce qui est sa place sur un écran de
     cette taille. */
  .tvhero .scrim {
    background:
      linear-gradient(0deg, rgba(10,14,21,.94) 0%, rgba(10,14,21,.87) 30%,
                            rgba(10,14,21,.85) 62%, rgba(10,14,21,.90) 100%);
  }
}

/* la commande d'arrêt devient un vrai bouton, donc elle se comporte comme tel */
.tvhero .mute {
  cursor: pointer;
  user-select: none;
  transition: background .18s, border-color .18s, transform .18s;
}
.tvhero .mute:hover { transform: scale(1.06); border-color: rgba(255,255,255,.5); }
.tvhero .mute:focus-visible { outline: 2px solid var(--crimson); outline-offset: 3px; }

/* ── le mot-symbole ──
   Le traitement des plateformes de diffusion : capitales très étirées, graisse
   maximale, crimson de la marque, et une lueur qui fait « écran allumé ».
   Aucune police n'est téléchargée : la pile s'appuie sur des polices déjà
   présentes sur les systèmes, condensées et hautes, avec un repli sur la
   police du site. Une police web de plus, c'est un chargement de plus et un
   texte qui saute au premier affichage. */
.tv .tvmarque {
  display: block;
  margin:0 0 12px;
  /* La police du site, et elle seule. Une pile « Impact / Haettenschweiler /
     Arial Narrow » donnerait trois rendus différents selon le système —
     Impact sur Windows, autre chose sur Mac, un repli sur Linux et Android.
     Un mot-symbole de marque qui change de forme d'un visiteur à l'autre
     n'est plus un mot-symbole. Le caractère « plateforme » vient donc de la
     mise en forme — capitales, graisse maximale, large approche, crimson et
     lueur d'écran — et non d'un fichier de police qu'on n'a pas. */
  font-size: clamp(19px, 2.5vw, 30px);
  font-weight: 900;
  letter-spacing: .30em;
  text-transform: uppercase;
  line-height: 1;
  color: #E8203F;
  text-shadow: 0 0 22px rgba(232, 32, 63, .55), 0 2px 3px rgba(0, 0, 0, .55);
  white-space: nowrap;
}
/* « TV » se détache en blanc : c'est ce qui fait lire l'ensemble comme la
   déclinaison télévisée d'une marque, et non comme un titre de plus. */
.tv .tvmarque i {
  font-style: normal;
  color: #fff;
  text-shadow: 0 0 18px rgba(255, 255, 255, .38), 0 2px 3px rgba(0, 0, 0, .5);
  margin-left:.12em;
}

@media (max-width: 560px) {
  .tv .tvmarque { letter-spacing: .20em; font-size:17px; white-space: normal; }
}


/* ═══ design.css ═══ */
/* ══════════════════════════════════════════════════════════════════════════
   TRULY FLUENT ACADEMY — COUCHE DE DESIGN
   Chargée en dernier. Elle ne remplace rien : elle re-proportionne.

   POURQUOI ELLE EXISTE
   Le site descend d'une maquette dessinée pour être vue en petit, dans un
   cadre de navigateur factice. D'où des corps de 13 px, des marges de 44 px,
   des rayons de 7 px. Affiché en vrai, en plein écran, cela donne un site
   dense et plat : tout se vaut, rien ne respire, l'œil n'a pas de point
   d'entrée. C'est exactement ce qui rendait la page monotone.

   CE QUE CETTE COUCHE CHANGE
   Une échelle. Le corps de texte, les titres, les blancs, les rayons et les
   ombres sont redéfinis ensemble, en proportion les uns des autres, de sorte
   que la hiérarchie se voie sans lire.

   LES VALEURS DE MOUVEMENT
   Relevées dans la feuille de style de production d'apple.com
   (ac-globalnav.built.css) : la courbe de signature est
   cubic-bezier(.32,.08,.24,1) — une sortie longue et très amortie — et les
   durées réelles se rangent en trois familles : 0,10-0,22 s pour un état
   (survol, appui), 0,28-0,44 s pour une apparition, 0,56-0,64 s pour
   l'ouverture d'une grande surface. Ce fichier n'utilise que ces trois
   familles. Une durée choisie au hasard se remarque ; une durée cohérente
   avec toutes les autres devient invisible, et c'est le but.
   ══════════════════════════════════════════════════════════════════════════ */

:root {
  /* ── mouvement ───────────────────────────────────────────────────────── */
  --e:      cubic-bezier(.32, .08, .24, 1);    /* la signature : sortie amortie */
  --e-in:   cubic-bezier(.8, 0, .68, .92);     /* disparitions */
  --e-soft: cubic-bezier(.04, .04, .12, .96);  /* glissements longs */
  --t-etat: .18s;    /* survol, appui */
  --t-app:  .36s;    /* apparition d'un élément */
  --t-gros: .6s;     /* ouverture d'une grande surface */

  /* ── rayons ──────────────────────────────────────────────────────────────
     Le logo est fait de deux bulles : sa géométrie est ronde, jamais
     anguleuse. Les rayons suivent donc une progression franche, et les
     grandes surfaces vont beaucoup plus loin que les 10-15 px d'origine. */
  --r-xs: 10px;
  --r-s:  14px;
  --r-m:  20px;
  --r-l:  28px;
  --r-xl: 38px;
  --r-pill: 999px;

  /* ── rythme vertical ─────────────────────────────────────────────────────
     Une seule variable commande l'air de tout le site. */
  --sect: clamp(64px, 8.5vw, 128px);   /* entre deux sections */
  --gout: clamp(20px, 4vw, 34px);      /* marge latérale */
  --gap:  clamp(16px, 2vw, 26px);      /* entre deux cartes */

  /* ── ombres ──────────────────────────────────────────────────────────────
     Deux couches : un contact net et très court, une diffusion large et
     faible. Une ombre unique paraît toujours collée ou toujours flottante ;
     deux couches donnent la profondeur sans lourdeur. */
  --sh:  0 1px 2px rgba(9,25,50,.06), 0 6px 20px -8px rgba(9,25,50,.14);
  --sh2: 0 2px 4px rgba(9,25,50,.07), 0 22px 48px -18px rgba(9,25,50,.28);
  --sh3: 0 3px 6px rgba(9,25,50,.09), 0 44px 90px -30px rgba(9,25,50,.42);
}

body.dark {
  --sh:  0 1px 2px rgba(0,0,0,.4),  0 8px 24px -10px rgba(0,0,0,.6);
  --sh2: 0 2px 6px rgba(0,0,0,.5),  0 26px 56px -20px rgba(0,0,0,.72);
  --sh3: 0 4px 10px rgba(0,0,0,.55), 0 50px 100px -32px rgba(0,0,0,.85);
}


/* ══════════════════════════════════════════════════════════════════════════
   1. TYPOGRAPHIE

   `Inter` était en tête de la pile sans jamais être chargée : aucune @font-face,
   aucun lien vers un fournisseur. Le navigateur passait donc silencieusement
   au suivant. On assume : -apple-system en tête, ce qui donne SF Pro sur les
   appareils Apple — le caractère même dont s'inspire la demande — et une
   fonte système propre partout ailleurs, sans une seule requête réseau.
   ══════════════════════════════════════════════════════════════════════════ */
body,
.site {
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI Variable Text",
               "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size:16px;
  line-height: 1.62;
  letter-spacing: -.006em;
  text-rendering: optimizeLegibility;
}

/* Les titres serrent leur interlettrage à mesure qu'ils grossissent : sans
   cela un grand titre paraît toujours délavé. `text-wrap: balance` égalise
   les lignes ; non supporté, il est simplement ignoré. */
.site h1, .site h2, .site h3, .site h4,
.site .atitre, .site h2.t, .site h2.sh, .site h1.t, .site h1.sh {
  text-wrap: balance;
  letter-spacing: -.028em;
  line-height: 1.06;
}
.site p, .site li { text-wrap: pretty; }

.site h2.sh, .site h1.sh { font-size: clamp(30px, 3.6vw, 50px); font-weight: 800; margin:0 0 12px; }
.site h2.t, .site h1.t { font-size: clamp(30px, 3.6vw, 50px); font-weight: 800; margin:0 0 12px; }
.site h3      { letter-spacing: -.022em; }
.site .card h3{ font-size:19px; font-weight: 700; margin:0 0 8px; line-height: 1.25; }

.site p.lead, .site p.lead2 {
  font-size: clamp(16.5px, 1.35vw, 20px);
  line-height: 1.58;
  color: var(--soft);
  /* 60 ch laissait la moitié droite du cadre vide sur un écran large, ce que
     les annotations pointaient comme « negative space ». 70 ch reste dans la
     fourchette lisible (45-75) et remplit la largeur gagnée. */
  max-width: 70ch;
  margin: 0 0 clamp(28px, 3.4vw, 48px);
  letter-spacing: -.011em;
}
.site .card p { font-size:15px; line-height: 1.6; }

/* Le sur-titre : plus petit, plus espacé, plus discret. Il annonce, il ne
   crie pas. Une pastille le précède — c'est ce qui accroche l'œil, pas la
   capitale rouge. */
.site .eyebrow, .site .sur {
  display: inline-flex; align-items: center; gap:8px;
  font-size:12px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: var(--crimson);
  margin-bottom:16px;
}
.site .eyebrow::before, .site .sur::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; flex: 0 0 6px;
  box-shadow: 0 0 0 4px color-mix(in srgb, currentColor 18%, transparent);
}
body.dark .site .eyebrow, body.dark .site .sur { color: #FF7E9C; }

.site .mini { font-size:13px; line-height: 1.55; }


/* ══════════════════════════════════════════════════════════════════════════
   2. RYTHME — c'est le changement le plus important du fichier

   Les sections passaient toutes à 44 px de haut, quelle que soit leur
   importance : impossible de savoir où commence une idée et où finit la
   précédente. Elles respirent maintenant proportionnellement à l'écran, et
   la largeur utile passe de 1000 à 1160 px.
   ══════════════════════════════════════════════════════════════════════════ */
.site section.blk { padding: var(--sect) var(--gout); }
.site .in         { max-width: 1160px; }
.site .blk2       { padding: var(--sect) var(--gout); max-width: 1160px; }

/* Deux sections voisines n'ont pas besoin de deux fois l'air : sans cette
   règle on obtient un trou de 256 px au milieu de la page.
   ET LE CHANGEMENT DE FOND NON PLUS. Je rendais le rembourrage complet à la
   section qui suit un fond différent : additionné au rembourrage bas de la
   précédente, cela faisait 244 px de vide mesurés entre « Le livre et l'écran »
   et « La collection ». Or quand le fond change, la séparation est déjà faite
   par la couleur — le blanc n'a plus à la refaire. Un tiers suffit. */
.site section.blk + section.blk { padding-top:0; }
.site section.blk.wt + section.blk:not(.wt),
.site section.blk:not(.wt) + section.blk.wt { padding-top: calc(var(--sect) * .34); }
/* la bande tarifs (.pricing) a son propre fond, comme .wt : la section qui la
   suit — le bloc « Le Club » — doit reprendre un vrai rembourrage haut, sinon
   le bloc reste collé au bas de la bande et paraît à cheval entre deux fonds.
   Le fondu du bas de .pricing amène déjà au noir ; ce rembourrage l'y pose. */
.site section.blk.pricing + section.blk { padding-top: var(--sect); }

.site .grid2, .site .grid3, .site .grid4 { gap: var(--gap); }

/* PIÈGE ÉVITÉ DE JUSTESSE — et déjà rencontré sur ce projet.
   `minmax(0, 1fr)` vaut mieux que `1fr`, qui refuse de descendre sous la
   largeur de son contenu. Mais écrit ici en `.site .grid3` (spécificité 0,2,0),
   il écrasait le repli d'assets/grilles_mobile.css, écrit en `.grid3` (0,1,0)
   à l'intérieur d'une media query — et une media query n'ajoute aucune
   spécificité. Résultat mesuré : trois colonnes maintenues à 320 px, du texte
   à une lettre par ligne sur cinq pages et jusqu'à 169 px de débordement.
   La correction n'est donc pas d'ajouter !important, c'est de ne parler que
   là où le repli n'a pas cours : au-dessus de 1 000 px. */
@media (min-width: 1001px) {
  .site .grid3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .site .grid2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .site .grid4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}


/* ══════════════════════════════════════════════════════════════════════════
   3. LES BOUTONS

   Ils étaient à 8 px de haut sur 17 de large : au doigt comme à la souris,
   c'est une cible étroite, et à l'œil c'est un bouton timide. Ils deviennent
   des pastilles pleines, et leur survol fait trois choses en même temps —
   ombre qui gonfle, très légère montée, fond qui s'éclaircit — pendant
   0,18 s. Un seul de ces trois effets se remarque ; les trois ensemble ne se
   remarquent pas, ils se ressentent.
   ══════════════════════════════════════════════════════════════════════════ */
.site .btn, .site .hbtn {
  border-radius: var(--r-pill);
  padding:12px 24px;
  font-size:15px; font-weight: 600; letter-spacing: -.008em;
  transition: transform var(--t-etat) var(--e),
              box-shadow var(--t-etat) var(--e),
              background-color var(--t-etat) var(--e),
              border-color var(--t-etat) var(--e),
              color var(--t-etat) var(--e);
  will-change: auto;
}
.site .btn.sm { padding:8px 16px; font-size:14px; }
.site .btn.lg { padding:16px 32px; font-size:17px; }

.site .btn:hover  { transform: translateY(-1.5px); box-shadow: 0 10px 26px -10px rgba(192,9,58,.6); }
.site .btn:active { transform: translateY(0) scale(.985); transition-duration: .08s; }
.site .btn.nv:hover { box-shadow: 0 10px 26px -10px rgba(9,45,89,.75); }
.site .btn.gh {
  border-width: 1px;
  border-color: color-mix(in srgb, currentColor 26%, transparent);
  background: transparent;
}
.site .btn.gh:hover {
  background: color-mix(in srgb, currentColor 8%, transparent);
  border-color: color-mix(in srgb, currentColor 45%, transparent);
  box-shadow: none;
}

/* L'anneau de mise au point : il ne doit apparaître qu'au clavier, jamais
   après un clic de souris — d'où :focus-visible et non :focus. */
.site a:focus-visible, .site button:focus-visible,
.site input:focus-visible, .site select:focus-visible, .site [tabindex]:focus-visible {
  outline: 2px solid var(--crimson);
  outline-offset: 3px;
  border-radius: var(--r-xs);
}


/* ══════════════════════════════════════════════════════════════════════════
   4. LES CARTES — et le projecteur qui suit le curseur

   `--mx` / `--my` sont écrits par anim.js : la position du curseur À
   L'INTÉRIEUR de la carte, en pourcentage. Une seule lueur radiale suit le
   pointeur. C'est très peu de chose, et c'est ce qui fait qu'une grille de
   cartes cesse d'être une grille de rectangles.
   ══════════════════════════════════════════════════════════════════════════ */
.site .card {
  border-radius: var(--r-m);
  padding: clamp(22px, 2.4vw, 32px);
  box-shadow: var(--sh);
  position: relative;
  isolation: isolate;
  transition: transform var(--t-app) var(--e),
              box-shadow var(--t-app) var(--e),
              border-color var(--t-app) var(--e);
}
.site .card::before {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--t-app) var(--e);
  background: radial-gradient(340px circle at var(--mx, 50%) var(--my, 0%),
              color-mix(in srgb, var(--crimson) 13%, transparent), transparent 62%);
}
.site .card:hover {
  transform: translateY(-4px);
  box-shadow: var(--sh2);
  border-color: color-mix(in srgb, var(--crimson) 32%, var(--brd));
}
.site .card:hover::before { opacity: 1; }

/* La carte « la plus choisie » : l'étiquette devient une pastille posée,
   pas une écharpe collée au bord. */
.site .card.hi { border-width: 1px; box-shadow: var(--sh2); }
.site .card.hi::after {
  top: -12px; right: 22px;
  font-size:11px; letter-spacing: .1em; font-weight: 700;
  padding:4px 12px; border-radius: var(--r-pill);
  box-shadow: 0 6px 18px -6px rgba(192,9,58,.8);
}
.site .card .ico {
  width: 46px; height: 46px; border-radius: var(--r-s);
  font-size:21px; margin-bottom:16px;
  transition: transform var(--t-app) var(--e);
}
.site .card:hover .ico { transform: scale(1.06) rotate(-3deg); }


/* ══════════════════════════════════════════════════════════════════════════
   5. LA BARRE DU HAUT

   Elle devient une lame de verre : fine, translucide, floutée. Le flou coûte
   un repeint à chaque défilement — on le limite donc à une bande basse, avec
   un fond opaque de repli là où backdrop-filter n'existe pas.
   ══════════════════════════════════════════════════════════════════════════ */
.site .topnav, body.dark .site .topnav,
.site .topnav.collante, body.dark .site .topnav.collante {
  padding: 13px var(--gout);
  gap:20px;
  border-bottom: 1px solid transparent;
  transition: background-color var(--t-app) var(--e),
              border-color var(--t-app) var(--e),
              backdrop-filter var(--t-app) var(--e),
              box-shadow var(--t-app) var(--e);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .site .topnav.collante { background: color-mix(in srgb, var(--paper) 72%, transparent); }
  body.dark .site .topnav.collante { background: rgba(9,13,20,.62); }
  /* posé par anim.js dès que la page a défilé */
  /* 20 px de flou et 170 % de saturation coûtaient, à la mesure, 7 images
     longues sur un défilement de 4 000 px contre 2 sans le verre : chaque
     image redessine la bande floutée. À 14 px l'effet est le même à l'œil et
     la dépense retombe. */
  .site .topnav.collante.pose {
    -webkit-backdrop-filter: blur(14px) saturate(140%);
            backdrop-filter: blur(14px) saturate(140%);
    border-bottom-color: color-mix(in srgb, var(--ink) 9%, transparent);
  }
  body.dark .site .topnav.collante.pose {
    background: rgba(9,13,20,.78);
    border-bottom-color: rgba(255,255,255,.08);
  }
}
.site .topnav .lk {
  font-size:14px; font-weight: 500;
  padding:8px 2px; position: relative;
  transition: color var(--t-etat) var(--e);
}
/* Le trait sous le lien pousse depuis le centre. Il est en transform, donc
   composé par le GPU : aucun recalcul de mise en page au survol. */
.site .topnav .lk::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 1px; height: 1.5px;
  background: currentColor; border-radius: 2px;
  transform: scaleX(0); transform-origin: 50% 50%;
  transition: transform var(--t-etat) var(--e);
}
.site .topnav .lk:hover::after, .site .topnav .lk.act::after { transform: scaleX(1); }
.site .topnav .lg { transition: transform var(--t-etat) var(--e); }
.site .topnav .lg:hover { transform: scale(1.03); }
.site .tiroirbtn { border-radius: var(--r-xs); width: 40px; height: 38px;
  transition: background-color var(--t-etat) var(--e), border-color var(--t-etat) var(--e); }


/* ══════════════════════════════════════════════════════════════════════════
   6. LE GRAND BANDEAU D'ACCUEIL
   ══════════════════════════════════════════════════════════════════════════ */
.site .hero { padding: clamp(72px, 9vw, 148px) var(--gout) clamp(76px, 9vw, 152px); }
.site .heroin { max-width: 1160px; gap: clamp(32px, 5vw, 72px); }
.site .hero h1 {
  font-size: clamp(38px, 5.6vw, 78px);
  letter-spacing: -.035em; line-height: 1.02; font-weight: 800;
  margin:0 0 20px;
}
.site .hero p { font-size: clamp(17px, 1.5vw, 21px); max-width: 30ch; margin-bottom:32px; line-height: 1.5; }
.site .hero .kick {
  border-radius: var(--r-pill); padding:8px 16px; font-size:12px; letter-spacing: .09em;
  margin-bottom:20px;
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
.site .hero .cta { gap:12px; }


/* ══════════════════════════════════════════════════════════════════════════
   7. PROFONDEUR — la parallaxe

   Les décors de fond (les bulles en filigrane, les lueurs) sont poussés loin
   sur l'axe Z.

   DEUX MESURES, PAS UNE — et c'est le point où l'on se trompe
   Une couche FIXE (le filigrane du site, épinglé au viewport) ne bouge pas du
   tout : elle est à l'infini. Pour la rapprocher, il faut la faire remonter
   un peu à mesure qu'on descend. Elle lit `--sy`, le défilement global.
   Une couche EN FLUX (les lueurs du bandeau) monte déjà à pleine vitesse avec
   la page. Pour l'éloigner, il faut la faire redescendre — la retenir. Elle
   lit `--py`, calculé par rapport à sa propre position dans l'écran.
   Appliquer la même formule aux deux donne l'inverse de l'effet voulu sur
   l'une des deux : le fond « colle » au curseur au lieu de traîner.

   Tout passe par translate3d et opacity, les deux seules propriétés que le
   compositeur sait animer sans repasser par la mise en page.
   ══════════════════════════════════════════════════════════════════════════ */
.site [data-prof] {
  transform: translate3d(0, var(--py, 0px), 0);
}

/* le filigrane général du site : la couche la plus lointaine */
body::before {
  transform: translate3d(0, calc(var(--sy, 0px) * .11), 0) scale(1.12);
  transition: opacity var(--t-gros) var(--e);
}

/* Les lueurs du bandeau d'accueil deviennent deux vraies couches, l'une
   derrière l'autre, qui dérivent à des vitesses différentes. */
.site .hero { isolation: isolate; }
.site .hero .lueur {
  position: absolute; border-radius: 50%; pointer-events: none; z-index: 0;
}
/* Pas de `filter: blur()` ici : un dégradé radial dont la transparence part
   du centre EST déjà un flou, et il ne coûte rien. Le filtre par-dessus
   refaisait le travail une seconde fois, en rasterisant à chaque image une
   surface de 900 px de côté — 4 images longues de plus sur un défilement. */
.site .hero .lueur.a {
  left: -8%; top: -18%; width: 62%; aspect-ratio: 1;
  background: radial-gradient(circle closest-side,
              rgba(41,102,178,.55) 0%, rgba(41,102,178,.28) 42%,
              rgba(41,102,178,.08) 68%, transparent 100%);
}
.site .hero .lueur.b {
  right: -12%; bottom: -28%; width: 58%; aspect-ratio: 1;
  background: radial-gradient(circle closest-side,
              rgba(178,20,64,.46) 0%, rgba(178,20,64,.22) 44%,
              rgba(178,20,64,.06) 70%, transparent 100%);
}
.site .heroin { z-index: 2; }


/* ══════════════════════════════════════════════════════════════════════════
   8. APPARITIONS AU DÉFILEMENT

   État de départ posé par anim.js, et par lui seul : si le script ne tourne
   pas — vieux navigateur, erreur JS, robot d'indexation — la classe n'est
   jamais posée et tout reste visible. Une apparition au défilement écrite
   en CSS pur cache le contenu à ceux qui n'ont pas le script. Jamais.
   ══════════════════════════════════════════════════════════════════════════ */
.site .vient {
  opacity: 0;
  transform: translate3d(0, 24px, 0);
  transition: opacity .6s var(--e), transform .6s var(--e);
  transition-delay: var(--retard, 0ms);
}
.site .vient.la { opacity: 1; transform: none; }


/* ══════════════════════════════════════════════════════════════════════════
   9. LA COLLECTION — présenter des livres comme des objets

   CE QUI N'ALLAIT PAS
   Chaque manuel était une carte : un cadre blanc, une bordure, et sous la
   couverture une ligne « 10,00 € · Disponible ». On regardait des fiches
   produit, pas des livres.

   CE QUI CHANGE
   Le cadre disparaît. Il ne reste que la couverture, posée sur la page, avec
   son ombre. Trois détails la font exister comme objet :
     · une tranche — un liseré sombre le long du bord gauche, comme le dos
       d'un livre vu de face ;
     · une lumière — une bande claire qui traverse la couverture en diagonale
       au survol, une fois, comme un reflet quand on incline un livre ;
     · une ombre qui s'ouvre en même temps que le livre monte, ce qui donne
       la hauteur. Sans elle, la montée ressemble à un glissement.

   Le prix ne figure plus ici : sur une planche de cinq couvertures, cinq
   étiquettes de prix transforment une collection en rayonnage de supermarché.
   Il reste sur la page Tarifs, où on le cherche vraiment.
   ══════════════════════════════════════════════════════════════════════════ */
.site .books { gap: clamp(16px, 2.2vw, 30px); }

.site .book {
  background: transparent !important;
  border: 0 !important;
  border-radius: 0;
  overflow: visible;
  box-shadow: none !important;
  transition: transform var(--t-app) var(--e);
}
.site .book .cv {
  border-radius: var(--r-s);
  overflow: hidden;
  box-shadow: var(--sh2);
  transform-origin: 50% 100%;
  transition: transform var(--t-app) var(--e), box-shadow var(--t-app) var(--e);
  isolation: isolate;
}
/* la tranche */
.site .book .cv::before {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 9px; z-index: 3;
  pointer-events: none;
  background: linear-gradient(90deg,
              rgba(0,0,0,.42) 0%, rgba(0,0,0,.14) 46%,
              rgba(255,255,255,.16) 72%, rgba(255,255,255,0) 100%);
}
/* le reflet — hors cadre au repos, il traverse au survol */
.site .book .refl {
  position: absolute; inset: -40% -60%; z-index: 4; pointer-events: none;
  background: linear-gradient(102deg, transparent 38%,
              rgba(255,255,255,.30) 48%, rgba(255,255,255,.06) 55%, transparent 62%);
  transform: translate3d(-130%, 0, 0);
  opacity: 0;
}
.site .book:hover .cv    { transform: translateY(-12px) scale(1.022); box-shadow: var(--sh3); }
.site .book:hover .refl  { animation: tfa-reflet .78s var(--e) forwards; }
@keyframes tfa-reflet {
  0%   { transform: translate3d(-130%, 0, 0); opacity: 0; }
  18%  { opacity: 1; }
  100% { transform: translate3d(130%, 0, 0);  opacity: 0; }
}

/* la pastille de niveau : elle avance légèrement avec la couverture */
.site .book .cv .lvl {
  top: 12px; right: 12px;
  border-radius: var(--r-pill); padding:4px 12px; font-size:11px; letter-spacing: .06em;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  transition: transform var(--t-app) var(--e);
}
.site .book:hover .cv .lvl { transform: translateY(-2px); }

/* la légende : elle ne porte plus le prix, seulement l'état, et elle
   s'éclaircit quand on survole le livre */
.site .book .ft {
  padding:12px 2px 0;
  display: block;
  font-size:14px;
  color: var(--soft2);
  transition: color var(--t-etat) var(--e);
  border: 0 !important;
}
.site .book .ft b  { display: block; font-size:15px; font-weight: 600; color: var(--ink);
                     letter-spacing: -.015em; transition: color var(--t-etat) var(--e); }
.site .book .ft em { font-style: normal; font-size:13px; color: var(--soft2); }
.site .book:hover .ft b { color: var(--crimson); }
body.dark .site .book .ft b { color: #EAF1FA; }
body.dark .site .book:hover .ft b { color: #FF7E9C; }

/* les manuels encore à écrire : sourds, mais pas éteints */
.site .book.a-venir .cv { box-shadow: var(--sh); }
.site .book.a-venir:hover .cv { transform: translateY(-6px); box-shadow: var(--sh2); }
.site .book .cv .bientot {
  bottom: 14px; border-radius: var(--r-pill); padding:4px 12px; font-size:10px;
  letter-spacing: .12em;
}


/* ══════════════════════════════════════════════════════════════════════════
   10. TFA TV — LES VIGNETTES

   L'ancien survol ouvrait une fausse fenêtre de lecture : badge « APERÇU »
   clignotant, minuteur qui défilait, barre de progression qui avançait. Rien
   de tout cela n'était vrai, et un intervalle JavaScript tournait à chaque
   passage de souris.

   Le nouveau survol dit la vérité et tient en trois gestes : la vignette
   grandit un peu, son image s'éloigne en se floutant, et le titre monte
   par-dessus. Le flou n'est pas décoratif — c'est lui qui rend le texte
   lisible sans avoir à poser un rectangle noir.
   ══════════════════════════════════════════════════════════════════════════ */
.site .tvtrack { gap: clamp(12px, 1.4vw, 20px); padding: 38px var(--gout); }
.site .tvcard  { transition: transform var(--t-app) var(--e); }
.site .tvcard .thumb {
  border-radius: var(--r-s);
  box-shadow: 0 4px 16px rgba(0,0,0,.42);
  transition: box-shadow var(--t-app) var(--e);
}
.site .tvcard .thumb .g {
  transition: transform var(--t-gros) var(--e), filter var(--t-app) var(--e);
}
.site .tvcard.hot { transform: scale(1.09); z-index: 30; }
.site .tvcard.hot .thumb { box-shadow: 0 22px 54px -12px rgba(0,0,0,.72); }
.site .tvcard.hot .thumb .g { transform: scale(1.1); filter: blur(7px) brightness(.62) saturate(1.15); }

/* la couche d'information : elle n'existe qu'au survol */
.site .tvcard .ov {
  position: absolute; inset: 0; z-index: 4;
  display: flex; flex-direction: column; justify-content: flex-end;
  padding:12px 12px;
  opacity: 0;
  transition: opacity var(--t-app) var(--e);
  pointer-events: none;
}
.site .tvcard.hot .ov { opacity: 1; }
.site .tvcard .ov b {
  display: block; font-size:14px; font-weight: 600; color: #fff; line-height: 1.3;
  letter-spacing: -.012em;
  transform: translate3d(0, 10px, 0);
  transition: transform var(--t-app) var(--e);
  text-shadow: 0 1px 12px rgba(0,0,0,.6);
}
.site .tvcard .ov small {
  display: block; font-size:12px; color: #C9DAEF; margin-top:4px;
  transform: translate3d(0, 14px, 0);
  transition: transform var(--t-app) var(--e);
}
.site .tvcard.hot .ov b, .site .tvcard.hot .ov small { transform: none; }
/* le rond de lecture, au centre */
.site .tvcard .ov .pl {
  position: absolute; left: 50%; top: 46%; width: 46px; height: 46px; margin:-24px 0 0 -24px;
  border-radius: 50%; display: grid; place-items: center;
  background: rgba(255,255,255,.94); color: #08152A; font-size:14px; padding-left:4px;
  transform: scale(.7); opacity: 0;
  transition: transform var(--t-app) var(--e), opacity var(--t-app) var(--e);
  box-shadow: 0 8px 24px rgba(0,0,0,.4);
}
.site .tvcard.hot .ov .pl { transform: scale(1); opacity: 1; }

/* on efface l'ancienne fenêtre : elle n'est plus construite, cette règle
   protège seulement d'un cache de page ancienne */
.site .tvcard .pop { display: none !important; }

/* l'étiquette Premium : un filet, du verre, et un léger recul au survol —
   plus le petit cartouche opaque d'avant */
.site .prem {
  top: 10px; right: 10px;
  font-size:9px; letter-spacing: .16em; font-weight: 700;
  border-radius: var(--r-pill); padding:4px 12px;
  border: 1px solid rgba(255,255,255,.42);
  background: rgba(10,18,34,.28);
  -webkit-backdrop-filter: blur(8px) saturate(150%); backdrop-filter: blur(8px) saturate(150%);
  transition: transform var(--t-app) var(--e), opacity var(--t-app) var(--e),
              border-color var(--t-app) var(--e);
}
.site .tvcard.hot .prem {
  transform: translateY(-3px);
  border-color: rgba(255,255,255,.75);
}
.site .tvcard .thumb .lk2, .site .tvcard .thumb .dur {
  border-radius: var(--r-pill); padding:4px 8px; font-size:10px; letter-spacing: .04em;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  transition: opacity var(--t-app) var(--e);
}
.site .tvcard.hot .thumb .lk2, .site .tvcard.hot .thumb .dur { opacity: 0; }
.site .tvcard .cap { font-size:13px; margin-top:12px; font-weight: 500;
  transition: color var(--t-etat) var(--e); }
.site .tvcard.hot .cap { color: #fff; }

/* les filtres : ils étaient trop serrés pour le doigt comme pour l'œil */
.site .tvchip {
  padding:8px 16px; border-radius: var(--r-pill); font-size:13px; font-weight: 500;
  transition: background-color var(--t-etat) var(--e), color var(--t-etat) var(--e),
              border-color var(--t-etat) var(--e), transform var(--t-etat) var(--e);
}
.site .tvchip:hover { transform: translateY(-1px); }
.site .tvrangee, .site .tvrow h3 { font-size: clamp(17px, 1.6vw, 22px); margin:32px 0 8px; }
.site .tvnav { border-radius: var(--r-s); width: 44px; }


/* ══════════════════════════════════════════════════════════════════════════
   11. LES DEUX BANDES BEIGES

   « Vous cherchez plutôt des cours pour votre enfant ? » et « Vous êtes
   professeur d'anglais ? » étaient peintes en sable et rose poudré —
   #F2E9DB / #E7DAC3 — héritées d'une palette qui n'a jamais été celle de la
   marque. En thème sombre elles viraient au brun (#2B2318), une couleur qui
   n'existe nulle part ailleurs sur le site. Elles reviennent dans le bleu
   nuit maison, chacune avec sa lueur : violette pour Kids, bleue pour les
   professeurs, de sorte qu'on les distingue sans sortir de la charte.
   ══════════════════════════════════════════════════════════════════════════ */
.site .kidsband, body.dark .site .kidsband,
.site .b2b,      body.dark .site .b2b {
  border-radius: var(--r-l);
  padding: clamp(26px, 3.2vw, 44px) clamp(24px, 3.4vw, 48px);
  gap: clamp(20px, 2.6vw, 34px);
  position: relative; overflow: hidden; isolation: isolate;
  color: #fff;
  border: 1px solid rgba(255,255,255,.10);
  box-shadow: var(--sh2);
}
.site .kidsband, body.dark .site .kidsband {
  background:
    radial-gradient(120% 150% at 8% 10%, rgba(126,74,196,.55), transparent 58%),
    linear-gradient(118deg, #14213D 0%, #1B2C51 55%, #241A47 100%);
}
.site .b2b, body.dark .site .b2b {
  background:
    radial-gradient(120% 150% at 92% 12%, rgba(31,96,178,.52), transparent 58%),
    linear-gradient(118deg, #0C1E38 0%, #102A4C 58%, #0B2038 100%);
}
.site .kidsband h3, .site .b2b h3,
body.dark .site .kidsband h3, body.dark .site .b2b h3 {
  color: #fff; font-size: clamp(21px, 2.2vw, 30px); font-weight: 700; margin:0 0 12px;
}
.site .kidsband p, .site .b2b p,
body.dark .site .kidsband p, body.dark .site .b2b p {
  color: #BFD2E9; font-size: clamp(14.5px, 1.15vw, 16.5px); max-width: 62ch; margin:0;
}
.site .kidsband .kf {
  width: 84px; height: 84px; flex: 0 0 84px; border-radius: var(--r-m); font-size:34px;
  background: linear-gradient(150deg, #C0093A, #7E4AC4);
  box-shadow: 0 16px 40px -12px rgba(126,74,196,.75);
  transition: transform var(--t-app) var(--e);
}
.site .kidsband:hover .kf { transform: rotate(-6deg) scale(1.05); }
.site .kidsband .badge, .site .b2b .badge {
  background: rgba(255,255,255,.10); border: 1px solid rgba(255,255,255,.17);
  color: #DCE9F8; border-radius: var(--r-pill); padding:4px 12px; font-size:12px;
}
.site .kidsband .mini, .site .b2b .mini { color: #9FB6D2; }
.site .kidsband .mini b, .site .b2b .mini b { color: #fff !important; }
/* la bande porte le filigrane des bulles, très en retrait */
.site .kidsband::after, .site .b2b::after {
  content: ""; position: absolute; z-index: -1; pointer-events: none;
  right: -70px; bottom: -110px; width: 320px; height: 320px;
  background: var(--bul) center/contain no-repeat; opacity: .06;
  transform: translate3d(0, var(--py, 0px), 0);
}
.site .b2b .btn.nv { background: #fff; color: #0C1E38; }
.site .b2b .btn.nv:hover { background: #fff; box-shadow: 0 12px 30px -10px rgba(255,255,255,.45); }


/* ══════════════════════════════════════════════════════════════════════════
   12. LA BASCULE MENSUEL / ANNUEL

   LE DÉFAUT
   Trois éléments disaient l'état en même temps — l'étiquette « Mensuel », le
   curseur, l'étiquette « Annuel » — et le curseur passait au rouge vif en
   position annuelle. On lisait donc un rouge de marque à côté d'un bouton
   d'appel rouge, et l'œil ne savait plus lequel des trois était l'état
   courant. S'y ajoutait un curseur animé sur `left`, propriété qui déclenche
   un recalcul de position à chaque image.

   LA CORRECTION
   Un seul objet dit l'état : une pastille pleine qui glisse sous l'étiquette
   active, en transform. Les étiquettes ne changent que de couleur. Et
   l'économie annuelle s'affiche enfin, ce qui était l'intérêt du bouton.
   ══════════════════════════════════════════════════════════════════════════ */
.site .billsw {
  position: relative;
  gap:0; padding:4px;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--ink) 7%, transparent);
  border: 1px solid color-mix(in srgb, var(--ink) 8%, transparent);
  isolation: isolate;
}
body.dark .site .billsw {
  background: rgba(255,255,255,.06); border-color: rgba(255,255,255,.09);
}
/* LA PASTILLE EST MESURÉE, PAS CALCULÉE.
   Elle était posée à `width: calc(50% - 4px)` — or « Mensuel » et « Annuel »
   n'ont pas la même largeur : elle débordait de l'un et flottait dans
   l'autre. Elle utilise maintenant exactement le même élément et le même
   script que le sélecteur Adultes / Enfants, largeur relevée sur l'étiquette
   visée, et glissement au survol en annonce du clic. */
.site .billsw .audpuce {
  position: absolute; flex: none; z-index: 0;
  top: 4px; bottom: 4px; left: 0;
}

/* `:not(.audpuce)` — la pastille est un `span` elle aussi. Sans cette
   exclusion, `.site .billsw span` (spécificité 0,2,1) l'emportait sur
   `.site .audpuce` (0,2,0) : la pastille devenait un troisième élément de la
   rangée, en position relative et sans fond. On la voyait alors flotter à
   gauche de « Mensuel », grise et décalée de 45 px. */
.site .billsw span:not(.audpuce) {
  position: relative; z-index: 1;
  flex: 1 1 50%; text-align: center; white-space: nowrap;
  padding:8px 20px; border-radius: var(--r-pill);
  font-size:14px; font-weight: 600; letter-spacing: -.01em;
  background: none !important;
  color: var(--soft);
  transition: color var(--t-app) var(--e);
}
.site .billsw span.on, body.dark .site .billsw span.on { color: #fff; }
.site .billsw:hover span.on { color: var(--soft); }
.site .billsw span:not(.audpuce):hover,
body.dark .site .billsw span:not(.audpuce):hover { color: #fff; }
/* le curseur séparé n'a plus lieu d'être : la pastille EST le curseur */
.site .billsw .knob { display: none !important; }
/* l'économie, annoncée à sa place */
.site .billsw .eco {
  position: absolute; left: 100%; top: 50%; transform: translate(14px, -50%);
  white-space: nowrap; font-size:13px; font-weight: 600; color: var(--green);
  opacity: 0; transition: opacity var(--t-app) var(--e);
  pointer-events: none;
}
body.annual .site .billsw .eco { opacity: 1; }
@media (max-width: 560px) {
  .site .billsw { width: 100%; max-width: 340px; }
  .site .billsw .eco { position: static; display: block; transform: none; margin-top:8px; text-align: center; }
}


/* ══════════════════════════════════════════════════════════════════════════
   13. LE PIED DE PAGE ET LES RÉSEAUX

   Les réseaux n'étaient qu'une colonne de mots, indistincts des liens de
   navigation d'à côté. Chacun reçoit sa marque et sa couleur officielle. Au
   repos le logo reste sobre — sept logos en couleurs vives dans un pied de
   page, c'est un feu d'artifice ; la couleur ne s'allume qu'au survol.
   ══════════════════════════════════════════════════════════════════════════ */
.site footer.site { padding-top: clamp(48px, 5vw, 76px); }
.site footer.site .cols { gap: clamp(26px, 3vw, 52px); }
.site footer.site h5 {
  font-size:12px; letter-spacing: .14em; font-weight: 700; margin-bottom:16px;
}
.site footer.site a {
  transition: color var(--t-etat) var(--e), transform var(--t-etat) var(--e);
}
.site footer.site .cols a:not(.res) { display: block; padding:4px 0; }
.site footer.site .cols a:not(.res):hover { transform: translateX(3px); }

.site footer.site a.res {
  display: flex; align-items: center; gap:12px;
  padding:8px 0; font-size:14px;
}
.site footer.site a.res svg {
  width: 19px; height: 19px; flex: 0 0 19px;
  fill: currentColor; color: var(--soft2);
  transition: color var(--t-app) var(--e), transform var(--t-app) var(--e);
}
.site footer.site a.res:hover svg { color: var(--rc, var(--crimson)); transform: scale(1.16); }
.site footer.site a.res:hover { color: var(--ink); }
body.dark .site footer.site a.res:hover { color: #fff; }
.site footer.site a.res[href=""], .site footer.site a.res:not([href]) { opacity: .45; }
.site footer.site .bot { margin-top: clamp(30px, 3.4vw, 52px); padding-top:20px; gap:16px; }


/* ══════════════════════════════════════════════════════════════════════════
   14. DÉTAILS QUI SE VOIENT PARTOUT
   ══════════════════════════════════════════════════════════════════════════ */
.site .badge, .site .puce, .site .tag {
  border-radius: var(--r-pill); padding:4px 12px; font-size:12px; letter-spacing: 0;
}
.site .bande, .site .attente, .site .exres, .site .authcarte, .site .authcote,
.site .serie, .site .kpicard, .site .txtblk, .site .ex, .site .illus {
  border-radius: var(--r-m);
}
.site .bande, .site .attente { padding: clamp(26px, 3.2vw, 44px) clamp(24px, 3.4vw, 48px); }
.site .bande h3, .site .attente h3 { font-size: clamp(21px, 2.2vw, 30px); font-weight: 700; }
.site .ain, .site .attente input {
  border-radius: var(--r-s); padding:12px 16px; font-size:15px;
  transition: border-color var(--t-etat) var(--e), background-color var(--t-etat) var(--e);
}
.site a.serie { transition: transform var(--t-app) var(--e), box-shadow var(--t-app) var(--e),
                            border-color var(--t-app) var(--e); }
.site a.serie:hover { transform: translateY(-4px); box-shadow: var(--sh2); }
.site .clubkpi > div, .site .kpicard { transition: transform var(--t-app) var(--e); }
.site .clubkpi > div:hover { transform: translateY(-3px); }

/* Les images ne doivent jamais apparaître d'un coup à leur pleine netteté
   pendant que la page se met en place : `decoding=async` est posé par
   anim.js, et un fondu de 0,44 s absorbe l'arrivée. */
.site img[data-fondu] { opacity: 0; transition: opacity .44s var(--e); }
.site img[data-fondu].la { opacity: 1; }


/* ══════════════════════════════════════════════════════════════════════════
   15. MOUVEMENT RÉDUIT — obligation, pas option

   Le critère WCAG 2.3.3 « Animation from Interactions » cite nommément la
   parallaxe. On ne coupe pas les animations à zéro : `animation: none` casse
   les scripts qui attendent un événement `animationend`. On les ramène à une
   durée imperceptible, ce qui déclenche les événements sans produire de
   mouvement. Les fondus d'opacité, eux, restent : ils ne sont pas du
   mouvement et ils aident à comprendre ce qui change.
   ══════════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
  .site *, .site *::before, .site *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .site .vient { opacity: 1 !important; transform: none !important; }
  .site [data-prof], .site .hero .lueur, body::before,
  .site .kidsband::after, .site .b2b::after { transform: none !important; }
  .site .books.deploie .book { animation: none !important; }
  .site .book:hover .cv, .site .card:hover, .site .tvcard.hot { transform: none !important; }
}


/* ══════════════════════════════════════════════════════════════════════════
   16. L'ÉVENTAIL DE LA COLLECTION

   Sur la page produit d'Apple, la gamme entre à l'écran groupée puis s'ouvre :
   les appareils s'écartent, se redressent et grandissent ensemble. C'est la
   seule animation de la page qui présente plusieurs objets d'un coup, et
   c'est pour cela qu'on la retient.

   Ici les cinq manuels font la même entrée, mais à leur manière : ils
   arrivent penchés vers le centre, comme des livres serrés sur une étagère,
   et se redressent un par un. La rotation de départ est donnée par --rot,
   écrit par anim.js selon la distance au centre de la rangée — le livre du
   milieu ne tourne pas, ceux des extrémités tournent le plus.

   L'animation ne se joue qu'une fois, à la première entrée à l'écran. Rejouée
   à chaque passage, elle deviendrait un tic.
   ══════════════════════════════════════════════════════════════════════════ */
.site .books.deploie .book {
  animation: tfa-eventail .82s var(--e) both;
  animation-delay: calc(var(--i, 0) * 65ms);
}
@keyframes tfa-eventail {
  from {
    opacity: 0;
    transform: translate3d(var(--dx, 0px), 34px, 0) rotate(var(--rot, 0deg)) scale(.9);
  }
  to {
    opacity: 1;
    transform: translate3d(0, 0, 0) rotate(0deg) scale(1);
  }
}


/* ══════════════════════════════════════════════════════════════════════════
   17. LE BANDEAU D'ACCUEIL (page d'accueil)

   Il faisait 470 px de haut, quelle que soit la taille de l'écran : sur un
   grand moniteur c'était une bande, pas une ouverture. Il occupe maintenant
   une part de la hauteur disponible, et son image dérive plus lentement que
   la page — c'est la parallaxe la plus lisible du site, parce que le regard
   s'y trouve déjà.

   DEUX MOUVEMENTS SUR UN SEUL ÉLÉMENT
   L'image répondait déjà à la souris, par un `transform` écrit en ligne
   depuis tfa.js. Ajouter la parallaxe de défilement au même endroit aurait
   fait que le dernier des deux efface l'autre. Les deux écrivent donc chacun
   leur variable, et le transform les additionne ici, une fois pour toutes.
   ══════════════════════════════════════════════════════════════════════════ */
.site .hero2 {
  height: auto;
  min-height: clamp(480px, 76vh, 760px);
  display: grid;
}
.site .hero2 > * { grid-area: 1 / 1; }
.site .hero2 .heroimg {
  transform: translate3d(var(--mx2, 0px), calc(var(--my2, 0px) + var(--py, 0px)), 0) scale(1.07);
  transition: transform .5s var(--e-soft);
}
.site .hero2 .heroctn { padding: clamp(30px, 6vw, 80px) var(--gout); position: relative; }
.site .hero2 .heroctn h1 {
  font-size: clamp(36px, 5.4vw, 76px);
  letter-spacing: -.036em; line-height: 1.02; font-weight: 800;
  max-width: 17ch; margin:0 0 20px;
}
.site .hero2 .heroctn .kick2 {
  font-size:12px; letter-spacing: .34em; font-weight: 600; margin-bottom:20px;
}
.site .hero2 .heroctn p {
  font-size: clamp(16.5px, 1.5vw, 21px); max-width: 56ch; line-height: 1.5; margin-bottom:32px;
}
.site .hero2 .heroctn .cta { gap:12px; }
.site .hbtn {
  border-radius: var(--r-pill); padding:12px 32px; font-size:16px; font-weight: 600;
  letter-spacing: -.01em;
}
.site .hbtn:hover { transform: translateY(-1.5px); }

/* la flèche du bas : elle respire au lieu de sauter */
.site .scrollhint {
  bottom: 26px; font-size:22px;
  animation: tfa-respire 2.6s var(--e) infinite;
}
@keyframes tfa-respire {
  0%, 100% { transform: translate(-50%, 0);    opacity: .5; }
  50%      { transform: translate(-50%, 8px);  opacity: .95; }
}
@media (prefers-reduced-motion: reduce) {
  .site .scrollhint { animation: none; transform: translateX(-50%); }
}


/* ══════════════════════════════════════════════════════════════════════════
   18. LA BARRE DU HAUT, MESURÉE

   Élargir les boutons et les écarts a fait passer la barre de une à quatre
   lignes : sept liens, un sélecteur, trois appels à l'action et un logo, cela
   fait 1 499 px de contenu pour 1 372 px utiles. Une barre qui se replie sur
   quatre lignes n'est plus une barre.

   Les valeurs ci-dessous sont ajustées à la mesure, pas à l'estime : la barre
   tient sur une ligne jusqu'à 1 300 px, et en dessous les liens rejoignent le
   tiroir ☰ — qui les contient déjà tous. Mieux vaut un menu assumé qu'une
   barre qui déborde.
   ══════════════════════════════════════════════════════════════════════════ */
.site .topnav, body.dark .site .topnav,
.site .topnav.collante, body.dark .site .topnav.collante {
  gap:16px; row-gap:8px;
  padding-left: clamp(16px, 2.2vw, 26px);
  padding-right: clamp(16px, 2.2vw, 26px);
}

  /* ══ LA BARRE DU HAUT SE MESURE EN LARGEUR, PAS EN CONFORT ══
     L'arrondi des demi-pixels remonte partout vers le haut : agrandir
     un texte ne nuit jamais. Ici, si. La barre porte dix éléments sur
     une seule ligne ; un demi-pixel gagné sur chacun l'a fait passer
     à DEUX lignes à 1280 px — vu sur la comparaison avant/après, pas
     deviné. Dans une barre dense, la contrainte n'est pas la lisibilité
     (13 px reste au-dessus du plancher), c'est l'encombrement. On
     arrondit donc vers le bas, et on l'écrit ici pour que le prochain
     passage de l'outil ne le défasse pas. */
  .site .topnav .lk { font-size:13px; }
.site .topnav .lg b { font-size:10px; letter-spacing: .07em; }
.site .topnav .rt { gap:8px; }
.site .topnav .rt .btn { padding:8px 16px; font-size:13px; }
.site .topnav .rt .btn.sm { padding:8px 12px; font-size:12px; }
.site .topnav .audsw a { padding:8px 12px; font-size:12px; }
.site .tiroirbtn { width: 38px; height: 36px; }

/* En dessous de 1 300 px les liens passent dans le tiroir. La règle d'origine
   attendait 980 px, largeur à laquelle la barre débordait depuis longtemps. */
@media (max-width: 1340px) {
  .site .topnav .lk { display: none; }
}
@media (max-width: 1080px) {
  .site .topnav .audsw { display: none; }
}
@media (max-width: 860px) {
  .site .topnav .rt .btn.gh { display: none; }
}


/* ══════════════════════════════════════════════════════════════════════════
   19. LE FILIGRANE — moins, mais mieux placé

   « Très peu de logo, il faut que ce soit épuré » : les bulles étaient à 5-7 %
   partout à la fois — fond de page, pied de page, bandes — et l'addition
   finissait par se voir. Elles descendent à 2,5-3,5 % et le pied de page n'en
   garde qu'une seule, à droite.
   ══════════════════════════════════════════════════════════════════════════ */
body::before      { opacity: .028 !important; }
body.dark::before { opacity: .035 !important; }
.site footer.site::before { display: none; }
.site footer.site::after  { opacity: .03; width: 300px; height: 230px; right: -90px; }

/* « Se connecter » redevient un lien, pas un bouton — c'est l'arbitrage que
   font Apple, Stripe ou Linear en haut de leurs pages. Trois surfaces pleines
   côte à côte se disputent l'attention, et surtout elles ne tiennent pas :
   1 412 px de contenu pour 1 388 utiles à 1 440 px d'écran. Après ce
   dégraissage — lien plutôt que bouton, sélecteur resserré, logo d'un demi-
   point plus petit, écarts à 13 px — il reste 1 340 px, soit 48 px de marge.
   Et l'œil sait enfin lequel des trois est l'action principale. */
.site .topnav .authbtns .lgin,
body.dark .site .topnav .authbtns .lgin {
  background: transparent !important; border: 0 !important; box-shadow: none !important;
  padding:8px 4px; font-weight: 500; color: var(--ink);
  transition: color var(--t-etat) var(--e);
}
body.dark .site .topnav .authbtns .lgin { color: #DCE7F5; }
.site .topnav .authbtns .lgin:hover { color: var(--crimson); }
body.dark .site .topnav .authbtns .lgin:hover { color: #FF7E9C; }
.site .topnav .authbtns { gap:8px; }
.site .topnav .rt { gap:8px; }
.site .topnav, .site .topnav.collante,
body.dark .site .topnav, body.dark .site .topnav.collante { gap:12px; }
.site .topnav .audsw a { padding:4px 12px; font-size:12px; }
.site .topnav .lg b { font-size:10px; letter-spacing: .06em; }
/* la règle « max-width: 1200px » qui masquait ici le sélecteur Adultes /
   Enfants a été supprimée : la section 25 la contredisait vingt lignes plus
   bas en le RÉAFFICHANT dès 1161 px. Le seuil unique est désormais posé une
   seule fois, plus bas, et il est mesuré. */


/* ══════════════════════════════════════════════════════════════════════════
   20. TROIS DÉFAUTS TROUVÉS EN REGARDANT LE RÉSULTAT

   a) LA PASTILLE DE NIVEAU EN DOUBLE
   Les couvertures portent déjà le niveau imprimé — la bulle « A1 » fait
   partie de l'illustration. Le site en superposait une seconde, en CSS. Tant
   qu'elles se recouvraient exactement, cela ne se voyait pas ; dès que la
   couverture s'est mise à monter au survol, on a vu les deux. On retire la
   pastille CSS là où la couverture existe : l'information est déjà là.

   b) L'ÉCONOMIE ANNONCÉE DEUX FOIS
   J'avais ajouté « 2 mois offerts » à côté de la bascule. Le badge d'à côté
   disait déjà « 2 mois offerts · jusqu'à −17 % » : les deux se chevauchaient
   littéralement. Le badge suffit ; il passe simplement en vert, parce qu'une
   économie n'est pas un appel à l'action et n'a rien à faire en rouge de
   marque à côté du bouton « S'abonner ».

   c) LE TITRE ÉCRIT DEUX FOIS SUR LES VIGNETTES
   Au survol, le titre s'affiche sur l'image floutée alors que la légende sous
   la vignette le répète. La légende s'efface le temps du survol.
   ══════════════════════════════════════════════════════════════════════════ */
.site .book.avec-couv .cv .lvl { display: none; }

.site .billbadge {
  background: color-mix(in srgb, var(--green) 14%, transparent);
  color: var(--green);
  border: 1px solid color-mix(in srgb, var(--green) 32%, transparent);
  border-radius: var(--r-pill); padding:8px 16px; font-size:13px;
  font-weight: 600; letter-spacing: 0;
}
body.dark .site .billbadge { color: #5FCB8A; border-color: rgba(95,203,138,.3);
  background: rgba(95,203,138,.12); }
.site .billrow { gap:16px; margin-bottom: clamp(30px, 3.4vw, 48px); }

.site .tvcard.hot .cap { opacity: 0; }
.site .tvcard .cap { transition: opacity var(--t-app) var(--e), color var(--t-etat) var(--e); }

/* La vignette grandit vers le centre de la rangée. Sans cela, la première
   déborde par la gauche et la dernière par la droite — elles se font couper
   au lieu de s'ouvrir. */
.site .tvcard { transform-origin: center center; }
.site .tvcard:first-child  { transform-origin: left center; }
.site .tvcard:last-child   { transform-origin: right center; }


/* ══════════════════════════════════════════════════════════════════════════
   21. TÉLÉPHONE — ce que l'audit a relevé à 320 px

   Les valeurs généreuses du bureau ne se transposent pas telles quelles : un
   bouton de 32 px de rembourrage tient dans une carte de 1 100 px, pas dans
   un écran de 320. Chaque correction ci-dessous répond à un défaut mesuré,
   pas à une intuition.
   ══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 760px) {
  /* le bouton de la bande Kids dépassait de 5 px de son cadre */
  .site .kidsband .btn.lg, .site .b2b .btn.lg,
  .site .kidsband .kbtn, .site .b2b .kbtn {
    width: 100%; text-align: center; padding-left:16px; padding-right:16px;
    margin-left:0;
  }
  .site .kidsband > div:last-child, .site .b2b > *:last-child { width: 100%; }

  /* la signature du pied de page sortait de 14 px : la ligne du bas doit
     pouvoir passer à la ligne comme n'importe quelle autre */
  .site footer.site .bot {
    flex-wrap: wrap; row-gap:12px; gap:12px;
  }
  .site footer.site .bot em { margin-left:0; }

  .site .hero2 { min-height: clamp(440px, 72vh, 560px); }
  .site .hero2 .heroctn h1 { font-size: clamp(30px, 8.6vw, 42px); }
  .site .billrow { flex-direction: column; }
}

@media (max-width: 400px) {
  .site .btn.lg { padding:12px 20px; font-size:15px; }
  .site .card { padding:20px 16px; }
  .site .kidsband, .site .b2b { padding:24px 20px; }
}


/* ══════════════════════════════════════════════════════════════════════════
   22. LA RANGÉE TFA TV AU DOIGT

   DÉFAUT MESURÉ : la première vignette collait au bord gauche de l'écran,
   sans marge, alors que la piste porte bien 20 px de rembourrage.

   CAUSE : `scroll-snap-align: start` aligne le bord de la vignette sur le
   début de la ZONE DE DÉFILEMENT, pas sur le bord intérieur du rembourrage.
   Le navigateur faisait donc défiler la rangée de 20 px dès l'affichage pour
   satisfaire l'accrochage — scrollLeft valait 20 au chargement, exactement la
   valeur du rembourrage. Le remède n'est pas de retirer la marge, c'est de
   dire au défilement où commence vraiment le contenu : `scroll-padding`.
   ══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 900px), (hover: none) {
  .site .tvviewport {
    scroll-padding-inline:20px;
    /* le masque adoucit le bord droit : on voit que la rangée continue */
    -webkit-mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 40px), transparent 100%);
            mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 40px), transparent 100%);
  }
  .site .tvtrack { padding:16px 20px 20px; gap:12px; }
  .site .tvcard, .site .tvcard:first-child, .site .tvcard:last-child { transform: none !important; }
  .site .tvcard .ov { display: none; }     /* il n'y a pas de survol au doigt */
  .site .tvcard.hot .cap { opacity: 1; }
  .site .tvchip { padding:8px 16px; font-size:13px; }
}

/* ── l'interlettrage des sur-titres est calculé pour le bureau ── */
@media (max-width: 620px) {
  .site .eyebrow, .site .sur { letter-spacing: .1em; font-size:11px; }
  .site .hero2 .heroctn .kick2 { letter-spacing: .18em; font-size:11px; }
}


/* ══════════════════════════════════════════════════════════════════════════
   23. TROIS PLANS DANS LE BANDEAU D'ACCUEIL

   La profondeur ne vient pas d'une couche qui bouge : elle vient de trois
   couches qui bougent à des vitesses différentes.
     · la photo, la plus lointaine, retenue de 60 px ;
     · deux lueurs colorées entre la photo et le voile, retenues de 90 et
       150 px, en `screen` pour qu'elles éclairent l'image au lieu de la
       salir ;
     · le titre, qui suit la page à sa vitesse.
   ══════════════════════════════════════════════════════════════════════════ */
.site .hero2 .lueur {
  position: absolute; border-radius: 50%; pointer-events: none;
  z-index: 1; mix-blend-mode: screen; opacity: .8;
}
.site .hero2 .heroscrim { z-index: 2; }
.site .hero2 .heroctn   { z-index: 3; }
.site .hero2 .scrollhint{ z-index: 4; }
.site .hero2 .lueur.a {
  left: -14%; top: -22%; width: 66%; aspect-ratio: 1;
  background: radial-gradient(circle closest-side,
              rgba(56,126,214,.50) 0%, rgba(56,126,214,.22) 44%, transparent 100%);
}
.site .hero2 .lueur.b {
  right: -16%; bottom: -30%; width: 62%; aspect-ratio: 1;
  background: radial-gradient(circle closest-side,
              rgba(214,36,88,.44) 0%, rgba(214,36,88,.18) 46%, transparent 100%);
}
@media (prefers-reduced-motion: reduce) { .site .hero2 .lueur { display: none; } }


/* ══════════════════════════════════════════════════════════════════════════
   24. LA COLLECTION EN GRAND — « Explore the lineup »

   Les couvertures faisaient 168 px de large dans une grille de cinq. Un
   manuel de 248 pages présenté à la taille d'une vignette de contact ne se
   vend pas : on ne lit ni le titre imprimé, ni l'illustration, ni le soin
   qu'il y a dedans.

   La rangée passe donc en défilement horizontal, avec des cartes de 300 à
   380 px : deux et demie tiennent à l'écran, la troisième dépasse — c'est
   ce débord qui dit qu'il y en a d'autres, sans avoir à l'écrire.
   ══════════════════════════════════════════════════════════════════════════ */
.site .lineup {
  display: flex;
  gap: clamp(18px, 2.2vw, 34px);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scroll-padding-inline:2px;
  padding:8px 2px 12px;
  margin:0 -2px;
  scrollbar-width: none;
  -ms-overflow-style: none;
  /* le bord droit s'estompe : la rangée continue visiblement */
  -webkit-mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 56px), transparent 100%);
          mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 56px), transparent 100%);
}
.site .lineup::-webkit-scrollbar { display: none; }
.site .lineup.aufond {                       /* dernière carte atteinte */
  -webkit-mask-image: none; mask-image: none;
}

.site .lvcard {
  flex: 0 0 clamp(268px, 27vw, 372px);
  scroll-snap-align: start;
  display: flex; flex-direction: column;
  position: relative;
}

/* ── la scène : le fond teinté sur lequel l'objet est posé ── */
.site .lvscene {
  position: relative;
  aspect-ratio: 1 / 1.3;
  border-radius: var(--r-l);
  overflow: hidden;
  /* FLEX ET NON GRID — la nuance a des conséquences.
     Dans une grille dont la piste est `auto`, la piste est dimensionnée par
     son contenu ; résoudre un `max-height: 100 %` de l'image contre cette
     piste serait circulaire, alors le navigateur l'ignore. Mesuré : une
     couverture de 390 px dans une boîte de 333, débordant de 16 px sous le
     cadre. En flex, le pourcentage se résout contre la boîte de contenu du
     conteneur, qui est définie par l'aspect-ratio. La couverture tient. */
  display: flex; align-items: center; justify-content: center;
  padding: clamp(18px, 2.2vw, 32px) clamp(26px, 3.2vw, 46px);
  margin-bottom:20px;
  background:
    radial-gradient(120% 90% at 50% 6%, var(--t1) 0%, transparent 66%),
    linear-gradient(168deg, var(--t2) 0%, var(--t3) 100%);
  transition: transform var(--t-app) var(--e);
}
.site .lvcard[data-niv="a1"] { --t1:rgba(214,36,88,.28); --t2:#1A1020; --t3:#0C0F18; --tc:#FF7E9C; }
.site .lvcard[data-niv="a2"] { --t1:rgba(20,160,178,.26); --t2:#08181E; --t3:#0A1018; --tc:#5FD6E4; }
.site .lvcard[data-niv="b1"] { --t1:rgba(38,166,110,.24); --t2:#0A1A14; --t3:#0A1018; --tc:#5FCB8A; }
.site .lvcard[data-niv="b2"] { --t1:rgba(214,140,30,.24); --t2:#1C1509; --t3:#0F1016; --tc:#E7A63C; }
.site .lvcard[data-niv="c1"] { --t1:rgba(140,90,220,.26); --t2:#150F26; --t3:#0B0E18; --tc:#B79BF0; }

/* La couverture : elle flotte, avec son ombre portée.
   `height: 100%` la faisait déborder par le bas — dans une grille, 100 %
   se calcule sur la zone de grille et non sur la boîte de contenu, si bien
   que l'image mangeait le rembourrage inférieur et se trouvait coupée net
   au ras du cadre. On contraint par les MAXIMA et on laisse l'image choisir
   sa taille : elle se réduit jusqu'à tenir, sans jamais être rognée. */
.site .lvscene .cvimg {
  position: static;
  width: auto; height: auto;
  max-width: 100%; max-height: 100%;
  object-fit: contain;
  border-radius: 6px;
  box-shadow:
    0 2px 4px rgba(0,0,0,.4),
    0 26px 50px -14px rgba(0,0,0,.72);
  transition: transform var(--t-gros) var(--e), box-shadow var(--t-gros) var(--e);
}
.site .lvscene .cvimg::selection { background: transparent; }
/* la tranche, comme sur un livre vu de face */
.site .lvscene::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.05);
}
/* le reflet qui traverse la couverture au survol */
.site .lvscene .refl {
  position: absolute; inset: -30% -60%; z-index: 3; pointer-events: none;
  background: linear-gradient(102deg, transparent 40%,
              rgba(255,255,255,.22) 49%, rgba(255,255,255,.04) 56%, transparent 63%);
  transform: translate3d(-130%, 0, 0); opacity: 0;
}
.site .lvcard:hover .cvimg { transform: translateY(-10px) scale(1.035); }
.site .lvcard:hover .refl  { animation: tfa-reflet .8s var(--e) forwards; }

.site .lvfictif { text-align: center; color: #fff; }
.site .lvfictif b { display: block; font-size: clamp(20px, 2.4vw, 30px); font-weight: 800;
  letter-spacing: -.03em; line-height: 1.05; }
.site .lvfictif span { display: block; margin-top:12px; font-size:11px; letter-spacing: .18em;
  color: rgba(255,255,255,.5); }

.site .lvcard.a-venir .cvimg { filter: grayscale(.45) brightness(.62); }
.site .lvcard.a-venir .lvscene { opacity: .9; }
.site .lvscene .bientot {
  position: absolute; left: 50%; bottom: 18px; transform: translateX(-50%); z-index: 4;
  font-size:10px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  color: #fff; background: rgba(8,12,18,.5);
  border: 1px solid rgba(255,255,255,.3);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  border-radius: var(--r-pill); padding:4px 12px; white-space: nowrap;
}

/* ── le bloc de texte, sous l'objet ── */
.site .lvniv {
  display: inline-block; align-self: flex-start;
  font-size:11px; font-weight: 700; letter-spacing: .14em;
  color: var(--tc); border: 1px solid color-mix(in srgb, var(--tc) 34%, transparent);
  background: color-mix(in srgb, var(--tc) 11%, transparent);
  border-radius: var(--r-pill); padding:4px 12px; margin-bottom:12px;
}
.site .lvcard h3 {
  font-size: clamp(21px, 1.9vw, 27px); font-weight: 700; letter-spacing: -.026em;
  margin:0 0 12px; line-height: 1.15;
}
.site .lvacc {
  font-size:15px; line-height: 1.5; color: var(--soft); margin:0 0 12px;
  min-height: 3em;
}
.site .lvmeta { font-size:14px; color: var(--soft2); margin:0 0 20px; }
.site .lvacts { display: flex; align-items: center; gap:16px; flex-wrap: wrap; margin-top:auto; }
.site .lvacts .btn { padding:12px 24px; font-size:15px; }
.site .lvlien {
  font-size:15px; font-weight: 500; color: var(--navy-l); text-decoration: none;
  display: inline-flex; align-items: center; gap:4px;
  transition: color var(--t-etat) var(--e);
}
body.dark .site .lvlien { color: #8FB6F0; }
.site .lvlien i { font-style: normal; transition: transform var(--t-etat) var(--e); }
.site .lvlien:hover i { transform: translateX(4px); }

/* ── les flèches, comme sur la rangée d'Apple ── */
.site .lvrail { position: relative; }
.site .lvnav2 {
  position: absolute; top: 30%; width: 44px; height: 44px; border-radius: 50%;
  border: 0; cursor: pointer; z-index: 5;
  background: color-mix(in srgb, var(--ink) 10%, transparent);
  color: var(--ink); font-size:17px; line-height: 1;
  display: grid; place-items: center;
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  opacity: 0; pointer-events: none;
  transition: opacity var(--t-app) var(--e), background-color var(--t-etat) var(--e),
              transform var(--t-etat) var(--e);
}
body.dark .site .lvnav2 { background: rgba(255,255,255,.12); color: #fff; }
.site .lvnav2.utile { opacity: 1; pointer-events: auto; }
.site .lvnav2:hover { transform: scale(1.08); background: color-mix(in srgb, var(--ink) 18%, transparent); }
body.dark .site .lvnav2:hover { background: rgba(255,255,255,.2); }
.site .lvnav2.g { left: -10px; }
.site .lvnav2.d { right: -10px; }

@media (max-width: 760px) {
  .site .lvcard { flex-basis: 78vw; }
  .site .lvnav2 { display: none; }
  .site .lvacc { min-height: 0; }
}


/* ══════════════════════════════════════════════════════════════════════════
   25. LES LIENS REVIENNENT DANS LA BARRE

   Je les avais renvoyés dans le tiroir sous 1 340 px pour faire tenir la
   barre. C'était le mauvais arbitrage : sur un écran réglé à 150 %, un
   1 920 px devient 1 280 px de CSS, et les liens disparaissaient sur des
   moniteurs parfaitement grands.

   Le poste supprimé est ailleurs : le mot « TRULY FLUENT ACADEMY » écrit à
   côté du logo pèse 140 px et répète ce que le logo dit déjà. Il s'efface
   sous 1 460 px — la marque reste, par ses deux bulles. C'est exactement ce
   que fait Apple, qui n'écrit jamais son nom à côté de sa pomme.
   Les liens tiennent alors jusqu'à 1 060 px.
   ══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 1460px) {
  .site .topnav .lg b { display: none; }
}
@media (max-width: 1340px) {
  .site .topnav .lk { display: block; }      /* on annule la règle précédente */
}
/* ══════════════════════════════════════════════════════════════════════════
   DEUX BANDES DE LARGEUR OÙ LA BARRE DU HAUT PASSAIT À DEUX LIGNES

   Trouvées en balayant la largeur de 980 à 1340 px de cinq en cinq, parce
   que l'auditeur ne teste que 320 · 375 · 390 · 430 · 768 · 1280 : entre la
   tablette et l'ordinateur, il y avait un trou de 512 px où personne n'a
   jamais regardé. C'est précisément là que vivent les portables 1152 et
   1280, et tout écran 1280 affiché à 110 % de zoom (1164 px réels).

   • 1065 → 1075 px : les liens de navigation réapparaissaient à 1061 px
     alors que la barre a besoin de 1080 px pour les porter.
   • 1165 → 1235 px : le sélecteur Adultes / Enfants réapparaissait à
     1161 px alors qu'il en faut 1240. Deux règles se contredisaient — une
     section le masquait sous 1200 px, une autre le rétablissait dès 1161 —
     et c'est la seconde qui gagnait, écrite plus bas.

   Les deux seuils sont maintenant MESURÉS, pas devinés, et posés une seule
   fois chacun. Le seuil des liens réutilise le palier 1080 qui existait
   déjà ailleurs dans la feuille, plutôt que d'en inventer un de plus.
   ══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 1080px) {
  .site .topnav .lk { display: none; }
}
@media (max-width: 1240px) { .site .topnav .audsw { display: none; } }
@media (min-width: 1241px) { .site .topnav .audsw { display: inline-flex; } }


/* ══════════════════════════════════════════════════════════════════════════
   26. LE PANNEAU DE NAVIGATION

   Il descend sous la barre, sur toute la largeur, dans le même verre. Sa
   hauteur est animée ; ses contenus se croisent en fondu. Les deux durées
   sont différentes à dessein : la surface met 0,36 s à se redimensionner, le
   contenu 0,28 s à apparaître, de sorte que le texte arrive dans un cadre
   déjà presque en place et non pendant qu'il bouge encore.
   ══════════════════════════════════════════════════════════════════════════ */
.site .mega {
  position: absolute; left: 0; right: 0; top: 100%;
  z-index: 79;
  pointer-events: none;
  /* La barre déclare `white-space: nowrap` pour que ses liens ne se coupent
     jamais en deux. Le panneau vit maintenant dedans : sans cette remise à
     zéro, il en héritait et les phrases de la carte de droite sortaient du
     cadre au lieu de passer à la ligne. */
  white-space: normal;
}
.site .topnav.collante { position: sticky; }
.site .mega .megabg {
  position: absolute; inset: 0;
  opacity: 0;
  transition: opacity var(--t-app) var(--e);
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--ink) 10%, transparent);
  box-shadow: 0 24px 48px -28px rgba(9,25,50,.5);
}
body.dark .site .mega .megabg {
  background: rgba(9,13,20,.9);
  border-bottom-color: rgba(255,255,255,.08);
  box-shadow: 0 30px 60px -30px rgba(0,0,0,.8);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .site .mega .megabg {
    -webkit-backdrop-filter: blur(18px) saturate(150%);
            backdrop-filter: blur(18px) saturate(150%);
  }
}
.site .mega.ouvert { pointer-events: auto; }
.site .mega.ouvert .megabg { opacity: 1; }

.site .megaboite {
  position: relative;
  height: 0; overflow: hidden;
  transition: height var(--t-app) var(--e);
}
.site .megapan {
  position: absolute; left: 0; right: 0; top: 0;
  opacity: 0; transform: translate3d(0, -10px, 0);
  pointer-events: none;
  /* `visibility` et non seulement `opacity` : un élément à opacité nulle
     reste dans l'ordre de tabulation. Sans cette ligne, six panneaux fermés
     glissaient une quarantaine de liens invisibles entre la barre et le
     contenu — au clavier, on tabulait dans le vide. Le délai la maintient
     visible le temps que le fondu de sortie se termine. */
  visibility: hidden;
  transition: opacity .28s var(--e), transform .28s var(--e), visibility 0s linear .28s;
}
.site .megapan.la {
  opacity: 1; transform: none; pointer-events: auto;
  visibility: visible; transition-delay: 0s;
}

.site .megain {
  max-width: 1160px; margin:0 auto;
  padding: 34px clamp(20px, 4vw, 34px) 40px;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)) 1.15fr;
  gap: clamp(24px, 3vw, 56px);
  align-items: start;
}
.site .megacol h6 {
  margin:0 0 12px; font-size:11px; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--soft2);
}
.site .megacol a {
  display: block; padding:8px 0;
  font-size:16px; font-weight: 500; letter-spacing: -.012em;
  color: var(--ink); text-decoration: none;
  transition: color var(--t-etat) var(--e), transform var(--t-etat) var(--e);
}
body.dark .site .megacol a { color: #E6EEF9; }
.site .megacol a:hover { color: var(--crimson); transform: translateX(3px); }
body.dark .site .megacol a:hover { color: #FF7E9C; }

/* la carte de droite : une seule mise en avant par panneau, jamais deux */
.site .megamise {
  display: block; text-decoration: none;
  border-radius: var(--r-m); padding:20px 24px;
  background: linear-gradient(150deg, #0F2444 0%, #16345C 60%, #241A47 100%);
  color: #fff; position: relative; overflow: hidden;
  transition: transform var(--t-app) var(--e), box-shadow var(--t-app) var(--e);
}
.site .megamise:hover { transform: translateY(-3px); box-shadow: var(--sh2); }
.site .megamise .ms { display: block; font-size:11px; font-weight: 700;
  letter-spacing: .16em; color: #FF9CB6; margin-bottom:12px; }
.site .megamise b { display: block; font-size:19px; font-weight: 700;
  letter-spacing: -.02em; margin-bottom:8px; }
.site .megamise .mt { display: block; font-size:14px; line-height: 1.5;
  color: #BFD2E9; margin-bottom:12px; }
.site .megamise .ml { display: inline-flex; align-items: center; gap:8px;
  font-size:14px; font-weight: 600; color: #fff; }
.site .megamise .ml i { font-style: normal; transition: transform var(--t-etat) var(--e); }
.site .megamise:hover .ml i { transform: translateX(4px); }

/* le lien dont le panneau est ouvert reste allumé */
.site .topnav .lk.deroule { color: var(--crimson); }
body.dark .site .topnav .lk.deroule { color: #FF7E9C; }
.site .topnav .lk.deroule::after { transform: scaleX(1); }

/* le panneau déroulant suit exactement les liens qui l'ouvrent : même seuil,
   sinon il resterait atteignable au clavier alors que son lien a disparu. */
@media (max-width: 1080px) { .site .mega { display: none; } }
@media (prefers-reduced-motion: reduce) {
  .site .megaboite { transition: none; }
  .site .megapan { transition: opacity .01ms; transform: none; }
}


/* ══════════════════════════════════════════════════════════════════════════
   27. ADULTES / ENFANTS — la pastille glissante

   Même principe que la bascule tarifaire, avec une différence qui compte :
   ce sélecteur-ci change de page. La pastille ne peut donc pas glisser au
   clic, elle serait coupée net par le chargement. Elle glisse au SURVOL, en
   annonce de ce qui va arriver, et le passage d'une page à l'autre est pris
   en charge par la transition de vue ci-dessous.

   Sa largeur est mesurée sur le lien visé, jamais fixée à 50 % : « Adultes »
   et « Enfants » ne font pas la même largeur, et une pastille à moitié
   déborderait de l'un en flottant dans l'autre.
   ══════════════════════════════════════════════════════════════════════════ */
.site .audsw {
  position: relative; isolation: isolate;
  border-radius: var(--r-pill); padding:4px;
  background: color-mix(in srgb, var(--ink) 7%, transparent);
  border: 1px solid color-mix(in srgb, var(--ink) 8%, transparent);
}
body.dark .site .audsw { background: rgba(255,255,255,.06); border-color: rgba(255,255,255,.09); }
.site .audpuce {
  position: absolute; z-index: 0; top: 3px; bottom: 3px; left: 0;
  border-radius: var(--r-pill);
  background: var(--navy);
  box-shadow: 0 3px 12px -4px rgba(9,45,89,.6);
  transition: transform var(--t-app) var(--e), width var(--t-app) var(--e);
}
body.dark .site .audpuce { background: #23477B; }
.site .audsw a, body.dark .site .audsw a {
  position: relative; z-index: 1;
  background: none !important;
  color: var(--soft);
  transition: color var(--t-app) var(--e);
}
.site .audsw a.on, body.dark .site .audsw a.on { color: #fff; }
.site .audsw:hover a.on { color: var(--soft); }
.site .audsw a:hover, body.dark .site .audsw a:hover { color: #fff; }


/* ══════════════════════════════════════════════════════════════════════════
   28. LE PASSAGE D'UNE PAGE À L'AUTRE

   Adultes → Enfants était une coupure franche : la page blanchissait, puis
   l'autre apparaissait. Une seule règle demande au navigateur de fondre
   l'ancienne page dans la nouvelle. Là où elle n'est pas comprise, la
   navigation reste ce qu'elle était — rien à prévoir en repli.
   ══════════════════════════════════════════════════════════════════════════ */
@view-transition { navigation: auto; }
::view-transition-old(root) { animation: tfa-sortie .22s var(--e-in) both; }
::view-transition-new(root) { animation: tfa-entree .34s var(--e) both; }
@keyframes tfa-sortie { to { opacity: 0; transform: scale(.994); } }
@keyframes tfa-entree { from { opacity: 0; transform: scale(1.006); } }
/* la barre du haut ne doit pas fondre avec le reste : elle est commune aux
   deux pages, elle doit paraître ne pas avoir bougé */
.site .topnav.collante { view-transition-name: tfa-barre; }
::view-transition-group(tfa-barre) { animation-duration: .28s; }
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
}

/* La cible de « Voir les tarifs › » mesurait 94 × 24 px : sous le doigt,
   c'est trop petit — le seuil confortable est 44 px de haut. On l'atteint par
   le rembourrage vertical plutôt qu'en grossissant le texte, qui doit rester
   secondaire par rapport au bouton plein d'à côté. */
.site .lvlien { padding:12px 2px; }


/* ══════════════════════════════════════════════════════════════════════════
   29. LE THÈME CLAIR — la barre en verre bleu

   Le blanc pur d'origine n'appartenait pas à la marque : la charte est bâtie
   sur le bleu nuit #092D59, et rien ne le rappelait en haut de page. La barre
   prend une teinte tirée de ce bleu même, éclaircie et rendue translucide —
   c'est la couleur de la marque vue à travers du verre, pas une couleur de
   plus.

   Le panneau déroulant reprend exactement la même recette, un ton plus dense :
   deux surfaces de verre superposées doivent se ressembler, sinon la seconde
   a l'air posée par-dessus au lieu d'appartenir à la première.
   ══════════════════════════════════════════════════════════════════════════ */
body:not(.dark) {
  --verre:      color-mix(in srgb, var(--navy) 12%, #FFFFFF);
  --verre-fort: color-mix(in srgb, var(--navy) 15%, #FFFFFF);
  --verre-brd:  color-mix(in srgb, var(--navy) 18%, transparent);
}
body:not(.dark) .site .topnav.collante {
  background: color-mix(in srgb, var(--verre) 78%, transparent);
}
body:not(.dark) .site .topnav.collante.pose {
  background: color-mix(in srgb, var(--verre) 86%, transparent);
  border-bottom-color: var(--verre-brd);
  box-shadow: 0 1px 0 rgba(255,255,255,.7) inset;
}
/* Opaque, et non translucide : sous la barre il n'y a pas un fond neutre mais
   la photo du bandeau, blanche et contrastée. À 8 % de transparence le titre
   « L'anglais enfin » traversait encore le panneau et rendait les liens
   illisibles. Le verre est réservé à la barre elle-même, qui est fine. */
body:not(.dark) .site .mega .megabg {
  background: var(--verre-fort);
  border-bottom-color: var(--verre-brd);
  box-shadow: 0 26px 50px -30px rgba(9,45,89,.42);
}
/* le tiroir, le sélecteur et les pastilles suivent la même teinte */
body:not(.dark) .site .audsw,
body:not(.dark) .site .billsw,
body:not(.dark) .site .tiroirbtn {
  background: color-mix(in srgb, var(--navy) 6%, transparent);
  border-color: var(--verre-brd);
}
body:not(.dark) .site .megacol h6 { color: color-mix(in srgb, var(--navy) 62%, transparent); }
body:not(.dark) .site .megacol a  { color: var(--navy); }


/* ══════════════════════════════════════════════════════════════════════════
   30. LE PRIX SUR LA COUVERTURE — le bandeau crimson

   LE CONCEPT VENAIT DE VOUS : un bandeau de marque qui monte du bas, le prix
   en grand, l'information secondaire à droite, le niveau en dessous. Ce qui
   change ici tient en quatre points, et chacun répond à un défaut visible sur
   la maquette d'origine.

   1. LE BANDEAU EST TRANSLUCIDE, PAS OPAQUE.
      Un aplat plein efface la moitié de la couverture au moment précis où
      l'on vient la regarder. Un dégradé de crimson à 88 % en bas et 72 % en
      haut laisse deviner l'illustration dessous : on voit qu'il y a un objet,
      pas un rectangle rouge posé dessus.

   2. IL NE COUVRE QUE 38 % DE LA HAUTEUR, PAS LA MOITIÉ.
      Assez pour deux lignes confortables, assez peu pour que la scène reste
      la vedette.

   3. TROIS ENTRÉES DÉCALÉES PLUTÔT QU'UNE.
      Le bandeau monte, puis le prix arrive par la gauche, puis le niveau se
      lève. Trente millisecondes séparent chaque départ. C'est ce décalage qui
      donne la sensation d'un mouvement composé plutôt que d'un bloc qui
      apparaît — le même principe que le tiroir du menu.

   4. LA COUVERTURE S'ASSOMBRIT SOUS LE BANDEAU.
      Sans cela le texte blanc lutte contre une illustration claire et il
      faut lui ajouter une ombre portée, qui salit tout.

   Le nombre de chapitres remplace le nombre de pages : c'est l'unité dans
   laquelle nos manuels sont réellement découpés, et la seule que je puisse
   afficher sans l'inventer.
   ══════════════════════════════════════════════════════════════════════════ */
.site .lvprix {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 5;
  height: 38%;
  display: flex; flex-direction: column; justify-content: center; gap:8px;
  padding: 0 clamp(20px, 2.2vw, 30px);
  color: #fff;
  background: linear-gradient(0deg,
              rgba(176, 8, 53, .90) 0%,
              rgba(192, 9, 58, .84) 62%,
              rgba(206, 16, 68, .74) 100%);
  border-top: 1px solid rgba(255, 255, 255, .16);
  transform: translate3d(0, 101%, 0);
  visibility: hidden;
  transition: transform var(--t-app) var(--e), visibility 0s linear var(--t-app);
  pointer-events: none;
}
.site .lvcard:hover .lvprix,
.site .lvcard:focus-within .lvprix {
  transform: none; visibility: visible; transition-delay: 0s;
}

/* ligne 1 : le prix, très grand, et ce qu'il y a dedans, à droite */
.site .lvp1 { display: flex; align-items: baseline; justify-content: space-between; gap:12px; }
.site .lvprix b {
  font-size: clamp(30px, 3vw, 42px); font-weight: 600; letter-spacing: -.04em;
  line-height: 1; white-space: nowrap;
  /* il entre par la gauche, comme sur votre exemple */
  transform: translate3d(-24px, 0, 0); opacity: 0;
  transition: transform .34s var(--e), opacity .3s var(--e);
}
.site .lvprix .lvp1 span {
  font-size:13px; font-weight: 500; color: rgba(255, 255, 255, .82);
  white-space: nowrap;
  transform: translate3d(16px, 0, 0); opacity: 0;
  transition: transform .34s var(--e), opacity .3s var(--e);
}
/* ligne 2 : le niveau, en français puis en code CECRL */
.site .lvp2 {
  font-size:15px; font-weight: 500; letter-spacing: -.01em;
  color: rgba(255, 255, 255, .92);
  transform: translate3d(0, 12px, 0); opacity: 0;
  transition: transform .34s var(--e), opacity .3s var(--e);
}
.site .lvcard:hover .lvprix b,
.site .lvcard:focus-within .lvprix b { transform: none; opacity: 1; transition-delay: .07s; }
.site .lvcard:hover .lvprix .lvp1 span,
.site .lvcard:focus-within .lvprix .lvp1 span { transform: none; opacity: 1; transition-delay: .11s; }
.site .lvcard:hover .lvp2,
.site .lvcard:focus-within .lvp2 { transform: none; opacity: 1; transition-delay: .14s; }

/* la couverture recule sous le bandeau */
.site .lvscene .cvimg { transition: transform var(--t-gros) var(--e), filter var(--t-app) var(--e); }
.site .lvcard:hover .cvimg { transform: translateY(-8px) scale(1.03); filter: brightness(.74) saturate(.95); }
.site .lvcard.a-venir:hover .cvimg { filter: grayscale(.45) brightness(.5); }

/* le « Bientôt » remonte pour ne pas se faire recouvrir */
.site .lvscene .bientot { transition: transform var(--t-app) var(--e), opacity var(--t-app) var(--e); }
.site .lvcard:hover .lvscene .bientot { opacity: 0; transform: translate(-50%, 14px); }

@media (hover: none) {
  /* Au doigt il n'y a pas de survol : le bandeau reste affiché en permanence,
     sinon l'information disparaît purement et simplement pour la moitié des
     visiteurs. Mais il reste À SA PLACE, au bas de la scène.
     `position: static` était une erreur : `.lvprix` est un enfant de
     `.lvscene`, qui est une boîte flexible centrant la couverture. Sorti du
     flux absolu, le bandeau devenait un deuxième élément de cette rangée et
     se rangeait À DROITE du livre, moitié hors cadre. Constaté à l'écran.
     Il reste donc absolu, simplement toujours visible et plus discret : un
     voile sombre au lieu de l'aplat crimson, qui pèserait en permanence. */
  .site .lvprix {
    height: auto; transform: none; visibility: visible;
    padding: 18px clamp(18px, 4vw, 24px) 16px; gap:4px;
    background: linear-gradient(0deg, rgba(6,10,16,.92) 0%, rgba(6,10,16,.72) 60%, rgba(6,10,16,0) 100%);
    border-top: 0;
  }
  .site .lvprix b, .site .lvprix .lvp1 span, .site .lvp2 {
    transform: none; opacity: 1; transition: none;
  }
  .site .lvprix b { font-size: clamp(24px, 6vw, 30px); color: #fff; }
  .site .lvprix .lvp1 span, .site .lvp2 { color: rgba(255,255,255,.78); }
  .site .lvp2 { font-size:14px; }
  .site .lvcard .lvmeta { display: none; }
  .site .lvcard .lvscene .bientot { bottom: 96px; }
}

@media (prefers-reduced-motion: reduce) {
  .site .lvprix, .site .lvprix b, .site .lvprix .lvp1 span, .site .lvp2 {
    transition-duration: .01ms !important;
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   31. LES FAMILLES DE LA COLLECTION

   Quatre pastilles encadrées, chacune avec un badge de comptage à fond plein :
   huit surfaces colorées pour dire quatre choses. Elles deviennent un
   sélecteur d'un seul tenant, avec une piste qui glisse sous l'onglet actif —
   la même mécanique que la bascule tarifaire et que le sélecteur Adultes /
   Enfants, si bien que le site n'a plus qu'une seule façon de dire « voici
   les options, en voici une de choisie ».

   Le nombre passe en exposant : il informe sans peser.
   ══════════════════════════════════════════════════════════════════════════ */
.site .famtabs {
  position: relative; isolation: isolate;
  display: inline-flex; flex-wrap: nowrap; gap:0;
  margin: clamp(20px, 2.4vw, 32px) 0 clamp(22px, 2.6vw, 34px);
  padding:4px;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--ink) 6%, transparent);
  border: 1px solid color-mix(in srgb, var(--ink) 8%, transparent);
  max-width: 100%; overflow-x: auto; scrollbar-width: none;
}
.site .famtabs::-webkit-scrollbar { display: none; }
body.dark .site .famtabs { background: rgba(255,255,255,.05); border-color: rgba(255,255,255,.08); }
body:not(.dark) .site .famtabs {
  background: color-mix(in srgb, var(--navy) 6%, transparent); border-color: var(--verre-brd);
}

/* La pastille se déplace en DEUX dimensions et prend la hauteur de sa cible.
   Les neuf catégories de TFA TV tiennent sur une ligne à 1 440 px et sur deux
   à 1 100 : une pastille qui ne bouge qu'horizontalement se retrouverait sur
   la mauvaise ligne dès le premier repli. */
.site .ftpuce {
  /* ORIGINE À ZÉRO, ET NON À 4 px.
     La position de la puce est calculée en JavaScript à partir de
     `offsetLeft`, qui se mesure depuis le bord intérieur de l'hôte. Un
     décalage de 4 px écrit ici s'AJOUTAIT à ce calcul, et la bordure de 1 px
     de l'hôte s'y ajoutait encore : la puce tombait 5 px trop à droite et
     5 px trop bas, sur chaque onglet. Assez peu pour passer pour un défaut
     de rendu, assez pour se voir. Une position calculée et une position
     déclarée ne doivent jamais se cumuler. */
  position: absolute; z-index: 0; top: 0; left: 0; width: 0; height: 0;
  border-radius: var(--r-pill);
  background: var(--navy);
  box-shadow: 0 4px 14px -5px rgba(9,45,89,.55);
  transition: transform var(--t-app) var(--e), width var(--t-app) var(--e),
              height var(--t-app) var(--e), background-color var(--t-app) var(--e);
}
.site .tvchips .ftpuce { top: 0; left: 0; }
body.dark .site .ftpuce { background: #23477B; }

.site .ftab, body.dark .site .ftab {
  position: relative; z-index: 1;
  font: inherit; border: 0; background: none; cursor: pointer;
  white-space: nowrap;
  display: inline-flex; align-items: baseline; gap:8px;
  padding:8px 16px; border-radius: var(--r-pill);
  font-size:14px; font-weight: 500; letter-spacing: -.01em;
  color: var(--soft);
  transition: color var(--t-app) var(--e);
}
.site .ftab i {
  font-style: normal; font-size:11px; font-weight: 600;
  color: color-mix(in srgb, currentColor 55%, transparent);
  background: none; padding:0; border-radius: 0;
}
.site .ftab:hover { color: var(--ink); }
body.dark .site .ftab:hover { color: #EAF1FA; }
.site .ftab.on, body.dark .site .ftab.on { color: #fff; }
.site .ftab.on i { color: rgba(255,255,255,.66); }


/* ══════════════════════════════════════════════════════════════════════════
   32. LE TIROIR ☰ — ouverture à la manière d'Apple

   L'ancienne ouverture : `translateX(-100%)` en 0,22 s, courbe `ease`, et le
   contenu déjà en place à l'arrivée. Le panneau arrivait comme un volet qui
   claque.

   Ce qui change :
   · le panneau glisse en 0,5 s sur la courbe de signature — assez lent pour
     qu'on voie qu'il vient de la gauche, assez amorti pour qu'il ne rebondisse
     pas ;
   · les entrées ne sont pas là quand il arrive : elles montent une par une,
     30 ms d'écart, pendant que le panneau finit sa course. C'est ce décalage
     qui fait qu'un menu paraît « se déployer » plutôt que « se montrer » ;
   · l'icône ☰ se replie en croix : le trait du haut descend et pivote de 45°,
     celui du milieu s'efface en se rétractant, celui du bas remonte et pivote
     de −45°. C'est le même bouton, il change d'état ; deux icônes qui se
     remplacent liraient comme deux boutons différents.
   ══════════════════════════════════════════════════════════════════════════ */
.site .tiroir, body.dark .site .tiroir, .tiroir {
  transition: transform .5s var(--e);
  will-change: transform;
}
.voile { transition: opacity .44s var(--e), visibility 0s linear .44s; }
.voile.ouvert { transition: opacity .34s var(--e), visibility 0s; }

.tiroir h4, .tiroir a, .tiroir .tnote {
  opacity: 0;
  transform: translate3d(-14px, 0, 0);
  transition: opacity .42s var(--e), transform .42s var(--e);
}
.tiroir.ouvert h4, .tiroir.ouvert a, .tiroir.ouvert .tnote {
  opacity: 1; transform: none;
  transition-delay: calc(140ms + var(--i, 0) * 26ms);
}
/* l'en-tête ne fait pas partie du déploiement : il appartient au panneau */
.tiroir .thead, .tiroir .thead * { opacity: 1; transform: none; transition: none; }

/* l'icône qui se replie en croix */
.site .tiroirbtn .hamb path {
  transform-box: fill-box; transform-origin: center;
  transition: transform .44s var(--e), opacity .2s var(--e);
}
body.menu-ouvert .site .tiroirbtn .h1,
body.menu-ouvert .tiroirbtn .h1 { transform: translateY(5px) rotate(45deg); }
body.menu-ouvert .site .tiroirbtn .h2,
body.menu-ouvert .tiroirbtn .h2 { opacity: 0; transform: scaleX(.15); }
body.menu-ouvert .site .tiroirbtn .h3,
body.menu-ouvert .tiroirbtn .h3 { transform: translateY(-5px) rotate(-45deg); }

@media (prefers-reduced-motion: reduce) {
  .tiroir h4, .tiroir a, .tiroir .tnote { opacity: 1; transform: none; transition: none; }
  .site .tiroirbtn .hamb path { transition: none; }
}

/* ── LA BARRE RESTE AU-DESSUS DU TIROIR ──────────────────────────────────────
   Le tiroir recouvrait la barre : l'icône avait beau se replier en croix,
   personne ne la voyait — 100 % du travail d'animation était invisible. Chez
   Apple la barre ne bouge jamais ; c'est elle qui porte l'état ouvert/fermé,
   et le panneau glisse dessous. On inverse donc l'ordre d'empilement, on
   décale le contenu du tiroir de la hauteur de la barre, et son en-tête
   interne disparaît : il ferait doublon avec la vraie barre restée en place,
   logo compris. */
.site .topnav.collante, body.dark .site .topnav.collante { z-index: 200; }
.tiroir { padding-top:80px; z-index: 190; }
.tiroir .thead { display: none; }
.voile { z-index: 180; }


/* ══════════════════════════════════════════════════════════════════════════
   33. OCCUPER LA PLACE

   Le constat, annoté sur les captures : « negative space » à gauche et à
   droite, « trop petit » au milieu. Les deux vont ensemble. Le contenu était
   enfermé dans 1 160 px au centre d'un écran qui en offre 1 280 à 1 900, et
   comme la colonne était étroite, tout ce qu'elle contenait avait été réduit
   pour y tenir. On élargit d'abord, on agrandit ensuite : dans l'autre sens
   on obtient du texte qui déborde.

   1 320 px, et jusqu'à 1 480 px au-delà de 1 700 px d'écran. Au-delà, on
   arrête : une ligne de texte de plus de 90 caractères se lit mal, quelle que
   soit la taille de l'écran.
   ══════════════════════════════════════════════════════════════════════════ */
.site .in, .site .blk2, .site .megain { max-width: 1320px; }
@media (min-width: 1700px) {
  .site .in, .site .blk2, .site .megain { max-width: 1480px; }
  .site .heroin, .site .hero2 .heroctn { max-width: 1480px; }
}
.site .heroin { max-width: 1320px; }

/* Les colonnes intérieures suivent : une grille de deux colonnes dans un
   cadre élargi doit répartir le gain, pas le laisser au milieu. */
.site .grid2 { gap: clamp(24px, 3vw, 52px); }
.site .grid3 { gap: clamp(20px, 2.2vw, 34px); }
.site .grid4 { gap: clamp(16px, 1.8vw, 28px); }
/* Encadré dans une requête média À PARTIR de 1 081 px — et pour la troisième
   fois de ce projet, pour la même raison : `.site .methode .grid2` (0,3,0)
   écrase le repli mobile écrit `.grid2` (0,1,0), et une requête média
   n'ajoute aucune spécificité. Sans ce cadre, la section restait à deux
   colonnes à 320 px et le texte débordait de 18 px. */
@media (min-width: 1081px) {
  .site .methode .grid2 { grid-template-columns: 1.06fr .94fr; }
}


/* ══════════════════════════════════════════════════════════════════════════
   34. DENSITÉ — que personne n'ait à plisser les yeux

   Relevé automatique : 219 déclarations de moins de 13 px dans les feuilles
   d'origine, dont une bonne part portait de vraies phrases. La maquette avait
   été dessinée pour être vue en petit ; ces corps-là n'ont jamais été prévus
   pour être lus en vrai.

   Distinction faite ici : une ÉTIQUETTE (un niveau, une durée, un état) peut
   rester petite, mais pas sous 11 px ; un TEXTE qui forme une phrase passe à
   15 px au minimum, 16,5 px dans les cartes.
   ══════════════════════════════════════════════════════════════════════════ */
.site .card p, .site .mrow p, .site .qcard2 span,
.site .exres div, .site .kcard p, .site .profcard p {
  font-size:17px; line-height: 1.6;
}
.site .mrow h4, .site .kcard h4 { font-size:18px; letter-spacing: -.018em; margin-bottom:4px; }
.site .mrow { gap:16px; margin-bottom:20px; align-items: flex-start; }
.site .mnum {
  width: 30px; height: 30px; flex: 0 0 30px; font-size:14px; font-weight: 700;
}
.site .mini, .site .apk, .site .serie .smeta, .site p.mini { font-size:14px; line-height: 1.6; }
.site ul.ck li { font-size:16px; padding:8px 0 8px 24px; }
.site ul.ck li::before { font-size:13px; }
.site .samplebox {
  font-size:16px; line-height: 1.68;
  padding: clamp(20px, 2.2vw, 28px) clamp(22px, 2.4vw, 32px);
  border-radius: var(--r-m);
}
.site .badge, .site .tag, .site .puce, .site .nivtag, .site .sniv,
.site .clubkpi span, .site .exres .lb, .site .lb {
  font-size:12px; letter-spacing: .06em;
}
.site .clubkpi b, .site .kpicard b { font-size: clamp(28px, 2.6vw, 38px); }
.site .price, .site .pm .p2 { font-size: clamp(30px, 2.8vw, 40px); }
.site .price small, .site .pm .p2 small { font-size:14px; }
.site .pm { padding: clamp(18px, 1.8vw, 26px) clamp(16px, 1.7vw, 24px); }
.site .pm h4 { font-size:17px; }
.site .pm .u { font-size:14px; margin-bottom:12px; }
.site .pm ul { font-size:15px; line-height: 1.6; }
.site .pm ul li { padding:4px 0 4px 16px; }
.site .doc p, .site .txtblk .corps { font-size:17px; line-height: 1.8; }
.site .exemples, .site .attention { font-size:16px; padding:16px 20px; border-radius: var(--r-s); }
.site .ex li { font-size:16px; padding:12px 0; }
.site .nmots { font-size:15px; padding:12px 20px; }
.site .st3 { font-size:15px; }
.site .ltfacts b { font-size: clamp(20px, 2vw, 26px); }
.site .quickrow .qcard2 b { font-size:16px; }
.site .authcote li { font-size:15px; }
.site .tvcard .cap { font-size:14px; }


/* ══════════════════════════════════════════════════════════════════════════
   35. TFA TV — LES AFFICHES VERTICALES

   Les vidéos sont tournées en 9:16 pour Instagram et TikTok. Les présenter
   dans un cadre 16:9 revenait à recadrer une image verticale en horizontale :
   on perdait la tête et les pieds, c'est-à-dire tout ce qui compte. La
   vignette devient donc une affiche verticale — le format des jaquettes de la
   référence Netflix, et celui du fichier lui-même.

   Conséquence de cadrage : une affiche verticale est HAUTE. À 180 px de large
   elle fait 320 px de haut ; six tiennent encore de front sur un écran de
   1 320 px, ce qui garde la rangée lisible sans la transformer en mur.
   ══════════════════════════════════════════════════════════════════════════ */
.site .tvrow { margin-bottom: clamp(34px, 3.6vw, 56px); }
.site .tvrow h3 {
  font-size: clamp(19px, 1.7vw, 25px); font-weight: 700; letter-spacing: -.024em;
  margin:0 0 16px; display: flex; align-items: baseline; gap:12px; flex-wrap: wrap;
}
.site .tvrow h3 span { font-size:14px; font-weight: 500; color: #93AECD; letter-spacing: 0; }

/* la zone de défilement : une vraie, avec molette, doigt et clavier */
.site .tvviewport {
  position: relative;
  overflow-x: auto; overflow-y: visible;
  scroll-snap-type: x proximity;
  scroll-padding-inline:2px;
  scrollbar-width: none; -ms-overflow-style: none;
  padding:8px 0 12px;
}
.site .tvviewport::-webkit-scrollbar { display: none; }
.site .tvtrack {
  display: flex; gap: clamp(12px, 1.1vw, 18px);
  padding:0; transform: none !important; width: max-content;
}

.site .tvcard {
  flex: 0 0 clamp(146px, 12.2vw, 194px);
  width: auto; scroll-snap-align: start;
  cursor: pointer; position: relative;
  transition: transform var(--t-app) var(--e);
  transform-origin: center bottom;
}
.site .tvcard .thumb {
  aspect-ratio: 9 / 16;                 /* le format des vidéos, pas un choix */
  border-radius: var(--r-s);
  overflow: hidden; position: relative;
  box-shadow: 0 4px 18px rgba(0,0,0,.45);
  transition: box-shadow var(--t-app) var(--e);
}
.site .tvcard.hot { transform: translateY(-8px) scale(1.05); z-index: 30; }
.site .tvcard.hot .thumb { box-shadow: 0 26px 60px -14px rgba(0,0,0,.78); }
.site .tvcard .thumb .g {
  position: absolute; inset: 0;
  transition: transform var(--t-gros) var(--e), filter var(--t-app) var(--e);
}
.site .tvcard.hot .thumb .g { transform: scale(1.08); filter: blur(9px) brightness(.55) saturate(1.2); }

/* les étiquettes : niveau en haut, durée en bas */
.site .tvcard .thumb .lk2 { position: absolute; top: 9px; left: 9px; }
.site .tvcard .thumb .dur { position: absolute; right: 9px; bottom: 11px; }
.site .tvcard .thumb .lk2, .site .tvcard .thumb .dur {
  background: rgba(6,10,16,.55); color: #EAF2FB;
  border-radius: var(--r-pill); padding:4px 12px;
  font-size:11px; font-weight: 600; letter-spacing: .03em;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  transition: opacity var(--t-app) var(--e);
}
.site .tvcard.hot .thumb .lk2, .site .tvcard.hot .thumb .dur { opacity: 0; }
.site .tvcard .thumb .prog { position: absolute; left: 0; right: 0; bottom: 0; height: 3px;
  background: rgba(255,255,255,.24); }
.site .tvcard .thumb .prog i { display: block; height: 100%; background: #F2436E; }

/* la couche d'information, verticale elle aussi */
.site .tvcard .ov { padding:12px 12px; }
.site .tvcard .ov .pl { top: 42%; }
.site .tvcard .ov b { font-size:14px; }
.site .tvcard .ov small { font-size:12px; }
.site .tvcard .cap { margin-top:12px; font-weight: 500; line-height: 1.35; }

/* ── le classement, comme sur la référence ──
   Le chiffre est posé DERRIÈRE l'affiche, en creux : plein, il pèserait
   autant qu'elle et l'on ne saurait plus lequel des deux regarder. */
.site .tvrow.top .tvcard { padding-left:32px; }
.site .tvrow.top .rang {
  position: absolute; left: -6px; z-index: 0;
  /* le chiffre s'aligne sur le BAS DE L'AFFICHE, pas sur le bas de la carte :
     la légende occupe 2,7 em sous l'affiche, et une valeur fixe faisait
     chevaucher le chiffre et le titre dès que celui-ci passait à la ligne */
  bottom: calc(2.7em + 14px);
  font-size:82px; font-weight: 800; line-height: .8; letter-spacing: -.06em;
  color: transparent;
  -webkit-text-stroke: 2px rgba(255,255,255,.30);
  transition: -webkit-text-stroke-color var(--t-app) var(--e), transform var(--t-app) var(--e);
  pointer-events: none;
}
.site .tvrow.top .tvcard.hot .rang {
  -webkit-text-stroke-color: rgba(242,67,110,.85);
  transform: translateX(-4px);
}

/* ── les flèches ── */
.site .tvnav {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 46px; height: 46px; border-radius: 50%;
  background: rgba(8,14,24,.62); border: 1px solid rgba(255,255,255,.16);
  color: #fff; font-size:19px; line-height: 1;
  display: grid; place-items: center; cursor: pointer; z-index: 20;
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  opacity: 0; pointer-events: none;
  transition: opacity var(--t-app) var(--e), transform var(--t-etat) var(--e),
              background-color var(--t-etat) var(--e);
}
.site .tvnav.l { left: 6px; }
.site .tvnav.r { right: 6px; }
.site .tvviewport:hover .tvnav.utile { opacity: 1; pointer-events: auto; }
.site .tvnav:hover { background: rgba(8,14,24,.9); transform: translateY(-50%) scale(1.08); }

/* le bord droit s'estompe tant qu'il reste des titres */
.site .tvviewport:not(.aufond) {
  -webkit-mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 64px), transparent 100%);
          mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 64px), transparent 100%);
}
/* … mais un masque coupe aussi ce qui grandit au survol. On le retire dès
   qu'une vignette est ouverte, sinon elle se fait rogner en s'agrandissant. */
.site .tvviewport:hover { -webkit-mask-image: none; mask-image: none; }


/* ══════════════════════════════════════════════════════════════════════════
   36. LA FLÈCHE DU BANDEAU, ET LE RECOUVREMENT

   Une flèche blanche pulsait sous le titre, à moitié cachée par la rangée
   d'accès rapide. Personne ne pouvait deviner ce qu'elle faisait : elle ne
   cliquait rien, elle ne désignait rien de précis, et elle était coupée. Un
   élément d'interface que l'on ne comprend pas est pire que pas d'élément
   du tout — on le retire.

   Ce qui invite à descendre, c'est la rangée d'accès rapide elle-même : elle
   chevauche volontairement le bas du bandeau, si bien qu'on voit qu'il y a
   quelque chose en dessous. Ce chevauchement était accidentel et mal empilé ;
   il devient délibéré, avec sa propre ombre et son propre plan.
   ══════════════════════════════════════════════════════════════════════════ */
.site .scrollhint { display: none; }

.site .hero2 + section.blk,
.site .hero2 ~ section.blk:first-of-type { position: relative; z-index: 5; }
.site .quickrow {
  position: relative; z-index: 5;
  margin-top: clamp(-72px, -5vw, -40px);
  gap: clamp(12px, 1.2vw, 20px);
}
.site .quickrow .qcard2 {
  border-radius: var(--r-m);
  padding: clamp(18px, 1.8vw, 26px) clamp(14px, 1.4vw, 20px);
  box-shadow: var(--sh2);
  transition: transform var(--t-app) var(--e), box-shadow var(--t-app) var(--e),
              border-color var(--t-app) var(--e);
}
.site .quickrow .qcard2:hover { transform: translateY(-5px); box-shadow: var(--sh3); }
.site .quickrow .i2 {
  width: 42px; height: 42px; border-radius: var(--r-s); font-size:19px;
  margin:0 auto 12px;
  transition: transform var(--t-app) var(--e);
}
.site .quickrow .qcard2:hover .i2 { transform: scale(1.08) rotate(-4deg); }


/* ══════════════════════════════════════════════════════════════════════════
   37. TROIS APPAREILS, TROIS MISES EN PAGE

   Un site « responsive » n'est pas un site qui rétrécit : c'est un site qui
   change de raisonnement. Trois seuils, trois intentions.

   ORDINATEUR (au-delà de 1 080 px) — la largeur est une ressource : plusieurs
   colonnes, la barre complète, le survol.
   TABLETTE (641 à 1 080 px) — deux colonnes, la barre passe au tiroir, les
   cibles grossissent parce qu'on y touche avec le doigt, mais l'écran reste
   assez large pour comparer deux choses côte à côte.
   TÉLÉPHONE (jusqu'à 640 px) — une seule colonne, tout à pleine largeur, les
   rangées défilent au doigt, et rien ne descend sous 15 px.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── TABLETTE ────────────────────────────────────────────────────────────── */
@media (min-width: 641px) and (max-width: 1080px) {
  :root { --sect: clamp(56px, 7.5vw, 92px); --gout: clamp(24px, 3.6vw, 40px); }
  .site h2.sh, .site h2.t, .site h1.sh, .site h1.t { font-size: clamp(28px, 4.4vw, 40px); }
  .site .hero2 { min-height: clamp(440px, 64vh, 620px); }
  .site .hero2 .heroctn h1 { font-size: clamp(34px, 6vw, 54px); }
  .site .methode .grid2 { grid-template-columns: 1fr; gap:32px; }
  .site .quickrow { margin-top:-32px; }
  /* deux colonnes de manuels : la couverture reste grande sans forcer le
     défilement horizontal pour trois titres */
  .site .lvcard { flex-basis: clamp(240px, 42vw, 320px); }
  .site .tvcard { flex: 0 0 clamp(140px, 20vw, 170px); }
  .site .card { padding:24px 20px; }
}

/* ── TÉLÉPHONE ───────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  :root { --sect: clamp(48px, 12vw, 72px); --gout: 20px; --gap:12px; }
  .site h2.sh, .site h2.t, .site h1.sh, .site h1.t { font-size: clamp(26px, 7.6vw, 34px); line-height: 1.1; }
  .site p.lead, .site p.lead2 { font-size:17px; }
  .site .card p, .site .mrow p, .site .qcard2 span { font-size:16px; }
  .site .mini, .site .apk { font-size:14px; }
  .site ul.ck li { font-size:16px; }
  .site .quickrow { margin-top:-24px; }
  .site .quickrow .qcard2 { padding:16px 16px; }
  .site .hero2 .heroctn .cta { flex-direction: column; align-items: stretch; }
  .site .hero2 .heroctn .cta > * { width: 100%; }
  /* les rangées d'étiquettes défilent au doigt plutôt que de se replier
     sur quatre lignes */
  .site .tvchips, .site .chapmeta {
    display: flex; flex-wrap: nowrap; overflow-x: auto;
    scrollbar-width: none; padding-bottom:4px;
    scroll-padding-inline:20px;
  }
  .site .tvchips::-webkit-scrollbar, .site .chapmeta::-webkit-scrollbar { display: none; }
  .site .tvchips > * , .site .chapmeta > * { flex: 0 0 auto; }
  .site .tvcard { flex: 0 0 39vw; }
  .site .tvrow.top .tvcard { padding-left:20px; }
  .site .tvrow.top .rang { font-size:52px; -webkit-text-stroke-width: 1.5px; }
  .site .prem { font-size:9px; padding:4px 8px; letter-spacing: .12em; }
  .site .tvcard .thumb .lk2, .site .tvcard .thumb .dur { font-size:11px; padding:2px 8px; }
  .site .tvnav { display: none; }
  .site .lvcard { flex-basis: 76vw; }
  .site .megain { display: none; }
  .site footer.site .cols { gap:24px; }
}

/* Entre 1 081 et 1 300 px — le petit ordinateur portable : les colonnes de
   quatre deviennent des colonnes de trois, sinon chaque carte tombe à 230 px
   et son texte redevient illisible. */
@media (min-width: 1081px) and (max-width: 1300px) {
  .site .grid4:not([style*="grid-template-columns"]) {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* ── Les rangées s'alignent sur le reste du site ──
   `#tvrows` est posé directement sous `.site`, sans conteneur : les affiches
   partaient donc du bord gauche de l'écran pendant que tout le reste de la
   page commençait à 1 320 px centrés. Et `scroll-snap-align: start` faisait
   défiler la rangée de la valeur du rembourrage dès l'affichage — d'où la
   première affiche coupée. `scroll-padding-inline` dit au défilement où
   commence vraiment le contenu. */
.site .tvrow > h3, .site .tvviewport {
  max-width: 1320px; margin-inline:auto;
  padding-inline: var(--gout);
}
.site .tvviewport { scroll-padding-inline: var(--gout); }
@media (min-width: 1700px) {
  .site .tvrow > h3, .site .tvviewport { max-width: 1480px; }
}
/* Une hauteur MINIMALE, pas un plafond. J'avais d'abord tronqué la légende à
   deux lignes : l'audit a relevé 19 px de texte masqué sur TFA TV, c'est-à-dire
   des titres de vidéo coupés en silence. Les affiches sont alignées par le
   haut ; une légende plus longue que les autres ne décale donc rien. */
.site .tvcard .cap { min-height: 2.7em; }
.site .tvchips {
  max-width: 1320px; margin-inline:auto; padding-inline: var(--gout);
}
@media (min-width: 1700px) { .site .tvchips { max-width: 1480px; } }

/* Six accès rapides empilés en pleine largeur, c'est trois écrans de
   défilement pour six mots. Deux colonnes : la rangée tient en un regard,
   et chaque pastille reste largement au-dessus de la cible tactile. */
@media (max-width: 760px) {
  .site .quickrow { grid-template-columns: repeat(2, minmax(0, 1fr)); gap:12px; }
  .site .quickrow .qcard2 { padding:16px 12px; }
  .site .quickrow .qcard2 b { font-size:15px; }
  .site .quickrow .qcard2 span { font-size:13px; }
  .site .quickrow .i2 { width: 36px; height: 36px; font-size:17px; margin-bottom:8px; }
}


/* ══════════════════════════════════════════════════════════════════════════
   38. LE REMBOURRAGE DES PANNEAUX — le relevé complet

   Passage automatique sur les feuilles d'origine : 82 panneaux déclarant un
   rayon d'au moins 9 px avec moins de 22 px de rembourrage. Autrement dit
   82 surfaces dessinées comme des cartes et remplies comme des étiquettes.
   Le bandeau du Club en faisait partie — 26 px pour un bloc de 1 480 px de
   large, c'est ce qui donnait l'impression d'étouffement pointée sur la
   capture.

   Distinction tenue ici : une PASTILLE (badge, étiquette, puce) garde son
   rembourrage serré, c'est sa nature ; un PANNEAU (une surface qui contient
   plusieurs choses) passe à un rembourrage proportionnel à sa taille.
   ══════════════════════════════════════════════════════════════════════════ */
.site .clubband, .site .clubwrap {
  border-radius: var(--r-l);
  padding: clamp(28px, 2.8vw, 46px) clamp(26px, 3vw, 48px);
  gap: clamp(28px, 3vw, 54px);
  margin-bottom:0;
}
.site .clubband h3, .site .clubband h1 { font-size: clamp(22px, 2.1vw, 30px); font-weight: 700; margin:0 0 12px; }
.site .clubband p { font-size:16px; line-height: 1.66; max-width: 58ch; }
.site .clubband .cta { margin-top: clamp(20px, 2vw, 30px) !important; gap:12px; }
.site .clubkpi { gap: clamp(12px, 1.2vw, 18px); }
.site .clubkpi > div {
  border-radius: var(--r-m);
  padding: clamp(18px, 1.8vw, 26px) clamp(12px, 1.2vw, 18px);
}

/* les autres panneaux relevés par le passage automatique */
.site .next, .site .archbox, .site .tcard, .site .ladder, .site .nat,
.site .exdemo, .site .fmt, .site .chit, .site .opt, .site .age,
.site .legend, .site .qsm, .site .starnote, .site .noteedit, .site .rgpd,
.site .accessbar, .site .pcard, .site .mascots {
  border-radius: var(--r-m);
  padding: clamp(20px, 2vw, 28px) clamp(18px, 1.9vw, 26px);
}
.site .child, .site .incl { padding:12px 16px; border-radius: var(--r-s); }
.site .authtabs { padding:4px; border-radius: var(--r-pill); }
.site .atab { border-radius: var(--r-pill); padding:12px 0; font-size:15px; }
.site .social { padding:12px 0; border-radius: var(--r-s); font-size:15px; }
.site .asexe label { padding:12px 0; border-radius: var(--r-s); font-size:15px; }
.site .attente input, .site .composer .fld2 { padding:12px 16px; border-radius: var(--r-s); }
.site .acctmenu { padding:8px; border-radius: var(--r-m); }
.site #installer { padding:12px 16px; border-radius: var(--r-m); }
.site .counter { padding:8px 16px; }

/* LES DEUX BOUTONS DU BANDEAU DU CLUB SE TOUCHAIENT — écart mesuré : 0 px.
   `display: flex` n'était déclaré que sur `.hero .cta` et `.heroctn .cta` ;
   ailleurs, `.cta` restait un bloc ordinaire, `gap` n'y avait aucun effet, et
   comme le balisage ne laisse aucune espace entre les deux liens, ils se
   collaient bord à bord. Ils lisaient comme un seul objet coupé en deux.
   La règle vaut maintenant partout où le nom est employé. */
.site .cta {
  display: flex; flex-wrap: wrap; align-items: center; gap:12px;
}
.site .hbtn { padding:12px 32px; border-radius: var(--r-pill); }


/* ══════════════════════════════════════════════════════════════════════════
   39. TFA TV — LE SURVOL PLUS VIF

   Le survol attendait 240 ms puis s'ouvrait en 360 ms : près de six dixièmes
   de seconde entre le moment où l'on pose la souris et celui où l'image est
   nette. C'est la bonne durée pour un panneau qui se déplie, pas pour une
   vignette que l'on survole en série. On descend à 90 ms d'attente et 220 ms
   d'ouverture — assez pour ne pas clignoter quand on traverse la rangée,
   assez vif pour répondre à l'intention.
   ══════════════════════════════════════════════════════════════════════════ */
.site .tvcard,
.site .tvcard .thumb,
.site .tvcard .thumb .g,
.site .tvcard .ov,
.site .tvcard .ov b,
.site .tvcard .ov small,
.site .tvcard .ov .pl,
.site .tvcard .cap,
.site .tvcard .prem,
.site .tvcard .thumb .lk2,
.site .tvcard .thumb .dur,
.site .tvrow.top .rang {
  transition-duration: .22s;
}
.site .tvcard.hot .thumb .g { filter: blur(8px) brightness(.55) saturate(1.2); }

/* Un élément de flexbox refuse par défaut de descendre sous la largeur de son
   contenu (`min-width: auto`). La bulle de message, élargie par le nouveau
   rembourrage, sortait donc de 45 px du fil de discussion à 320 px — l'audit
   l'a relevé. `min-width: 0` lève ce plancher ; le texte se replie alors
   normalement, y compris un pseudonyme sans espace. */
.site .msg, .site .msg .bb, .site .chit, .site .room {
  min-width: 0;
}
.site .msg .bb, .site .msg .nm { overflow-wrap: anywhere; }

/* Le message vocal déclarait `min-width: 190px` — une largeur absolue dans une
   bulle qui, à 320 px d'écran, n'en fait que 100. Il en sortait de 45 px.
   Une largeur minimale fixe est toujours une promesse qu'on ne peut pas tenir
   sur petit écran : elle devient une largeur souhaitée, plafonnée par la
   place réellement disponible. */
.site .voice { min-width: 0; flex-wrap: wrap; row-gap:8px; }
.site .voice .wave { flex: 1 1 60px; min-width: 0; }

/* LE RELEVÉ COMPLET DES LARGEURS MINIMALES FIXES — six déclarations, toutes
   écrites pour un cadre de maquette large. Sur un écran de 320 px elles
   deviennent des promesses intenables : le champ de saisie du fil de
   discussion en réclamait 220, la barre d'accès 260. Une largeur minimale
   n'a de sens que relative à la place disponible.
   `min(valeur, 100 %)` conserve l'intention — « aussi large que possible » —
   sans jamais dépasser le cadre. */
.site .composer .fld2 { min-width: min(220px, 100%); }
.site .accessbar .txt { min-width: min(260px, 100%); }
.site .attente input  { min-width: min(180px, 100%); }
.site .fld            { min-width: min(88px, 100%); }
.site .ex input, .site .ex select { min-width: min(96px, 100%); max-width: 100%; }
.site .composer, .site .accessbar { flex-wrap: wrap; }


/* ══════════════════════════════════════════════════════════════════════════
   40. LES BULLES TARIFAIRES

   TROIS DÉFAUTS, UNE MÊME ORIGINE
   La rangée de tarifs de la page d'accueil n'utilise pas `.card` mais `.pm` —
   un composant distinct, hérité de la maquette, que la couche de design
   n'avait jamais repris. D'où : aucune élévation au survol, aucune lueur, et
   des accents de couleur laissés tels quels.

   Ces accents étaient faux, et vérifiables : « TFA Kids » portait
   `--acc: #1B4A85` (bleu) sous un bandeau cyan, et « Les manuels »
   `--acc: #092D59` — un bleu nuit presque invisible sur fond sombre — sous un
   bandeau vert. Le prix et les ✓ de cette bulle étaient donc illisibles.
   Chaque accent reprend maintenant la teinte claire de SON bandeau.

   La lisibilité en thème clair est traitée séparément : une teinte choisie
   pour ressortir sur du bleu nuit n'a pas le contraste voulu sur du blanc.
   ══════════════════════════════════════════════════════════════════════════ */
.site .pm, .site .card { --acc-l: var(--acc, var(--navy)); }
body:not(.dark) .site .pm, body:not(.dark) .site .card {
  --acc-l: color-mix(in srgb, var(--acc, var(--navy)) 78%, #000);
}

/* la couleur du prix et des coches suit la bulle */
.site .pm .p2, .site .pm .p2 span, .site .card .price { color: var(--acc-l); }
.site .pm ul li::before, .site .card ul.ck li::before { color: var(--acc-l); }
.site .pm ul li.no::before, .site .card ul.ck li.no::before {
  color: color-mix(in srgb, var(--crimson) 72%, var(--soft2));
}
body.dark .site .pm ul li.no::before, body.dark .site .card ul.ck li.no::before {
  color: #FF7E9C;
}
.site .pm h4 { color: var(--acc-l); }

/* ── l'élévation et la lueur, comme partout ailleurs sur le site ──
   Trois choses en même temps : la bulle monte, son ombre s'ouvre, et une
   lueur crimson suit le curseur à l'intérieur. Une seule de ces trois se
   remarque ; les trois ensemble se ressentent. */
.site .pm {
  position: relative; isolation: isolate;
  border-radius: var(--r-m);
  transition: transform var(--t-app) var(--e), box-shadow var(--t-app) var(--e),
              border-color var(--t-app) var(--e);
}
.site .pm::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  border-radius: inherit; pointer-events: none; opacity: 0;
  transition: opacity var(--t-app) var(--e);
  background: radial-gradient(320px circle at var(--mx, 50%) var(--my, 0%),
              color-mix(in srgb, var(--crimson) 22%, transparent), transparent 64%);
}
.site .pm:hover {
  transform: translateY(-6px);
  box-shadow: var(--sh2);
  border-color: color-mix(in srgb, var(--crimson) 40%, var(--brd));
}
.site .pm:hover::before { opacity: 1; }
/* le bandeau de couleur s'anime avec elle */
.site .pm .cap2 { transition: transform var(--t-app) var(--e), filter var(--t-app) var(--e); }
.site .pm:hover .cap2 { filter: brightness(1.25) saturate(1.15); }

/* la lueur des cartes classiques était trop discrète pour se voir */
.site .card::before {
  background: radial-gradient(340px circle at var(--mx, 50%) var(--my, 0%),
              color-mix(in srgb, var(--crimson) 22%, transparent), transparent 64%);
}
.site .card:hover { transform: translateY(-6px); }


/* ══════════════════════════════════════════════════════════════════════════
   41. LA PASTILLE PASSE AU ROUGE QUAND ELLE CHANGE DE CÔTÉ

   La pastille glisse déjà au survol, en annonce du clic. Elle change aussi de
   couleur : bleu nuit tant qu'elle désigne l'option EN COURS, crimson dès
   qu'elle annonce un CHANGEMENT. Le sélecteur porte alors les deux couleurs
   de la marque, et l'on distingue d'un regard « voici où vous êtes » de
   « voici où vous allez ».

   Pour les familles de la collection — quatre onglets — la pastille alterne
   franchement : bleu, rouge, bleu, rouge. La couleur devient un repère de
   position autant qu'un état.
   ══════════════════════════════════════════════════════════════════════════ */
.site .audpuce, .site .ftpuce {
  background: var(--teinte, var(--navy));
  box-shadow: 0 4px 14px -4px color-mix(in srgb, var(--teinte, var(--navy)) 60%, transparent);
  transition: transform var(--t-app) var(--e), width var(--t-app) var(--e),
              background-color var(--t-app) var(--e), box-shadow var(--t-app) var(--e);
}
body.dark .site .audpuce, body.dark .site .ftpuce {
  background: var(--teinte, #23477B);
}


/* ══════════════════════════════════════════════════════════════════════════
   42. LES CATÉGORIES DE TFA TV

   Elles reçoivent la mécanique des onglets de la collection : une pastille
   qui glisse sous l'élément visé, bleu nuit et crimson en alternance.

   UNE DIFFÉRENCE DE TRAITEMENT, ET ELLE EST VOULUE : pas de capsule autour de
   la rangée. Neuf étiquettes qui se replient sur deux lignes dans un cadre
   arrondi donnent une forme bâtarde, ni ligne ni bloc. Ici la pastille se
   déplace seule sur un fond transparent — et les neuf contours individuels
   disparaissent, ce qui rend la rangée nettement plus calme.
   ══════════════════════════════════════════════════════════════════════════ */
.site .tvchips {
  position: relative; isolation: isolate;
  gap:4px 8px; padding-bottom:12px;
}
.site .tvchip, body.dark .site .tvchip {
  position: relative; z-index: 1;
  border-color: transparent;
  background: transparent;
  color: #A8C0DC;
  font-weight: 500;
  transition: color var(--t-app) var(--e), transform var(--t-etat) var(--e);
}
.site .tvchip:hover, body.dark .site .tvchip:hover { color: #fff; border-color: transparent; }
.site .tvchip.on, body.dark .site .tvchip.on {
  background: transparent; border-color: transparent; color: #fff; font-weight: 600;
}
/* quand la pastille est ailleurs, l'onglet actif reprend sa couleur de repos :
   deux étiquettes blanches en même temps ne disent plus laquelle est choisie */
.site .tvchips:hover .tvchip.on { color: #A8C0DC; }
.site .tvchips .tvchip:hover { color: #fff; }


/* ══════════════════════════════════════════════════════════════════════════
   43. L'OUVERTURE DU BANDEAU D'ACCUEIL

   ══ UN DÉFAUT SILENCIEUX, TROUVÉ EN PRÉPARANT CETTE ANIMATION ══
   `.heroimg` portait encore l'animation `kenburns` héritée de la maquette —
   26 secondes, `transform: scale(1)` → `scale(1.07)`, en boucle. Or une
   animation CSS écrase la propriété qu'elle anime, quelle que soit la
   spécificité du sélecteur qui la déclare par ailleurs.

   Conséquence : la parallaxe du bandeau n'a JAMAIS fonctionné. Mesuré à
   l'instant — `--py` passe bien de 4,73 px à 47,40 px au défilement, et la
   matrice réellement appliquée reste `matrix(1.0011, 0, 0, 1.0011, 0, 0)`.
   Aucune translation. Idem pour le suivi de la souris.

   Je ne l'avais pas vu parce que je vérifiais que les VARIABLES étaient
   écrites, pas que le mouvement était appliqué. On mesure l'effet, jamais
   l'entrée.

   ══ CE QUE FAIT L'OUVERTURE ══
   L'image entre à 1,34 et se pose à 1,07 en 2,6 s — un mouvement long, qui
   ralentit à l'arrivée au lieu de s'arrêter net. Le bandeau sort d'un noir
   plein qui s'efface en 1,9 s. Puis le sur-titre, le titre, le texte et les
   boutons se lèvent l'un après l'autre, 130 ms d'écart.

   `@property` permet d'animer `--zoom` comme un nombre. Là où il n'est pas
   compris — moins de 6 % des navigateurs — la variable ne s'anime pas : le
   bandeau s'affiche directement à sa taille finale, ce qui est exactement le
   repli souhaité.
   ══════════════════════════════════════════════════════════════════════════ */
@property --zoom {
  syntax: '<number>';
  inherits: false;
  initial-value: 1.07;
}

.site .hero2 .heroimg {
  /* une seule déclaration porte les trois mouvements : le suivi de la souris,
     la parallaxe de défilement, et l'échelle d'ouverture */
  animation: none;                      /* on coupe le `kenburns` de la maquette */
  transform: translate3d(var(--mx2, 0px), calc(var(--my2, 0px) + var(--py, 0px)), 0)
             scale(var(--zoom));
}
/* Les animations d'ouverture sont GARDÉES PAR UNE CLASSE, et pas posées en
   dur. C'est la condition pour pouvoir les relancer : retirer la classe
   supprime l'animation, la remettre la redémarre de zéro. Changer un simple
   `animation-delay` ne relance rien — l'animation est déjà terminée, elle
   reste terminée. */
body.ouvre .site .hero2 .heroimg {
  animation: tfa-ouverture 2.6s var(--e-soft) 3.7s both;
}
@keyframes tfa-ouverture {
  from { --zoom: 1.34; }
  to   { --zoom: 1.07; }
}

/* PAS DE DÉRIVE PERPÉTUELLE. J'avais d'abord reporté le `kenburns` sur
   l'image elle-même, pour ne rien perdre. Mesuré : une animation infinie sur
   un PNG de 500 Ko force le compositeur à retravailler cette couche à chaque
   image, même quand le bandeau est sorti de l'écran — 20 % d'images longues
   en plus sur un défilement complet.
   Et elle n'a plus de raison d'être : ce `kenburns` existait justement parce
   que RIEN d'autre ne bougeait dans le bandeau. Maintenant que la parallaxe
   fonctionne, c'est elle qui donne le mouvement, et elle s'arrête d'elle-même
   dès que le bandeau quitte l'écran. */

/* le noir dont le bandeau émerge.
   IL EST TRANSPARENT AU REPOS. L'animation, gardée par `body.ouvre`, le pose
   à l'opaque puis l'efface. Écrit dans l'autre sens — opaque au repos — le
   bandeau resterait NOIR chez qui n'a pas de JavaScript, chez qui a demandé
   moins d'animation, et sur toute page où la classe n'est pas posée. La règle
   de repos doit toujours être l'état SÛR. */
.site .hero2::after {
  content: ""; grid-area: 1 / 1; z-index: 2;
  background: #05090F; opacity: 0; pointer-events: none;
}
body.ouvre .site .hero2::after {
  animation: tfa-devoile 1.9s var(--e) 3.7s both;
}
@keyframes tfa-devoile {
  0%   { opacity: 1; }
  100% { opacity: 0; }
}

/* le texte se lève, un élément après l'autre */
body.ouvre .site .hero2 .heroctn > * {
  animation: tfa-leve .95s var(--e) both;
}
@keyframes tfa-leve {
  from { opacity: 0; transform: translate3d(0, 30px, 0); }
  to   { opacity: 1; transform: none; }
}
body.ouvre .site .hero2 .heroctn > *:nth-child(1) { animation-delay: 4.30s; }
body.ouvre .site .hero2 .heroctn > *:nth-child(2) { animation-delay: 4.43s; }
body.ouvre .site .hero2 .heroctn > *:nth-child(3) { animation-delay: 4.56s; }
body.ouvre .site .hero2 .heroctn > *:nth-child(4) { animation-delay: 4.69s; }
body.ouvre .site .hero2 .heroctn > *:nth-child(5) { animation-delay: 4.82s; }

/* les deux lueurs arrivent en dernier, quand le cadre est posé */
body.ouvre .site .hero2 .lueur {
  animation: tfa-lueur 1.6s var(--e) 4.8s both;
}
@keyframes tfa-lueur { from { opacity: 0; } to { opacity: .8; } }

@media (prefers-reduced-motion: reduce) {
  body.ouvre .site .hero2 .heroimg,
  body.ouvre .site .hero2::after,
  body.ouvre .site .hero2 .heroctn > *,
  body.ouvre .site .hero2 .lueur { animation: none; }
  .site .hero2::after { display: none; }
}


/* ══════════════════════════════════════════════════════════════════════════
   44. L'OUVERTURE DU LOGO — arrivée, séparation, rideau

   Trois temps, enchaînés sans coupure :

   1. L'ARRIVÉE (0 → 1,15 s) — le logo entre de dos, en pivotant sur trois
      axes, et vient se poser de face. Deux copies fantômes le suivent avec
      70 et 140 ms de retard : ce sont elles qui donnent la traînée de la
      référence Apple. Une seule copie ne se verrait pas, quatre feraient une
      bouillie.

   2. LA SIGNATURE ET LA PAUSE (0,95 → 3,15 s) — le nom se pose sous les
      bulles, ligne après ligne, et TOUT S'ARRÊTE DEUX SECONDES.

      Cette pause est le seul but de la séquence. Une marque qu'on ne lit pas
      n'est pas une marque : le mouvement attire l'œil, l'immobilité lui donne
      le temps de lire. Deux secondes, c'est la durée mesurée d'une lecture
      confortable de trois lignes courtes — en dessous on devine, au-dessus on
      s'impatiente. Le reste de la chronologie a été décalé d'autant plutôt
      que raccourci : on n'achète pas du temps de lecture en accélérant le
      geste qui l'entoure.

   3. LA SÉPARATION (3,15 → 4,20 s) — les deux bulles, jointes comme dans le
      logo, s'écartent chacune vers son côté en pivotant légèrement. Chacune
      part vers le panneau de SA couleur et s'y fond : le rideau n'apparaît
      pas de nulle part, ce sont les bulles qui deviennent le rideau. Le nom
      s'efface vers le haut au même instant, il ne reste pas orphelin.

   4. LE RIDEAU (3,80 → 4,80 s) — les deux panneaux s'ouvrent. La courbe
      démarre lentement puis file : un rideau a du poids, il ne part pas
      instantanément. Le bandeau d'accueil est déjà en train de jouer son
      ouverture derrière — on le découvre en mouvement, pas à l'arrêt.

   ══ POURQUOI ELLE REJOUE ══
   Elle jouait avant UNE FOIS PAR SESSION, retenue dans `sessionStorage` :
   trois secondes de péage à chaque page semblaient trop cher. Le compromis
   est levé à la demande — elle rejoue à chaque chargement, et à la demande en
   survolant le logo de la barre plus d'une seconde.

   C'est la seconde de survol qui rend la chose tenable : personne ne pose sa
   souris une seconde pleine sur un logo par accident. Un déclenchement au
   simple survol relancerait le rideau chaque fois qu'on va vers le menu.
   ══════════════════════════════════════════════════════════════════════════ */

/* ══════════════════════════════════════════════════════════════════════════
   LE GÉNÉRIQUE EST UN CALQUE DE LA PAGE, PAS UN MEUBLE DU HERO.

   Il a d'abord vécu DANS `.hero2`, en absolu : le rideau ne couvrait que la
   bande du hero, la barre du haut restait allumée au-dessus et les
   raccourcis en dessous. Première correction : `fixed` + z-index 300 — sans
   effet, car `.hero2` (position relative, z-index 1) crée un contexte
   d'empilement : 300 n'y signifie plus « au-dessus de tout ». Deuxième
   correction : soulever le hero à 300 pendant l'ouverture — pire, car la
   classe `ouvre` n'est pas retirée à la fin, le hero restait à 300 pour
   toujours et passait PAR-DESSUS la barre collante au défilement.

   La leçon des trois essais : un voile plein écran n'appartient à aucune
   section. Il est posé par anim.js directement sous `.site` — qui ne crée
   aucun contexte — et son propre z-index (300 > 200, la barre) suffit.
   Aucune autre règle, aucun étage à soulever, rien à remettre en place.
   `pointer-events: none` reste indispensable : le voile couvre tout,
   y compris les boutons — sans lui, rien n'est cliquable pendant 5 s.
   ══════════════════════════════════════════════════════════════════════════ */
/* `.site.site` ET NON `.site` : la maquette pose `body.dark .site > *
   { position: relative; z-index: 1 }` — plus spécifique que `.site .intro`,
   elle écrasait le `fixed` du voile EN THÈME SOMBRE SEULEMENT. D'où un
   défaut invisible dans les tests (thème par défaut au premier chargement
   local) et bien réel chez le visiteur. Le doublement pèse trois classes :
   il gagne dans les deux thèmes, sans !important. */
.site.site > .intro {
  position: fixed; inset: 0; z-index: 300;
  overflow: hidden;
  perspective: 1100px;
  pointer-events: none;
}
.site .intro .rideau {
  position: absolute; top: -2px; bottom: -2px; width: 50.4%;
  animation: none;
}
/* LES PANNEAUX COMMENCENT PRESQUE NOIRS.
   Première version : ils portaient d'emblée le bleu nuit et le crimson de la
   marque. Résultat vérifié à l'écran — la bulle bleue sur un panneau bleu et
   la bulle rouge sur un panneau rouge : on ne voyait plus que les contours.
   Ils partent donc d'un noir bleuté et prennent leur couleur PENDANT la
   séparation. La bulle verse littéralement sa teinte dans son panneau, et
   c'est ce qui fait comprendre que le rideau, c'est elle. */
.site .intro .rideau.g {
  left: 0;
  background: #070B12;
  animation: tfa-teinte-g .55s var(--e) 3.52s both,
             tfa-rideau-g 1s cubic-bezier(.62, 0, .2, 1) 3.8s both;
}
.site .intro .rideau.d {
  right: 0;
  background: #070B12;
  animation: tfa-teinte-d .55s var(--e) 3.52s both,
             tfa-rideau-d 1s cubic-bezier(.62, 0, .2, 1) 3.8s both;
}
@keyframes tfa-teinte-g { to { background: #0C2B52; } }
@keyframes tfa-teinte-d { to { background: #B4082F; } }
@keyframes tfa-rideau-g { from { transform: none; } to { transform: translate3d(-101%, 0, 0); } }
@keyframes tfa-rideau-d { from { transform: none; } to { transform: translate3d(101%, 0, 0); } }

/* le logo, au centre */
/* LE BLOC EST REMONTÉ, PAS CENTRÉ. Le nom pend sous les bulles : centrer les
   bulles laisse la signature basse et la composition penche. On remonte donc
   l'ensemble de la moitié de la hauteur du nom, pour que ce soit le GROUPE qui
   soit centré — c'est ce que voit l'œil, pas la boîte. */
.site .intro .ilogo {
  /* LA HAUTEUR COMPTE AUTANT QUE LA LARGEUR.
     `clamp(230px, 27vw, 430px)` ne connaît que la largeur de l'écran. Sur un
     téléphone posé en paysage, ou sur un navigateur dont les barres mangent
     la moitié de la fenêtre, le bandeau devient bas et le groupe logo +
     signature — qui mesure 1,02 fois cette valeur en hauteur — se fait
     couper par le `overflow: hidden` du rideau. Et pendant la culbute, où le
     logo pivote sur trois axes, il balaie encore plus large que sa boîte.
     On borne donc aussi par la hauteur disponible. */
  --lw: clamp(180px, min(27vw, 40vh), 430px);
  position: absolute; left: 50%; top: 50%;
  width: var(--lw); aspect-ratio: 420 / 312;
  /* la signature mesure .282 × --lw de haut, creux compris : on remonte de la
     moitié, pour que le GROUPE soit centré et non la seule boîte des bulles */
  transform: translate(-50%, calc(-50% - var(--lw) * .141));
  transform-style: preserve-3d;
}
.site .intro .ib {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: contain;
}
/* l'arrivée : le conteneur pivote, les bulles restent jointes */
.site .intro .tour {
  position: absolute; inset: 0;
  animation: tfa-arrive 1.15s cubic-bezier(.2, .7, .2, 1) both;
  transform-origin: 50% 50%;
}
@keyframes tfa-arrive {
  from { opacity: 0; transform: rotate3d(.25, 1, .12, -168deg) scale(.28) translateZ(-260px); }
  55%  { opacity: 1; }
  to   { opacity: 1; transform: rotate3d(.25, 1, .12, 0deg) scale(1) translateZ(0); }
}
/* ── LES TRAÎNÉES DOIVENT AVOIR DISPARU QUAND LE LOGO SE POSE ──────────────
   Elles s'effaçaient de 0,72 à 1,28 s, alors que l'arrivée se termine à
   1,15 s. Pendant les quatre dernières dixièmes, les trois copies étaient
   donc EXACTEMENT superposées — et deux d'entre elles sont floutées. Ce que
   l'on voyait n'était pas une traînée de mouvement mais un logo dédoublé,
   et le premier mot de la personne qui le regarde est « c'est flou ».

   Une traînée n'a de sens que TANT QUE ÇA BOUGE. Elles s'effacent maintenant
   entre 0,38 et 0,52 s, en pleine course, quand l'écart entre les copies est
   encore lisible comme de la vitesse. Le logo se pose net.

   Le flou lui-même est divisé par deux : à cette vitesse il n'a pas besoin
   d'être appuyé pour se lire, et un flou léger sur une copie qui s'efface
   vite coûte beaucoup moins cher à composer. */
.site .intro .tour.fantome { pointer-events: none; }
.site .intro .tour.f1 { opacity: .30; filter: blur(.5px); }
.site .intro .tour.f2 { opacity: .15; filter: blur(1.2px); }
.site .intro .tour.fantome { animation-name: tfa-arrive, tfa-efface; animation-duration: 1.15s, .34s; }
.site .intro .tour.f1 { animation-delay: .07s, .38s; }
.site .intro .tour.f2 { animation-delay: .14s, .32s; }
@keyframes tfa-efface { to { opacity: 0; } }

/* la séparation : chaque bulle rejoint son panneau */
.site .intro .tour.vraie .bleue  { animation: tfa-part-g 1.05s cubic-bezier(.5, 0, .25, 1) 3.15s both; }
.site .intro .tour.vraie .rouge  { animation: tfa-part-d 1.05s cubic-bezier(.5, 0, .25, 1) 3.15s both; }
@keyframes tfa-part-g {
  0%   { transform: none; opacity: 1; }
  100% { transform: translate3d(-124%, 0, 0) rotate(-13deg) scale(1.1); opacity: 0; }
}
@keyframes tfa-part-d {
  0%   { transform: none; opacity: 1; }
  100% { transform: translate3d(124%, 0, 0) rotate(13deg) scale(1.1); opacity: 0; }
}

/* ── LA SIGNATURE ──────────────────────────────────────────────────────────
   « TRULY FLUENT / ACADEMY / Fluency starts here », DÉCOUPÉE DANS LE LOGO
   OFFICIEL et non recomposée en CSS.

   Elle l'a d'abord été, en texte : trois `letter-spacing` réglés à l'œil pour
   approcher le dessin. C'était honnête et ce n'était pas le logo — ni la
   bonne fonte, ni le bon interlettrage, et une compensation de `text-indent`
   à maintenir pour que le centrage ne parte pas de travers. Le fichier de la
   charte existe : on y découpe le texte, et la question ne se pose plus.

   ══ LES PROPORTIONS VIENNENT DU LOGO, PAS D'UN CHOIX ══
   Mesuré sur le fichier officiel : les bulles font 1403 px de large, « TRULY
   FLUENT » 1410, « ACADEMY » 1401, l'accroche 1192. Les deux premières lignes
   sont calées sur la MÊME largeur que le dessin, la troisième sur 85 %. Ce
   sont ces rapports qui sont écrits ici, en fraction de `--lw`.

   C'est aussi ce qui règle la question du responsive. La version en texte
   avait un défaut mesuré : le logo touche son plancher de 230 px dès 851 px
   de large et n'y bouge plus, tandis que le texte, lui, continuait de
   rétrécir avec la fenêtre — à 768 px on obtenait de grosses bulles
   surmontant une signature de 19 px. Une largeur exprimée en fraction du
   logo ne peut pas avoir ce défaut : il n'y a plus qu'une seule mesure.
   ────────────────────────────────────────────────────────────────────────── */
.site .intro .imot {
  position: absolute; left: 50%; top: 100%;
  margin-top: calc(var(--lw) * .0385);      /* le creux du logo : 54 / 1403 */
  transform: translateX(-50%);
  width: var(--lw);
  display: flex; flex-direction: column; align-items: center;
  filter: drop-shadow(0 2px 20px rgba(0, 0, 0, .55));
}
.site .intro .imot img { display: block; height: auto; }
.site .intro .imot .m1 { width: calc(var(--lw) * 1.005); }
.site .intro .imot .m2 { width: calc(var(--lw) * .999); margin-top: calc(var(--lw) * .0335); }
.site .intro .imot .m3 { width: calc(var(--lw) * .850); margin-top: calc(var(--lw) * .052); }

/* Entrée puis sortie, DEUX animations et non une seule longue.
   La sortie est en `forwards` et pas en `both` : `both` remplirait aussi vers
   l'ARRIÈRE, c'est-à-dire que sa première image écraserait l'entrée pendant
   toute la durée de l'attente — la ligne resterait invisible. `forwards` ne
   retient que la fin. C'est la seule combinaison qui laisse les deux
   animations cohabiter sur les mêmes propriétés. */
.site .intro .imot > * {
  animation: tfa-mot .8s var(--e) both,
             tfa-mot-sort .52s var(--e) forwards;
}
.site .intro .imot > *:nth-child(1) { animation-delay: .95s, 3.15s; }
.site .intro .imot > *:nth-child(2) { animation-delay: 1.07s, 3.19s; }
.site .intro .imot > *:nth-child(3) { animation-delay: 1.20s, 3.23s; }
@keyframes tfa-mot {
  from { opacity: 0; transform: translate3d(0, 15px, 0); filter: blur(7px); }
  to   { opacity: 1; transform: none; filter: blur(0); }
}
@keyframes tfa-mot-sort {
  to { opacity: 0; transform: translate3d(0, -16px, 0); filter: blur(5px); }
}

/* une lueur qui naît au moment de la séparation, sur la ligne de partage */
.site .intro .fente {
  position: absolute; left: 50%; top: 0; bottom: 0; width: 2px; margin-left: -1px;
  background: linear-gradient(180deg, transparent, rgba(255,255,255,.85), transparent);
  opacity: 0;
  animation: tfa-fente 1.15s var(--e) 3.65s both;
}
@keyframes tfa-fente {
  0%   { opacity: 0; transform: scaleY(.2); }
  28%  { opacity: 1; transform: scaleY(1); }
  100% { opacity: 0; transform: scaleY(1) scaleX(3); }
}

@media (prefers-reduced-motion: reduce) {
  .site .intro { display: none; }
}


/* ══════════════════════════════════════════════════════════════════════════
   45. LE TÉLÉPHONE PRIS AU SÉRIEUX

   La section 37 posait déjà trois paliers, et annonçait « rien ne descend
   sous 15 px ». Mesuré sur un vrai téléphone de 390 px : 83 éléments de
   texte sous 13 px sur la seule page d'accueil, 77 sur la page du Club.
   L'intention était juste, la règle ne l'était pas — elle nommait une
   poignée de sélecteurs (`p.lead`, `.card p`, `.mini`, `ul.ck li`) et
   laissait tout le reste au réglage de l'ordinateur.

   ══ POURQUOI CE N'EST PAS UNE QUESTION DE GOÛT ══
   Sur un écran d'ordinateur, l'œil est à 60 cm et la fenêtre fait 1 400 px de
   large : 11,5 px y sont un gris typographique discret, exactement ce qu'on
   veut pour une mention secondaire. Sur un téléphone tenu à 30 cm, le même
   11,5 px occupe le même angle visuel qu'un 6 px sur l'écran — c'est-à-dire
   qu'il n'est plus discret, il est illisible. La taille de police n'est pas
   une valeur esthétique portable d'un appareil à l'autre.

   La règle n'est donc plus une liste de noms mais une liste de RÔLES : les
   listes d'avantages, les mentions de pied de page, les étiquettes, les
   horodatages, les compteurs. Un rôle survit à la prochaine page ; un nom de
   classe, non.

   ══ ET LES CIBLES TACTILES ══
   Mesuré au même endroit : 24 liens et boutons de moins de 40 px de haut,
   dont onze liens de pied de page à 30 px et sept icônes sociales à 37 px.
   Le seuil confortable du doigt est de 44 px — ce n'est pas une convention
   d'Apple, c'est la largeur moyenne d'une pulpe de pouce. En dessous, on ne
   rate pas la cible une fois sur dix : on la rate, on revient, et on finit
   par ne plus essayer.
   ══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 640px) {

  /* ── 1. LE PLANCHER DE LISIBILITÉ ────────────────────────────────────── */

  /* les listes d'avantages : le contenu le plus lu de toute la page tarifs */
  .site ul.ck li,
  .site .pm ul li,
  .site .card ul li,
  .site .rlist li { font-size:15px; line-height: 1.5; }

  /* le pied de page : onze liens à 12,5 px, c'est le plan du site rendu
     inutilisable au moment précis où l'on en a besoin */
  .site footer.site .cols a:not(.res),
  .site footer.site .cols p { font-size:15px; }
  .site footer.site .cols h5 { font-size:13px; letter-spacing: .1em; }
  .site footer.site .bot a,
  .site footer.site .bot span,
  .site footer.site .bot em { font-size:14px; }
  .site footer.site .cols .lg b { font-size:13px; }

  /* les sur-titres : ils sont en capitales espacées, ils peuvent rester
     petits — mais pas à 11 px */
  .site .eyebrow, .site .kick2 { font-size:13px; }

  /* étiquettes, pastilles, compteurs */
  .site .badge, .site .billbadge, .site .lb, .site .bientot,
  .site .tags2 span, .site .chit span, .site .clubkpi span,
  .site .member .row span, .site .ladder .res b, .site .ladder .st3 span,
  .site table.inv th { font-size:13px; }

  /* la salle de discussion du Club : c'est là que le texte était le plus
     petit de tout le site — jusqu'à 9 px, soit une ligne qu'on ne lit pas,
     qu'on devine */
  .site .roomgrp { font-size:13px; }
  .site .room .rt b { font-size:14px; }
  .site .room .rt span, .site .mini2 { font-size:13px; }
  .site .msg .nm { font-size:13px; }
  .site .msg .tm, .site .msg .mtag { font-size:12px; }
  .site .msg .bb { font-size:15px; }

  /* la barre du haut : « Se connecter » et « S'inscrire » sont les deux
     seuls mots de la barre sur téléphone, ils ne peuvent pas être les plus
     petits de l'écran */
  .site .topnav .authbtns a { font-size:13px; }

  /* ── 2. LES CIBLES DU DOIGT ──────────────────────────────────────────── */

  /* On agrandit par le REMBOURRAGE et non par la hauteur : une hauteur
     imposée sur un lien en ligne ne fait rien du tout — la boîte d'un élément
     `inline` ignore `height`. Le rembourrage vertical, lui, agrandit bien la
     zone cliquable. C'est la même raison qui fait qu'un `min-height` sur un
     `<a>` de pied de page n'aurait rien changé aux 30 px mesurés. */
  .site footer.site .cols a:not(.res) {
    display: block; padding-block:8px; margin-block:-2px;
  }
  .site footer.site .bot a { display: inline-block; padding-block:8px; }
  /* `.res` DÉSIGNE DEUX CHOSES DIFFÉRENTES. Écrite sans portée, la règle
     `width: 44px; height: 44px` a touché les deux : les liens sociaux du pied
     de page, qui font toute la largeur, se sont écrasés en carrés de 44 px —
     icône par-dessus le texte — et la ligne de résultat du test de niveau,
     qui porte la même classe pour une raison sans rapport, s'est repliée en
     une colonne de 44 px qui débordait sur la section suivante.
     Une cible tactile s'agrandit par sa HAUTEUR MINIMALE, jamais par une
     largeur imposée : la largeur appartient à la mise en page. */
  .site .ftab, .site .tvchip, .site .chip { min-height: 44px; }
  .site .btn, .site .btn.gh, .site .btn.sm, .site .btn.nv, .site .hbtn {
    min-height: 46px;
  }
  .site .topnav .tiroirbtn, .site .topnav .lg { min-height: 44px; min-width: 44px; }
  .site .topnav .authbtns a { display: inline-flex; align-items: center; min-height: 44px; }

  /* ── 3. LES BULLES TARIFAIRES : LE VIDE REMONTE ──────────────────────── */

  /* Les six formules défilent au doigt, côte à côte, et le défilement les
     met toutes à la hauteur de la plus grande. La formule « Découverte », qui
     a trois avantages là où « Premium » en a huit, se retrouvait donc avec
     81 px de vide MESURÉS sous son bouton — un trou au bas de la carte, qui
     la fait paraître inachevée.
     On ne peut pas supprimer ce vide : l'égalité des hauteurs est ce qui rend
     la comparaison lisible. On le DÉPLACE. Le bouton est poussé contre le bas
     de la carte ; le vide passe au-dessus de lui, où il devient une respiration
     entre la liste et l'action, et les six boutons s'alignent sur une même
     ligne d'un bout à l'autre du défilement. */
  .site .grid4 > .card { display: flex; flex-direction: column; }
  .site .grid4 > .card > .btn { margin-top:auto; }
  .site .grid4 > .card > .sep { margin-top:auto; }
  .site .grid4 > .card > .sep ~ .btn { margin-top:0; }

  /* ── 4. LA RESPIRATION VERTICALE ─────────────────────────────────────── */

  /* Le passage d'une section à l'autre coûtait jusqu'à 110 px de noir plein
     sur un écran qui en fait 844. On resserre — mais sur la SECTION, pas sur
     les cartes : c'est l'espace entre les blocs qui était trop grand, pas
     celui à l'intérieur. Le confort de lecture vient du second. */
  :root { --sect: clamp(40px, 9.5vw, 58px); }
  .site .quickrow { margin-top:-20px; }
}

/* ── TABLETTE : le même plancher, un cran au-dessus ───────────────────────
   Entre 641 et 1 080 px on tient l'appareil à la même distance qu'un
   téléphone — c'est un écran tactile, pas un petit ordinateur. Le plancher
   s'applique donc aussi, simplement moins haut : la place ne manque pas. */
@media (min-width: 641px) and (max-width: 1080px) {
  .site ul.ck li, .site .pm ul li, .site .card ul li { font-size:15px; }
  .site footer.site .cols a:not(.res) { font-size:15px; display: block; padding-block:8px; }
  .site footer.site .cols h5 { font-size:13px; }
  .site .eyebrow, .site .kick2 { font-size:12px; }
  .site .roomgrp, .site .room .rt span, .site .mini2 { font-size:13px; }
  .site .msg .nm { font-size:13px; }
  .site .msg .tm, .site .msg .mtag { font-size:12px; }
  /* `.res` DÉSIGNE DEUX CHOSES DIFFÉRENTES. Écrite sans portée, la règle
     `width: 44px; height: 44px` a touché les deux : les liens sociaux du pied
     de page, qui font toute la largeur, se sont écrasés en carrés de 44 px —
     icône par-dessus le texte — et la ligne de résultat du test de niveau,
     qui porte la même classe pour une raison sans rapport, s'est repliée en
     une colonne de 44 px qui débordait sur la section suivante.
     Une cible tactile s'agrandit par sa HAUTEUR MINIMALE, jamais par une
     largeur imposée : la largeur appartient à la mise en page. */
}


/* ══════════════════════════════════════════════════════════════════════════
   46. LE PLANCHER, DEUXIÈME PASSE — ET POURQUOI `.site.site`

   La passe précédente a fait tomber le compte de 83 à 36 sur l'accueil, mais
   une partie des déclarations n'a rien changé : `.site .bientot` restait à
   10 px, `.site .kick2` à 10,5 px. Ce ne sont pas des règles oubliées, ce
   sont des règles ÉCRASÉES — la règle d'origine était plus spécifique que la
   correction, et une requête de média n'ajoute aucune spécificité.

   C'est le même piège que la grille à trois colonnes qui refusait de se
   replier, et que la pastille du sélecteur mensuel/annuel. Trois fois le
   même. La parade adoptée ici : répéter la classe racine. `.site.site` vaut
   deux classes au lieu d'une, ce qui suffit à passer devant sans recourir à
   `!important` — lequel n'aurait fait que déplacer le problème d'un cran
   plus loin, en rendant la règle suivante impossible à écrire.

   Répéter une classe est laid. C'est aussi la seule façon honnête de dire
   « ceci l'emporte » sans fermer la porte à la correction d'après.
   ══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 640px) {
  .site.site .bientot, .site.site .kick2, .site.site .eyebrow,
  .site.site .lb, .site.site .sub, .site.site .badge,
  .site.site .tcard .foot span, .site.site .kpicard .sub,
  .site.site .nslot, .site.site .rn2, .site.site .rv, .site.site .acc,
  .site.site .clubkpi span, .site.site .chit span, .site.site .roomgrp,
  .site.site .room .rt span, .site.site .mini2,
  .site.site .cal .dn, .site.site .cal .slot, .site.site .cal .slot span,
  .site.site .st, .site.site table.tb th, .site.site table.inv th,
  .site.site .ladder .st3 span, .site.site .ladder .res b,
  .site.site .tvhero .meta span, .site.site .tvhero .tag,
  .site.site .tvfoot span { font-size:13px; }

  .site.site .msg .tm, .site.site .msg .mtag { font-size:12px; }
  .site.site .msg .nm { font-size:14px; }

  /* LES AFFICHES DE TFA TV GROSSISSENT PLUTÔT QUE LEURS ÉTIQUETTES.
     La durée et la mention « Premium » sont posées SUR l'affiche : les
     grossir seules les ferait manger la vignette. On élargit donc l'affiche
     — de 39 à 45 % de la largeur d'écran, soit deux et quart visibles au lieu
     de deux et demie — et les étiquettes suivent en proportion. On perd un
     quart d'affiche de vue d'ensemble, on gagne une image lisible. */
  .site.site .tvcard { flex: 0 0 45vw; }
  .site.site .prem { font-size:10px; padding:4px 8px; letter-spacing: .1em; }
  .site.site .tvcard .thumb .lk2,
  .site.site .tvcard .thumb .dur { font-size:12px; padding:4px 8px; }
  .site.site .tvchip { font-size:14px; }

  /* LE BOUTON CONTRE LE BAS DE LA CARTE.
     `margin-top: auto` était bien écrit mais perdait contre une règle plus
     spécifique — d'où les 76 px de vide qui subsistaient sous le bouton.
     `:last-child` ajoute le poids qui manquait. */
  .site.site .grid4 > .card { display: flex; flex-direction: column; }
  .site.site .grid4 > .card > .btn:last-child { margin-top:auto; }

  /* LE TABLEAU DÉFILE, IL NE DÉBORDE PAS.
     Mesuré : 504 px de contenu dans une carte de 338. Un tableau de cinq
     colonnes ne se replie pas — le rapport entre les colonnes EST
     l'information. On le fait donc défiler horizontalement dans sa carte,
     comme les rangées d'affiches, plutôt que de le laisser pousser la page
     entière de 159 px vers la droite. */
  .site.site .card > table.tb,
  .site.site .card > table.inv { display: block; overflow-x: auto; }
  .site.site table.tb, .site.site table.inv { min-width: 100%; }
}


/* ══════════════════════════════════════════════════════════════════════════
   47. LE STYLE EN LIGNE QUI GAGNAIT TOUJOURS

   Trois tentatives pour pousser le bouton d'une carte tarifaire contre son
   bas — `margin-top: auto`, puis la même chose plus spécifique, puis encore
   plus spécifique avec `:last-child`. Aucune n'a rien changé. Le vide sous le
   bouton restait mesuré à 97 px.

   La cause n'était dans aucune feuille de style : chaque bouton portait
   `style="width:100%;text-align:center;margin-top:15px"` dans le balisage.
   Un attribut `style` bat TOUTE règle de sélecteur, quelle qu'en soit la
   spécificité — il n'est pas en haut de l'échelle, il est à côté. Aucune
   surenchère de classes ne pouvait aboutir, et j'ai perdu deux passes à
   monter une échelle qui ne menait nulle part.

   Il restait `!important`, qui aurait marché. Ç'aurait été soigner le
   symptôme : neuf boutons, trois propriétés purement présentationnelles
   écrites dans le contenu, qu'aucune règle ne pourra jamais adapter à un
   appareil. Ils portent maintenant une classe, et la règle vit ici.

   LEÇON — quand une règle CSS « ne prend pas » malgré une spécificité
   croissante, vérifier l'attribut `style` du balisage AVANT d'ajouter un
   sélecteur de plus. Le symptôme d'une règle écrasée par une autre règle et
   celui d'une règle écrasée par un style en ligne sont identiques ; le second
   ne se corrige jamais depuis la feuille de style.
   ══════════════════════════════════════════════════════════════════════════ */
.site .cardcta { width: 100%; text-align: center; margin-top:16px; }

@media (max-width: 640px) {
  /* le bouton descend au bas de la carte, le vide passe au-dessus de lui */
  .site .grid4 > .card > .cardcta:last-child { margin-top:auto; }
}


/* ══════════════════════════════════════════════════════════════════════════
   48. LE RESTE, ET LE MÊME PLANCHER SUR TABLETTE

   Les trente dernières mentions sous 13 px, une par une : compteurs, libellés
   de champ, âges, notes de bas de carte, horodatages du Club. Elles sont
   nommées ici plutôt que rattrapées par une règle générale — parce qu'une
   règle générale du type `font-size: max(13px, 1em)` posée sur tous les
   éléments de texte écraserait aussi les titres, dont la taille propre est
   supérieure à celle de leur parent. Le remède serait pire.

   ══ ET LA TABLETTE ══
   Mesuré à 820 px : de 15 à 49 mentions sous 13 px par page, contre 1 à 13
   sur téléphone. Le palier tablette n'avait reçu qu'une poignée de règles.
   C'est une incohérence de raisonnement : une tablette se tient à la même
   distance qu'un téléphone et se touche du même doigt. Le plancher de
   lisibilité et le seuil de 44 px valent donc jusqu'à 1 080 px, sans
   exception — c'est le NOMBRE DE COLONNES qui distingue les deux appareils,
   pas la taille du texte.
   ══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 1080px) {
  .site.site .lg b,
  .site.site .row > div > span, .site.site .ag, .site.site .incl b,
  .site.site .nat p, .site.site .billbadge, .site.site .rgpd b,
  .site.site .acbadge, .site.site .acnote, .site.site .accessbar .txt span,
  .site.site .roomhead b, .site.site .roomsearch,
  .site.site .livebar b, .site.site .livebar span, .site.site .join,
  .site.site .fixit b, .site.site .fixit s, .site.site .fld2,
  .site.site .enonly b, .site.site .gain, .site.site .counter b,
  .site.site .report p, .site.site .rline span,
  .site.site .alab, .site.site .asep span, .site.site .aoubli a,
  .site.site .authcote .sur, .site.site .vl small,
  .site.site .lock, .site.site .day .slot span, .site.site .cal .slot span,
  .site.site .ladder > div, .site.site .grid2 > div > div { font-size:13px; }

  /* les mêmes rôles que sur téléphone : la tablette n'est pas un petit
     ordinateur, c'est un grand téléphone */
  .site.site ul.ck li, .site.site .pm ul li, .site.site .card ul li,
  .site.site .rlist li { font-size:15px; line-height: 1.5; }
  .site.site .eyebrow, .site.site .kick2, .site.site .bientot,
  .site.site .badge, .site.site .lb, .site.site .sub, .site.site .st,
  .site.site .nslot, .site.site .rn2, .site.site .rv, .site.site .acc,
  .site.site .clubkpi span, .site.site .chit span, .site.site .roomgrp,
  .site.site .room .rt span, .site.site .mini2, .site.site .tvchip,
  .site.site table.tb th, .site.site table.inv th,
  .site.site .ladder .st3 span, .site.site .ladder .res b,
  .site.site .tcard .foot span, .site.site .kpicard .sub,
  .site.site .tvhero .meta span, .site.site .tvfoot span { font-size:13px; }
  .site.site footer.site .cols h5 { font-size:13px; letter-spacing: .1em; }

  /* LE PIED DE PAGE ATTEINT ENFIN 44 PX.
     Le rembourrage posé à la passe précédente perdait lui aussi contre une
     règle plus spécifique : mesuré à 34 px au lieu des 46 attendus. Il fallait
     le même poids de sélecteur que le reste de cette section. */
  .site.site footer.site .cols a:not(.res) {
    display: block; font-size:15px; padding-block:12px; margin-block:-4px;
  }
  .site.site footer.site .bot a { display: inline-block; padding-block:12px; }

  /* le calendrier des créneaux : 37 mentions sous 13 px à lui seul sur
     tablette, dont les heures elles-mêmes à 9 px */
  .site.site .cal .dn, .site.site .cal .slot,
  .site.site .day .dn, .site.site .day .slot { font-size:13px; }
  .site.site .msg .bb, .site.site .msg b, .site.site .room b,
  .site.site .thread b { font-size:14px; }
  .site.site footer.site .cols p, .site.site footer.site .bot a,
  .site.site footer.site .bot span, .site.site footer.site .bot em { font-size:14px; }

  /* le bouton au bas de la carte vaut aussi sur tablette : c'est le même
     défilement horizontal, donc les mêmes hauteurs égalisées */
  .site.site .grid4 > .card { display: flex; flex-direction: column; }
  .site.site .grid4 > .card > .cardcta:last-child { margin-top:auto; }
}


/* ══════════════════════════════════════════════════════════════════════════
   49. LE PLUS PETIT ÉCRAN REPREND SES DROITS

   Le plancher de lisibilité de la section 45 a porté « Se connecter » et
   « S'inscrire » de 12 à 13,5 px, et leur a donné 44 px de haut. Bon pour le
   doigt, et l'audit l'a immédiatement sanctionné : 20 px de débordement
   horizontal sur les DIX-SEPT pages, à 320 px de large. La barre du haut ne
   rentrait plus.

   C'est le compromis inévitable d'une barre fixe : chaque pixel donné à un
   élément est pris à un autre. À 320 px il n'y a plus de marge à distribuer.
   On rend donc le pixel typographique — les deux libellés redescendent — mais
   PAS la hauteur de 44 px, qui ne coûte rien en largeur. Le doigt garde sa
   cible, l'œil perd un demi-point sur deux mots qu'il n'a pas besoin de lire.

   320 px n'est pas un cas d'école : c'est un iPhone SE, et c'est aussi tout
   téléphone récent dont l'utilisateur a agrandi la police du système.
   ══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 400px) {
  .site.site .topnav .authbtns a { font-size:12px; }
  .site.site .topnav .authbtns .sgup,
  .site.site .topnav .authbtns .lgin { padding-inline:8px; }
  .site.site .topnav .rt { gap:8px; }
}


/* ══════════════════════════════════════════════════════════════════════════
   50. LA RANGÉE D'ONGLETS SUR TÉLÉPHONE : PLUS DE CADRE, DONC PLUS DE CADRE
       COUPÉ

   Les quatre catégories de la collection tiennent sur 527 px. Un téléphone en
   offre 350. La rangée défile donc — c'est le bon comportement — mais elle
   porte un CADRE en pilule, bordure et fond compris, et ce cadre est coupé
   net par le bord de l'écran. On ne lit pas « il y a la suite à droite », on
   lit « ce bloc est cassé ». Les deux personnes qui l'ont signalé l'ont
   entouré au feutre rouge, sur téléphone comme sur ordinateur.

   Le cadre est la promesse d'un contenant fermé. Dès que le contenu le
   dépasse, la promesse est fausse, et il vaut mieux la retirer que la tenir à
   moitié. Sur téléphone la rangée devient donc une simple file d'onglets qui
   glisse, sans boîte autour — la pastille active suffit à dire où l'on est —
   et un dégradé sur le bord droit dit qu'il y a la suite.

   Le masque est posé sur le CONTENEUR EXTÉRIEUR et non sur la rangée qui
   défile : appliqué à la rangée, il aurait défilé avec elle et se serait
   promené au milieu des onglets.
   ══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 640px) {
  .site.site #famtabs {
    background: none; border-color: transparent; box-shadow: none;
    padding-inline:0;
    display: flex; max-width: 100%;
    scroll-padding-inline:0;
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent);
            mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent);
  }
  /* la pastille garde son fond : c'est elle qui porte maintenant la forme */
  .site.site #famtabs .ftpuce { box-shadow: 0 4px 14px -4px rgba(0, 0, 0, .5); }
  .site.site #famtabs::-webkit-scrollbar { display: none; }
}


/* ══════════════════════════════════════════════════════════════════════════
   51. CODER POUR LA STRUCTURE, STYLER POUR L'ŒIL

   Six pages n'avaient AUCUN h1 : leur titre visuel était un h2 ou un h3,
   choisi pour sa taille. Visuellement rien à redire — mais pour un moteur de
   recherche et un lecteur d'écran, ces pages n'avaient pas de titre. La
   hiérarchie du document et la hiérarchie visuelle sont deux choses
   différentes : on promeut la balise, on garde la classe, et l'écran ne
   change pas d'un pixel.

   La page des cours n'a pas de titre à l'écran — elle ouvre sur la carte du
   professeur, et c'est un choix de mise en page qu'on ne casse pas. Elle
   reçoit un h1 masqué à la manière des lecteurs d'écran : présent dans le
   document, absent du rendu. Ce n'est pas du texte caché pour tricher, c'est
   l'étiquette de la page.

   Et l'interligne des h4 de 17-18 px passait de 1,06 — un réglage de grand
   titre — à des titres qui se replient sur deux lignes en mobile. 1,25 les
   laisse serrés sans les coller. */
.site .sr-seul {
  position: absolute; width: 1px; height: 1px; margin:-2px;
  padding:0; border: 0; clip-path: inset(50%); overflow: hidden;
  white-space: nowrap;
}
.site .mrow h4, .site .pm h4, .site .kcard h4 { line-height: 1.25; }

/* ── la vignette de couverture rejoint le langage des autres surfaces ──
   Toutes les images posées sur une carte ont un rayon et une ombre ; celle-ci
   n'en avait pas. Un rayon plus petit que celui de sa carte : un coin
   intérieur est toujours plus serré que le coin qui l'entoure. */
.site .mc-img { border-radius: 10px; box-shadow: var(--sh2); }

/* ── le rang du copyright se replie au lieu de déborder ──
   Cinq éléments en ligne (© · CGV · Mentions · Confidentialité · signature)
   ne tiennent pas en 320 px depuis que le plancher de lisibilité a monté leur
   taille de 11,5 à 13,5 px. L'audit l'a mesuré : 8 px coupés par
   l'overflow:hidden du pied de page. Un rang d'étiquettes se replie. */
@media (max-width: 400px) {
  .site.site footer.site .bot { flex-wrap: wrap; row-gap:0; }
}


/* ══════════════════════════════════════════════════════════════════════════
   52. LES FONCTIONNALITÉS — test de niveau, formulaires, lecteur TV

   Trois interfaces nouvelles, un seul langage : celui des panneaux existants.
   Rayon, ombre à deux couches, rembourrage et échelle d'atténuation viennent
   des jetons — rien n'est inventé ici, tout est réutilisé.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── le test de niveau ── */
.site #test-niveau h3 { margin:8px 0 8px; }
.site .tn-actions { display: flex; gap:12px; flex-wrap: wrap; margin-top:12px; }
.site .tn-comment { margin-top:12px; }
.site .tn-comment p { font-size:15px; color: var(--soft); margin:0; }
.site .tn-q { font-size: clamp(19px, 2vw, 24px); margin:8px 0 16px; }
.site .tn-choix { display: flex; flex-direction: column; gap:12px; max-width: 560px; }
.site .tn-opt {
  font: inherit; text-align: left; cursor: pointer;
  background: var(--surf2, rgba(255,255,255,.06));
  color: var(--ink); border: 1px solid var(--brd);
  border-radius: 12px; padding:12px 16px;
  transition: border-color var(--t-etat) var(--e), transform var(--t-etat) var(--e);
}
.site .tn-opt:hover:not(:disabled) { border-color: var(--crimson); transform: translateX(3px); }
.site .tn-opt.juste { border-color: var(--green); color: var(--green); font-weight: 700; }
.site .tn-opt.faux  { border-color: var(--crimson); color: var(--crimson); }
.site .tn-opt:disabled { cursor: default; opacity: .85; }
.site .tn-explique { margin-top:12px; }
.site .tn-explique p { font-size:15px; margin:0 0 12px; }
.site .tn-niveau { font-style: normal; color: var(--crimson); }
.site .tn-note { font-size:14px; color: var(--soft2); margin:12px 0 0; }

/* ── la fenêtre de formulaire (réservation, licence, contact) ──
   z-index AU-DESSUS de la barre collante (200) et du menu (300) : sinon le
   haut de la fenêtre, et son bouton de fermeture, passent SOUS la barre du
   haut. On aligne la fenêtre en haut (pas au centre) avec une marge propre,
   pour qu'elle ne soit jamais rognée par la barre même quand elle est haute. */
.fvoile {
  position: fixed; inset: 0; z-index: 500;
  background: rgba(5, 9, 15, .62); backdrop-filter: blur(3px);
  display: flex; align-items: flex-start; justify-content: center;
  padding:max(24px, 5vh) 20px 24px; overflow-y: auto;
}
.fmodale {
  background: var(--surf, #182130); color: var(--ink);
  border: 1px solid var(--brd); border-radius: 22px;
  box-shadow: 0 30px 80px -24px rgba(5,9,15,.7);
  padding:30px 34px 32px; width: min(600px, 100%);
  margin: auto;
  position: relative;
}
body:not(.dark) .fmodale { background: #fff; }
/* l'en-tête de marque : le logo complet, un fichier par thème */
.fmarque { display:flex; justify-content:center; margin:6px 0 18px; }
.fmarque img { height:138px; width:auto; display:block; }
.fmarque .fls { display:none; }
body.dark .fmarque .flc { display:none; }
body.dark .fmarque .fls { display:block; }
.fmodale h3 { margin:0 0 4px; font-size:23px; font-weight:900; text-align:center;
  letter-spacing:-.01em; }
.fmodale .fctx {
  display: block; width: fit-content; margin:6px auto 2px;
  font-size:12.5px; font-weight: 700; letter-spacing: .04em;
  color: var(--crimson);
  background: color-mix(in srgb, var(--crimson) 12%, transparent);
  border-radius: 999px; padding:4px 14px;
}
.fmodale .ftxt { font-size:14.5px; color: var(--soft); margin:6px auto 20px;
  text-align:center; max-width:44ch; line-height:1.55; }
/* nom + e-mail côte à côte : la fenêtre est large, on l'exploite et on
   raccourcit d'autant la hauteur (moins de défilement, croix toujours visible) */
.frang { display:grid; grid-template-columns:1fr 1fr; gap:0 16px; }
.fmodale label { display: block; font-size:13px; font-weight: 700; margin:0 0 14px;
  color:var(--soft); }
.fmodale label small { font-weight: 400; color: var(--soft2); }
.fmodale input, .fmodale textarea {
  display: block; width: 100%; margin-top:5px;
  font: inherit; font-size:15px; color: var(--ink);
  background: var(--paper); border: 1px solid var(--brd);
  border-radius: 11px; padding:12px 13px;
}
.fmodale textarea { resize: vertical; min-height: 84px; }
.fmodale input:focus, .fmodale textarea:focus {
  outline: 2px solid var(--crimson); outline-offset: 1px; border-color: transparent;
}
.fmodale .fenvoi { width: 100%; justify-content: center; margin-top:6px;
  padding:13px 0; font-size:15px; font-weight:700;
  box-shadow:0 8px 22px -10px rgba(192,9,58,.55); }
.fmodale .fnote {
  font-size:14px; color: var(--crimson);
  margin:0 0 14px; padding:9px 13px;
  background: color-mix(in srgb, var(--crimson) 10%, transparent);
  border-radius: 11px;
}
.fmodale .fnote.ok { color: var(--green); background: color-mix(in srgb, var(--green) 12%, transparent); }
/* le bouton de fermeture : rond, discret, franchement rouge au survol */
.ffermer {
  position: absolute; top: 16px; right: 16px;
  width: 40px; height: 40px; border-radius: 50%;
  display: grid; place-items: center; padding:0; line-height:0;
  cursor: pointer;
  background: color-mix(in srgb, var(--ink) 6%, transparent);
  color: var(--soft); border: 1px solid color-mix(in srgb, var(--ink) 12%, transparent);
  transition: background-color var(--t-etat) var(--e), color var(--t-etat) var(--e),
              border-color var(--t-etat) var(--e), transform var(--t-etat) var(--e);
}
.ffermer svg { width:16px; height:16px; display:block; }
.ffermer:hover { background: var(--crimson); color:#fff; border-color:var(--crimson);
  transform: rotate(90deg) scale(1.05); }
.ffermer:active { transform: rotate(90deg) scale(.95); }
@media (max-width:520px){
  .frang { grid-template-columns:1fr; }
  .fmarque img { height:112px; }
  .fmodale h3 { font-size:20px; }
}

/* ── le lecteur TFA TV ── */
.tvlecteur {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(3, 6, 10, .88);
  display: flex; align-items: center; justify-content: center;
  padding:16px;
}
.tvl-cadre {
  width: min(420px, 92vw); aspect-ratio: 9 / 16;
  max-height: 88vh; border-radius: 16px; overflow: hidden;
  background: #000; box-shadow: var(--sh2);
}
.tvl-cadre iframe, .tvl-cadre video { width: 100%; height: 100%; border: 0; display: block; }
.tvl-charge { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  text-align: center; padding: 24px; color: #fff; background: rgba(8,12,22,.72);
  font-weight: 600; font-size: 15px; line-height: 1.5; }
.tvl-charge.err { background: rgba(8,12,22,.9); color: #FFD7D7; }

/* ── Salle de cours en direct (RealtimeKit) ── */
.rtk-plein { position: fixed; inset: 0; z-index: 9999; background: #0A0E17; display: flex; }
.rtk-plein rtk-meeting { flex: 1; width: 100%; height: 100%; }
.rtk-fermer { position: absolute; top: 14px; right: 14px; z-index: 2; width: 42px; height: 42px;
  border: 0; border-radius: 50%; background: rgba(255,255,255,.14); color: #fff; font-size: 20px;
  cursor: pointer; line-height: 42px; }
.rtk-fermer:hover { background: rgba(255,255,255,.24); }
.rtk-charge { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  text-align: center; padding: 24px; color: #fff; font-weight: 600; font-size: 15px; line-height: 1.5; }
.rtk-charge.err { color: #FFD7D7; }
.rtk-marque { position: absolute; top: 14px; left: 16px; z-index: 4; pointer-events: none; opacity: .9; }
.rtk-marque img { height: 30px; width: auto; display: block; filter: drop-shadow(0 1px 5px rgba(0,0,0,.55)); }
.tvl-fiche {
  background: var(--surf, #182130); color: var(--ink);
  border: 1px solid var(--brd); border-radius: 18px; box-shadow: var(--sh2);
  padding:24px 24px; width: min(430px, 100%);
}
.tvl-fiche h3 { margin:8px 0 8px; font-size:21px; }
.tvl-fiche p { font-size:15px; color: var(--soft); margin:0 0 12px; }
.tvl-note { font-size:14px; color: var(--soft2); }
.tvl-fermer {
  position: fixed; top: 18px; right: 18px; z-index: 61;
  width: 40px; height: 40px; border-radius: 50%;
  font: inherit; font-size:16px; cursor: pointer;
  background: rgba(255,255,255,.12); color: #fff; border: 0;
}
@media (max-width: 640px) {
  .fmodale, .tvl-fiche { padding:20px 16px; }
}


/* ══════════════════════════════════════════════════════════════════════════
   53. LA RANGÉE DES TARIFS SE COMPTE TOUTE SEULE

   Cinq colonnes en dur dans la feuille, six imposées par un attribut
   `style` sur la page, deux réclamées par la feuille mobile sous 1000 px et
   jamais obtenues : trois avis contradictoires pour une seule rangée. Le
   plus fort gagnait — l'attribut — et la sixième carte se faisait couper à
   1024 px.

   `auto-fit` + `minmax` remplace les trois : on déclare la largeur MINIMALE
   qu'une formule doit avoir pour rester lisible, et le navigateur en met
   autant que la place le permet. Six sur un grand écran, cinq à 1024 px,
   quatre sur tablette, deux sur téléphone — sans une seule requête média,
   et sans qu'on ait à connaître le nombre de formules à l'avance. Le jour
   où Yann en ajoutera une septième, il n'y aura rien à changer ici.
   ══════════════════════════════════════════════════════════════════════════ */
.site .pricemini {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap:12px;
}

/* ══ SIX FORMULES NE SE RANGENT BIEN QU'EN 1, 2, 3 OU 6 COLONNES ══
   `auto-fit` seul remplit la place au mieux, et donnait donc 5 + 1 à
   1024 px et 4 + 2 à 900 px : une carte seule au bout d'une rangée, alors
   que la page invite justement à COMPARER les formules. Une rangée
   orpheline casse la comparaison.
   Deux seuils suffisent à ne garder que des diviseurs de six — et ce sont
   les deux mêmes que le reste du site emploiera : la tablette et
   l'ordinateur. Sous 520 px, `auto-fit` reprend la main : une colonne sur
   un petit téléphone, deux dès qu'il y a la place. */
@media (min-width: 521px)  { .site .pricemini { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1141px) { .site .pricemini { grid-template-columns: repeat(6, minmax(0, 1fr)); } }


/* ══════════════════════════════════════════════════════════════════════════
   54. UNE SEULE HAUTEUR DE CIBLE TACTILE

   Elle était déclarée quatre fois, dans quatre contextes différents, avec
   quatre valeurs : 40 px sur tout écran sans souris, 36 px pour les
   étiquettes, 44 px sur tablette, 46 px sur téléphone. Ce n'était pas une
   progression réfléchie — un doigt ne rétrécit pas quand l'écran grandit.
   C'était quatre décisions prises à quatre moments, dont seule la dernière
   arrivait à l'écran sur téléphone, et dont la PREMIÈRE — 40 px, sous le
   seuil recommandé — restait la règle effective sur les portables tactiles
   et les grandes tablettes, c'est-à-dire exactement là où personne n'était
   allé vérifier.

   Une valeur, une règle, un endroit. 46 px partout où il n'y a pas de
   souris. Sur ordinateur, le remplissage donne déjà 45 px : le plancher ne
   change donc rien à ce qui existe, il empêche seulement de descendre
   au-dessous sans s'en rendre compte.
   ══════════════════════════════════════════════════════════════════════════ */
@media (hover: none) {
  .site.site .btn, .site.site .hbtn, .site.site .tvbtn, .site.site button {
    min-height: 46px; display: inline-flex; align-items: center; justify-content: center;
  }
  .site.site .tvchip, .site.site .ftab, .site.site .chip, .site.site .audsw a {
    min-height: 44px; display: inline-flex; align-items: center;
  }
}

/* ── le bouton « grand » redevenait un bouton normal sous 400 px ──
   `padding:12px 20px; font-size:15px` : exactement les valeurs du bouton de
   base. L'appel à l'action principal d'une page perdait donc toute
   hiérarchie sur les téléphones les plus étroits — l'endroit où il compte le
   plus. Il reste plus petit qu'au bureau, parce que la place manque, mais il
   reste plus grand que les autres. */
@media (max-width: 400px) {
  .site .btn.lg { padding:14px 24px; font-size:16px; }
}


/* ══════════════════════════════════════════════════════════════════════════
   55. LES COMPLÉMENTS D'ABONNEMENT SONT DEVENUS DE VRAIS LIENS

   Les trois lignes « Une heure en plus · TFA Kids · Le manuel suivant »
   étaient des `<div>` avec une flèche → et rien derrière : elles avaient
   toute l'apparence d'un lien et aucun comportement. On clique, il ne se
   passe rien, et l'on ne sait pas si c'est cassé ou si c'est normal.
   Ce sont maintenant des `<a>` vers les pages qui existent déjà. Le style
   ne change pas d'un pixel — seule la couleur héritée du lien devait être
   neutralisée, et le curseur devient enfin celui d'un lien.
   ══════════════════════════════════════════════════════════════════════════ */
.site a.ritem {
  color: inherit;
  text-decoration: none;
}
.site a.ritem:hover .ar { color: var(--crimson); }
.site a.ritem .ar { transition: transform var(--t-etat) var(--e), color var(--t-etat) var(--e); }
.site a.ritem:hover .ar { transform: translateX(3px); }

/* la ligne « aucun abonnement » : le montant à 0 € ne doit pas crier */
.site .member .row > div > b { font-variant-numeric: tabular-nums; }

/* Le reçu PDF est un vrai lien maintenant qu'il en existe : sans cette
   règle il s'affichait en bleu souligné du navigateur, au milieu d'un
   tableau qui n'a pas une seule autre couleur. */
.site .inv a {
  color: var(--crimson); text-decoration: none; font-weight: 700;
  white-space: nowrap;
}
.site .inv a:hover { text-decoration: underline; }
body.dark .site .inv a { color: #FF8FAB; }


/* ══════════════════════════════════════════════════════════════════════════
   56. S'ENTRAÎNER — LES DÉCLENCHEURS DEVENUS RÉELS

   Les « 10 questions / Série de 20 / 40 questions » étaient des <span> ;
   ce sont des <button>, parce qu'un élément qui agit doit en être un —
   clavier, lecteur d'écran et focus compris. Un bouton hérite de la fonte
   et du fond du navigateur : on remet ce que les <span> avaient, rien de
   plus. Les cartes déclencheuses prennent le curseur qui dit « je fais
   quelque chose ». */
.site .qbtns button { border: 0; font: inherit; color: inherit; background: none; }
.site .qbtns button.qbig { background: #fff; color: var(--navy); }
.site .qbtns button.qsm { border: 1.5px solid rgba(255,255,255,.4); background: none; }
.site .qbtns button.qsm:hover { background: rgba(255,255,255,.14); }
.site .tcard[data-serie], .site .tcard[data-bientot] { cursor: pointer; }

/* la série se joue dans le bandeau : les écrans du test (tn-*) y sont
   posés sur fond marine — le texte doit rester lisible dessus */
.site #niveau .tn-q { color: #fff; }
.site #niveau .tn-explique p { color: #DCE6F1; }

/* ══════════════════════════════════════════════════════════════════════════
   57. LE QUESTIONNAIRE D'ACCUEIL (onboarding, façon Duolingo)

   Un plein écran posé SUR la page (hors `.site`), affiché à la première
   connexion une fois l'animation du logo retirée. Une question à la fois, de
   grandes cartes qu'on tape, une barre de progression. Lisible dans les deux
   thèmes : l'écran porte ses propres couleurs, il n'hérite de rien. */
.qz{position:fixed;inset:0;z-index:500;display:flex;align-items:center;
  justify-content:center;padding:22px;overflow:auto;
  background:linear-gradient(160deg,#F7FAFF,#E9F1FB);
  -webkit-tap-highlight-color:transparent}
.qzcard{width:100%;max-width:560px;text-align:center;
  animation:qzin .35s ease both}
@keyframes qzin{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.qzcard{animation:none}}

.qztop{display:flex;align-items:center;gap:12px;margin-bottom:26px}
.qzback{width:34px;height:34px;flex:0 0 auto;border:0;border-radius:50%;
  background:rgba(9,45,89,.08);color:var(--navy);font-size:20px;line-height:1;
  cursor:pointer}
.qzback.qzvide{visibility:hidden}
.qzbar{flex:1;height:9px;border-radius:6px;background:rgba(9,45,89,.12);overflow:hidden}
.qzbar>i{display:block;height:100%;border-radius:6px;background:var(--crimson);
  transition:width .35s ease}
.qzskip{flex:0 0 auto;border:0;background:none;color:var(--soft);font-size:13px;
  cursor:pointer;padding:6px 4px}
.qzskip:hover{color:var(--crimson)}

.qzstep{font-size:12px;letter-spacing:.6px;text-transform:uppercase;
  color:var(--soft);font-weight:700;margin-bottom:8px}
.qzq{font-size:24px;line-height:1.2;color:var(--navy);margin:0 0 22px;font-weight:800}

.qzopts{display:grid;grid-template-columns:1fr 1fr;gap:12px}
/* les cases : la même facture que les cartes du site — surface en léger
   dégradé, liseré lumineux en haut, et au survol l'élévation + la LUEUR
   CRIMSON radiale qui suit la marque partout ailleurs. */
.qzopt{position:relative;z-index:0;overflow:hidden;
  display:flex;align-items:center;gap:14px;text-align:left;padding:17px 18px;
  border:1px solid var(--brd);border-radius:16px;cursor:pointer;font:inherit;
  background:linear-gradient(180deg,#FFFFFF,#F5F8FD);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.85), 0 1px 2px rgba(9,45,89,.06);
  transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease}
.qzopt::before{content:"";position:absolute;inset:0;z-index:-1;
  border-radius:inherit;pointer-events:none;opacity:0;transition:opacity .18s ease;
  background:radial-gradient(300px circle at 50% 0%,
    color-mix(in srgb, var(--crimson) 14%, transparent), transparent 64%)}
.qzopt:hover{transform:translateY(-3px);
  border-color:color-mix(in srgb, var(--crimson) 42%, var(--brd));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.85),
    0 12px 28px -10px rgba(192,9,58,.42), 0 3px 10px rgba(9,45,89,.08)}
.qzopt:hover::before{opacity:1}
.qzopt.on{border-color:var(--crimson);
  background:linear-gradient(180deg,#FFF6F8,var(--rose));
  box-shadow:0 8px 22px -8px rgba(192,9,58,.4)}
.qze{flex:0 0 auto;width:46px;height:46px;border-radius:13px;
  display:flex;align-items:center;justify-content:center;
  background:var(--blue);font-size:23px;line-height:1;
  transition:transform .18s ease}
.qzopt:hover .qze{transform:scale(1.07) rotate(-4deg)}
.qzt{display:flex;flex-direction:column;gap:2px;min-width:0}
.qzt b{font-size:15px;color:var(--ink);font-weight:700}
.qzt span{font-size:12.5px;color:var(--soft)}

.qzfin .qzmasc{margin:0 auto 14px;width:64px;height:64px;border-radius:50%;
  background:var(--blue);display:flex;align-items:center;justify-content:center}
.qzfin .qzmasc .bulles{height:34px}
.qzp{font-size:15.5px;line-height:1.6;color:var(--soft);margin:0 auto 24px;max-width:440px}
.qzactions{display:flex;flex-direction:column;gap:10px;max-width:340px;margin:0 auto}
.qzactions .btn{width:100%;text-decoration:none;text-align:center}
.qztab{border:0;background:none;color:var(--soft);font-size:13.5px;cursor:pointer;
  padding:6px;margin-top:2px}
.qztab:hover{color:var(--crimson)}

@media (max-width:560px){
  .qzopts{grid-template-columns:1fr}
  .qzq{font-size:21px}
}

/* ── thème sombre : l'écran prend des tons profonds, le texte s'éclaircit ── */
body.dark .qz{background:linear-gradient(160deg,#0C1119,#111A28)}
body.dark .qzq{color:#E4EBF5}
body.dark .qzback{background:rgba(255,255,255,.08);color:#E4EBF5}
body.dark .qzbar{background:rgba(255,255,255,.12)}
body.dark .qzopt{background:linear-gradient(180deg,#1A2536,#111A28);
  border-color:#2B374A;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.05), 0 1px 2px rgba(0,0,0,.3)}
body.dark .qzopt::before{background:radial-gradient(300px circle at 50% 0%,
  rgba(192,9,58,.22), transparent 64%)}
body.dark .qzopt:hover{border-color:color-mix(in srgb, var(--crimson) 55%, #2B374A);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.05),
    0 14px 30px -10px rgba(192,9,58,.5), 0 4px 12px rgba(0,0,0,.35)}
body.dark .qzopt.on{border-color:var(--crimson);
  background:linear-gradient(180deg,rgba(192,9,58,.2),rgba(192,9,58,.1));
  box-shadow:0 8px 24px -8px rgba(192,9,58,.5)}
body.dark .qze{background:rgba(255,255,255,.07)}
body.dark .qzt b{color:#E4EBF5}
body.dark .qzt span{color:#8692A4}
body.dark .qzp{color:#B7C1D0}
body.dark .qzfin .qzmasc{background:#14263B}

/* ── 57b. HABILLAGE DE MARQUE DU QUESTIONNAIRE ──
   Logo TFA en tête, couleurs de la marque, bouton PASSER façon interface,
   et l'emplacement des mascottes Truly & Fluent sur l'écran final. */

/* le fond prend une touche de marque plutôt que du gris neutre */
.qz{background:
  radial-gradient(1100px 520px at 50% -8%, rgba(9,45,89,.10), transparent 70%),
  radial-gradient(700px 460px at 92% 108%, rgba(192,9,58,.08), transparent 70%),
  linear-gradient(160deg,#F7FAFF,#EAF1FB)}

/* l'en-tête : le logo complet, généreux et bien aéré. Un fichier par thème —
   le texte navy de l'officiel serait invisible sur fond sombre. */
.qzhead{display:flex;align-items:center;justify-content:center;
  margin:4px 0 26px}
.qzhead img{height:150px;width:auto;display:block}
.qzhead .qls{display:none}
body.dark .qzhead .qlc{display:none}
body.dark .qzhead .qls{display:block}
@media (max-width:560px){.qzhead img{height:112px}}

/* la barre : dégradé navy → crimson, la marque jusque dans la progression */
.qzbar>i{background:linear-gradient(90deg,var(--navy),var(--crimson))}

/* le bouton PASSER : soigné, encadré aux couleurs de la marque */
.qzpasser{flex:0 0 auto;border:1.5px solid var(--crimson);background:#fff;
  color:var(--crimson);font-size:11.5px;font-weight:800;letter-spacing:.8px;
  padding:7px 15px;border-radius:22px;cursor:pointer;line-height:1;
  box-shadow:0 2px 8px rgba(192,9,58,.14);transition:all .16s ease}
.qzpasser:hover{background:var(--crimson);color:#fff;
  box-shadow:0 5px 16px rgba(192,9,58,.28);transform:translateY(-1px)}

/* les mascottes sur l'écran final */
.qzduo{margin:0 auto 16px;max-width:320px}
.qzduo img{width:100%;height:auto;display:block;
  filter:drop-shadow(0 12px 26px rgba(9,45,89,.18))}

/* les boutons d'action finaux, exactement la facture des boutons du site */
.qzactions .qzprim{box-shadow:0 6px 18px rgba(192,9,58,.26)}

/* ── thème sombre : logo blanc, bouton PASSER adapté ── */
body.dark .qz{background:
  radial-gradient(1100px 520px at 50% -8%, rgba(27,74,133,.28), transparent 70%),
  radial-gradient(700px 460px at 92% 108%, rgba(192,9,58,.16), transparent 70%),
  linear-gradient(160deg,#0B111B,#0E1726)}
body.dark .qzhead b{color:#EAF1FB}
body.dark .qzpasser{background:transparent;color:#FF9BB4;border-color:#FF9BB4}
body.dark .qzpasser:hover{background:var(--crimson);color:#fff;border-color:var(--crimson)}

/* ── 57c. LE FOND ANIMÉ DU QUESTIONNAIRE ──
   Quatre emblèmes TFA, pas un de plus, qui montent très lentement à travers
   l'écran — l'effet « ballons » de la référence, ramené à une version sobre :
   opacité faible, deux plans de profondeur (les gros sont floutés), aucune
   interaction. Le fond est FIXE et rogné : rien ne crée de barre de
   défilement. Les mascottes Truly & Fluent accompagnent CHAQUE question,
   posées dans le coin — et s'effacent sur l'écran final, où le grand duo
   prend le relais au centre. */
.qzfond{position:fixed;inset:0;overflow:hidden;pointer-events:none}
.qzcorps{position:relative;min-height:100%;width:100%;
  display:flex;align-items:center;justify-content:center}
.qz{display:block}          /* le centrage vit désormais dans .qzcorps */

.qz .qzlogo{position:absolute;top:100%;opacity:.13;
  animation:qzmonte linear infinite}
/* six bulles, délais répartis pour qu'il y en ait TOUJOURS à l'écran —
   jamais de creux, jamais d'encombrement */
.qz .qzlogo.l1{height:76px;left:5%;filter:blur(2.5px);
  animation-duration:58s;animation-delay:-8s}
.qz .qzlogo.l2{height:42px;left:13%;
  animation-duration:74s;animation-delay:-34s}
.qz .qzlogo.l3{height:66px;right:6%;filter:blur(2px);
  animation-duration:64s;animation-delay:-52s}
.qz .qzlogo.l4{height:46px;right:13%;
  animation-duration:80s;animation-delay:-18s}
.qz .qzlogo.l5{height:56px;left:9%;filter:blur(1.5px);
  animation-duration:70s;animation-delay:-62s}
.qz .qzlogo.l6{height:36px;right:9%;
  animation-duration:66s;animation-delay:-44s}
@keyframes qzmonte{
  0%   {transform:translate(0,6vh)}
  50%  {transform:translate(14px,-56vh)}
  100% {transform:translate(0,-118vh)}
}

/* les mascottes du coin, présentes à chaque question.
   L'IMAGE EST CADRÉE AUX GENOUX : son bord bas est une coupe. Elle est donc
   ancrée SOUS le bord de l'écran (-20px), assez bas pour que même au sommet
   du flottement (+9px) la coupe reste hors champ — on ne voit jamais les
   jambes tronquées, seulement le duo qui émerge du bord, comme s'il se
   tenait juste derrière. */
.qzmascotte{position:absolute;right:22px;bottom:-26px;width:212px}
.qzmascotte img{width:100%;height:auto;display:block;
  filter:drop-shadow(0 10px 22px rgba(9,45,89,.22));
  animation:qzflotte 6.5s ease-in-out infinite}
@keyframes qzflotte{0%,100%{transform:translateY(0)}50%{transform:translateY(-9px)}}
#qz.qzfini .qzmascotte{display:none}

/* petits écrans : on garde l'épure — les mascottes du coin s'effacent,
   deux logos suffisent */
@media (max-width:900px){
  .qzmascotte{display:none}
  .qz .qzlogo.l2,.qz .qzlogo.l4{display:none}
}

/* mouvement réduit : tout s'immobilise, posé à des hauteurs fixes */
@media (prefers-reduced-motion:reduce){
  .qz .qzlogo{animation:none}
  .qz .qzlogo.l1{top:16%}.qz .qzlogo.l2{top:58%}
  .qz .qzlogo.l3{top:24%}.qz .qzlogo.l4{top:66%}
  .qz .qzlogo.l5{top:42%}.qz .qzlogo.l6{top:80%}
  .qzmascotte img{animation:none}
}

/* ── 57d. LES BOUTONS DES SURFACES HORS `.site` ──
   Le questionnaire (#qz) et les fenêtres de formulaire (.fmodale) sont posés
   sur <body>, HORS de `.site` — or toute la facture des boutons du site est
   accrochée à `.site .btn`. Sans ce bloc, leurs boutons retombent sur le
   `.btn` nu de la maquette : des rectangles bruts qui cassent l'architecture.
   On leur applique EXACTEMENT la même recette : pilule, mêmes tailles, même
   élévation au survol, même variante fantôme. */
#qz .btn, .fmodale .btn {
  border-radius: var(--r-pill);
  padding:12px 24px;
  font-size:15px; font-weight:600; letter-spacing:-.008em;
  transition: transform var(--t-etat) var(--e),
              box-shadow var(--t-etat) var(--e),
              background-color var(--t-etat) var(--e),
              border-color var(--t-etat) var(--e),
              color var(--t-etat) var(--e);
}
#qz .btn:hover, .fmodale .btn:hover {
  transform: translateY(-1.5px);
  box-shadow: 0 10px 26px -10px rgba(192,9,58,.6);
}
#qz .btn:active, .fmodale .btn:active {
  transform: translateY(0) scale(.985); transition-duration:.08s;
}
#qz .btn.gh, .fmodale .btn.gh {
  border:1px solid color-mix(in srgb, currentColor 26%, transparent);
  background:transparent;
}
#qz .btn.gh:hover, .fmodale .btn.gh:hover {
  background: color-mix(in srgb, currentColor 8%, transparent);
  border-color: color-mix(in srgb, currentColor 45%, transparent);
  box-shadow:none;
}

/* ── l'écran final tient SANS défilement : logo généreux, duo plus discret ── */
.qzfin .qzhead{margin:0 0 10px}
.qzfin .qzhead img{height:132px}
.qzduo{max-width:188px;margin:0 auto 8px}
.qzfin .qzq{font-size:22px;margin-bottom:8px}
.qzp{margin:0 auto 18px}
@media (max-width:560px){.qzfin .qzhead img{height:112px}.qzduo{max-width:168px}}
.qzactions{gap:9px}

/* ══════════════════════════════════════════════════════════════════════════
   57e. LES SÉRIES D'ENTRAÎNEMENT — MÊME EXPÉRIENCE IMMERSIVE QUE L'ONBOARDING

   La série se joue désormais dans le plein écran `.qz` (mêmes deux couches,
   même décor, mêmes cases `.qzopt`) et non plus dans le bandeau. Ce bloc
   n'ajoute que ce qui est PROPRE à un exercice noté : la pastille-lettre des
   réponses, les états juste/faux, et le volet d'explication. Tout le reste
   est hérité de §57/57b/57c/57d — on ne réécrit rien. */

/* la pastille des réponses porte une LETTRE (A,B,C…), pas un emoji : un objet,
   conforme à « aucune représentation d'âmes » */
.qzserie .qze{font-size:17px;font-weight:800;color:var(--navy)}
body.dark .qzserie .qze{color:#CFE0F6}

/* après la réponse : plus d'élévation au survol, l'exercice est figé */
.qzserie .qzopt:disabled{cursor:default}
.qzserie .qzopt:disabled:hover{transform:none;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.85), 0 1px 2px rgba(9,45,89,.06)}
.qzserie .qzopt:disabled:hover::before{opacity:0}
.qzserie .qzopt:disabled:hover .qze{transform:none}

/* la bonne réponse — vert ; la réponse fausse choisie — crimson */
.qzserie .qzopt.juste{border-color:var(--green);
  background:linear-gradient(180deg,#F2FBF5,#E6F7EC)}
.qzserie .qzopt.juste .qze{background:color-mix(in srgb,var(--green) 20%,#fff);
  color:var(--green)}
.qzserie .qzopt.faux{border-color:var(--crimson);
  background:linear-gradient(180deg,#FFF4F6,#FCE8ED)}
.qzserie .qzopt.faux .qze{background:color-mix(in srgb,var(--crimson) 16%,#fff);
  color:var(--crimson)}
body.dark .qzserie .qzopt.juste{border-color:var(--green);
  background:linear-gradient(180deg,#12291D,#0E2016)}
body.dark .qzserie .qzopt.faux{border-color:var(--crimson);
  background:linear-gradient(180deg,#2A1119,#200B12)}
body.dark .qzserie .qzopt.juste .qze{background:rgba(95,203,138,.18);color:#7FE0A2}
body.dark .qzserie .qzopt.faux .qze{background:rgba(255,120,150,.16);color:#FF9BB4}

/* le volet d'explication, sous les cases */
.qzexp{margin-top:18px;text-align:left;border-radius:14px;padding:15px 17px;
  background:var(--surf);border:1px solid var(--brd);animation:qzin .28s ease both}
.qzexp p{margin:0 0 12px;font-size:14.5px;line-height:1.6;color:var(--soft)}
.qzexp p b{color:var(--ink)}
.qzexp .qzej{color:var(--green)} .qzexp .qzef{color:var(--crimson)}
.qzexp .btn{width:100%;justify-content:center}
body.dark .qzexp{background:#14202F;border-color:var(--brd)}

/* le bouton QUITTER : même pilule que PASSER */
.qzserie .qzq{font-size:22px}
@media (max-width:560px){.qzserie .qzq{font-size:19px}}

/* le test de niveau dans l'overlay : le niveau en crimson, la note discrète
   (les règles du bandeau sont accrochées à `.site`, l'overlay est dehors) */
#qz .tn-niveau{font-style:normal;color:var(--crimson)}
body.dark #qz .tn-niveau{color:#FF8FAB}
#qz .tn-note{font-size:13.5px;color:var(--soft2);margin:14px 0 0}
#qz .tn-note a{color:var(--crimson);font-weight:700;text-decoration:none}
#qz .tn-note a:hover{text-decoration:underline}

/* ══════════════════════════════════════════════════════════════════════════
   LA RÈGLE DES BOUTONS (audit v90) — tout ce qui se clique porte le même
   langage : arrondi du site, et une réponse au survol (levée + ombre ou
   accent), comme les .btn. Ici, les retardataires repérés au peigne fin.
   ══════════════════════════════════════════════════════════════════════════ */
.site .qbig { border-radius: var(--r-pill);
  transition: transform .18s var(--e), box-shadow .18s var(--e); }
.site .qbig:hover { transform: translateY(-1.5px);
  box-shadow: 0 10px 26px -10px rgba(9,45,89,.55); }
.site .qbig:active { transform: translateY(0) scale(.985); }
.site .qzback { transition: transform .18s var(--e), background-color .18s var(--e); }
.site .qzback:hover { transform: translateY(-1px); background: rgba(120,140,170,.28); }
.tvl-fermer { transition: transform .18s ease, opacity .18s ease; }
.tvl-fermer:hover { transform: scale(1.12); opacity: .85; }

/* Les SURCOUCHES (voiles injectés hors du conteneur .site) héritent du même
   langage de boutons — sans porter la classe .site, qui casserait leur
   position:fixed (cause du voile invisible du 22/08). */
.fvoile .btn, #cours-modale .btn {
  border-radius: var(--r-pill); padding:12px 24px;
  font-size:15px; font-weight: 600; letter-spacing: -.008em;
  transition: transform .18s var(--e), box-shadow .18s var(--e),
              background-color .18s var(--e), border-color .18s var(--e);
}
.fvoile .btn:hover, #cours-modale .btn:hover {
  transform: translateY(-1.5px); box-shadow: 0 10px 26px -10px rgba(192,9,58,.6);
}
.fvoile .btn:active, #cours-modale .btn:active { transform: translateY(0) scale(.985); }
#cours-modale .btn.ghost { background: transparent; color: var(--soft);
  border: 1.5px solid var(--brd); }
#cours-modale .btn.ghost:hover { border-color: var(--crimson); color: var(--crimson);
  box-shadow: none; }

/* La SIGNATURE des formulaires (règle du 22/08) : le logo centré en tête et
   Truly & Fluent pouces en l'air dans le coin — sur toutes les cartes de
   formulaire pleine page (connexion, inscription, mot de passe), comme sur
   les fenêtres .fmodale. */
.site .authcarte { position: relative; }
.site .authcarte .aduo {
  position: absolute; left: 16px; top: 12px; height: 84px; width: auto;
  pointer-events: none; filter: drop-shadow(0 6px 14px rgba(0,0,0,.35));
}
@media (max-width: 640px) {
  .site .authcarte .aduo { height: 60px; left: 10px; top: 10px; }
}

/* ══════════════════════════════════════════════════════════════════════════
   LA BRILLANCE DES BOUTONS (23/08) — la règle des boutons, acte II.
   Au survol, un reflet oblique traverse la pastille en 0,65 s : c'est le
   quatrième effet de la famille (montée + ombre + fond + reflet), et comme
   les trois autres, il se ressent plus qu'il ne se remarque. Le reflet vit
   dans ::before pour ne toucher ni au texte ni à la géométrie du bouton ;
   `overflow:hidden` le garde à l'intérieur de la pilule. Même règle que
   toujours : TOUS les boutons — y compris ceux des voiles, qui vivent hors
   de `.site` (voir TFA_REGLE_BOUTONS).
   ══════════════════════════════════════════════════════════════════════════ */
.site .btn, .site .hbtn, .site .tvbtn,
.fvoile .btn, #cours-modale .btn {
  position: relative; overflow: hidden;
}
.site .btn::before, .site .hbtn::before, .site .tvbtn::before,
.fvoile .btn::before, #cours-modale .btn::before {
  content: ""; position: absolute; top: 0; bottom: 0; left: -85%; width: 60%;
  background: linear-gradient(105deg,
    transparent 0%, rgba(255,255,255,.38) 50%, transparent 100%);
  transform: skewX(-18deg);
  pointer-events: none; opacity: 0;
}
.site .btn:hover::before, .site .hbtn:hover::before, .site .tvbtn:hover::before,
.fvoile .btn:hover::before, #cours-modale .btn:hover::before {
  animation: tfa-brille .65s var(--e);
}
/* sur un bouton fantôme (fond transparent), le reflet se fait discret */
.site .btn.gh::before, .site .tvbtn.gh::before,
.fvoile .btn.ghost::before, #cours-modale .btn.ghost::before {
  background: linear-gradient(105deg,
    transparent 0%, rgba(255,255,255,.14) 50%, transparent 100%);
}
@keyframes tfa-brille {
  0%   { left: -85%; opacity: 1; }
  100% { left: 120%; opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .site .btn::before, .site .hbtn::before, .site .tvbtn::before,
  .fvoile .btn::before, #cours-modale .btn::before { display: none; }
}

/* ══ Connexion ⇄ Inscription : glissement horizontal (comme l'app) ══ */
.apiste{ position:relative; overflow:hidden;
  transition:height .44s cubic-bezier(.32,.08,.24,1); }
.avoltrack{ display:flex; align-items:flex-start; width:200%;
  transition:transform .44s cubic-bezier(.32,.08,.24,1); }
.avoltrack > .avol{ width:50%; flex:0 0 50%; display:block; }
body.vers-inscription .avoltrack{ transform:translateX(-50%); }
@media (prefers-reduced-motion:reduce){ .apiste,.avoltrack{ transition:none; } }

/* le prix annuel « X € par an » s'affiche en vert (repère d'économie) */
.mini .by, .u .by { color: var(--green); }

/* ══ Le Club — rooms verrouillées + félicitations de niveau ══ */
.room.roomverr { opacity: .5; cursor: default; }
.room.roomverr .rn { filter: grayscale(1); }
.roomlock { font-size: 10.5px; font-weight: 800; color: var(--crimson); letter-spacing: .3px; margin-left: 6px; }

.fete-niveau { position: fixed; inset: 0; z-index: 2147483400; display: flex; align-items: center; justify-content: center;
  padding: 26px; background: rgba(6,10,18,.74); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
  opacity: 0; transition: opacity .28s ease; overflow: hidden; }
.fete-niveau.on { opacity: 1; }
.fete-conf { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }
.fete-conf i { position: absolute; top: -24px; width: 9px; height: 14px; border-radius: 2px;
  animation-name: fete-tombe; animation-timing-function: cubic-bezier(.25,.6,.4,1); animation-iteration-count: 1; opacity: .95; }
@keyframes fete-tombe { 0% { transform: translateY(-30px) rotate(0); opacity: 0; }
  10% { opacity: 1; } 100% { transform: translateY(112vh) rotate(560deg); opacity: 1; } }
.fete-carte { position: relative; width: 100%; max-width: 360px; text-align: center;
  background: #fff; color: var(--navy); border-radius: 22px; padding: 24px 24px 20px;
  box-shadow: 0 40px 90px -28px rgba(0,0,0,.6);
  transform: scale(.82); opacity: 0; animation: fete-pop .42s cubic-bezier(.2,1.15,.4,1) .12s forwards; }
@keyframes fete-pop { to { transform: scale(1); opacity: 1; } }
.fete-emb { height: 58px; width: auto; display: block; margin: 0 auto 8px; }
.fete-niv { display: inline-block; margin: 0 auto 10px; font-weight: 900; font-size: 15px; letter-spacing: 1px;
  color: #fff; background: linear-gradient(135deg, #1B4A85, #092D59); border-radius: 999px; padding: 5px 16px; }
.fete-carte h2 { margin: 0 0 6px; font-size: 22px; font-weight: 900; color: var(--navy); }
.fete-carte p { margin: 0 0 18px; font-size: 14.5px; line-height: 1.55; color: var(--soft); }
.fete-cta { display: block; width: 100%; height: 50px; border: 0; border-radius: 14px; cursor: pointer;
  background: var(--crimson); color: #fff; font: inherit; font-weight: 800; font-size: 15px; }
.fete-cta:hover { background: var(--crimson-d); }
.fete-plus { display: block; width: 100%; margin-top: 8px; height: 40px; border: 0; background: none;
  color: var(--soft); font: inherit; font-weight: 600; cursor: pointer; }

/* Le Club — traduction d'un message au toucher */
.msg .bb[data-txt] { cursor: pointer; }
.msg-trad { margin-top: 6px; padding-top: 6px; border-top: 1px dashed color-mix(in srgb, var(--navy) 22%, transparent);
  font-size: 13px; line-height: 1.5; color: var(--soft); font-style: italic; }
.msg-trad::before { content: "FR "; font-style: normal; font-weight: 800; color: var(--crimson); font-size: 11px; }

/* Le Club — chip @nametag (identité + modifier) */
.hdlchip { display:flex; align-items:center; gap:10px; margin-top:10px; padding-top:10px;
  border-top:1px solid var(--brd2); flex-wrap:wrap; }
.hdlchip .hdllab { font-size:10.5px; font-weight:800; letter-spacing:.6px; color:var(--soft2); text-transform:uppercase; }
.hdlchip b { color:var(--navy); font-size:14px; }
.hdlchip .btn.sm { margin-left:auto; }

/* Le Club — groupes d'amis (créer / rejoindre / demandes) */
.grp-actions { display:flex; gap:8px; padding:12px; margin-top:4px;
  border-top:1px solid var(--brd2); }
.grp-actions .btn.sm { flex:1; justify-content:center; }
/* badge « X demandes » sur un groupe que j'ai créé */
.rn.rn-dem { display:inline-flex; align-items:center; justify-content:center;
  min-width:22px; height:22px; padding:0 6px; border:none; border-radius:11px;
  background:var(--crimson); color:#fff; font-size:12px; font-weight:800;
  cursor:pointer; box-shadow:0 1px 4px rgba(192,9,58,.4); }
.rn.rn-dem:hover { filter:brightness(1.08); }
/* le code d'invitation à copier */
.grp-code { margin:6px 0 4px; padding:16px; border:2px dashed var(--brd);
  border-radius:14px; text-align:center; font-size:30px; font-weight:800;
  letter-spacing:5px; color:var(--navy); cursor:pointer; user-select:all;
  position:relative; background:var(--c1-faible,rgba(27,74,133,.05)); }
.grp-code span { position:absolute; top:8px; right:10px; font-size:11px;
  font-weight:700; letter-spacing:.4px; color:var(--soft); }
.grp-code:hover { border-color:var(--navy); }
/* une demande dans le panneau du créateur */
.grp-dem { display:flex; align-items:center; gap:10px; padding:10px 0;
  border-top:1px solid var(--brd2); }
.grp-dem:first-child { border-top:none; }
.grp-dem-nom { display:flex; flex-direction:column; gap:2px; flex:1; min-width:0; }
.grp-dem-nom b { color:var(--navy); font-size:14px; }
.grp-dem-nom span { font-size:12px; color:var(--soft); }
.grp-dem-act { display:flex; gap:6px; flex-shrink:0; }
.grp-dem-oui, .grp-dem-non { border:none; border-radius:9px; padding:8px 12px;
  font-size:13px; font-weight:700; cursor:pointer; }
.grp-dem-oui { background:var(--navy); color:#fff; }
.grp-dem-non { background:transparent; color:var(--crimson); border:1.5px solid var(--brd); }
.grp-dem-non:hover { border-color:var(--crimson); }
