/* ── socle ─────────────────────────────────────────
   Les seuils de rupture, le thème clair et sombre, le gabarit de page, les
   cartes, les champs, les boutons, les messages, les projets, les tableaux,
   et le pied de page.

   Découpé de index.html le 16/09/2026 (étape A2 de REFONTE.md). L'ORDRE DES
   FEUILLES DANS index.html COMPTE : deux règles de même spécificité se
   départagent par leur position, et ce découpage a été fait par tranches
   contiguës précisément pour ne rien changer à cet ordre. Déplacer une feuille
   dans la liste, ou une règle d'une feuille à l'autre, peut donc modifier le
   rendu sans modifier une seule déclaration. outils/comparer.mjs le vérifie.
   ───────────────────────────────────────────────────────────────────────── */

/* ── Les seuils de rupture ────────────────────────────────────────────────
   Il y en avait dix, écrits de quatre façons : avec espace et en rem, sans
   espace et en rem, avec espace et en pixels, sans espace et à la décimale
   près (33.9rem, pour ne pas recouvrir 34rem). Aucun n'était nommé nulle part :
   pour savoir ce qui changeait à 640 px il fallait lire les 890 lignes.

   Ils sont six, et cette table est la seule liste qui fasse foi :
   outils/mesurer.mjs la lit ici même et refuse toute media query qui n'y
   figure pas. Une variable CSS ne peut pas servir à cela — « @media
   (max-width: var(--x)) » ne s'applique jamais, essayé et mesuré — donc c'est
   l'écriture littérale qui est contrôlée, pas remplacée.

   @seuil minuscule  (max-width: 27rem)    432 px  on retire l'accessoire
   @seuil telephone  (max-width: 30rem)    480 px  ce qui est côte à côte s'empile
   @seuil etroit     (max-width: 40rem)    640 px  ce qui suppose de la largeur se replie
   @seuil moyen      (min-width: 34rem)    544 px  les grilles serrées s'élargissent
   @seuil large      (min-width: 38rem)    608 px  les projets passent en grille
   @seuil bureau     (min-width: 58rem)    928 px  deux colonnes de classes

   Ajouter un seuil est une décision, pas un réflexe : chaque nouveau seuil est
   une largeur de plus à vérifier à chaque changement, pour toujours.
   ────────────────────────────────────────────────────────────────────────── */

/* Contrastes (05/10, lot 1 des propositions) : tout couple texte / fond de
   cette table passe 4,5 : 1 (WCAG 1.4.3) dans les deux thèmes, mesuré par
   axe-core dans outils/t_navigation.mjs. Trois teintes ont bougé pour cela :
     --ink-faint  #8697A6 -> #5E6F7F en clair (2,6 à 3,0 : 1 avant ; aucune
                  teinte plus pâle ne passe sur --surface-alt) et #71828F ->
                  #8193A1 en sombre (3,8 à 4,6 : 1 avant) ;
     --ok, --signal un cran plus foncés en clair (4,34 et 4,46 : 1 sur leur
                  fond « soft », juste sous le seuil) ;
     --on-accent  le texte posé SUR --accent : blanc en clair, encre foncée en
                  sombre — le blanc sur #4FB3AD faisait 2,5 : 1, et c'était le
                  bouton « Me connecter » des étudiants. */
:root{
  --ground:#F4F6F8; --surface:#FFF; --surface-alt:#EDF1F4;
  --ink:#17212B; --ink-soft:#5A6B7B; --ink-faint:#5E6F7F;
  --rule:#DCE3E9; --rule-soft:#E9EEF2;
  --accent:#0E6E6E; --accent-ink:#0A5555; --accent-soft:#E1EFEE; --on-accent:#FFF;
  --signal:#A64C08; --signal-soft:#FBF0E2;
  --ok:#18733F; --ok-soft:#E3F2E9;
  --f-sans:"IBM Plex Sans",ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --f-mono:"IBM Plex Mono",ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
}
@media (prefers-color-scheme: dark){:root{
  --ground:#0F171E; --surface:#16202A; --surface-alt:#1B2733;
  --ink:#E4EAF0; --ink-soft:#9CACBB; --ink-faint:#8193A1;
  --rule:#26333F; --rule-soft:#1F2B36;
  --accent:#4FB3AD; --accent-ink:#79CBC5; --accent-soft:#123230; --on-accent:#0B1A1F;
  --signal:#D9903F; --signal-soft:#33260F;
  --ok:#4FBF84; --ok-soft:#10301F;
}}
*{box-sizing:border-box;margin:0;padding:0}
body{background:var(--ground);color:var(--ink);font-family:var(--f-sans);
     font-size:16px;line-height:1.6;-webkit-font-smoothing:antialiased}
.wrap{max-width:52rem;margin:0 auto;padding:0 1.25rem 4rem}

header{border-bottom:1px solid var(--rule);padding:2.75rem 0 1.5rem;margin-bottom:2rem}
.eyebrow{font-family:var(--f-mono);font-size:.7rem;letter-spacing:.14em;
         text-transform:uppercase;color:var(--accent);display:block;margin-bottom:.5rem}
h1{font-size:2rem;line-height:1.1;letter-spacing:-.02em;font-weight:600}
.sub{color:var(--ink-soft);margin-top:.5rem}

.card{background:var(--surface);border:1px solid var(--rule);border-radius:8px;
      padding:1.5rem;margin-bottom:1rem}
h2{font-size:1.15rem;font-weight:600;letter-spacing:-.01em;margin-bottom:.35rem}
.hint{color:var(--ink-soft);font-size:.92rem;margin-bottom:1.1rem}

.tabs{display:flex;gap:.4rem;margin-bottom:1.5rem}
.tab{flex:1;background:var(--surface);border:1px solid var(--rule);border-radius:7px;
     padding:.6rem .8rem;font:inherit;font-size:.92rem;font-weight:500;color:var(--ink-soft);cursor:pointer}
.tab[aria-selected="true"]{background:var(--accent-soft);border-color:var(--accent);color:var(--accent-ink)}
.tab:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible{
  outline:2px solid var(--accent);outline-offset:2px}

.field{display:flex;flex-direction:column;gap:.3rem;margin-bottom:.9rem}
label{font-size:.83rem;font-weight:500;color:var(--ink-soft)}
/* 44 px : la taille en dessous de laquelle un doigt rate sa cible. Le portail
   se pilote au téléphone en séance, pas seulement à la souris au bureau. */
input,select{background:var(--surface-alt);color:var(--ink);border:1px solid var(--rule);
  border-radius:7px;padding:.6rem .7rem;font:inherit;font-size:.95rem;width:100%;
  min-height:44px}
.row{display:flex;gap:.7rem}
.row .field{flex:1}

.btn{background:var(--accent);color:var(--on-accent);border:0;border-radius:7px;padding:.65rem 1.1rem;
     font:inherit;font-size:.95rem;font-weight:600;cursor:pointer;min-height:44px}
.btn:hover{filter:brightness(1.08)}
.btn[disabled]{opacity:.55;cursor:default}
.btn-sec{background:transparent;color:var(--ink-soft);border:1px solid var(--rule)}

.msg{border-left:2px solid var(--signal);background:var(--signal-soft);
     border-radius:0 5px 5px 0;padding:.7rem .9rem;font-size:.9rem;margin-bottom:1rem}
.msg.ok{border-left-color:var(--ok);background:var(--ok-soft)}

.ident{display:flex;align-items:center;gap:.7rem;flex-wrap:wrap;
       background:var(--accent-soft);border:1px solid var(--accent);
       border-radius:8px;padding:.85rem 1.1rem;margin-bottom:1.25rem}
.ident-num{font-family:var(--f-mono);font-size:1.35rem;font-weight:600;color:var(--accent-ink)}
.ident-txt{flex:1;font-size:.92rem;color:var(--ink)}
.ident-txt b{font-weight:600}

.projets{display:grid;gap:.8rem;grid-template-columns:1fr}
@media (min-width: 38rem){.projets{grid-template-columns:1fr 1fr}}
a.projet{display:flex;gap:.9rem;align-items:flex-start;text-decoration:none;color:inherit;
  background:var(--surface);border:1px solid var(--rule);border-radius:8px;padding:1.1rem}
a.projet:hover{border-color:var(--accent);background:var(--accent-soft)}
.projet-ico{font-family:var(--f-mono);font-size:.72rem;font-weight:600;letter-spacing:.04em;
  color:var(--accent);background:var(--accent-soft);border:1px solid var(--accent);
  border-radius:5px;padding:.3rem .45rem;flex:none;margin-top:.15rem}
a.projet:hover .projet-ico{background:var(--surface)}
/* display:block — sans lui ces deux <span> restent en ligne, la marge basse
   du titre n'agit pas, et « Bloc 1 DEV » se colle à sa description. Le
   défaut touchait aussi « Vos projets » côté étudiant. */
.projet-t{display:block;font-weight:600;font-size:.98rem;margin-bottom:.15rem}
.projet-d{display:block;font-size:.87rem;color:var(--ink-soft);line-height:1.45}

table{width:100%;border-collapse:collapse;font-size:.9rem}
th{text-align:left;font-family:var(--f-mono);font-size:.68rem;letter-spacing:.09em;
   text-transform:uppercase;color:var(--ink-faint);font-weight:500;
   padding:0 .6rem .45rem 0;border-bottom:1px solid var(--rule)}
td{padding:.55rem .6rem .55rem 0;border-bottom:1px solid var(--rule-soft);color:var(--ink-soft)}
td:first-child,th:first-child{padding-left:0}
tr:last-child td{border-bottom:0}
.num{font-family:var(--f-mono);font-variant-numeric:tabular-nums;color:var(--ink)}
.scroll{overflow-x:auto}
/* Une zone qui défile se prend au clavier (tabindex="0", WCAG 2.1.1) : son
   focus doit donc se voir comme celui d'un bouton. */
.scroll:focus-visible{outline:2px solid var(--accent);outline-offset:2px}


footer{margin-top:2.5rem;padding-top:1.25rem;border-top:1px solid var(--rule);
       font-size:.83rem;color:var(--ink-faint);display:flex;flex-direction:column;gap:.35rem}
.spin{color:var(--ink-faint);font-size:.92rem}
[hidden]{display:none!important}

/* ── Le lien d'évitement (WCAG 2.4.1) ─────────────────────────────────────
   Il est le premier élément de la page et reste invisible tant qu'il n'a pas
   le focus. Pas de display:none ni de visibility:hidden : les deux le
   retireraient aussi de l'ordre de tabulation, et il ne servirait plus à rien.
   On le sort de l'écran, et il revient dès qu'on l'atteint au clavier. */
.evitement{position:absolute;left:-9999px;top:0;z-index:50;
  background:var(--accent);color:var(--on-accent);font-size:.95rem;font-weight:600;
  padding:.7rem 1.1rem;border-radius:0 0 8px 0;text-decoration:none}
.evitement:focus{left:0}
#contenu:focus{outline:none}
