/* =========================================================================
   rotatestudy · systeme de design · composants
   Mesures reprises de la planche B « Objet » v2 (docs/refonte-2026-10/planches/B-objet/v2/), sur les jetons.
   Liste fermee : deux boutons, deux portes, ligne et bande de matiere, formules, panneau de question, onglets,
   champs, deux badges, encadre, fil d'Ariane, barre de navigation, menu telephone, barre d'achat, livre-piste,
   avion RS-1. Rien d'autre sans passer par design.html.
   Regles : un rayon par famille (papier 3, ecran 22, surfaces 28, actions pilule) ; une seule ombre
   (--shadow-lift, objets qui se levent) ; une lumiere en haut a gauche (--hi, liseré du bord haut) ;
   au survol les boutons changent de ton, jamais de taille ; pas de barre coloree a gauche.
   ========================================================================= */

/* ---- 1. Boutons : plein (l'action) et contour (l'action secondaire), en pilule ----
   <a class="btn" href="…">Get the pack</a>   <button class="btn ghost" type="button">Login</button>
   .btn.sm : version courte (barre de navigation, barre d'achat).
   Desactive : visiblement inerte (opacite reduite), le survol ne change rien.
   Exception : un bouton d'achat (button[data-achat]) est livre disabled seulement en attendant qu'achat.js l'active ;
   il garde son aspect normal (curseur par defaut, pas de survol). Il ne devient inerte qu'avec la classe .inert
   (posee par achat.js quand la vente est fermee ou la cle sans prix, tache 12). */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--sp1);min-height:48px;padding:0 var(--sp3);
  border:0;border-radius:var(--r-pill);background:var(--blue);color:var(--on-blue);
  font:600 var(--s2)/1 var(--fd);letter-spacing:-.01em;white-space:nowrap;text-decoration:none;cursor:pointer;
  transition:background-color var(--t-hover) var(--ease),color var(--t-hover) var(--ease),box-shadow var(--t-hover) var(--ease)}
.btn:not(:disabled):not(.inert):hover{background:var(--blue-hover)}
.btn:disabled{cursor:default}
.btn:disabled:not([data-achat]),.btn[data-achat].inert{cursor:default;opacity:.45}
.btn.ghost{background:transparent;color:var(--ink);box-shadow:inset 0 0 0 1px var(--line)}
.btn.ghost:not(:disabled):not(.inert):hover{background:var(--surface-2);box-shadow:inset 0 0 0 1px var(--dim)}
.btn.sm{min-height:40px;padding:0 var(--sp2);font-size:var(--s1)}

/* Bascule de theme : un rond a moitie plein, meme place sur toutes les pages (theme.js ecoute .theme-btn). */
.theme-btn{display:grid;place-items:center;width:40px;height:40px;flex:none;padding:0;border:0;border-radius:var(--r-pill);
  background:transparent;color:var(--dim);cursor:pointer;
  transition:background-color var(--t-hover) var(--ease),color var(--t-hover) var(--ease)}
.theme-btn:hover{color:var(--ink);background:var(--surface-2)}
.theme-btn svg{width:18px;height:18px}

/* ---- 2. Barre de navigation ----
   <header class="nav"><div class="wrap nav-in">
     <a class="brand" href="/"><svg …/><span>rotate<span>study</span></span></a>
     <nav class="nav-links">…</nav> <button class="theme-btn">…</button>
     <a class="btn ghost sm login" href="/account">Login</a> <a class="btn sm" href="notes.html#buy">Get the pack</a>
     <details class="mnav">…</details>
   </div></header>
   Le flou est porte par ::before : un backdrop-filter sur .nav elle-meme enfermerait le menu telephone (fixe). */
.nav{position:sticky;top:0;z-index:30;isolation:isolate;border-bottom:1px solid var(--line)}
.nav::before{content:"";position:absolute;inset:0;z-index:-1;background:var(--nav-bg);
  -webkit-backdrop-filter:saturate(1.6) blur(18px);backdrop-filter:saturate(1.6) blur(18px)}
.nav-in{display:flex;align-items:center;gap:var(--sp2);height:var(--nav-h)}
.brand{display:inline-flex;align-items:center;gap:var(--sp1);flex:none;color:var(--ink);
  font:700 var(--s2)/1 var(--fd);letter-spacing:-.02em;text-decoration:none}
.brand>span>span{color:var(--blue)}
.brand svg{width:20px;height:20px;flex:none}
.nav-links{display:flex;gap:var(--sp3);margin:0 var(--sp1) 0 auto}
.nav-links a{color:var(--dim);font-size:var(--s1);white-space:nowrap;text-decoration:none}
.nav-links a:hover,.nav-links a[aria-current="page"]{color:var(--ink)}
@media (max-width:1024px){.nav-links{gap:var(--sp2)}}
/* En dessous de 960 px les liens ne tiennent plus sur une ligne : le menu telephone prend le relais. */
@media (max-width:960px){
  .nav-links{display:none}
  .nav .theme-btn{margin-left:auto}
}
@media (max-width:480px){.nav .btn:not(.ghost){display:none}}
/* 320 px : marque, bascule, Login et menu ne tiennent qu'avec un ecart de 8 (revue de la tache 4). */
@media (max-width:359px){.nav-in{gap:var(--sp1)}}

/* ---- 3. Menu telephone : un <details>, sans script ----
   <details class="mnav"><summary aria-label="Menu"><i></i><i></i></summary>
     <nav class="mnav-panel"><a href="notes.html">Notes</a>…</nav></details> */
.mnav{display:none}
.mnav>summary{display:grid;place-content:center;gap:var(--sp1);width:40px;height:40px;border-radius:var(--r-pill);
  list-style:none;cursor:pointer;color:var(--ink)}
.mnav>summary::-webkit-details-marker{display:none}
.mnav>summary i{display:block;width:18px;height:1.5px;background:currentColor;transition:transform var(--t-hover) var(--ease)}
.mnav[open]>summary i:first-child{transform:translateY(4.75px) rotate(45deg)}
.mnav[open]>summary i:last-child{transform:translateY(-4.75px) rotate(-45deg)}
.mnav-panel{display:flex;flex-direction:column;padding:var(--sp2) var(--pad) var(--sp5);background:var(--bg)}
.mnav-panel a:not(.btn){display:block;padding:var(--sp2) 0;border-bottom:1px solid var(--line);color:var(--ink);
  font:600 var(--s4)/1.2 var(--fd);letter-spacing:-.02em;text-decoration:none}
.mnav-panel .btn{margin-top:var(--sp3);align-self:flex-start}
@media (max-width:960px){
  .mnav{display:block}
  .mnav-panel{position:fixed;left:0;right:0;top:var(--nav-h);bottom:0;z-index:29;overflow-y:auto}
}

/* ---- 4. Fil d'Ariane : <nav class="crumbs" aria-label="Breadcrumb"><ol><li><a href="/">Home</a></li>
   <li aria-hidden="true">›</li><li><a href="../subjects.html">Subjects</a></li><li aria-hidden="true">›</li>
   <li aria-current="page">062</li></ol></nav> (separateurs dans le balisage, caches aux lecteurs d'ecran) */
.crumbs{font-size:var(--s1);color:var(--dim)}
.crumbs ol{display:flex;flex-wrap:wrap;gap:var(--sp1);margin:0;padding:0;list-style:none}
.crumbs a{color:var(--dim);text-decoration:none}
.crumbs a:hover{color:var(--ink)}
.crumbs [aria-current]{color:var(--ink)}

/* ---- 5. Portes : les deux entrees egales de l'accueil (« I revise », « I practise »), aux memes places partout ----
   <div class="doors"><a class="door" href="notes.html"><div class="door-obj" aria-hidden="true">…</div>
     <h2 class="door-title">I revise</h2><p class="door-text">…</p>
     <div class="door-foot"><p class="door-price num">€79<small>the pack, all thirteen</small></p>
     <span class="btn">Open the notes</span></div></a> …</div>
   Toute la porte est le lien (cible enorme au pouce) ; son bouton n'est qu'un repere visuel. */
.doors{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--gap)}
.door{position:relative;display:flex;flex-direction:column;overflow:hidden;padding:0 var(--sp4) var(--sp4);
  border-radius:var(--r-surface);background:var(--surface);color:var(--ink);text-decoration:none;
  box-shadow:inset 0 1px 0 var(--hi),0 0 0 1px var(--line);transition:box-shadow var(--t-hover) var(--ease)}
a.door:hover{box-shadow:inset 0 1px 0 var(--hi),0 0 0 1px var(--dim)}
a.door .btn{pointer-events:none}
a.door:hover .btn{background:var(--blue-hover)}
.door-obj{position:relative;height:232px;display:grid;place-items:center;perspective:1100px}
.door-title{font-size:var(--s4);line-height:1.15;letter-spacing:-.03em}
.door-text{max-width:27em;margin-top:var(--sp1);color:var(--dim)}
.door-foot{display:flex;align-items:center;justify-content:space-between;gap:var(--sp2);margin-top:auto;padding-top:var(--sp3)}
.door-price{font:600 var(--s2)/1.3 var(--fd);letter-spacing:-.01em;color:var(--ink)}
.door-price small{display:block;font:400 var(--s1)/1.4 var(--fb);letter-spacing:0;color:var(--dim);white-space:nowrap}
@media (max-width:760px){
  .doors{gap:var(--sp1)}
  .door{padding:0 var(--sp2) var(--sp2)}
  .door-obj{height:176px}
  .door-text{display:none}
  .door-foot{flex-direction:column;align-items:stretch;gap:var(--sp2);padding-top:var(--sp2)}
  .door .btn{min-height:40px;padding:0 var(--sp1);font-size:var(--s1)}
}

/* ---- 6. Matieres. Les cellules sont communes a la ligne et a la bande :
   <span class="code">062</span><span class="name">Radio Navigation</span>
   <span class="pages">31<small> pages</small></span><span class="qs">512<small> questions</small></span>
   <span class="price">€11.90</span>   (unites toujours visibles : jamais deux nombres nus cote a cote) */
:is(.subject-row,.subject-band) :is(.code,.pages,.qs,.price){font-variant-numeric:tabular-nums}
:is(.subject-row,.subject-band) .code{font-family:var(--fd);font-weight:600;font-size:var(--s1);color:var(--dim)}
:is(.subject-row,.subject-band) .name{font:600 var(--s2)/1.25 var(--fd);letter-spacing:-.015em;color:var(--ink);
  transition:color var(--t-hover) var(--ease)}
:is(.subject-row,.subject-band) :is(.pages,.qs){text-align:right;font-size:var(--s1);color:var(--dim)}
:is(.subject-row,.subject-band) .price{text-align:right;font:600 var(--s2)/1.25 var(--fd);color:var(--ink)}
:is(.subject-row,.subject-band) small{font-size:inherit;color:inherit}
:is(.subject-row,.subject-band):hover .name{color:var(--blue-ink)}

/* 6a. Ligne de matiere : une etape de la route GPS. Sa hauteur suit le nombre de pages (--p, 1,75 px par page,
   2,1 sur telephone) ; .wp est la balise, remplie (.wp::after) quand l'avion l'a survolee (motion.css). */
.subject-row{--f:1.75px;position:relative;display:grid;align-items:start;
  grid-template-columns:48px 64px minmax(0,1fr) 96px 128px 88px;column-gap:var(--sp2);
  min-height:calc(var(--p,24) * var(--f));padding-top:4px;color:var(--ink);text-decoration:none}
.subject-row>*{line-height:21px}
.subject-row .code{grid-column:2}
.wp{position:absolute;left:24px;top:14.5px;width:9px;height:9px;margin:-4.5px 0 0 -4.5px;rotate:45deg;
  border:1.5px solid var(--dim);background:var(--bg);transition:background-color var(--t-hover) var(--ease),border-color var(--t-hover) var(--ease)}
.subject-row:hover .wp{border-color:var(--blue)}
@media (max-width:760px){
  .subject-row{--f:2.1px;grid-template-columns:32px 40px minmax(0,1fr) auto;grid-template-rows:auto auto;align-content:start;column-gap:var(--sp1)}
  .subject-row .code{grid-column:2;grid-row:1}
  .subject-row .name{grid-column:3;grid-row:1;font-size:var(--s2);line-height:20px}
  .subject-row .price{grid-column:4;grid-row:1}
  .subject-row :is(.pages,.qs){grid-row:2;line-height:18px}
  .subject-row .pages{grid-column:3;justify-self:start;text-align:left}
  .subject-row .qs{grid-column:3/5;justify-self:end}
  .wp{left:20px}
}
/* Tres petits ecrans (320) : plus de colonne des pages (la longueur de l'etape la dit), le prix passe sous le nom, a cote
   des questions : le nom garde toute la ligne. */
@media (max-width:359px){
  .subject-row .pages{display:none}
  .subject-row .name{grid-column:3/5}
  .subject-row .price{grid-row:2;grid-column:4;line-height:18px}
  .subject-row .qs{grid-column:3;justify-self:start;text-align:left}
}

/* 6b. Bande de matiere : la pile a l'echelle, chaque bande a l'epaisseur de sa matiere (--p pages). */
.subject-band{display:grid;align-items:center;grid-template-columns:80px minmax(0,1fr) 96px 128px 88px;column-gap:var(--sp2);
  height:calc(44px + (var(--p,23) - 23) * 1.55px);padding:0 var(--sp3);border-radius:var(--r-paper);
  background:var(--surface);color:var(--ink);text-decoration:none;box-shadow:inset 0 1px 0 var(--hi),0 0 0 1px var(--line);
  transition:background-color var(--t-hover) var(--ease)}
.subject-band:hover{background:var(--surface-2)}
@media (max-width:760px){
  .subject-band{grid-template-columns:40px minmax(0,1fr) auto;padding:0 var(--sp2)}
  .subject-band :is(.pages,.qs){display:none}
}

/* ---- 7. Formules de la banque : un seul objet, quatre colonnes (deux sur iPad et telephone) ----
   <ul class="plans"><li class="plan"><p class="plan-len">6 months</p><p class="plan-price num">€129</p>
     <p class="plan-per num">€21.50 a month</p><button class="btn" data-achat="banque:6" disabled>Get 6 months</button></li>…</ul>
   Pas de quatre cartes : une seule surface, des filets entre les colonnes, aucune formule « mise en avant ». */
.plans{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));margin:0;padding:0;list-style:none;overflow:hidden;
  border-radius:var(--r-surface);background:var(--surface);box-shadow:inset 0 1px 0 var(--hi),0 0 0 1px var(--line)}
.plan{display:flex;flex-direction:column;padding:var(--sp4) var(--sp3) var(--sp3)}
.plan+.plan{border-left:1px solid var(--line)}
.plan-len{font:600 var(--s2)/1.3 var(--fd);letter-spacing:-.01em;color:var(--ink)}
.plan-price{margin-top:var(--sp3);font:600 var(--s4)/1 var(--fd);letter-spacing:-.025em;color:var(--ink)}
.plan-per{margin:var(--sp1) 0 var(--sp4);font-size:var(--s1);color:var(--dim);white-space:nowrap}
.plan .btn{margin-top:auto;align-self:flex-start}
@media (max-width:1024px){
  .plans{grid-template-columns:repeat(2,minmax(0,1fr))}
  .plan:nth-child(3){border-left:0}
  .plan:nth-child(n+3){border-top:1px solid var(--line)}
}
@media (max-width:760px){
  .plan{padding:var(--sp3) var(--sp2) var(--sp2)}
  .plan .btn{align-self:stretch;padding:0 var(--sp1)}
}

/* ---- 8. Panneau de question : l'ecran d'entrainement, vrai composant ----
   Habille le balisage de l'essai gratuit (gen_subjects.essai_html + ESSAI_JS) sans y toucher :
   <div class="qpanel"><p class="qp-bar"><b>031 Mass &amp; Balance</b><span class="num">4 / 10</span></p>
     <ol class="qfree"><li class="qf" data-c="2"><p class="qf-q"><span class="qf-n">4</span><span>…</span></p>
     <ol class="qf-r" type="A"><li><button type="button" data-i="0">…</button></li>…</ol>
     <details class="qf-e"><summary>Show the answer</summary><p><b>Answer C.</b> …</p></details></li></ol></div>
   ESSAI_JS pose .fait sur la question, .ok sur la bonne reponse (anneau vert, « Correct » : ce qu'on retient) et .ko
   sur la reponse choisie si elle est fausse (anneau orange, « Wrong »). Les classes .ok/.ko sont le contrat d'ESSAI_JS.
   « Remember » et « Exam trap » restent les deux badges du texte d'explication. */
.qpanel{padding:var(--sp2) var(--sp3) var(--sp3);border-radius:var(--r-screen);background:var(--surface);
  box-shadow:inset 0 1px 0 var(--hi),0 0 0 1px var(--line),var(--shadow-lift)}
.qp-bar{display:flex;justify-content:space-between;gap:var(--sp2);padding:0 0 var(--sp2);border-bottom:1px solid var(--line);
  font:500 var(--s1)/1.3 var(--fb);color:var(--dim)}
.qp-bar b{font-weight:500;color:var(--ink)}
.qfree{display:grid;gap:var(--sp5);margin:0;padding:0;list-style:none}
.qf{list-style:none}
.qf-q{display:flex;gap:var(--sp2);margin:var(--sp2) 0;font:500 var(--s2)/1.5 var(--fb);color:var(--ink)}
.qf-n{min-width:1.5em;padding-top:.2em;font:600 var(--s1)/1.5 var(--fd);color:var(--dim);font-variant-numeric:tabular-nums}
.qf-r{display:grid;gap:var(--sp1);margin:0;padding:0;list-style:none;counter-reset:qf}
.qf-r li{counter-increment:qf}
.qf-r button{display:grid;grid-template-columns:24px minmax(0,1fr) auto;align-items:center;gap:var(--sp2);width:100%;min-height:48px;
  padding:12px var(--sp2);border:0;border-radius:var(--r-screen);background:var(--surface-2);color:var(--ink);text-align:left;
  font:500 var(--s2)/1.35 var(--fb);cursor:pointer;box-shadow:inset 0 0 0 1.5px transparent;
  transition:box-shadow var(--t-hover) var(--ease),opacity var(--t-text) var(--ease)}
.qf-r button::before{content:counter(qf,upper-alpha);font:600 var(--s1)/1 var(--fd);color:var(--dim)}
.qf-r button::after{font:600 var(--s1)/1 var(--fd)}
.qf-r button:not(:disabled):hover{box-shadow:inset 0 0 0 1.5px var(--dim)}
.qf-r button:disabled{cursor:default}
.qf-r button.ok{box-shadow:inset 0 0 0 1.5px var(--green-ink)}
.qf-r button.ok::after{content:"Correct";color:var(--green-ink)}
.qf-r button.ko{box-shadow:inset 0 0 0 1.5px var(--orange-ink)}
.qf-r button.ko::after{content:"Wrong";color:var(--orange-ink)}
.qf.fait .qf-r button:not(.ok):not(.ko){opacity:.55}
.qf-e{margin-top:var(--sp2)}
.qf-e>summary{display:inline-flex;list-style:none;cursor:pointer;color:var(--blue-ink);font:500 var(--s1)/1.4 var(--fb)}
.qf-e>summary::-webkit-details-marker{display:none}
.qf.fait .qf-e>summary{display:none}
.qf-e p{margin-top:var(--sp2);padding-top:var(--sp2);border-top:1px solid var(--line);font-size:var(--s1);line-height:1.6;color:var(--dim)}
.qf-e b{color:var(--ink)}
@media (max-width:760px){
  .qpanel{padding:var(--sp2) var(--sp2) var(--sp3)}
  .qf-r button{padding:12px}
}

/* ---- 9. Onglets : role="tablist", l'onglet choisi porte aria-selected="true" (ou aria-current="page" pour des liens) ----
   Explanation / Comments / Improve dans le quiz, Questions / Notes dans l'espace client. */
.tabs{display:inline-flex;gap:4px;padding:4px;border-radius:var(--r-pill);background:var(--surface-2);box-shadow:inset 0 0 0 1px var(--line)}
.tabs>:is(a,button){display:inline-flex;align-items:center;min-height:40px;padding:0 var(--sp2);border:0;border-radius:var(--r-pill);
  background:transparent;color:var(--dim);font:600 var(--s1)/1 var(--fd);text-decoration:none;cursor:pointer;
  transition:background-color var(--t-hover) var(--ease),color var(--t-hover) var(--ease)}
.tabs>:is(a,button):hover{color:var(--ink)}
.tabs>:is([aria-selected="true"],[aria-current="page"]){background:var(--surface);color:var(--ink);box-shadow:0 0 0 1px var(--line)}

/* ---- 10. Champs : libelle au-dessus, aide et message en dessous, jamais de texte d'exemple comme libelle ----
   <div class="field"><label for="u">Username</label><input id="u" aria-describedby="u-h"><p class="field-hint" id="u-h">…</p></div>
   Une ligne = pilule ; plusieurs lignes = rayon d'ecran. Contour --line-strong (3:1), focus --focus.
   Erreur : aria-invalid="true" + .field-msg, un filet et un texte orange sous le champ, jamais un anneau (le focus
   en est un) ; pas de rouge. */
.field{display:grid;gap:var(--sp1)}
.field>label{font:500 var(--s1)/1.3 var(--fb);color:var(--ink)}
.field :is(input,select,textarea){width:100%;min-height:48px;padding:0 var(--sp2);border:0;border-radius:var(--r-pill);
  background:var(--surface);color:var(--ink);font:400 var(--s2)/1.4 var(--fb);box-shadow:inset 0 0 0 1px var(--line-strong);
  transition:box-shadow var(--t-hover) var(--ease)}
.field textarea{min-height:128px;padding:12px var(--sp2);border-radius:var(--r-screen);resize:vertical}
.field :is(input,select,textarea):hover{box-shadow:inset 0 0 0 1px var(--ink)}
.field :is(input,select,textarea):focus-visible{outline:2px solid var(--focus);outline-offset:2px;box-shadow:inset 0 0 0 1px var(--focus)}
.field ::placeholder{color:var(--dim);opacity:1}
.field-hint{font-size:var(--s1);color:var(--dim)}
.field-msg{padding-top:var(--sp1);border-top:2px solid var(--orange-ink);font:500 var(--s1)/1.4 var(--fb);color:var(--orange-ink)}

/* ---- 11. Badges : les deux sens des accents, et seulement eux, dans le texte d'explication ----
   Libelle discret en couleur, petite taille, sans boite ni pilule : <span class="badge-trap">Exam trap</span> */
.badge-remember,.badge-trap{display:inline-flex;align-items:center;font:600 var(--s1)/1 var(--fd);letter-spacing:-.005em;white-space:nowrap}
.badge-remember{color:var(--green-ink)}
.badge-trap{color:var(--orange-ink)}

/* ---- 12. Encadre : un filet fin au-dessus et un libelle. Remplace toute boite a barre coloree a gauche (bannie). ----
   <div class="note"><p class="note-label">Verification</p><p>…</p></div>
   .note.remember (vert, a retenir) et .note.trap (orange, piege d'examen) : le filet et le libelle prennent la couleur. */
.note{padding-top:var(--sp2);border-top:1px solid var(--line)}
.note-label{margin-bottom:var(--sp1);font:600 var(--s1)/1.3 var(--fd);letter-spacing:-.005em;color:var(--ink)}
.note>p:not(.note-label){color:var(--dim)}
.note.remember{border-top-color:var(--green-ink)}
.note.remember .note-label{color:var(--green-ink)}
.note.trap{border-top-color:var(--orange-ink)}
.note.trap .note-label{color:var(--orange-ink)}

/* ---- 13. Barre d'achat basse (telephone seulement) ----
   <div class="buybar"><span><b>€79</b> All 13 subjects</span><a class="btn sm" href="#buy">Get the pack</a></div>
   achat.js pose .cache tant qu'un bouton d'achat de la page est a l'ecran. */
.buybar{position:relative;display:none;align-items:center;justify-content:space-between;gap:var(--sp2);
  padding:12px var(--pad) calc(12px + env(safe-area-inset-bottom));isolation:isolate;border-top:1px solid var(--line)}
.buybar::before{content:"";position:absolute;inset:0;z-index:-1;background:var(--nav-bg);
  -webkit-backdrop-filter:saturate(1.6) blur(18px);backdrop-filter:saturate(1.6) blur(18px)}
.buybar>span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--s1);color:var(--dim)}
.buybar b{margin-right:var(--sp1);font:600 var(--s3)/1 var(--fd);color:var(--ink);font-variant-numeric:tabular-nums}
.buybar .btn{flex:none}
@media (max-width:760px){
  .buybar{display:flex;position:fixed;left:0;right:0;bottom:0;z-index:40;transition:transform var(--t-text) var(--ease)}
  .buybar.cache{transform:translateY(110%)}
  body:has(.buybar){padding-bottom:72px}
}

/* ---- 14. Livre-piste : le livre du logo (img/favicon.svg) en traits fins, devenu piste ----
   <div class="runway-book" aria-hidden="true"><i></i><i></i><i></i></div>
   Memes cotes que le logo (dos arrondi, trois lignes de pages, retraits) a l'echelle --rb ; couverture 1,5 px,
   pages 1 px (le rapport epais/fin du logo). Gris, pas bleu : le bleu reste a ce qu'on peut toucher. */
.runway-book{--rb:.2;position:relative;height:calc(170px * var(--rb));pointer-events:none}
.runway-book::before{content:"";position:absolute;inset:0;border:1.5px solid var(--runway);border-right:0;
  border-radius:var(--r-pill) 0 0 var(--r-pill)}
.runway-book i{position:absolute;right:calc(30.6px * var(--rb));height:1px;margin-top:-.5px;background:var(--runway)}
.runway-book i:nth-child(1){top:calc(46px * var(--rb));left:calc(72.4px * var(--rb))}
.runway-book i:nth-child(2){top:calc(85px * var(--rb));left:calc(53.1px * var(--rb))}
.runway-book i:nth-child(3){top:calc(124px * var(--rb));left:calc(72.4px * var(--rb))}
@media (max-width:760px){.runway-book{--rb:.14}}

/* ---- 15. Avion RS-1 : toujours un fichier de la bibliotheque, jamais redessine ----
   Toile carree de la bibliotheque, pivot au centre : point bas du train principal de profil (le meme train rentre),
   centre de gravite vu de dessus. left / top de .rs1 designent le pivot (le bloc se centre dessus).
   --rs1-u : px par unite de l'avion (decollage et atterrissage 10 px, 8 sur telephone ; rotation 24, 9 sur telephone).
   Les attitudes tournent le dessin a plat (profil p00, dessus c000) autour du pivot avec la propriete rotate :
   transform reste libre pour le mouvement. Ne pas les combiner avec les fichiers deja tournes (p12, p15).
   Le train est un groupe .gear : seul lui s'efface a la rentree, jamais la cellule.
   La couleur vient du theme (--plane : Cockpit en sombre, Carte en clair), le SVG peint en currentColor.
   background:none sur les attitudes : l'ancien .rs1 de site.css (avion en masque CSS : .p12, .p00, .c000, .face, retire
   a la tache 13) peint son fond, qui ferait un carre derriere le SVG. */
.rs1{--rs1-u:10px;--rs1-span:20.2087;--rs1-size:calc(var(--rs1-u) * var(--rs1-span));
  position:absolute;left:0;top:0;width:var(--rs1-size);height:var(--rs1-size);
  margin:calc(var(--rs1-size) / -2) 0 0 calc(var(--rs1-size) / -2);
  color:var(--plane);transform-origin:50% 50%;pointer-events:none}
.rs1>svg,.rs1>img{position:absolute;inset:0;width:100%;height:100%}
:is(.rs1.ground,.rs1.rotate,.rs1.climb,.rs1.approach,.rs1.top){background:none}
.rs1.ground{rotate:0deg}
.rs1.rotate{rotate:-12deg}
.rs1.climb{rotate:-15deg}
.rs1.approach{rotate:-3deg}
.rs1.top{--rs1-span:20.3077;rotate:var(--hdg,0deg)}
.rs1 .gear{transition:opacity var(--t-object) var(--ease),translate var(--t-object) var(--ease)}
.rs1.climb .gear{opacity:0;translate:0 -8px}

/* ---- 16. Accueil, premier ecran : la phrase, le decollage, les deux portes (planche B v2) ----
   <section class="hero home" id="hero"><div class="wrap">
     <h1><span class="l">Thirteen subjects.</span><span class="l">One standard.</span></h1><p class="lead">…</p>
     <div class="takeoff" aria-hidden="true"><div class="runway-book">…</div><span class="rs1 ground"><svg>…</svg></span></div>
     <div class="doors cta"><a class="door" …><div class="door-obj" aria-hidden="true"><div class="door-pages">3 <img></div></div>…</a>
       <a class="door" …><div class="door-obj" aria-hidden="true"><div class="door-screen qpanel">…<ol class="door-ans">…</ol></div></div>…</a></div>
   </div></section>
   .hero .cta reste la cible d'achat.js (la barre d'achat se cache tant que les portes sont a l'ecran). .home passe devant
   les anciennes regles .hero et .cta de site.css (meme poids, chargee apres). Le h1 est la au premier rendu. */
.home{padding:var(--sp4) 0 0;text-align:center;overflow-x:clip}
.home h1{font-size:var(--s6);line-height:1.02;letter-spacing:-.04em}
.home h1 .l{display:block;white-space:nowrap}
.home .lead{max-width:31em;margin:var(--sp2) auto 0}
.home .doors{align-items:stretch;margin-top:var(--sp3);text-align:left}
/* Le decollage : le RS-1 aligne contre le dos du livre, le train principal (le pivot) pose sur la couverture.
   --sky : le ciel au-dessus du livre, ou l'avion se tient. --range : longueur du geste au defilement (motion.css
   et motion.js la lisent ici). Les autres variables placent les etapes (en part de la largeur de la scene, cqw) :
   --xr1 debut de la rotation, --xr2 rotation a 12 degres, --xl envol, --gam pente de montee (plus faible que
   l'assiette, comme en vrai), --exit sortie hors de l'ecran a droite. */
.takeoff{--sky:48px;--range:250px;position:relative;container-type:inline-size;padding-top:var(--sky);text-align:left}
.takeoff .rs1{--x0:calc(17px + var(--rs1-size) * .389 + 8px);--xr1:.40;--xr2:.50;--xl:.56;--gam:.105;
  --exit:calc(50vw + 50cqw + var(--rs1-size) * .5);left:var(--x0);top:var(--sky);z-index:2}
/* Porte « I revise » : trois pages du PDF, posees en pile sur la table ; elles se levent un peu au survol. */
.door-pages{--k:.78;position:relative;width:196px;aspect-ratio:794/1123;translate:-8px -40px;scale:var(--k);transform:rotateX(38deg) rotateZ(-14deg);
  transform-style:preserve-3d;transition:transform var(--t-object) var(--ease)}
.door-pages img{position:absolute;inset:0;width:100%;height:100%;border-radius:var(--r-paper);box-shadow:var(--shadow-lift),0 0 0 1px var(--line)}
.door-pages img:nth-child(1){transform:translate3d(26px,16px,-2px) rotate(7deg)}
.door-pages img:nth-child(2){transform:translate3d(12px,7px,-1px) rotate(3.5deg)}
a.door:hover .door-pages{transform:rotateX(34deg) rotateZ(-12deg) translateY(-8px)}
/* Porte « I practise » : l'ecran d'entrainement (.qpanel) en reduction, la bonne reponse entouree de vert. */
.door-screen{--k:.56;position:absolute;left:50%;top:50%;width:480px;translate:-50% -50%;scale:var(--k);text-align:left;
  transform:rotateX(14deg);transition:transform var(--t-object) var(--ease)}
a.door:hover .door-screen{transform:rotateX(8deg) translateY(-8px)}
.door-ans{display:grid;gap:var(--sp1);margin:0;padding:0;list-style:none;counter-reset:qf}
.door-ans li{display:grid;grid-template-columns:24px minmax(0,1fr) auto;align-items:center;gap:var(--sp2);min-height:40px;
  padding:0 var(--sp2);border-radius:var(--r-screen);background:var(--surface-2);font:500 var(--s2)/1.35 var(--fb);counter-increment:qf}
.door-ans li::before{content:counter(qf,upper-alpha);font:600 var(--s1)/1 var(--fd);color:var(--dim)}
.door-ans .ok{box-shadow:inset 0 0 0 1.5px var(--green-ink)}
.door-ans .ok::after{content:"Correct";font:600 var(--s1)/1 var(--fd);color:var(--green-ink)}
@media (max-width:760px){
  .takeoff{--range:180px}
  .takeoff .rs1{--rs1-u:8px;--x0:calc(11.9px + var(--rs1-size) * .389 + 8px);--xr1:.55;--xr2:.66;--xl:.72}
  .door-pages{--k:.42;translate:-24px -56px}
  .home .door-price small{min-height:2.8em;white-space:normal}
  .door-screen{--k:.3}
}

/* ---- 17. Accueil : les pages qui se levent (#look), puis la question gratuite (#try) (planche B v2) ----
   <section class="look" id="look"><div class="wrap"><h2>…</h2><p class="lead">…</p>
     <div class="fan-stage"><div class="fan">
       <figure class="sheet s1 lift"><img …></figure><figure class="sheet s3 lift"><img …></figure>
       <figure class="sheet s2 lift"><img …><span class="socket p-head" data-theme="dark"></span>…<span class="part p-head" data-theme="dark"></span>…</figure>
     </div><ul class="callouts"><li class="c-head"><b>The chapter</b>…</li><li class="c-table">…</li></ul></div>
     <p class="legend">…<span class="small">…</span></p></div></section>
   <section class="try" id="try"><div class="wrap"><div class="tr-txt">…</div><div class="tr-dev lift"><div class="qpanel">…</div></div></div></section>
   La pose finale (l'eventail ouvert) est portee par translate et rotate, jamais par transform : le geste de motion.css
   (.lift, fan-s1 a fan-s3) passe par transform et les proprietes individuelles, et « reduire les animations »
   (.lift{transform:none}) laisse les pages ouvertes. La page de devant livre deux pieces (.part), decoupees dans
   img/en-1.webp aux places du titre et du tableau (--x --y --w --h, en part de la page), soulevees de --z ; dessous,
   leur empreinte (.socket). Pieces et empreintes sont du papier sombre dans les deux themes (data-theme="dark"). */
.look,.try{padding:var(--section) 0 0}
.look{overflow-x:clip}
.look .lead,.try .lead{margin-top:var(--sp2)}
.fan-stage{position:relative;height:620px;margin-top:var(--sp5);perspective:1700px;perspective-origin:45% 30%}
.fan{--sw:320px;position:absolute;left:42%;top:var(--sp5);width:var(--sw);aspect-ratio:794/1123;margin-left:calc(var(--sw) / -2);
  transform-style:preserve-3d}
.sheet{position:absolute;inset:0;margin:0;border-radius:var(--r-paper);transform-style:preserve-3d;
  box-shadow:var(--shadow-lift),0 0 0 1px var(--line)}
.sheet img{width:100%;height:100%;border-radius:var(--r-paper)}
.fan .s1{translate:-68% 3% -80px;rotate:-7deg}
.fan .s3{translate:68% 3% -80px;rotate:7deg}
.fan .s2{rotate:y -15deg}
/* Les pages de cote restent derriere, dans l'ombre de celle de devant. */
.fan .s1 img,.fan .s3 img{filter:brightness(.6)}
[data-theme="light"] .fan .s1 img,[data-theme="light"] .fan .s3 img{filter:brightness(.85)}
.socket,.part{position:absolute;left:calc(var(--x) * 100%);top:calc(var(--y) * 100%);width:calc(var(--w) * 100%);
  height:calc(var(--h) * 100%);border-radius:var(--r-paper)}
.socket{background:var(--surface);box-shadow:inset 0 0 0 1px var(--line)}
.part{background:var(--surface) url(../img/en-1.webp?v=aac33450b2) no-repeat;background-size:calc(100% / var(--w)) calc(100% / var(--h));
  background-position:calc(var(--x) / (1 - var(--w)) * 100%) calc(var(--y) / (1 - var(--h)) * 100%);
  box-shadow:var(--shadow-lift);transform:translateZ(var(--z))}
.p-head{--x:.066;--y:.042;--w:.62;--h:.118;--z:46px}
.p-table{--x:.066;--y:.434;--w:.866;--h:.384;--z:30px}
.callouts{margin:0;padding:0;list-style:none}
.callouts li{position:absolute;left:79%;width:21%;padding-left:var(--sp3);font-size:var(--s1);line-height:1.5;color:var(--dim)}
.callouts li::before{content:"";position:absolute;left:0;top:.75em;width:12px;height:1px;background:var(--line-strong)}
.callouts b{display:block;margin-bottom:4px;font:600 var(--s2)/1.3 var(--fd);letter-spacing:-.015em;color:var(--ink)}
.c-head{top:var(--sp7)}
.c-table{top:340px}
.legend{max-width:none;margin-top:var(--sp4);text-align:center;font-size:var(--s3);line-height:1.45;color:var(--dim)}
.legend .small{display:block;margin-top:var(--sp1)}
/* La question : le texte a gauche, le panneau jouable a droite (6 colonnes), qui se leve de la table. */
.try .wrap{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));column-gap:var(--gap);align-items:start}
.tr-txt{grid-column:1/span 6}
.tr-txt .small{max-width:30em;margin-top:var(--sp3)}
.tr-more{margin-top:var(--sp3);font:500 var(--s2)/1.4 var(--fb)}
.tr-dev{grid-column:7/span 6}
.tr-dev .qpanel{max-width:560px;margin-left:auto}
.tr-dev .qf-q{margin-bottom:var(--sp3)}
@media (max-width:1180px){
  .fan{--sw:280px}
  .fan-stage{height:560px}
  .c-table{top:300px}
}
/* iPad et telephone : l'eventail au centre, les legendes dessous, la question sous son texte. */
@media (max-width:1024px){
  .fan-stage{height:auto;margin-top:var(--sp4);perspective:1100px}
  .fan{--sw:240px;position:relative;left:50%;top:0;margin:var(--sp2) 0 var(--sp5) calc(var(--sw) / -2)}
  .fan .s1{translate:-52% 4% -60px}
  .fan .s3{translate:52% 4% -60px}
  .p-head{--z:26px}
  .p-table{--z:18px}
  .callouts{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--sp3)}
  .callouts li{position:relative;left:auto;top:auto;width:auto;padding-left:0}
  .callouts li::before{display:none}
  .tr-txt,.tr-dev{grid-column:1/-1}
  .tr-dev{margin-top:var(--sp4)}
  .tr-dev .qpanel{margin-left:0}
}
@media (max-width:760px){
  .fan{--sw:160px}
  .fan .s1{translate:-46% 4% -60px}
  .fan .s3{translate:46% 4% -60px}
  .callouts{grid-template-columns:1fr;gap:var(--sp2)}
  .legend{text-align:left;font-size:var(--s2)}
}

/* ---- 18. Accueil : « Thirteen exams. Then rotation. » (#rotation), puis la route GPS des matieres (#route) (planche B v2) ----
   <section class="rot" id="rotation"><div class="wrap">
     <h2 class="display rot-h"><span class="l">Thirteen exams.</span><span class="l rot-on">Then rotation.</span></h2>
     <div class="rot-scene" aria-hidden="true"><div class="runway-book">…</div><span class="rs1 rotate"><svg>…</svg></span></div>
   </div></section>
   Le moment de la marque : le RS-1 du decollage en grand (24 px par unite, 9 sur telephone), sur le meme livre-piste.
   Pose de base : en rotation (.rs1.rotate, 12 degres) au milieu de la piste (--xr2), train sorti : c'est ce que montrent le
   mouvement reduit et un navigateur sans script. Le geste (motion.css) part de --x0 (le seuil, la queue contre le dos du livre),
   roule jusqu'a --xr1, cabre jusqu'a --xr2, decolle a --xl, monte a la pente --gam (plus faible que l'assiette) et sort a
   --exit (au-dela du bord droit de l'ecran). --ra / --rb : etendue du geste, en part de la traversee de la scene a l'ecran
   (cover) ; --ri debut de la rotation (38 %), --rm pose en rotation (50 %) ; motion.js lit --ra et --rb pour son repli. */
.rot{--ra:28%;--rb:70%;--ri:calc(var(--ra) + (var(--rb) - var(--ra)) * .38);--rm:calc(var(--ra) + (var(--rb) - var(--ra)) * .5);
  padding:var(--section) 0 0;overflow-x:clip;timeline-scope:--rot}
.rot-h .l{display:block;white-space:nowrap}
.rot-h .l:first-child{color:var(--dim)}
.rot-scene{--sky:216px;position:relative;container-type:inline-size;margin-top:var(--sp5);padding-top:var(--sky)}
.rot-scene .rs1{--rs1-u:24px;--x0:calc(17px + var(--rs1-size) * .389 + 8px);--xr1:.40;--xr2:.50;--xl:.56;--gam:.176;
  --exit:calc(50vw + 50cqw + var(--rs1-size) * .5);left:calc(var(--xr2) * 100cqw);top:var(--sky);z-index:2}
/* La route : un plan de vol vertical, le meme sur ordinateur et telephone.
   <section class="fpl" id="route"><div class="wrap"><h2 id="subjects">…</h2><p class="lead">…</p>
     <div class="fpl-route"><div class="fpl-track" aria-hidden="true"><svg class="fpl-rail">path#route-path</svg>
       <svg class="fpl-flown">…</svg><span class="fpl-ship"><span class="rs1 top"><svg>…</svg></span></span></div>
       <ol class="route"><li class="subject-row" style="--p:29">(6a) avec un lien a.name</li>…</ol></div>
     <p class="fpl-tot">…</p></div></section>
   La piste (.fpl-track) va de la premiere balise au bas de la derniere etape, sur l'axe des balises : chaque etape a la
   longueur de sa matiere, la route finit sur le filet du total. Le trace est un chemin SVG etire sur la piste (trait non
   mis a l'echelle) ; sa partie volee (.fpl-flown, bleue) grandit depuis le haut. Le symbole (RS-1 vu de dessus, cap 180)
   est pose sur la premiere balise ; au defilement il reste au centre de l'ecran (position collante, motion.css), la route
   defile sous lui et chaque balise se remplit (.wp::after) quand son centre passe sous lui. Toute la ligne est cliquable
   (le lien du nom s'etend a la ligne). */
.fpl{padding:var(--section) 0 0}
.fpl .lead{margin-top:var(--sp2)}
.fpl-route{--wp-y:14.5px;position:relative;margin-top:var(--sp6)}
.route{margin:0;padding:0;list-style:none}
.route .name{color:var(--ink);text-decoration:none}
.route .name::after{content:"";position:absolute;inset:0;z-index:1}
.route .name:focus-visible{outline:none}
.route .name:focus-visible::after{outline:2px solid var(--focus);outline-offset:2px;border-radius:var(--r-paper)}
.wp::after{content:"";position:absolute;inset:-1.5px;background:var(--blue);opacity:0;transition:opacity var(--t-hover) var(--ease)}
.fpl-track{position:absolute;left:24px;top:var(--wp-y);bottom:0;width:0;pointer-events:none}
.fpl-rail,.fpl-flown{position:absolute;left:-1px;top:0;width:2px;max-width:none;height:100%;overflow:visible}
.fpl-rail path,.fpl-flown path{fill:none;stroke-width:1.5px;vector-effect:non-scaling-stroke}
.fpl-rail path{stroke:var(--line-strong)}
.fpl-flown{transform-origin:50% 0;scale:1 0}
.fpl-flown path{stroke:var(--blue)}
.fpl-ship{position:relative;top:0;display:block;height:0;z-index:2}
.fpl-ship .rs1{--rs1-u:2.5px;--hdg:180deg}
.fpl-tot{display:flex;flex-wrap:wrap;justify-content:space-between;gap:var(--sp1) var(--sp3);max-width:none;margin:0;padding-top:var(--sp4);
  border-top:1px solid var(--line);font-size:var(--s1);color:var(--dim);font-variant-numeric:tabular-nums}
.fpl-tot b{color:var(--ink)}
@media (max-width:760px){
  .rot{--ra:20%;--rb:76%}
  .rot-scene{--sky:104px;margin-top:var(--sp4)}
  .rot-scene .rs1{--rs1-u:9px;--x0:calc(11.9px + var(--rs1-size) * .389 + 8px);--xr1:.50;--xr2:.62;--xl:.68}
  .fpl-route{margin-top:var(--sp5)}
  .fpl-track{left:20px}
  .fpl-ship .rs1{--rs1-u:2.2px}
}
/* Tres petits ecrans (320) : chaque phrase du titre tient sur sa ligne. */
@media (max-width:359px){.rot-h{font-size:var(--s6)}}

/* ---- 19. Accueil : le pack (#pricing), les formules (#bank), la methode (#method), la FAQ (#faq) ; l'atterrissage (pied) ----
   <section class="nb" id="pricing"><div class="wrap"><div class="nb-txt"><h2>The notes.</h2><p class="lead">…</p>
     <p class="nb-more"><a href="notes.html">…</a></p></div>
     <div class="nb-buy"><p class="nb-price num">€79<small>once…</small></p><ul class="nb-incl">…</ul>
     <button class="btn" data-achat="pack" disabled>…</button><p class="nb-save">…</p></div></div></section>
   <section class="bank" id="bank"><div class="wrap"><h2>…</h2><p class="lead">…</p><ul class="plans">(7)</ul>
     <p class="plans-one">…</p><div class="bank-notes"><div class="note">(12)</div>×2</div></div></section>
   <section class="method" id="method"><div class="wrap"><h2>…</h2><div class="method-notes"><div class="note">…<h3>…</h3><p>…</p></div>×4</div>
     <p class="method-more">…</p></div></section>
   <section id="faq" class="qa"><div class="wrap"><h2>…</h2><div class="qa-list"><details><summary>…</summary><p>…</p></details>…</div></div></section>
   Le pack est la seule surface de la section (le prix, ce qu'il contient, le bouton) ; a cote, la phrase et le lien vers
   notes.html. Les formules sont une surface a filets (7), aucune mise en avant. Methode et conditions : des encadres a filet
   au-dessus (12), jamais de cartes. La FAQ : des lignes a filet, le signe s'ouvre en moins. */
.nb,.bank,.method,.qa{padding:var(--section) 0 0}
.nb .wrap{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));column-gap:var(--gap);align-items:center}
.nb-txt{grid-column:1/span 6}
.nb-buy{grid-column:7/span 6;display:flex;flex-direction:column;padding:var(--sp5) var(--sp5) var(--sp4);
  border-radius:var(--r-surface);background:var(--surface);box-shadow:inset 0 1px 0 var(--hi),0 0 0 1px var(--line)}
.nb .lead,.bank .lead{margin-top:var(--sp2)}
.nb-more,.method-more{margin-top:var(--sp3);font:500 var(--s2)/1.4 var(--fb)}
.nb-price{display:flex;align-items:baseline;gap:var(--sp2);font:600 var(--s5)/1 var(--fd);letter-spacing:-.04em;color:var(--ink)}
.nb-price small{font:400 var(--s1)/1.3 var(--fb);letter-spacing:0;color:var(--dim)}
.nb-incl{display:grid;gap:var(--sp1);margin:var(--sp3) 0 0;padding:0;list-style:none;color:var(--ink)}
.nb-incl li{position:relative;padding-left:var(--sp3)}
.nb-incl li::before{content:"";position:absolute;left:0;top:.8em;width:8px;height:1px;background:var(--dim)}
.nb-buy .btn{align-self:flex-start;margin-top:var(--sp4)}
.nb-save{margin-top:var(--sp2);font-size:var(--s1);color:var(--dim);font-variant-numeric:tabular-nums}
.plan-price small{margin-left:var(--sp1);font:400 var(--s1)/1 var(--fb);letter-spacing:0;color:var(--dim)}
.bank .plans{margin-top:var(--sp5)}
.plans-one{margin-top:var(--sp3);color:var(--dim)}
.plans-one a{color:var(--ink);font-weight:500}
.bank-notes,.method-notes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--sp5) var(--gap)}
.bank-notes{margin-top:var(--sp6)}
.bank-notes .note>p:not(.note-label){font-size:var(--s1)}
.method-notes{margin-top:var(--sp5)}
.method-notes h3{margin-bottom:var(--sp1);font-size:var(--s3);line-height:1.25;letter-spacing:-.02em}
.method-notes .note>p:not(.note-label){max-width:34em}
.qa-list{max-width:52rem;margin-top:var(--sp5);border-top:1px solid var(--line)}
.qa details{border-bottom:1px solid var(--line)}
.qa summary{display:flex;justify-content:space-between;align-items:baseline;gap:var(--sp3);padding:var(--sp3) 0;list-style:none;
  font:600 var(--s3)/1.35 var(--fd);letter-spacing:-.015em;color:var(--ink);text-wrap:balance;cursor:pointer;
  transition:color var(--t-hover) var(--ease)}
.qa summary::-webkit-details-marker{display:none}
.qa summary::after{content:"+";flex:none;width:1em;text-align:center;font-weight:400;color:var(--dim)}
.qa details[open] summary::after{content:"\2212"}
.qa summary:hover{color:var(--blue-ink)}
.qa details p{max-width:var(--measure);padding-bottom:var(--sp3);color:var(--dim)}
@media (max-width:1024px){
  .nb-txt,.nb-buy{grid-column:1/-1}
  .nb-buy{margin-top:var(--sp5)}
}
@media (max-width:760px){
  .nb-buy{padding:var(--sp4) var(--sp3) var(--sp3)}
  .nb-buy .btn{align-self:stretch}
  .bank-notes,.method-notes{grid-template-columns:minmax(0,1fr);gap:var(--sp4)}
  .bank-notes{margin-top:var(--sp5)}
  .qa summary{padding:var(--sp2) 0}
}

/* L'atterrissage, en tete du pied de chaque page (commun.LANDING) :
   <div class="landing" aria-hidden="true"><div class="wrap"><div class="land-scene"><div class="runway-book">…</div>
     <span class="rs1 ground"><svg>…</svg></span></div></div></div>
   Le meme livre-piste (14) et le meme RS-1 (15) que le decollage du haut de l'accueil, a la meme echelle (10 px par unite,
   8 sur telephone). Pose de base : pose sur la couverture, arrete a --xs de la piste, train sorti ; c'est ce que voient le
   mouvement reduit et les navigateurs sans animation liee a la vue. Le geste (motion.css, rs1-land) place les etapes en
   part de la largeur de la scene (cqw) : --xa fin de l'approche, --xt toucher, --xn nez pose, --xs arret. La zone coupe ce
   qui sort a gauche de l'ecran (l'avion arrive de la) : la page ne s'elargit jamais. */
.landing{overflow-x:clip;padding-bottom:var(--sp6)}
.land-scene{--sky:112px;position:relative;container-type:inline-size;padding-top:var(--sky)}
.landing .rs1{--xa:.34;--xt:.46;--xn:.56;--xs:.72;left:calc(var(--xs) * 100cqw);top:var(--sky);z-index:2}
@media (max-width:760px){
  .land-scene{--sky:80px}
  .landing .rs1{--rs1-u:8px;--xs:.70}
  .landing{padding-bottom:var(--sp5)}
}

/* ---- 20. Pages matiere (templates/subject.html, gen_subjects.page, tache 8) ----
   Fil d'Ariane (4) au-dessus du h1 ; premier ecran : le nom exact, ce qu'est la page, le chapeau de la fiche, trois
   chiffres, les deux actions (.hero .cta, cible de la barre d'achat) et une page de la fiche (l'image LCP : visible au
   premier rendu, a sa taille, jamais differee). Puis ce que couvrent les fiches (une ligne a filet par partie), les pieges (un encadre orange, 12), les questions gratuites (le panneau 8 de l'accueil, #try), l'achat
   (la surface des formules 7, deux colonnes) et les autres matieres (lignes de matiere 6, sans balise de route).
   Aucun avion : la page se pose dans le pied comme les autres. .subj passe devant les anciennes regles .cta de site.css. */
.subj-crumbs{padding-top:var(--sp4)}
.subj{padding:var(--sp4) 0 0}
.subj .wrap{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));column-gap:var(--gap);align-items:start}
.subj-txt{grid-column:1/span 7}
.subj h1{font-size:var(--s5);line-height:1.04;letter-spacing:-.035em}
.subj-name,.subj-what{display:block}
.subj-what{margin-top:var(--sp2);font-size:var(--s4);line-height:1.15;letter-spacing:-.02em;color:var(--dim)}
.subj .lead{margin-top:var(--sp3)}
.subj .lead em{font-style:normal;color:var(--ink)}
.subj-facts{display:flex;gap:var(--sp5);margin:var(--sp4) 0 0;padding:var(--sp3) 0 0;list-style:none;
  border-top:1px solid var(--line);font-size:var(--s1);color:var(--dim)}
.subj-facts b{display:block;margin-bottom:var(--sp1);font:600 var(--s4)/1 var(--fd);letter-spacing:-.025em;color:var(--ink)}
.subj .cta{display:flex;flex-wrap:wrap;gap:var(--sp1);margin-top:var(--sp4)}
.subj .cta .btn{padding:0 var(--sp3);font-size:var(--s2);white-space:nowrap}
.subj-page{grid-column:9/span 4;margin:0}
.subj-page img{width:100%;border-radius:var(--r-paper);box-shadow:var(--shadow-lift),0 0 0 1px var(--line)}
.subj-sec{padding:var(--section) 0 0}
.subj-sec .lead{margin-top:var(--sp2)}
/* Ce que couvrent les fiches : une ligne a filet par partie, une seule fois (numero, titre et une ligne de description,
   code des Learning Objectives a droite), comme les lignes de matiere (6). */
.subj-parts{margin:var(--sp5) 0 0;padding:0;list-style:none;border-top:1px solid var(--line)}
.subj-part{display:grid;grid-template-columns:96px minmax(0,1fr) 200px;column-gap:var(--gap);align-items:baseline;
  padding:var(--sp3) 0;border-bottom:1px solid var(--line)}
.subj-part-n{font:600 var(--s1)/1.4 var(--fd);color:var(--dim)}
.subj-part-t{font:600 var(--s3)/1.3 var(--fd);letter-spacing:-.015em;color:var(--ink)}
.subj-part-d{max-width:40em;margin-top:var(--sp1);color:var(--dim)}
.subj-part-code{text-align:right;font:500 var(--s1)/1.4 var(--fb);color:var(--dim)}
/* Les pieges : un seul encadre orange (12), une ligne par piege, numerotee. */
.subj-sec .note.trap{max-width:52rem;margin-top:var(--sp5)}
.trap-list{margin:0;padding:0;list-style:none;counter-reset:t}
.trap-list li{display:grid;grid-template-columns:40px minmax(0,1fr);padding:var(--sp2) 0;border-top:1px solid var(--line);
  counter-increment:t;color:var(--ink)}
.trap-list li:first-child{border-top:0;padding-top:var(--sp1)}
.trap-list li::before{content:counter(t,decimal-leading-zero);padding-top:.15em;font:600 var(--s1)/1.4 var(--fd);
  color:var(--orange-ink);font-variant-numeric:tabular-nums}
/* Les dix questions : le panneau de l'accueil (8, #try), sous son texte (le titre porte le nom de la matiere, il lui faut
   la largeur) ; une question par bloc, separees d'un filet. */
.subj-try .tr-txt{grid-column:1/-1}
.subj-try .tr-dev{grid-column:1/span 8;margin-top:var(--sp5)}
.subj-try .tr-dev .qpanel{max-width:none;margin-left:0}
/* L'ancienne feuille borne chaque <p> a 66 caracteres : la barre du panneau prend toute sa largeur. */
.subj-try .qp-bar{max-width:none}
.subj-try .qfree{gap:var(--sp4)}
.subj-try .qf+.qf{padding-top:var(--sp4);border-top:1px solid var(--line)}
/* L'achat : la surface des formules (7) a deux colonnes, les fiches puis la banque de la matiere. */
.plans.two{grid-template-columns:repeat(2,minmax(0,1fr));margin-top:var(--sp5)}
.plan-desc{margin:calc(var(--sp2) * -1) 0 var(--sp4);font-size:var(--s1);color:var(--dim)}
/* Les autres matieres : lignes de matiere (6) sans balise ni longueur de route ; toute la ligne est le lien. */
.subjects-list{margin:var(--sp5) 0 0;padding:0;list-style:none;border-top:1px solid var(--line)}
.subjects-list .subject-row{grid-template-columns:64px minmax(200px,1fr) 96px 128px 88px;min-height:0;padding:var(--sp2) 0;
  border-bottom:1px solid var(--line)}
.subjects-list .subject-row .code{grid-column:1}
.subjects-list .name{color:var(--ink);text-decoration:none}
.subjects-list .name::after{content:"";position:absolute;inset:0}
.subjects-list .name:focus-visible{outline:none}
.subjects-list .name:focus-visible::after{outline:2px solid var(--focus);outline-offset:2px;border-radius:var(--r-paper)}
@media (max-width:1024px){
  .subj-txt{grid-column:1/-1}
  .subj-page{grid-column:1/-1;width:min(320px,70%);margin-top:var(--sp5)}
  .subj-try .tr-dev{grid-column:1/-1;margin-top:var(--sp4)}
}
@media (max-width:760px){
  .subj-crumbs{padding-top:var(--sp3)}
  .subj .cta{flex-direction:column;align-items:stretch}
  .subj-facts{gap:var(--sp4)}
  .subj-page{width:min(240px,64%)}
  /* Telephone : numero et code sur une ligne, titre et description sur toute la largeur. */
  .subj-part{grid-template-columns:auto minmax(0,1fr);gap:var(--sp1);padding:var(--sp2) 0}
  .subj-part>div{grid-column:1/-1;grid-row:2}
  .subj-part-code{grid-column:2;grid-row:1;text-align:left}
  .plans.two{grid-template-columns:minmax(0,1fr)}
  .plans.two .plan+.plan{border-left:0;border-top:1px solid var(--line)}
  .subjects-list .subject-row{grid-template-columns:40px minmax(0,1fr) auto}
  .subjects-list .subject-row .code{grid-column:1;grid-row:1}
  .subjects-list .subject-row .name{grid-column:2}
  .subjects-list .subject-row .price{grid-column:3}
  .subjects-list .subject-row .pages{grid-column:2}
  .subjects-list .subject-row .qs{grid-column:2/4}
}
@media (max-width:359px){
  .subjects-list .subject-row .name{grid-column:2/4}
  .subjects-list .subject-row .price{grid-column:3;grid-row:2}
  .subjects-list .subject-row .qs{grid-column:2}
}

/* ---- 21. Pages transverses (notes, question-bank, subjects, free-questions, method, updates ; gen_site.py, tache 9) ----
   Aucun composant nouveau : le premier ecran des pages matiere (20, .hero.subj, texte sur 7 colonnes), les trois pages de
   l'accueil dans leur pose ouverte (17, #look sans .lift), le pack (19, .nb), les formules (7), le panneau de question et le
   texte de la question gratuite (8 et 17, .try : texte a gauche, panneau a droite), les encadres (12, grilles 19), les lignes
   de matiere (6 et 20) et les lignes a filet des parties (20). Ce bloc ne fait que les poser sur ces pages :
   - .tp-body : la liste qui suit le chapeau dans le premier ecran (subjects, free-questions, updates), toute la largeur ;
   - #buy de notes.html : sous le pack, les 13 matieres (.buy-list : pages, prix et la marque « Buy », pas de questions) et
     deux encadres ; une seule action d'achat dans la section, chaque matiere s'achete sur sa page ;
   - free-questions.html : chaque ligne de partie est un lien (vers #q1 de la page matiere), comme les lignes de matiere ;
   - figure#dashboard : l'image du plan 3 (img/dashboard.webp), emise par gen_site.py seulement si le fichier existe ;
   - ol.updates : le journal date, une ligne a filet par entree, la date en chiffres tabulaires. */
/* notes.html : les trois pages suivent le premier ecran de pres (leur titre est pour les lecteurs d'ecran) : ensemble, ils
   font le premier ecran, comme le decollage et les portes de l'accueil. */
.notes-look{padding-top:var(--sp4)}
.notes-look .fan-stage{margin-top:0}
/* Premier ecran sans objet (subjects, free-questions, method, updates) : le titre prend toute la largeur. */
.tp-list .subj-txt{grid-column:1/-1}
/* L'encadre orange de la grille de method.html : aligne sur ses voisins (20 decale celui des pages matiere). */
.method-notes .note.trap{max-width:none;margin-top:0}
.tp-body{grid-column:1/-1;margin-top:var(--sp6)}
.tp-body>.subjects-list,.tp-body>.subj-parts{margin-top:0}
.subjects-list+.fpl-tot{border-top:0}
.nb-one,.nb-notes{grid-column:1/-1}
.nb-one{margin-top:var(--sp7)}
.nb-one .subjects-list{margin-top:var(--sp3)}
.subjects-list.buy-list .subject-row{grid-template-columns:64px minmax(200px,1fr) 96px 88px 64px}
.subject-row .go{text-align:right;font:600 var(--s1)/21px var(--fd);color:var(--blue-ink)}
.free-list .subj-part{position:relative}
.free-list .subj-part-t a{color:var(--ink);text-decoration:none;transition:color var(--t-hover) var(--ease)}
.free-list .subj-part-t a::after{content:"";position:absolute;inset:0}
.free-list .subj-part-t a:focus-visible{outline:none}
.free-list .subj-part-t a:focus-visible::after{outline:2px solid var(--focus);outline-offset:2px;border-radius:var(--r-paper)}
.free-list .subj-part:hover .subj-part-t a{color:var(--blue-ink)}
.free-list .subj-part-code{color:var(--blue-ink);white-space:nowrap}
.tp-body .method-more{margin-top:var(--sp4)}
.dash{max-width:calc(var(--col) * 2 / 3);margin:var(--sp5) 0 0}
.dash img{width:100%;border-radius:var(--r-screen);box-shadow:inset 0 1px 0 var(--hi),0 0 0 1px var(--line)}
.dash figcaption{margin-top:var(--sp2);font-size:var(--s1);color:var(--dim)}
/* question-bank.html (#free) : les 13 matieres vers leurs questions gratuites (nom, questions de la banque, « 10 free → »). */
.try-list{margin-top:var(--sp5)}
.subjects-list.try-list .subject-row{grid-template-columns:64px minmax(200px,1fr) 128px 96px}
/* method.html : deux parties en texte (Sources, Corrections), l'encadre des signalements, puis une liste de trois lignes. */
.method-txt{max-width:var(--measure);margin-top:var(--sp4)}
.method-txt p+p{margin-top:var(--sp2)}
.method-report{max-width:34em;margin-top:var(--sp5)}
.method-report h3{margin-bottom:var(--sp1);font-size:var(--s3);line-height:1.25;letter-spacing:-.02em}
.method-list{max-width:52rem;margin:var(--sp4) 0 0;padding:0;list-style:none;border-top:1px solid var(--line)}
.method-list li{padding:var(--sp3) 0;border-bottom:1px solid var(--line);color:var(--dim)}
.method-list b{color:var(--ink)}
.updates{margin:0;padding:0;list-style:none;border-top:1px solid var(--line)}
.updates li{display:grid;grid-template-columns:200px minmax(0,1fr);column-gap:var(--gap);padding:var(--sp3) 0;border-bottom:1px solid var(--line)}
.updates time{font:600 var(--s1)/1.9 var(--fd);color:var(--dim);font-variant-numeric:tabular-nums}
.upd-t{font:600 var(--s3)/1.3 var(--fd);letter-spacing:-.015em}
.updates p{max-width:40em;margin-top:var(--sp1);color:var(--dim)}
.updates .upd-mod{font-size:var(--s1)}
@media (max-width:760px){
  .tp-body{margin-top:var(--sp5)}
  .nb-one{margin-top:var(--sp6)}
  .subjects-list.buy-list .subject-row{grid-template-columns:40px minmax(0,1fr) auto}
  .subjects-list.buy-list .subject-row .go{grid-column:3;grid-row:2}
  .subjects-list.try-list .subject-row{grid-template-columns:40px minmax(0,1fr) auto}
  .subjects-list.try-list .subject-row .go{grid-column:3;grid-row:1}
  .subjects-list.try-list .subject-row .qs{grid-column:2;justify-self:start;text-align:left}
  .method-list li{padding:var(--sp2) 0}
  .updates li{grid-template-columns:minmax(0,1fr);row-gap:var(--sp1);padding:var(--sp2) 0}
}
@media (max-width:359px){
  .subjects-list.buy-list .subject-row .go{grid-column:2;text-align:left}
  .subjects-list.try-list .subject-row .name{grid-column:2}
}
