/* =============================================================================
   HABILLAGE V2 — couche d'essai
   =============================================================================

   Cette feuille est chargée en dernier, après tailwind.css, dark.css et
   app.css. Elle ne change aucune structure, aucun comportement, aucune classe
   du HTML : elle se contente de redéfinir ce que valent les classes déjà
   posées. Retirer la ligne <link> de app.html suffit à revenir exactement à
   l'ancien habillage — c'est le but d'une branche d'essai.

   Ce qu'elle corrige, dans l'ordre de ce qui saute aux yeux :

     1. les dégradés lilas peints sur le bandeau et la barre latérale ;
     2. le `font-black` posé 239 fois, qui fait crier toute l'interface ;
     3. les bordures de 2 px et les quatre rayons mélangés ;
     4. les dégradés bleu-indigo, ramenés à une seule signature indigo→violet ;
     5. les ombres noires, remplacées par des ombres teintées.

   Ce qu'elle ne touche pas : les couleurs qui portent un sens (ambre pour
   l'alerte, émeraude pour la réussite, rose pour l'erreur), les tailles de
   cible tactile, les règles d'accessibilité et le mode sombre généré.

   La maquette d'origine et le raisonnement complet : design/proposition-ui/.
   ============================================================================= */

/* ------------------------------------------------------------------ jetons */

:root {
    --v2-bg:          #f3f4fb;
    --v2-surface:     #ffffff;
    --v2-surface-2:   #f7f8fd;
    --v2-line:        #e5e6f4;
    --v2-line-strong: #cbcee6;
    --v2-ink:         #14162b;
    --v2-ink-2:       #494f6d;
    --v2-ink-3:       #7a80a2;
    --v2-accent:      #4f46e5;
    --v2-accent-2:    #8b5cf6;
    --v2-accent-soft: #eef0fe;
    --v2-grad:        linear-gradient(135deg, #6366f1 0%, #8b5cf6 55%, #6366f1 100%);
    --v2-glow:        0 6px 18px -6px rgb(99 102 241 / .55);
    --v2-shadow:      0 1px 2px rgb(49 46 129 / .06), 0 1px 3px rgb(49 46 129 / .08);
    --v2-shadow-2:    0 14px 36px -10px rgb(49 46 129 / .22), 0 2px 8px rgb(49 46 129 / .08);
}

html.dark {
    --v2-bg:          #080a17;
    --v2-surface:     #12142a;
    --v2-surface-2:   #0d0f21;
    --v2-line:        #262a4d;
    --v2-line-strong: #3a3f6d;
    --v2-ink:         #eaebf9;
    --v2-ink-2:       #b0b4d6;
    --v2-ink-3:       #838ab2;
    --v2-accent:      #8b8cf9;
    --v2-accent-soft: #221f52;
    --v2-shadow:      0 1px 2px rgb(0 0 0 / .55);
    --v2-shadow-2:    0 18px 44px -12px rgb(0 0 0 / .8), 0 2px 8px rgb(0 0 0 / .45);
}

/* ------------------------------------------------------------------- fonds */

/* Le gris de l'espace de travail tire vers le violet : un gris parfaitement
   neutre donne un écran d'hôpital. */
body.bg-slate-100 { background-color: var(--v2-bg); }
html.dark body { background-color: var(--v2-bg) !important; }

/* Bandeau et barre latérale : le dégradé lilas s'efface au profit d'une
   surface plate. C'est le plan de classe qui doit attirer l'œil, pas le
   cadre qui l'entoure. */
.cm-chrome,
html.dark .cm-chrome {
    background: var(--v2-surface) !important;
    border-color: var(--v2-line) !important;
}

/* Filet de couleur sous le bandeau : deux pixels suffisent à donner une
   identité à l'écran là où un dégradé plein champ écrasait le contenu. */
header.cm-chrome {
    position: relative;
    border-radius: 0 !important;
    box-shadow: none !important;
}

header.cm-chrome::after {
    content: '';
    position: absolute;
    inset: auto 0 -1px 0;
    height: 2px;
    background: var(--v2-grad);
}

aside.cm-chrome {
    border-radius: 0 !important;
    box-shadow: none !important;
    /* Lavis d'accent en tête de colonne, éteint en 200 px. */
    background-image: linear-gradient(180deg,
        color-mix(in srgb, var(--v2-accent) 7%, transparent), transparent 200px) !important;
}

/* En-tête des pages annexes — compte, connexion, inscription, administration.
   Elles n'ont pas le bandeau `.cm-chrome` de l'application, mais elles
   méritent le même filet de couleur : c'est lui qui fait qu'on reconnaît le
   produit d'un écran à l'autre. */
header.cm-entete-v2 {
    position: sticky;
    border-bottom-color: var(--v2-line) !important;
}

header.cm-entete-v2::after {
    content: '';
    position: absolute;
    inset: auto 0 -1px 0;
    height: 2px;
    background: var(--v2-grad);
}

/* Le fond des écrans d'authentification — grille et halo — a vécu ici en
   copie de celui du site. Les deux ont divergé le temps d'un commit. Il est
   maintenant dans `/css/fond-site.css`, chargé aussi bien par le site que par
   ces pages, et la classe à poser sur le corps est `cm-fond-site`. */

/* ------------------------------------------------------------- typographie */

/* Le noir absolu (900) est réservé aux nombres et aux titres de modale ;
   partout ailleurs, 600 suffit à faire un gras. Quand tout crie, plus rien
   ne ressort. */
.font-black { font-weight: 600; }
h1.font-black, h2.font-black { font-weight: 750; }

/* Les capitales espacées restent, mais moins hurlantes. */
.tracking-widest { letter-spacing: .06em; }

.text-slate-800, .text-slate-900 { color: var(--v2-ink); }
.text-slate-600, .text-slate-700 { color: var(--v2-ink-2); }
.text-slate-500 { color: var(--v2-ink-3); }

/* --------------------------------------------------------- formes et filets */

/* Une seule échelle de rayons, au lieu de quatre valeurs voisines posées au
   hasard sur des éléments contigus. */
.rounded-lg  { border-radius: 8px; }
.rounded-xl  { border-radius: 10px; }
.rounded-2xl { border-radius: 14px; }
.rounded-3xl { border-radius: 18px; }
@media (min-width: 1024px) { .lg\:rounded-2xl { border-radius: 14px; } }

/* Un filet d'un pixel. La bordure double est ce qui donnait à l'ensemble son
   air de maquette scolaire ; l'état actif se marque par la couleur et par un
   halo, pas par l'épaisseur. */
.border-2 { border-width: 1px; }

.border-slate-200, .border-slate-100 { border-color: var(--v2-line); }
.border-slate-300 { border-color: var(--v2-line-strong); }
.border-indigo-200, .border-indigo-100 { border-color: color-mix(in srgb, var(--v2-accent) 25%, var(--v2-line)); }

/* Les ombres noires grisent tout ce qu'elles touchent sur un fond coloré. */
.shadow-sm, .shadow-md { box-shadow: var(--v2-shadow); }
.shadow-lg, .shadow-xl, .shadow-2xl { box-shadow: var(--v2-shadow-2); }

/* --------------------------------------------------------------- dégradés */

/* Une seule signature — indigo→violet — pour toutes les actions principales.
   Les six variantes bleu, indigo et violet qui coexistaient n'étaient pas des
   nuances : c'était du hasard accumulé. */
.from-blue-500, .from-blue-600, .from-blue-700,
.from-indigo-500, .from-indigo-600, .from-indigo-700,
.hover\:from-indigo-600:hover, .hover\:from-indigo-700:hover,
.hover\:from-blue-700:hover, .hover\:from-violet-700:hover {
    --tw-gradient-from: #6366f1 var(--tw-gradient-from-position);
    --tw-gradient-to: rgb(99 102 241 / 0) var(--tw-gradient-to-position);
    --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
}

.to-blue-600, .to-blue-700, .to-indigo-600, .to-indigo-700, .to-violet-600, .to-purple-700,
.hover\:to-blue-600:hover, .hover\:to-blue-700:hover,
.hover\:to-indigo-700:hover, .hover\:to-violet-600:hover, .hover\:to-purple-700:hover {
    --tw-gradient-to: #8b5cf6 var(--tw-gradient-to-position);
}

/* Les aplats vifs qui portent un sens — ambre pour l'alerte, émeraude pour la
   réussite, rose pour l'erreur — gardent leur teinte : ce sont les seuls
   endroits où la couleur dit quelque chose.

   Ils perdent en revanche leur dégradé. Deux arrêts saturés sur un bouton de
   trente pixels de haut, c'est la signature de l'ancienne version, et les
   boutons indigo l'avaient déjà quittée : les verts et les ambrés restaient
   seuls à l'arborer, au milieu d'une interface qui s'était aplanie autour
   d'eux. Une teinte pleine par intention, la même partout. */

.bg-gradient-to-r.from-emerald-400,
.bg-gradient-to-r.from-emerald-500,
.bg-gradient-to-br.from-emerald-400,
.bg-gradient-to-br.from-emerald-500 {
    background-image: none !important;
    background-color: #047857;
}
.hover:from-emerald-600:hover { background-color: #065f46; }

.bg-gradient-to-r.from-amber-400,
.bg-gradient-to-r.from-amber-500,
.bg-gradient-to-br.from-amber-400,
.bg-gradient-to-br.from-amber-500 {
    background-image: none !important;
    background-color: #f59e0b;
    color: #451a03;
}
.hover:from-amber-500:hover,
.hover:from-amber-600:hover { background-color: #fbbf24; }

.bg-gradient-to-r.from-red-500,
.bg-gradient-to-r.from-rose-500,
.bg-gradient-to-br.from-red-500,
.bg-gradient-to-br.from-rose-500 {
    background-image: none !important;
    background-color: #be123c;
}
.hover:from-red-600:hover { background-color: #9f1239; }

.bg-gradient-to-r.from-violet-500,
.bg-gradient-to-r.from-violet-600,
.bg-gradient-to-br.from-violet-500,
.bg-gradient-to-br.from-violet-600 {
    background-image: none !important;
    background-color: #7c3aed;
}
.hover:from-violet-700:hover { background-color: #6d28d9; }

.bg-gradient-to-r.from-slate-700,
.bg-gradient-to-br.from-slate-700 {
    background-image: none !important;
    background-color: #334155;
}

/* Le bouton principal gagne l'ombre colorée du site. */
.bg-gradient-to-r.from-indigo-600,
.bg-gradient-to-r.from-blue-600 { box-shadow: var(--v2-glow); }

/* ------------------------------------------------------- aplats indigo doux */

.bg-indigo-50  { background-color: var(--v2-accent-soft); }
.text-indigo-600, .text-indigo-700 { color: var(--v2-accent); }

/* --------------------------------------------------------------- la salle */

/* Le plan est un objet posé sur un fond teinté, au lieu de cases flottant
   dans une zone vide.

   Le quadrillage qui doublait ce fond a été retiré : la salle a déjà sa
   grille, dessinée par les places elles-mêmes, et une seconde trame derrière
   ne rappelait rien qu'on ne voie déjà. Les deux halos restent — ils donnent
   au fond sa profondeur, sans rien y écrire. */
.cm-app main > section {
    position: relative;
    background: var(--v2-bg);
}

.cm-app main > section::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background-image:
        radial-gradient(32rem 20rem at 20% -3rem, color-mix(in srgb, var(--v2-accent) 15%, transparent), transparent 70%),
        radial-gradient(28rem 20rem at 88% 6%, color-mix(in srgb, var(--v2-accent-2) 12%, transparent), transparent 72%);
    -webkit-mask-image: radial-gradient(ellipse 95% 75% at 50% 0%, #000 15%, transparent 88%);
    mask-image: radial-gradient(ellipse 95% 75% at 50% 0%, #000 15%, transparent 88%);
}

/* La carte qui contient le plan.

   Elle portait un liseré coloré en tête, emprunté aux cartes du site. Il y
   faisait doublon : le bandeau de l'application en a déjà un, deux centimètres
   plus haut, et deux traits violets parallèles ne signent pas mieux qu'un. */
.cm-app main > section > div.bg-white {
    position: relative;
    z-index: 1;
    border-radius: 20px !important;
    border-color: var(--v2-line) !important;
    box-shadow: var(--v2-shadow-2) !important;
}

/* ------------------------------------------------- configuration de la salle */

/* Le tiroir de configuration gardait trois colonnes quelle que soit la
   largeur disponible. Sur un écran de 1 024 px, où la barre latérale en prend
   déjà 384, chaque carte tombait à 190 px — et la case « Rangées − 5 + » à
   68 px, son compteur débordant de 48 px hors de la carte.
   Les colonnes se replient maintenant selon la place. */
/* 165 px et non 210 : les trois étapes doivent tenir sur une seule ligne
   partout où c'est possible — c'est un parcours numéroté, le lire en L n'a
   aucun sens. Elles ne se replient qu'en dessous de 475 px de large, sur
   téléphone donc. */
.cm-app main .grid.grid-cols-3 {
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}

/* Ce sont les deux compteurs « Rangées » et « Colonnes » qui, eux, s'empilent
   quand la carte se resserre. C'est là que se trouvait le débordement : à
   190 px de carte, ils tentaient de rester côte à côte et sortaient du cadre. */
.cm-app main .grid.grid-cols-3 .grid.grid-cols-2 {
    grid-template-columns: repeat(auto-fit, minmax(125px, 1fr));
}

/* ---------------------------------------------------------------- places */

/* Une place occupée est une petite carte : lavis coloré en haut, filet plus
   ferme, ombre douce — au lieu d'un aplat bleu vif. */
[data-seat] {
    transition: border-color .15s, box-shadow .15s, transform .15s, background-color .15s;
}

/* `data-exemple` : les pastilles de la légende. Elles portaient encore les
   couleurs d'avant le thème V2 et annonçaient donc autre chose que ce que la
   grille montre — une légende qui se trompe est pire que pas de légende. */
[data-seat].bg-indigo-50,
[data-exemple].bg-indigo-50 {
    background-color: var(--v2-surface) !important;
    background-image: linear-gradient(165deg,
        color-mix(in srgb, var(--v2-accent) 10%, transparent), transparent 62%) !important;
    border-color: color-mix(in srgb, var(--v2-accent) 35%, var(--v2-line)) !important;
    box-shadow: var(--v2-shadow);
}

[data-seat].bg-indigo-50:hover { transform: translateY(-2px); box-shadow: var(--v2-shadow-2); }

/* Place fixée à la main : elle redevient jaune sur toute sa surface.
 *
 * La version V2 l'avait réduite à un filet ambre sur le bord gauche, au motif
 * que le fond servait déjà à trois autres choses. Le raisonnement tenait sur
 * une maquette et pas devant une classe : trois pixels sur un bord ne se
 * voient pas quand on cherche des yeux, dans une grille de trente places,
 * celles qu'on a soi-même épinglées. La couleur, elle, se repère sans être
 * cherchée — c'est tout ce qu'on lui demande.
 *
 * Le filet du bord disparaît : le contour ambre en fait le tour, et un bord
 * plus épais que les trois autres donnait une carte de travers.
 *
 * L'aplat est un peu plus soutenu que le lavis indigo des places occupées.
 * Il le faut : l'ambre est une couleur claire, et à teneur égale elle se lit
 * deux fois moins bien. */
[data-seat].bg-amber-50,
[data-exemple].bg-amber-50 {
    background-color: color-mix(in srgb, #f59e0b 13%, var(--v2-surface)) !important;
    background-image: linear-gradient(165deg,
        color-mix(in srgb, #f59e0b 16%, transparent), transparent 70%) !important;
    border-color: color-mix(in srgb, #d97706 45%, var(--v2-line)) !important;
    box-shadow: var(--v2-shadow);
}

[data-seat].bg-amber-50:hover { transform: translateY(-2px); box-shadow: var(--v2-shadow-2); }

/* Place libre : le pointillé suffit. L'étiquette « ▾ LIBRE », répétée
   trente-cinq fois, noyait les noms d'élèves ; elle reste là pour les
   lecteurs d'écran, mais s'efface presque complètement à l'œil. */
[data-seat] span.select-none.text-center {
    color: var(--v2-line-strong) !important;
    font-weight: 500;
    font-size: 10px;
    letter-spacing: .08em;
    opacity: .8;
}

/* ---------------------------------------------------------- pictogrammes */

/* Les émojis du bandeau (🤖 🔍 📄 ⚙️ 🌙) laissent la place à un jeu d'icônes
   dessiné au même trait : un émoji change de dessin à chaque système, et
   l'application ne ressemblait à personne.

   Les quatre repères de profil — bavard, PAP, vue, allée — restent des
   pictogrammes, eux : ce sont ceux que les enseignants lisent le plus vite.
   Ils sont simplement redessinés et posés dans une pastille de leur couleur. */

.cm-icon {
    width: 15px;
    height: 15px;
    flex: 0 0 auto;
}

.cm-icon-sm { width: 13px; height: 13px; flex: 0 0 auto; }
.cm-icon-lg { width: 26px; height: 26px; flex: 0 0 auto; }
.cm-icon-xl { width: 40px; height: 40px; flex: 0 0 auto; }

/* La boîte appartient à la classe de base, et non à sa variante.
   Elle ne vivait que dans `.cm-pic-lg` : un `cm-pic` employé seul n'avait donc
   aucune dimension, et le SVG qu'il contient — dessiné sans largeur, comme il
   se doit dans une planche — retombait sur sa taille intrinsèque. Un
   pictogramme de cent pixels s'installait alors au milieu d'une phrase de
   douze. Cinq endroits en souffraient, dont deux écrans du tutoriel. */
.cm-pic {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    flex: 0 0 auto;
    border-radius: 5px;
    background: color-mix(in srgb, var(--cm-c) 15%, transparent);
    color: var(--cm-c);
}
.cm-pic svg { width: 74%; height: 74%; display: block; }

.cm-pic-lg { width: 20px; height: 20px; border-radius: 6px; }
.cm-pic-lg svg { width: 13px; height: 13px; }

.cm-pic-bavard { --cm-c: #e11d48; }
.cm-pic-pap    { --cm-c: #059669; }
.cm-pic-vision { --cm-c: #d97706; }
.cm-pic-allee  { --cm-c: #4f46e5; }

html.dark .cm-pic-bavard { --cm-c: #fb7185; }
html.dark .cm-pic-pap    { --cm-c: #34d399; }
html.dark .cm-pic-vision { --cm-c: #fbbf24; }
html.dark .cm-pic-allee  { --cm-c: #8b8cf9; }

/* ------------------------------------------------- liste d'élèves (colonne) */

/* Un élève déjà placé s'éteint, comme une tâche cochée : vingt-quatre noms
   traités ne doivent pas peser autant que les quatre qui attendent. Le
   contraste plein revient au survol — on éteint l'attention, jamais la
   lisibilité. */
.drag-source-list.border-l-emerald-400 { border-left-color: var(--v2-line-strong) !important; }
.drag-source-list.border-l-emerald-400 p { color: var(--v2-ink-3); font-weight: 500; }
.drag-source-list.border-l-emerald-400 .bg-emerald-50 {
    background-color: var(--v2-surface-2) !important;
    color: var(--v2-ink-3) !important;
    font-weight: 600;
}
.drag-source-list.border-l-emerald-400:hover p { color: var(--v2-ink); }

/* Celui qui reste à placer garde, lui, tout son contraste. */
.drag-source-list.border-l-amber-400 p { font-weight: 600; }

/* --------------------------------------------------- relations de voisinage */

/* Les deux listes de camarades étaient en `flex-wrap` : chaque ligne se calait
   sur la longueur des noms qu'elle contenait, si bien qu'aucune pastille n'en
   surplombait une autre. Sur trente noms, l'œil n'avait plus aucune colonne à
   suivre — et les deux colonnes voisines, « placer à côté » et « ne pas placer
   à côté », ne se répondaient pas non plus.

   Une grille règle les deux d'un coup : les pastilles occupent toute la largeur
   de leur cellule, donc elles s'alignent verticalement d'une liste à l'autre.
   Le nombre de colonnes suit la place disponible — deux dans la fiche élève,
   une seule sur un téléphone. */
.flex-wrap.max-h-36 {
    display: grid !important;
    /* 118 px : deux colonnes tiennent dans les 266 px utiles d'un panneau de la
       fiche élève. À 132 px, il en manquait trois — et la grille retombait sur
       une seule colonne, ce qui n'aidait personne. */
    grid-template-columns: repeat(auto-fill, minmax(118px, 1fr));
    gap: 5px;
    align-content: start;
}

.flex-wrap.max-h-36 > button {
    width: 100%;
    min-width: 0;
    justify-content: flex-start;
}

/* Un nom trop long s'abrège plutôt que de déformer sa pastille : la largeur
   régulière est ce qu'on est venu chercher. */
.flex-wrap.max-h-36 > button > span:last-child {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ------------------------------------------------ fiche élève en panneau */

/* La fiche était une modale plein écran : régler les contraintes d'un élève
   revenait à masquer le plan sur lequel on travaille. Sur un écran assez
   large pour les montrer tous les deux, elle devient un panneau ancré à
   droite, et la zone du plan se rétrécit d'autant plutôt que d'être
   recouverte.
   Sous 1 100 px, rien ne change : la modale reste la bonne réponse. */

@media (min-width: 1360px) {

    /* Le voile disparaît, et la surcouche cesse de s'étendre sur tout l'écran :
       le reste de l'application redevient cliquable, sans quoi le panneau se
       comporterait encore comme une modale. */
    /* Le panneau se range contre la liste des élèves, et non à l'autre bout
       de l'écran. C'est de la liste qu'on vient — on y clique un nom — et
       c'est vers elle qu'on retourne au suivant : mille pixels de plan entre
       les deux faisaient traverser l'écran à chaque élève.

       384 px : la largeur de la liste au-delà de 1024 px. Repliée, la fiche
       revient contre le bord. */
    .cm-fiche {
        left: 0;
        right: auto;
        width: 380px;
        top: var(--cm-hauteur-entete, 63px);   /* mesuré, non recopié */
        padding: 0 !important;
        background: transparent !important;
        backdrop-filter: none !important;
        -webkit-backdrop-filter: none !important;
        transition: left .25s cubic-bezier(.22, 1, .36, 1);
    }

    .cm-liste-ouverte .cm-fiche { left: 384px; }

    .cm-fiche-panel {
        max-width: none !important;
        max-height: none !important;
        width: 100%;
        height: 100%;
        border-radius: 18px 18px 0 0 !important;
        border-right: 1px solid var(--v2-line);
        box-shadow: var(--v2-shadow-2) !important;
    }

    /* L'onglet de fermeture n'existe qu'ici : posé sur le bord du panneau, il
       rappelle depuis le plan qu'une fiche est ouverte. En modale, la croix de
       l'en-tête suffit — d'où le `hidden` porté par le HTML lui-même, qui vaut
       aussi si cette feuille venait à être retirée. */
    .cm-fiche-tab {
        display: flex !important;
        left: auto;
        right: 0;
        transform: translate(100%, -50%);
    }

    /* Le plan cède la place au lieu de passer dessous — le plan seul :
       `main` contient aussi la liste des élèves, et l'écarter par la gauche
       aurait poussé la liste hors de l'écran avec lui. */
    .cm-app main > section { transition: margin-left .25s cubic-bezier(.22, 1, .36, 1); }
    .cm-app.cm-fiche-open main > section { margin-left: 380px; }

    /* Ces 380 px sont pris à la colonne du plan, et le `xl:` de Tailwind ne le
       sait pas : il ne connaît que la largeur de la fenêtre. Au-delà de 1280 px
       il envoie donc les deux groupes d'outils se poser en absolu dans les
       coins, et réserve au titre la largeur qu'ils occupent — un calcul juste
       sur une colonne pleine, faux sur une colonne amputée.

       Le titre s'y repliait sur trois lignes : `rounded-full` sur une boîte de
       71 px ne donne plus une pastille mais un ovale, le tiret cadratin restait
       orphelin en bout de ligne, et l'ensemble mangeait 135 px de haut (71 de
       pastille, 64 de réserve) là où la hauteur est précisément ce qui manque.

       Les deux groupes repassent donc dans le flux, au-dessus du plan : c'est la
       disposition déjà retenue sous 1280 px, où elle ne gêne personne. Le titre
       récupère toute la colonne, tient sur une ligne, et l'ensemble retombe à
       une soixantaine de pixels.

       Les bornes sont mesurées, non choisies. 1360 px est le seuil de cette
       requête elle-même : en deçà la fiche est une modale, elle ne prend rien à
       la colonne. 1540 px est la largeur à partir de laquelle « CE1-CE2 — PLAN
       02 — NOVEMBRE » tient de nouveau sur une ligne dans ce qui reste. Entre
       les deux, et seulement là, il y a quelque chose à corriger. */
    @media (max-width: 1539.98px) {
        .cm-app.cm-fiche-open .cm-outils-plan       { display: flex; }
        .cm-app.cm-fiche-open .cm-outils-plan > div { position: static; }

        .cm-app.cm-fiche-open .cm-titre-plan {
            padding-left: 0;
            padding-right: 0;
            padding-top: .25rem;      /* pt-1 : la valeur d'avant `xl` */
            margin-bottom: .75rem;    /* mb-3 : plus de coins à dégager */
        }
    }

    /* Deux colonnes de contraintes dans 400 px de large, cela donnait des
       cartes de 170 px : elles repassent sur une seule colonne. */
    .cm-fiche-panel .grid-cols-2 { grid-template-columns: minmax(0, 1fr); }

    /* L'en-tête de la fiche n'a plus à faire 80 px de haut : le panneau reste
       ouvert d'un élève à l'autre, on ne le redécouvre pas à chaque fois. */
    .cm-fiche-panel .p-5 { padding: 12px 14px; }
    .cm-fiche-panel h2.text-xl { font-size: 15px; }

    /* Les en-têtes de section portent un titre et un jeu de filtres côte à
       côte : dans 400 px, le second sortait du panneau. Ils passent à la
       ligne plutôt que d'être coupés.

       Le repli est limité au corps de la fiche : dans l'en-tête, il ferait
       tomber « précédent / suivant / fermer » sur une deuxième ligne. */
    .cm-fiche-panel .overflow-y-auto .flex.items-center.justify-between {
        flex-wrap: wrap;
        gap: 6px;
    }

    /* Sans cela, le titre se replie sur deux lignes pour laisser de la place
       aux filtres — qui débordent quand même. En lui interdisant la coupure,
       ce sont les filtres qui descendent d'une ligne, entiers. */
    .cm-fiche-panel .overflow-y-auto .flex.items-center.justify-between > p {
        white-space: nowrap;
    }

    /* Et sans cela, le groupe de filtres se comprime au lieu de descendre :
       le dernier bouton restait coupé par le bord du panneau. */
    .cm-fiche-panel .overflow-y-auto .flex.items-center.justify-between > div {
        flex: 0 0 auto;
    }
}

/* ---------------------------------------------- fiche élève : l'en-tête */

/* L'en-tête flottait sur le même blanc que le corps : rien ne disait où
   finissait ce qui reste — le nom, la place, les chevrons — et où commençait
   ce qui défile. Un lavis d'accent, éteint vers le bas, l'assied sans ramener
   le bandeau plein de l'ancienne version, qui annonçait « FICHE ÉLÈVE » sur
   quatre-vingts pixels. */
.cm-fiche-entete {
    background-image: linear-gradient(135deg,
        color-mix(in srgb, var(--v2-accent) 22%, var(--v2-surface)),
        color-mix(in srgb, var(--v2-accent-2, var(--v2-accent)) 14%, var(--v2-surface)));
    border-bottom-color: color-mix(in srgb, var(--v2-accent) 30%, var(--v2-line)) !important;
}

/* ------------------------------------------ fiche élève : les alignements */

/* Trois défauts se voyaient d'un coup d'œil sur la fiche, tous dus à des
   éléments qui se calaient chacun sur son propre contenu. */

/* 1. Une hauteur commune à tous les contrôles. « Fille | Garçon | — » ne
      faisait pas la même hauteur que « Petit·e | Grand·e », ni que les
      pastilles de niveau juste en dessous : trois lignes, trois hauteurs. */
.cm-fiche-panel [role="group"] > button,
.cm-fiche-panel .rounded-lg.overflow-hidden > button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding-top: 0;
    padding-bottom: 0;
    line-height: 1;
}

/* Le plancher de hauteur ne vaut qu'au pointeur fin. Au doigt, app.css impose
   44 px à tous les boutons — un plancher plus bas, mais plus spécifique,
   l'aurait emporté et aurait rendu ces contrôles moins atteignables sur
   tablette. Or c'est l'appareil d'usage en classe. */
@media (pointer: fine) {
    .cm-fiche-panel [role="group"] > button,
    .cm-fiche-panel .rounded-lg.overflow-hidden > button {
        min-height: 30px;
    }
}

/* 2. Une gouttière d'ascenseur réservée en permanence dans les deux listes de
      camarades. Sans elle, la colonne de droite se décalait de six pixels dès
      que la liste devenait assez longue pour défiler — et seulement dans
      celle des deux qui défilait. */
.cm-fiche-panel .max-h-36 {
    scrollbar-gutter: stable;
    padding-right: 2px;
}

/* 3. Les pastilles de l'historique débordaient du panneau : un nom à rallonge
      poussait la ligne au-delà du bord droit. */
.cm-fiche-panel span.rounded-full.border {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cm-fiche-panel .flex.items-start.gap-2 > div { min-width: 0; }

/* ------------------------------------------------------------- noms longs */

/* Une classe n'est jamais faite que de « Léa MARTIN » : il y a des particules,
   des doubles noms, des prénoms composés. Partout où le nom était coupé net
   par un `truncate`, il peut désormais se replier sur deux lignes — au-delà,
   l'abréviation reprend ses droits.

   « VANDENBROUCKE-LEMOINE Marie-Charlotte » devient donc deux lignes lisibles
   au lieu de « VANDENBROUCK… », et l'élève reste identifiable sans avoir à
   ouvrir sa fiche. */

/* Dans les places : prénom sur la ligne haute, nom sur la ligne basse.
   Le repli n'a lieu que si la case est assez large — chaque case étant déjà
   un conteneur de requête (`container-type: inline-size`), on le lui demande.
   Sur un téléphone, où une case tombe à 64 px, deux lignes déborderaient :
   l'abréviation y reste la moins mauvaise solution. */
/* 66 px et non 78 : une requête `inline-size` porte sur la boîte de contenu,
   bordure et remplissage déduits. Une case de 87 px n'en mesure que 77 de
   ce point de vue — et le repli ne se déclenchait jamais. */
@container (min-width: 66px) {
    [data-seat] .truncate {
        white-space: normal;
        overflow-wrap: anywhere;
        display: -webkit-box;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 2;
        line-clamp: 2;
        overflow: hidden;
        line-height: 1.12;
    }
}

/* Dans la liste d'élèves : seules les lignes concernées s'agrandissent. */
.drag-source-list p.truncate {
    white-space: normal;
    overflow-wrap: anywhere;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
    line-height: 1.25;
}

/* Dans l'en-tête de la fiche élève : sans plancher de largeur, un nom à
   rallonge poussait les boutons « précédent / suivant / fermer » hors de la
   modale. */
[role="dialog"] .p-5.flex > div:first-child,
[role="dialog"] .p-5.flex > div:first-child > div { min-width: 0; }

[role="dialog"] h2.text-xl {
    overflow-wrap: anywhere;
    line-height: 1.15;
}

/* ------------------------------------------------------------- le tableau */

/* Le tableau de la salle reprend la signature de couleur : c'est le repère
   qui dit dans quel sens se lit le plan, il mérite d'être vu. */
.cm-tableau {
    background-image: var(--v2-grad) !important;
    background-color: transparent !important;
    border-color: transparent !important;
    box-shadow: var(--v2-glow) !important;
}
.cm-tableau span { color: #fff !important; }
.cm-tableau svg { color: rgb(255 255 255 / .6) !important; }

/* ------------------------------------ correction d'un défaut de mode sombre */

/* Trouvé en essayant cet habillage, mais antérieur à lui : la couche sombre
   générée ne traite que les classes de fond pleines. `bg-white/70` et
   `bg-white/80` lui échappent, et restent donc blanches en mode sombre —
   d'où une légende blanche portant un texte gris clair, illisible, sous
   chaque plan de classe. La correction de fond appartient au générateur
   (scripts/build-dark-css.mjs), qui devrait dériver aussi les variantes
   d'opacité ; en attendant, ces deux règles rendent la légende lisible. */
html.dark .bg-white\/70 { background-color: rgb(18 20 42 / .72) !important; }
html.dark .bg-white\/80 { background-color: rgb(18 20 42 / .8) !important; }

/* ------------------------------------------------------ champs et pastilles */

.cm-field {
    border-color: var(--v2-line-strong);
    border-radius: 10px;
    background-color: var(--v2-surface-2);
}
.cm-field:focus {
    border-color: var(--v2-accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--v2-accent) 18%, transparent);
}

/* Les infobulles suivent la même encre que le reste. */
.tooltip-icon::after,
.tooltip-icon-wide::after { background: var(--v2-ink); border-radius: 8px; }

/* ------------------------------------------------- page du compte encadrée */

html.cm-encadre body { background: var(--v2-bg); }
html.cm-encadre .cm-compte-corps { max-width: none; padding: 16px 16px 24px; }

/* -------------------------------------------------------------- animations */

/* Les halos clignotants en ambre deviennent une pulsation plus douce — mais
   elles gardent l'ambre. Les avoir passées à l'indigo d'accent était une
   erreur : ces deux halos désignent la seule chose à faire maintenant, sur
   des cartes elles-mêmes indigo. Un signal de la couleur du décor ne signale
   rien. */
@keyframes v2-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgb(251 191 36 / .65); }
    50%      { box-shadow: 0 0 0 8px rgb(251 191 36 / 0); }
}
.config-pulse, .import-pulse { animation: v2-pulse 2s ease-in-out infinite; }

/* ---------------------------------------------- fenêtre des réglages ---- */

/* Une seule apparence pour toutes les actions ordinaires.
   Elles en avaient sept — indigo pâle, émeraude, bleu, violet, ardoise, un
   dégradé délavé et un rouge encadré — si bien que la couleur ne disait plus
   rien : l'émeraude servait à la fois d'« importer » et d'« export Excel ».
   Elle revient à ce qui mérite d'être signalé, et le reste se ressemble. */
.cm-reglage {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-height: 40px;
    padding: 8px 10px;
    border: 1px solid var(--v2-line-strong);
    border-radius: 10px;
    background: var(--v2-surface);
    color: var(--v2-ink-2);
    font-size: 11px;
    font-weight: 600;
    line-height: 1.15;
    text-align: center;
    transition: background-color .15s, border-color .15s, color .15s;
}

.cm-reglage:hover:not(:disabled) {
    background: var(--v2-accent-soft);
    border-color: var(--v2-accent);
    color: var(--v2-accent);
}
