/* LANGIAL ACADEMY — complément de charte.
   Auteur : Brice Kengni Zanguim.

   CE FICHIER N'INVENTE RIEN. La charte vit chez la maison mère et arrive par
   `charte/app.min.css` (jetons de couleur, motif Ndop, aurores, .card, .btn, .chip,
   .field, .toast, .bottom-nav, .brand…). On n'ajoute ici que les quelques éléments
   propres à un espace d'enseignement, en réutilisant SES variables — jamais de
   couleur en dur, jamais un composant redessiné.

   Toute règle de ce fichier est préfixée `ac-` pour qu'on voie d'un coup d'œil ce qui
   appartient à la filiale et ce qui vient de la mère. */

/* ─────────────────────────────────────────────────────────────────────────────
   Le seul correctif GÉNÉRAL, et il mérite son explication.
   L'attribut `hidden` du HTML est posé par une règle de la feuille du navigateur,
   de spécificité plus faible que n'importe quelle classe. Tout élément portant à la
   fois `hidden` et une classe qui pose un `display` reste donc VISIBLE. La maison
   mère a rencontré le piège au moins trois fois et l'a corrigé au cas par cas
   (`.chip[hidden]`, `.onboard-ribbon[hidden]`, le bouton d'installation…) ; une règle
   générale règle la famille entière, présente et à venir. À remonter chez la mère.
   ───────────────────────────────────────────────────────────────────────────── */
[hidden] { display: none !important; }

/* ─────────────────────────────────────────────────────────────────────────────
   Deuxième complément, du même ordre : la charte de la maison mère ne style que
   `input[type="text"]`, `select` et `textarea`. Tout autre type de champ reste donc
   brut, au style par défaut du navigateur — un champ de mot de passe deux fois moins
   haut que le champ juste au-dessus, par exemple. Academy en emploie cinq sortes
   (mot de passe, courriel, nombre, date, fichier), on étend donc la même règle sans en
   changer une valeur.
   À REMONTER CHEZ LA MÈRE : LANGIAL possède lui-même cinq champs de mot de passe
   (modale de compte, réinitialisation), aujourd'hui non stylés pour cette raison.
   ───────────────────────────────────────────────────────────────────────────── */
input[type="password"], input[type="email"], input[type="number"],
input[type="date"], input[type="search"], input[type="tel"], input[type="file"] {
  width: 100%; background: var(--bg); color: var(--text);
  border: 1px solid var(--border); border-radius: 11px;
  padding: 11px 13px; font-size: 1rem; font-family: inherit;
  transition: border-color .16s ease, box-shadow .16s ease, background .16s ease;
}
/* Un champ de fichier reste haut de gamme : le bouton interne reprend la teinte de la
   marque plutôt que le gris du système. */
input[type="file"]::file-selector-button {
  border: 1px solid var(--border); background: var(--panel); color: var(--text);
  border-radius: 9px; padding: 7px 12px; margin-right: 12px; font-family: inherit;
  font-weight: 700; cursor: pointer;
}
/* La charte donne aux zones de texte une taille de police généreuse, pensée pour la
   saisie d'un mot dans une langue à tons. Dans Academy, ces zones servent à rédiger une
   leçon ou une consigne : on revient à une taille de lecture normale. */
.view textarea, .ac-modale textarea { font-size: 1rem; line-height: 1.6; }

/* ── Portail : la vitrine de la filiale ──────────────────────────────────── */
.ac-portail-hero { text-align: center; padding: 26px 0 8px; }
/* Enfant DIRECT seulement : sans le `>`, cette taille s'appliquait aussi aux icônes
   des boutons placés dans l'en-tête, qui s'affichaient alors en 84 pixels. */
.ac-portail-hero > img { width: 84px; height: 84px; }
.ac-portail-hero h1 { font-family: var(--font-display); font-size: clamp(1.7rem, 5vw, 2.4rem); margin: 12px 0 6px; }
/* UNE MESURE DE LECTURE, TENUE À UN SEUL ENDROIT.
   L'accroche du portail était bridée à quarante-quatre signes par ligne : deux cent
   cinquante-cinq signes s'y empilaient sur SIX lignes, une colonne étroite et dense qu'on
   lit comme un bloc au lieu de la lire comme une phrase. Quarante-quatre est le plancher de
   ce qui se lit confortablement ; soixante-douze en est le milieu, et c'est là qu'un
   paragraphe d'explication respire. La valeur vit dans un seul jeton : les textes de ce
   genre, partout sur la plateforme, s'y accrochent et ne peuvent plus diverger. */
:root { --mesure-lecture: 72ch; }
.ac-portail-hero p {
  color: var(--muted); max-width: var(--mesure-lecture); margin: 0 auto; line-height: 1.65;
}
.ac-portail-actions { display: flex; flex-wrap: wrap; gap: 12px; justify-content: center; margin: 20px 0 6px; }

.ac-espaces { display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); }
.ac-espace { display: flex; align-items: center; gap: 13px; text-decoration: none; color: inherit; }
.ac-espace-logo {
  width: 52px; height: 52px; flex: 0 0 auto; border-radius: 14px; object-fit: cover;
  border: 1px solid var(--border); background: var(--panel2);
  /* Quand l'établissement n'a pas déposé de logo, la vignette accueille l'icône
     d'établissement : il faut donc qu'elle sache aussi centrer un enfant. */
  display: grid; place-items: center; overflow: hidden;
}
.ac-espace-logo .ac-ico { width: 28px; height: 28px; }
.ac-espace-nom { font-family: var(--font-display); font-weight: 700; }
.ac-espace-lieu { display: block; font-size: .82rem; color: var(--muted); }

/* ── Connexion ───────────────────────────────────────────────────────────── */
.ac-connexion-carte { width: min(100%, 430px); margin: 6vh auto 0; text-align: center; }
.ac-connexion-logo { width: 74px; height: 74px; border-radius: 20px; object-fit: cover; border: 1px solid var(--border); }
.ac-connexion-titre { font-family: var(--font-display); margin: 12px 0 2px; font-size: 1.4rem; }
.ac-connexion-carte .field { text-align: left; }
.ac-bloc { width: 100%; justify-content: center; }
.ac-sous-titre { color: var(--muted); margin: 0 0 18px; }
/* La même mesure de lecture qu'au portail, et pour la raison inverse : ici les phrases
   n'étaient pas trop serrées mais trop LARGES. Mesuré dans un espace, l'explication de
   l'espacement des révisions tenait sur une seule ligne de cent vingt-sept signes — au-delà
   de quatre-vingts, l'œil perd le début de la ligne suivante et relit deux fois. La borne
   ne rétrécit rien là où la carte est déjà étroite ; elle n'agit que là où il y a trop de
   place, ce qui est exactement le défaut. */
.ac-note { font-size: .8rem; color: var(--muted); margin: 14px 0 0; max-width: var(--mesure-lecture); }

/* ── Messages ────────────────────────────────────────────────────────────── */
.ac-erreur, .ac-succes { padding: 10px 13px; border-radius: 12px; margin-bottom: 12px; font-size: .9rem; text-align: left; }
.ac-erreur { background: color-mix(in srgb, var(--red) 12%, var(--panel));
  border: 1px solid color-mix(in srgb, var(--red) 40%, var(--border)); color: var(--red-txt); }
.ac-succes { background: color-mix(in srgb, var(--green) 12%, var(--panel));
  border: 1px solid color-mix(in srgb, var(--green) 40%, var(--border)); color: var(--green-txt); }
.ac-avis {
  background: color-mix(in srgb, var(--gold) 14%, var(--panel));
  border: 1px solid color-mix(in srgb, var(--gold) 42%, var(--border));
  color: var(--gold-txt); border-radius: 12px; padding: 9px 13px; font-size: .86rem; font-weight: 600;
}

/* ── Titres de vue et pastilles ──────────────────────────────────────────── */
.ac-titre { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.ac-titre h2 { font-family: var(--font-display); margin: 0; font-size: 1.4rem; }
.ac-titre .ac-compte { color: var(--muted); font-size: .9rem; font-weight: 600; }
.ac-titre-modale { font-family: var(--font-display); margin: 0 0 14px; font-size: 1.2rem; }
/* L'ÉTIQUETTE reprend le badge de la maison mère.
   Elle avait été redessinée ici — même idée, autres valeurs — et les deux univers ne se
   ressemblaient plus de près. On garde les mesures de la mère (`.badge` : .66rem, 3px 8px,
   999px) et l'on n'ajoute que ce qu'Academy a en propre : un fond, parce que ses étiquettes
   se posent sur des cartes et non sur un fond uni, et les variantes d'état. */
.ac-etiq {
  display: inline-block; padding: 3px 9px; border-radius: 999px;
  font-size: .68rem; font-weight: 700; white-space: nowrap;
  border: 1px solid var(--border); background: var(--panel2); color: var(--muted);
}
.ac-etiq--ok { color: var(--green-txt); border-color: color-mix(in srgb, var(--green) 45%, var(--border)); }
.ac-etiq--attente { color: var(--gold-txt); border-color: color-mix(in srgb, var(--gold) 45%, var(--border)); }
.ac-etiq--brouillon { color: var(--violet-txt); border-color: color-mix(in srgb, var(--violet) 45%, var(--border)); }
.ac-etiq--retard { color: var(--red-txt); border-color: color-mix(in srgb, var(--red) 45%, var(--border)); }

/* ── Cours, chapitres, leçons ────────────────────────────────────────────── */
.ac-grille { display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.ac-cours-titre { font-family: var(--font-display); font-size: 1.08rem; margin: 0 0 6px; }
.ac-desc { color: var(--muted); font-size: .9rem; line-height: 1.55; margin: 0 0 10px; max-width: var(--mesure-lecture); }

.ac-chapitre { margin-bottom: 18px; }
.ac-chapitre-titre { display: flex; align-items: center; gap: 10px; font-family: var(--font-display);
  font-weight: 700; margin: 0 0 10px; font-size: 1.04rem; }
/* Marqueur de chapitre : un filet vertical dégradé, PAS un losange. Aucun petit carré
   décoratif ne subsiste sur la plateforme (Brice 2026-08-11), et le filet reprend le
   langage de la maison mère (cf. .zone::before, .notif--unread::before). */
.ac-chapitre-titre::before { content: ""; width: 4px; height: 1.15em; border-radius: 4px;
  background: linear-gradient(180deg, var(--ton), color-mix(in srgb, var(--ton) 40%, var(--green)));
  flex: 0 0 auto;
  box-shadow: 0 0 10px -2px color-mix(in srgb, var(--ton) 70%, transparent); }

.ac-ligne {
  display: flex; align-items: center; gap: 12px; padding: 12px 14px;
  border: 1px solid var(--border); border-radius: 14px; background: var(--panel);
  margin-bottom: 8px; cursor: pointer; text-decoration: none; color: inherit;
  transition: transform .15s, border-color .15s, box-shadow .15s;
}
.ac-ligne:hover { transform: translateX(3px); border-color: var(--ton);
  box-shadow: 0 6px 18px color-mix(in srgb, var(--ton) 20%, transparent); }
.ac-ligne-ico { width: 30px; height: 30px; flex: 0 0 auto; border-radius: 9px; background: var(--panel2);
  display: grid; place-items: center; font-weight: 800; font-size: .82rem; color: var(--muted); }
.ac-ligne-ico img { width: 20px; height: 20px; object-fit: contain; }
.ac-ligne.is-faite .ac-ligne-ico { background: color-mix(in srgb, var(--green) 20%, var(--panel2)); color: var(--green-txt); }
.ac-ligne-titre { flex: 1; font-weight: 600; min-width: 0; }
.ac-ligne-meta { font-size: .78rem; color: var(--muted); }

/* La piste doit se VOIR même vide : à deux cent soixante kilo-octets sur cinq gigas, le
   remplissage est nul et la barre se lisait comme un filet égaré sous le texte. */
.ac-barre {
  height: 7px; border-radius: 999px; overflow: hidden; margin-top: 10px;
  background: color-mix(in srgb, var(--ton) 16%, var(--panel2));
  border: 1px solid var(--border);
}
.ac-barre > i { display: block; height: 100%; background: linear-gradient(90deg, var(--ton), var(--green)); transition: width .5s ease; }

/* ── Contenu d'une leçon ─────────────────────────────────────────────────── */
.ac-corps { line-height: 1.75; font-size: 1.02rem; }
.ac-corps p { margin: 0 0 1em; }
.ac-media { margin: 14px 0; }
.ac-media audio { width: 100%; }
.ac-media video { width: 100%; border-radius: 12px; background: #000; }
.ac-media iframe { width: 100%; height: 70vh; border: 1px solid var(--border); border-radius: 12px; background: var(--panel2); }
.ac-media-nom { display: flex; align-items: center; gap: 7px; font-size: .84rem; color: var(--muted);
  margin-bottom: 6px; font-weight: 600; }
.ac-media-nom img { width: 18px; height: 18px; object-fit: contain; }

/* ── Administration ──────────────────────────────────────────────────────── */
.ac-table-enveloppe { overflow-x: auto; }
.ac-table { width: 100%; border-collapse: collapse; font-size: .9rem; }
.ac-table th, .ac-table td { text-align: left; padding: 9px 10px; border-bottom: 1px solid var(--hairline); }
.ac-table th { font-size: .74rem; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.ac-table tbody tr:hover { background: var(--panel2); }

/* Six tuiles. En remplissage automatique, l'écran large en posait cinq sur la première
   rangée et laissait la sixième seule à côté d'un trou de quatre places. Trois par rangée
   les répartit exactement, deux sur un écran étroit, une sur un téléphone. */
.ac-stats { display: grid; gap: 12px; grid-template-columns: repeat(2, 1fr); }
@media (min-width: 760px) { .ac-stats { grid-template-columns: repeat(3, 1fr); } }
/* Une seule colonne SEULEMENT sur les écrans vraiment étroits : à 390 pixels, six tuiles
   empilées faisaient une colonne interminable là où deux par rangée tenaient très bien. */
@media (max-width: 340px) { .ac-stats { grid-template-columns: 1fr; } }
.ac-stat { background: var(--panel); border: 1px solid var(--border); border-radius: 14px; padding: 14px; }
/* Les six tuiles du tableau de bord portaient toutes la même encre : six nombres alignés,
   impossibles à distinguer d'un coup d'œil. Chacune prend maintenant le ton de ce qu'elle
   compte — les gens, la matière, le travail à faire — et l'on repère celle qu'on cherche
   avant de l'avoir lue. */
.ac-stat b { display: block; font-family: var(--font-display); font-size: 1.6rem; color: var(--ton-txt); }
/* Le ton se lisait AU RANG de la tuile : les trois premières en cyan, les deux suivantes en
   vert, la dernière en ambre. Deux torts. Trois nombres de suite portaient la même encre, et
   l'œil ne trouvait plus celui qu'il cherchait. Surtout, « cours publiés » et « leçons » —
   la matière même — s'affichaient dans le vert de la révision : la couleur renseignait de
   travers, ce qui est plus nuisible que de ne rien dire. Chaque tuile déclare maintenant
   sa famille, et une tuile ajoutée demain ne décale plus les autres. */
/* Le ton se déclare par l'attribut `data-ton`, dont la table vit avec les tons eux-mêmes. */
.ac-stat { border-color: color-mix(in srgb, var(--ton) 30%, var(--border)); }
.ac-stat span { font-size: .8rem; color: var(--muted); }

/* ── Divers ──────────────────────────────────────────────────────────────── */
.ac-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 14px; }
/* L'ÉTAT VIDE emploie les classes de la maison mère — `empty-state` et `empty-illus` — et
   n'en redéfinit AUCUNE mesure. Academy en avait recopié l'idée avec d'autres valeurs, et
   figeait l'illustration à 108 pixels : la même image paraissait deux fois plus petite d'un
   site à l'autre. `ac-vide` ne sert plus qu'à porter ce qui est propre à la filiale. */
.ac-vide { color: var(--muted); }
/* UN ÉCHEC N'EST PAS UNE ABSENCE. « Aucune annonce pour le moment » et « le serveur n'a pas
   répondu » s'affichaient dans le même cadre, avec la même illustration paisible : on lisait
   une panne comme une page normalement vide, et l'on attendait sans savoir qu'il fallait
   réessayer. La carte d'échec porte le ton de ce qui va mal, et le dit en couleur avant
   même qu'on ait lu la phrase. */
.ac-souci {
  border-left: 3px solid var(--ton-corbeille);
  background: color-mix(in srgb, var(--ton-corbeille) 5%, var(--panel));
}
.ac-souci p { color: var(--ton-corbeille-txt); font-weight: 600; }

/* AU-DESSUS DE TOUT, y compris de la barre basse. La fenêtre modale vivait au plan 80 quand
   la barre de navigation de la maison mère occupe le plan 500 et la bulle de notifications
   le 550 : la barre traversait donc le voile, restait visible en travers du contenu, et —
   mesuré, pas supposé — recevait encore les clics. Sur la fenêtre qui remet les identifiants
   en clair, celle qu'on a rendue insensible à Échap et au clic à côté PRÉCISÉMENT pour que
   les mots de passe ne se perdent pas, une pression distraite sur « Cours » les emportait.
   Le plan 10000 est celui des présentations de la maison mère : la filiale s'y range. */
.ac-modale { position: fixed; inset: 0; z-index: 10000; display: grid; place-items: center;
  background: rgba(3, 8, 14, .62); backdrop-filter: blur(3px); padding: 18px; }
/* Et le message de la plateforme repasse au-dessus de la fenêtre : au plan 50 de la charte,
   une erreur annoncée pendant qu'une fenêtre est ouverte se serait affichée derrière elle,
   c'est-à-dire nulle part. */
.toast { z-index: 10010; }
.ac-modale-carte { width: min(96%, 560px); max-height: 88vh; overflow-y: auto; }

/* ── Réordonnancement : flèches discrètes, actives au survol de la rangée ── */
.ac-rangee { display: flex; align-items: center; gap: 8px; }
.ac-rangee .ac-ligne { flex: 1; min-width: 0; }
/* Les flèches forment un petit bloc attaché à la rangée plutôt que deux boutons
   flottants : sans ce fond, elles paraissaient posées sur le motif de la page. */
.ac-fleches {
  display: inline-flex; flex-direction: column; gap: 2px; flex: 0 0 auto;
  /* Même surface que la rangée qu'elles accompagnent : avec `--panel2` et un filet, le
     bloc se fondait dans le motif de la page et les deux flèches paraissaient posées dans
     le vide, à côté de la carte au lieu d'être attachées à elle. */
  padding: 3px; border-radius: 12px; background: var(--panel);
  border: 1px solid var(--border);
}
.ac-chapitre-titre .ac-fleches { flex-direction: row; margin-left: auto; padding: 2px; }
/* Une flèche est une COMMANDE, pas une décoration : elle portait pourtant l'encre grise des
   textes secondaires, et son glyphe tenait dans onze pixels. Sur un fond sombre, l'apprenant
   qui doit ranger trois fragments cherchait où appuyer. Elle prend l'encre de son écran —
   violette dans un exercice, ambrée dans un devoir — et un glyphe qu'on distingue. */
.ac-fleche {
  border: 1px solid var(--border); background: var(--panel); color: var(--ton-txt);
  border-radius: 7px; width: 30px; height: 26px; font-size: .82rem; line-height: 1;
  cursor: pointer; padding: 0; transition: color .15s, border-color .15s, opacity .15s;
}
/* Au DOIGT, 30 par 26 pixels ne suffit pas : c'est un apprenant qui remet des fragments
   dans l'ordre sur un téléphone, pas un enseignant à la souris. Les commandes grandissent
   là où l'on touche, et seulement là. */
@media (pointer: coarse) {
  /* Le glyphe suit la boîte : cette règle le figeait à .8rem, valeur qui était plus grande
     que la base tant que la base valait .68 — et qui, la base ayant grossi, RÉTRÉCISSAIT
     l'arrière-plan tactile. Une exception qui inverse ce qu'elle corrigeait ne se voit
     jamais à l'écran d'un ordinateur. */
  .ac-fleche { width: 40px; height: 34px; font-size: .92rem; }
  .ac-fleches { gap: 4px; padding: 4px; }
}
/* Une flèche qui ne mène nulle part se voit : la première rangée ne monte pas, la dernière
   ne descend pas. Elle restait active et cliquable, sans effet. */
.ac-fleche:disabled { opacity: .28 !important; cursor: default; }
/* L'atténuation ne vaut QUE pour les flèches de réordonnancement, qui doivent
   s'effacer tant qu'on ne survole pas la ligne. Posée sur `.ac-fleche` tout court, elle
   éteignait aussi les commandes de la visionneuse de documents et de la remise en ordre,
   qui sont des commandes permanentes — elles restaient à 55 % pour toujours, faute d'un
   parent à survoler. Vu sur une capture, invisible à la mesure. */
.ac-rangee .ac-fleche, .ac-chapitre-titre .ac-fleche, .ac-bloc-outils .ac-fleche { opacity: .55; }
.ac-rangee:hover .ac-fleche, .ac-chapitre-titre:hover .ac-fleche,
.ac-bloc:hover .ac-bloc-outils .ac-fleche, .ac-fleche:focus-visible { opacity: 1; }
.ac-fleche:hover { color: var(--ton-txt); border-color: var(--ton); }

/* ── Vitesse de lecture ──────────────────────────────────────────────────── */
/* Trois vitesses seulement, et 1× par défaut : sur une langue à tons, ralentir sert à
   entendre un ton, pas à jouer avec un curseur. */
.ac-vitesses { display: flex; gap: 6px; margin-top: 8px; }
.ac-vitesse {
  border: 1px solid var(--border); background: var(--panel); color: var(--muted);
  border-radius: 999px; padding: 4px 11px; font-size: .78rem; font-weight: 700;
  font-family: inherit; cursor: pointer; transition: color .15s, border-color .15s, background .15s;
}
.ac-vitesse:hover { color: var(--text); border-color: var(--ton); }
/* La vitesse choisie est PLEINE, pas teintée.
   Le contour teinté à douze pour cent posait l'encre cyan sur une surface elle-même déjà
   teintée — le cadre d'un exercice, le fond d'un lecteur — et le contraste tombait sur le
   seuil exact de 4,50, mesuré. Une pastille pleine ne dépend plus de ce qu'il y a dessous :
   5,36 en clair, 10,48 en sombre, quelle que soit la surface d'accueil. Et une commande
   choisie doit de toute façon se voir choisie. */
.ac-vitesse.is-on {
  color: var(--sur-accent); border-color: var(--ton); background: var(--ton);
}
.ac-vitesse.is-on:hover { color: var(--sur-accent); }

/* ── Découpe d'un enregistrement ─────────────────────────────────────────── */
.ac-onde { width: 100%; height: 150px; border: 1px solid var(--border); border-radius: 12px;
  background: var(--panel); touch-action: none; cursor: ew-resize; display: block; }

/* ── Suivi de l'apprenant : série de jours et palier ─────────────────────── */
.ac-suivi { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
.ac-serie {
  display: inline-flex; align-items: center; gap: 8px; font-weight: 800;
  font-family: var(--font-display); font-size: 1.05rem; color: var(--gold-txt);
  border: 1px solid color-mix(in srgb, var(--gold) 42%, var(--border));
  background: color-mix(in srgb, var(--gold) 12%, var(--panel));
  border-radius: 999px; padding: 7px 15px;
}
.ac-palier { display: inline-flex; align-items: center; gap: 8px; font-weight: 700;
  border: 1px solid var(--border); background: var(--panel); border-radius: 999px; padding: 7px 15px; }
.ac-palier-suite { color: var(--muted); font-weight: 600; font-size: .84rem; }

/* ── Squelettes de chargement ────────────────────────────────────────────── */
/* Une page qui affiche « Chargement… » donne l'impression d'attendre ; une page qui
   montre déjà sa structure donne l'impression d'arriver. */
.ac-squelette { border-radius: 10px; background: var(--panel2); position: relative; overflow: hidden; }
.ac-squelette::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--ton) 14%, transparent), transparent);
  transform: translateX(-100%); animation: ac-luire 1.4s ease-in-out infinite;
}
@keyframes ac-luire { to { transform: translateX(100%); } }
.ac-sq-titre { height: 22px; width: 46%; margin-bottom: 14px; }
.ac-sq-ligne { height: 14px; margin-bottom: 9px; }
.ac-sq-ligne:nth-child(odd) { width: 92%; }
.ac-sq-ligne:nth-child(even) { width: 74%; }
@media (prefers-reduced-motion: reduce) { .ac-squelette::after { animation: none; } }

/* ── Tableau de suivi de l'enseignant ────────────────────────────────────── */
.ac-jauge { display: inline-block; width: 84px; height: 7px; border-radius: 999px;
  background: var(--panel2); overflow: hidden; vertical-align: middle; margin-right: 8px; }
.ac-jauge > i { display: block; height: 100%; background: linear-gradient(90deg, var(--ton), var(--green)); }
.ac-alerte-decroche { color: var(--red-txt); font-weight: 700; }

/* Icône d'action posée dans un bouton de la charte. */
.ac-ico { width: 18px; height: 18px; object-fit: contain; flex: 0 0 auto; }

@media (max-width: 620px) {
  .ac-connexion-carte { margin-top: 2vh; }
  /* La barre basse donne déjà accès au compte : le doublon d'en-tête passait sur
     deux lignes et gonflait le bandeau. */
  #lien-compte { display: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   LEÇON COMPOSÉE — une suite de blocs, pas un texte avec des pièces jointes

   Chaque type de bloc a sa forme propre, mais tous partagent le rythme vertical
   de la page : c'est ce qui fait qu'une leçon se lit comme un récit et non comme
   un empilement. Rien n'est peint en dur, tout dérive des jetons de la charte.
   ═══════════════════════════════════════════════════════════════════════════ */
.ac-lecon { padding-bottom: 8px; }
.ac-bloc { position: relative; margin: 0 0 20px; scroll-margin-top: 90px; }
.ac-bloc:last-child { margin-bottom: 0; }

/* Commandes de l'enseignant : discrètes au repos, franches au survol du bloc. */
.ac-bloc-outils {
  position: absolute; top: -6px; right: 0; display: flex; gap: 5px; z-index: 3;
  opacity: 0; transform: translateY(-3px);
  transition: opacity .18s ease, transform .18s ease;
}
.ac-bloc:hover .ac-bloc-outils,
.ac-bloc:focus-within .ac-bloc-outils { opacity: 1; transform: none; }
/* La croix qui supprime un bloc était grise comme les trois flèches voisines et ne rougissait
   qu'une fois survolée — c'est-à-dire au moment où l'on s'apprête à cliquer, trop tard pour
   qu'elle serve d'avertissement. Elle porte son ton en permanence, comme les autres retraits
   de la plateforme. */
.ac-fleche--danger {
  color: var(--ton-corbeille-txt);
  border-color: color-mix(in srgb, var(--ton-corbeille) 45%, var(--border));
  --ton: var(--ton-corbeille); --ton-txt: var(--ton-corbeille-txt);
}
.ac-fleche--danger:hover {
  color: var(--ton-corbeille-txt); border-color: var(--ton-corbeille);
  background-color: color-mix(in srgb, var(--ton-corbeille) 14%, var(--panel));
}

.ac-bloc-titre2 {
  font-family: var(--font-display); font-size: 1.28rem; margin: 26px 0 10px;
  padding-left: 13px; border-left: 4px solid; border-image: linear-gradient(180deg, var(--ton), var(--green)) 1;
}
/* Sans distinction, « Leçons 4 éléments » se lit comme une seule phrase, et l'on cherche
   un instant ce que veut dire le nombre. Le compte s'écrit plus petit et en retrait. */
.ac-bloc-titre2 .ac-compte {
  font-family: var(--font-sans, inherit); font-size: .82rem; font-weight: 600;
  color: var(--muted); margin-left: 8px;
}
.ac-bloc-titre3 { font-family: var(--font-display); font-size: 1.08rem; margin: 20px 0 8px; color: var(--label); }
.ac-bloc-liste { margin: 0; padding-left: 22px; line-height: 1.7; }
.ac-bloc-liste li { margin-bottom: 5px; }
.ac-bloc-liste li::marker { color: var(--ton-txt); }

.ac-bloc-citation {
  margin: 0; padding: 14px 18px 14px 22px; border-radius: 0 14px 14px 0;
  border-left: 4px solid color-mix(in srgb, var(--gold) 65%, transparent);
  background: color-mix(in srgb, var(--gold) 8%, transparent);
  font-style: italic; line-height: 1.7;
}

/* Encadrés : quatre tons, une seule mécanique. La couleur porte le sens, jamais
   seule — le titre le dit aussi, pour qui ne distingue pas les teintes. */
.ac-encadre {
  --ton: var(--cyan);
  border-radius: 14px; padding: 13px 16px; line-height: 1.65;
  border: 1px solid color-mix(in srgb, var(--ton) 42%, var(--border));
  background: color-mix(in srgb, var(--ton) 9%, var(--panel));
  box-shadow: inset 3px 0 0 var(--ton);
}
.ac-encadre--info { --ton: var(--cyan); }
.ac-encadre--attention { --ton: var(--red); }
.ac-encadre--astuce { --ton: var(--green); }
.ac-encadre--exemple { --ton: var(--violet); }
.ac-encadre-titre {
  margin: 0 0 6px; font-size: .74rem; font-weight: 800; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ton);
}
.ac-encadre--info .ac-encadre-titre { color: var(--cyan-txt); }
.ac-encadre--attention .ac-encadre-titre { color: var(--red-txt); }
.ac-encadre--astuce .ac-encadre-titre { color: var(--green-txt); }
.ac-encadre--exemple .ac-encadre-titre { color: var(--violet-txt); }
.ac-encadre p:last-child { margin-bottom: 0; }

.ac-figure { margin: 0; }
.ac-figure img { max-width: 100%; border-radius: 14px; border: 1px solid var(--border); display: block; }
.ac-figure--pleine img { width: 100%; }
.ac-figure figcaption { margin-top: 7px; font-size: .84rem; color: var(--muted); text-align: center; }
.ac-separateur { border: none; height: 1px; margin: 26px auto; width: 62%;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--ton) 45%, transparent), transparent); }
.ac-bloc-vide { font-style: italic; }

/* ── Vocabulaire ─────────────────────────────────────────────────────────── */
.ac-vocab-intro { margin: 0 0 10px; color: var(--muted); }
.ac-vocab-table { width: 100%; border-collapse: collapse; }
.ac-vocab-table th, .ac-vocab-table td { text-align: left; padding: 9px 12px; border-bottom: 1px solid var(--border); }
.ac-vocab-table th { width: 40%; font-family: var(--font-display); color: var(--ton-txt); font-weight: 700; }
.ac-vocab-table tr:last-child th, .ac-vocab-table tr:last-child td { border-bottom: none; }
.ac-vocab-note { margin: 9px 0 0; font-size: .8rem; color: var(--muted); }

/* ── Question ────────────────────────────────────────────────────────────── */
/* Le cadre du quiz vient de `.ac-exo` : il était recopié ici, au violet figé. */
.ac-quiz-question { margin: 0 0 12px; font-weight: 700; font-family: var(--font-display); }
.ac-quiz-choix { display: flex; flex-direction: column; gap: 8px; margin-bottom: 13px; }
.ac-quiz-option {
  display: flex; align-items: flex-start; gap: 10px; padding: 9px 12px; border-radius: 11px;
  border: 1px solid var(--border); background: var(--panel); cursor: pointer;
  transition: border-color .15s ease, background .15s ease, transform .12s ease;
}
.ac-quiz-option:hover { border-color: var(--ton); transform: translateX(2px); }
.ac-quiz-option input { margin-top: 2px; flex: 0 0 auto; }
.ac-quiz-option.est-solution { border-color: var(--green); background: color-mix(in srgb, var(--green) 12%, var(--panel)); }
.ac-quiz-saisie { width: 100%; margin-bottom: 12px; }
.ac-quiz-verdict { margin: 11px 0 0; font-weight: 600; line-height: 1.6; }
.ac-quiz-verdict.est-juste { color: var(--green-txt); }
.ac-quiz-verdict.est-faux { color: var(--gold-txt); }

/* ── Visionneuse de documents ────────────────────────────────────────────── */
.ac-pdf { border: 1px solid var(--border); border-radius: 16px; overflow: hidden; background: var(--panel); }
.ac-pdf-barre {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 9px 12px; background: var(--panel2); border-bottom: 1px solid var(--border);
}
.ac-pdf-nom { display: flex; align-items: center; gap: 8px; font-weight: 700; font-size: .92rem; min-width: 0; }
.ac-pdf-pages, .ac-pdf-zoom { display: inline-flex; align-items: center; gap: 6px; font-size: .84rem; color: var(--muted); }
/* Commandes de consultation : ce sont les boutons qu'on utilise le plus dans un document
   de vingt-huit pages. Ils méritent une vraie surface de clic, pas la taille d'une flèche
   de réordonnancement qu'on touche une fois par mois. */
.ac-pdf-barre .ac-fleche {
  width: 32px; height: 28px; font-size: 1rem; font-weight: 700; color: var(--text);
  background: var(--panel);
}
.ac-pdf-barre .ac-fleche:hover { color: var(--ton-txt); border-color: var(--ton);
  box-shadow: 0 0 12px -6px var(--ton); }
.ac-pdf-pages [data-pdf-compteur] { min-width: 5.5em; text-align: center; font-variant-numeric: tabular-nums; }
.ac-pdf-zoom [data-pdf-niveau] { min-width: 4.2em; text-align: center; font-variant-numeric: tabular-nums; }
.ac-pdf-zoom { margin-left: auto; }
.ac-pdf-vue { padding: 12px; display: flex; justify-content: center; background: var(--bg); max-height: 78vh; overflow: auto; }
.ac-pdf-toile { border-radius: 8px; box-shadow: 0 8px 26px -16px rgba(0,0,0,.5); background: #fff; }

/* ── Palette de composition (enseignant) ─────────────────────────────────── */
.ac-palette-titre { margin: 0 0 11px; font-family: var(--font-display); font-weight: 700; }
.ac-palette-grille { display: grid; gap: 9px; grid-template-columns: repeat(auto-fill, minmax(184px, 1fr)); }
/* LA PALETTE ENSEIGNE LE CODE DE COULEURS. Six de ses seize tuiles n'avaient aucune image
   et les autres s'en partageaient quatre : la grille alternait des tuiles à icône et des
   tuiles sans, si bien que les titres eux-mêmes ne s'alignaient plus, et quatre exercices
   différents montraient le même livre. Chaque sorte a désormais son image ET le ton de sa
   famille — cyan pour ce qui compose la leçon, vert pour ce qui nourrit la révision, violet
   pour ce qui fait travailler. L'enseignant apprend la couleur ici, et la retrouve ensuite
   dans la leçon sans qu'on ait eu à la lui expliquer. */
.ac-palette-btn {
  text-align: left; border: 1px solid color-mix(in srgb, var(--ton) 26%, var(--border));
  background: var(--panel2);
  border-radius: 12px; padding: 10px 12px; cursor: pointer; font: inherit; color: inherit;
  display: flex; flex-direction: column; gap: 3px;
  transition: border-color .15s ease, transform .12s ease, box-shadow .15s ease;
}
.ac-palette-btn .ac-palette-nom { color: var(--ton-txt); }
.ac-palette-btn:hover {
  border-color: var(--ton); transform: translateY(-2px);
  box-shadow: 0 8px 20px -12px color-mix(in srgb, var(--ton) 70%, transparent);
}
.ac-palette-nom { font-weight: 700; font-size: .92rem; }
.ac-palette-aide { font-size: .78rem; color: var(--muted); line-height: 1.4; }

/* ── Notes personnelles ──────────────────────────────────────────────────── */
.ac-note-perso summary { cursor: pointer; font-family: var(--font-display); font-weight: 700; }
.ac-note-perso textarea { width: 100%; margin-top: 8px; }

/* ── Cartes de révision ──────────────────────────────────────────────────── */
.ac-carte-revision {
  min-height: 190px; display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 14px; text-align: center; padding: 26px;
}
.ac-carte-terme { font-family: var(--font-display); font-size: 1.8rem; font-weight: 700; }
.ac-carte-sens { font-size: 1.15rem; color: var(--ton-txt); font-weight: 600; }
.ac-carte-palier { font-size: .78rem; color: var(--muted); letter-spacing: .06em; text-transform: uppercase; }

/* La pile.
   Une carte seule au milieu d'un écran vide ne dit rien de ce qui reste. Deux épaisseurs
   décalées derrière elle le disent d'un coup d'œil, et la carte du dessus paraît se
   soulever quand on la retourne. Elles sont décoratives : le compte exact reste écrit. */
/* Une carte-mémoire large de neuf cents pixels pour un mot de quatre lettres n'est plus une
   carte, c'est une bannière. On lui rend sa forme, quelle que soit la largeur de l'écran. */
.ac-pile { position: relative; width: min(100%, 560px); margin: 0 auto; }
.ac-pile::before, .ac-pile::after {
  content: ""; position: absolute; inset: 0; border-radius: var(--r, 16px);
  border: 1px solid var(--border); background: var(--panel2); z-index: 0;
  opacity: 0; transition: opacity .2s ease, transform .2s ease;
}
/* On ne réduit QUE la largeur : une mise à l'échelle uniforme rognait aussi la hauteur et
   annulait presque le décalage, si bien que la pile ne dépassait que de trois pixels. */
.ac-pile.a-deux::before, .ac-pile.a-trois::before {
  opacity: 1; transform: translateY(13px) scaleX(.955);
  background: color-mix(in srgb, var(--ton) 14%, var(--panel2));
  border-color: color-mix(in srgb, var(--ton) 40%, var(--border));
}
.ac-pile.a-trois::after {
  opacity: 1; transform: translateY(26px) scaleX(.91);
  background: color-mix(in srgb, var(--ton) 8%, var(--panel2));
  border-color: color-mix(in srgb, var(--ton) 26%, var(--border));
}
/* La carte du dessus porte l'ombre de la charte ; sans fond opaque, on verrait les
   épaisseurs à travers elle. */
.ac-pile .ac-carte-revision { background: var(--panel); }
.ac-pile .ac-carte-revision { position: relative; z-index: 1; }

/* Avancement de la série. */
.ac-revision-avance {
  height: 6px; border-radius: 999px; overflow: hidden; margin: 0 auto 6px;
  width: min(100%, 560px);
  background: color-mix(in srgb, var(--ton) 22%, var(--panel2));
  border: 1px solid var(--border);
}
.ac-revision-avance > span {
  display: block; height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--ton), var(--green));
  transition: width .35s cubic-bezier(.2,.7,.2,1);
}
.ac-revision-etape {
  text-align: center; margin: 0 0 18px; font-size: .8rem; color: var(--muted);
}
.ac-clavier-aide { margin: 34px 0 0; text-align: center; }
.ac-clavier-aide kbd {
  font-family: var(--font-mono, ui-monospace, monospace); font-size: .78rem;
  border: 1px solid var(--border); border-bottom-width: 2px; border-radius: 6px;
  padding: 1px 6px; background: var(--panel2); color: var(--text);
}

/* Les cinq boîtes de Leitner. */
.ac-boites { margin: 24px 0 0; }
.ac-boites-titre {
  font-family: var(--font-display); font-size: .95rem; margin: 0 0 10px;
  color: var(--muted); letter-spacing: .04em; text-transform: uppercase;
}
.ac-boites-rangee {
  display: grid; grid-template-columns: repeat(6, 1fr); gap: 8px; align-items: end;
}
/* SUR UN TÉLÉPHONE, SIX COLONNES NE TIENNENT PAS. À 390 pixels, chaque colonne dispose
   d'une cinquantaine de pixels, et « 16 jours » écrit sans césure en réclame davantage :
   la sixième boîte sortait de l'écran, son libellé passait sous la bulle de notifications,
   et rien ne le signalait — la page ne défile pas horizontalement, parce que le corps de la
   charte porte `overflow-x: clip`. Le débordement était donc COUPÉ, pas visible : aucun
   contrôle de largeur ne pouvait l'attraper, seul l'œil le voyait. Deux rangées de trois,
   et les cinq boîtes plus la colonne des mots jamais vus se lisent en entier. */
@media (max-width: 560px) {
  .ac-boites-rangee { grid-template-columns: repeat(3, 1fr); gap: 10px 8px; }
}
.ac-boite { display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 0; }
/* LE TUBE D'UNE COLONNE DOIT SE VOIR MÊME VIDE. Il était rempli à sept pour cent de ton
   SUR DU TRANSPARENT : le décor de la page traversait le verre, et cinq colonnes sur six
   disparaissaient purement et simplement. On ne lisait plus un histogramme mais une seule
   barre verte posée au hasard sur un fond à motifs. L'aplat s'appuie donc sur le panneau,
   qui arrête le décor, et le contour prend assez de ton pour dessiner la colonne. */
.ac-boite-barre {
  width: 100%; height: 68px; display: flex; align-items: flex-end;
  border-radius: 10px 10px 4px 4px;
  background: color-mix(in srgb, var(--ton) 9%, var(--panel));
  border: 1px solid color-mix(in srgb, var(--ton) 30%, var(--border));
  padding: 3px; box-sizing: border-box;
}
.ac-boite-barre > span {
  width: 100%; height: var(--part, 0%); min-height: 3px; border-radius: 7px 7px 2px 2px;
  background: linear-gradient(180deg, var(--ton), color-mix(in srgb, var(--green) 70%, var(--ton)));
  animation: acBoitePousse .5s cubic-bezier(.2,.7,.2,1);
  transition: height .35s cubic-bezier(.2,.7,.2,1);
}
.ac-boite.est-vide .ac-boite-barre > span { background: var(--border); }
.ac-boite-n { font-family: var(--font-display); font-weight: 700; font-size: .95rem; }
/* Les six libellés doivent tenir sur une ligne chacun : un seul qui se brise sur deux
   lignes décale toute la rangée et les nombres cessent d'être alignés. */
.ac-boite-nom {
  font-size: .7rem; color: var(--text); text-align: center; line-height: 1.25;
  white-space: nowrap;
}
.ac-boite-delai { font-size: .64rem; color: var(--muted); text-align: center; }
@keyframes acBoitePousse { from { height: 0; } }
@media (prefers-reduced-motion: reduce) {
  .ac-boite-barre > span { animation: none; }
}

/* ── Glossaire et annonces ───────────────────────────────────────────────── */
.ac-glo-terme { font-family: var(--font-display); font-weight: 700; color: var(--ton-txt); margin: 0; }
.ac-glo-tiret { color: var(--muted); font-weight: 400; }
.ac-glo-sens { color: var(--text); font-weight: 600; }
.ac-glo-note { font-size: .86rem; color: var(--muted); line-height: 1.55; margin: 4px 0 0; }

/* Un dictionnaire, pas une pile de fiches : les termes d'une même initiale tiennent dans
   une seule carte, séparés par un filet, et l'abécédaire mène droit à la lettre voulue. */
.ac-stockage { margin-top: 14px; }

/* ── Pied de page public ─────────────────────────────────────────────────────
   Il reprend `site-footer` de la maison mère sans le redessiner ; seule la mention de
   propriété, propre à la filiale, se pose ici. */
.ac-pied-mention {
  flex: 1 1 100%; margin: 18px 0 0; padding-top: 14px;
  border-top: 1px solid var(--border);
  color: var(--muted); font-size: .78rem; line-height: 1.6;
}
.ac-pied-mention span { color: var(--cyan-txt); font-weight: 700; }
/* Le nom et sa ligne d'explication sont deux `span` : sans `display:block`, ils se
   collaient sur une même ligne. Et le lien de marque ne se souligne pas. */
/* Le SOL déclaré de cette surface.
   Le pied de page est un îlot sombre dans les deux thèmes, et son fond est une PHOTO : il
   n'a donc aucune couleur de fond qu'une mesure puisse lire, et le contrôle de contraste
   retombait sur le sol de la page — blanc en thème clair — pour conclure à tort que ses
   liens étaient illisibles. La surface déclare elle-même son sol, mesuré sur la capture
   rendue : la bande où se posent les textes vaut en moyenne rgb(10, 25, 29). */
.ac-actions--entete { margin: 0 0 16px; }

/* Échéance d'un devoir, et note obtenue : trois valeurs qui vivaient en style EN LIGNE. */
/* L'échéance ne se coupe pas en deux. Sur un téléphone, la ligne se brisait après le « à »,
   qui restait seul en bout de ligne pendant que « rendre dans 7 jours » passait à la
   suivante : le regard cherche une date et trouve une préposition. Le groupe passe entier
   à la ligne, ou n'y passe pas. */
.ac-echeance { color: var(--ton-txt); font-weight: 700; white-space: nowrap; }
.ac-echeance--tard { color: var(--red-txt); }
.ac-note-obtenue {
  font-size: 1.7rem; font-family: var(--font-display); color: var(--ton-txt); margin: .2em 0;
}

.ac-avance-cours { margin: 0 0 18px; }
.ac-avance-cours .ac-note { margin-top: 7px; }
.ac-titre-devoirs { margin-top: 22px; }

/* Une consigne posée AVANT le champ qu'elle explique, et le compte VIF de ce qu'on y a
   écrit : trous détectés, personnes reconnues dans une liste collée. Le nom reste neutre,
   la règle servant déjà deux fenêtres et devant en servir d'autres. */
.ac-note--avant { margin: 0 0 10px; }
.ac-compte-vif {
  font-size: .8rem; margin: 4px 0 12px; font-weight: 700; color: var(--green-txt);
}
.ac-compte-vif.est-vide { color: var(--gold-txt); font-weight: 600; }

/* Le document en plein écran : le navigateur peint un fond noir par défaut, qui n'a rien à
   voir avec la charte. On reprend la surface de la plateforme, et la barre reste en vue. */
.ac-pdf.est-plein {
  background: var(--bg); display: flex; flex-direction: column; padding: 0;
}
.ac-pdf.est-plein .ac-pdf-barre { flex: 0 0 auto; }
.ac-pdf.est-plein .ac-pdf-vue {
  flex: 1 1 auto; overflow: auto; display: grid; place-items: center;
}

/* ── Vitrine du portail ──────────────────────────────────────────────────────
   Quatre cartes qui disent ce qu'un espace contient. Elles apparaissent l'une après
   l'autre au défilement, ce qui donne à la page un déroulé plutôt qu'un empilement. */
.ac-offre { margin: 34px 0 30px; }
.ac-offre-titre {
  font-family: var(--font-display); font-size: 1.3rem; text-align: center; margin: 0 0 18px;
}
/* Quatre cartes : DEUX par rangée, jamais trois. En remplissage automatique, un écran
   large en posait trois puis laissait la quatrième seule à côté d'un trou — et le texte,
   serré dans un tiers de largeur, se brisait en colonnes trop étroites. */
.ac-offre-grille { display: grid; gap: 14px; grid-template-columns: 1fr; }
@media (min-width: 760px) { .ac-offre-grille { grid-template-columns: repeat(2, 1fr); } }
/* La carte de la vitrine prend le contour de sa famille, comme les tuiles du tableau de
   bord : quatre cadres rigoureusement identiques annonçaient quatre choses différentes. */
.ac-offre-carte { text-align: left; border-color: color-mix(in srgb, var(--ton) 30%, var(--border)); }
.ac-offre-carte .ac-ico { width: 38px; height: 38px; margin-bottom: 10px; }
.ac-offre-carte h3 {
  font-family: var(--font-display); font-size: 1.02rem; margin: 0 0 7px;
  color: var(--ton-txt);
}
.ac-offre-carte p { color: var(--muted); line-height: 1.6; margin: 0; font-size: .92rem; }
.ac-offre-note {
  margin: 18px auto 0; max-width: var(--mesure-lecture); text-align: center; color: var(--muted);
  font-size: .9rem; line-height: 1.65;
}

/* Vérification publique d'une attestation. */
.ac-verif { width: min(100%, 620px); margin: 4vh auto 0; }
.ac-verif-verdict {
  font-family: var(--font-display); font-weight: 700; font-size: 1.05rem; margin: 0 0 10px;
}
.ac-verif-ok .ac-verif-verdict { color: var(--green-txt); }
.ac-verif-non { border-color: color-mix(in srgb, var(--red) 45%, var(--border)); margin-top: 16px; }
.ac-verif-non .ac-verif-verdict { color: var(--red-txt); }

/* Le dépôt de fichier, replié : il reste offert sans concurrencer l'enregistrement. */
.ac-depot-fichier { margin-top: 10px; }
.ac-depot-fichier summary {
  cursor: pointer; color: var(--muted); font-size: .84rem; width: fit-content;
}
.ac-depot-fichier summary:hover { color: var(--ton-txt); }
.ac-depot-fichier input[type="file"] { margin-top: 8px; }

.ac-hl-titre { color: var(--text); text-decoration: none; font-weight: 600; }
.ac-hl-titre:hover { color: var(--ton-txt); }

/* Le mot cherché, dans l'extrait. Un fond teinté plutôt que le jaune du navigateur, qui
   jure avec la charte et devient illisible en thème sombre. */
.ac-res-extrait mark {
  background: color-mix(in srgb, var(--gold) 30%, transparent);
  color: var(--text); border-radius: 4px; padding: 0 2px; font-weight: 700;
}

/* ── Alertes ─────────────────────────────────────────────────────────────────
   Rangées par jour, et l'état « non lue » se voit. */
.ac-notif-jour { margin: 0 0 16px; }
.ac-notif-quand {
  font-size: .74rem; letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted); margin: 0 0 6px; font-family: var(--font-display);
}
.ac-notif.est-non-lue {
  background: color-mix(in srgb, var(--ton) 9%, var(--panel));
  border-color: color-mix(in srgb, var(--ton) 38%, var(--border));
}
.ac-notif.est-non-lue .ac-ligne-titre { font-weight: 700; }
/* La pastille : à gauche, hors du flux, pour ne pas décaler les lignes déjà lues. */
.ac-notif.est-non-lue::before {
  content: ""; position: absolute; left: 6px; top: 50%; width: 6px; height: 6px;
  transform: translateY(-50%); border-radius: 50%; background: var(--ton);
  box-shadow: 0 0 8px var(--ton);
}
.ac-notif { position: relative; }

/* Remise des identifiants à l'ouverture d'un espace : ces deux lignes ne seront plus
   redonnées, elles se lisent donc comme un document, pas comme un message. */
.ac-remise {
  margin: 16px 0; padding: 14px 16px; border-radius: 14px;
  background: color-mix(in srgb, var(--ton) 8%, var(--panel2));
  border: 1px solid color-mix(in srgb, var(--ton) 30%, var(--border));
}
.ac-remise dt {
  font-size: .74rem; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted); margin-top: 10px;
}
.ac-remise dt:first-child { margin-top: 0; }
.ac-remise dd { margin: 3px 0 0; }
.ac-remise code { font-size: 1rem; font-weight: 700; color: var(--ton-txt); word-break: break-all; }

/* LE PIED RESTE EN BAS, et ne laisse rien paraître sous lui.
   La charte de la mère réserve `padding-bottom: 89px` sur le corps pour que la barre basse
   ne recouvre jamais la dernière ligne d'une page. Sur les pages publiques d'Academy — le
   portail, l'ouverture d'un espace, la vérification d'une attestation, la connexion — il n'y
   a PAS de barre basse : cette réserve n'abritait plus rien et devenait une bande de fond
   nue de quatre-vingt-neuf pixels SOUS le pied de page. Sur un écran haut, où la page ne
   défile pas, le pied se retrouvait ainsi suspendu au-dessus du vide, ce qui n'est plus un
   pied de page. On retire la réserve exactement là où la barre n'existe pas, et le corps,
   déjà en colonne avec `min-height: 100vh` et un `.wrap` en `flex: 1 0 auto`, pousse
   naturellement le pied contre le bas de la fenêtre. */
body.a-pied-public { padding-bottom: 0; }
.ac-pied { --sol-local: #0b1a1e; }
.ac-pied .foot-brand { text-decoration: none; }
/* `foot-sub` a disparu du balisage en même temps que la ligne qui expliquait au visiteur
   d'où venait la plateforme : le sélecteur ne visait plus rien. */
.ac-pied .foot-title { display: block; }

/* ── Repères de lecture d'une leçon ──────────────────────────────────────────
   Une leçon ouverte seule ne disait rien de sa place : on avançait sans savoir combien de
   chemin restait. Le rail montre le cours d'un coup d'œil, cran par cran. */
.ac-lecon-reperes { color: var(--muted); font-size: .84rem; margin: 4px 0 10px; }
.ac-lecon-rail { display: flex; gap: 4px; margin: 0 0 16px; }
.ac-lecon-cran {
  flex: 1 1 0; height: 5px; border-radius: 999px; min-width: 6px;
  background: color-mix(in srgb, var(--ton) 14%, var(--panel2));
  border: 1px solid var(--border);
  transition: background .25s ease, transform .25s ease;
}
.ac-lecon-cran.est-passe { background: color-mix(in srgb, var(--green) 55%, var(--ton)); border-color: transparent; }
.ac-lecon-cran.est-ici {
  background: var(--ton); border-color: transparent; transform: scaleY(1.6);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ton) 20%, transparent);
}
.ac-lecon-voisines {
  display: flex; justify-content: space-between; gap: 12px; margin-top: 18px; flex-wrap: wrap;
}
.ac-media-image { max-width: 100%; border-radius: 12px; }

/* Copies : l'entête d'une copie et le dépliant de correction. Ces trois valeurs vivaient en
   style EN LIGNE, donc hors d'atteinte de la feuille et impossibles à harmoniser. */
.ac-copie-entete { margin-bottom: 6px; }
.ac-copie-nom { margin: 0; }
.ac-depliant { cursor: pointer; }

/* Liste des comptes : même parti que le journal. Plutôt qu'un tableau de six colonnes qui
   déborde de l'écran d'un téléphone, les colonnes secondaires se replient sous le nom. */
.ac-cpt-sous { display: none; }
@media (max-width: 640px) {
  /* Six colonnes ne tiennent pas dans trois cent quatre-vingt-dix pixels, quoi qu'on
     replie : le bouton « Nouveau mot de passe » finissait toujours coupé au bord. La ligne
     devient donc un BLOC — nom, puis la ligne d'identité repliée, puis les deux actions
     côte à côte sur toute la largeur. Plus rien ne sort de l'écran. */
  .ac-table--comptes, .ac-table--comptes tbody, .ac-table--comptes tr, .ac-table--comptes td {
    display: block; width: auto;
  }
  .ac-table--comptes thead { display: none; }
  .ac-table--comptes tr { padding: 13px 2px; border-top: 1px solid var(--border); }
  .ac-table--comptes tr:first-child { border-top: 0; }
  .ac-table--comptes td { border: 0; padding: 0; }
  /* Identifiant, rôle et dernière visite sont repris dans la ligne repliée sous le nom. */
  .ac-table--comptes td:nth-child(2), .ac-table--comptes td:nth-child(3),
  .ac-table--comptes td:nth-child(5) { display: none; }
  .ac-table--comptes td:nth-child(1) { font-weight: 700; }
  .ac-table--comptes td:nth-child(4) { margin-top: 7px; }
  .ac-table--comptes .ac-cpt-sous {
    display: block; color: var(--muted); font-size: .74rem; margin-top: 3px; font-weight: 400;
  }
  .ac-table--comptes .ac-cpt-sous code { font-size: .74rem; }
  .ac-table--comptes td:last-child { display: flex; gap: 8px; margin-top: 9px; }
  .ac-table--comptes td:last-child .btn { flex: 1 1 0; justify-content: center; }
}

.ac-glo-groupe { margin: 0 0 14px; }
/* La lettre reste accrochée en haut de l'écran pendant qu'on parcourt sa tranche : on sait
   toujours où l'on est dans le lexique, sans remonter. */
.ac-glo-lettre {
  /* Collant sous l'en-tête, jamais derrière : `--h-entete` est mesurée au chargement et à
     chaque changement de largeur. Et c'est une PASTILLE, pas un bandeau : un fond pleine
     largeur masquait le motif Ndop et se lisait comme un filet de séparation égaré. */
  position: sticky; top: calc(var(--h-entete, 0px) + 6px); z-index: 2;
  font-family: var(--font-display); font-size: .95rem; margin: 0 0 8px;
  color: var(--ton-txt); letter-spacing: .1em;
  width: max-content; padding: 3px 12px; border-radius: 999px;
  background: color-mix(in srgb, var(--ton) 12%, var(--panel));
  border: 1px solid color-mix(in srgb, var(--ton) 32%, var(--border));
}
.ac-glo-liste { padding: 0; }
/* L'action à DROITE du terme, pas en dessous : posée sous chaque entrée, elle doublait la
   hauteur de la ligne et un lexique de trente mots devenait un couloir. */
.ac-glo-entree {
  display: flex; align-items: flex-start; gap: 14px;
  padding: 12px 18px; border-top: 1px solid var(--border);
}
.ac-glo-entree:first-child { border-top: 0; }
.ac-glo-corps { flex: 1 1 auto; min-width: 0; }
.ac-glo-retirer { flex: 0 0 auto; }
.ac-abecedaire { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 18px; }
.ac-abecedaire .chip--btn { text-decoration: none; min-width: 34px; justify-content: center; }
/* UNE ANNONCE PORTE UNE VOIX, et sa carte ne le disait pas : c'était un rectangle
   exactement semblable à tous les autres, dans une page dont seul le titre était teinté.
   Elle prend donc un montant du ton des annonces sur son flanc gauche — la même marque que
   le filet d'un titre de section — et l'enseignant qui l'a écrite se détache du reste de la
   ligne de contexte. Rien d'appuyé : de quoi reconnaître l'objet sans le crier. */
.ac-annonce {
  border-left: 3px solid var(--ton);
  border-top-left-radius: 6px; border-bottom-left-radius: 6px;
}
.ac-annonce-meta { font-size: .78rem; color: var(--muted); margin: 0 0 6px; }
.ac-annonce-meta b, .ac-annonce .ac-cours-titre { color: var(--ton-txt); }

/* ── Raccourcis de l'accueil ─────────────────────────────────────────────── */
/* Trois colonnes au plus. En remplissage automatique, un écran large en posait quatre et
   laissait le cinquième raccourci seul sur sa rangée ; à trois, cinq raccourcis se
   répartissent 3 + 2, et six se répartissent 3 + 3. */
/* LA DERNIÈRE TUILE NE RESTE PAS SEULE SUR SA RANGÉE. Les raccourcis sont quatre pour un
   apprenant, cinq pour une direction : sur trois colonnes, le quatrième se retrouvait seul
   à gauche avec un grand vide à sa droite, juste au-dessus d'une grille de cours qui, elle,
   tombait juste. On ne voyait pas le défaut sur la démonstration, où l'accueil est presque
   nu ; il saute aux yeux dès que la page se remplit. La tuile orpheline s'étale donc sur les
   colonnes qui restent, et la rangée redevient pleine — c'est vrai à trois colonnes comme à
   deux, et le cas se règle sans savoir combien de raccourcis le rôle en cours affiche. */
/* UNE RANGÉE, ET RIEN QUI PENDE AU BOUT.
   Les raccourcis étaient une grille à trois colonnes fixes : le quatrième se retrouvait seul
   à gauche avec un grand vide à sa droite, juste au-dessus d'une grille de cours qui, elle,
   tombait juste. On ne le voyait pas sur la démonstration, dont l'accueil est presque nu ;
   cela saute aux yeux dès que la page se remplit.

   J'ai d'abord voulu faire déborder la dernière tuile par `:last-child:nth-child(3n+1)`.
   Cela ne marchait pas, et la raison mérite d'être écrite : l'accueil d'un apprenant
   contient un cinquième raccourci — « Reprendre » — RENDU MAIS MASQUÉ tant qu'il n'y a rien
   à reprendre. `:nth-child` compte la position dans le document, masqué compris : « Annonces »
   n'était donc jamais le dernier enfant.

   Une rangée souple règle la question sans compter personne. Chaque tuile réclame au moins
   deux cent soixante pixels et prend sa part de ce qui reste : trois par rangée sur un
   écran, deux sur une tablette, et celle qui se retrouve seule s'étale. Un raccourci masqué
   ne participe pas, un raccourci ajouté demain non plus. */
.ac-raccourcis { display: flex; flex-wrap: wrap; gap: 10px; margin: 0 0 18px; }
.ac-raccourcis > * { flex: 1 1 260px; min-width: 0; }
.ac-raccourci {
  display: flex; align-items: center; gap: 12px; text-decoration: none; color: inherit;
  border: 1px solid var(--border); border-radius: 14px; padding: 12px 14px;
  background: var(--panel);
  transition: border-color .16s ease, transform .14s ease, box-shadow .16s ease;
}
.ac-raccourci:hover {
  border-color: var(--ton); transform: translateY(-2px);
  box-shadow: 0 10px 24px -14px color-mix(in srgb, var(--ton) 75%, transparent);
}
.ac-raccourci .ac-ico { width: 26px; height: 26px; }
.ac-raccourci span { display: flex; flex-direction: column; min-width: 0; }
/* Le mot du raccourci prend l'encre de sa destination : c'est lui qu'on lit, pas la
   plaque, et c'est là que la couleur renseigne le plus vite. */
.ac-raccourci b { font-family: var(--font-display); font-size: .98rem; color: var(--ton-txt); }
/* La description tient sur DEUX lignes plutôt que d'être coupée au milieu d'un mot :
   « le lexique de l'établisse… » ne renseigne personne. */
.ac-raccourci i { font-style: normal; font-size: .8rem; color: var(--muted); line-height: 1.35;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
.ac-raccourci { align-items: flex-start; }
.ac-raccourci .ac-ico { margin-top: 2px; }
.ac-suivi { width: 100%; border-collapse: collapse; }
.ac-suivi th, .ac-suivi td { text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--border); }

/* ── Les quatre exercices ajoutés ────────────────────────────────────────── */
.ac-exo {
  /* Le cadre lit le TON, pas le violet : il vaut violet aujourd'hui parce que c'est celui
     de la famille « exercice », et le jour où cette famille changera de couleur, ce cadre
     n'aura pas à s'en apercevoir. */
  border: 1px solid color-mix(in srgb, var(--ton) 38%, var(--border));
  background: color-mix(in srgb, var(--ton) 7%, var(--panel));
  border-radius: 16px; padding: 15px 17px;
  transition: border-color .2s ease, background .2s ease;
}
.ac-exo.est-reussi { border-color: var(--green); background: color-mix(in srgb, var(--green) 8%, var(--panel)); }

.ac-app-lignes { display: flex; flex-direction: column; gap: 9px; margin-bottom: 13px; }
.ac-app-ligne { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
/* Le terme à relier suit le TON de l'exercice, comme tout ce qui vit dans son cadre : un
   exercice violet dont les mots restaient cyan se lisait comme deux choses collées. */
.ac-app-terme {
  font-family: var(--font-display); font-weight: 700; color: var(--ton-txt);
  min-width: 7em; padding: 7px 11px; border-radius: 10px;
  background: color-mix(in srgb, var(--ton) 12%, var(--panel));
  border: 1px solid color-mix(in srgb, var(--ton) 26%, var(--border));
}
.ac-app-choix { flex: 1 1 12em; min-width: 0; }
.ac-app-choix.est-faux, input.ac-trou.est-faux { border-color: var(--red); }

/* Le numéro de rang doit se voir : c'est lui qui dit « premier, deuxième », pas la
   simple position visuelle. */
/* L'EXERCICE DE REMISE EN ORDRE N'AFFICHAIT AUCUN NUMÉRO. La liste était bien une `<ol>` en
   `list-style: decimal`, et la règle `li::marker` teintait consciencieusement une puce qui
   n'existait pas : poser `display: flex` sur un `<li>` lui retire son `display: list-item`,
   donc son marqueur. Dans un exercice dont toute la consigne est « du premier au dernier »,
   le rang de chaque fragment était la seule information manquante. Un compteur le rend, et
   le rend mieux : une pastille du ton de l'exercice, qui se renumérote toute seule à chaque
   échange puisque c'est la position dans le document qui la fixe. */
.ac-ordre-liste {
  list-style: none; counter-reset: ordre; padding-left: 0; margin: 0 0 13px;
  display: flex; flex-direction: column; gap: 8px;
}
.ac-ordre-item {
  display: flex; align-items: center; gap: 12px;
  padding: 9px 12px; border-radius: 11px; background: var(--panel); border: 1px solid var(--border);
  transition: border-color .15s ease, transform .12s ease;
}
.ac-ordre-item::before {
  counter-increment: ordre; content: counter(ordre);
  flex: 0 0 auto; width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center;
  font-family: var(--font-display); font-weight: 800; font-size: .8rem;
  color: var(--ton-txt);
  background: color-mix(in srgb, var(--ton) 14%, var(--panel));
  border: 1px solid color-mix(in srgb, var(--ton) 40%, var(--border));
}
/* Le texte du fragment occupe la place laissée, et pousse les flèches à droite. */
.ac-ordre-item > span:not(.ac-ordre-boutons) { flex: 1 1 auto; min-width: 0; }
.ac-ordre-item:hover { border-color: var(--ton); transform: translateX(2px); }
.ac-ordre-boutons { display: inline-flex; gap: 5px; flex: 0 0 auto; }

.ac-trous-phrase { line-height: 2.4; font-size: 1.05rem; margin: 0 0 13px; }
/* `input.ac-trou` et non `.ac-trou` : la charte de la mère style `input[type="text"]`,
   dont la spécificité (0,1,1) l'emportait sur une simple classe (0,1,0). Les champs
   prenaient toute la largeur et hachaient la phrase en morceaux — vu à l'écran, pas
   mesurable autrement. */
input.ac-trou {
  display: inline-block; width: auto; min-width: 6em; max-width: 12em; margin: 0 4px;
  padding: 4px 9px; border-radius: 9px; border: 1px solid var(--border);
  background: var(--panel); color: var(--text); font: inherit; font-weight: 600;
  border-bottom: 2px solid var(--ton);
}

.ac-pron-cote { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.ac-pron-bloc { min-width: 0; }
.ac-pron-etiq {
  margin: 0 0 6px; font-size: .74rem; font-weight: 800; letter-spacing: .09em;
  text-transform: uppercase; color: var(--muted);
}

/* ── Recherche, corbeille ────────────────────────────────────────────────── */
.ac-recherche-champ { width: 100%; }
.ac-res { display: block; text-decoration: none; color: inherit; }
.ac-res-genre {
  display: inline-block; font-size: .68rem; font-weight: 800; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ton-txt); margin-bottom: 3px;
}
.ac-res-extrait { color: var(--muted); font-size: .86rem; line-height: 1.55; margin: 4px 0 0; }
.ac-corb-ligne { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.ac-corb-liste { padding: 0; }
.ac-corb-liste .ac-corb-ligne { padding: 12px 18px; border-top: 1px solid var(--border); }
.ac-corb-liste .ac-corb-ligne:first-child { border-top: 0; }
.ac-corb-nom { flex: 1 1 12em; min-width: 0; }
.ac-corb-reste { font-size: .8rem; color: var(--gold-txt); font-weight: 700; }
.ac-corb-reste.est-expire { color: var(--red-txt); }
.ac-attestation {
  text-align: center; padding: 30px 26px;
  border: 2px solid color-mix(in srgb, var(--gold) 55%, var(--border));
}
.ac-attestation h3 { font-family: var(--font-display); font-size: 1.5rem; margin: 12px 0 4px; }
/* Ces deux mesures vivaient en attribut `style` sur la balise. Un style en ligne l'emporte
   sur la feuille : tant qu'il y reste, aucune correction d'ensemble ne peut plus l'atteindre,
   et deux lignes voisines finissent par ne plus s'aligner sans qu'on comprenne pourquoi. */
.ac-attestation-ligne { margin-bottom: 10px; }
.ac-attestation-ligne .ac-cours-titre { flex: 1 1 12em; }
.ac-attestation-num { font-family: var(--font-mono); font-size: .9rem; color: var(--muted); letter-spacing: .08em; }

/* ── Téléphone : les raccourcis de l'accueil ─────────────────────────────────
   Ce bloc vient EN FIN DE FICHIER, et ce n'est pas un détail. Écrit plus haut, il se
   trouvait avant la règle de base de `.ac-raccourcis` ; à spécificité égale, c'est
   l'ordre du fichier qui tranche, et la version téléphone était donc perdante. Elle
   n'avait aucun effet, et la capture le montrait sans qu'on sache pourquoi.

   Quatre raccourcis empilés repoussaient les COURS sous la ligne de flottaison : on
   descendait un écran entier avant de voir ce pour quoi on était venu. */
@media (max-width: 620px) {
  .ac-raccourcis { grid-template-columns: 1fr 1fr; gap: 8px; }
  .ac-raccourci { padding: 10px 11px; gap: 9px; }
  .ac-raccourci .ac-ico { width: 22px; height: 22px; margin-top: 1px; }
  .ac-raccourci b { font-size: .86rem; }
  .ac-raccourci i { font-size: .71rem; }
}

/* ── Champs de fichier habillés en français ─────────────────────────────────
   Le champ natif reste présent et focalisable au clavier ; il est seulement rendu
   invisible. On ne l'enlève pas du flux avec `display:none`, qui le retirerait aussi de
   la navigation au clavier et des formulaires. */
.ac-fichier {
  display: flex; align-items: center; gap: 11px; flex-wrap: wrap;
  position: relative; width: 100%;
}
.ac-fichier input[type="file"] {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; cursor: pointer; border: none; padding: 0; margin: 0;
}
.ac-fichier-btn {
  flex: 0 0 auto; padding: 9px 15px; border-radius: 11px; font-weight: 700; font-size: .9rem;
  border: 1px solid color-mix(in srgb, var(--ton) 45%, var(--border));
  background: color-mix(in srgb, var(--ton) 10%, var(--panel)); color: var(--ton-txt);
  transition: border-color .15s ease, background .15s ease, transform .12s ease;
}
.ac-fichier:hover .ac-fichier-btn { border-color: var(--ton); transform: translateY(-1px); }
.ac-fichier:focus-within .ac-fichier-btn { outline: 2px solid var(--ton); outline-offset: 2px; }
.ac-fichier-nom { font-size: .86rem; color: var(--muted); min-width: 0; overflow-wrap: anywhere; }
.ac-fichier-nom.est-choisi { color: var(--text); font-weight: 600; }

/* ── Couleur de l'établissement : pipette + code ─────────────────────────── */
.ac-couleur { display: flex; align-items: center; gap: 11px; }
.ac-couleur input[type="color"] {
  flex: 0 0 auto; width: 52px; height: 42px; padding: 3px; cursor: pointer;
  border: 1px solid var(--border); border-radius: 11px; background: var(--panel);
}
.ac-couleur input[type="text"] { flex: 1 1 auto; min-width: 0; font-family: var(--font-mono); }

/* Un lien qui EST un bouton doit se comporter comme un bouton : la charte de la mère
   souligne les liens, ce qui faisait de « Exporter tout l'espace » un intrus à côté de
   « Journal d'activité », son voisin immédiat. */
/* Un LIEN habillé en bouton.
   `.btn` de la charte ne pose pas de `display` : appliquée à une balise `a`, elle laissait
   un texte souligné en ligne, sans forme de bouton. Trois liens de navigation en
   souffraient (« Leçon suivante », « Inscrire des apprenants »). La règle vaut pour tout
   lien portant `.btn`, présent et à venir — on ne compte pas sur la discipline d'ajouter
   une classe de plus à chaque fois. */
a.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  text-decoration: none;
}
a.btn:hover, .ac-lien-bouton, .ac-lien-bouton:hover { text-decoration: none; }

/* Variante discrète, pour la navigation secondaire : le bouton s'efface au repos et ne
   reprend corps qu'au survol. Elle était NOMMÉE dans le code sans exister nulle part. */
.btn--fantome {
  background-color: color-mix(in srgb, var(--panel2) 62%, transparent);
  background-image: none; box-shadow: none;
  color: var(--muted); border-color: var(--border);
}
.btn--fantome:hover {
  color: var(--text); border-color: var(--ton);
  background-color: color-mix(in srgb, var(--ton) 8%, transparent);
}
/* Une note sous un champ a besoin d'air : sans marge, elle touchait le libellé suivant
   et l'on ne savait plus à quel champ elle se rapportait. */
.ac-note--champ { display: block; margin: 6px 0 4px; line-height: 1.5; }
.field + .field { margin-top: 2px; }

/* ── Fil de progression de lecture ──────────────────────────────────────────
   Posé sous l'en-tête, il avance à mesure qu'on descend DANS la leçon. Il ne dit pas
   « voilà combien il reste de page », il dit « voilà où tu en es de ce que tu lis ».
   Composité (transform seul), donc sans coût au défilement. */
.ac-fil-lecture {
  position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 480;
  pointer-events: none; background: transparent;
}
.ac-fil-lecture[hidden] { display: none; }
.ac-fil-lecture > i {
  display: block; height: 100%; transform-origin: left center; transform: scaleX(0);
  background: linear-gradient(90deg, var(--ton), var(--green) 55%, var(--gold));
  box-shadow: 0 0 12px -2px color-mix(in srgb, var(--ton) 80%, transparent);
  transition: transform .12s linear;
}
/* Arrivé au bout, le fil se dore un instant : la leçon est parcourue. */
.ac-fil-lecture.est-fini > i {
  background: linear-gradient(90deg, var(--gold), var(--green));
  box-shadow: 0 0 16px -2px color-mix(in srgb, var(--gold) 85%, transparent);
}
@media (prefers-reduced-motion: reduce) { .ac-fil-lecture { display: none; } }

/* ── Ordre d'empilement : le contenu au-dessus de la décoration ──────────────
   Affirmé plutôt que supposé. La trame `.bg-motif` vit en z-index -1 ; le contenu se
   place explicitement au-dessus, de sorte qu'aucune page présente ou future ne puisse
   repasser dessous. (Aucun défaut constaté à ce jour : c'est une garantie, pas un
   correctif — le « fantôme » observé sur le portail venait de ma méthode de capture,
   pas du produit.) */
.wrap { position: relative; z-index: 1; }

/* La colonne de réponses d'un appariement s'étirait jusqu'au bord de la carte, très loin
   du terme qu'elle complète : l'œil devait traverser tout l'écran pour relier les deux.
   On la borne à une largeur de lecture. */
.ac-app-choix { flex: 0 1 22em; max-width: 100%; }
.ac-app-terme { min-width: 8em; }

/* ── Barre d'actions d'un cours : trois groupes, pas huit boutons en file ────
   Huit actions alignées sans hiérarchie se valent toutes, et l'œil n'y trouve plus la
   plus courante. On sépare le quotidien (composer), le suivi (la classe) et l'occasionnel
   (dupliquer, emporter, retirer). */
.ac-barre-cours {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 12px 14px;
}
.ac-actions--groupe { display: flex; gap: 8px; flex-wrap: wrap; margin: 0; }
.ac-barre-sep {
  width: 1px; align-self: stretch; min-height: 26px; flex: 0 0 auto;
  background: linear-gradient(180deg, transparent, var(--border) 25%, var(--border) 75%, transparent);
}
/* UNE ACTION DE RETRAIT. Elle ne prenait sa couleur qu'AU SURVOL : au repos, « Supprimer »
   avait exactement la mise de « Modifier », et dans une rangée de boutons gris rien ne
   disait lequel ferme une porte. Or c'est avant de poser la main qu'on a besoin de le
   savoir — au survol, il est déjà trop tard pour choisir. Elle se signale donc en
   permanence, sans crier : contour et encre du ton de la corbeille, aplat à peine teinté,
   qui s'affirme quand la main s'approche. */
.ac-btn-danger {
  background-color: color-mix(in srgb, var(--ton-corbeille) 8%, var(--panel));
  background-image: none;
  border-color: color-mix(in srgb, var(--ton-corbeille) 45%, var(--border));
  color: var(--ton-corbeille-txt);
  /* Le fil de la charte d'interaction, le halo du focus et l'onde du clic lisent tous
     `--ton` : le poser ici suffit à ce que tout le bouton parle la même langue. */
  --ton: var(--ton-corbeille); --ton-txt: var(--ton-corbeille-txt);
}
.ac-btn-danger:hover, .ac-btn-danger:focus-visible {
  color: var(--ton-corbeille-txt); border-color: var(--ton-corbeille);
  background-color: color-mix(in srgb, var(--ton-corbeille) 16%, var(--panel));
  box-shadow: 0 6px 18px -10px color-mix(in srgb, var(--ton-corbeille) 80%, transparent);
}
@media (max-width: 620px) { .ac-barre-sep { display: none; } }

/* Un titre de section placé DANS `.ac-titre` gardait sa marge basse, ce qui décalait le
   compteur voisin vers le bas : il pendait sous la ligne comme un indice. */
.ac-titre > .ac-chapitre-titre { margin: 0; }
.ac-titre { align-items: baseline; }
.ac-titre h2, .ac-titre h3 { line-height: 1.2; }

/* Le nom de l'espace dans l'en-tête est une MARQUE, pas le titre du document : il est le
   même sur toutes les pages. Deux `h1` sur une page brouillent la structure pour un
   lecteur d'écran, qui s'en sert pour savoir où il est. On garde l'apparence exacte de la
   charte — c'est `.brand-txt h1` chez la mère — en la reportant sur le paragraphe. */
.brand-txt .ac-marque-nom {
  font-family: var(--font-mono); font-weight: 600; letter-spacing: -.02em;
  font-size: clamp(1.15rem, 3.6vw, 1.55rem); line-height: 1.03; margin: 0;
  background: linear-gradient(100deg, #eafcff 0%, var(--ton) 45%, var(--green) 100%);
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
  color: var(--ton);
}
:root[data-theme="light"] .brand-txt .ac-marque-nom {
  background: linear-gradient(100deg, var(--ton) 0%, var(--green) 100%);
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
}

/* « Academy » DISTINCT de « LANGIAL ».
   Écrits du même trait et de la même taille, les deux mots se lisaient comme un seul nom, et
   l'on ne savait plus lequel désigne la maison mère et lequel la filiale. Le second est
   maintenant plus petit, d'une autre encre, et n'hérite PAS du dégradé découpé sur le texte
   du premier — d'où le `-webkit-text-fill-color` remis explicitement, sans quoi il resterait
   transparent. */
.ac-marque-filiale {
  display: inline-block; margin-left: .42em;
  font-family: var(--font-display);
  font-size: .68em; font-weight: 700; letter-spacing: .02em;
  vertical-align: .12em;
  background: none; -webkit-background-clip: initial; background-clip: initial;
  -webkit-text-fill-color: var(--gold-txt); color: var(--gold-txt);
}

/* ── La suite d'une leçon terminée ───────────────────────────────────────────
   Posée dans la page, à l'endroit même où l'on vient de cliquer : elle accompagne au
   lieu d'interrompre, et n'exige aucun geste pour disparaître. */
.ac-suite {
  border-color: color-mix(in srgb, var(--green) 45%, var(--border));
  background: color-mix(in srgb, var(--green) 8%, var(--panel));
  display: flex; flex-direction: column; gap: 12px; align-items: flex-start;
}
.ac-suite-mot { margin: 0; font-family: var(--font-display); font-size: 1.02rem; }

/* ── Une correction déjà rendue se LIT, elle ne se déplie pas ────────────────
   Le formulaire vivait dans un dépliant replié dès qu'une copie était corrigée : la note
   s'affichait dans une pastille, mais le commentaire écrit et la remarque parlée
   restaient cachés. Un enseignant qui rouvrait une copie ne voyait pas ce qu'il avait
   écrit. La correction se lit maintenant d'emblée ; le formulaire reste là, replié, pour
   qui veut la reprendre. */
.ac-correction-faite {
  margin: 12px 0; padding: 12px 14px; border-radius: 14px;
  border: 1px solid color-mix(in srgb, var(--green) 40%, var(--border));
  background: color-mix(in srgb, var(--green) 8%, var(--panel));
}
.ac-correction-titre {
  display: flex; align-items: center; gap: 8px; margin: 0 0 8px;
  font-size: .78rem; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  color: var(--green-txt);
}
/* Un dépliant doit se voir dépliable : le style de titre masquait le marqueur natif. */
.ac-depliant { display: flex; align-items: center; gap: 10px; list-style: none; }
.ac-depliant::-webkit-details-marker { display: none; }
.ac-depliant::after {
  content: "▾"; margin-left: auto; font-size: .8rem; color: var(--muted);
  transition: transform .18s ease;
}
details[open] > .ac-depliant::after { transform: rotate(180deg); }

/* ── Journal d'activité ─────────────────────────────────────────────────────── */
.ac-journal-filtres { display: flex; gap: 8px; flex-wrap: wrap; margin: 0 0 12px; }
.ac-journal-filtres .chip--btn.is-active {
  border-color: var(--ton); color: var(--ton-txt);
  background: color-mix(in srgb, var(--ton) 14%, transparent);
}
.ac-journal-detail { color: var(--muted); font-size: .86rem; }
/* La carte qui ne porte qu'un champ de recherche : elle respire moins qu'une carte de
   contenu, sinon un simple champ occuperait la hauteur d'un paragraphe entier. */
.ac-carte-chercher { padding: 14px 16px; margin-bottom: 14px; }
.ac-carte-chercher .field { margin: 0; }
.ac-journal-chercher { margin: 0 0 12px; }
.ac-journal-chercher .champ { width: 100%; }
/* Sur un téléphone, « à l'instant » se brisait en deux lignes à chaque entrée et le journal
   devenait un mur de vingt-huit pavés. La date tient désormais sur une ligne, et le détail
   passe SOUS l'action au lieu d'occuper une quatrième colonne : rien n'est perdu, tout
   tient dans la largeur. */
.ac-journal-quand { white-space: nowrap; font-variant-numeric: tabular-nums; }
.ac-journal-sous { display: none; }
@media (max-width: 640px) {
  .ac-table--journal th:nth-child(4), .ac-table--journal td:nth-child(4) { display: none; }
  .ac-table--journal .ac-journal-sous {
    display: block; color: var(--muted); font-size: .8rem; margin-top: 2px;
  }
}

/* ── Liste d'inscription ────────────────────────────────────────────────────
   Un apprenant déjà inscrit se distinguait par une case cochée et grisée : trop discret
   pour qu'on le voie dans une liste de trente noms. La ligne entière le dit. */
.ac-liste-inscription { max-height: 44vh; overflow: auto; display: flex; flex-direction: column; gap: 4px; }
.ac-inscrit-ligne { padding: 7px 10px; border-radius: 10px; transition: background .15s ease; }
.ac-inscrit-ligne:hover { background: color-mix(in srgb, var(--ton) 8%, transparent); }
.ac-inscrit-ligne.est-inscrit { background: color-mix(in srgb, var(--green) 8%, transparent); }
.ac-inscrit-ligne .ac-etiq { margin-left: 8px; }

/* Un cours composé par quelqu'un d'autre le dit : dans un institut, plusieurs
   enseignants travaillent sur le même espace et chacun peut agir sur les cours des
   autres. Savoir de qui est un cours avant d'y toucher n'est pas de la courtoisie. */
.ac-auteur-autre {
  display: flex; align-items: center; gap: 8px; margin: 0 0 14px;
  padding: 8px 12px; border-radius: 11px;
  border: 1px solid color-mix(in srgb, var(--gold) 38%, var(--border));
  background: color-mix(in srgb, var(--gold) 9%, transparent);
  color: var(--gold-txt);
}
.ac-auteur-autre .ac-ico { width: 18px; height: 18px; }

/* ── Filtres de la liste des comptes ────────────────────────────────────────
   Cinq cents apprenants rendus d'un coup, sans autre moyen de retrouver quelqu'un que de
   faire défiler : c'est la taille que vise INSEL, pas un cas théorique. */
.ac-filtres-comptes { display: flex; gap: 10px; flex-wrap: wrap; margin: 12px 0; }
.ac-filtres-comptes input { flex: 1 1 16em; min-width: 0; }
.ac-filtres-comptes select { flex: 0 0 auto; }

/* ═══════════════════════════════════════════════════════════════════════════
   IDENTITÉ D'ACADEMY — I. LES ICÔNES ONT UNE PLACE
   ═══════════════════════════════════════════════════════════════════════════
   Les douze icônes de la filiale sont des illustrations : contour sombre teinté, lumière
   venant du haut-gauche, six à douze éléments de détail, exportées en 220 pixels de haut.
   Elles étaient posées dans l'interface à DIX-HUIT pixels. À cette taille, un livre relié
   avec ses lacets et son losange Ndop devient une tache brune de quatre pixels : elles
   étaient partout et reconnaissables nulle part, au point qu'on pouvait chercher où elles
   se trouvaient. Rien à réparer dans les fichiers ; tout à réparer dans leur mise en scène.

   Deux règles : elles gagnent en taille partout où elles PORTENT un sens, et là où elles
   ouvrent une action, elles reposent sur une plaque teintée qui les détache du fond, comme
   les vignettes qu'elles sont. Une icône purement décorative au fil d'un texte reste petite,
   sinon elle bouscule la ligne. */

/* Au fil du texte : à peine plus grande, pour rester alignée sur la ligne de base. */
.ac-ico { width: 22px; height: 22px; }

/* La PLAQUE : le cadre dans lequel une icône devient un objet.
   Elle reprend l'accent de l'établissement, garde une épaisseur visible en thème sombre,
   et suit son bouton au survol. */
.ac-plaque {
  display: grid; place-items: center; flex: 0 0 auto;
  width: 46px; height: 46px; border-radius: 14px;
  background: linear-gradient(150deg,
    color-mix(in srgb, var(--ton) 20%, var(--panel2)),
    color-mix(in srgb, var(--green) 12%, var(--panel2)));
  border: 1px solid color-mix(in srgb, var(--ton) 34%, var(--border));
  box-shadow: inset 0 1px 0 var(--card-sheen, rgba(255,255,255,.14));
  transition: transform .18s cubic-bezier(.2,.7,.2,1), box-shadow .18s ease, border-color .18s ease;
}
.ac-plaque .ac-ico { width: 32px; height: 32px; }

/* Raccourcis de l'accueil : ce sont les portes de la plateforme, elles méritent leur plaque. */
.ac-raccourci .ac-plaque { width: 44px; height: 44px; }
.ac-raccourci .ac-plaque .ac-ico { width: 31px; height: 31px; margin: 0; }
.ac-raccourci:hover .ac-plaque {
  transform: scale(1.06) rotate(-3deg);
  border-color: var(--ton);
  box-shadow: 0 6px 16px -8px color-mix(in srgb, var(--ton) 80%, transparent);
}

/* Vitrine du portail : la carte est grande, l'icône aussi. Elle l'était encore trop peu —
   cinquante-huit pixels dans une carte qui en fait plus de quatre cents de large, l'image se
   lisait comme une vignette d'accompagnement plutôt que comme le sujet de la carte. */
.ac-offre-carte .ac-plaque { width: 76px; height: 76px; border-radius: 21px; margin-bottom: 14px; }
/* L'image occupe franchement sa plaque : à cinquante-six pixels dans soixante-seize, celles
   dont le dessin porte déjà une marge — la calebasse de la révision — paraissaient flotter
   au milieu d'un cadre vide pendant que les autres le remplissaient. */
.ac-offre-carte .ac-plaque .ac-ico { width: 62px; height: 62px; }

/* Barre basse : elle était à 27,6 px, hérités de la mère dont les icônes sont plus
   simples. Les nôtres ont besoin d'un peu plus d'air pour se distinguer les unes des
   autres du coin de l'œil. */
.bottom-nav-ico { height: 32px; }
.bottom-nav-home-ico { height: 40px; }

/* Dans un bouton, l'icône monte à vingt-quatre : elle reste subordonnée au mot, mais on
   la reconnaît. */
.btn .ac-ico, .chip .ac-ico { width: 24px; height: 24px; }

/* L'ICÔNE ET LE MOT SUR LA MÊME LIGNE, ET AU MÊME MILIEU.
   `.btn` de la charte est un bouton en flux : une image y est posée sur la LIGNE DE BASE du
   texte, si bien qu'elle paraît toujours un peu enfoncée, d'autant plus qu'elle est grande.
   Rien ne le disait, mais cela se voyait sur chacun des boutons à icône de la plateforme.
   On les met tous en rangée centrée, une fois pour toutes, plutôt que d'ajuster un décalage
   au cas par cas. `inline-flex` et non `flex` : un bouton ne doit pas se mettre à occuper
   toute la largeur de son conteneur au passage. */
.btn, .chip { display: inline-flex; align-items: center; justify-content: center; gap: 9px; }
/* Le bouton d'appel du portail : celui qu'on veut voir de loin. Son icône passe à trente-six
   pixels et son texte grossit d'autant, sans quoi l'image écrase le mot. */
.ac-btn-large { font-size: 1.02rem; padding: 13px 22px; gap: 11px; }
.ac-btn-large .ac-ico--btn { width: 36px; height: 36px; }

/* ═══════════════════════════════════════════════════════════════════════════
   IDENTITÉ D'ACADEMY — II. LA CHARTE D'INTERACTION
   ═══════════════════════════════════════════════════════════════════════════
   Le reproche est juste : rien ne distinguait, au premier coup d'œil, ce qui se clique de
   ce qui se lit. Une carte de cours, une ligne de leçon, une pastille de filtre et un
   paragraphe se ressemblaient tous. Il fallait poser une LANGUE — pas un effet ici et un
   effet là, mais un vocabulaire tenu, appliqué par des sélecteurs structurels, que l'on
   reconnaisse d'un écran à l'autre et d'une application à l'autre.

   Quatre mots, et rien d'autre :

   LE FIL      Un fil d'accent court le long du bord haut de toute surface qui répond. Il
               est invisible au repos et se TISSE de gauche à droite au survol, comme le fil
               d'un métier. C'est la signature d'Academy : là où le fil passe, on peut agir.
   LA LEVÉE    La surface monte de deux pixels et prend une ombre teintée. Elle se
               rapproche, littéralement.
   L'APPUI     Au clic, elle redescend sous le doigt et se creuse. Le geste a un poids.
   LE HALO     Au clavier, un anneau d'accent doublé d'un halo. Le même partout, pour que
               naviguer sans souris ne soit pas naviguer à l'aveugle.

   Tout cela s'éteint proprement sous `prefers-reduced-motion` : la couleur et l'anneau
   restent, le mouvement s'arrête. Une interface qui ne bouge pas doit rester lisible. */

/* La famille des surfaces qui RÉPONDENT. Une seule liste, tenue à un seul endroit :
   ajouter un composant cliquable, c'est ajouter un sélecteur ici, pas réinventer un effet. */
.btn,
.chip--btn,
.ac-carte-cours,
.ac-espace,
.ac-raccourci,
.ac-res,
.ac-ligne,
.ac-inscrit-ligne,
.ac-glo-entree,
.ac-palette-btn,
.bottom-nav-tab,
.ac-vitesse,
.ac-fleche,
.ac-plaque {
  position: relative;
  isolation: isolate;
}

/* ── LE FIL ────────────────────────────────────────────────────────────────
   Deux pixels d'accent, masqués au repos par une échelle horizontale nulle. Au survol, il
   se tisse depuis la gauche. `transform` seulement : aucune reprise de mise en page, donc
   aucun coût mesurable. */
.btn::before,
.chip--btn::before,
.ac-carte-cours::before,
.ac-espace::before,
.ac-raccourci::before,
.ac-res::before,
.ac-ligne::before,
.ac-palette-btn::before {
  content: "";
  position: absolute; left: 8px; right: 8px; top: 0; height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg,
    transparent,
    color-mix(in srgb, var(--ton) 92%, transparent) 22%,
    color-mix(in srgb, var(--green) 92%, transparent) 78%,
    transparent);
  transform: scaleX(0); transform-origin: left center;
  transition: transform .34s cubic-bezier(.2,.8,.2,1);
  pointer-events: none; z-index: 2;
}
.btn:hover::before, .btn:focus-visible::before,
/* LE LECTEUR AUDIO RESTE CELUI DE LANGIAL, ET NE SUIT PAS LE TON.
   J'ai essayé l'inverse, et il faut dire pourquoi c'était une erreur : dans l'exercice de
   prononciation, un cadre violet contenait un bouton de lecture cyan, ce qui m'a paru une
   incohérence. J'ai donc teinté le lecteur — et le résultat était pire. Sa forme d'onde est
   dessinée par le script de la maison mère, dans un canevas, avec une couleur qui n'est pas
   du CSS : elle restait verte. On obtenait un lecteur à moitié violet, à moitié vert, ce
   qu'aucun des deux choix francs ne donnait.

   La règle qui vaut : LE LECTEUR EST UN OBJET DE LANGIAL, pas un objet d'Academy. On le
   reconnaît d'un site à l'autre, comme le bouton clair/sombre ou la barre basse. Le ton
   colore ce qui appartient à la filiale — la carte, ses pastilles, ses boutons — et
   s'arrête à la frontière des composants repris tels quels. C'est aussi ce que Brice
   demande depuis le début : ne pas fabriquer deux univers.

   LA FRONTIÈRE EST DONC CELLE-CI : le ton colore ce qui appartient à la filiale — la carte,
   ses pastilles, SES BOUTONS — et s'arrête au bord des composants repris tels quels. Le
   bouton d'enregistrement en fait partie : sur la page d'un devoir, il est l'action
   principale, seule dans une carte ambre, et il s'affichait en cyan. Sa variante rouge, qui
   dit que l'enregistrement TOURNE, n'est pas touchée : ce rouge-là ne désigne pas une
   famille d'objet mais un état, et il doit se lire pareil partout. */
/* `.btn.btn--rec` et non `.btn--rec` : la charte écrit la règle avec les deux classes,
   et une seule classe ici ne suffisait pas à l'emporter. Le bouton restait cyan et je
   l'ai cru corrigé — c'est la capture qui a tranché, pas la lecture du code. */
.btn.btn--rec { border-color: var(--ton); color: var(--ton-txt);
  background: color-mix(in srgb, var(--ton) 10%, var(--panel));
  box-shadow: inset 0 1px 0 var(--card-sheen), 0 8px 22px -12px var(--ton); }
.btn.btn--rec:hover { background: var(--ton); border-color: var(--ton); color: var(--bg); }

/* LA DERNIÈRE FAMILLE QUI IGNORAIT LE TON. Les cartes, les lignes, les boutons, les
   flèches et les plaques suivent tous la couleur de leur écran ; la pastille, elle,
   s'allumait en cyan partout, parce que la charte de la mère écrit ce cyan en dur dans
   `.chip--btn:hover`. Sur la page des alertes, orange du titre au point de lecture, on
   survolait « Tout marquer comme lu » et il virait au cyan. Même geste, même lueur, même
   levée d'un pixel : seule la teinte suit désormais la page. Là où aucune famille n'est
   déclarée, `--ton` vaut le cyan et rien ne change. */
.chip--btn:hover {
  color: var(--ton-txt); border-color: var(--ton);
  box-shadow: inset 0 1px 0 var(--card-sheen), 0 0 16px -2px color-mix(in srgb, var(--ton) 45%, transparent);
}
.chip--btn:hover .chip-ico {
  filter: drop-shadow(0 0 6px color-mix(in srgb, var(--ton) 70%, transparent));
}
.chips-nav .chip--btn:hover {
  background: color-mix(in srgb, var(--ton) 16%, transparent);
  color: var(--ton-txt); box-shadow: none;
}

.chip--btn:hover::before, .chip--btn:focus-visible::before,
.ac-carte-cours:hover::before, .ac-carte-cours:focus-visible::before,
.ac-espace:hover::before, .ac-espace:focus-visible::before,
.ac-raccourci:hover::before, .ac-raccourci:focus-visible::before,
.ac-res:hover::before, .ac-res:focus-visible::before,
.ac-ligne:hover::before, .ac-ligne:focus-visible::before,
.ac-palette-btn:hover::before, .ac-palette-btn:focus-visible::before { transform: scaleX(1); }

/* ── LA LEVÉE et L'APPUI ───────────────────────────────────────────────────
   La charte de la mère lève déjà `.btn` d'un pixel ; on unifie tout le reste sur le même
   geste, et l'on ajoute l'appui, qui manquait partout. */
.ac-carte-cours, .ac-espace, .ac-res, .ac-ligne, .ac-inscrit-ligne, .ac-glo-entree {
  transition: transform .16s cubic-bezier(.2,.7,.2,1), box-shadow .18s ease,
              border-color .18s ease, background .18s ease;
}
.ac-carte-cours:hover, .ac-espace:hover, .ac-res:hover {
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--ton) 62%, var(--border));
  box-shadow: 0 14px 30px -18px color-mix(in srgb, var(--ton) 85%, transparent),
              inset 0 1px 0 var(--card-sheen, rgba(255,255,255,.12));
}
.ac-ligne:hover, .ac-inscrit-ligne:hover, .ac-glo-entree:hover {
  background: color-mix(in srgb, var(--ton) 9%, transparent);
}
.btn:active, .chip--btn:active, .ac-carte-cours:active, .ac-espace:active,
.ac-raccourci:active, .ac-res:active, .ac-ligne:active, .ac-palette-btn:active {
  transform: translateY(1px) scale(.988);
  box-shadow: inset 0 2px 7px -3px rgba(0,0,0,.45);
}

/* ── LE HALO ───────────────────────────────────────────────────────────────
   Un seul anneau pour toute la plateforme. Il ne remplace pas le contour du système : il
   s'y ajoute, plus visible, dans la couleur de l'établissement. */
.btn:focus-visible, .chip--btn:focus-visible, .ac-carte-cours:focus-visible,
.ac-espace:focus-visible, .ac-raccourci:focus-visible, .ac-res:focus-visible,
.ac-ligne:focus-visible, .ac-palette-btn:focus-visible, .bottom-nav-tab:focus-visible,
.ac-vitesse:focus-visible, .ac-fleche:focus-visible,
input:focus-visible, select:focus-visible, textarea:focus-visible, summary:focus-visible {
  outline: 2px solid var(--ton);
  outline-offset: 2px;
  box-shadow: 0 0 0 6px color-mix(in srgb, var(--ton) 22%, transparent);
}

/* ── L'ONDE ────────────────────────────────────────────────────────────────
   Au clic, un disque d'accent se dilate depuis le point touché. Posé par le script, qui
   connaît la position du doigt ; le style vit ici. */
.ac-onde {
  position: absolute; border-radius: 50%; pointer-events: none; z-index: 3;
  width: var(--d, 60px); height: var(--d, 60px);
  left: var(--x, 50%); top: var(--y, 50%);
  background: radial-gradient(circle,
    color-mix(in srgb, var(--ton) 55%, #fff) 0%, transparent 70%);
  transform: translate(-50%, -50%) scale(0); opacity: 0;
  animation: acOnde 620ms cubic-bezier(.2,.7,.2,1) forwards;
}
/* L'opacité ne suit PAS la même course que la taille. Avec une seule étape, l'assouplissement
   avançait le disque à quatre-vingts pour cent de sa taille en trente pour cent du temps, et
   emportait l'opacité avec lui : mesurée à 0,11 à cent-soixante-dix millisecondes, l'onde
   n'était déjà plus qu'un souffle. Elle tient maintenant sa lumière le temps qu'on la voie,
   puis s'efface. */
@keyframes acOnde {
  0%   { transform: translate(-50%, -50%) scale(0);   opacity: .62; }
  55%  { opacity: .40; }
  100% { transform: translate(-50%, -50%) scale(1);   opacity: 0; }
}

/* Le curseur : une main sur tout ce qui répond, y compris les cartes rendues cliquables
   par un attribut plutôt que par une balise. */
.ac-carte-cours, .ac-espace, .ac-raccourci, .ac-res, .ac-ligne,
[data-action], [role="button"] { cursor: pointer; }
[data-action]:disabled, [role="button"][aria-disabled="true"] { cursor: not-allowed; }

@media (prefers-reduced-motion: reduce) {
  .btn::before, .chip--btn::before, .ac-carte-cours::before, .ac-espace::before,
  .ac-raccourci::before, .ac-res::before, .ac-ligne::before, .ac-palette-btn::before {
    transition: none; transform: scaleX(1); opacity: .5;
  }
  .ac-carte-cours:hover, .ac-espace:hover, .ac-res:hover,
  .btn:active, .chip--btn:active, .ac-carte-cours:active { transform: none; }
  .ac-onde { animation: none; display: none; }
  .ac-raccourci:hover .ac-plaque { transform: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   IDENTITÉ D'ACADEMY — III. LA PAGE PREND VIE
   ═══════════════════════════════════════════════════════════════════════════
   Une page n'est pas un empilement de blocs qui apparaissent tous ensemble : c'est un
   déroulé. Trois gestes, tenus, et rien de plus — au-delà, le mouvement cesse d'être une
   information et devient du bruit.

   LA MONTÉE     Les éléments d'une liste entrent l'un après l'autre, en montant de huit
                 pixels. On lit dans l'ordre où ils arrivent.
   LA RÉVÉLATION Ce qui est plus bas que l'écran attend d'y entrer pour apparaître. Le
                 défilement devient une progression, pas un saut.
   LE TISSAGE    Un fleuron entre deux sections : trois fils d'accent qui se croisent, et
                 un losange au centre. Dessiné en CSS, sans image à charger.

   La maison mère évite délibérément `transform` sur `.card` — il créerait un bloc conteneur
   qui capturerait le `position: fixed` de son clavier ancré. Academy n'a pas ce clavier,
   mais la charte est partagée : la montée porte donc sur les classes PROPRES à la filiale,
   jamais sur `.card` en général. */

/* ── LA MONTÉE ─────────────────────────────────────────────────────────────
   Six crans de retard, puis plus rien : au-delà, une liste de cinquante leçons ferait
   attendre la dernière une seconde et demie pour rien. */
.ac-carte-cours, .ac-raccourci, .ac-offre-carte, .ac-res, .ac-glo-groupe, .ac-notif-jour {
  animation: acMontee .46s cubic-bezier(.2,.7,.2,1) both;
}
.ac-carte-cours:nth-child(2), .ac-raccourci:nth-child(2), .ac-offre-carte:nth-child(2),
.ac-res:nth-child(2), .ac-glo-groupe:nth-child(2), .ac-notif-jour:nth-child(2) { animation-delay: .06s; }
.ac-carte-cours:nth-child(3), .ac-raccourci:nth-child(3), .ac-offre-carte:nth-child(3),
.ac-res:nth-child(3), .ac-glo-groupe:nth-child(3), .ac-notif-jour:nth-child(3) { animation-delay: .12s; }
.ac-carte-cours:nth-child(4), .ac-raccourci:nth-child(4), .ac-offre-carte:nth-child(4),
.ac-res:nth-child(4), .ac-glo-groupe:nth-child(4), .ac-notif-jour:nth-child(4) { animation-delay: .18s; }
.ac-carte-cours:nth-child(5), .ac-raccourci:nth-child(5), .ac-res:nth-child(5) { animation-delay: .24s; }
.ac-carte-cours:nth-child(n+6), .ac-raccourci:nth-child(n+6), .ac-res:nth-child(n+6) { animation-delay: .3s; }
@keyframes acMontee {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

/* ── LA RÉVÉLATION ─────────────────────────────────────────────────────────
   Posée par le script, qui seul sait ce qui est entré dans l'écran. Sans le script — pas
   de JavaScript, ou un observateur indisponible — rien n'est masqué : on ne cache jamais
   du contenu derrière un effet. */
.ac-revele { opacity: 0; transform: translateY(14px); }
.ac-revele.est-vu {
  opacity: 1; transform: none;
  transition: opacity .55s cubic-bezier(.2,.7,.2,1), transform .55s cubic-bezier(.2,.7,.2,1);
}

/* ── LE TISSAGE ────────────────────────────────────────────────────────────
   Le fleuron d'Academy. Trois fils, un losange, aucune image. */
.ac-tissage {
  position: relative; height: 26px; margin: 30px 0 26px;
  display: flex; align-items: center; justify-content: center; gap: 10px;
}
.ac-tissage::before, .ac-tissage::after {
  content: ""; height: 1.5px; flex: 1 1 0; max-width: 240px;
  background: linear-gradient(90deg, transparent,
    color-mix(in srgb, var(--ton) 55%, transparent) 45%,
    color-mix(in srgb, var(--green) 55%, transparent));
}
.ac-tissage::after { background: linear-gradient(270deg, transparent,
    color-mix(in srgb, var(--ton) 55%, transparent) 45%,
    color-mix(in srgb, var(--green) 55%, transparent)); }
.ac-tissage i {
  width: 13px; height: 13px; display: block; transform: rotate(45deg);
  border: 1.5px solid color-mix(in srgb, var(--ton) 88%, transparent);
  border-radius: 2px;
  box-shadow: 0 0 10px -2px color-mix(in srgb, var(--ton) 70%, transparent);
}
.ac-tissage i:nth-child(2) { border-color: color-mix(in srgb, var(--green) 70%, transparent);
  box-shadow: 0 0 10px -2px color-mix(in srgb, var(--green) 70%, transparent); }

/* ── L'ONGLET ACTIF ────────────────────────────────────────────────────────
   Le même fil que la charte d'interaction, posé sous l'onglet où l'on se trouve : la
   signature se retrouve jusque dans la barre basse. */
.bottom-nav-tab.is-active::after {
  content: ""; position: absolute; left: 22%; right: 22%; bottom: 4px; height: 2px;
  border-radius: 2px; background: linear-gradient(90deg, var(--ton), var(--green));
  box-shadow: 0 0 8px -1px var(--ton);
}

@media (prefers-reduced-motion: reduce) {
  .ac-carte-cours, .ac-raccourci, .ac-offre-carte, .ac-res, .ac-glo-groupe, .ac-notif-jour {
    animation: none;
  }
  .ac-revele { opacity: 1; transform: none; }
  .ac-revele.est-vu { transition: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   IDENTITÉ D'ACADEMY — IV. LA MATIÈRE
   ═══════════════════════════════════════════════════════════════════════════
   Il restait des surfaces plates : un titre de page en texte nu, des cadres sans épaisseur.
   Deux ajouts de matière, et aucun ornement rapporté — les vignettes d'angle ont été
   retirées de la plateforme et ne reviendront pas.

   LE TITRE PORTE SON FIL. Chaque titre de vue est précédé du même fil vertical tissé
   cyan-vert que les sections en portent déjà : on reconnaît la page d'Academy à sa
   première ligne, et la hiérarchie devient lisible avant même d'être lue.

   LES CADRES ONT UNE ÉPAISSEUR. Un filet de lumière au bord haut, comme un objet éclairé
   par le dessus. C'est de la matière, pas de la décoration : elle ne s'ajoute pas à la
   carte, elle dit de quoi la carte est faite. */

.ac-titre h2 {
  position: relative;
  padding-left: 15px;
  font-size: 1.5rem;
  letter-spacing: -.01em;
}
.ac-titre h2::before {
  content: ""; position: absolute; left: 0; top: .12em; bottom: .12em; width: 4px;
  border-radius: 3px;
  background: linear-gradient(180deg, var(--ton), var(--green));
  box-shadow: 0 0 12px -3px color-mix(in srgb, var(--ton) 85%, transparent);
}

/* Le bonjour de l'accueil : c'est la première chose que lit un apprenant en ouvrant
   l'application, et c'était la plus discrète de l'écran. */
#vue-accueil > .ac-titre h2 { font-size: clamp(1.55rem, 4.4vw, 2rem); }

/* L'épaisseur des cadres. `inset` seulement : aucune ombre portée supplémentaire, donc
   aucun calque de plus à composer. */
.card {
  box-shadow: var(--shadow-card, 0 10px 26px -18px rgba(0,0,0,.5)),
              inset 0 1px 0 var(--card-sheen, rgba(255,255,255,.14));
}

/* Un état vide n'est pas une page en panne : son illustration respire. */
.ac-vide img { animation: acRespire 5.5s ease-in-out infinite; }
@keyframes acRespire {
  0%, 100% { transform: translateY(0) scale(1); opacity: .85; }
  50%      { transform: translateY(-4px) scale(1.02); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .ac-vide img { animation: none; }
}

/* ── Le carnet de notes ──────────────────────────────────────────────────────
   Un enseignant BALAIE son carnet du regard, il ne le lit pas ligne à ligne. La couleur
   porte donc l'information avant le chiffre : rouge sous dix, vert au-dessus de seize,
   ambre entre les deux. Le nom reste visible pendant qu'on fait défiler les colonnes —
   sans quoi, à la douzième, on ne sait plus de qui l'on regarde les notes. */
.ac-carnet { min-width: max-content; }
.ac-carnet th, .ac-carnet td { text-align: center; white-space: nowrap; }
.ac-carnet .ac-carnet-nom { text-align: left; position: sticky; left: 0; z-index: 2;
  background: var(--panel); box-shadow: 1px 0 0 var(--border); }
.ac-carnet thead th { font-size: .74rem; vertical-align: bottom; padding-bottom: 6px; }
.ac-carnet-devoir {
  display: block; max-width: 9.5em; overflow: hidden; text-overflow: ellipsis;
  font-weight: 700;
}
.ac-carnet-sur { display: block; color: var(--muted); font-weight: 400; font-size: .7rem; }
.ac-carnet-case {
  font-variant-numeric: tabular-nums; font-weight: 700; min-width: 3.2em;
  border-radius: 8px;
}
.ac-carnet-case.est-faible { color: var(--red-txt); background: color-mix(in srgb, var(--red) 14%, transparent); }
.ac-carnet-case.est-moyenne { color: var(--gold-txt); background: color-mix(in srgb, var(--gold) 13%, transparent); }
.ac-carnet-case.est-forte { color: var(--green-txt); background: color-mix(in srgb, var(--green) 14%, transparent); }
.ac-carnet-case.est-vide { color: var(--muted); opacity: .55; }
.ac-carnet-case.est-attente { color: var(--ton-txt); font-size: 1.3rem; line-height: 1; }
.ac-carnet-moyenne { font-weight: 700; font-variant-numeric: tabular-nums; }
.ac-carnet tfoot td { border-top: 2px solid var(--border); font-weight: 700; }

.ac-carnet-resume {
  display: flex; flex-wrap: wrap; gap: 8px 18px; margin: 0 0 14px;
  font-size: .86rem; color: var(--muted);
}
.ac-carnet-resume b { color: var(--text); font-size: 1.05rem; }
.ac-carnet-resume .est-attente b { color: var(--ton-txt); }
.ac-carnet-resume .est-manque b { color: var(--red-txt); }

/* La fenêtre du carnet est un TABLEAU : elle a besoin de la largeur qu'une fenêtre
   ordinaire n'a pas. */
.ac-modale-carte:has(.ac-carnet) { width: min(97%, 1080px); }

/* ── Le fil des questions d'une leçon ────────────────────────────────────────
   Une question et ses réponses forment un bloc : la réponse est décalée sous la question,
   et celle d'un professeur porte un liseré qui la distingue au premier regard — dans une
   classe, on cherche d'abord ce qu'a dit le professeur. */
.ac-questions { margin-top: 26px; }
.ac-question { margin-bottom: 12px; }
.ac-question.est-resolue { opacity: .82; }
.ac-question-meta { font-size: .82rem; color: var(--muted); margin: 0 0 8px; }
.ac-question-meta b { color: var(--text); }
.ac-question-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.ac-question-actions .chip--btn.is-active {
  border-color: var(--ton); color: var(--ton-txt);
  background: color-mix(in srgb, var(--ton) 14%, transparent);
}
.ac-reponse {
  margin: 12px 0 0 18px; padding: 12px 14px; border-radius: 12px;
  background: color-mix(in srgb, var(--ton) 5%, var(--panel2));
  border-left: 3px solid var(--border);
}
.ac-reponse.est-du-professeur {
  border-left-color: var(--ton);
  background: color-mix(in srgb, var(--ton) 9%, var(--panel2));
}
.ac-question-repondre { margin-top: 12px; }
.ac-question-repondre summary,
.ac-question-poser summary {
  cursor: pointer; font-family: var(--font-display); font-weight: 700; width: fit-content;
  display: flex; align-items: center; gap: 8px;
}
.ac-question-repondre textarea, .ac-question-poser textarea { width: 100%; margin-top: 10px; }
.ac-question-poser { margin-top: 18px; }

/* ── Signalement de bug ──────────────────────────────────────────────────────
   Le contexte joint est REPLIÉ mais toujours atteignable : celui qui signale doit pouvoir
   voir ce qui part, celui qui traite doit pouvoir le lire sans effort. */
/* Deux champs côte à côte quand la place le permet. Nommé pour ce qu'il fait : réutiliser
   la classe des filtres de comptes aurait lié deux écrans qui n'ont rien à voir. */
.ac-deux-champs { display: flex; gap: 12px; flex-wrap: wrap; }
.ac-deux-champs .field { flex: 1 1 220px; min-width: 0; }

.ac-bug-contexte { margin-top: 10px; }
.ac-bug-contexte summary {
  cursor: pointer; color: var(--muted); font-size: .84rem; width: fit-content;
}
.ac-bug-contexte summary:hover { color: var(--ton-txt); }
.ac-bug-contexte ul { margin: 10px 0 0; padding-left: 18px; font-size: .84rem; line-height: 1.8; }
.ac-bug-contexte code { font-size: .8rem; word-break: break-all; }
.ac-bug-reponse {
  border-left: 3px solid var(--ton); padding-left: 12px; margin-top: 10px;
  color: var(--text);
}
.ac-bug { margin-bottom: 12px; }
.ac-etiq.ac-bug-critique { color: var(--red-txt); border-color: color-mix(in srgb, var(--red) 55%, var(--border)); }
.ac-etiq.ac-bug-majeur { color: var(--gold-txt); border-color: color-mix(in srgb, var(--gold) 55%, var(--border)); }
/* Le mot du bouton s'efface sur un écran étroit : l'icône suffit à le reconnaître, et
   l'en-tête d'un téléphone n'a pas la place de tout porter.
   Mesuré à 390 pixels : la pastille finissait à 386, soit quatre pixels du bord, et
   paraissait coupée sur une capture. La marge de l'en-tête vaut 3 % chez la mère, ce qui
   fait douze pixels — encore faut-il que le groupe de pastilles ne les mange pas. */
@media (max-width: 560px) {
  .ac-bug-mot { display: none; }
  /* Le groupe de pastilles débordait sa piste de grille de six pixels et mangeait la marge
     de l'en-tête : la dernière pastille finissait coupée au bord. Elle peut désormais passer
     à la ligne plutôt que déborder — un en-tête un peu plus haut vaut mieux qu'une commande
     tronquée, sur laquelle on n'ose plus appuyer. */
  /* SUR TÉLÉPHONE, TOUT RESTE SUR UNE SEULE LIGNE, comme chez la maison mère.
     J'avais donné aux commandes une deuxième rangée (`grid-row: 2`) parce que la somme des
     trois pistes débordait de huit pixels. C'était résoudre le problème en changeant la
     mise en page, alors que la mère, elle, tient sur un rang — et Brice a raison de le
     relever : le bouton clair/sombre se retrouvait sous le logo au lieu d'être à sa hauteur.
     La mère y parvient en RÉTRÉCISSANT la marque sous 560 pixels : `.brand-mark` passe de 52
     à 42 pixels et `.brand-txt h1` à 1,62rem sans retour à la ligne. Ces deux règles ne
     touchaient pas Academy, dont le nom d'espace est un `<p class="ac-marque-nom">` et non
     un `h1` — d'où le débordement, et d'où la rustine. On applique la même réduction au bon
     sélecteur, et la ligne tient. Un nom d'établissement trop long s'abrège d'un point de
     suspension : mieux vaut « INSEL-Ngiemb… » sur le rang du logo qu'un nom entier qui
     pousse les commandes ailleurs. */
  .topbar > .brand { max-width: 100%; min-width: 0; }
  .brand-txt { overflow: hidden; min-width: 0; }
  .brand-txt .ac-marque-nom {
    font-size: clamp(1rem, 4.2vw, 1.32rem);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  /* La ligne d'accroche sous le nom disparaît sur un téléphone : elle vole la largeur dont
     le nom a besoin, et la maison mère la masque déjà à cette taille. */
  .chips-nav--top { justify-content: flex-end; gap: 6px; min-width: 0; }
  /* La grille de l'en-tête est décalée de sept pixels vers la droite par rapport à sa boîte
     de contenu — mesuré : elle commence à 19 quand la marge vaut 11,7. Le décalage vient de
     la feuille de la maison mère et ne se corrige pas d'ici sans la réécrire, ce qu'on
     s'interdit. On rend donc à la dernière pastille l'air qu'elle a perdu. Ce qui compte
     n'est pas la marge théorique, mais que rien ne frôle le bord de l'écran sous le pouce. */
  .topbar { padding-right: calc(3% + 9px); }
  #bouton-bug { padding-left: 9px; padding-right: 9px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   IDENTITÉ D'ACADEMY — V. LES TONS
   ═══════════════════════════════════════════════════════════════════════════
   Le reproche est juste : tout était cyan. Un cours, un devoir, un exercice, une annonce et
   la corbeille portaient la même couleur, si bien que la couleur ne disait plus rien — elle
   décorait au lieu de renseigner, et l'ensemble paraissait éteint.

   On donne donc UN TON À CHAQUE FAMILLE D'OBJET. Ce n'est pas de la variété pour la
   variété : c'est une information. Au bout de deux jours, on reconnaît un devoir à son ambre
   avant d'avoir lu son titre, et un exercice à son violet.

     COURS et leçons        cyan       la matière même, le socle
     DEVOIRS et copies      ambre      l'échéance, l'effort demandé
     EXERCICES              violet     le jeu, l'essai sans conséquence
     RÉVISION               vert       la mémoire qui pousse
     LEXIQUE et recherche   indigo     le mot que l'on cherche
     ANNONCES               rose       la voix qui interpelle
     DIRECTION              or         ce qui engage l'établissement
     CORBEILLE              rouge      ce qui est en sursis

   TOUT passe par une seule variable, `--ton`. Le fil de la charte d'interaction, la plaque
   d'une icône, la lueur au survol, le filet d'un titre : tous la lisent. Reteinter une
   famille, c'est changer une ligne — et rien ne peut diverger, puisque rien ne connaît sa
   propre couleur.

   Chaque ton a DEUX valeurs : l'aplat, qui remplit, et l'encre, qui écrit. Les six nouvelles
   encres ont été mesurées avant d'être posées : 6,58 au plus bas sur le panneau clair, 8,93
   au plus bas sur le sombre. La règle des deux métiers d'une couleur ne se contourne pas
   sous prétexte qu'on en ajoute. */

:root {
  --ton-cours: var(--cyan);        --ton-cours-txt: var(--cyan-txt);
  --ton-devoir: #b06f16;           --ton-devoir-txt: #8a4b12;
  --ton-exercice: var(--violet);   --ton-exercice-txt: var(--violet-txt);
  --ton-revision: var(--green);    --ton-revision-txt: var(--green-txt);
  --ton-lexique: #4f46e5;          --ton-lexique-txt: #3b3fa8;
  /* LA VOIX QUI INTERPELLE — en orange brûlé, plus en rose.
     J'avais choisi un magenta (#c2185b) pour ce ton. Deux torts, et le second est le pire.
     D'abord il jurait avec le rouge de la corbeille : sur un téléphone, les deux plaques de
     l'accueil se ressemblaient au point qu'on ne distinguait plus « Annonces » de
     « Corbeille ». Ensuite et surtout, Brice écrit noir sur blanc qu'il veut éviter le rose
     et le magenta — une règle donnée n'a pas à être redécouverte sur une capture d'écran.
     L'orange brûlé s'éloigne franchement du rouge, et reste distinct de l'ambre des devoirs,
     qui tire sur le brun doré. */
  --ton-annonce: #c2410c;          --ton-annonce-txt: #9a3412;
  --ton-direction: var(--gold);    --ton-direction-txt: var(--gold-txt);
  --ton-corbeille: var(--red);     --ton-corbeille-txt: var(--red-txt);
  /* LES GENS. Un neuvième ton, ajouté parce que le tableau de bord compte deux choses de
     nature différente — des personnes et de la matière — et n'avait qu'une seule couleur
     pour les dire. Le bleu de la charte n'était employé nulle part ailleurs : il distingue
     donc sans rien brouiller. Il ne désigne jamais un objet du cours, toujours ceux qui
     l'apprennent ou qui l'enseignent. */
  --ton-gens: var(--blue);         --ton-gens-txt: #1e4fb5;
  /* Le ton par défaut d'un écran : celui de la matière — c'est-à-dire le cyan de la charte.
     C'est ce qui a permis de basculer d'un coup les quatre-vingt-quinze usages du cyan figé
     qui restaient dans cette feuille : là où aucune famille n'est déclarée, `--ton` VAUT
     `--cyan` et rien ne change ; là où une famille l'est, tout la suit désormais, jusqu'au
     survol d'une flèche et au marqueur d'une liste. */
  --ton: var(--ton-cours);
  --ton-txt: var(--ton-cours-txt);
}
:root[data-theme="dark"] {
  --ton-devoir: #e8a860;           --ton-devoir-txt: #f0a868;
  --ton-lexique: #818cf8;          --ton-lexique-txt: #a5b4fc;
  --ton-annonce: #fb923c;          --ton-annonce-txt: #fdba74;
  --ton-gens-txt: #7aa7ff;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ton-devoir: #e8a860;         --ton-devoir-txt: #f0a868;
    --ton-lexique: #818cf8;        --ton-lexique-txt: #a5b4fc;
    --ton-annonce: #fb923c;        --ton-annonce-txt: #fdba74;
    --ton-gens-txt: #7aa7ff;
  }
}

/* Chaque écran déclare le sien. Une seule ligne par vue, et tout ce qu'elle contient suit. */
#vue-devoirs, #vue-devoir       { --ton: var(--ton-devoir);    --ton-txt: var(--ton-devoir-txt); }
#vue-reviser                    { --ton: var(--ton-revision);  --ton-txt: var(--ton-revision-txt); }
#vue-glossaire, #vue-recherche  { --ton: var(--ton-lexique);   --ton-txt: var(--ton-lexique-txt); }
#vue-annonces                   { --ton: var(--ton-annonce);   --ton-txt: var(--ton-annonce-txt); }
#vue-admin                      { --ton: var(--ton-direction); --ton-txt: var(--ton-direction-txt); }
#vue-corbeille                  { --ton: var(--ton-corbeille); --ton-txt: var(--ton-corbeille-txt); }
.ac-exo                         { --ton: var(--ton-exercice);  --ton-txt: var(--ton-exercice-txt); }

/* ET N'IMPORTE QUEL ÉLÉMENT PEUT DÉCLARER LE SIEN, par `data-ton`. Les tuiles du tableau de
   bord se teintaient par leur RANG dans la rangée — trois cyan, deux verts, un ambre — si
   bien qu'ajouter une tuile décalait la couleur de toutes les suivantes, et que « cours
   publiés » portait le vert de la révision. Une famille se nomme ; elle ne se compte pas.
   Une seule table, ici, pour toute la plateforme : la tuile qui compte des gens, la carte
   qui présente les exercices sur le portail, et tout ce qui viendra ensuite. */
[data-ton="cours"]     { --ton: var(--ton-cours);     --ton-txt: var(--ton-cours-txt); }
[data-ton="devoir"]    { --ton: var(--ton-devoir);    --ton-txt: var(--ton-devoir-txt); }
[data-ton="exercice"]  { --ton: var(--ton-exercice);  --ton-txt: var(--ton-exercice-txt); }
[data-ton="revision"]  { --ton: var(--ton-revision);  --ton-txt: var(--ton-revision-txt); }
[data-ton="lexique"]   { --ton: var(--ton-lexique);   --ton-txt: var(--ton-lexique-txt); }
[data-ton="annonce"]   { --ton: var(--ton-annonce);   --ton-txt: var(--ton-annonce-txt); }
[data-ton="direction"] { --ton: var(--ton-direction); --ton-txt: var(--ton-direction-txt); }
[data-ton="corbeille"] { --ton: var(--ton-corbeille); --ton-txt: var(--ton-corbeille-txt); }
[data-ton="gens"]      { --ton: var(--ton-gens);      --ton-txt: var(--ton-gens-txt); }
.ac-questions                   { --ton: var(--ton-lexique);   --ton-txt: var(--ton-lexique-txt); }

/* ── Ce qui LIT le ton ─────────────────────────────────────────────────────── */

/* Le fil de la charte d'interaction : il prend la couleur de la famille qu'il souligne. */
.btn::before, .chip--btn::before, .ac-carte-cours::before, .ac-espace::before,
.ac-raccourci::before, .ac-res::before, .ac-ligne::before, .ac-palette-btn::before {
  background: linear-gradient(90deg,
    transparent,
    color-mix(in srgb, var(--ton) 92%, transparent) 22%,
    color-mix(in srgb, var(--ton) 62%, var(--green)) 78%,
    transparent);
}

/* La levée et son halo. */
.ac-carte-cours:hover, .ac-espace:hover, .ac-res:hover {
  border-color: color-mix(in srgb, var(--ton) 62%, var(--border));
  box-shadow: 0 14px 30px -18px color-mix(in srgb, var(--ton) 85%, transparent),
              inset 0 1px 0 var(--card-sheen, rgba(255,255,255,.12));
}
.ac-ligne:hover, .ac-inscrit-ligne:hover, .ac-glo-entree:hover {
  background: color-mix(in srgb, var(--ton) 9%, transparent);
}
.btn:focus-visible, .chip--btn:focus-visible, .ac-carte-cours:focus-visible,
.ac-espace:focus-visible, .ac-raccourci:focus-visible, .ac-res:focus-visible,
.ac-ligne:focus-visible, .ac-palette-btn:focus-visible, .bottom-nav-tab:focus-visible,
.ac-vitesse:focus-visible, .ac-fleche:focus-visible,
input:focus-visible, select:focus-visible, textarea:focus-visible, summary:focus-visible {
  outline-color: var(--ton);
  box-shadow: 0 0 0 6px color-mix(in srgb, var(--ton) 22%, transparent);
}
.ac-onde { background: radial-gradient(circle, color-mix(in srgb, var(--ton) 55%, #fff) 0%, transparent 70%); }

/* Le filet des titres, et celui des sections. */
.ac-titre h2::before { background: linear-gradient(180deg, var(--ton), color-mix(in srgb, var(--ton) 40%, var(--green))); }
.ac-titre h2::before { box-shadow: 0 0 12px -3px color-mix(in srgb, var(--ton) 85%, transparent); }
.ac-bloc-titre2 { border-image: linear-gradient(180deg, var(--ton), color-mix(in srgb, var(--ton) 40%, var(--green))) 1; }
.ac-chapitre-titre::before { background: var(--ton); }

/* La plaque d'une icône. */
/* La plaque porte franchement son ton : à vingt-deux pour cent elle restait grise et la
   palette ne se voyait pas. Le contour aussi, sinon le cadre reste neutre et annule ce que
   le fond dit. */
.ac-plaque {
  background: linear-gradient(150deg,
    color-mix(in srgb, var(--ton) 40%, var(--panel2)),
    color-mix(in srgb, var(--ton) 16%, var(--panel2)));
  border-color: color-mix(in srgb, var(--ton) 58%, var(--border));
  box-shadow: inset 0 1px 0 var(--card-sheen, rgba(255,255,255,.16)),
              0 2px 10px -6px color-mix(in srgb, var(--ton) 70%, transparent);
}
.ac-raccourci:hover .ac-plaque {
  border-color: var(--ton);
  box-shadow: 0 6px 16px -8px color-mix(in srgb, var(--ton) 80%, transparent);
}

/* Les raccourcis de l'accueil portent CHACUN le ton de sa destination : c'est la première
   fois qu'on voit la palette entière, et elle annonce ce qu'on trouvera derrière. */
.ac-raccourci[href="#/reviser"]   { --ton: var(--ton-revision);  --ton-txt: var(--ton-revision-txt); }
.ac-raccourci[href="#/recherche"] { --ton: var(--ton-lexique);   --ton-txt: var(--ton-lexique-txt); }
.ac-raccourci[href="#/glossaire"] { --ton: var(--ton-lexique);   --ton-txt: var(--ton-lexique-txt); }
.ac-raccourci[href="#/annonces"]  { --ton: var(--ton-annonce);   --ton-txt: var(--ton-annonce-txt); }
.ac-raccourci[href="#/corbeille"] { --ton: var(--ton-corbeille); --ton-txt: var(--ton-corbeille-txt); }

/* Une carte de cours garde le ton de la matière, mais ses étiquettes se distinguent : le
   niveau, l'avancement et l'alerte ne disent pas la même chose et ne doivent pas se
   ressembler. */
.ac-carte-cours .ac-etiq:first-of-type {
  color: var(--ton-cours-txt);
  border-color: color-mix(in srgb, var(--ton-cours) 42%, var(--border));
  background: color-mix(in srgb, var(--ton-cours) 10%, transparent);
}
.ac-barre > i { background: linear-gradient(90deg, var(--ton), color-mix(in srgb, var(--ton) 40%, var(--green))); }

/* Les étiquettes d'un cours et les pastilles de la barre basse suivent aussi. */
.bottom-nav-tab[href="#/devoirs"]   { --acc: var(--ton-devoir);   --acc-txt: var(--ton-devoir-txt); }
.bottom-nav-tab[href="#/reviser"]   { --acc: var(--ton-revision); --acc-txt: var(--ton-revision-txt); }
.bottom-nav-tab[href="#/copies"]    { --acc: var(--ton-exercice); --acc-txt: var(--ton-exercice-txt); }
.bottom-nav-tab[href="#/notifications"] { --acc: var(--ton-annonce); --acc-txt: var(--ton-annonce-txt); }
.bottom-nav-tab.is-active::after {
  background: linear-gradient(90deg, var(--acc, var(--ton)), color-mix(in srgb, var(--acc, var(--ton)) 45%, var(--green)));
  box-shadow: 0 0 8px -1px var(--acc, var(--ton));
}

/* L'icône d'une étiquette ou d'une palette : posée dans le flux du texte, elle doit
   s'aligner sur la ligne de base plutôt que la bousculer. */
.ac-etiq .ac-ico { width: 15px; height: 15px; vertical-align: -3px; margin-right: 2px; }
.ac-ligne-meta .ac-ico { width: 16px; height: 16px; vertical-align: -3px; }
.ac-palette-ico { width: 26px; height: 26px; margin-bottom: 6px; }
.ac-palette-btn { display: flex; flex-direction: column; align-items: flex-start; }

/* Le SOL déclaré du bandeau de page.
   Comme le pied de page, son fond est une PHOTO : aucune couleur qu'une mesure puisse lire,
   et le contrôle de contraste retombait sur le sol clair de la page pour conclure à tort que
   l'accroche dorée était illisible. La maison mère écrit la règle noir sur blanc dans sa
   feuille : « la bannière est TOUJOURS sombre, image identique dans les deux thèmes, donc le
   texte utilise des couleurs VIVES fixes ». Le sol déclaré ici est MESURÉ sur la bande où le
   texte se pose réellement, tiers gauche du bandeau rendu : rgb(25, 28, 22). */
/* UN VOILE SOUS LE TEXTE DU BANDEAU.
   La maison mère n'en a pas besoin : ses six images sont sombres à gauche par construction,
   et son texte s'y pose sans rien demander. Les sept images d'Academy ont été commandées
   avec la même contrainte, et cinq la respectent largement — mesuré sur le fichier lui-même,
   entre 5,0 et 11,1 de contraste. Deux non : le bandeau des devoirs tombe à 3,34 pour l'or
   de l'accroche et 3,78 pour le vert de la phrase, celui de l'attestation à 4,38. En dessous
   de 4,5, un texte n'est plus lisible pour qui voit mal, et sur un téléphone en plein soleil
   il ne l'est plus pour personne.

   On pourrait retoucher ces deux images. On pose plutôt un dégradé sur TOUTES : ce qui est
   déjà sombre ne change pas visiblement, ce qui est trop clair devient lisible, et l'image
   suivante — celle qu'on commandera dans six mois et qui arrivera un peu trop lumineuse —
   sera couverte sans qu'on ait à y penser. C'est la différence entre garantir par la
   structure et espérer par la discipline.

   Le dégradé s'arrête à cinquante-cinq pour cent : au-delà se trouve le sujet, et l'assombrir
   abîmerait la photographie sans servir personne. */
.page-banner::before {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(100deg,
    rgba(6, 10, 14, .72) 0%,
    rgba(6, 10, 14, .58) 22%,
    rgba(6, 10, 14, .22) 42%,
    rgba(6, 10, 14, 0) 55%);
}
/* Le sol déclaré suit : c'est sur CE fond-là que le texte se pose désormais, et c'est lui
   que la mesure de contraste doit prendre pour référence. */
.page-banner { --sol-local: #0a0f13; }

/* ── Le titre de vue, celui de la maison mère ────────────────────────────────
   `view-title view-title--ico` vient de sa feuille et n'est pas réécrit ici : capsule
   teintée, bordure-comète qui tourne, respiration lente, icône de 34 pixels. On n'ajoute
   que ce qui est propre à la filiale — la teinte suit le TON de la famille, si bien que
   chaque page annonce sa couleur dès sa première ligne. */
.ac-titre-cours     { --acc: var(--ton-cours);     --acc-txt: var(--ton-cours-txt); }
.ac-titre-devoir    { --acc: var(--ton-devoir);    --acc-txt: var(--ton-devoir-txt); }
.ac-titre-revision  { --acc: var(--ton-revision);  --acc-txt: var(--ton-revision-txt); }
.ac-titre-lexique   { --acc: var(--ton-lexique);   --acc-txt: var(--ton-lexique-txt); }
.ac-titre-annonce   { --acc: var(--ton-annonce);   --acc-txt: var(--ton-annonce-txt); }
.ac-titre-direction { --acc: var(--ton-direction); --acc-txt: var(--ton-direction-txt); }
.ac-titre-corbeille { --acc: var(--ton-corbeille); --acc-txt: var(--ton-corbeille-txt); }

/* Le titre porte maintenant sa capsule : le filet vertical ferait double emploi. */
.ac-titre .view-title { margin: 0; }
.ac-titre h2.view-title { padding-left: 20px; }
.ac-titre h2.view-title::before { content: none; }
.view-title .title-ico { width: 34px; height: 34px; }

/* ── Le bouton principal prend le TON de sa page ─────────────────────────────
   Chez la mère, `.btn--primary` est cyan partout : elle n'a qu'un seul métier par écran.
   Academy en a plusieurs, et six boutons teal alignés d'un écran à l'autre finissaient par
   ne plus rien dire. Le bouton qui publie un devoir est ambre, celui qui ajoute un terme au
   lexique est indigo, celui qui écrit une annonce est rose. On garde EXACTEMENT la forme de
   la mère — même fond plein, même ombre portée, même halo au survol — et l'on ne change que
   la teinte, qui vient du ton de la page.

   L'encre posée dessus reste `--sur-accent`, la seule dont on ait vérifié qu'elle se lit sur
   n'importe quel aplat, y compris ceux qu'un établissement choisit lui-même. */
.btn--primary {
  background: var(--ton); border-color: var(--ton);
  color: var(--sur-accent);
  box-shadow: 0 8px 20px -10px var(--ton);
}
.btn--primary:hover {
  box-shadow: 0 0 34px -4px var(--ton), 0 0 12px -2px var(--ton), 0 8px 20px -10px var(--ton);
}
/* Un bouton principal DANS une fenêtre suit le ton de ce que la fenêtre traite, pas celui de
   la page qui l'a ouverte : c'est l'action qui compte, pas d'où l'on vient. */
.ac-modale-carte { --ton: var(--ton-cours); --ton-txt: var(--ton-cours-txt); }

/* ── L'en-tête suit la GRILLE de la maison mère ──────────────────────────────
   Sa `.topbar` est une grille de TROIS colonnes — la marque, un espace souple, les
   pastilles — et sa règle place le groupe de pastilles en colonne 3. Academy n'avait posé
   que deux enfants : le groupe atterrissait dans une troisième colonne inexistante, se
   dimensionnait sur son contenu et débordait de huit pixels dans la marge, si bien que la
   dernière pastille paraissait coupée au bord. Mesuré à 390 pixels : zone utile jusqu'à
   378, pastille jusqu'à 386.

   On ne réécrit pas sa grille : on lui donne le TROISIÈME enfant qu'elle attend, un simple
   espace souple, et tout se remet en place. */
.topbar > .ac-entete-espace { grid-column: 2; grid-row: 1; }

/* Et le NOM DE L'ÉTABLISSEMENT doit pouvoir se tronquer.
   La maison mère pose `min-width: 0` sur `.brand` et `.brand-txt` précisément pour cela, et
   note l'incident qui le lui a appris. Academy héritait de ces deux règles mais son nom, lui,
   n'avait ni `overflow` ni `text-overflow` : « INSEL-Ngiemboon » occupait 212 pixels
   incompressibles, la grille débordait de huit, et la dernière pastille finissait dans la
   marge. Mesuré, pas supposé. */
.brand-txt .ac-marque-nom {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ── Un bouton principal DÉSACTIVÉ doit se lire comme indisponible ───────────
   La charte de la mère l'atténue à cinquante pour cent. Sur un aplat cyan, cela suffisait ;
   sur l'ambre d'un devoir posé sur un fond clair, le bouton devient beige et se lit comme
   un bouton actif délavé — on appuie, il ne se passe rien, on recommence. Un bouton qui
   n'est pas disponible perd donc son APLAT et redevient un contour : la différence ne se
   discute plus, quel que soit le ton de la page. */
.btn--primary:disabled {
  background: transparent; background-image: none;
  color: var(--muted); border-color: var(--border);
  box-shadow: none; opacity: .75;
}
.btn--primary:disabled::before { display: none; }
