/* APP-EDU — core/ui/components.css
   Couche 3 : composants RÉUTILISABLES, partagés par les 2 portails et les 3 modules.
   Règles dures (cf. DESIGN_SYSTEM.md) : APLATS (aucun dégradé), profondeur = ombre + bordure.
   Ce fichier ne contient PAS le chrome (sidebar, topbar, grille d'app, accueil) : celui-ci est
   défini une seule fois dans portal/ (chrome unifié élève/prof).
   Convention de nommage : préfixe `edu-` pour éviter les collisions. */

/* ============================ Boutons ============================ */
.edu-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 9px 16px; border-radius: var(--edu-pill);
  background: var(--edu-surface); border: 1px solid var(--edu-border);
  color: var(--edu-muted); font-family: var(--edu-font-ui); font-size: 13px; font-weight: 600;
  transition: color .14s, border-color .14s, transform .14s, box-shadow .14s, background .14s;
}
.edu-btn:hover { color: var(--edu-text); border-color: var(--edu-border-strong); transform: translateY(-1px); box-shadow: var(--edu-shadow); }
.edu-btn:active { transform: none; }
.edu-btn--primary { background: var(--edu-accent); color: #fff; border-color: transparent; }
.edu-btn--primary:hover { background: var(--edu-accent-dark); color: #fff; }
.edu-btn--ghost { background: transparent; box-shadow: none; }
.edu-btn--sm { padding: 6px 12px; font-size: 12px; }

/* ============================ Cartes ============================ */
.edu-card {
  background: var(--edu-surface); border: 1px solid var(--edu-border); border-radius: var(--edu-radius);
  padding: 18px; box-shadow: var(--edu-shadow-sm);
  transition: transform .16s, box-shadow .16s, border-color .16s;
}
.edu-card--link { display: block; text-decoration: none; color: inherit; }
.edu-card--link:hover { transform: translateY(-2px); box-shadow: var(--edu-shadow-lg); border-color: var(--edu-border-strong); cursor: pointer; }

/* ============================ Badges & chips ============================ */
.edu-badge {
  font-size: 10px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
  padding: 2px 8px; border-radius: var(--edu-pill);
  background: var(--edu-surface-2); color: var(--edu-faint); border: 1px solid var(--edu-border);
}
.edu-badge--count { background: var(--edu-depots-bg); color: var(--edu-depots); border-color: transparent; }

.edu-chip {
  font-size: 10.5px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
  padding: 4px 10px; border-radius: var(--edu-pill); white-space: nowrap;
}
.edu-chip--new { background: var(--edu-depots); color: #fff; }
.edu-chip--ok  { background: var(--edu-ok-bg); color: var(--edu-ok); }
.edu-chip--warn { background: color-mix(in srgb, var(--edu-warn) 16%, transparent); color: var(--edu-warn); }

/* ============================ Titre & sous-titre de page (`.adm-page`, hors session) ============
   Le rôle « titre de page » vivait sous 6 noms (`.res-h1`/`.inst-h1`/`.adu-h1`/`.typ-h1`/`.cons-h1`/
   `.shell-title`) ; « sous-titre » sous 5 (`.res-lede`/`.inst-lede`/`.adu-lede`/`.typ-lede`/
   `.cons-intro`). UN rôle = UN composant = UN nom (audit GRAPHISME, 22/08) — mais EXTRAIT, jamais
   inventé : seule la partie RÉELLEMENT byte-identique migre ici ; la partie qui diffère — et qu'on
   n'a pas le droit de trancher à l'aveugle, sans écran pour la juger — RESTE locale, nommément.
   `.edu-page-h1` = EXACTEMENT `.res-h1`/`.inst-h1`/`.adu-h1` (les 3 étaient déjà byte-identiques :
   `font-size:21px; margin:14px 0 2px`) → ces 3 classes ont MIGRÉ ici, zéro pixel changé.
   `.edu-lede` = la portion COMMUNE aux 5 (`color:var(--edu-muted); font-size:13.5px`, vraie dans les
   5 fichiers) ; la marge basse, elle, DIVERGE sans raison visible (6px pour la réserve, 18px pour
   instance/équipe, 16px pour la console, 6px pour le Montage) → laissée en classe LOCALE (margin
   seul) plutôt qu'un compromis inventé.
   ⛔ N'ONT PAS MIGRÉ, sciemment : `.cons-h1`/`.cons-intro` (console.css — valeurs RÉELLEMENT
   différentes : 22px/`margin:0 0 4px`/couleur `--edu-text` explicite, migrer aurait changé un pixel
   sans preuve que c'est voulu).
   ✅ **`.typ-h1`+`.typ-h1--page` DU MONTAGE ONT MIGRÉ** (ticket GRAPHISME du 23/08) : leur valeur
   EFFECTIVE était déjà `21px/700/margin:14px 0 2px`, donc `.edu-page-h1` — zéro réglage à inventer.
   `.typ-h1` **seul** (sans `--page`, `margin:0`) reste local à `montage.css` : c'est un TROISIÈME
   réglage (le titre éditable en tête d'écran, sans la marge de page), pas un doublon.
   `.typ-lede` a migré à la marge près, exactement comme prévu : ne garde plus QUE `margin:0 0 6px`
   (`portal/assets/montage.css`), le reste vient désormais d'`.edu-lede`. */
.edu-page-h1 { font-size: 21px; margin: 14px 0 2px; }
.edu-lede { color: var(--edu-muted); font-size: 13.5px; }

/* ============================ Vocabulaire visuel étendu (22-23/08) ============================
   Les 4 pièces qui manquaient au vocabulaire commun, EXTRAITES de `portal/assets/calendrier.css`
   (⭐ l'écran que Gabriel a jugé beau, 2026-08-22 — cf. DESIGN_SYSTEM.md §« LES TROIS ÉCRANS DE
   RÉFÉRENCE ») : zéro pixel changé, la source de chaque valeur est nommée. `.edu-callout` (bandeau
   à simple filet) et `.edu-stat` (carte de chiffre) EXISTAIENT DÉJÀ (plus haut dans ce fichier) —
   les 4 ci-dessous sont celles qui manquaient réellement.

   ⚠ **`calendrier.css` N'A PAS ÉTÉ TOUCHÉ** : ses classes `.cal-*` continuent de porter leurs
   propres déclarations, byte pour byte identiques à celles migrées ici. Une bascule de son HTML
   (`portal/calendrier.py`) vers ces classes partagées est un geste **sans aucun gain visuel**
   (les valeurs sont déjà identiques) et **tout le risque** sur le seul écran que Gabriel a jugé
   beau, sans moyen de le revérifier à l'écran dans ce ticket (⛔ aucun serveur ne se lance ici) —
   refusé, nommément (`_CR/2026-08.md`).

   ✅ **LE MONTAGE CONSOMME `.edu-col-day` ET `.edu-content-card`** (troisième passe, 23/08 — un
   tiers a mesuré la cascade et trouvé la première version de ce paragraphe fausse dès son
   écriture : elle disait que Le Montage n'appelait pas ces classes, `70a5a58` avait déjà fait
   l'inverse). La colonne-jour et la carte (tête, suite, sujet en attente sur la desserte) portent
   la classe partagée EN PLUS de leur classe `mtg-*` (qui garde la prise du JS et l'échelle de
   temps `--p × --mtg-part`) — `class="edu-col-day mtg-col"`, `class="edu-content-card mtg-card"`.
   `montage.css` ne redéclare plus le fond, la bordure ni le rayon : `.mtg-col` et `.mtg-card` n'y
   gardent QUE ce qui diverge vraiment (la largeur figée du plateau, le `padding` nul de la carte
   — imposé par l'échelle de temps — et la couleur du filet, qui suit un VERDICT plutôt qu'un
   type de contenu, ce dont Le Montage ne dispose pas). Gardé par `tests/test_charte_vocabulaire.py`
   (l'extraction ET la consommation) et `tests/test_grille_montage.py §10` (le fond de la carte
   reste calculé comme distinct de son conteneur — pas une chaîne comparée, une couleur résolue).
   ⚠ `.edu-tabs` et `.edu-divider-word`, eux, restent **EN STOCK** : Le Montage n'a ni pagination
   de semaine ni séparateur à hauteur libre (son mur de pause a une hauteur VERROUILLÉE par
   l'échelle de temps, TS11) — aucun écran ne les consomme encore, et ce n'est pas un oubli. */
.edu-tabs { display: inline-flex; gap: 6px; flex-wrap: wrap; }
.edu-tab {
  font-size: 12.5px; font-weight: 600; color: var(--edu-muted); text-decoration: none;
  padding: 5px 12px; border: 1px solid var(--edu-border); border-radius: var(--edu-pill);
  background: var(--edu-surface);
}
.edu-tab:hover { color: var(--edu-accent-ink); border-color: var(--edu-accent); }
.edu-tab.is-on { color: var(--edu-accent-ink); background: var(--edu-accent-soft);
  border-color: var(--edu-accent); }

.edu-col-day {
  min-width: 0;
  background: var(--edu-surface); border: 1px solid var(--edu-border);
  border-radius: var(--edu-radius); box-shadow: var(--edu-shadow-sm); overflow: hidden;
  display: flex; flex-direction: column;
}

.edu-content-card {
  background: var(--edu-surface-2); border: 1px solid var(--edu-border);
  border-radius: var(--edu-radius-sm); padding: 7px 8px;
  border-left: 3px solid var(--edu-border-strong);
}
.edu-content-card--cours  { border-left-color: var(--edu-cours); }
.edu-content-card--evals  { border-left-color: var(--edu-evals); }
.edu-content-card--depots { border-left-color: var(--edu-depots); }
.edu-content-card--ok     { border-left-color: var(--edu-ok); }
.edu-content-card-tag {
  font-size: 9.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  color: var(--edu-muted);
}
.edu-content-card--cours  .edu-content-card-tag { color: var(--edu-cours); }
.edu-content-card--evals  .edu-content-card-tag { color: var(--edu-evals); }
.edu-content-card--depots .edu-content-card-tag { color: var(--edu-depots); }
.edu-content-card--ok     .edu-content-card-tag { color: var(--edu-ok); }
.edu-content-card-title { font-size: 12.5px; font-weight: 600; line-height: 1.3; color: var(--edu-text); }

.edu-divider-word { display: flex; align-items: center; gap: 8px; padding: 1px 11px;
  color: var(--edu-faint); font-size: 10.5px; letter-spacing: .06em; }
.edu-divider-word::before, .edu-divider-word::after { content: ""; height: 0;
  border-top: 1px dashed var(--edu-border); flex: 1; }

/* ============================ Section & grilles ============================ */
.edu-section { margin-bottom: 26px; }
.edu-section-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 14px; }
.edu-section-head h2 { font-family: var(--edu-font-display); font-size: 18px; font-weight: 700; }
.edu-section-head .edu-section-meta { font-size: 12.5px; color: var(--edu-faint); }
.edu-section-head .edu-section-more { margin-left: auto; font-size: 12.5px; color: var(--edu-accent); font-weight: 600; }

.edu-grid { display: grid; gap: 16px; }
.edu-grid--2 { grid-template-columns: repeat(2, 1fr); }
.edu-grid--3 { grid-template-columns: repeat(3, 1fr); }
.edu-grid--auto { grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
@media (max-width: 720px) { .edu-grid--2, .edu-grid--3 { grid-template-columns: 1fr; } }

/* ============================ Tuiles de synthèse (KPI) ============================ */
.edu-stat { position: relative; overflow: hidden; }
.edu-stat .edu-stat-k { font-size: 11px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--edu-muted); }
.edu-stat .edu-stat-v { font-family: var(--edu-font-display); font-size: 32px; font-weight: 700; letter-spacing: -.02em; font-variant-numeric: tabular-nums; line-height: 1.05; margin: 4px 0 2px; }
.edu-stat .edu-stat-s { font-size: 12.5px; color: var(--edu-muted); }
/* teinte par module (aplats) */
.edu-stat--cours  { background: var(--edu-cours-bg);  border-color: transparent; }
.edu-stat--cours  .edu-stat-v { color: var(--edu-cours); }
.edu-stat--evals  { background: var(--edu-evals-bg);  border-color: transparent; }
.edu-stat--evals  .edu-stat-v { color: var(--edu-evals); }
.edu-stat--depots { background: var(--edu-depots-bg); border-color: transparent; }
.edu-stat--depots .edu-stat-v { color: var(--edu-depots); }

/* ============================ Liste d'items + icône ============================ */
.edu-list { display: flex; flex-direction: column; gap: 10px; }
.edu-item {
  display: flex; align-items: center; gap: 14px; padding: 14px 16px;
  background: var(--edu-surface); border: 1px solid var(--edu-border); border-radius: var(--edu-radius);
  box-shadow: var(--edu-shadow-sm); transition: transform .15s, box-shadow .15s;
}
.edu-item--link:hover { transform: translateY(-2px); box-shadow: var(--edu-shadow); cursor: pointer; }
.edu-item--unread { border-left: 3px solid var(--edu-depots); }
.edu-item-body { flex: 1; min-width: 0; }
.edu-item-title { font-weight: 600; font-size: 14.5px; }
.edu-item-sub { font-size: 12.5px; color: var(--edu-muted); margin-top: 2px; }
.edu-item-meta { font-size: 12px; color: var(--edu-faint); white-space: nowrap; font-variant-numeric: tabular-nums; font-weight: 500; }

/* icône de contenu : carré arrondi teinté module + SVG stroke monochrome (jamais d'emoji ici) */
.edu-ic { width: 40px; height: 40px; border-radius: 11px; flex-shrink: 0; display: grid; place-items: center; background: var(--edu-cours-bg); color: var(--edu-cours); }
.edu-ic svg { width: 19px; height: 19px; }
.edu-ic--cours  { background: var(--edu-cours-bg);  color: var(--edu-cours); }
.edu-ic--evals  { background: var(--edu-evals-bg);  color: var(--edu-evals); }
.edu-ic--depots { background: var(--edu-depots-bg); color: var(--edu-depots); }
.edu-ic--ok     { background: var(--edu-ok-bg);     color: var(--edu-ok); }

/* ============================ Lecteur de document (prose) ============================ */
.edu-reader { background: var(--edu-surface); border: 1px solid var(--edu-border); border-radius: var(--edu-radius); overflow: hidden; box-shadow: var(--edu-shadow-sm); }
.edu-reader-head { padding: 26px 30px; background: var(--edu-cours-bg); border-bottom: 1px solid var(--edu-border); }
.edu-reader-kicker { font-size: 11px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--edu-cours); }
.edu-reader-head h2 { font-family: var(--edu-font-display); font-size: 27px; font-weight: 700; letter-spacing: -.02em; margin: 8px 0 10px; }
.edu-reader-meta { font-size: 12.5px; color: var(--edu-muted); display: flex; gap: 18px; flex-wrap: wrap; }
.edu-reader-foot { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 18px 30px; border-top: 1px solid var(--edu-border); background: var(--edu-surface-2); }

.edu-prose { padding: 26px 30px; line-height: 1.75; }
.edu-prose > * + * { margin-top: 14px; }
.edu-prose h3 { font-family: var(--edu-font-display); font-size: 19px; font-weight: 700; margin-top: 26px; color: var(--edu-text); }
.edu-prose p { color: var(--edu-muted); }
.edu-prose strong { color: var(--edu-text); font-weight: 600; }
.edu-prose ul { padding-left: 20px; color: var(--edu-muted); list-style: disc; }
.edu-prose li + li { margin-top: 6px; }
.edu-prose code { font-family: var(--edu-font-mono); font-size: 12.5px; background: var(--edu-surface-2); border: 1px solid var(--edu-border); padding: 1px 6px; border-radius: 6px; color: var(--edu-accent-ink); }
.edu-prose pre { font-family: var(--edu-font-mono); font-size: 12.5px; line-height: 1.5; background: var(--edu-surface-2); border: 1px solid var(--edu-border); border-radius: var(--edu-radius-sm); padding: 16px; overflow-x: auto; color: var(--edu-text); }
.edu-prose a { color: var(--edu-accent); text-decoration: underline; text-underline-offset: 2px; }

/* encadré (info) */
.edu-callout { border-left: 4px solid var(--edu-evals); background: var(--edu-evals-bg); padding: 13px 16px; border-radius: 0 10px 10px 0; color: var(--edu-text); }
.edu-callout--ok    { border-left-color: var(--edu-ok); background: var(--edu-ok-bg); }
.edu-callout--warn  { border-left-color: var(--edu-warn); background: color-mix(in srgb, var(--edu-warn) 12%, var(--edu-surface)); }

/* ============================ Message d'état (carte) ============================
   Composant GLOBAL (PAS scopé .cours-doc) : messages d'état pleine-page émis par les modules
   HORS prose — evals « épreuve terminée », « quiz introuvable », « plus de réponses »… Carte
   centrée dans le langage de .evals-wait / callouts (tokens uniquement, theme-aware clair/sombre).
   Variantes neutre / warn / danger / ok. Émis par modules/evals/view.py `_box`/`error_box`. */
.edu-state {
  text-align: center; max-width: 480px; margin: 10px auto;
  padding: 28px 30px; border-radius: var(--edu-radius);
  border: 1px solid var(--edu-border); background: var(--edu-surface);
  box-shadow: var(--edu-shadow-sm);
}
.edu-state-title { font-family: var(--edu-font-display); font-size: 18px; font-weight: 700; color: var(--edu-text); margin: 0 0 8px; }
.edu-state-msg { color: var(--edu-muted); margin: 0 auto; max-width: 36em; line-height: 1.6; }
.edu-state-msg + .edu-state-msg { margin-top: 8px; }
.edu-state--neutral { background: var(--edu-surface-2); }
.edu-state--warn   { border-color: color-mix(in srgb, var(--edu-warn) 42%, var(--edu-border)); background: color-mix(in srgb, var(--edu-warn) 9%, var(--edu-surface)); }
.edu-state--warn   .edu-state-title { color: var(--edu-warn); }
.edu-state--danger { border-color: color-mix(in srgb, var(--edu-danger) 42%, var(--edu-border)); background: color-mix(in srgb, var(--edu-danger) 8%, var(--edu-surface)); }
.edu-state--danger .edu-state-title { color: var(--edu-danger); }
.edu-state--ok     { border-color: color-mix(in srgb, var(--edu-ok) 42%, var(--edu-border)); background: var(--edu-ok-bg); }
.edu-state--ok     .edu-state-title { color: var(--edu-ok); }

/* ============================ Lexique (dl) ============================ */
.edu-lex { display: flex; flex-direction: column; gap: 11px; }
.edu-lex-entry { background: var(--edu-surface); border: 1px solid var(--edu-border); border-radius: var(--edu-radius); padding: 15px 18px; box-shadow: var(--edu-shadow-sm); transition: transform .15s, box-shadow .15s; }
.edu-lex-entry:hover { transform: translateY(-2px); box-shadow: var(--edu-shadow); }
.edu-lex-term { display: flex; align-items: baseline; gap: 11px; }
.edu-lex-term dt { font-family: var(--edu-font-mono); font-weight: 500; color: var(--edu-accent-ink); font-size: 14px; background: var(--edu-cours-bg); padding: 2px 9px; border-radius: 7px; }
.edu-lex-term .edu-lex-full { font-size: 12.5px; color: var(--edu-faint); }
.edu-lex-entry dd { margin-top: 7px; font-size: 13.5px; color: var(--edu-muted); }

/* ============================ Ressource (lien/fichier) ============================ */
.edu-res { display: flex; align-items: center; gap: 14px; padding: 16px; background: var(--edu-surface); border: 1px solid var(--edu-border); border-radius: var(--edu-radius); box-shadow: var(--edu-shadow-sm); transition: transform .15s, box-shadow .15s, border-color .15s; }
.edu-res:hover { transform: translateY(-2px); box-shadow: var(--edu-shadow-lg); border-color: var(--edu-accent); }
.edu-res-ext { margin-left: auto; color: var(--edu-faint); font-size: 16px; }
.edu-res:hover .edu-res-ext { color: var(--edu-accent); }

/* ============================ Champ de recherche ============================ */
.edu-search {
  display: flex; align-items: center; gap: 8px; background: var(--edu-surface-2);
  border: 1px solid var(--edu-border); border-radius: var(--edu-radius-sm); padding: 0 11px;
}
.edu-search svg { flex-shrink: 0; color: var(--edu-faint); }
.edu-search input { flex: 1; background: none; border: none; outline: none; color: var(--edu-text); font-size: 13.5px; padding: 10px 0; }
.edu-search input::placeholder { color: var(--edu-faint); }
.edu-search kbd { font-family: var(--edu-font-mono); font-size: 10px; color: var(--edu-faint); border: 1px solid var(--edu-border-strong); border-radius: 5px; padding: 1px 5px; }

/* ============================ Calendrier ============================ */
.edu-cal { background: var(--edu-surface); border: 1px solid var(--edu-border); border-radius: var(--edu-radius); overflow: hidden; box-shadow: var(--edu-shadow-sm); }
.edu-cal-head { display: flex; align-items: center; justify-content: space-between; padding: 16px 20px; background: var(--edu-surface-2); border-bottom: 1px solid var(--edu-border); }
.edu-cal-head .edu-cal-m { font-family: var(--edu-font-display); font-size: 17px; font-weight: 700; }
.edu-cal-nav { display: flex; gap: 6px; }
.edu-cal-nav button { width: 32px; height: 32px; border-radius: 9px; background: var(--edu-surface); border: 1px solid var(--edu-border); color: var(--edu-muted); display: grid; place-items: center; }
.edu-cal-nav button:hover { color: var(--edu-text); border-color: var(--edu-border-strong); }
.edu-cal-week, .edu-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); }
.edu-cal-week { background: var(--edu-surface-2); border-bottom: 1px solid var(--edu-border); }
.edu-cal-week span { padding: 10px; text-align: center; font-size: 11px; font-weight: 700; text-transform: uppercase; color: var(--edu-faint); letter-spacing: .06em; }
.edu-cal-day { min-height: 84px; padding: 8px; border-right: 1px solid var(--edu-border); border-bottom: 1px solid var(--edu-border); display: flex; flex-direction: column; gap: 4px; }
.edu-cal-day:nth-child(7n) { border-right: none; }
.edu-cal-day .edu-cal-n { font-size: 12.5px; font-weight: 600; color: var(--edu-muted); font-variant-numeric: tabular-nums; font-family: var(--edu-font-mono); }
.edu-cal-day--out { background: var(--edu-surface-2); }
.edu-cal-day--out .edu-cal-n { color: var(--edu-faint); opacity: .6; }
.edu-cal-day--today .edu-cal-n { background: var(--edu-accent); color: #fff; width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center; }
.edu-ev { font-size: 10.5px; font-weight: 600; padding: 3px 7px; border-radius: 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.edu-ev--cours { background: var(--edu-cours-bg); color: var(--edu-cours); }
.edu-ev--evals { background: var(--edu-evals-bg); color: var(--edu-evals); }
.edu-ev--depots { background: var(--edu-depots-bg); color: var(--edu-depots); }
@media (max-width: 560px) { .edu-cal-day { min-height: 58px; } }

/* ==================== Fiche de renseignement (formulaire) ====================
   Composant PARTAGÉ (core/fiche) : édité par le prof (portal/admin) ET rempli par l'élève
   (portal/student). Classes neutres `fiche-*` — vit ici pour que les DEUX cadres l'héritent
   sans copier de CSS (« le cœur est importé, jamais copié »). */
.fiche-form { max-width: 760px; }
.fiche-fs {
  border: 1px solid var(--edu-border); border-radius: var(--edu-radius);
  padding: 8px 16px 16px; margin: 0 0 16px;
}
.fiche-fs legend {
  font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--edu-accent-ink); padding: 0 8px;
}
.fiche-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 16px; }
.fiche-field { display: flex; flex-direction: column; gap: 5px; }
.fiche-field:has(textarea) { grid-column: 1 / -1; }   /* les zones de texte prennent toute la largeur */
.fiche-field label { font-size: 12.5px; font-weight: 600; color: var(--edu-muted); }
.fiche-req { color: var(--edu-danger); font-weight: 700; }   /* marqueur champ obligatoire */
.fiche-in {
  width: 100%; padding: 8px 11px; border: 1px solid var(--edu-border-strong);
  border-radius: var(--edu-radius-sm); background: var(--edu-surface-2);
  font-size: 14px; font-family: var(--edu-font-ui);
}
.fiche-in:focus { border-color: var(--edu-accent); background: var(--edu-surface); outline: none; }
textarea.fiche-in { resize: vertical; min-height: 42px; }
.fiche-ro {                                            /* champ en lecture seule (identité côté élève) */
  padding: 8px 11px; border: 1px dashed var(--edu-border); border-radius: var(--edu-radius-sm);
  background: var(--edu-surface); color: var(--edu-muted); font-size: 14px;
}
.fiche-check { grid-column: 1 / -1; display: flex; gap: 10px; align-items: flex-start; font-size: 13px; cursor: pointer; }
.fiche-check input { margin-top: 3px; }
.fiche-check-sub { color: var(--edu-muted); font-size: 12px; line-height: 1.4; }
.fiche-foot { display: flex; justify-content: space-between; gap: 12px; margin-top: 4px; }

@media (max-width: 640px) { .fiche-grid { grid-template-columns: 1fr; } }

/* ==================== Contenu de cours rendu (.md -> HTML, RENDER_MODEL Track B) ====================
   Le module `cours` rend un .md via core/render (même dialecte que le PDF). Charte « cours » polie
   (2026-07-08, validée maquette) : on IMPORTE le traitement structurel du PDF (bandeaux de section,
   filets d'accent, tables à en-tête teinté, blocs de code sombres, callouts à kicker) dans les
   tokens --edu-* de l'app -> reste dans la charte (violet, aplats) + thème clair/sombre suivi.
   Classes des composants = EXACTEMENT celles du PDF (`_TEMPLATES/PDF/style.css`) -> parité. */
.cours-doc { line-height: 1.75; }
.cours-doc > * + * { margin-top: 15px; }
/* corps à l'encre --edu-text (lisible), pas au gris --edu-muted */
.cours-doc p, .cours-doc li { color: var(--edu-text); }
.cours-doc ul, .cours-doc ol { padding-left: 22px; }
.cours-doc ul { list-style: disc; }
.cours-doc li { margin: 5px 0; }
.cours-doc li::marker { color: var(--edu-cours); }

/* Titres : h1 filet + tick ; h2 = BANDEAU de section teinté (le geste signature du PDF) */
.cours-doc h1 { font-family: var(--edu-font-display); font-size: 30px; font-weight: 700; line-height: 1.15; letter-spacing: -.015em; color: var(--edu-text); text-wrap: balance; margin: 2px 0 6px; padding-bottom: 12px; border-bottom: 2px solid var(--edu-cours); position: relative; }
.cours-doc h1::after { content: ""; position: absolute; left: 0; bottom: -2px; width: 56px; height: 2px; background: var(--edu-accent); }
.cours-doc h2 { font-family: var(--edu-font-display); font-size: 20px; font-weight: 700; letter-spacing: -.01em; color: var(--edu-text); text-wrap: balance; margin: 36px 0 6px; padding: 9px 15px; background: var(--edu-cours-bg); border-left: 4px solid var(--edu-cours); border-radius: 0 var(--edu-radius-sm) var(--edu-radius-sm) 0; }
.cours-doc h3 { font-family: var(--edu-font-display); font-size: 17px; font-weight: 600; color: var(--edu-text); margin: 28px 0 4px; padding-bottom: 6px; border-bottom: 1px solid var(--edu-border); }
.cours-doc h4 { font-size: 14px; font-weight: 700; letter-spacing: .01em; color: var(--edu-accent-ink); margin: 20px 0 0; }

/* Code : inline discret ; bloc SOMBRE « premium » + liseré d'accent (repris du PDF) */
.cours-doc :not(pre) > code { font-family: var(--edu-font-mono); font-size: 12px; background: var(--edu-accent-soft); color: var(--edu-accent-ink); padding: 1px 6px; border-radius: 6px; }
.cours-doc pre { font-family: var(--edu-font-mono); font-size: 12.5px; line-height: 1.55; background: #211c33; color: #e9e6f5; border-left: 3px solid var(--edu-accent); border-radius: var(--edu-radius-sm); padding: 14px 16px; overflow-x: auto; white-space: pre; }
.cours-doc pre code { background: none; border: 0; padding: 0; color: inherit; font-size: inherit; }

/* Tables : conteneur scrollable arrondi (.table-wrap émis par core/render), en-tête teinté + zébrage */
.cours-doc .table-wrap { overflow-x: auto; border: 1px solid var(--edu-border); border-radius: var(--edu-radius-sm); box-shadow: var(--edu-shadow-sm); }
.cours-doc table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.cours-doc thead th { background: var(--edu-cours-bg); color: var(--edu-accent-ink); font-weight: 700; font-size: 11px; letter-spacing: .06em; text-transform: uppercase; padding: 11px 13px; text-align: left; border-bottom: 2px solid var(--edu-cours); }
.cours-doc tbody td { padding: 9px 13px; color: var(--edu-muted); border-top: 1px solid var(--edu-border); }
.cours-doc tbody tr:nth-child(even) { background: var(--edu-surface-2); }
.cours-doc tbody td:first-child { color: var(--edu-text); font-weight: 600; }

/* Callouts `:::info/success/warning/danger/note` — filet 4px + titre kicker MAJUSCULE coloré */
.cours-doc .info-box, .cours-doc .success-box, .cours-doc .warning-box,
.cours-doc .danger-box, .cours-doc .neutral-box {
  border-left: 4px solid var(--edu-evals); background: var(--edu-evals-bg);
  padding: 14px 18px 15px; border-radius: 0 var(--edu-radius-sm) var(--edu-radius-sm) 0; color: var(--edu-text);
}
.cours-doc .box-title { font-size: 11px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; margin: 0 0 6px; color: var(--edu-evals); }
.cours-doc .info-box { border-left-color: var(--edu-cours); background: var(--edu-cours-bg); }
.cours-doc .info-box .box-title { color: var(--edu-cours); }
.cours-doc .success-box { border-left-color: var(--edu-ok); background: var(--edu-ok-bg); }
.cours-doc .success-box .box-title { color: var(--edu-ok); }
.cours-doc .warning-box { border-left-color: var(--edu-warn); background: color-mix(in srgb, var(--edu-warn) 13%, var(--edu-surface)); }
.cours-doc .warning-box .box-title { color: var(--edu-warn); }
.cours-doc .danger-box  { border-left-color: var(--edu-danger); background: color-mix(in srgb, var(--edu-danger) 12%, var(--edu-surface)); }
.cours-doc .danger-box .box-title { color: var(--edu-danger); }
.cours-doc .neutral-box { border-left-color: var(--edu-border-strong); background: var(--edu-surface-2); }
.cours-doc .neutral-box .box-title { color: var(--edu-muted); }
.cours-doc .info-box p, .cours-doc .success-box p, .cours-doc .warning-box p,
.cours-doc .danger-box p, .cours-doc .neutral-box p { margin: 0; color: var(--edu-text); }

/* Grille label/valeur `:::grid` — cartes à filet gauche */
.cours-doc .info-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; }
.cours-doc .info-card { background: var(--edu-surface-2); border-left: 3px solid var(--edu-cours); border-radius: 0 var(--edu-radius-sm) var(--edu-radius-sm) 0; padding: 11px 14px; }
.cours-doc .info-card .label { font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--edu-accent-ink); }
.cours-doc .info-card .value { font-size: 14px; color: var(--edu-text); margin-top: 3px; }

/* Rangée de stats `:::stats` — tuiles teintées, chiffre serif (variantes primary/success/warning) */
.cours-doc .stats-row { display: flex; flex-wrap: wrap; gap: 12px; }
.cours-doc .stat-box { flex: 1 1 130px; text-align: center; padding: 15px 12px; border-radius: var(--edu-radius-sm); background: var(--edu-accent-soft); }
.cours-doc .stat-box.success { background: var(--edu-ok-bg); }
.cours-doc .stat-box.warning { background: color-mix(in srgb, var(--edu-warn) 15%, var(--edu-surface)); }
.cours-doc .stat-value { font-family: var(--edu-font-display); font-size: 29px; font-weight: 700; line-height: 1; color: var(--edu-accent-ink); font-variant-numeric: tabular-nums; }
.cours-doc .stat-box.success .stat-value { color: var(--edu-ok); }
.cours-doc .stat-box.warning .stat-value { color: var(--edu-warn); }
.cours-doc .stat-label { font-size: 11.5px; color: var(--edu-muted); margin-top: 6px; }

/* Blockquote teinté */
.cours-doc blockquote { background: var(--edu-surface-2); border-left: 3px solid var(--edu-border-strong); border-radius: 0 var(--edu-radius-sm) var(--edu-radius-sm) 0; padding: 12px 16px; color: var(--edu-muted); }
.cours-doc blockquote p { margin: 0; color: var(--edu-muted); }

/* Figures (images `.cours-fig`, émises par core/render) : carton CLAIR fixe + légende. Le fond clair
   ne suit PAS le thème -> un schéma/illustration reste lisible en mode sombre (pas un bloc sombre). */
.cours-doc .cours-fig { margin: 8px 0; text-align: center; }
.cours-doc .cours-fig img { max-width: 100%; height: auto; border: 1px solid #e7e3f1; border-radius: var(--edu-radius-sm); background: #ffffff; padding: 10px; }
.cours-doc figcaption { font-size: 12px; color: var(--edu-faint); margin-top: 8px; font-style: italic; text-wrap: balance; }
.cours-doc hr { border: 0; height: 1px; background: var(--edu-border); margin: 28px 0; }

/* Diagrammes Mermaid — rendus par mermaid.js (lazy). Carton CLAIR fixe (thème mermaid = marine,
   parité PDF) : lisible en clair ET sombre. Avant rendu : la source reste visible (jamais un vide
   muet, règle anti-échec silencieux) ; après : SVG centré, responsive. */
.cours-doc pre.mermaid { background: #ffffff; border: 1px solid #e7e3f1; border-radius: var(--edu-radius-sm); padding: 16px; margin: 8px 0; text-align: center; color: #40474f; overflow-x: auto; white-space: pre-wrap; font-size: 12px; }
/* LISIBILITÉ (RENDER_MODEL §2) : le SVG est mis à l'ÉCHELLE sur la largeur du contenu — plus un
   bandeau minuscule centré. `!important` bat le `max-width:<Npx>` INLINE que mermaid pose (useMaxWidth) :
   sans lui, un petit diagramme restait petit sur un large écran. `height:auto` garde le ratio ; les
   chaînes longues sont déjà basculées en vertical à la source (`render.orient_mermaid`). */
.cours-doc pre.mermaid svg { width: 100% !important; max-width: 100% !important; height: auto; }
.cours-doc pre.mermaid.mermaid--error { text-align: left; }
.cours-doc pre.mermaid.mermaid--error svg { width: auto !important; }

/* Item de liste cliquable (activité `cours` pointant une page .md) */
.edu-item--link { display: flex; align-items: center; justify-content: space-between; gap: 12px; text-decoration: none; color: inherit; cursor: pointer; transition: background .12s, border-color .12s; }
.edu-item--link:hover { background: var(--edu-cours-bg); border-color: var(--edu-cours); }
.edu-item-arrow { color: var(--edu-cours); font-weight: 700; flex: 0 0 auto; }

/* ==================== GLOSSAIRE (core/lexique) — le lexique dans sa vraie nature ====================
   Porté d'APP-SHARE `components/lexicon` : entrées structurées (terme · anglais, définition,
   catégorie), recherche, filtre catégorie, index alphabétique. Rendu serveur (core/lexique.render),
   filtré côté client. Re-thémé avec les tokens --edu-* (clair/sombre suivi). Namespace `lex-*`. */
.lexicon { max-width: 100%; }
/* En-tête : UNE ligne (le titre est déjà répété par le chrome du lecteur au-dessus). Centré + 27px,
   il coûtait 81px de haut pour deux compteurs. */
.lex-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  margin-bottom: 12px; padding-bottom: 9px; border-bottom: 1px solid var(--edu-border); }
.lex-title { font-family: var(--edu-font-display); font-size: 20px; font-weight: 700; letter-spacing: -.02em; color: var(--edu-text); margin: 0; }
.lex-meta { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 12.5px; color: var(--edu-muted); }
.lex-count { font-weight: 700; color: var(--edu-accent-ink); background: var(--edu-accent-soft); padding: 2px 10px; border-radius: var(--edu-pill); }
.lex-catn { align-self: center; }

/* ---- LE BANDEAU (`lex-bar`) — UN seul cadre collant, deux lignes -------------------------------
   Avant : trois bandes pleine largeur empilées (recherche · domaines · alphabet) = 136px avalés pour
   trois contrôles minuscules, dans une largeur restée vide. Les trois n'ont pas le même poids, donc
   plus la même surface : la RECHERCHE est le geste principal (mais un mot n'a jamais eu besoin de
   683px), le DOMAINE est un aiguillage (chips, dans l'espace libéré, même ligne), l'ALPHABET est un
   INDEX de navigation (pas un filtre) -> ligne discrète sous un filet, dans le même cadre.
   Collant seulement en desktop : sur un téléphone, un bandeau qui suit le scroll rognerait la lecture. */
/* `top` : le bandeau se cale SOUS la topbar du portail (`.shell-topbar`, collante, ~78px, z-index 5) —
   avec `top: 0` (l'ancien réglage) il glissait DESSOUS et devenait illisible dès le premier scroll :
   un contrôle collant qu'on ne voit pas ne sert à rien. Valeur miroir, jamais un re-style de `shell-*`
   (frontière) ; si la topbar change de taille, le bandeau colle juste un peu plus haut/bas — rien ne casse. */
.lex-bar { position: sticky; top: 78px; z-index: 3; display: flex; flex-direction: column; gap: 6px;
  margin-bottom: 14px; padding: 8px 12px; background: var(--edu-surface); border: 1px solid var(--edu-border);
  border-radius: var(--edu-radius); box-shadow: var(--edu-shadow-sm); }
.lex-controls { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.lex-search { flex: 0 1 300px; min-width: 180px; padding: 7px 12px; border: 1px solid var(--edu-border-strong);
  border-radius: var(--edu-radius-sm); font-size: 14px; font-family: var(--edu-font-ui);
  background: var(--edu-surface-2); color: var(--edu-text); }
.lex-search:focus { outline: none; border-color: var(--edu-accent); background: var(--edu-surface);
  box-shadow: 0 0 0 3px var(--edu-accent-soft); }
.lex-search::placeholder { color: var(--edu-faint); }
.lex-catfilter { padding: 7px 10px; border: 1px solid var(--edu-border-strong); border-radius: var(--edu-radius-sm);
  font-size: 13px; font-family: var(--edu-font-ui); background: var(--edu-surface-2); color: var(--edu-text); cursor: pointer; min-width: 150px; }
.lex-catfilter:focus-visible { outline: 2px solid var(--edu-accent); outline-offset: 1px; }
.lex-resn { font-size: 12.5px; color: var(--edu-muted); margin-left: auto; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Filtre DOMAINE (agrégat de N lexiques) — des chips, jamais un 2ᵉ select : l'élève les voit d'un
   coup (≤ 5). Masqué par le rendu lui-même quand la session n'a qu'un domaine. Elles vivent DANS la
   ligne de contrôles ; sur un écran étroit elles passent à la ligne, sans bande à elles. */
.lex-domains { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; flex: 1 1 auto; min-width: 0; }
.lex-dom { padding: 4px 11px; border: 1px solid var(--edu-border-strong); background: var(--edu-surface);
  color: var(--edu-text); font-family: var(--edu-font-ui); font-size: 12px; font-weight: 600;
  border-radius: var(--edu-pill); cursor: pointer; transition: background .12s, color .12s, border-color .12s; }
.lex-dom:hover { border-color: var(--edu-accent); color: var(--edu-accent); }
.lex-dom:focus-visible { outline: 2px solid var(--edu-accent); outline-offset: 2px; }
.lex-dom.active { background: var(--edu-accent); border-color: var(--edu-accent); color: #fff; }
/* L'étiquette de domaine sur la carte : ce qui rend deux homonymes (Trame IP / Trame Radio) lisibles.
   ⚠ Elle vit dans `.lex-term-r` avec le ✓ : c'est le bloc de droite, INSÉCABLE (sans quoi, sur un nom
   long, le ✓ retombait seul à la ligne — vu à l'écran). C'est `.lex-term-r` qui porte le `margin-left`. */
.lex-term-r { margin-left: auto; flex: 0 0 auto; display: flex; align-items: center; gap: 6px; }
.lex-domtag { font-size: 10.5px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--edu-accent-ink); background: var(--edu-accent-soft);
  padding: 2px 8px; border-radius: var(--edu-pill); }
.lex-domn { align-self: center; }

/* Index alphabétique — un INDEX, pas un filtre : plus de bande encadrée, une ligne discrète dans le
   bandeau, séparée par un filet. */
.lex-alpha { display: flex; flex-wrap: wrap; gap: 2px; align-items: center; margin: 0;
  padding-top: 6px; border-top: 1px solid var(--edu-border); }
.lex-let { width: 24px; height: 24px; display: grid; place-items: center; border: 0; background: transparent;
  color: var(--edu-muted); font-family: var(--edu-font-ui); font-size: 12px; font-weight: 600;
  border-radius: var(--edu-radius-sm); cursor: pointer; transition: background .12s, color .12s; }
/* « Tout » n'est pas une lettre : sans largeur propre, la boîte carrée le tronquait en « Tou ». */
.lex-let--all { width: auto; padding: 0 10px; margin-right: 4px; }
.lex-let:hover { background: var(--edu-surface-2); color: var(--edu-accent); }
.lex-let:focus-visible { outline: 2px solid var(--edu-accent); outline-offset: 1px; }
.lex-let.active { background: var(--edu-accent); color: #fff; }

/* Sections par lettre + grille de cartes */
/* `scroll-margin-top` : le saut de l'index doit atterrir SOUS la topbar (78) + le bandeau collant (93),
   sinon la lettre visée se gare derrière eux et l'élève croit que le bouton n'a rien fait. */
.lex-section { margin-bottom: 26px; scroll-margin-top: 180px; }
.lex-section-t { font-family: var(--edu-font-display); font-size: 20px; font-weight: 700; color: var(--edu-accent-ink);
  margin: 0 0 12px; padding-bottom: 5px; border-bottom: 2px solid var(--edu-cours); display: inline-block; }
.lex-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 12px; }
.lex-term { background: var(--edu-surface); border: 1px solid var(--edu-border); border-radius: var(--edu-radius);
  padding: 14px 16px; box-shadow: var(--edu-shadow-sm); transition: border-color .12s, box-shadow .12s; }
.lex-term:hover { border-color: var(--edu-cours); box-shadow: var(--edu-shadow); }
.lex-term-h { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-bottom: 4px; }
.lex-name { font-weight: 700; font-size: 15px; color: var(--edu-text); }
.lex-en { font-style: italic; color: var(--edu-muted); font-size: 12.5px; }
.lex-en::before { content: "· "; }
.lex-def { font-size: 13.5px; color: var(--edu-text); line-height: 1.55; margin: 4px 0 8px; }
.lex-cat { display: inline-block; font-size: 11px; font-weight: 600; padding: 2px 9px; border: 0;
  border-radius: var(--edu-pill); background: var(--edu-surface-2); color: var(--edu-muted); cursor: pointer; }
.lex-cat:hover { filter: brightness(.96); }
.lex-empty { text-align: center; padding: 48px 0; color: var(--edu-muted); font-size: 15px; }

/* ---- LE « VU » (N3) : l'élève marque les termes qu'il a lus ------------------------------------
   Mémoire `localStorage` (jamais le serveur), clé = `domaine§nom` — cf. `core/lexique.py`.
   Marque DISCRÈTE et theme-aware : le terme vu **s'efface** (texte estompé, fond retiré) et son ✓
   s'allume. ⛔ Aucune couleur en dur : `--edu-ok` / `--edu-faint` / `--edu-surface-2` — donc clair ET
   sombre suivent. On grise le TEXTE plutôt que la carte (`opacity`) : un `opacity` sur la carte
   éteindrait aussi le ✓ et la bague de focus. */
.lex-term[data-vu] { cursor: pointer; }
.lex-vu {
  flex: 0 0 auto; background: none; border: 0; cursor: pointer;
  color: var(--edu-faint); font-size: 12px; line-height: 1; padding: 3px 6px; border-radius: 6px;
  opacity: .25; transition: opacity .12s, color .12s;
}
.lex-term:hover .lex-vu { opacity: .7; }
.lex-vu:focus-visible { opacity: 1; outline: 2px solid var(--edu-accent); outline-offset: 1px; }
.lex-vu[aria-pressed="true"] { opacity: 1; color: var(--edu-ok); }
.lex-term.is-vu { background: var(--edu-surface-2); box-shadow: none; }
.lex-term.is-vu .lex-name, .lex-term.is-vu .lex-def, .lex-term.is-vu .lex-en { color: var(--edu-faint); }
.lex-term.is-vu .lex-cat { opacity: .6; }
/* la remise à zéro : discrète (une ligne de texte), et ABSENTE tant qu'il n'y a rien à effacer */
.lex-vureset {
  background: none; border: 0; cursor: pointer; padding: 3px 6px; border-radius: var(--edu-radius-sm);
  font-family: var(--edu-font-ui); font-size: 12px; color: var(--edu-faint); white-space: nowrap;
}
.lex-vureset:hover { color: var(--edu-accent); background: var(--edu-surface-2); }
.lex-vureset:focus-visible { outline: 2px solid var(--edu-accent); outline-offset: 1px; }
.lex-vureset[hidden] { display: none; }

/* Pastilles de catégorie (palette fixe, lisible en clair ET sombre — comme le carton clair des figures) */
.lex-cat.category-technique { background: #dbeafe; color: #1d4ed8; }
.lex-cat.category-equipement { background: #dcfce7; color: #15803d; }
.lex-cat.category-animation { background: #fef3c7; color: #b45309; }
.lex-cat.category-contenu { background: #f3e8ff; color: #7c3aed; }
.lex-cat.category-diffusion { background: #ffedd5; color: #c2410c; }
.lex-cat.category-habillage { background: #fce7f3; color: #be185d; }
.lex-cat.category-metier { background: #e0e7ff; color: #4338ca; }
.lex-cat.category-production { background: #ccfbf1; color: #0d9488; }
.lex-cat.category-mesure { background: #fef9c3; color: #a16207; }
.lex-cat.category-reglementation { background: #fee2e2; color: #dc2626; }
.lex-cat.category-commercial { background: #d1fae5; color: #059669; }
.lex-cat.category-programmation { background: #ede9fe; color: #6d28d9; }
.lex-cat.category-journalisme { background: #e0f2fe; color: #0284c7; }
.lex-cat.category-musique { background: #fecaca; color: #b91c1c; }
.lex-cat.category-juridique { background: #fda4af; color: #be123c; }

.lex-sources { margin-top: 30px; padding-top: 16px; border-top: 1px solid var(--edu-border); }
.lex-sources h4 { font-size: 11px; font-weight: 700; color: var(--edu-muted); margin: 0 0 8px; text-transform: uppercase; letter-spacing: .06em; }
.lex-sources ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 4px 16px; }
.lex-sources a { color: var(--edu-muted); text-decoration: none; font-size: 13px; }
.lex-sources a:hover { color: var(--edu-accent); }

/* MOBILE — c'est le cas d'usage réel (les élèves sont au téléphone, en salle). Le bandeau ne devient
   PAS une colonne : la recherche prend la ligne, la catégorie et le compteur se partagent la suivante,
   les chips de domaine passent à la ligne d'elles-mêmes. Et il ne COLLE plus : sur un écran de 700px
   de haut, un bandeau qui suit le scroll rogne la lecture qu'il est censé servir. */
@media (max-width: 720px) {
  .lex-bar { position: static; padding: 8px 10px; }
  .lex-search { flex: 1 1 100%; min-width: 0; }
  .lex-catfilter { flex: 1 1 auto; min-width: 0; }
  .lex-resn { margin-left: auto; }
  /* Les 26 lettres se replient : resserrées, elles tiennent en 2 lignes au lieu de 3 (une bande
     d'index de 3 lignes sur un téléphone repousserait le premier terme hors de l'écran). */
  .lex-alpha { gap: 1px; }
  .lex-let { width: 24px; height: 26px; }
  /* `width: auto` RÉAFFIRMÉ : la règle `.lex-let` ci-dessus est de même spécificité et plus tardive
     que celle de la base — sans ça, « Tout » repasse à 24px et la lettre A lui monte dessus. */
  .lex-let--all { width: auto; padding: 0 9px; margin-right: 2px; }
  .lex-section { scroll-margin-top: 76px; }   /* bandeau non collant : seule la topbar gêne */
  .lex-grid { grid-template-columns: 1fr; }
}

/* ---- Picker partagé (Montage + Régie) — cadre + polish, tokens uniquement ----
   Le menu déroulant piochable : cadre, position, recherche, groupes, repli catalogue.
   Contraste, hover d'item, focus-visible accent, ombre tokenisée, ouverture animée
   (l'anim est neutralisée par le reset `prefers-reduced-motion` de base.css). */
.edu-pick { position: relative; display: inline-block; }
.edu-pick > summary { list-style: none; cursor: pointer; }
.edu-pick > summary::-webkit-details-marker { display: none; }
.edu-pick-menu {
  position: absolute; z-index: 50; top: calc(100% + 6px); left: 0;
  min-width: 260px; max-width: 380px; max-height: 360px; overflow-y: auto;
  display: flex; flex-direction: column; gap: 2px; padding: 8px;
  background: var(--edu-surface); border: 1px solid var(--edu-border-strong);
  border-radius: var(--edu-radius); box-shadow: var(--edu-shadow-lg);
}
@keyframes edu-pick-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } }
.edu-pick[open] > .edu-pick-menu { animation: edu-pick-in .13s ease-out; transform-origin: top; }
.edu-pick-search {
  width: 100%; box-sizing: border-box; padding: 7px 10px; margin-bottom: 4px;
  border: 1px solid var(--edu-border); border-radius: var(--edu-radius-sm);
  background: var(--edu-surface-2); color: var(--edu-text); font: inherit; font-size: 13px;
}
.edu-pick-search:focus-visible {
  outline: none; border-color: var(--edu-accent);
  box-shadow: 0 0 0 2px var(--edu-accent-soft);
}
.edu-pick-count { font-size: 11px; color: var(--edu-muted); padding: 0 2px 4px; }
.edu-pick-count:empty { display: none; }
.edu-pick-group {
  font-size: 10.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  color: var(--edu-faint); padding: 6px 4px 2px;
}
.edu-pick-item {
  text-align: left; width: 100%; padding: 7px 10px; border-radius: var(--edu-radius-sm);
  border: 1px solid transparent; background: transparent; color: var(--edu-text);
  font: inherit; font-size: 13px; line-height: 1.35; cursor: pointer;
  transition: background .1s, color .1s;
}
/* Survol = affordance « sélectionnable » (aplat accent doux + encre accent). */
.edu-pick-item:hover {
  background: var(--edu-accent-soft); color: var(--edu-accent-ink); border-color: transparent;
}
/* Focus clavier = anneau accent NET, distinct du survol (ne jamais le remplacer par le hover). */
.edu-pick-item:focus-visible {
  background: var(--edu-accent-soft); color: var(--edu-accent-ink);
  outline: 2px solid var(--edu-accent); outline-offset: -2px; border-color: transparent;
}
.edu-pick-item[hidden], .edu-pick-group[hidden] { display: none; }
.edu-pick-more { margin-top: 4px; border-top: 1px solid var(--edu-border); padding-top: 4px; }
.edu-pick-more > summary {
  list-style: none; cursor: pointer; font-size: 12px; font-weight: 600;
  color: var(--edu-muted); padding: 4px; border-radius: var(--edu-radius-sm);
  transition: color .1s;
}
.edu-pick-more > summary:hover { color: var(--edu-accent-ink); }
.edu-pick-more > summary:focus-visible {
  outline: 2px solid var(--edu-accent); outline-offset: -2px; color: var(--edu-text);
}
.edu-pick-more > summary::-webkit-details-marker { display: none; }
.edu-pick-fam {
  font-size: 11px; font-weight: 800; letter-spacing: .02em;
  color: var(--edu-text); padding: 8px 4px 2px; margin-top: 4px;
  border-top: 1px solid var(--edu-border);
}
.edu-pick-menu > .edu-pick-fam:first-of-type { border-top: 0; margin-top: 0; }
.edu-pick-fam[hidden] { display: none; }

/* ======================= LE RAIL DE LECTURE (sommaire + reprise + marque-pages) ===============
   Un TP de 30 pages : l'élève clique ailleurs, revient, il est perdu. Le rail est UN SEUL objet
   (les marque-pages vivent EN TÊTE du sommaire : c'est UNE navigation, pas deux).
   Émis par `modules/cours/rail.py` — éligibilité STRUCTURELLE (prose + >= 3 titres h1/h2), zéro
   drapeau YAML. Tokens `--edu-*` seulement (clair ET sombre) ; aucun re-style des `.edu-*`. */

.read-wrap { display: grid; grid-template-columns: minmax(0, 1fr) 232px; gap: 20px; align-items: start; }
.read-col { min-width: 0; }
/* la tête de section ne doit pas passer SOUS la topbar collante quand on saute dessus */
.read-wrap .cours-doc h1, .read-wrap .cours-doc h2 { scroll-margin-top: 92px; }

/* le rail : collant sous la topbar */
.read-rail {
  position: sticky; top: 78px; max-height: calc(100vh - 100px); overflow-y: auto;
  background: var(--edu-surface); border: 1px solid var(--edu-border);
  border-radius: var(--edu-radius); box-shadow: var(--edu-shadow-sm); padding: 12px 10px 14px;
}
.read-h {
  font-size: 10.5px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--edu-faint); margin: 6px 6px 8px;
}
.read-toc { display: flex; flex-direction: column; gap: 1px; }
.read-row { position: relative; display: flex; align-items: center; gap: 2px; }
.read-link {
  flex: 1; min-width: 0; text-align: left; background: none; border: 0; cursor: pointer;
  font-family: var(--edu-font-ui); font-size: 12.5px; line-height: 1.35; color: var(--edu-muted);
  padding: 6px 8px; border-radius: 8px; border-left: 2px solid transparent;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.read-row.read-lvl2 .read-link { padding-left: 18px; font-size: 12px; }
.read-link:hover { background: var(--edu-surface-2); color: var(--edu-text); }
.read-link:focus-visible { outline: 2px solid var(--edu-accent); outline-offset: -2px; }
.read-link.is-active {
  color: var(--edu-accent-ink); background: var(--edu-accent-soft);
  border-left-color: var(--edu-accent); font-weight: 600;
}
.read-add {
  flex: 0 0 auto; background: none; border: 0; cursor: pointer; padding: 3px 4px; border-radius: 6px;
  font-size: 12px; line-height: 1; opacity: .18; filter: grayscale(1);
}
.read-row:hover .read-add, .read-add:focus-visible { opacity: .6; }
.read-add.is-on { opacity: 1; filter: none; }
.read-add:focus-visible { outline: 2px solid var(--edu-accent); outline-offset: 1px; }

/* palette FERMÉE (4 teintes = 4 tokens ; aucun color picker, aucune valeur en dur).
   ⚠ N4c : elle était `position:absolute` -> elle RECOUVRAIT la ligne suivante du sommaire (vu à
   l'écran). Elle est maintenant **dans le flux**, insérée APRÈS la ligne visée : elle se pose
   dessous et pousse la suite. Rien à recouvrir, donc plus rien à masquer. */
.read-pal {
  display: flex; gap: 6px; padding: 5px 6px; margin: 2px 0 3px 18px; width: max-content;
  background: var(--edu-surface-2); border: 1px solid var(--edu-border-strong);
  border-radius: var(--edu-radius-sm); box-shadow: var(--edu-shadow-sm);
}
.read-pal[hidden] { display: none; }
.read-sw { width: 16px; height: 16px; border-radius: 50%; border: 1px solid var(--edu-border-strong); cursor: pointer; padding: 0; }
.read-sw:focus-visible { outline: 2px solid var(--edu-accent); outline-offset: 2px; }

.read-dot { flex: 0 0 auto; width: 9px; height: 9px; border-radius: 50%; }
.read-dot--accent, .read-sw.read-dot--accent { background: var(--edu-accent); }
.read-dot--evals,  .read-sw.read-dot--evals  { background: var(--edu-evals); }
.read-dot--ok,     .read-sw.read-dot--ok     { background: var(--edu-ok); }
.read-dot--warn,   .read-sw.read-dot--warn   { background: var(--edu-warn); }
.read-dot--pointer { background: var(--edu-pointer); }

/* 🔒 REPÈRE DU FORMATEUR (P4) — PUBLIC, teinté « pointeur » (jaune/or). Distinct des marque-pages
   PRIVÉS de l'élève. En tête de la liste des marque-pages ; « 📍 le formateur regarde ici ». */
.read-mark--pointer, .read-mark--pointer:hover { background: var(--edu-pointer-bg); }
.read-mark--pointer .read-mlab { color: var(--edu-pointer-ink); font-weight: 600; }
/* la SECTION pointée : bande de surlignage + liseré vif (theme-aware, aucune couleur en dur). */
.read-pointed {
  background: var(--edu-pointer-bg); box-shadow: inset 4px 0 0 0 var(--edu-pointer);
  padding: 3px 8px 3px 12px; border-radius: 5px; scroll-margin-top: 84px;
}
/* 📍 prof (P4) : bouton injecté par le module `pointer` dans chaque section du sommaire (aperçu Régie).
   Aligné visuellement sur le 🔖, teinté « pointeur » à l'état actif. */
.read-pin {
  flex: 0 0 auto; background: none; border: 0; cursor: pointer; padding: 3px 4px; border-radius: 6px;
  font-size: 12px; line-height: 1; opacity: .28; filter: grayscale(1);
}
.read-row:hover .read-pin, .read-pin:focus-visible { opacity: .7; }
.read-pin.is-on { opacity: 1; filter: none; }
.read-pin:focus-visible { outline: 2px solid var(--edu-pointer); outline-offset: 1px; }
/* en aperçu prof, le prof pose des 📍 (repères publics), pas des 🔖 (marque-pages privés) : on masque les 🔖. */
.read-wrap.pointer-prof .read-add { display: none; }

.read-marks { display: flex; flex-direction: column; gap: 2px; margin-bottom: 12px; }
.read-empty { font-size: 11.5px; color: var(--edu-faint); line-height: 1.4; margin: 0 6px 2px; }
.read-mark { display: flex; align-items: center; gap: 6px; padding: 3px 4px 3px 8px; border-radius: 8px; }
.read-mark:hover { background: var(--edu-surface-2); }
.read-mlab {
  flex: 1; min-width: 0; text-align: left; background: none; border: 0; padding: 3px 0; cursor: pointer;
  font-family: var(--edu-font-ui); font-size: 12px; color: var(--edu-text); line-height: 1.3;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.read-mlab:focus-visible { outline: 2px solid var(--edu-accent); outline-offset: 1px; border-radius: 6px; }
/* 🔒 « section modifiée » : le marque-page RESTE listé (jamais effacé en silence) mais NE SAUTE PAS
   (jamais au mauvais endroit) — le titre visé n'existe plus dans le document. */
.read-mlab.is-stale { cursor: default; color: var(--edu-faint); white-space: normal; }
.read-stale {
  display: block; font-style: normal; font-size: 10px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--edu-warn);
}
.read-del { flex: 0 0 auto; background: none; border: 0; cursor: pointer; color: var(--edu-faint); font-size: 11px; padding: 2px 4px; border-radius: 6px; }
.read-del:hover { color: var(--edu-danger); background: var(--edu-surface); }
.read-del:focus-visible { outline: 2px solid var(--edu-accent); outline-offset: 1px; }

/* le bandeau de reprise : automatique, mais JAMAIS silencieux.
   ⚠ IL DOIT ÊTRE COLLANT — défaut vu AU NAVIGATEUR, invisible aux tests (jsdom n'a pas de layout) :
   en flux normal, le bandeau vit en HAUT du document… et la reprise nous dépose 2000 px plus bas.
   Il était donc rendu, correct, et JAMAIS VU. Un bandeau qu'on ne voit pas est un saut muet — soit
   exactement le mal qu'on soigne (🔒 arbitrage (4)). */
.read-resume {
  position: sticky; top: 62px; z-index: 30;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 12px;
  padding: 9px 14px; font-size: 12.5px; color: var(--edu-accent-ink);
  background: var(--edu-accent-soft); border: 1px solid var(--edu-border);
  border-radius: var(--edu-pill);
}
.read-resume[hidden] { display: none; }
.read-resume-lab { color: var(--edu-muted); }
.read-resume-t { font-weight: 600; }
.read-resume-t::before { content: "« "; } .read-resume-t::after { content: " »"; }
.read-top {
  margin-left: auto; background: none; border: 0; cursor: pointer; font-family: var(--edu-font-ui);
  font-size: 12px; font-weight: 600; color: var(--edu-accent); padding: 2px 6px; border-radius: var(--edu-pill);
}
.read-top:hover { background: var(--edu-surface); }
.read-top:focus-visible { outline: 2px solid var(--edu-accent); outline-offset: 1px; }

/* ==================== PANNEAU « PIÈCES » (RENDER_MODEL §8) ====================
   Les pièces d'un document (médias, schéma, annexe, PDF) déclarées en front-matter `pieces:`, dans
   la colonne latérale au niveau des marque-pages. Rendues DANS la page ; jouables inline. Tokens
   `--edu-*` seulement (clair ET sombre). */
.read-pieces { margin-bottom: 12px; }
.piece {
  border: 1px solid var(--edu-border); border-radius: var(--edu-radius-sm);
  background: var(--edu-surface-2); margin: 0 2px 6px; overflow: hidden;
}
.piece-h {
  display: flex; align-items: center; gap: 7px; cursor: pointer; list-style: none;
  padding: 7px 9px; font-family: var(--edu-font-ui); font-size: 12px; font-weight: 600;
  color: var(--edu-text); line-height: 1.3;
}
.piece-h::-webkit-details-marker { display: none; }
.piece-h:hover { background: var(--edu-surface); }
.piece-h:focus-visible { outline: 2px solid var(--edu-accent); outline-offset: -2px; }
.piece-ic { flex: 0 0 auto; font-size: 13px; }
.piece-t { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.piece[open] .piece-h { border-bottom: 1px solid var(--edu-border); }
.piece-body { padding: 9px; min-width: 0; }
/* Le lecteur média TIENT dans la colonne étroite du rail : un `<audio>`/`<video>` prend sinon sa
   largeur intrinsèque (~300px) et déborde à droite (barre de progression rognée). On force la
   contrainte au conteneur — `width:100%` + `max-width:100%` + `box-sizing:border-box` — et
   `min-width:0` sur les blocs parents pour qu'ils puissent rétrécir sous la largeur intrinsèque. */
.read-pieces, .piece, .piece-body { min-width: 0; }
.piece-media,
.read-pieces audio, .read-pieces video {
  display: block; width: 100%; max-width: 100%; box-sizing: border-box;
}
video.piece-media { height: auto; border-radius: var(--edu-radius-sm); }
.piece-img { width: 100%; height: auto; border-radius: var(--edu-radius-sm); display: block; }
/* le schéma (annexe .md à SVG embarqué) rendu DANS la page ; scrollable s'il déborde. */
.piece-schema { overflow: auto; max-height: 70vh; }
.piece-schema img, .piece-schema svg { width: 100%; height: auto; display: block; }
.piece-schema h1 { font-size: 14px; margin: 0 0 6px; }
.piece-schema p { font-size: 11.5px; color: var(--edu-muted); line-height: 1.4; }
.piece-open {
  display: inline-block; font-size: 12px; font-weight: 600; color: var(--edu-accent-ink);
  background: var(--edu-accent-soft); border: 1px solid var(--edu-border);
  border-radius: var(--edu-pill); padding: 6px 12px; text-decoration: none;
}
.piece-open:hover { background: var(--edu-surface); }
.piece-missing { font-size: 11.5px; color: var(--edu-warn); margin: 0; line-height: 1.4; }

/* Accordéons du rail (marque-pages / sommaire) : le titre `.read-h` devient un summary cliquable —
   les marque-pages se replient pour partager la hauteur avec le panneau Pièces (§8). */
.read-h--acc { cursor: pointer; list-style: none; display: flex; align-items: center; gap: 6px; }
.read-h--acc::-webkit-details-marker { display: none; }
.read-h--acc::after {
  content: "▸"; margin-left: auto; font-size: 10px; transition: transform .15s; color: var(--edu-faint);
}
details[open] > .read-h--acc::after { transform: rotate(90deg); }
.read-marks-acc, .read-toc-acc { margin-bottom: 4px; }

/* bouton « Sommaire » : mobile seulement */
.read-toggle { display: none; }

/* ---- < 900 px : le rail devient un TIROIR. Il ne doit JAMAIS écraser le texte. ---- */
@media (max-width: 900px) {
  .read-wrap { grid-template-columns: 1fr; }
  .read-toggle {
    display: inline-flex; align-items: center; gap: 6px; margin-bottom: 12px; cursor: pointer;
    font-family: var(--edu-font-ui); font-size: 12.5px; font-weight: 600; color: var(--edu-text);
    background: var(--edu-surface); border: 1px solid var(--edu-border-strong);
    border-radius: var(--edu-pill); padding: 7px 14px; box-shadow: var(--edu-shadow-sm);
  }
  .read-rail {
    position: fixed; z-index: 40; top: 0; right: 0; bottom: 0; width: min(280px, 84vw);
    max-height: none; border-radius: 0; border-width: 0 0 0 1px; box-shadow: var(--edu-shadow-lg);
    padding-top: 18px; transform: translateX(102%); transition: transform .18s ease; visibility: hidden;
  }
  .read-wrap.rail-open .read-rail { transform: none; visibility: visible; }
}

/* ============================ « Emporter ce support » (TICKET P) ============================
   Cluster COMPACT icône-seule en tête de la colonne de contenu (page de cours) + rangée de
   téléchargements de la page lexique. Remplace l'ancien gros callout pleine largeur.
   Même sobriété que le poste de commande de la Régie (`.fil-cmd-ico`) : icône seule, sens porté par
   `aria-label` + `title`. Namespace `support-*` (⛔ aucun re-style des `.edu-*`). Theme-aware :
   tokens `--edu-*` seulement, aucune couleur en dur, aucun dégradé. */
.support-bar {
  display: flex; align-items: center; justify-content: flex-end; flex-wrap: wrap;
  gap: 8px; margin: 0 0 16px; padding-bottom: 12px;
  border-bottom: 1px solid var(--edu-border);
}
.support-ico {
  position: relative; box-sizing: border-box; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; padding: 0;
  font-size: 16px; line-height: 1; cursor: pointer; text-decoration: none;
  border: 1px solid var(--edu-border); border-radius: var(--edu-radius-sm);
  background: var(--edu-surface); color: var(--edu-text);
  transition: border-color .12s, background .12s, color .12s;
}
.support-ico:hover,
.support-ico:focus-visible {
  border-color: var(--edu-accent); background: var(--edu-accent-soft); color: var(--edu-accent-ink);
}
.support-ico:focus-visible { outline: 2px solid var(--edu-accent); outline-offset: 2px; }
/* Pas d'email en fiche : le bouton mail devient inactif (jamais une phrase pleine largeur). */
.support-ico.is-disabled {
  cursor: not-allowed; opacity: .5; color: var(--edu-faint);
  border-style: dashed; background: transparent;
}
.support-ico.is-disabled:hover {
  border-color: var(--edu-border); background: transparent; color: var(--edu-faint);
}
.support-gl { display: inline-flex; }
.support-mailform { display: inline-flex; margin: 0; padding: 0; border: 0; }
/* Version « peut-être à jour » : petit ⚠ en coin du bouton Télécharger (sens dans son `title`). */
.support-warn { position: absolute; top: -6px; right: -6px; font-size: 11px; line-height: 1; pointer-events: none; }
.support-ico--warn { border-color: var(--edu-warn); }
/* Flash mail : message TRANSITOIRE après action, discret à gauche du cluster (jamais un pavé). */
.support-flash { margin-right: auto; align-self: center; font-size: .82rem; font-weight: 600; }
.support-flash--ok  { color: var(--edu-ok); }
.support-flash--err { color: var(--edu-danger); }
.support-flash--warn { color: var(--edu-warn); }

/* Page lexique : rangée compacte de puces de téléchargement nommées (une par lexique). */
.support-dlrow { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin: 0 0 18px; }
.support-dlrow-lab { font-size: .82rem; font-weight: 600; color: var(--edu-muted); }
.support-dl {
  display: inline-flex; align-items: center; gap: 6px; box-sizing: border-box;
  padding: 5px 12px; font-size: .82rem; text-decoration: none;
  border: 1px solid var(--edu-border); border-radius: var(--edu-radius-sm);
  background: var(--edu-surface); color: var(--edu-text);
  transition: border-color .12s, background .12s, color .12s;
}
.support-dl:hover,
.support-dl:focus-visible {
  border-color: var(--edu-accent); background: var(--edu-accent-soft); color: var(--edu-accent-ink);
}
.support-dl:focus-visible { outline: 2px solid var(--edu-accent); outline-offset: 2px; }
