/* Pages de compte : connexion, inscription, mot de passe oublié, mon espace, mentions légales. */
.compte main{max-width:var(--col);margin-inline:auto;padding:5vh 5vw var(--e-10)}
.compte h1{font-size:clamp(34px,4.5vw,56px);margin:var(--e-3) 0 var(--e-5)}
.compte h2{font-size:clamp(22px,2.6vw,32px);margin:var(--e-7) 0 var(--e-4)}
.compte p,.compte li,.compte label,.compte td,.compte th{font-size:var(--t-4)}
.compte .lead{font-size:clamp(18px,1.8vw,22px)}
.carte{border:1px solid var(--line);border-radius:var(--r);padding:var(--e-6);background:var(--card);box-shadow:var(--sh);max-width:520px}
.carte.large{max-width:none}
/* `minmax(0,1fr)` et non `1fr` : une colonne `1fr` ne descend pas sous son contenu, et le
   <select> « un élève ou un étudiant (je choisis mon année) » mesure 468 px. La carte
   débordait donc de 163 px sur un téléphone. */
.deux{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--e-6);align-items:start}
.deux.seul{grid-template-columns:minmax(0,1fr)}
@media (max-width:820px){.deux{grid-template-columns:minmax(0,1fr)}}
form.formulaire{display:flex;flex-direction:column;gap:var(--e-4)}
form.formulaire.etroit{max-width:360px;margin:var(--e-2) 0}
form.formulaire.moyen{max-width:520px;margin-top:var(--e-3)}
.champ{display:flex;flex-direction:column;gap:var(--e-2)}
.champ label{color:var(--muted);font-size:var(--t-2);letter-spacing:.04em;text-transform:uppercase}
/* `min-width:0` : un <select> est aussi large que sa plus longue option, et `width:100%`
   n'y change rien — c'est le minimum INTRINSÈQUE qui pousse la colonne de la grille.
   Le navigateur coupe alors l'affichage fermé ; la liste déroulée, elle, reste entière. */
.champ input,.champ select,.champ textarea{font:inherit;font-size:var(--t-4);color:var(--fg);background:var(--bg);border:1px solid var(--line);border-radius:var(--r-s);padding:var(--e-3) var(--e-3);width:100%;min-width:0;box-sizing:border-box}
.champ select{cursor:pointer}
.champ textarea{resize:vertical;min-height:80px}
.champ input:focus-visible,.champ select:focus-visible,.champ textarea:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
.champ [aria-invalid="true"]{border-color:var(--ko);box-shadow:0 0 0 2px color-mix(in srgb,var(--ko) 30%,transparent)}
.champ .aide{color:var(--muted);font-size:var(--t-2)}
/* champ obligatoire : astérisque après le libellé (la légende « * obligatoire » est portée par le formulaire) */
.champ:has([required]) label::after{content:" *";color:var(--ko)}
.formulaire .obligatoire{color:var(--muted);font-size:var(--t-2);margin:0}
.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}
.btn.principal{background:var(--accent);color:var(--bg);border-color:var(--accent);font-weight:600;text-align:center}
.btn.principal:hover{filter:brightness(1.08)}
.btn.bloc{display:block;width:100%;text-align:center}
.message{border-radius:var(--r-s);padding:var(--e-3) var(--e-4);font-size:var(--t-3);display:none}
.message.ko{display:block;background:color-mix(in srgb,var(--ko) 12%,transparent);color:var(--ko);border:1px solid var(--ko)}
.message.ok{display:block;background:color-mix(in srgb,var(--ok) 12%,transparent);color:var(--ok);border:1px solid var(--ok)}
.message.info{display:block;background:var(--card-2);color:var(--fg);border:1px solid var(--accent)}
.sep{display:flex;align-items:center;gap:var(--e-3);color:var(--muted);font-size:var(--t-2);letter-spacing:.1em;text-transform:uppercase;margin:var(--e-2) 0}
.sep::before,.sep::after{content:"";flex:1;border-top:1px solid var(--line)}
.fournisseurs{display:flex;flex-direction:column;gap:var(--e-3)}
.fournisseurs .btn{display:flex;align-items:center;justify-content:center;gap:var(--e-3)}
.fournisseurs svg{width:20px;height:20px}
/* LA CASE A COCHER DES CONDITIONS fait 13 px — la taille par defaut du navigateur. Son <label>
   enveloppe le texte, donc la zone cliquable est large ; encore faut-il que le curseur le DISE,
   sinon rien n indique qu on peut cliquer la phrase. Mesure faite au telephone le 07/10/2026. */
/* UN LIBELLE DE CASE DOIT POUVOIR SE COUPER. En `display:flex`, le texte et le lien
   « conditions d'utilisation » deviennent deux elements de ligne distincts, et deux elements
   de ligne ne se coupent jamais l'un dans l'autre : sur inscription.html la ligne poussait la
   page de 138 px sur un telephone. Un retrait negatif rend exactement la meme mise en page —
   case a gauche, texte aligne — en laissant la phrase se couper ou elle veut. */
.case{display:block;padding-left:calc(1.1em + var(--e-3));text-indent:calc(-1.1em - var(--e-3));
  font-size:var(--t-3);color:var(--muted);cursor:pointer;min-height:24px}
.case input{accent-color:var(--accent);width:1.1em;height:1.1em;margin-right:var(--e-3);vertical-align:-.15em}
.liens{display:flex;gap:var(--e-4);flex-wrap:wrap;font-size:var(--t-3);margin-top:var(--e-2)}
/* une seule échelle .small sur tout le site (16 px, comme style.css) : la règle ne fait que reprendre la main sur `.compte p` */
.compte .small,.compte p.small{color:var(--muted);font-size:var(--t-3)}
/* Mon espace */
.profil{display:flex;align-items:center;gap:var(--e-5);margin-bottom:var(--e-2)}
.profil .eyebrow{margin:0 0 var(--e-1)}
.profil h1{margin:0}
.profil .avatar{width:64px;height:64px;border-radius:50%;background:var(--accent);color:var(--bg);display:flex;align-items:center;justify-content:center;font-size:30px;font-weight:700}
/* `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. */
.blocs{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(280px,100%),1fr));gap:var(--e-5);margin:var(--e-5) 0}
.bloc{border:1px solid var(--line);border-radius:var(--r);padding:var(--e-5);background:var(--code);display:flex;flex-direction:column;gap:var(--e-3)}
.bloc h3{margin:0;font-size:var(--t-5)}
.jauge{height:10px;border:1px solid var(--line);border-radius:var(--r-s);overflow:hidden;background:var(--bg)}
.jauge i{display:block;height:100%;background:var(--accent);transition:width .4s}
.bloc .chiffres{display:flex;justify-content:space-between;color:var(--muted);font-size:var(--t-2)}
.reprendre{border:1px solid var(--accent);border-radius:var(--r);padding:var(--e-6);display:flex;flex-wrap:wrap;gap:var(--e-5);align-items:center;justify-content:space-between}
.reprendre .titre{font-size:var(--t-6);font-weight:600}
.reprendre .eyebrow{margin:0 0 var(--e-2)}
.pages{list-style:none;padding:0;margin:0;border-top:1px solid var(--line)}
/* LA COLONNE DES ACTIONS PRENAIT TOUT CE QU ELLE VOULAIT. En `auto`, elle vaut son max-content :
   le selecteur d annee et trois boutons cote a cote, 397 px mesures — qui ne laissaient que
   152 px au nom de l enfant, a son identifiant et a son abonnement. `fit-content()` lui pose un
   plafond : au-dela, elle se replie sur elle-meme au lieu de serrer le texte. */
.pages li{display:grid;grid-template-columns:minmax(0,1fr) fit-content(26rem);gap:var(--e-2) var(--e-5);align-items:center;padding:var(--e-3) 0;border-bottom:1px solid var(--line);margin:0}
.pages a{text-decoration:none;color:var(--fg);font-size:var(--t-4)}
.pages a:hover{color:var(--accent)}
.pages .meta{color:var(--muted);font-size:var(--t-2)}
.pages .etat{font-size:var(--t-2);color:var(--muted);text-align:right}
.pages .etat.fini{color:var(--ok)}
/* OUVRIR L'ANNÉE EST L'ACTION PRINCIPALE D'UNE LIGNE SANS ABONNEMENT, et c'était un lien en
   petit, gris, coincé entre « série 0 j » et « Jamais connecté ». Il prend la taille et la
   couleur d'une action : le violet d'accent, et le pas typographique au-dessus du corps de
   texte. Les mesures viennent des échelles — aucune valeur en dur, que le contrôle `echelle`
   refuserait. */
.pages .ouvrir{margin:var(--e-3) 0 0}
.pages .ouvrir .btn{font-size:var(--t-4);padding:var(--e-3) var(--e-5)}
/* ───── CHAQUE ENFANT DANS SON CADRE ─────────────────────────────────────────────────────────
   LES TEINTES DE LA CHARTE NE VIVAIENT QUE SUR L'ACCUEIL. `--tone-sage`, `--tone-lilac`,
   `--tone-apricot`, `--tone-blue`, `--tone-rose` sont declarees dans `style.css` pour toute
   l'application, mais seule `apex.css` les employait : « Mon espace » parlait une autre langue
   que la page d'accueil, et c'est exactement ce qui se voyait.
   LE MOTIF EST CELUI DE L'ACCUEIL, repris et non reinvente : une teinte, et un filet de la meme
   famille un ton plus soutenu (`.home .entry-parent`, `.home .result`). Le filet est ici DERIVE
   de la teinte par `color-mix` au lieu d'etre une couleur de plus a tenir : le theme sombre
   redefinit les teintes, et les filets suivent sans qu'on y touche.
   UNE TEINTE PAR ENFANT, qui tourne sur cinq — huit enfants au plus par parent (MAX_ENFANTS) :
   deux cartes voisines ne portent jamais la meme. */
.pages.enfants{border-top:0}
.pages.enfants > li{display:block;background:var(--teinte);border:1px solid color-mix(in srgb,var(--teinte) 70%,var(--fg) 16%);border-radius:var(--r);padding:var(--e-5);margin:0 0 var(--e-4)}
.pages.enfants > li:last-child{margin:0}
.pages.enfants > li.t1{--teinte:var(--tone-sage)}
.pages.enfants > li.t2{--teinte:var(--tone-lilac)}
.pages.enfants > li.t3{--teinte:var(--tone-apricot)}
.pages.enfants > li.t4{--teinte:var(--tone-blue)}
.pages.enfants > li.t5{--teinte:var(--tone-rose)}
/* CE QUI EST POSE SUR LA TEINTE REVIENT AU PAPIER. Le bloc de detail etait `--code`, un vert
   pale : pose sur une carte lilas ou abricot, il jurait. Sur une carte teintee, une surface
   interieure se lit par son blanc, et son filet se derive de la teinte qui l'entoure. */
.pages.enfants .detail-enfant{background:var(--sheet);border-color:color-mix(in srgb,var(--teinte) 55%,var(--fg) 22%)}
.pages.enfants .ouvrir{margin:var(--e-4) 0 0}
/* UNE HIERARCHIE, PAS UNE LIGNE. Le prenom, l'identifiant et l'annee tenaient sur une seule
   ligne au meme corps : la carte n'avait pas de titre. Le prenom en prend un, l'identifiant et
   l'annee passent en seconde ligne discrete, et les compteurs en troisieme. */
.pages.enfants .nom{display:block;font-size:var(--t-5);line-height:1.25}
.pages.enfants .ident{display:block;color:var(--muted);font-size:var(--t-2);margin:var(--e-1) 0 0}
.pages.enfants .meta{display:block;margin:var(--e-2) 0 0}
/* LES COMMANDES FORMENT UNE SEULE RANGEE, alignee a gauche comme le texte qu'elle suit — et non
   une colonne calee a droite, qui n'a plus de sens une fois la carte empilee. */
.pages.enfants .etat{display:flex;flex-wrap:wrap;align-items:center;gap:var(--e-3);margin:var(--e-4) 0 0;text-align:left}
.pages.enfants .etat .actions{margin:0;justify-content:flex-start}
.pages.enfants .etat select,.pages.enfants .etat .btn{background:var(--sheet)}
.vide{color:var(--muted);padding:var(--e-4) 0}
.danger{border-color:var(--ko)}
.danger h2{color:var(--ko);margin-top:0;font-size:var(--t-6)}
.btn.rouge{border-color:var(--ko);color:var(--ko)}
.btn.rouge:hover{background:var(--ko);color:var(--bg)}
.legal main{max-width:900px}
.legal h2{font-size:var(--t-7);margin:var(--e-7) 0 var(--e-3)}
.legal p,.legal li{font-size:var(--t-3);color:var(--muted)}
.legal strong{color:var(--fg)}
/* Gamification dans Mon espace */
.niveau{display:grid;grid-template-columns:auto minmax(0,1fr);gap:var(--e-4) var(--e-6);align-items:center;border:1px solid var(--line);border-radius:var(--r);padding:var(--e-5) var(--e-6);background:var(--code);margin:var(--e-3) 0 var(--e-6)}
.niveau .num{font-size:44px;font-weight:700;color:var(--accent);line-height:1}
.niveau .titre{font-size:var(--t-6);font-weight:600}
.niveau .jauge{margin-top:var(--e-2)}
.niveau .stats{display:flex;gap:var(--e-5);flex-wrap:wrap;color:var(--muted);font-size:var(--t-2);margin-top:var(--e-2)}
/* « Défi du jour » (.defi-jour, distinct de .defi = exercice de cours dans style.css) */
.defi-jour{border:1px solid var(--warn);border-radius:var(--r);padding:var(--e-4) var(--e-5);display:flex;gap:var(--e-4);align-items:center;flex-wrap:wrap;justify-content:space-between}
.defi-jour .ic{font-size:30px}
.defi-jour .texte{flex:1}
.defi-jour.fait{border-color:var(--ok)}
.badges{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(150px,100%),1fr));gap:var(--e-3);margin:var(--e-3) 0}
.badge-c{border:1px solid var(--line);border-radius:var(--r);padding:var(--e-4) var(--e-3);text-align:center;background:var(--code)}
.badge-c .ic{font-size:34px;display:block;margin-bottom:var(--e-2)}
.badge-c b{display:block;font-size:var(--t-2)}
.badge-c small{display:block;color:var(--muted);font-size:var(--t-1);margin-top:var(--e-1);line-height:1.35}
/* UN BADGE A GAGNER SE LIT PAR SON TEXTE, PAS PAR SA TRANSPARENCE (AC22-10). L'opacite de .45 portait
   sur toute la carte, texte compris : le nom tombait a 2,4:1 en clair. Elle ne porte plus que sur
   l'icone, decorative (aria-hidden) ; l'etat est ecrit par mon-espace.html (« Obtenu », « À gagner »)
   et le texte reste en couleur pleine. */
.badge-c .etat-badge{display:block;color:var(--muted);font-size:var(--t-1);margin-top:var(--e-1)}
.badge-c.verrou{color:var(--muted)}
.badge-c.verrou .ic{opacity:.45;filter:grayscale(1)}
.carte-parcours{margin:var(--e-3) 0 var(--e-6)}
.carte-parcours h3{font-size:var(--t-4);margin:var(--e-4) 0 var(--e-2);color:var(--muted)}
.carte-parcours .matiere{margin:var(--e-2) 0 2px}
.circuit{display:flex;flex-wrap:wrap;gap:var(--e-2) 0;align-items:center}
.circuit a{display:flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:50%;border:2px solid var(--line);color:var(--muted);text-decoration:none;font-size:var(--t-1);font-weight:600;position:relative;background:var(--bg)}
.circuit a+a::before{content:"";position:absolute;right:100%;top:50%;width:14px;height:2px;background:var(--line);margin-right:2px}
.circuit a.fini{background:var(--accent);border-color:var(--accent);color:var(--bg)}
.circuit a.fini+a::before{background:var(--accent)}
.circuit a.encours{border-color:var(--accent);color:var(--accent);box-shadow:0 0 0 4px color-mix(in srgb,var(--accent) 18%,transparent)}
.circuit a{margin-right:var(--e-4)}
.circuit a:hover{transform:scale(1.12)}
@media (pointer:coarse){.circuit a{width:44px;height:44px;font-size:var(--t-2)}.circuit a:hover{transform:none}}
/* Ma classe / Ma famille */
.champ input.code{text-transform:uppercase;letter-spacing:.2em}
.messages h3{font-size:var(--t-4);margin:var(--e-4) 0 var(--e-2)}
.messages .carte{max-width:none;padding:var(--e-3) var(--e-4);margin:var(--e-2) 0}
.messages .carte.moi{border-style:dashed}
.messages .carte.nonlu{border-color:var(--accent)}
.pages .etat select,.pages .etat .btn{font:inherit;font-size:var(--t-2)}
.pages .etat select{color:var(--fg);background:var(--bg);border:1px solid var(--line);border-radius:var(--r-s);padding:var(--e-1) var(--e-2)}
.pages .etat .actions{display:flex;gap:var(--e-2);flex-wrap:wrap;justify-content:flex-end;margin-top:var(--e-2)}
/* ET SOUS 900 px, LES DEUX COLONNES N EN FONT PLUS QU UNE. Cote a cote sur un telephone, le nom
   tombe a une poignee de pixels. Les actions passent alors sous le texte, alignees a gauche
   comme lui — un bouton cale a droite sous une ligne calee a gauche se lit comme un orphelin.
   LE SEUIL EST A 900, PAS A 720 : mesure a 768 px, les deux colonnes tenaient encore, mais les
   actions prenaient 397 px et il ne restait que 274 px au texte. Le seuil doit tomber la ou le
   texte cesse d etre lisible, pas la ou la grille cesse de tenir. */
@media (max-width:900px){
  .pages li{grid-template-columns:minmax(0,1fr)}
  .pages .etat{text-align:left}
  .pages .etat .actions{justify-content:flex-start}
}
.identifiants{width:100%;border-collapse:collapse;font-size:var(--t-2);margin:var(--e-3) 0}
.identifiants td,.identifiants th{padding:var(--e-2) var(--e-2);border-bottom:1px solid var(--line);text-align:left}
.identifiants code{font-size:var(--t-3)}
.identifiants-carte{border:1px solid var(--ok);border-radius:var(--r);padding:var(--e-4) var(--e-5);margin:var(--e-3) 0;background:var(--code)}
.identifiants-carte .actions{display:flex;gap:var(--e-2);flex-wrap:wrap}

/* TABLEAUX EN CARTES SUR TELEPHONE.
   Un tableau de huit colonnes sur un ecran de 375 px defile lateralement : la page ne deborde pas, mais on lit
   « 3 682,28 € » sans savoir de quelle colonne il tombe, et il faut ramener le doigt a gauche entre chaque
   ligne. Chaque ligne devient donc une carte, et chaque cellule porte l intitule de sa colonne.
   L INTITULE VIENT DE L ENTETE, pose par compte.js : les six ecrans qui affichent ces tableaux les construisent
   chacun a leur facon, et leur demander a tous d ecrire un attribut de plus aurait fait six endroits a tenir
   d accord. La feuille de style ne sait rien faire de `data-libelle` quand il manque — elle n affiche rien, et
   la carte reste lisible. */
@media (max-width:720px){
  .identifiants,.identifiants tbody,.identifiants tr,.identifiants td{display:block;width:auto}
  /* L entete disparait : ses intitules sont maintenant DANS les cellules. */
  .identifiants thead,.identifiants tr:first-child:has(th){display:none}
  .identifiants tr{border:1px solid var(--line);border-radius:var(--r);padding:var(--e-3);margin:0 0 var(--e-3)}
  .identifiants td{display:flex;gap:var(--e-4);align-items:baseline;justify-content:space-between;
    border:0;border-bottom:1px solid color-mix(in srgb,var(--line) 45%,transparent);padding:var(--e-2) 0;text-align:right}
  .identifiants tr td:last-child{border-bottom:0;padding-bottom:0}
  .identifiants td::before{content:attr(data-libelle);color:var(--muted);text-align:left;flex:0 1 auto;font-size:var(--t-1)}
  /* Une cellule sans intitule — la colonne des boutons — prend toute la largeur au lieu de laisser un vide. */
  .identifiants td:not([data-libelle]),.identifiants td[data-libelle=""]{justify-content:flex-start;text-align:left}
  .identifiants td:not([data-libelle])::before,.identifiants td[data-libelle=""]::before{content:none}
  /* La ligne « rien a afficher » n est pas un enregistrement : pas de cadre, pas d intitule. */
  .identifiants td.vide{border:0;text-align:left;justify-content:flex-start}
  .identifiants tr:has(td.vide){border:0;padding:0}
}
.mini-form{display:flex;gap:var(--e-2);flex-wrap:wrap;align-items:flex-end;margin:var(--e-2) 0}
.mini-form .champ{flex:1;min-width:180px}
.detail-enfant{margin:var(--e-2) 0 var(--e-3);padding:var(--e-3) var(--e-4);border:1px solid var(--line);border-radius:var(--r-s);background:var(--code)}
.detail-enfant summary{cursor:pointer;color:var(--muted);font-size:var(--t-2)}
/* Impression des identifiants d'un enfant : body.impression (posée le temps de window.print) n'imprime que la carte .impression. */
@media print{body.impression header,body.impression footer,body.impression main>*:not(.impression),body.impression #famille-zone>*:not(.impression){display:none!important}body.impression #famille-zone{display:block!important}}
[hidden]{display:none!important}

/* barre de navigation des pages connectées (Compte.navigation) */
.modnav .nav-sep{width:1px;align-self:stretch;background:var(--line);margin:0 var(--e-1)}
@media (max-width:1000px){.modnav .nav-sep{display:none}}
.compte select.inline{font:inherit;font-size:var(--t-3);padding:var(--e-1) var(--e-2);border-radius:var(--r-s);border:1px solid var(--line);background:var(--bg);color:var(--fg)}

/* Aperçu du récapitulatif parental : c'est un courriel, on le montre tel qu'il partira. */
.apercu-recap{white-space:pre-wrap;font-family:inherit;font-size:var(--t-3);line-height:1.5;background:var(--code);border:1px solid var(--line);border-radius:var(--r-s);padding:var(--e-3);margin:var(--e-3) 0;max-height:320px;overflow:auto}
