/* LA PALETTE ET L ARCHITECTURE, refaites le 7 octobre 2026 sur le modele demande.
   CE QUI CHANGE, ET POURQUOI CE N EST PAS QU UNE AFFAIRE DE COULEURS. La plateforme etait SOMBRE par defaut,
   avec un accent vert vif : un ecran de veille, pas une page qu on lit une heure. Le modele demande est
   l inverse — un papier clair, des cartes blanches posees dessus avec une ombre douce, et un accent GRIS
   ARDOISE qui ne crie pas. L accent cesse d etre une couleur et devient un niveau de gris : c est pour cela
   que la bascule du defaut en clair n est pas separable du changement de palette. Un accent ardoise sur fond
   sombre serait invisible.
   LES POLICES NE BOUGENT PAS : elles ne faisaient pas partie de la demande.
   LE DEFAUT SUIT DESORMAIS LE SYSTEME. Sans choix explicite, la page prend le theme du systeme d exploitation
   plutot qu un sombre impose ; `data-theme` ne sert plus qu a passer outre, dans un sens comme dans l autre. */
/* `--bg` PORTE DEUX SENS, ET ILS COINCIDENT AUJOURD HUI SEULEMENT. C est le fond de la page, et
   c est aussi l ENCRE posee sur un aplat : `color:var(--bg)` apparait sur `.btn.principal`, sur
   `button:hover`, sur `.cell.fini`, sur `.circuit a.fini` — 40 emplois au total, dont une bonne
   part ne sont pas des fonds. Tant que la page est blanche, les deux lectures donnent la meme
   couleur et rien ne le trahit. Le jour ou quelqu un voudra teinter la page, changer ce jeton
   teintera DU MEME COUP le texte de tous les boutons pleins : il faudra alors le dedoubler, pas
   le modifier. En sombre, les deux sens coincident aussi — l encre y est le noir du fond. */
:root{--bg:#fff;--sheet:#fff;--card:#fff;--card-2:#fff0de;--fg:#243830;--muted:#536057;--faint:#65746a;
  --accent:#6c48a8;--accent-l:#f1edff;--accent-line:#d9cbee;--line:#d8ded7;--line-soft:#e4e8e4;--code:#eaf4e1;
  --ok:#285440;--ok-soft:#edf5e5;--ko:#bf4019;--ko-soft:#fce9e5;--warn:#9a630d;--warn-soft:#fff0de;
  --lecture:66ch;color-scheme:light;
  /* Les LAVIS de survol et de selection. Ils etaient ecrits rgba(255,255,255,.06) en dur : une encre
     blanche, invisible sur du papier. En jeton, chaque theme pose la sienne et les regles ne changent plus. */
  --wash:rgba(36,56,48,.05);--wash-2:rgba(36,56,48,.09);
  /* L ARCHITECTURE : une colonne de lecture bornee, un rayon de carte, deux ombres. Elles vivent en jetons
     pour la meme raison que les espacements — sans quoi chaque ecran reposerait la sienne. */
  --col:min(1060px,100%);--r:18px;--r-s:12px;--r-pill:999px;
  --sh:0 1px 2px rgba(36,56,48,.05), 0 6px 20px rgba(36,56,48,.06);
  --sh2:0 2px 6px rgba(36,56,48,.07), 0 18px 44px rgba(36,56,48,.10);
  /* L ECHELLE D ESPACEMENT, batie sur les valeurs reellement utilisees et non sur une grille arbitraire.
     Il y avait 28 valeurs distinctes : chaque ecran avait pose celle qui tombait bien, et rien ne reliait
     22 px a 24 px sinon qu ils se ressemblent. Une grille de 4 px imposee aurait deplace 6 px vers 8 px sur
     cinquante et une declarations — une densification visible partout. En partant des valeurs existantes,
     chaque pas absorbe ses voisines a 2 px pres : le rythme se regularise, aucun ecran ne change de
     proportions. 1 px et 2 px restent bruts : ce sont des filets, pas des espaces. */
  --e-1:4px;--e-2:8px;--e-3:12px;--e-4:16px;--e-5:20px;--e-6:24px;--e-7:32px;--e-8:40px;--e-9:48px;--e-10:56px;--e-11:64px;
  /* L ECHELLE TYPOGRAPHIQUE, pour les tailles FIXES. Les tailles fluides restent en clamp() : elles ont deux
     bornes reglees ensemble, qu un pas unique ne saurait porter. 16 px est le seuil en dessous duquel iOS
     agrandit la page des qu un champ recoit le focus — d ou le regroupement de 15 px sur 16 px. */
  --t-1:12px;--t-2:14px;--t-3:16px;--t-4:18px;--t-5:20px;--t-6:22px;--t-7:24px;
  --rose-vif:#d20066;--rose-encre:#fff;--rose-soft:#fff2f8;--rose-line:#f7a8cf;
  /* LA PALETTE APEX. Onze couleurs viennent de la maquette ; les surfaces et les etats en
     sont derives, teinte et saturation gardees, clarte reglee jusqu au contraste exige. */
  /* TROIS ENCRES SOUS 4,5:1 SUR UNE SURFACE OU ELLES SE POSENT (AC22-3), reglees par cette regle :
     clarte HSL seule, jusqu a 4,5 contre TOUTES leurs surfaces a la fois — releve du 25/10/2026,
     regle par regle, et le test « jetons » du lot B en tient la liste.
       faint en clair, 88988d -> 65746a : 2,79 -> 4,53 sur le rose de l aide, ou se posent
         « (3 mots entre les deux) » et le « ? » des tableaux de proportion ; 3,03 -> 4,93 sur
         la feuille. C est du texte courant, pas du gros texte.
       rose-vif en clair, e3006e -> d20066 : 3,94 -> 4,50 sous l etiquette d un morceau de mot
         (lavis sur rose), 4,30 -> 4,91 sur le rose de l aide ; et le blanc pose SUR lui monte de
         4,68 a 5,34.
       ok en sombre, 5a8d74 -> 7ead96 (dans les deux blocs sombres plus bas) : 2,99 -> 4,52 au
         survol de la liste Scratch, 3,52 -> 4,88 sur le ruban « deja reussi », 4,44 -> 6,71 sur
         la surface d exercice. Le noir pose SUR lui (bouton juste du quiz) monte de 4,99 a 7,54.
     Aucune des trois n est une couleur de la maquette : faint et ok sombre en sont derivees, le
     rose est anterieur a la charte. Et deep, qui valait la meme chose que ok en sombre, n est pas
     touche : il ne sert qu a l accueil, sur d autres surfaces. */
  --violet:#6c48a8;--deep:#285440;--leaf:#4f7c66;--coral:#e97957;--apricot:#f2bb66;
  --tone-apricot:#fff0de;--tone-lilac:#f1edff;--tone-sage:#edf5e5;--tone-rose:#fce9e5;--tone-blue:#eaf4ff;
}
/* LE SOMBRE, declare une fois et applique par deux chemins : le reglage du systeme quand personne n a choisi,
   et l attribut quand quelqu un a choisi. Sans le premier, un ecran regle en sombre recevrait du papier blanc
   en pleine nuit ; sans le second, le bouton de theme ne servirait a rien. */
@media (prefers-color-scheme:dark){:root:not([data-theme=light]){--bg:#0b110f;--sheet:#131d19;--card:#131d19;--card-2:#1b2a24;
  --fg:#eef2f0;--muted:#b2bdb6;--faint:#849589;--accent:#a289cc;--accent-l:#1e172a;--accent-line:#4d3871;
  --line:#2e3d37;--line-soft:#222d29;--code:#1b2a24;--ok:#7ead96;--ok-soft:#121d18;--ko:#e97957;--ko-soft:#392018;
  --warn:#f2bb66;--warn-soft:#392c18;color-scheme:dark;
  --rose-vif:#ff4fa3;--rose-encre:#10141b;--rose-soft:#2a1420;--rose-line:#7d2b55;
  --wash:rgba(255,255,255,.06);--wash-2:rgba(255,255,255,.10);
  --sh:0 1px 2px rgba(0,0,0,.45), 0 6px 20px rgba(0,0,0,.35);
  --sh2:0 2px 6px rgba(0,0,0,.5), 0 18px 44px rgba(0,0,0,.45);
  /* Les memes, eclaircis pour le fond sombre : la teinte reste celle de la charte. */
  --violet:#a289cc;--deep:#5a8d74;--leaf:#78ab92;--coral:#e97957;--apricot:#f2bb66;
  --tone-apricot:#392c18;--tone-lilac:#1e172a;--tone-sage:#121d18;--tone-rose:#392018;--tone-blue:#15212b;
}}
:root[data-theme=dark]{--bg:#0b110f;--sheet:#131d19;--card:#131d19;--card-2:#1b2a24;
  --fg:#eef2f0;--muted:#b2bdb6;--faint:#849589;--accent:#a289cc;--accent-l:#1e172a;--accent-line:#4d3871;
  --line:#2e3d37;--line-soft:#222d29;--code:#1b2a24;--ok:#7ead96;--ok-soft:#121d18;--ko:#e97957;--ko-soft:#392018;
  --warn:#f2bb66;--warn-soft:#392c18;color-scheme:dark;
  --rose-vif:#ff4fa3;--rose-encre:#10141b;--rose-soft:#2a1420;--rose-line:#7d2b55;
  --wash:rgba(255,255,255,.06);--wash-2:rgba(255,255,255,.10);
  --sh:0 1px 2px rgba(0,0,0,.45), 0 6px 20px rgba(0,0,0,.35);
  --sh2:0 2px 6px rgba(0,0,0,.5), 0 18px 44px rgba(0,0,0,.45);
  /* Les memes, eclaircis pour le fond sombre : la teinte reste celle de la charte. */
  --violet:#a289cc;--deep:#5a8d74;--leaf:#78ab92;--coral:#e97957;--apricot:#f2bb66;
  --tone-apricot:#392c18;--tone-lilac:#1e172a;--tone-sage:#121d18;--tone-rose:#392018;--tone-blue:#15212b;
}
:root[data-theme=dark] .py textarea,:root:not([data-theme=light]) .py textarea{background:var(--card-2)}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
/* UN MOT PLUS LONG QUE SA COLONNE POUSSE TOUTE LA PAGE. Mesure sur master/index a 320 px :
   « Tesseract/PaddleOCR/TrOCR/LayoutLM/VLM » fait 313 px dans une colonne de 207 — rien ne
   casse sur une barre oblique —, et la page debordait de 49 px. `break-word` ne coupe QUE
   le mot qui ne tient pas : tant que le texte rentre, il ne change rien, et il ne touche pas
   au calcul de largeur minimale des grilles. */
body{margin:0;background:var(--bg);color:var(--fg);font-family:Segoe UI,Arial,sans-serif;overflow-wrap:break-word}
header{min-height:54px;display:flex;align-items:center;justify-content:space-between;padding:0 5vw;border-bottom:1px solid var(--line);gap:var(--e-4);background:var(--sheet)}
/* Le fil d Ariane du module — « LYCÉE · 01 » — porte un lien de 19 px de haut, mesure au
   telephone. Meme raison que dans la barre de compte : 24 px est le minimum d une cible tactile. */
header a{display:inline-flex;align-items:center;min-height:24px}
header b{letter-spacing:.12em;font-size:var(--t-2);white-space:nowrap}
/* « PRIMAIRE · INFORMATIQUE · SCRATCH » fait 312 px : il déborde d'un écran de 320.
   En dessous de 640, il passe à la ligne plutôt que de pousser la page. */
@media(max-width:640px){header b{white-space:normal}}
header b a{color:var(--fg);text-decoration:none}
header b a:hover{color:var(--accent)}
/* L EN-TETE D UN MODULE NE POUSSE PLUS LA PAGE (releve du 28/10/2026, present en production). Au-dessus de 750 px il
   reste sur une ligne, et le <select id="toc">, que cours.js remplit d un titre par diapositive, gardait pour minimum
   sa plus longue option, bornee a 40vw : a 768 px, 313 px de select repoussaient « Vue complete » hors de l ecran —
   590 modules sur 812, de 16 a 134 px, et 39 de plus a 1024 px en « Vue complete », dont le libelle est plus long.
   Le select rend desormais la place qu il n emploie pas : il n affiche que la diapositive en cours, et la liste
   deroulee garde les titres entiers. Les boutons, eux, ne se compriment plus : « Vue complete » passait sur deux
   lignes avant meme de sortir de l ecran. */
header>#toc{min-width:0}
header>#toc~button{flex-shrink:0}
button,select,.btn{font:inherit;color:var(--fg);background:transparent;border:1px solid var(--line);padding:var(--e-3) var(--e-4);border-radius:var(--r-pill);cursor:pointer;background:var(--card);text-decoration:none;display:inline-block}
/* L attribut hidden doit gagner sur la regle ci-dessus. Une regle d AUTEUR bat la
   feuille du navigateur quelle que soit la specificite : un <button hidden> restait
   donc VISIBLE partout dans le depot. Decouvert le 04/10/2026 sur le paquet de
   cartes, ou « Montrer la reponse » ne disparaissait pas une fois la carte retournee. */
[hidden]{display:none !important}
/* Survol décoratif : jamais sur un bouton désactivé, et seulement avec un pointeur qui survole —
   au toucher, le premier tap laisserait l'état :hover collé jusqu'au tap suivant. */
@media (hover:hover){button:not(:disabled):hover,.btn:hover{background:var(--accent);color:var(--bg)}}
button:disabled{opacity:.35;cursor:default}
a.btn[aria-disabled=true]{opacity:.35;cursor:default;pointer-events:none}
/* variante compacte : utilisée par la barre de compte, l'admin et Ma famille */
button.mini,.btn.mini{padding:2px var(--e-2);font-size:var(--t-2);border-radius:var(--r-pill);line-height:1.3}
/* Le bouton de depliage du menu n existe que sur les petits ecrans (regle dans la requete media plus bas). */
.nav-bascule{display:none}
select{max-width:40vw;background:var(--bg)}
main{max-width:var(--col);margin:auto}
.slide{display:none;padding:5vh 7vw var(--e-7);min-height:calc(100vh - 145px)}
.slide.active{display:block}
.eyebrow{color:var(--accent);text-transform:uppercase;letter-spacing:.14em;font-size:var(--t-2);margin:0 0 var(--e-5)}
h1{font-size:clamp(32px,6vw,84px);line-height:1.05;letter-spacing:-.045em;max-width:1000px;margin:var(--e-6) 0}
h2{font-size:clamp(30px,3.8vw,52px);line-height:1.1;letter-spacing:-.03em;margin:0 0 var(--e-7)}
h3{font-size:var(--t-7);color:var(--accent);margin:var(--e-2) 0 var(--e-4)}
p,li,td,th{font-size:clamp(17px,1.5vw,22px);line-height:1.5}
/* LA LONGUEUR DE LIGNE, MESUREE. Sur un ecran de 1440 px, les paragraphes couraient de 102 a 114 caracteres
   par ligne, la ou la lecture confortable se situe entre 45 et 75 : l oeil perd le debut de la ligne suivante
   et relit la meme. C est la premiere chose que reglent OpenClassrooms, Khan Academy et freeCodeCamp.
   LA BORNE EST EN `ch`, PAS EN PIXELS : elle suit la taille du texte, qui est elle-meme fluide (clamp). En
   pixels, une borne juste a 17 px devenait trop large a 22 px — c est exactement ce qui se passait avec
   1000 px. Un `max-width` ne fait que PLAFONNER : dans une carte ou une colonne etroite, il ne change rien. */
p{max-width:var(--lecture)}
ul,ol,dl{max-width:var(--lecture)}
/* LA MESURE DE LECTURE EST FAITE POUR LA PROSE, ET ELLE RABOTAIT DES COMPOSANTS. 66ch vaut
   569 px : toute liste s y trouvait bornee, y compris celles qui ne sont pas du texte suivi.
   Mesure du 22/10/2026, a 1425 px de large :
     - `ul.modules` (le sommaire d un cycle) tombait a 569 px dans un parent de 778, et sa grille
       `repeat(auto-fill, minmax(280px,1fr))` ne rendait plus qu UNE colonne au lieu de deux ;
     - `ul.pages` (la liste des enfants, des pages suivies) donnait 152 px a sa colonne de texte.
   Le symptome se lit comme « rien n est responsive » : la page s elargit, le contenu non.
   `.path-list` portait deja son propre `max-width:none`, pose a la main — le mur avait donc deja
   ete heurte une fois, et repare a un seul endroit.
   N Y SONT PAS AJOUTEES les listes de COURS — `.etapes`, `.pas`, `.arcs`, `.ordre`, `.steps` —
   bien qu elles enlevent aussi leurs puces : aucun defaut n y a ete mesure, et elles vivent dans
   une colonne de lecture ou la borne est legitime. 48 750 `.etapes` dans le depot : on ne les
   deplace pas sur une intuition. */
.modules,.pages{max-width:none}
li{margin-bottom:var(--e-3)}
ul,ol{padding-left:var(--e-6)}
/* Le chapeau est plus gros, donc moins de caracteres pour la meme largeur : 50ch le laisse respirer sans
   depasser les trois ou quatre lignes qu on lit d un coup d oeil. */
.lead{font-size:clamp(22px,2.3vw,32px);max-width:50ch;color:var(--muted)}
.split{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--e-9);align-items:start}
/* UN TABLEAU LARGE NE TIENT PAS DANS UNE DEMI-COLONNE. La feuille empilait deja les deux
   colonnes sur un ecran etroit, et — entre 751 et 1024 px — des qu un tableau etait present.
   Au-dela, rien : un tableau des rangs a huit colonnes restait coince dans une moitie d ecran,
   et la colonne voisine se reduisait a un filet ou le texte tombait mot par mot. Les blocs dont
   le tableau porte CINQ COLONNES OU PLUS sont marques « large » et s empilent a toute largeur ;
   les 1 373 autres, a deux ou quatre colonnes, se lisent tres bien cote a cote et ne bougent pas. */
.split.large{grid-template-columns:minmax(0,1fr)}
.big{font-size:clamp(55px,8vw,110px);color:var(--accent);font-weight:650;letter-spacing:-.05em}
.callout{border-left:4px solid var(--accent);padding:var(--e-3) 0 var(--e-3) var(--e-6);margin:var(--e-6) 0;font-size:clamp(18px,1.6vw,23px);color:var(--accent)}
.callout.warn{border-color:var(--warn);color:var(--warn)}
pre{background:var(--code);padding:var(--e-6);border-radius:var(--r-s);overflow:auto;line-height:1.6;font-size:clamp(15px,1.45vw,20px);border:1px solid var(--line);margin:var(--e-4) 0}
/* CE QUI SAIT DEJA DEFILER GARDE SES MOTS ENTIERS. `body` coupe desormais un mot qui ne tient
   pas (voir plus haut) ; un bloc de code et une formule, eux, ont leur propre defilement, et
   couper une formule au milieu d'un symbole serait pire que la faire defiler.
   LE CODE EN LIGNE, LUI, N A PAS DE DEFILEMENT A LUI (releve du 28/10/2026) : il figurait dans
   cette regle, et un appel sans espace plus long que la ligne poussait toute la page —
   `QuantileRegressor(quantile=tau,` dans une etape de methode, une adresse dans une definition,
   `LocallyLinearEmbedding(method="hessian",` dans un titre jusqu a 1 440 px. Il herite desormais
   de son parent : coupe dans un paragraphe, entier dans un <pre> et dans une formule. */
pre,.formule{overflow-wrap:normal}
code{font-family:Consolas,"Cascadia Mono",monospace;color:var(--accent)}
pre.poeme{white-space:pre-wrap;padding:var(--e-4) var(--e-5)}
pre.poeme code{font-family:inherit;color:inherit}
p code,li code,td code{background:var(--code);padding:1px var(--e-1);border-radius:var(--r-s);font-size:.92em}
table{width:100%;border-collapse:collapse}
/* UN TABLEAU LARGE DEFILE SEUL, A TOUTE LARGEUR (releve du 28/10/2026). Un tableau ne descend pas sous
   la somme de ses colonnes, et la regle qui le fait defiler ne vaut que sous 751 px : au-dela,
   onze modules debordaient en « Vue complete » — 380 px a 751 pour un tableau de tests a douze
   colonnes, 92 px a 1 280 pour un tableau de cinq colonnes dans une demi-colonne. cours.js
   enveloppe chaque tableau d une diapositive dans .defilant : le tableau garde sa largeur de 100 %,
   et seul ce qui depasse defile. Un conteneur qui defile coupe ce qui sort de ses bords, et vingt
   de ces tableaux portent des champs : 8 px de marge interieure, repris par une marge negative,
   laissent entier l anneau de focus (5 px) d un champ de la premiere colonne, sans deplacer le tableau. */
.defilant{overflow-x:auto;padding:0 var(--e-2);margin:0 calc(-1 * var(--e-2))}
/* UN TABLEAU QUI DEFILE LE DIT (releve du rendu du 05/11/2026) : a 320 px, cinquante tableaux de 4e cachaient des
   colonnes entieres, et une barre de defilement est invisible au repos sur un telephone. cours.js pose cette ligne
   avant chaque .defilant et ne la montre que si le tableau deborde, comme la frise dit « elle defile de cote ». */
.defilant-indice{margin:var(--e-2) 0 0;font-size:var(--t-1);color:var(--muted)}
.defilant-indice[hidden]{display:none}
th{text-align:left;color:var(--accent)}
td,th{border-bottom:1px solid var(--line);padding:var(--e-3) var(--e-4) var(--e-3) 0;vertical-align:top}
details{margin-top:var(--e-6);padding-top:var(--e-4);border-top:1px solid var(--line);color:var(--muted)}
summary{cursor:pointer;font-size:var(--t-4);color:var(--fg)}
summary:hover{color:var(--accent)}
details p,details li{font-size:var(--t-4)}
details pre{font-size:var(--t-3)}
a{color:var(--accent)}
footer{display:flex;align-items:center;gap:var(--e-4);padding:var(--e-4) 5vw;border-top:1px solid var(--line);background:var(--bg)}
/* Les liens du pied de page mesuraient 21 px de haut. Le critere WCAG 2.5.8 excepte les liens
   DANS UNE PHRASE, ce qu ils sont ; mais vingt-et-un pixels sous un doigt restent etroits, et
   trois pixels de remplissage ne deplacent rien d autre. */
footer a{display:inline-flex;align-items:center;min-height:24px}
#count{margin-right:auto;color:var(--muted);min-width:70px}
#progress{position:fixed;bottom:0;left:0;height:4px;background:var(--accent);transition:width .15s;z-index:40}
.small{font-size:var(--t-3);color:var(--muted)}
.steps{list-style:none;padding:0;counter-reset:step}
.steps li{counter-increment:step;border-bottom:1px solid var(--line);padding:var(--e-3) 0;display:flex;gap:var(--e-6)}
.steps li:before{content:counter(step,decimal-leading-zero);color:var(--accent);font-weight:bold}
/* Le contenu d une etape est un element de flex : sa largeur minimale etait celle de sa plus longue
   ligne de code, et un <pre> de 1 247 px elargissait l etape au lieu de defiler — 10 modules de
   licence, a toutes les largeurs (releve du 28/10/2026). */
.steps li>*{min-width:0}
/* UN RAYON FIXE, PAS LA PILULE (releve du rendu du 05/11/2026) : a 320 px, une reponse de quatre ou cinq lignes
   dans un bouton de rayon 999 px devenait une ellipse, et les lettres des coins sortaient du fond vert de la bonne
   reponse, blanc sur blanc. */
.quiz button{display:block;margin:var(--e-3) 0;width:100%;text-align:left;border-radius:var(--r-s)}
.quiz button.good{background:var(--ok);color:var(--bg);border-color:var(--ok)}
.quiz button.bad{background:transparent;color:var(--ko);border-color:var(--ko)}
/* après la réponse (seule la première compte), les boutons ne réagissent plus au survol */
.quiz.repondu button{cursor:default}
.quiz.repondu button:hover{background:transparent;color:var(--fg)}
.quiz.repondu button.good,.quiz.repondu button.good:hover{background:var(--ok);color:var(--bg)}
.quiz.repondu button.bad:hover{background:transparent;color:var(--ko)}
.quiz .quiz-regle{margin:0 0 var(--e-2)}
.feedback{min-height:60px;margin-top:var(--e-3);font-size:var(--t-5)}
.feedback.ok{color:var(--ok)}
.feedback.ko{color:var(--ko)}
.overview .slide{display:block;border-bottom:2px solid var(--line);min-height:0;padding-top:var(--e-10);padding-bottom:var(--e-10)}
.overview footer{position:sticky;bottom:0}
.tag{color:var(--accent)}
/* Un seul indicateur de focus, lié au thème (visible en clair comme en sombre) ; le halo de fond le détache des fonds colorés. */
:focus-visible{outline:3px solid var(--accent);outline-offset:2px;box-shadow:0 0 0 5px var(--bg)}

/* Badges de niveau et défis */
.badge{display:inline-block;font-size:var(--t-2);letter-spacing:.08em;text-transform:uppercase;padding:var(--e-1) var(--e-2);border-radius:var(--r-pill);border:1px solid var(--line);color:var(--muted);vertical-align:middle;margin-left:var(--e-2)}
.badge.star{color:var(--accent);border-color:var(--accent)}
.badge.x{color:var(--warn);border-color:var(--warn)}
.defi{border:1px solid var(--line);border-radius:var(--r);padding:var(--e-5) var(--e-5);margin:var(--e-5) 0;background:var(--card);box-shadow:var(--sh)}
.defi h3{margin-top:0}
.defi.x{border-color:var(--warn)}
.defi.x h3{color:var(--warn)}

/* Fiches de cours (lycée → prépa) : définitions, théorèmes, démonstrations, exercices corrigés */
.def,.thm,.methode,.exo{border-left:4px solid var(--accent);border-radius:0 var(--r) var(--r) 0;padding:var(--e-4) var(--e-5);margin:var(--e-5) 0;background:var(--card);box-shadow:var(--sh)}
.def>b:first-child,.thm>b:first-child,.methode>b:first-child,.exo>b:first-child{color:var(--accent)}
/* LES ETAPES D UNE FICHE METHODE : un geste par ligne, son numero dans une pastille, et de l air
   entre les lignes — l eleve doit pouvoir suivre la liste du doigt. La classe ne s appelle PAS
   « methode » : celle-la porte deja une bordure et un fond de carte, et imbriquee elle coupait
   les numeros de la liste. */
.etapes{list-style:none;counter-reset:etape;margin:var(--e-4) 0 0;padding:0}
/* Le numero est pose en ABSOLU, et le texte coule normalement. Une premiere version faisait du
   <li> une grille : chacun de ses enfants devenait alors une case, et un simple <b> au milieu
   d une phrase sautait a la ligne. */
.etapes>li{counter-increment:etape;position:relative;padding-left:2.6em;line-height:1.55}
.etapes>li+li{margin-top:var(--e-4)}
.etapes>li::before{content:counter(etape);position:absolute;left:0;top:.1em;
  display:flex;align-items:center;justify-content:center;width:1.8em;height:1.8em;
  border-radius:50%;background:var(--accent);color:var(--bg);font-weight:700;font-size:var(--t-2);line-height:1}
.def>.etapes+.erreur-frequente{margin-top:var(--e-5)}
body.primaire .etapes{gap:var(--e-5)}
.thm{border-color:var(--warn)}
.thm>b:first-child{color:var(--warn)}
.exo{border-color:var(--muted)}
.exo>b:first-child{color:var(--fg)}
/* Pipelines prêts à l'emploi (.tp) et cas d'usage (.cas) du master. AUCUNE règle ne les visait :
   346 blocs sur 80 pages s'affichaient en texte nu, collés au paragraphe précédent, sans que rien
   ne le signale — relevé le 08/10/2026 en vérifiant le premier module de la filière Data & BI.
   Ils rejoignent la même famille que .def et .thm ; le cas d'usage prend la couleur « ok » pour se
   distinguer du code à exécuter, et ses intertitres <i> deviennent des étiquettes lisibles. */
.tp,.cas{border-left:4px solid var(--accent);border-radius:0 var(--r) var(--r) 0;padding:var(--e-4) var(--e-5);margin:var(--e-5) 0;background:var(--card);box-shadow:var(--sh)}
.tp>b:first-child,.cas>b:first-child{color:var(--accent);display:block;margin-bottom:var(--e-2)}
.cas{border-color:var(--ok)}
.cas>b:first-child{color:var(--ok)}
.cas i{font-style:normal;font-weight:600;color:var(--muted)}
.tp .py{margin-top:var(--e-3)}
.preuve{margin:var(--e-2) 0 var(--e-1) var(--e-2);padding-left:var(--e-4);border-left:2px dashed var(--line);color:var(--muted)}
.preuve>b:first-child{color:var(--fg)}
.preuve::before{content:"Démonstration. ";font-weight:600;color:var(--fg)}
.preuve::after{content:" ∎";color:var(--accent)}
.formule{font-family:"Cambria Math","Times New Roman",serif;font-size:clamp(19px,1.8vw,26px);text-align:center;margin:var(--e-3) 0;padding:var(--e-3) var(--e-4);background:var(--code);border:1px solid var(--line);border-radius:var(--r-s);overflow-x:auto}
.formule .ou{display:block;font-family:inherit;font-size:.75em;color:var(--muted);margin-top:var(--e-1)}
.fiche-plan li{margin-bottom:var(--e-1)}
.corr{margin-top:var(--e-3);padding-top:var(--e-2);border-top:1px solid var(--line)}

/* Barre de compte (assets/app.js) */
#compte-bar{display:flex;align-items:center;justify-content:space-between;gap:var(--e-4);flex-wrap:wrap;padding:var(--e-2) 5vw;font-size:var(--t-2);line-height:1.4;background:var(--sheet);border-bottom:1px solid var(--line);color:var(--muted)}
/* LES CIBLES TACTILES DE LA BARRE, mesurees au telephone le 07/10/2026 et non estimees. Le lien
   du logo faisait 18 x 18 px : son texte est masque sous 750 px (regle plus bas) et il ne restait
   que l image. « Se connecter » et « Creer un compte » faisaient 20 px de haut. Le minimum du
   critere WCAG 2.5.8 est 24 px, et un doigt n a pas la precision d un curseur. On elargit la zone
   CLIQUABLE sans toucher a la hauteur de la barre : le remplissage vertical rentre dans les 53 px
   qu elle fait deja. */
#compte-bar a{color:var(--accent);text-decoration:none;display:inline-flex;align-items:center;min-height:24px}
#compte-bar a:hover{text-decoration:underline}
#compte-bar .site{color:var(--fg);letter-spacing:.06em;font-weight:700;font-size:var(--t-2);display:inline-flex;align-items:center;gap:var(--e-2)}
#compte-bar .site .logo{width:18px;height:18px;vertical-align:middle}
#compte-bar .gauche,#compte-bar .droite,#compte-bar .prog{display:flex;align-items:center;gap:var(--e-3);flex-wrap:wrap}
#compte-bar .barre{width:110px;height:6px;border:1px solid var(--line);border-radius:3px;overflow:hidden;background:var(--bg)}
#compte-bar .barre i{display:block;height:100%;background:var(--accent);transition:width .3s}
#compte-bar .av{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;background:var(--accent);color:var(--bg);font-style:normal;font-weight:700;font-size:var(--t-1);margin-right:var(--e-2);vertical-align:middle}
/* Gamification (assets/jeu.js) */
#compte-bar .serie{color:var(--warn)}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
/* LIEN D EVITEMENT. Au clavier, chaque page commence par l en-tete : sur une page de cours, c est le fil
   d Ariane, le selecteur de diapositive et « Vue complete » a retraverser avant d atteindre la lecon, et un
   module en compte une dizaine. Le lien saute directement au contenu, et ne se montre qu au focus.
   IL VIT ICI, PAS DANS CHAQUE PAGE. La regle etait recopiee en ligne dans les quatorze pages qui portaient le
   lien ; les autres l auraient affiche nu, en toutes lettres, au-dessus du titre. Un comportement partage
   appartient a la feuille partagee. */
.evitement{position:absolute;left:-999px;top:8px;z-index:100;background:var(--accent);color:var(--bg);padding:var(--e-3) var(--e-4);border-radius:var(--r-s);font-weight:600;text-decoration:none}
.evitement:focus{left:8px}
#compte-bar .xp{display:inline-flex;align-items:center;gap:var(--e-2)}
#compte-bar .xp .barre{width:70px}
/* Au doigt, les boutons son/thème doivent atteindre la cible minimale (WCAG 2.5.8) */
@media (pointer:coarse){#compte-bar button.mini{padding:var(--e-2) var(--e-3);min-width:32px;min-height:32px}}
/* L ANNONCE COMMUNE (assets/app.js, poserAnnonce) : sous la barre de compte, ou en tete de <main> sur les ecrans
   sans barre. Selecteurs par #annonce et non par classe : sur les pages legales, `.legal p` (compte.css, charge
   APRES cette feuille) passerait le texte en gris et en plus grand. Contrastes mesures sur --accent-l : texte
   10,87 (clair) et 15,35 (sombre), lien et bord du bouton 5,85 et 5,77. */
#annonce{display:flex;align-items:flex-start;gap:var(--e-3);padding:var(--e-3) 5vw;background:var(--accent-l);color:var(--fg);border-bottom:1px solid var(--accent-line);font-size:var(--t-3);line-height:1.5}
#annonce p{flex:1 1 auto;min-width:0;margin:0;color:inherit;font-size:inherit;overflow-wrap:anywhere}
#annonce a{color:var(--accent);text-decoration:underline;text-underline-offset:3px}
#annonce .annonce-fermer{flex:none;display:inline-flex;align-items:center;justify-content:center;min-width:44px;min-height:44px;padding:0;border:1px solid var(--accent);border-radius:var(--r-s);background:transparent;color:var(--fg);font-size:var(--t-4);line-height:1}
main>#annonce{margin:0 0 var(--e-4);border:1px solid var(--accent-line);border-radius:var(--r-s);padding:var(--e-3) var(--e-4)}
@media print{#annonce{display:none!important}}
/* au-dessus de la pastille WhatsApp (bas 78 px + ≈ 52 px de haut), qu'ils masquaient pendant leur affichage */
#toasts{position:fixed;right:18px;bottom:150px;z-index:60;display:flex;flex-direction:column;gap:var(--e-3);max-width:min(360px,calc(100vw - 36px))}
.toast{display:flex;gap:var(--e-3);align-items:center;background:var(--card);color:var(--fg);border:1px solid var(--accent);border-radius:var(--r);padding:var(--e-4);box-shadow:var(--sh2);font-size:var(--t-3);animation:toast-in .35s ease-out}
.toast .mascotte{flex:none;width:44px;height:44px}
.toast .mascotte svg{width:100%;height:100%}
.toast b{color:var(--accent)}
.toast small{display:block;color:var(--muted);font-size:var(--t-2)}
/* toast de récompense (badge gagné, défi relevé) : classe distincte de la pastille .badge, dont il héritait capitales et marge. */
.toast.recompense{border-color:var(--warn)}
.toast.recompense .icone{font-size:30px;flex:none}
.toast.sortie{animation:toast-out .3s ease-in forwards}
@keyframes toast-in{from{transform:translateY(16px);opacity:0}to{transform:none;opacity:1}}
@keyframes toast-out{to{transform:translateY(16px);opacity:0}}
.confettis{position:fixed;inset:0;pointer-events:none;z-index:59;overflow:hidden}
.confettis i{position:absolute;top:-12px;width:9px;height:14px;border-radius:2px;opacity:.95;animation:confetti linear forwards}
@keyframes confetti{0%{transform:translate3d(0,0,0) rotate(0)}100%{transform:translate3d(var(--dx),105vh,0) rotate(720deg);opacity:.7}}
.out.bravo{animation:bravo .6s ease-out}
@keyframes bravo{0%{box-shadow:0 0 0 0 color-mix(in srgb,var(--accent) 70%,transparent)}100%{box-shadow:0 0 0 14px color-mix(in srgb,var(--accent) 0%,transparent)}}
.mascotte-oeil{animation:cligne 4s infinite}
@keyframes cligne{0%,92%,100%{transform:scaleY(1)}96%{transform:scaleY(.1)}}
@media (prefers-reduced-motion:reduce){.toast,.toast.sortie,.confettis i,.out.bravo,.mascotte-oeil,.aides details.jynap.parait{animation:none!important}.confettis,.flash-rose{display:none}
/* plus aucun mouvement : ni défilement animé entre diapositives, ni transition, ni soulèvement au survol */
html{scroll-behavior:auto}
*,*::before,*::after{transition:none!important}
.modules a:hover,.modules a:focus-visible,.circuit a:hover{transform:none!important}}
/* Coups de pouce (assets/aide.js) */
.coup-de-pouce{display:flex;flex-wrap:wrap;gap:var(--e-2);align-items:center;margin:var(--e-4) 0 var(--e-2);font-size:var(--t-3)}
.coup-de-pouce .cp-etat{color:var(--muted);margin-right:var(--e-2)}
.coup-de-pouce button{padding:var(--e-2) var(--e-3);font-size:var(--t-2)}
.coup-de-pouce .cp-texte{flex-basis:100%;white-space:pre-wrap;background:var(--code);border-left:3px solid var(--warn);padding:var(--e-3) var(--e-4);border-radius:0 var(--r-s) var(--r-s) 0;font-size:var(--t-3);color:var(--fg);font-family:Consolas,"Cascadia Mono",monospace}
/* Le tuteur IA (28/10/2026) : son bouton dans la barre « Vérifier » ou la barre de la cellule, son panneau sous
   l'exercice. La réponse est du texte brut : pre-wrap garde ses retours à la ligne, overflow-wrap coupe une ligne de
   code trop longue plutôt que d'élargir la page. */
.tuteur-ouvrir{margin-left:auto}
.tuteur{border:1px solid var(--accent-line);border-radius:var(--r);background:var(--accent-l);padding:var(--e-4);margin:var(--e-3) 0 var(--e-4);min-width:0}
.tuteur[hidden],.tuteur-form[hidden]{display:none}
.tuteur-aide{margin:0 0 var(--e-2);color:var(--muted)}
.tuteur-fil{display:flex;flex-direction:column;gap:var(--e-2);margin:var(--e-2) 0}
.tuteur-msg{margin:0;padding:var(--e-3) var(--e-4);border-radius:var(--r-s);white-space:pre-wrap;overflow-wrap:anywhere;line-height:1.5;font-size:var(--t-3);color:var(--fg)}
.tuteur-msg.tuteur{background:var(--card);border-left:3px solid var(--accent);border-radius:0 var(--r-s) var(--r-s) 0}
.tuteur-msg.eleve{background:var(--code);align-self:flex-end;max-width:85%}
.tuteur-msg.attente{color:var(--muted);font-style:italic;animation:tuteur-attente 1.2s ease-in-out infinite alternate}
/* La réponse mise en page (30/10/2026) : des blocs aérés, les calculs sur une ardoise alignée sur le « = », et le bloc
   « À toi » encadré — la seule bordure pleine du message. Les règles générales des p et des li (taille de lecture,
   mesure de 66ch, marge du bas) n'y entrent pas : le message garde la taille du fil. */
.tuteur-msg.tuteur.mis-en-forme{white-space:normal;line-height:1.55}
.tuteur-bloc+.tuteur-bloc{margin-top:.85em}
.tuteur-msg.tuteur p,.tuteur-msg.tuteur li{margin:0;font-size:inherit;line-height:inherit;max-width:62ch}
.tuteur-msg.tuteur p{white-space:pre-wrap}
.tuteur-msg.tuteur ul,.tuteur-msg.tuteur ol{margin:.3em 0 0;padding-left:1.4em}
.tuteur-msg.tuteur li+li{margin-top:.2em}
.tuteur-msg.tuteur .tuteur-code{margin:.3em 0 0;padding:var(--e-2) var(--e-3);font-size:.95em;white-space:pre;overflow-x:auto}
/* Une ligne de calcul ne se coupe pas : trop longue pour l'écran (« 1 250 + 3 480 + 2 975 + 4 120 = 11 825 » à 320 px),
   l'ardoise défile seule, comme .formule — sans elle, toute la page défilait à l'horizontale (revue du 30/10/2026). */
.tuteur-ardoise{display:grid;grid-template-columns:max-content max-content max-content;column-gap:.4em;row-gap:.2em;align-items:baseline;width:fit-content;max-width:100%;box-sizing:border-box;overflow-x:auto;margin:.35em 0 .1em;padding:.35em .9em;background:var(--code);border-radius:var(--r-s);font-size:1.2em;line-height:1.35;font-variant-numeric:tabular-nums}
.tuteur-ardoise.avec-etiquette{grid-template-columns:fit-content(8em) max-content max-content max-content}
.tuteur-ligne{display:contents}
.tc-etiquette{font-size:.75em;color:var(--muted);padding-right:.3em}
.tc-gauche{text-align:right;white-space:nowrap}
.tc-signe{font-weight:700}
.tc-droite{white-space:nowrap}
.tuteur-ardoise .op{color:var(--accent);font-weight:700}
.tuteur-case{display:inline-block;min-width:2.2em;text-align:center;border:2px dashed var(--accent);border-radius:var(--r-s);color:var(--accent);font-weight:700;line-height:1.2}
.tuteur-a-toi{padding:.6em .85em;background:var(--accent-l);border:2px solid var(--accent);border-radius:var(--r-s);font-weight:600;font-size:1.0625em}
.tuteur-bloc+.tuteur-a-toi{margin-top:1.1em}
.tuteur-a-toi-tete{display:block;font-size:var(--t-2);letter-spacing:.06em;text-transform:uppercase;color:var(--accent);font-weight:700;margin-bottom:.15em}
.tuteur-a-toi .tuteur-ardoise{background:var(--card)}
/* Au téléphone, et dans le panneau flottant du master (26rem au plus), l'étiquette passe au-dessus de son calcul :
   les « = » restent alignés, et une étiquette longue ne s'écrase pas en colonne étroite. */
.tuteur-flottant .tuteur-ardoise.avec-etiquette{grid-template-columns:max-content max-content max-content}
.tuteur-flottant .tuteur-ardoise.avec-etiquette .tc-etiquette{grid-column:1/-1;width:0;min-width:100%}
@media (max-width:640px){.tuteur-ardoise.avec-etiquette{grid-template-columns:max-content max-content max-content}.tuteur-ardoise.avec-etiquette .tc-etiquette{grid-column:1/-1;width:0;min-width:100%}}
.tuteur-msg.nouveau>.tuteur-bloc{animation:tuteur-bloc .28s ease-out both}
.tuteur-msg.nouveau>.tuteur-bloc+.tuteur-bloc{animation-delay:.12s}
.tuteur-msg.nouveau>.tuteur-bloc+.tuteur-bloc+.tuteur-bloc{animation-delay:.24s}
.tuteur-msg.nouveau>.tuteur-bloc+.tuteur-bloc+.tuteur-bloc+.tuteur-bloc{animation-delay:.36s}
.tuteur-msg.nouveau>.tuteur-bloc+.tuteur-bloc+.tuteur-bloc+.tuteur-bloc+.tuteur-bloc{animation-delay:.48s}
.tuteur-msg.nouveau>.tuteur-bloc+.tuteur-bloc+.tuteur-bloc+.tuteur-bloc+.tuteur-bloc+.tuteur-bloc{animation-delay:.6s}
@keyframes tuteur-bloc{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
.tuteur-form label{display:block;margin:var(--e-2) 0 var(--e-1)}
.tuteur-form textarea{display:block;width:100%;box-sizing:border-box;min-height:3.2em;font:inherit;font-size:var(--t-3);padding:var(--e-2) var(--e-3);border:1px solid var(--line);border-radius:var(--r-s)}
.tuteur-actions{display:flex;flex-wrap:wrap;gap:var(--e-2);margin:var(--e-2) 0 0}
.tuteur-rdv{margin:var(--e-2) 0}
.tuteur-etat{margin:var(--e-2) 0 0;color:var(--muted)}
/* La pièce jointe (29/10/2026) : un bouton, le nom du fichier, de quoi le retirer. */
.tuteur-piece{display:flex;flex-wrap:wrap;align-items:center;gap:var(--e-2);margin:var(--e-2) 0 0}
.tuteur-fichier{color:var(--muted);overflow-wrap:anywhere;min-width:0}
.tuteur-retirer{background:none;border:0;color:var(--accent);text-decoration:underline;cursor:pointer;font:inherit;font-size:var(--t-2);min-height:24px}
/* La pastille du master : en bas à droite, au-dessus du pied de page des diapositives (--pied-cours, mesuré par aide.js). */
.tuteur-pastille{position:fixed;right:max(16px,env(safe-area-inset-right));bottom:calc(var(--pied-cours,0px) + 12px);z-index:45;border-radius:var(--r-pill);box-shadow:var(--sh2);min-height:44px;background:var(--accent);border-color:var(--accent);color:var(--bg);font-weight:600}
.tuteur-pastille:hover{background:var(--accent);color:var(--bg);filter:brightness(1.08)}
.tuteur-flottant{position:fixed;right:max(16px,env(safe-area-inset-right));bottom:calc(var(--pied-cours,0px) + 68px);z-index:45;width:min(26rem,calc(100vw - 32px));max-height:min(70vh,40rem);overflow:auto;border-radius:var(--r);box-shadow:var(--sh2);background:var(--bg)}
.tuteur-flottant[hidden]{display:none}
.tuteur-flottant .tuteur{margin:0}
@media print{.tuteur-pastille,.tuteur-flottant{display:none!important}}
@media (prefers-reduced-motion:reduce){.tuteur-msg.attente,.tuteur-msg.nouveau>.tuteur-bloc{animation:none}}
@keyframes tuteur-attente{from{opacity:.55}to{opacity:1}}
/* Éditeur Python intégré */
.py{border:1px solid var(--line);border-radius:var(--r-s);overflow:hidden;margin:var(--e-4) 0;background:var(--code)}
.py textarea{display:block;width:100%;min-height:120px;background:var(--code);color:var(--fg);border:0;padding:var(--e-4) var(--e-5);font-family:Consolas,"Cascadia Mono",monospace;font-size:clamp(16px,1.4vw,19px);line-height:1.55;resize:vertical;tab-size:4;outline:none}
.py textarea:focus{box-shadow:inset 0 0 0 2px var(--accent)}
.py-bar{display:flex;align-items:center;gap:var(--e-3);padding:var(--e-2) var(--e-3);border-top:1px solid var(--line);background:var(--bg);flex-wrap:wrap}
.py-bar button{padding:var(--e-2) var(--e-4);font-size:var(--t-3)}
.py-bar .run{background:var(--accent);color:var(--bg);border-color:var(--accent);font-weight:600}
.py-bar .run:hover{filter:brightness(1.1)}
/* Arreter : present seulement pendant une execution. `urgent` parait au bout de huit
   secondes, quand l attente cesse d etre normale — voir pyrun.js (F09). */
.py-bar .stop{border-color:var(--ko);color:var(--ko)}
.py-bar .stop:disabled{opacity:.5}
.py-bar .stop.urgent{background:var(--ko);color:var(--bg);font-weight:600}
.py-bar .stop[hidden]{display:none}
.py-bar .status{color:var(--muted);font-size:var(--t-2);margin-left:auto}
.py .out{margin:0;border:0;border-top:1px solid var(--line);border-radius:0;min-height:38px;max-height:320px;color:var(--fg);white-space:pre-wrap;font-size:clamp(14px,1.3vw,18px)}
.py .out:empty{display:none}
.py .out.err{color:var(--ko)}
.py .out .stderr{color:var(--ko)}

/* Page d'accueil */
.hero{padding:8vh 7vw var(--e-8)}
.hero h1{max-width:1100px}
.parts{padding:0 7vw var(--e-10);display:grid;grid-template-columns:minmax(0,1fr);gap:var(--e-8)}
.part h2{font-size:clamp(26px,3vw,40px);margin-bottom:var(--e-2)}

/* LES ANNEES SE DEPLIENT. Le sommaire du college faisait 54 800 caracteres : un eleve de troisieme traversait
   la sixieme, la cinquieme et la quatrieme — sept matieres et leurs modules chacune — avant d atteindre les
   siens. Chaque annee est maintenant un <details> ; le sommaire tient en quelques lignes.
   LE RESUME EST UNE CIBLE, DONC IL EN A L AIR : toute la largeur cliquable, un curseur de main, un chevron qui
   tourne. Un pliant qui ne se voit pas est un pliant que personne n ouvre. */
details.part>summary{cursor:pointer;list-style:none;display:flex;align-items:center;gap:var(--e-4);
  padding:var(--e-4) 0;border-bottom:1px solid var(--line)}
details.part>summary::-webkit-details-marker{display:none}
details.part>summary::after{content:'';flex:none;width:12px;height:12px;margin-left:auto;
  border-right:2px solid var(--accent);border-bottom:2px solid var(--accent);transform:rotate(45deg);
  transition:transform .15s}
details.part[open]>summary::after{transform:rotate(225deg)}
details.part>summary h2{margin:0}
@media (hover:hover){details.part>summary:hover h2{color:var(--accent)}}
details.part>summary:focus-visible{outline:3px solid var(--accent);outline-offset:2px}
@media (prefers-reduced-motion:reduce){details.part>summary::after{transition:none}}
/* Meme pliant pour les annees de « Ma progression » dans /mon-espace : la sienne est ouverte, les autres
   attendent un clic. Le titre y est un h3 et non un h2 — d ou une regle a part plutot qu un selecteur commun
   qui aurait force les deux a se ressembler. */
details.annee-parcours>summary{cursor:pointer;list-style:none;display:flex;align-items:center;gap:var(--e-4);padding:var(--e-2) 0}
details.annee-parcours>summary::-webkit-details-marker{display:none}
details.annee-parcours>summary::after{content:'';flex:none;width:10px;height:10px;margin-left:auto;
  border-right:2px solid var(--accent);border-bottom:2px solid var(--accent);transform:rotate(45deg)}
details.annee-parcours[open]>summary::after{transform:rotate(225deg)}
details.annee-parcours>summary h3{margin:0}
details.annee-parcours>summary:focus-visible{outline:3px solid var(--accent);outline-offset:2px}
.part .sub{color:var(--muted);margin:0 0 var(--e-5);font-size:var(--t-4)}
/* `min(Npx,100%)` ET NON `Npx` : un minimum fixe plus large que le conteneur fait deborder
   la grille au lieu de la replier. Mesure : sur master/index a 320 px, la colonne utile
   vaut 249 px et `minmax(280px,1fr)` imposait 280 — 31 px de debordement, invisible sur
   un ecran large et permanent sur un telephone. */
.modules{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(280px,100%),1fr));gap:var(--e-4);list-style:none;padding:0;margin:0}
.modules li{margin:0}
.modules a{display:block;border:1px solid var(--line);border-radius:var(--r-s);padding:var(--e-4) var(--e-5);color:var(--fg);text-decoration:none;height:100%;transition:border-color .15s,transform .15s}
@media (hover:hover){.modules a:hover{border-color:var(--accent);transform:translateY(-2px)}}
.modules a:focus-visible{border-color:var(--accent);transform:translateY(-2px)}
.modules .num{color:var(--accent);font-size:var(--t-2);letter-spacing:.12em}
.modules .title{display:block;font-size:var(--t-5);font-weight:600;margin:var(--e-1) 0 var(--e-2);line-height:1.25}
.modules .desc{display:block;color:var(--muted);font-size:var(--t-3);line-height:1.45}
.modules a.soon{opacity:.45;pointer-events:none}
.modules a.soon .num:after{content:" · bientôt"}
.modnav{display:flex;gap:var(--e-3);flex-wrap:wrap}
/* page courante : visible aussi hors connexion (aria-current était posé sans aucun style). */
.modnav [aria-current="page"]{background:var(--accent);color:var(--bg);border-color:var(--accent);font-weight:600}

/* Pastille WhatsApp */






@media(max-width:750px){
header{padding:var(--e-4) 5vw;flex-wrap:wrap}
.split{grid-template-columns:minmax(0,1fr);gap:var(--e-4)}
.slide{padding:var(--e-7) 6vw;min-height:calc(100vh - 180px)}
h2{margin-bottom:var(--e-6)}
select{max-width:100%;width:auto;flex:1 1 150px;min-width:0}
footer{gap:var(--e-2);flex-wrap:wrap;position:sticky;bottom:0}
/* pied du diaporama : « Imprimer / PDF » n'a pas de sens sur téléphone, et Précédente/Suivante
   se partagent une rangée entière à 44 px de haut au lieu d'être rejetées l'une après l'autre. */
#print{display:none}
#count{flex-basis:100%;margin-right:0}
#prev,#next{flex:1 1 0;min-height:44px}
h1 br{display:none}
button{padding:var(--e-2) var(--e-3)}
.small.hint{display:none}
td,th{font-size:var(--t-3)}
/* iOS Safari agrandit la page dès qu'un champ de moins de 16 px reçoit le focus */
input,select,textarea{font-size:var(--t-3)}
/* un tableau large défile seul au lieu de faire défiler toute la page */
.slide table{display:block;overflow-x:auto;max-width:100%}
  /* Meme chose hors des cours : un tableau ne se comprime pas sous la somme de ses
     colonnes, et celui de master/donnees (cinq colonnes) poussait la page à 562 px. */
  .part table,.carte table{display:block;overflow-x:auto;max-width:100%}
.slide td,.slide th{padding-right:var(--e-3)}
/* NAVIGATION SUR TELEPHONE : UN BOUTON QUI DEPLIE, ET PLUS UNE RANGEE QUI DEFILE.
   La rangee qui defile etait un choix delibere — « plutot que quatre rangees empilees » — et il coutait plus
   cher qu il n y paraissait. Mesure sur un ecran de 375 px : la barre d un directeur tient 1067 px de contenu
   dans 338 px. Sept entrees sur dix — Comptabilite, Paie, Classes, Fournitures, Mon espace, Primaire,
   College — sont hors de vue, sans la moindre marque qui dise qu il y a quelque chose a cote. Un depliant
   garde l en-tete court ET ne cache rien : c est ce que font les trois plateformes citees.
   SANS JAVASCRIPT, la rangee defile comme avant : le bouton n existe que si un script le pose. */
.modnav{flex-wrap:wrap;overflow-x:auto;max-width:100%;gap:var(--e-2);padding-bottom:var(--e-1)}
.modnav .btn,.modnav button,.modnav select{white-space:nowrap;padding:var(--e-2) var(--e-3);flex:none}
.modnav:has(.nav-bascule){overflow:visible}
/* SOUS 400 PX, UN LIBELLE PASSE A LA LIGNE (releve du rendu du 05/11/2026) : « 04 : L’Europe de la « révolution
   industrielle » » faisait 377 px pour 282, et la barre defilait sans le dire. */
@media (max-width:400px){.modnav .btn{white-space:normal;flex:1 1 100%;max-width:100%}}
.nav-bascule{display:inline-flex;align-items:center;gap:var(--e-2);min-height:44px}
.modnav[data-ouvert="0"]>:not(.nav-bascule){display:none}
.modnav[data-ouvert="1"]{width:100%}
.modnav[data-ouvert="1"]>:not(.nav-bascule){flex:1 1 100%;min-height:44px;display:flex;align-items:center;justify-content:center}
/* Le separateur entre le menu du profil et les parcours est un trait VERTICAL : deplie en colonne, il devenait
   une barre vide de 44 px au milieu de la liste. Il est decoratif (aria-hidden), on le retire. */
.modnav[data-ouvert="1"] .nav-sep{display:none}
/* CIBLES TACTILES. Au doigt, une cible de moins de 44 px se manque : les entrees du menu en faisaient 43. */
.modnav .btn,.modnav button{min-height:44px;display:inline-flex;align-items:center}
/* barre de compte : logo et prénom sans libellé, pour tenir sur une ou deux rangées */
#compte-bar{gap:var(--e-3)}
#compte-bar .site,#compte-bar .qui{font-size:0;gap:0}
/* Le nom disparait : le logo devient la cible, et il doit alors faire la taille d une cible. */
#compte-bar .site .logo{width:28px;height:28px}
#compte-bar a{min-height:32px}
#compte-bar .site .logo{font-size:var(--t-2)}

#toasts{bottom:175px}

.hero{padding:var(--e-8) 6vw var(--e-5)}
.parts{padding:0 6vw var(--e-8)}
}
/* Tablette : une cellule de code sur une demi-colonne ne tient pas (≈ 32 caractères) */
@media(min-width:751px) and (max-width:1024px){
.split{gap:var(--e-7)}
.split:has(.py),.split:has(pre),.split:has(table){grid-template-columns:minmax(0,1fr)}
}
@media print{
/* Le paysage est fait pour les diapositives ; les pages de compte, de prof, d'admin et les pages
   légales (body.compte) s'impriment en portrait, format des fiches et des listes d'identifiants. */
@page{size:A4 landscape;margin:14mm}
@page fiche{size:A4 portrait;margin:14mm}
body.compte{page:fiche}
body{background:white;color:#172126}
header,footer,#progress,.py-bar,#compte-bar,#sommaire{display:none!important}
.slide,.slide.active{display:block;min-height:0;break-after:page;padding:0;font-size:var(--t-3)}
.slide:last-child{break-after:auto}
h1{font-size:50px}h2{font-size:34px}p,li,td,th{font-size:var(--t-4)}
pre,.py textarea{font-size:var(--t-3);background:#f3f5f1;color:#172126;white-space:pre-wrap;border:1px solid #ccc}
code,.eyebrow,h3,.callout,a,.big{color:#345916}
.lead,details,.small{color:#465256}
/* Les replis fermés sont du bruit à l'impression, mais un corrigé ou une FAQ ouverts avant
   d'imprimer doivent figurer sur la feuille (un enseignant imprime la fiche avec les réponses). */
details{display:none}
details[open]{display:block}
.quiz button{color:#172126}
.split{gap:var(--e-6)}
/* une feuille ne defile pas : ce qui depasse s imprime au lieu d etre coupe */
.defilant{overflow:visible}
.defilant-indice{display:none}
}

h3.matiere{font-size:var(--t-4);letter-spacing:.08em;text-transform:uppercase;color:var(--accent);margin:var(--e-6) 0 var(--e-2)}
.modules li.bientot{opacity:.55}.modules li.bientot .lien{display:block;border:1px dashed var(--line);border-radius:var(--r-s);padding:var(--e-4) var(--e-5);height:100%}

/* ---------- exercices interactifs (assets/exos.js) et coups de pouce progressifs ---------- */
.defi.exo{background:color-mix(in srgb,var(--code) 55%,transparent)}
.defi.exo .consigne{margin:var(--e-2) 0 var(--e-3)}
/* Une question par ligne : le séparateur « · » devenait invisible au milieu d’un paragraphe (R42). */
.defi.exo .q{display:block;margin:var(--e-2) 0;padding-left:2px}
/* Un item et son champ ne se separent pas en fin de ligne : sur telephone, « 0,42 [   ] » suivi de
   « 0,3 » a la ligne suivante ne dit plus ce qu on compare. */
.defi.exo .q.lettre{display:flex;flex-wrap:wrap;align-items:center;gap:var(--e-2)}
.defi.exo .q.lettre::before{flex:none}
.defi.exo .q .trou{flex:0 1 auto;min-width:0}
.defi.exo .q + .q{border-top:1px solid color-mix(in srgb,var(--line) 55%,transparent);padding-top:var(--e-2)}
/* Repère de question, posé par un compteur : le texte de l’exercice n’est pas touché. */
/* Les sous-questions se suivent a. b. c. SUR TOUT L EXERCICE, jamais par paragraphe : un manuel ne
   repart pas a « a. » au milieu d un enonce. Le compteur vit donc sur l exercice. */
.defi.exo{counter-reset:q}
.defi.exo .q.lettre{counter-increment:q}
.defi.exo .q.lettre::before{content:counter(q,lower-alpha) '. ';color:var(--muted);font-weight:600}
/* Exercice déjà réussi : on le dit, on ne le ferme pas. Au-delà de trois tentatives, aucun marqueur — le refaire
   est justement ce qu'il faut (assets/exos.js). */
.defi.exo.deja-fait{border-color:color-mix(in srgb,var(--ok) 55%,var(--line))}
.defi.exo .deja{display:inline-block;margin:0 0 var(--e-3);padding:var(--e-1) var(--e-3);border-radius:var(--r-pill);font-size:var(--t-2);font-weight:600;
  background:color-mix(in srgb,var(--ok) 18%,transparent);color:var(--ok);border:1px solid color-mix(in srgb,var(--ok) 45%,transparent)}
.defi.exo .trou{font:inherit;color:var(--fg);background:var(--bg);border:1px solid var(--line);border-radius:var(--r-s);padding:var(--e-2) var(--e-3);min-width:80px;max-width:100%}
/* LA FRACTION : numérateur sur dénominateur, barre horizontale. Les 269 fractions d’affichage du
   dépôt — 16 fichiers, dont 59 pour les sphères de troisième — portaient ces trois règles dans le
   <style> de leur propre page ; elles vivent ici, donc toute page y a droit, et une page qui
   l’oubliait ne colle plus ses deux nombres (« 84126 »).
   (Le chiffre a d’abord été annoncé à 53 : c’était un `grep -c`, donc des LIGNES d’un HTML
   minifié où une seule ligne porte toute une diapositive, et non des éléments.) */
.frac{display:inline-block;vertical-align:middle;text-align:center;margin:0 .15em}
.frac>span{display:block;padding:0 .3em}
.frac>span:first-child{border-bottom:2px solid currentColor}
/* LA FRACTION À REMPLIR : la barre est tracée D’ABORD, l’élève n’a qu’à poser ses deux valeurs.
   Il n’a plus à décider où va le numérateur dans « 3/4 » — ce qui est justement la confusion que
   la barre existe pour lever. Chaque case est corrigée séparément : on voit laquelle est fausse. */
/* LES DEUX MOITIES SONT DE MEME HAUTEUR, et la barre tombe donc au milieu. Sans cela, une
   fraction dont le champ est EN HAUT et sa voisine dont le champ est EN BAS posaient leurs
   barres a dix pixels l une de l autre sur la meme ligne : « 7,258 = 7 + [ ]/10 + 5/[ ] ».
   Deux rangees 1fr sont egales PAR CONSTRUCTION — pas de hauteur devinee en em, qui aurait
   derive des que les rembourrages du depot, eux, sont en pixels. */
.defi.exo .frac.saisie{margin:0 .25em;display:inline-grid;grid-template-rows:1fr 1fr}
.defi.exo .frac.saisie>span{display:flex;align-items:center;justify-content:center}
.defi.exo .frac.saisie>span{padding:var(--e-1) 0}
.defi.exo .frac.saisie>span:first-child{padding-bottom:var(--e-2)}
.defi.exo .frac.saisie>span:last-child{padding-top:var(--e-2)}
.defi.exo .frac.saisie .trou{min-width:0;width:4.6em;text-align:center;padding:var(--e-1) var(--e-2)}
body.primaire .defi.exo .frac.saisie .trou{width:5.2em}
.defi.exo textarea.trou{width:100%;min-height:80px;display:block;margin-top:var(--e-2)}
/* LE VERDICT SE VOIT SANS LA COULEUR (AC22-4, WCAG 1.4.1). Vert et rouge ne font que 1,63:1 l un
   contre l autre en clair, et 1,13:1 en sombre une fois l encre ok reglee pour le texte (1,33
   avant) : pour qui les distingue mal, un champ juste et un champ faux se ressemblaient trait
   pour trait. Une FORME s ajoute donc a la teinte : un trait plein pour
   ce qui est juste, un trait TIRETE pour ce qui est a revoir — sur les champs et sur les elements a
   ordonner, qui sont des boites —, et une coche ou une croix au bout du texte d une reponse cochee.
   La croix est muette pour les aides techniques (texte de remplacement vide) : exos.js leur ecrit
   deja « — juste » ou « — à revoir », et le signe lu en plus du mot ne dirait rien de neuf. */
.defi.exo .trou.good{border-color:var(--ok);border-width:2px;box-shadow:0 0 0 2px color-mix(in srgb,var(--ok) 35%,transparent)}
.defi.exo .trou.bad{border-color:var(--ko);border-width:2px;border-style:dashed;box-shadow:0 0 0 2px color-mix(in srgb,var(--ko) 35%,transparent)}
.defi.exo .qcm label{display:block;padding:var(--e-2) var(--e-3);border:1px solid var(--line);border-radius:var(--r-s);margin:var(--e-2) 0;cursor:pointer}
.defi.exo .qcm label.good{border-color:var(--ok);color:var(--ok)}
.defi.exo .qcm label.bad{border-color:var(--ko);color:var(--ko);border-style:dashed}
.defi.exo .qcm label.good::after{content:"✔";content:"✔" / "";margin-left:var(--e-2);font-weight:700}
.defi.exo .qcm label.bad::after{content:"✗";content:"✗" / "";margin-left:var(--e-2);font-weight:700}
.defi.exo ol.ordre{list-style:none;padding:0;counter-reset:pos}
.defi.exo ol.ordre li{display:flex;flex-wrap:wrap;align-items:center;gap:var(--e-3);padding:var(--e-2) var(--e-3);border:1px solid var(--line);border-radius:var(--r-s);margin:var(--e-2) 0;counter-increment:pos}
/* LE TEXTE D UN ELEMENT A ORDONNER EST UN SEUL BLOC (releve du 28/10/2026). Dans un flex, chaque
   morceau de texte et chaque <i>, <sub> ou <sup> devenait un element a part, qui ne partage pas
   sa ligne : « Guillaume Apollinaire, » / « Calligrammes » / « : des poemes... » en trois colonnes,
   et les boutons repousses hors de l ecran — 73 modules a 320 px, jusqu a 230 px. exos.js range
   desormais le texte dans .libelle ; sous 12em de place, les boutons passent a la ligne. */
.defi.exo ol.ordre li>.libelle{flex:1 1 12em;min-width:0}
.defi.exo ol.ordre li::before{content:counter(pos);color:var(--muted);min-width:1.4em}
.defi.exo ol.ordre li.good{border-color:var(--ok);border-width:2px}
.defi.exo ol.ordre li.bad{border-color:var(--ko);border-width:2px;border-style:dashed}
.defi.exo .fleches{margin-left:auto;display:flex;gap:var(--e-1)}
.defi.exo .fleches button{padding:var(--e-1) var(--e-3);font-size:var(--t-3);line-height:1.2;min-width:40px;min-height:36px}
.defi.exo .verif{display:flex;align-items:center;gap:var(--e-4);flex-wrap:wrap;margin:var(--e-4) 0 var(--e-2)}
.defi.exo .retour.ok{color:var(--ok)}
.defi.exo .retour.ko{color:var(--ko)}
.defi.exo.reussi{border-color:var(--ok)}
.aides{margin-top:var(--e-3)}
.aides details{margin-top:var(--e-2);padding:var(--e-2) var(--e-4);border:1px dashed var(--line);border-radius:var(--r-s);border-top:1px dashed var(--line)}
.aides details summary{cursor:pointer;color:var(--fg);font-weight:600}
.aides details.corr{border-style:solid;border-color:var(--accent)}
.aides details.corr summary{color:var(--accent)}
.aides details p{margin:var(--e-2) 0}
/* LES FIGURES DE GEOMETRIE, celles qu on compare avec son cahier. currentColor partout : la figure suit le
   theme sans qu on la redessine. Une largeur maximale, parce qu un triangle de six centimetres n a aucune
   raison d occuper tout un ecran de bureau — et 100 % en dessous, pour qu il tienne sur un telephone. */
.fig{display:block;width:100%;max-width:340px;margin:var(--e-3) auto;color:var(--fg);overflow:visible}
.fig text{font-family:inherit}
.aides .fig{max-width:300px;opacity:.95}
.aides .erreur-frequente{border-left:3px solid var(--warn);padding-left:var(--e-3);color:var(--muted)}

/* ---------- primaire (primaire/modules) : lisible par un enfant — plus grand, plus aéré, images en emoji ---------- */
body.primaire .slide{font-size:var(--t-5);line-height:1.6}
body.primaire h1{font-size:clamp(34px,6vw,52px)}
body.primaire h2{font-size:clamp(26px,4vw,36px)}
body.primaire .lead{font-size:var(--t-6)}
body.primaire .def,body.primaire .methode{font-size:var(--t-5);padding:var(--e-4) var(--e-5)}
body.primaire .image{font-size:44px;line-height:1.3;letter-spacing:.08em;text-align:center;margin:var(--e-3) 0}
body.primaire .image.petite{font-size:30px}
/* Les schemas du primaire. Le bloc .image affiche du TEXTE en 44px : parfait pour des emoji,
   inutile pour une droite graduee. .image-svg accueille un vrai dessin, qui suit la couleur du
   texte (currentColor) et donc le theme clair ou sombre sans une ligne de plus. */
.image-svg{margin:var(--e-5) 0;text-align:center}
.image-svg svg{color:var(--fg)}
.image-svg .small{margin-top:var(--e-2);color:var(--muted)}
body.primaire .defi.exo .trou{font-size:var(--t-5);padding:var(--e-3) var(--e-4);min-width:70px}
body.primaire .defi.exo .qcm label{font-size:var(--t-5);padding:var(--e-3) var(--e-4)}
/* La case elle-meme faisait 13 px — la taille par defaut du navigateur — a cote d un texte de
   20 px. Le label de 58 px reste la cible, et le doigt y tombe ; mais a cet age la case doit se
   VOIR. Mesure au telephone, pas a l oeil. */
body.primaire .defi.exo .qcm input[type=checkbox],
body.primaire .defi.exo .qcm input[type=radio]{width:1.1em;height:1.1em;accent-color:var(--accent);
  vertical-align:-.15em;margin-right:var(--e-1)}
body.primaire .defi.exo ol.ordre li{font-size:var(--t-5);padding:var(--e-3) var(--e-4)}
body.primaire .defi.exo button,body.primaire .verif button{font-size:var(--t-4);padding:var(--e-3) var(--e-5)}
body.primaire .defi.exo .fleches button{font-size:var(--t-5);padding:var(--e-2) var(--e-3);min-width:44px;min-height:44px}
body.primaire .aides details summary{font-size:var(--t-4)}
body.primaire table{font-size:var(--t-5)}
/* Emploi du temps : grille de lecture (assets/compte.js, grilleEmploi). Sur un portable elle défile plutôt que de s'écraser. */
.edt{width:100%;border-collapse:collapse;font-size:var(--t-2);margin:var(--e-3) 0}
.edt th,.edt td{border:1px solid var(--line);padding:var(--e-1);vertical-align:top;text-align:left}
.edt th{background:var(--code);color:var(--muted);font-weight:600;text-align:center}
.edt th.edt-h{width:56px;text-align:right;color:var(--muted);font-weight:400}
.edt .edt-jour{background:color-mix(in srgb,var(--accent) 10%,transparent)}
.edt .edt-case{background:color-mix(in srgb,var(--accent) 16%,transparent);border-left:3px solid var(--accent);border-radius:var(--r-s);padding:var(--e-1) var(--e-2);margin-bottom:var(--e-1);line-height:1.3}
.edt .edt-case:last-child{margin-bottom:0}
@media(max-width:820px){.edt{display:block;overflow-x:auto;white-space:nowrap}}
/* Compteur avant la correction detaillee (exos.js) : elle ne s ouvre qu apres quatre tentatives. */
/* ========================= « JE N Y ARRIVE PAS » : l aide didactique (16/10/2026)
   Les trois coups de pouce sont DISCRETS A DESSEIN : ils soufflent, ils n expliquent pas.
   Quand ils ne suffisent pas, l eleve n a plus que la correction — c est-a-dire la reponse,
   qui n apprend rien. Ce bloc comble ce vide : il reprend la question mot a mot, rappelle le
   vocabulaire et la propriete, refait le geste, puis rend la main. Rose tres vif et voulu :
   il doit se voir d un coup d oeil au milieu des pointilles gris.
   Il n est PAS cache ici : c est exos.js qui le masque jusqu au deuxieme echec. */
.aides details.jynap{margin-top:var(--e-4);padding:0;overflow:hidden;counter-reset:pas;
  border:2px solid var(--rose-vif);border-top:2px solid var(--rose-vif);
  border-radius:var(--r-s);background:var(--rose-soft)}
.aides details.jynap>summary{cursor:pointer;list-style:none;display:flex;align-items:center;
  gap:var(--e-3);margin:0;padding:var(--e-3) var(--e-4);
  background:var(--rose-vif);color:var(--rose-encre);
  font-weight:800;font-size:var(--t-5);letter-spacing:.01em;line-height:1.25}
.aides details.jynap>summary::-webkit-details-marker{display:none}
.aides details.jynap>summary::marker{content:''}
.aides details.jynap>summary::before{content:'?';flex:0 0 auto;display:flex;
  align-items:center;justify-content:center;width:1.7em;height:1.7em;border-radius:50%;
  background:var(--rose-encre);color:var(--rose-vif);font-size:var(--t-4);line-height:1}
.aides details.jynap[open]>summary{border-bottom:2px solid var(--rose-vif)}
/* LES QUATRE PAS SONT FRERES, sans conteneur : voir le point 4 de l en-tete. Le compteur
   vit donc sur le <details>, et le filet de separation court sur toute la largeur. */
.aides details.jynap .bloom-pas{counter-increment:pas;padding:var(--e-4)}
.aides details.jynap .bloom-pas+.bloom-pas{border-top:1px dashed var(--rose-line)}
.aides details.jynap .bloom-pas>b{display:block;margin-bottom:var(--e-2);
  color:var(--rose-vif);font-size:var(--t-4)}
.aides details.jynap .bloom-pas>b::before{content:counter(pas) '. '}
.aides details.jynap .etapes>li::before{background:var(--rose-vif);color:var(--rose-encre)}
.aides details.jynap p{margin:var(--e-2) 0}
/* le mot de vocabulaire qu on rappelle : on le MONTRE, on ne le mentionne pas */
.aides details.jynap .mot{display:inline-block;padding:.05em .6em;border-radius:var(--r-pill);max-width:100%;
  box-sizing:border-box;overflow-wrap:anywhere;
  background:var(--rose-vif);color:var(--rose-encre);font-weight:700;white-space:nowrap;line-height:1.25}
/* une etiquette plus large que l aide passe a la ligne (releve du 04/11/2026 : « organisation internationale »
   coupee a 320 px) ; les courtes restent d un seul tenant */
@media (max-width:480px){.aides details.jynap .mot{white-space:normal}}
/* ===== LES SEANCES D UN CHAPITRE (F23, prototype) =====
   Le bandeau dit trois choses et pas une de plus : ou l on est, ce qu on vise, et quand on a
   fini. Il est pose en tete de chaque diapositive de la seance par assets/seances.js, qui lit
   un plan JSON de la page — le decoupage est une decision humaine, le script ne fait que
   l afficher. */
.seance-bandeau{border-left:3px solid var(--accent);background:var(--code);border-radius:0 var(--r-s) var(--r-s) 0;
  padding:var(--e-3) var(--e-4);margin:0 0 var(--e-5)}
.seance-bandeau p{margin:0}
.seance-bandeau .ou{font-size:var(--t-2);color:var(--muted);letter-spacing:.04em;text-transform:uppercase}
.seance-bandeau .ou b{color:var(--fg)}
.seance-bandeau .objectif{margin-top:var(--e-2);font-size:var(--t-4);color:var(--fg)}
.seance-bandeau .fin{margin-top:var(--e-2);font-size:var(--t-2);color:var(--muted)}
.seance-bandeau.fini{border-left-color:var(--ok)}
.seance-bandeau.fini .fin{color:var(--ok)}
/* Au-dela de la selection, l exercice reste la — « conserver la banque comme ressource ». Le filet
   pointille dit qu il est HORS de la selection de l etape, pas qu il est facultatif : il compte pour
   l etape comme pour le devoir, et le texte du bandeau le dit (revue du 25/10/2026). */
.slide.seance-libre .seance-bandeau{border-left-style:dotted}
.slide.seance-bilan .seance-bandeau{border-left-color:var(--warn)}
.seance-bandeau.bilan{border-left-color:var(--warn)}
.seance-bandeau.bilan .ou b{color:var(--warn)}
/* Hors etape : ce qui n appartient a aucune etape du plan — en fin de chapitre, et en tete pour les
   « Defis » de lycee. Un trait pointille, pour que la diapositive ne se lise pas comme une etape qu on
   aurait sautee ; mais ses exercices comptent pour le devoir et la grille de l enseignant, et le
   bandeau l ecrit. Le trait ne dit donc pas « supplement ». */
.seance-bandeau.hors{border-left-color:var(--line);border-left-style:dotted}
.seance-bandeau.hors .ou b{color:var(--muted)}
/* Le sommaire liste les seances AVANT les 152 diapositives : c est le plan du chapitre. */
.seances-plan{border-bottom:1px solid var(--line);padding-bottom:var(--e-4);margin-bottom:var(--e-4)}
.seances-titre{margin:0 0 var(--e-2);font-size:var(--t-2);color:var(--muted);letter-spacing:.04em;text-transform:uppercase}
.seances-plan ol{margin:0;padding-left:var(--e-6)}
.seances-plan li{margin:var(--e-1) 0;display:flex;gap:var(--e-3);align-items:baseline;justify-content:space-between}
.seances-plan .combien{color:var(--muted);font-size:var(--t-1);white-space:nowrap}
/* Le « #sommaire » est nécessaire : la règle générale « #sommaire .combien », plus bas, porte un identifiant
   et l'emportait, si bien qu'une étape finie gardait le gris des autres (relevé du 25/10/2026). */
.seances-plan .combien.fini,#sommaire .seances-plan .combien.fini{color:var(--ok)}
/* LA LISTE DES ETAPES PORTE SON NUMERO (AC-24). Le bandeau dit « Étape k sur N », et le sommaire
   n ecrivait aucun numero : la regle « #sommaire ol » (list-style:none, padding:0), specificite 1,0,1,
   bat « .seances-plan ol », 0,1,1, et l eleve devait compter les lignes pour retrouver l etape k.
   Rendre la puce ne suffirait pas : chaque ligne est en display:flex, et une boite flex ne porte
   pas de marqueur de liste. Le numero est donc un compteur, pose DANS le lien comme le « 01 » des
   diapositives juste en dessous — il en a la place, la teinte et la taille. */
#sommaire .seances-plan ol{counter-reset:etape}
#sommaire .seances-plan li{counter-increment:etape}
#sommaire .seances-plan a::before{content:counter(etape);color:var(--muted);font-variant-numeric:tabular-nums;font-size:var(--t-2);min-width:2.2em}

/* --- les figures du bloc rose : voir l en-tete de poser_jynap_figures.py --- */
.aides details.jynap .fig{max-width:360px;opacity:1;margin:var(--e-3) auto}
.aides details.jynap .fig-fr{margin:var(--e-3) 0}
.aides details.jynap .fig-fr figcaption{color:var(--muted)}
.aides details.jynap .fig,.aides details.jynap .fig-fr{--accent:var(--rose-vif)}
.aides details.jynap figure{padding:0}
/* LA FIGURE D UN GESTE est plus petite et calee a gauche : elle appartient a SA ligne.
   Centrees et pleine taille, quatre figures d affilee se liraient comme quatre figures
   independantes au lieu d une progression. */
.aides details.jynap .etapes .fig{max-width:190px;margin:var(--e-2) 0 var(--e-1)}
/* LA LEGENDE EST DU TEXTE, PAS DU DESSIN. Dans le SVG elle subissait l echelle : un 14
   devenait un 33 quand la feuille etirait un viewBox de 154 a 360 px. En <figcaption> elle
   garde la taille du reste de la page, se renvoie a la ligne, et reste lisible par un
   lecteur d ecran. Meme raison que figures_francais.py : ce qui porte des MOTS sort du SVG. */
.aides details.jynap .fig-leg{margin:var(--e-3) auto;padding:0;max-width:360px;text-align:center}
.aides details.jynap .fig-leg figcaption{margin-top:var(--e-1);font-size:var(--t-2);
  font-weight:700;color:var(--rose-vif)}
.aides details.jynap .etapes .fig-leg{margin:var(--e-2) 0 var(--e-1);max-width:190px;text-align:left}
/* --- l instant ou le bouton rose parait : voir poser_annonce_jynap.py --- */
@keyframes jynap-parait{0%{transform:scale(.97);box-shadow:0 0 0 0 var(--rose-vif)}
  55%{box-shadow:0 0 0 12px transparent}
  100%{transform:scale(1);box-shadow:0 0 0 0 transparent}}
.aides details.jynap.parait{animation:jynap-parait .7s ease-out}
@keyframes flash-rose{0%{opacity:0}22%{opacity:.15}100%{opacity:0}}
.flash-rose{position:fixed;inset:0;z-index:58;pointer-events:none;
  background:var(--rose-vif);opacity:0;animation:flash-rose .5s ease-out}
.toast.aide{border-color:var(--rose-vif)}
.toast.aide b{color:var(--rose-vif)}
.toast.aide .icone{flex:none;display:flex;align-items:center;justify-content:center;
  width:40px;height:40px;border-radius:50%;background:var(--rose-vif);
  color:var(--rose-encre);font-size:var(--t-6);font-weight:800}
.corr-compte{display:inline-block;margin-left:var(--e-3);font-size:var(--t-4);opacity:.72;font-style:italic}
/* Choix d un QCM a la forme <li data-ok> : exos.js les rend cliquables. */
.choix>li[role=radio]{cursor:pointer;border-radius:var(--r-s);padding:var(--e-2) var(--e-3);transition:background .12s}
.choix>li[role=radio]:hover,.choix>li[role=radio]:focus-visible{background:var(--wash)}
.choix>li.choisi{background:var(--wash-2);font-weight:600}
.choix>li.good{background:rgba(46,204,113,.18)}
.choix>li.bad{background:rgba(231,76,60,.18)}
/* le fond vert ou rouge ne suffit pas : la meme coche et la meme croix que les QCM (voir plus haut) */
.choix>li.good::after{content:"✔";content:"✔" / "";margin-left:var(--e-2);font-weight:700}
.choix>li.bad::after{content:"✗";content:"✗" / "";margin-left:var(--e-2);font-weight:700}

/* ------------------------------------------------------------------ le sommaire
   Pose le 04/10/2026. Le panneau est construit par `assets/cours.js` et n existe
   dans aucun fichier de cours : les 714 modules le recoivent sans regeneration.
   Il se superpose a la diapositive plutot que de la pousser, pour que fermer le
   sommaire rende exactement l ecran qu on avait avant de l ouvrir. */
#sommaire{position:fixed;inset:0;z-index:40;background:var(--bg);overflow:auto;
  padding:var(--e-7) 5vw var(--e-9)}
#sommaire .dedans{max-width:860px;margin:0 auto}
#sommaire h2{margin:0}
#sommaire .small{color:var(--muted);margin:var(--e-2) 0 var(--e-6)}
#sommaire ol{list-style:none;padding:0;margin:0}
#sommaire li.rubrique{margin:var(--e-6) 0 var(--e-2);color:var(--muted);
  font-size:var(--t-1);letter-spacing:.12em;text-transform:uppercase}
#sommaire li.rubrique:first-child{margin-top:0}
#sommaire a{display:flex;align-items:baseline;gap:var(--e-4);
  padding:var(--e-3) var(--e-2);border-bottom:1px solid var(--line);
  color:var(--fg);text-decoration:none}
#sommaire a:hover,#sommaire a:focus-visible{color:var(--accent);background:var(--wash)}
#sommaire a[aria-current=true]{color:var(--accent);font-weight:600}
#sommaire .num{color:var(--muted);font-variant-numeric:tabular-nums;
  font-size:var(--t-2);min-width:2.2em}
#sommaire a[aria-current=true] .num{color:var(--accent)}
#sommaire .quoi{flex:1 1 auto}
#sommaire .combien{color:var(--muted);font-size:var(--t-1);white-space:nowrap}

/* ---- La dictée (dictee.js) ------------------------------------------------------------------ */
.defi.dictee{background:color-mix(in srgb,var(--code) 55%,transparent)}
.dictee-outils{display:flex;flex-wrap:wrap;gap:var(--e-2);align-items:center;margin:var(--e-3) 0}
.dictee-outils button{padding:var(--e-2) var(--e-3)}
.dictee-outils .debit{color:var(--muted);font-size:var(--t-1);display:flex;align-items:center;gap:var(--e-2)}
.dictee-saisie{width:100%;font:inherit;line-height:1.7;padding:var(--e-3);
  border:1px solid var(--line);border-radius:var(--r-s);background:var(--bg);color:var(--fg)}
.dictee-sortie:empty{display:none}
.dictee-sortie .score{margin:var(--e-3) 0 var(--e-2);font-weight:600}
.dictee-mots{line-height:2.1}
.dictee-mots .mot{padding:1px var(--e-1);border-radius:var(--r-s)}
/* `--bad` N A JAMAIS ETE DECLARE (AC22-3 a) : le mot faux prenait donc dans les deux themes la
   valeur de repli #f87171, un rouge clair de theme sombre — 2,58:1 sur la dictee en clair. Il
   prend l encre du faux de tout le depot : 4,95 en clair, 5,93 en sombre sur la meme surface.
   Les replis de `--ok` tombent aussi : le jeton existe. */
.dictee-mots .bon{color:var(--ok)}
.dictee-mots .faux{color:var(--ko);text-decoration:underline wavy}
.dictee-mots .oubli{color:var(--warn);outline:1px dashed currentColor}
.dictee-mots .trop{color:var(--muted);text-decoration:line-through}
.dictee-sortie .legende{color:var(--muted);font-size:var(--t-1)}
.dictee-avis,.dictee-texte{color:var(--muted)}
.dictee-texte{font-size:var(--t-1);border-left:2px solid var(--line);padding-left:var(--e-3)}

/* ---- Les cartes de vocabulaire (cartes.js) --------------------------------------------------- */
.defi.cartes{background:color-mix(in srgb,var(--code) 55%,transparent)}
.cartes-compte{color:var(--muted);font-size:var(--t-1);margin:var(--e-2) 0 var(--e-3)}
.cartes-ui .carte{border:1px solid var(--line);border-radius:var(--r-s);padding:var(--e-5);
  margin:var(--e-3) 0;text-align:center;background:var(--bg)}
.cartes-ui .recto{font-size:var(--t-4);font-weight:600;margin:var(--e-3) 0}
.cartes-ui .verso{border-top:1px solid var(--line);margin-top:var(--e-4);padding-top:var(--e-3)}
.cartes-ui .sens{font-size:var(--t-2)}
.cartes-ui .famille{color:var(--muted);font-size:var(--t-1)}
.cartes-ui .exemple{color:var(--muted)}
.cartes-ui .juger{display:flex;flex-wrap:wrap;gap:var(--e-2);justify-content:center;margin-top:var(--e-3)}
.cartes-ui .juger button{flex:1 1 7em;padding:var(--e-2) var(--e-3)}
/* meme jeton absent, meme repli #f87171 : le bord du bouton « à revoir » prend l encre du faux */
.cartes-ui .q-revoir{border-color:var(--ko)}
.cartes-ui .q-facile{border-color:var(--ok)}
.cartes-boutons{display:flex;flex-wrap:wrap;gap:var(--e-2)}
.cartes-fin{color:var(--muted)}

/* ---- Schémas de l'aide « Je n'y arrive pas » (figures_aide.py) ------------------------------- */
.fig-fr.suite .pas{list-style:none;display:flex;flex-wrap:wrap;gap:var(--e-6);
  margin:0;padding:0;counter-reset:pas}
.fig-fr.suite .pas>li{counter-increment:pas;position:relative;display:flex;flex-direction:column;
  gap:2px;border:1px solid var(--line);border-radius:var(--r-s);
  padding:var(--e-2) var(--e-3) var(--e-2) 2.4em}
.fig-fr.suite .pas>li::before{content:counter(pas);position:absolute;left:var(--e-2);top:50%;
  transform:translateY(-50%);display:flex;align-items:center;justify-content:center;
  width:1.5em;height:1.5em;border-radius:50%;background:var(--accent);color:var(--bg);
  font-size:var(--t-1);font-weight:700;line-height:1}
/* LA FLECHE EST A DROITE DE CHAQUE CASE, et non a gauche de la suivante. A gauche, un
   retour a la ligne la posait SEULE EN DEBUT DE LIGNE, pointant vers rien. A droite,
   elle termine la ligne en pointant vers ce qui continue en dessous — ce qui se lit. */
.fig-fr.suite .pas>li:not(:last-child)::after{content:"→";position:absolute;right:-1.05em;
  top:50%;transform:translateY(-50%);color:var(--muted)}
.fig-fr.suite .quoi{color:var(--muted);font-size:var(--t-1)}
.fig-fr.suite .boucle{margin:var(--e-3) 0 0;color:var(--muted);font-size:var(--t-1)}

.fig-fr.duo{display:flex;flex-wrap:wrap;align-items:center;gap:var(--e-3)}
.fig-fr.duo figcaption{flex-basis:100%}
.fig-fr.duo .cote{flex:1 1 11em;min-width:0;border:1px solid var(--line);
  border-radius:var(--r-s);padding:var(--e-3)}
.fig-fr.duo .cote>b{display:block;margin-bottom:var(--e-2);color:var(--accent);
  font-size:var(--t-1);text-transform:uppercase;letter-spacing:.04em}
.fig-fr.duo .entre{flex:0 0 auto;color:var(--muted);font-size:var(--t-5)}

.fig-fr.prop{display:flex;flex-wrap:wrap;align-items:center;gap:var(--e-4)}
.fig-fr.prop figcaption{flex-basis:100%}
.fig-fr.prop table{border-collapse:collapse;flex:1 1 15em}
/* Enveloppe par cours.js (.defilant), le tableau n est plus l element de flex : l enveloppe prend sa place — la meme
   part de la ligne —, et le tableau la remplit. Sans cela, il retombait a la largeur de son contenu. */
.fig-fr.prop>.defilant{flex:1 1 15em;min-width:0}
.fig-fr.prop th,.fig-fr.prop td{border:1px solid var(--line);padding:var(--e-2) var(--e-3);
  text-align:center;font-variant-numeric:tabular-nums}
.fig-fr.prop th{color:var(--accent);font-weight:600;text-align:left;white-space:nowrap}
.fig-fr.prop .vide{color:var(--faint)}
.fig-fr.prop .op span{display:inline-block;border:1px solid var(--accent);
  border-radius:var(--r-pill);padding:var(--e-1) var(--e-3);color:var(--accent);
  font-weight:700;white-space:nowrap}

.fig-fr.lien .ligne{align-items:flex-end}
.fig-fr.lien .m{display:flex;flex-direction:column;gap:2px;padding:var(--e-1) var(--e-2);
  border-bottom:2px solid transparent}
.fig-fr.lien .m.tenu{border-bottom-color:var(--accent);color:var(--accent);font-weight:600}
.fig-fr.lien .etiq{color:var(--muted);font-size:var(--t-1);font-weight:400}
.fig-fr.lien .arcs{list-style:none;margin:var(--e-3) 0 0;padding:0}
.fig-fr.lien .arcs li{color:var(--muted);font-size:var(--t-2);padding:2px 0}
.fig-fr.lien .arcs b{color:var(--fg)}
.fig-fr.lien .saut{color:var(--faint)}

.fig-fr.arbre .q{margin:0 0 var(--e-2);font-weight:600}
.fig-fr.arbre ul{list-style:none;margin:0;padding:0 0 0 var(--e-5);
  border-left:2px solid var(--line)}
.fig-fr.arbre li{position:relative;padding:var(--e-2) 0}
.fig-fr.arbre li::before{content:"";position:absolute;left:calc(-1 * var(--e-5));top:1.15em;
  width:var(--e-4);height:2px;background:var(--line)}
.fig-fr.arbre .rep{display:inline-block;margin-right:var(--e-2);padding:0 var(--e-2);
  border:1px solid var(--line);border-radius:var(--r-pill);color:var(--accent);
  font-size:var(--t-1);font-weight:600}
.fig-fr.arbre .verdict{font-weight:600}
.fig-fr.arbre .noeud .noeud{margin-top:var(--e-2)}
.fig-fr.morceaux .ligne{gap:0;align-items:stretch}
.fig-fr.morceaux.detache .ligne{gap:var(--e-2)}
.fig-fr.morceaux .mc{display:flex;flex-direction:column;align-items:center;gap:2px;
  padding:var(--e-2) var(--e-3);border:1px solid var(--line)}
.fig-fr.morceaux .mc+.mc{margin-left:-1px;border-left-color:var(--accent)}
.fig-fr.morceaux.detache .mc+.mc{margin-left:0;border-left-color:var(--line)}
.fig-fr.morceaux .mc:first-child{border-radius:var(--r-s) 0 0 var(--r-s);background:var(--wash)}
.fig-fr.morceaux .mc:last-child{border-radius:0 var(--r-s) var(--r-s) 0}
.fig-fr.morceaux .nom{min-height:1.2em;color:var(--accent);font-size:var(--t-1);
  text-transform:uppercase;letter-spacing:.04em;line-height:1.2}
.fig-fr.morceaux .mc>b{font-size:var(--t-4)}
.fig-fr.morceaux .fait{margin:var(--e-3) 0 0;font-size:var(--t-4);font-weight:700}

.fig-fr.alignees table{border-collapse:collapse}
.fig-fr.alignees th[scope=row]{padding-right:var(--e-3);text-align:left;white-space:nowrap;
  color:var(--accent);font-size:var(--t-1);text-transform:uppercase;letter-spacing:.04em}
.fig-fr.alignees td{padding:var(--e-1) var(--e-2);text-align:center}
/* la case qui change prend un FOND ET un soulignement : jamais la couleur seule */
.fig-fr.alignees td.jeu{background:color-mix(in srgb,var(--accent) 12%,transparent);
  border-bottom:2px solid var(--accent);font-weight:600}
.fig-fr.alignees td.verdict{padding-left:var(--e-3);color:var(--muted);font-size:var(--t-1)}

.fig-fr.autour .centre{display:inline-block;margin:0 0 var(--e-2);padding:var(--e-2) var(--e-4);
  border:2px solid var(--accent);border-radius:var(--r-s);color:var(--accent);font-weight:700}
.fig-fr.autour .titre{margin:var(--e-3) 0 var(--e-1);color:var(--muted);font-size:var(--t-1);
  text-transform:uppercase;letter-spacing:.04em}
.fig-fr.autour .ligne{display:flex;flex-wrap:wrap;gap:var(--e-2);align-items:center}
.fig-fr.autour .el{display:inline-flex;align-items:baseline;gap:var(--e-1);
  padding:var(--e-1) var(--e-3);border:1px solid var(--line);border-radius:var(--r-pill)}
.fig-fr.autour .fl{color:var(--accent);font-weight:700}
/* ce qui ne passe pas est BARRE, et non simplement absent : une absence ne s enseigne pas */
.fig-fr.autour .ligne.bloque .el{color:var(--muted)}
.fig-fr.autour .ligne.bloque .txt{text-decoration:line-through}
.fig-fr.autour .nom{color:var(--muted);font-size:var(--t-1)}

.fig-fr.rangs table{border-collapse:collapse;font-variant-numeric:tabular-nums}
.fig-fr.rangs th,.fig-fr.rangs td{min-width:2.2em;padding:var(--e-1) var(--e-3);
  border:1px solid var(--line);text-align:center}
.fig-fr.rangs th[scope=col]{color:var(--accent);font-size:var(--t-1);font-weight:600;
  text-transform:uppercase;letter-spacing:.03em}
.fig-fr.rangs th[scope=row]{padding-right:var(--e-3);border:0;text-align:left;
  white-space:nowrap;color:var(--muted);font-size:var(--t-1)}
/* la virgule est une BORDURE, pas une idee */
.fig-fr.rangs .apres-virgule{border-left:2px solid var(--accent)}
.fig-fr.rangs .facteur{margin:var(--e-2) 0 0;color:var(--muted);font-size:var(--t-1)}

.fig-fr.temps .axe{display:flex;flex-wrap:wrap;gap:var(--e-4);align-items:flex-start;
  margin-top:var(--e-4);padding-top:var(--e-3);border-top:2px solid var(--line)}
.fig-fr.temps .zone{position:relative;display:flex;flex-direction:column;gap:var(--e-1);
  flex:1 1 8em}
.fig-fr.temps .zone .t{color:var(--muted);font-size:var(--t-1);text-transform:uppercase;
  letter-spacing:.04em}
.fig-fr.temps .zone.maintenant .t{color:var(--accent);font-weight:700}
.fig-fr.temps .zone.maintenant::before{content:"";position:absolute;
  left:calc(-1 * var(--e-2));top:calc(-1 * var(--e-3) - 2px);width:3px;height:var(--e-4);
  background:var(--accent)}
.fig-fr.temps .ev{padding:var(--e-1) var(--e-2);border:1px solid var(--line);
  border-radius:var(--r-s)}
/* un POINT et une DUREE ne se dessinent pas pareil : c est toute la lecon du temps verbal */
.fig-fr.temps .ev.duree{border-radius:var(--r-pill);background:var(--wash)}

/* ---- Schémas du français et de l'histoire-géo (figures_francais.py) -------------------------- */
.fig-fr{margin:var(--e-4) 0;padding:0}
.fig-fr figcaption{color:var(--muted);font-size:var(--t-1);margin-top:var(--e-2)}
.fig-fr .ligne{display:flex;flex-wrap:wrap;gap:var(--e-2);align-items:flex-end}

.fig-fr.phrase .groupe{display:flex;flex-direction:column;gap:2px;
  border:1px solid var(--line);border-radius:var(--r-s);padding:var(--e-2) var(--e-3)}
.fig-fr.phrase .groupe.nomme{border-color:var(--accent)}
.fig-fr.phrase .etiq{color:var(--accent);font-size:var(--t-1);text-transform:uppercase;
  letter-spacing:.04em}

.fig-fr.accords .mot{border-bottom:2px solid transparent;padding:2px var(--e-1)}
.fig-fr.accords .mot.porte{border-bottom-color:var(--accent);color:var(--accent)}
.fig-fr.accords .marque{display:block;margin-top:var(--e-2);color:var(--muted);
  font-size:var(--t-1)}

.fig-fr.syllabes .syl{border:1px solid var(--line);border-radius:var(--r-pill);
  padding:var(--e-2) var(--e-3)}
.fig-fr.syllabes .compte{display:block;margin-top:var(--e-2);color:var(--muted);
  font-size:var(--t-1)}

.fig-fr.famille{display:flex;flex-wrap:wrap;gap:var(--e-2);align-items:center}
.fig-fr.famille .radical{border:1px solid var(--accent);border-radius:var(--r-s);
  padding:var(--e-2) var(--e-3);color:var(--accent);font-weight:600}
.fig-fr.famille .fleche{color:var(--muted)}
.fig-fr.famille .derives{display:flex;flex-wrap:wrap;gap:var(--e-2)}
.fig-fr.famille .derive{border:1px solid var(--line);border-radius:var(--r-s);
  padding:var(--e-2) var(--e-3)}

.fig-fr.tableau table{border-collapse:collapse;width:100%}
.fig-fr.tableau th,.fig-fr.tableau td{border:1px solid var(--line);
  padding:var(--e-2) var(--e-3);text-align:left}
.fig-fr.tableau th{color:var(--accent);font-weight:600}

.fig-fr.texte{border-left:3px solid var(--accent);padding-left:var(--e-4)}
.fig-fr.texte .l{display:block;line-height:1.8}

.fig-fr.frise ol{list-style:none;margin:0;padding:0 0 0 var(--e-5);
  border-left:2px solid var(--line)}
.fig-fr.frise li{position:relative;display:flex;flex-wrap:wrap;gap:var(--e-3);
  padding:var(--e-2) 0}
.fig-fr.frise li::before{content:"";position:absolute;left:calc(-1 * var(--e-5) - 6px);
  top:1em;width:9px;height:9px;border-radius:50%;background:var(--accent)}
.fig-fr.frise .date{color:var(--accent);font-variant-numeric:tabular-nums;
  min-width:6.5em;font-weight:600}
.fig-fr.frise .quoi{flex:1 1 12em}

.fig-fr.lieux .nord{display:block;color:var(--muted);font-size:var(--t-1);
  margin-bottom:var(--e-2)}
.fig-fr.lieux table{border-collapse:collapse}
.fig-fr.lieux td{border:1px solid var(--line);padding:var(--e-3);min-width:4.5em;
  height:2.6em;text-align:center;font-size:var(--t-1)}
.fig-fr.lieux td.pris{border-color:var(--accent);color:var(--accent)}

.fig-fr.rose svg{max-width:160px}

/* ---- Écouter un mot étranger (parler.js) ----------------------------------------------------- */
/* Seul un element REELLEMENT prononcable est souligne : la classe est posee par parler.js
   quand il a trouve une voix. Sans cela, le pointille annoncerait un son absent. */
.dire.parlable{border-bottom:1px dotted var(--line)}
button.dire-ecouter{font-size:var(--t-1);line-height:1;padding:2px var(--e-1);margin-left:var(--e-2);
  border-radius:var(--r-pill);vertical-align:baseline;color:var(--accent);border-color:var(--accent)}
button.dire-ecouter.parle{background:color-mix(in srgb,var(--accent) 22%,transparent)}

/* ---- Schémas des langues vivantes (figures_langue.py) ---------------------------------------- */
.fig-fr.dialogue ol{list-style:none;margin:0;padding:0}
.fig-fr.dialogue li{display:grid;grid-template-columns:auto minmax(0,1fr);gap:var(--e-2) var(--e-3);
  padding:var(--e-2) 0;border-bottom:1px solid var(--line)}
.fig-fr.dialogue li:last-child{border-bottom:0}
.fig-fr.dialogue .qui{color:var(--accent);font-weight:600;white-space:nowrap}
.fig-fr.dialogue .dit{grid-column:2}
.fig-fr.dialogue .trad{grid-column:2;color:var(--muted);font-size:var(--t-1);font-style:italic}

.fig-fr.phrase-mots .mot{border:1px solid var(--line);border-radius:var(--r-s);
  padding:var(--e-2) var(--e-3)}
.fig-fr.phrase-mots .entier{display:block;margin-top:var(--e-3);color:var(--muted);
  font-size:var(--t-1)}

/* ===== LA MISE EN PAGE D APPLICATION (rail, barre haute, cartes, parcours) =====
   Reprise de la maquette d audit : proportions, rayons, graisses et paliers.
   LES COULEURS NE CHANGENT PAS : tout vient des jetons definis plus haut, donc le
   theme sombre suit sans une regle de plus. Ces classes vivaient dans mon-espace.html,
   ou elles ne servaient qu a une page ; ici elles servent a toutes. */
/* MON ESPACE — la structure de la maquette APEX, avec les couleurs du depot.
   Les proportions, les rayons, les graisses et les paliers viennent de la maquette ; les
   teintes viennent des jetons existants, donc le theme sombre suit sans une ligne de plus. */
body.espace{background:var(--bg)}
/* LE RAIL NE S AFFICHE PLUS, SUR AUCUNE PAGE. La maquette ne connait pas de rail : ses
   ecrans se naviguent par une barre horizontale, et le site s aligne dessus. Le balisage
   reste en place — il ne coute rien et le jour ou un ecran voudra un rail, il est la. */
.shell{max-width:1440px;margin:auto;display:grid;grid-template-columns:minmax(0,1fr);min-height:100dvh}
.sidebar{background:var(--sheet);border-right:1px solid var(--line);padding:var(--e-7) var(--e-5) var(--e-6);display:flex;flex-direction:column}
.sidebar{display:none}   /* APRES la regle ci-dessus : a specificite egale, la derniere gagne */
.sidebar .brand{display:block;padding:0 var(--e-3);margin:0 0 var(--e-8);text-decoration:none;font-size:var(--t-5);letter-spacing:.1em;font-weight:700;color:var(--fg)}
.navigation{display:grid;gap:var(--e-2)}
/* `text-decoration:none` : les sept liens du rail etaient SOULIGNES, faute de remise a
   zero. Un lien de navigation est un jeton, pas une note de bas de page. */
.nav-link{text-decoration:none;display:flex;gap:var(--e-3);align-items:center;text-align:left;width:100%;font-size:var(--t-2);padding:var(--e-3) var(--e-4);border:0;border-radius:var(--r-s);min-height:44px;background:none;color:var(--muted);cursor:pointer}
.nav-link:hover{background:var(--wash)}
.nav-link.active{background:var(--accent-l);color:var(--fg);font-weight:600}
.nav-link .pastille{margin-left:auto;min-width:1.4em;padding:0 .4em;border-radius:var(--r-pill);background:var(--accent);color:var(--sheet);font-size:var(--t-1);text-align:center}
.sidebar-bottom{margin-top:auto;padding:var(--e-7) var(--e-3) 0;font-size:var(--t-1)}
.sidebar-bottom a{color:var(--muted)}
.sidebar-bottom small{display:block;margin-top:var(--e-3);color:var(--faint);font-size:var(--t-1)}
.content{min-width:0;display:flex;flex-direction:column}
/* UN SEUL BANDEAU. Cette barre etait blanche, posee sous la barre d application qui l est
   aussi : deux surfaces empilees, dont celle-ci ne portait qu un bouton deja offert
   au-dessus. Et comme la coque est centree a 1440 px tandis que la barre d application
   couvre la fenetre, elle devenait un rectangle blanc flottant au-dela. La maquette
   ecrit sa barre SANS fond — `.mock-nav{padding:18px 26px;border-bottom:1px solid
   var(--line)}` — et c est ce qu on reprend : le papier passe dessous. */
header.topbar{display:flex;align-items:center;justify-content:space-between;gap:var(--e-5);padding:var(--e-6) var(--e-8) var(--e-5);border-bottom:1px solid var(--line);background:transparent;position:static}
header.topbar .crumb{font-size:var(--t-2);color:var(--muted)}
header.topbar nav.modnav{margin-left:auto}
/* LES JETONS DE NAVIGATION, REPRIS DE `.mock-nav a` : un contour transparent qui ne se
   revele qu au survol et au focus, un rayon de 22 px, 44 px de haut. Sans fond blanc,
   ils se posent sur le papier au lieu de dessiner une seconde rangee de cartes. */
/* `var(--r-pill)` et non les 22 px de la maquette : dans `style.css` les rayons viennent des
   jetons, et le test `echelle` le garde. Sur un jeton de 44 px de haut, un rayon de 22 px EST
   une pilule — la forme est la meme, c est l ecriture qui rentre dans l echelle du depot. */
header.topbar nav.modnav a.btn{background:transparent;border:1px solid transparent;border-radius:var(--r-pill);text-decoration:none}
/* L ENCRE RESTE CELLE DU TEXTE AU SURVOL. `.btn:hover` (plus haut) pose `color:var(--bg)`, faite pour un aplat
   violet ; ici le fond reste transparent, et le libelle prenait la couleur de la page : invisible, en clair comme en
   sombre (constat de l utilisateur du 27/10/2026). `.principal` et `[aria-current]`, ecrits plus bas avec la meme
   specificite, gardent leur propre encre. */
header.topbar nav.modnav a.btn:hover,header.topbar nav.modnav a.btn:focus-visible{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent);color:var(--fg)}
/* ET SA COULEUR DE TEXTE AVEC. J avais pose le fond violet sans toucher l encre : elle est
   restee sombre sur du violet — 1,86 en clair, 2,66 en sombre. `var(--bg)` est l encre qui
   va sur un aplat d accent : claire quand la page est claire, sombre quand elle l est. */
header.topbar nav.modnav a.btn.principal{background:var(--accent);border-color:var(--accent);color:var(--bg)}
/* LA PAGE COURANTE RESTE RECONNAISSABLE. Mon jeton transparent est plus specifique que
   `.modnav [aria-current]`, et il effacait le reperage : la personne ne voyait plus ou
   elle etait. Elle le retrouve en lavis lilas — l accent REMPLI reste reserve a l action
   principale, pour que deux choses differentes ne se ressemblent pas. */
header.topbar nav.modnav a.btn[aria-current="page"]{background:var(--accent-l);border-color:var(--accent-line);color:var(--fg);font-weight:600}
/* LA REGLE QUI MASQUAIT LES LIENS RECOPIES EST PARTIE AVEC LE RAIL. Elle cachait les
   liens de la barre des lors que le rail les avait repris ; le rail n etant plus
   affiche, elle ne laissait qu une barre vide — l accueil y a perdu ses sept liens de
   niveau pendant un lot entier, sans que rien le signale. `refletRail()` continue de
   remplir `#rail-nav`, qui ne s affiche plus : c est du travail pour rien, pas un
   defaut, et le jour ou un ecran voudra un rail il le retrouvera tel quel. */
header.topbar>b{display:none}
.account{display:flex;gap:var(--e-2);align-items:center;text-align:left;padding:0;border:0;background:none;cursor:pointer}
.account .avatar{width:34px;height:34px;flex:none;border-radius:50%;display:grid;place-items:center;background:var(--accent-l);color:var(--fg);font-weight:700}
.account-text{font-size:var(--t-1);font-weight:600;color:var(--fg)}
.account-text small{display:block;font-size:var(--t-1);font-weight:400;color:var(--muted)}
.xp-repere{display:inline-flex;align-items:center;gap:var(--e-2);min-height:44px;padding:var(--e-2) var(--e-3);border:1px solid var(--warn);border-radius:var(--r-pill);background:var(--warn-soft);color:var(--warn);font-size:var(--t-1);font-weight:650;white-space:nowrap;font-variant-numeric:tabular-nums}
/* La colonne de lecture du depot (--col, marges automatiques) ne vaut pas ici : le rail porte deja la gouttiere, et la carte doit occuper la largeur du panneau. */
/* `width:100%` ET `min-width:0`, ET C'EST `margin:auto` QUI L'EXIGE. `main` porte
   `margin:auto` pour se centrer dans sa largeur maximale ; or une marge automatique sur
   l'axe transversal ANNULE l'etirement d'un element de flex. `main` se dimensionne alors
   sur son contenu, et son minimum l'emporte sur la place disponible.
   Mesure sur l'espace enseignant vu par la direction : le tableau d'affectation des
   matieres, pourtant deja rendu defilant (`display:block;overflow-x:auto`), portait `main`
   a 515 px dans une fenetre de 376 — 139 px de debordement, et le defilement du tableau ne
   servait a rien puisque son parent s'elargissait pour lui. Avec `width:100%`, `main` vaut
   la fenetre, `max-width` le borne toujours sur grand ecran, et `margin:auto` centre encore. */
.content>main{padding:var(--e-7) var(--e-8) var(--e-9);flex:1 1 auto;min-width:0;width:100%}
/* La colonne de lecture tombe SEULEMENT la ou le contenu est un tableau de bord. Sur une page de texte — mentions legales, CGU, offres — elle reste : 66 caracteres se lisent, une ligne de 1 000 px non. */
body.espace .content>main{width:auto;max-width:none;margin:0}
body.espace .path-list{max-width:none}
.welcome-row{display:flex;align-items:center;justify-content:space-between;gap:var(--e-5);margin:0 0 var(--e-5)}
.welcome-row h1{font-size:clamp(26px,2.6vw,34px);line-height:1.2;letter-spacing:-.035em;margin:0}

/* LA CARTE DE REPRISE : deux colonnes, le texte et l'illustration. */
.resume{display:grid;grid-template-columns:minmax(0,1fr) 255px;border:1px solid var(--line);border-radius:var(--r);background:var(--accent-l);overflow:hidden}
.resume-copy{padding:var(--e-7) var(--e-7) var(--e-6)}
.resume .eyebrow{margin:0 0 var(--e-2)}
.resume h2{font-size:27px;line-height:1.2;letter-spacing:-.025em;margin:0 0 var(--e-4);max-width:25ch}
.resume .primary{display:inline-flex;align-items:center;justify-content:center;gap:var(--e-5);padding:11px var(--e-6);min-height:45px;background:var(--accent);color:var(--sheet);border:1px solid var(--accent);border-radius:var(--r-s);font-size:var(--t-2);font-weight:600;text-decoration:none}
.resume .primary:hover{filter:brightness(1.12)}
.progress-line{display:flex;align-items:center;gap:var(--e-3);margin:var(--e-4) 0 0;color:var(--muted);font-size:var(--t-1)}
.jauge-fine{flex:0 0 108px;height:5px;border-radius:var(--r-pill);background:var(--line);overflow:hidden}
.jauge-fine i{display:block;height:100%;background:var(--accent)}
.resume-art{position:relative;display:grid;place-items:center;min-width:0;padding:var(--e-5);background:var(--card-2)}
.resume-art svg{width:100%;max-width:230px;height:auto}
.resume-art .art-disque{fill:var(--accent-l)}
.resume-art .art-socle{fill:var(--sheet);stroke:var(--line)}
.resume-art .art-feuille{fill:var(--sheet);stroke:var(--accent-line)}
.resume-art .art-trait{stroke:var(--accent-line);stroke-width:3;stroke-linecap:round;fill:none}
.resume-art .art-ligne{stroke:var(--line);stroke-width:2;stroke-linecap:round;fill:none}

/* LE PARCOURS : au plus trois etapes, la courante marquee. */
.section-head{display:flex;align-items:center;justify-content:space-between;gap:var(--e-5);margin:var(--e-7) 0 var(--e-3)}
.section-head h2{font-size:var(--t-3);margin:0;font-weight:600}
.text-link{border:0;background:none;font-size:var(--t-1);color:var(--muted);text-decoration:underline;text-underline-offset:4px;padding:var(--e-2) 0;cursor:pointer}
/* La colonne de lecture du depot (66ch) borne les listes : elle a du sens pour un texte, pas pour un tableau de bord. */
.path-list{list-style:none;padding:0;margin:0;background:var(--sheet);border:1px solid var(--line);border-radius:var(--r-s);overflow:hidden}
.path-item{display:flex;gap:var(--e-3);align-items:center;padding:var(--e-3) var(--e-4);border-top:1px solid var(--line)}
.path-item:first-child{border-top:0}
.path-item.current{background:var(--accent-l)}
.path-symbol{flex:0 0 1.75rem;height:1.75rem;border-radius:50%;display:grid;place-items:center;border:1px solid var(--line);font-size:var(--t-1);background:var(--sheet)}
.path-item.current .path-symbol{background:var(--accent);border-color:var(--accent);color:var(--sheet)}
.path-title{flex:1;min-width:0;font-size:var(--t-2);font-weight:500}
.path-item.current .path-title{font-weight:600}
.path-state{color:var(--muted);font-size:var(--t-1);white-space:nowrap}
.bottom-row{display:flex;gap:var(--e-4);justify-content:space-between;align-items:center;margin-top:var(--e-4)}
.message-short{border:0;background:none;font-size:var(--t-2);color:var(--muted);padding:var(--e-2) 0;text-align:left;cursor:pointer;text-decoration:underline;text-underline-offset:4px}
.help-link{font-size:var(--t-1);color:var(--muted);padding:var(--e-2) 0;white-space:nowrap}

/* LES PANNEAUX : un seul affiche a la fois, choisi par le rail. */
.vue-section[hidden]{display:none}
.hors-panneau{display:none!important}
.panneau-titre{margin-top:0}

@media (max-width:1080px){
  /* PLUS DE PISTE POUR LE RAIL. Ce bloc reservait encore `183px minmax(0,1fr)` a la coque apres que le rail a
     cesse de s afficher (`.sidebar{display:none}`, plus haut) : entre 901 et 1080 px, le contenu tombait dans la
     piste de 183 px, une lettre par ligne — l accueil a 1024 px : `main` 183 px, le titre 16, la page 81 862 px de
     haut (mesure du 28/10/2026). La coque garde l unique piste posee plus haut. Les regles du rail qui suivent ne
     touchent qu un element cache et restent avec son balisage ; si le rail revient, sa piste reviendra avec lui. */
  .sidebar{padding-left:var(--e-4);padding-right:var(--e-4)}
  .nav-link{font-size:var(--t-1);padding:var(--e-3);gap:var(--e-2)}
  header.topbar{padding:var(--e-5) var(--e-6)}
  .content>main{padding:var(--e-6)}
  .resume{grid-template-columns:minmax(0,1fr) 205px}
  .resume-copy{padding:var(--e-6)}
  .resume h2{font-size:25px}
}
@media (max-width:900px){
  .shell{display:block;min-height:0}
  .sidebar{padding:var(--e-4) var(--e-6) 0;border-right:0;border-bottom:1px solid var(--line)}
  .sidebar .brand{margin:0 0 var(--e-4);padding:0}
  .navigation{display:flex;gap:var(--e-2);justify-content:space-between;overflow:auto}
  .nav-link{font-size:var(--t-1);border-radius:var(--r-s) var(--r-s) 0 0;padding:var(--e-3) var(--e-2);gap:var(--e-2);min-height:44px}
  .sidebar-bottom{display:none}
  header.topbar{padding:var(--e-3) var(--e-6)}
  .welcome-row h1{font-size:27px}
  .resume{grid-template-columns:minmax(0,1fr) 195px}
}
@media (max-width:640px){
  .resume{grid-template-columns:minmax(0,1fr) 96px;border-radius:var(--r-s)}
  .resume-copy{padding:var(--e-6) var(--e-5)}
  .resume h2{font-size:var(--t-7);margin-bottom:var(--e-2)}
  .resume-art{padding:0 var(--e-2)}
  .resume-art svg{max-width:none;width:195px;opacity:.94}
  .content>main{padding:var(--e-5) var(--e-4) var(--e-7)}
  .section-head{margin-top:var(--e-6)}
  .path-item{padding:var(--e-3)}
}
@media (max-width:420px){
  .nav-link{font-size:var(--t-1);gap:var(--e-1);padding:var(--e-2) var(--e-1)}
  .resume{grid-template-columns:minmax(0,1fr) 64px}
  .resume h2{font-size:23px}
  .welcome-row h1{font-size:24px}
}

/* LES CITATIONS ET LES FIGURES DES DOCUMENTS, SOUS 480 PX : aucune regle ne remplacait les 40 px de marge du
   navigateur, et dans un encadre ou un exercice a 320 px une citation n avait plus que 150 px, deux ou trois mots
   par ligne (releve du 01/11/2026, histgeo). Le retrait devient un filet a gauche. */
@media (max-width:480px){
  blockquote,figure{margin:var(--e-3) 0}
  blockquote{padding-left:var(--e-3);border-left:3px solid var(--line)}
}
