/**
 * Console d'administration — habillage.
 *
 * Écrite à la main plutôt qu'en utilitaires Tailwind, pour trois raisons qui se
 * sont toutes vérifiées à l'usage :
 *
 *   — le mode sombre est engendré (`scripts/build-dark-css.mjs`) à partir des
 *     classes utilitaires rencontrées, ce qui marche bien pour un bouton et mal
 *     pour une grille de tableau ou un dégradé de graphique. Ici, tout part des
 *     jetons `--v2-*` définis par `app-v2.css` : le sombre suit tout seul,
 *     puisque ce sont les mêmes variables qui changent de valeur ;
 *   — une console est faite d'une dizaine de motifs répétés cent fois (carte,
 *     ligne de tableau, étiquette, jauge). Les décrire une fois coûte moins
 *     cher que de recopier douze utilitaires à chaque occurrence, et surtout
 *     cela leur donne un nom ;
 *   — les graphiques sont du SVG dessiné à la main : leurs couleurs doivent
 *     être lisibles depuis le JavaScript comme depuis la feuille, donc être des
 *     variables CSS.
 *
 * Convention de nommage : `cm-a-` (« administration »), pour ne rien croiser de
 * ce qui existe ailleurs dans le produit.
 */

/* ==========================================================================
   1. Jetons propres à la console
   ========================================================================== */

:root {
    /* Palette des séries de données.
     *
     * Six teintes, choisies pour rester distinguables l'une de l'autre en
     * vision dichromate : on ne passe pas du rouge au vert, on passe du bleu à
     * l'orangé, et les valeurs de luminosité diffèrent d'une série à l'autre —
     * de sorte qu'une capture d'écran en noir et blanc reste lisible. Aucun
     * graphique de cette console ne se lit par la couleur seule : chaque série
     * porte son intitulé, et les infobulles nomment ce qu'elles montrent. */
    --cm-a-serie-1: #6366f1; /* indigo — la mesure principale, partout */
    --cm-a-serie-2: #10b981; /* émeraude — ce qui aboutit, ce qui est validé */
    --cm-a-serie-3: #f59e0b; /* ambre — ce qui attend, ce qui alerte doucement */
    --cm-a-serie-4: #ec4899; /* rose — les seconds rôles */
    --cm-a-serie-5: #06b6d4; /* cyan */
    --cm-a-serie-6: #a855f7; /* violet */

    /* Les tons d'état, séparés de la palette des séries : ils veulent dire
       quelque chose, ils ne servent pas à distinguer. */
    --cm-a-ok:     #059669;
    --cm-a-veille: #d97706;
    --cm-a-alerte: #e11d48;

    /* Le fond des graphiques et leurs repères. Un quadrillage se voit trop vite
       et devient du bruit : il est délibérément à la limite du perceptible. */
    --cm-a-grille:  rgb(20 22 43 / .07);
    --cm-a-curseur: rgb(20 22 43 / .22);

    --cm-a-rail: 252px;
}

html.dark {
    --cm-a-serie-1: #818cf8;
    --cm-a-serie-2: #34d399;
    --cm-a-serie-3: #fbbf24;
    --cm-a-serie-4: #f472b6;
    --cm-a-serie-5: #22d3ee;
    --cm-a-serie-6: #c084fc;

    --cm-a-ok:     #34d399;
    --cm-a-veille: #fbbf24;
    --cm-a-alerte: #fb7185;

    --cm-a-grille:  rgb(234 235 249 / .09);
    --cm-a-curseur: rgb(234 235 249 / .28);
}

/* ==========================================================================
   2. Charpente — rail, bandeau, contenu
   ========================================================================== */

body.cm-a-corps {
    background: var(--v2-bg);
    color: var(--v2-ink);
    min-height: 100vh;
    min-height: 100dvh;
}

.cm-a-shell {
    display: grid;
    grid-template-columns: 1fr;
    min-height: 100vh;
    min-height: 100dvh;
}

@media (min-width: 1024px) {
    .cm-a-shell { grid-template-columns: var(--cm-a-rail) minmax(0, 1fr); }
}

/* --- Rail de navigation --------------------------------------------------- */

.cm-a-rail {
    display: flex;
    flex-direction: column;
    gap: 4px;
    background: var(--v2-surface);
    border-right: 1px solid var(--v2-line);
    padding: 14px 12px;
}

@media (min-width: 1024px) {
    .cm-a-rail {
        position: sticky;
        top: 0;
        height: 100vh;
        height: 100dvh;
        overflow-y: auto;
        overscroll-behavior: contain;
    }
}

/* Sous 1024 px le rail devient un tiroir. Il sort de la gauche plutôt que de
   se replier en accordéon : un menu qui pousse le contenu vers le bas fait
   sauter la lecture, et sur un téléphone on referme d'un geste vers le bord. */
@media (max-width: 1023px) {
    .cm-a-rail {
        position: fixed;
        inset: 0 auto 0 0;
        z-index: 60;
        width: min(84vw, var(--cm-a-rail));
        transform: translateX(-100%);
        transition: transform .22s cubic-bezier(.4, 0, .2, 1);
        box-shadow: var(--v2-shadow-2);
        overflow-y: auto;
    }
    .cm-a-rail[data-ouvert="oui"] { transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    .cm-a-rail { transition: none; }
}

.cm-a-voile {
    position: fixed;
    inset: 0;
    z-index: 55;
    background: rgb(5 7 18 / .5);
    backdrop-filter: blur(2px);
}

.cm-a-marque {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 8px 14px;
    text-decoration: none;
}

.cm-a-marque-texte {
    font-size: 14px;
    font-weight: 800;
    line-height: 1.1;
    letter-spacing: -.02em;
    color: var(--v2-accent);
}

.cm-a-marque-sous {
    display: block;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--v2-ink-3);
    margin-top: 2px;
}

.cm-a-groupe {
    font-size: 10px;
    font-weight: 900;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--v2-ink-3);
    padding: 14px 10px 6px;
}

.cm-a-lien {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 9px 10px;
    border: 0;
    border-radius: 11px;
    background: transparent;
    color: var(--v2-ink-2);
    font-size: 13.5px;
    font-weight: 700;
    text-align: left;
    cursor: pointer;
    transition: background-color .15s, color .15s;
}

.cm-a-lien:hover { background: var(--v2-surface-2); color: var(--v2-ink); }

.cm-a-lien[aria-current="page"] {
    background: var(--v2-accent-soft);
    color: var(--v2-accent);
}

.cm-a-lien-icone {
    flex: none;
    width: 18px;
    height: 18px;
    opacity: .85;
}

/* La pastille de compte à traiter. Elle ne s'affiche que si elle porte un
   nombre : une pastille vide est une décoration, et on cesse de la voir. */
.cm-a-pastille {
    margin-left: auto;
    flex: none;
    min-width: 20px;
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--cm-a-alerte);
    color: #fff;
    font-size: 10px;
    font-weight: 900;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.cm-a-pastille[data-ton="veille"] { background: var(--cm-a-veille); }
.cm-a-pastille[data-ton="calme"]  { background: var(--v2-line-strong); color: var(--v2-ink-2); }

.cm-a-rail-pied {
    margin-top: auto;
    padding-top: 14px;
    border-top: 1px solid var(--v2-line);
}

/* --- Bandeau du haut ------------------------------------------------------ */

.cm-a-entete {
    position: sticky;
    top: 0;
    z-index: 30;
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    padding: 12px 16px;
    background: color-mix(in srgb, var(--v2-surface) 88%, transparent);
    backdrop-filter: blur(10px);
    border-bottom: 1px solid var(--v2-line);
}

@media (min-width: 768px) { .cm-a-entete { padding: 14px 26px; } }

/* Le bandeau sur téléphone : le titre d'abord, les outils dessous.
 *
 * `flex-wrap` était déjà là, mais il ne servait à rien : le bloc du titre est
 * `flex-1 min-w-0`, donc il se comprime jusqu'à zéro au lieu de pousser les
 * boutons à la ligne. Sur un écran de 480 px, les six outils tenaient sur la
 * première ligne et le titre se lisait en colonne, un mot par ligne, dans les
 * 140 px qui restaient.
 *
 * Deux règles suffisent : une largeur minimale au titre, et une base de 100 %
 * aux outils. La rangée d'outils passe alors dessous en entier, ce qui est
 * aussi le bon ordre de lecture — on veut savoir où l'on est avant de savoir
 * ce qu'on peut faire. */
@media (max-width: 767px) {
    .cm-a-entete-titre { flex: 1 1 auto; min-width: 160px; }
    .cm-a-entete-actions { flex: 1 0 100%; }
}

.cm-a-titre {
    font-size: 17px;
    font-weight: 900;
    letter-spacing: -.02em;
    color: var(--v2-ink);
    line-height: 1.15;
}

.cm-a-sous-titre {
    font-size: 11.5px;
    font-weight: 500;
    color: var(--v2-ink-3);
    margin-top: 1px;
}

.cm-a-contenu { padding: 20px 16px 64px; }

@media (min-width: 768px) { .cm-a-contenu { padding: 26px 26px 80px; } }

/* ==========================================================================
   3. Boutons et champs
   ========================================================================== */

.cm-a-bouton {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    padding: 7px 13px;
    border: 1px solid var(--v2-line);
    border-radius: 10px;
    background: var(--v2-surface);
    color: var(--v2-ink-2);
    font-size: 12.5px;
    font-weight: 800;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color .15s, border-color .15s, color .15s, transform .1s;
}

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

.cm-a-bouton:active:not(:disabled) { transform: translateY(1px); }
.cm-a-bouton:disabled { opacity: .45; cursor: not-allowed; }

.cm-a-bouton[data-ton="primaire"] {
    background: var(--v2-accent);
    border-color: transparent;
    color: #fff;
    box-shadow: var(--v2-glow);
}
.cm-a-bouton[data-ton="primaire"]:hover:not(:disabled) {
    background: color-mix(in srgb, var(--v2-accent) 86%, #000);
    color: #fff;
}

.cm-a-bouton[data-ton="danger"] { color: var(--cm-a-alerte); }
.cm-a-bouton[data-ton="danger"]:hover:not(:disabled) {
    border-color: var(--cm-a-alerte);
    color: var(--cm-a-alerte);
    background: color-mix(in srgb, var(--cm-a-alerte) 10%, transparent);
}

.cm-a-bouton[data-ton="danger-plein"] {
    background: var(--cm-a-alerte);
    border-color: transparent;
    color: #fff;
}
.cm-a-bouton[data-ton="danger-plein"]:hover:not(:disabled) {
    background: color-mix(in srgb, var(--cm-a-alerte) 85%, #000);
    color: #fff;
}

.cm-a-bouton[data-ton="veille"] { color: var(--cm-a-veille); }
.cm-a-bouton[data-ton="veille"]:hover:not(:disabled) {
    border-color: var(--cm-a-veille);
    color: var(--cm-a-veille);
    background: color-mix(in srgb, var(--cm-a-veille) 12%, transparent);
}

/* Bouton d'icône carré du bandeau. */
.cm-a-icone {
    width: 34px;
    height: 34px;
    padding: 0;
    flex: none;
}

.cm-a-champ {
    width: 100%;
    padding: 7px 11px;
    border: 1px solid var(--v2-line-strong);
    border-radius: 10px;
    background: var(--v2-surface);
    color: var(--v2-ink);
    font-size: 13px;
    font-weight: 600;
    outline: none;
    transition: border-color .15s, box-shadow .15s;
}

.cm-a-champ::placeholder { color: var(--v2-ink-3); font-weight: 500; }

.cm-a-champ:focus {
    border-color: var(--v2-accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--v2-accent) 18%, transparent);
}

select.cm-a-champ {
    appearance: none;
    padding-right: 28px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='%237a80a2'%3E%3Cpath d='M5.5 7.5 10 12l4.5-4.5' stroke='%237a80a2' stroke-width='1.8' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 7px center;
    background-size: 16px;
}

/* Les puces de filtre rapide : elles disent l'état courant sans qu'on ait à
   déplier un menu, et un filtre actif se voit de loin. */
.cm-a-puce {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 11px;
    border: 1px solid var(--v2-line);
    border-radius: 999px;
    background: var(--v2-surface);
    color: var(--v2-ink-2);
    font-size: 12px;
    font-weight: 800;
    cursor: pointer;
    transition: all .15s;
}

.cm-a-puce:hover { border-color: var(--v2-line-strong); color: var(--v2-ink); }

.cm-a-puce[aria-pressed="true"] {
    background: var(--v2-accent);
    border-color: transparent;
    color: #fff;
}

.cm-a-puce-compte {
    font-size: 10.5px;
    font-weight: 900;
    opacity: .7;
    font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   4. Cartes
   ========================================================================== */

.cm-a-carte {
    background: var(--v2-surface);
    border: 1px solid var(--v2-line);
    border-radius: 16px;
    box-shadow: var(--v2-shadow);
}

.cm-a-carte-tete {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 14px;
    flex-wrap: wrap;
    padding: 15px 18px;
    border-bottom: 1px solid var(--v2-line);
}

.cm-a-carte-titre {
    font-size: 14px;
    font-weight: 900;
    color: var(--v2-ink);
    letter-spacing: -.01em;
}

.cm-a-carte-note {
    font-size: 11.5px;
    font-weight: 500;
    color: var(--v2-ink-3);
    margin-top: 2px;
    max-width: 62ch;
    line-height: 1.5;
}

.cm-a-carte-corps { padding: 18px; }

/* --- Indicateur chiffré --------------------------------------------------- */

.cm-a-kpi {
    position: relative;
    display: block;
    width: 100%;
    text-align: left;
    padding: 15px 16px 13px;
    background: var(--v2-surface);
    border: 1px solid var(--v2-line);
    border-radius: 16px;
    box-shadow: var(--v2-shadow);
    overflow: hidden;
    transition: transform .15s, box-shadow .15s, border-color .15s;
}

button.cm-a-kpi { cursor: pointer; }

button.cm-a-kpi:hover {
    transform: translateY(-2px);
    box-shadow: var(--v2-shadow-2);
    border-color: var(--v2-line-strong);
}

.cm-a-kpi-libelle {
    font-size: 10.5px;
    font-weight: 900;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--v2-ink-3);
}

.cm-a-kpi-valeur {
    font-size: 27px;
    font-weight: 900;
    letter-spacing: -.03em;
    color: var(--v2-ink);
    line-height: 1.05;
    margin-top: 6px;
    font-variant-numeric: tabular-nums;
}

.cm-a-kpi-note {
    font-size: 11.5px;
    font-weight: 500;
    color: var(--v2-ink-3);
    margin-top: 3px;
}

/* La variation. Elle porte une flèche *et* un signe : la couleur seule ne dit
   rien à qui ne la perçoit pas, et « en hausse » n'est pas toujours une bonne
   nouvelle — une hausse des échecs de connexion n'a rien de réjouissant. C'est
   pourquoi le vert et le rouge ne sont pas posés ici mais demandés par
   l'appelant, qui sait, lui, dans quel sens va le bien. */
.cm-a-delta {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    margin-top: 7px;
    padding: 2px 7px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 900;
    font-variant-numeric: tabular-nums;
    background: var(--v2-surface-2);
    color: var(--v2-ink-2);
}

.cm-a-delta[data-sens="bien"] {
    background: color-mix(in srgb, var(--cm-a-ok) 14%, transparent);
    color: var(--cm-a-ok);
}
.cm-a-delta[data-sens="mal"] {
    background: color-mix(in srgb, var(--cm-a-alerte) 14%, transparent);
    color: var(--cm-a-alerte);
}

/* L'esquisse posée au fond de la carte : une tendance à hauteur de coup d'œil,
   sans axes ni chiffres — ceux-ci sont déjà écrits au-dessus. */
.cm-a-kpi-esquisse {
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    height: 38px;
    opacity: .5;
    pointer-events: none;
}

/* ==========================================================================
   5. Tableaux
   ========================================================================== */

.cm-a-table-boite { overflow-x: auto; }

.cm-a-table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    font-size: 13px;
}

.cm-a-table thead th {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--v2-surface-2);
    border-bottom: 1px solid var(--v2-line);
    padding: 9px 12px;
    text-align: left;
    font-size: 10.5px;
    font-weight: 900;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--v2-ink-3);
    white-space: nowrap;
}

.cm-a-table tbody td {
    padding: 10px 12px;
    border-bottom: 1px solid var(--v2-line);
    color: var(--v2-ink-2);
    vertical-align: middle;
}

.cm-a-table tbody tr:last-child td { border-bottom: 0; }
.cm-a-table tbody tr:hover td { background: var(--v2-surface-2); }

.cm-a-table tbody tr[data-choisie="oui"] td {
    background: color-mix(in srgb, var(--v2-accent) 9%, transparent);
}

.cm-a-num { text-align: right; font-variant-numeric: tabular-nums; }

/* Une règle par ligne, avec sa raison dessous. Le tiret vertical tient lieu de
   puce : quatre ronds alignés sur des paragraphes de deux lignes se lisent mal,
   et l'énoncé compte ici autant que la liste. */
.cm-a-liste-regles {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.cm-a-liste-regles li {
    padding-left: 12px;
    border-left: 3px solid var(--v2-line);
}

.cm-a-liste-regles li p:first-child { text-align: left; }

/* L'en-tête d'une colonne de nombres se range à droite comme ses nombres.
   `.cm-a-table thead th` pose `text-align: left` avec deux classes de
   spécificité, et `.cm-a-num` seule ne le renversait pas : les intitulés
   « Ce mois », « Cette année » flottaient à gauche de colonnes dont les
   valeurs se lisaient à droite, et l'œil les rattachait à la mauvaise. */
.cm-a-table thead th.cm-a-num { text-align: right; }

/* Le tableau des compteurs : quatre colonnes de même largeur, sinon
   l'algorithme du navigateur les taille sur le contenu et « Depuis le
   début » s'étire bien au-delà de ses quatre chiffres. */
.cm-a-table-compteurs th.cm-a-num { width: 17%; }

/* En-tête cliquable. La flèche occupe sa place même éteinte : sans cela, la
   colonne se décale au premier clic et les autres avec elle. */
.cm-a-tri {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    border: 0;
    background: none;
    padding: 0;
    font: inherit;
    color: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
    cursor: pointer;
}

.cm-a-tri:hover { color: var(--v2-ink); }

.cm-a-tri-fleche {
    width: 9px;
    font-size: 9px;
    opacity: 0;
    transition: opacity .15s;
}

.cm-a-tri[aria-sort="ascending"] .cm-a-tri-fleche,
.cm-a-tri[aria-sort="descending"] .cm-a-tri-fleche { opacity: 1; }
.cm-a-tri[aria-sort="ascending"],
.cm-a-tri[aria-sort="descending"] { color: var(--v2-accent); }

/* La barre d'actions groupées, qui n'existe qu'une fois quelque chose de
   coché. Elle vient du bas de la fenêtre plutôt que du haut du tableau : la
   sélection se fait en descendant, et une barre en haut de page serait déjà
   hors de vue au moment où l'on veut agir. */
.cm-a-lot {
    position: sticky;
    bottom: 12px;
    z-index: 20;
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin: 12px 14px 0;
    padding: 10px 14px;
    border-radius: 14px;
    background: var(--v2-ink);
    color: #fff;
    box-shadow: var(--v2-shadow-2);
}

html.dark .cm-a-lot { background: var(--v2-surface); border: 1px solid var(--v2-line-strong); }

.cm-a-lot .cm-a-bouton {
    background: rgb(255 255 255 / .1);
    border-color: rgb(255 255 255 / .18);
    color: #fff;
}
.cm-a-lot .cm-a-bouton:hover:not(:disabled) {
    background: rgb(255 255 255 / .2);
    border-color: rgb(255 255 255 / .35);
    color: #fff;
}

html.dark .cm-a-lot .cm-a-bouton {
    background: var(--v2-surface-2);
    border-color: var(--v2-line);
    color: var(--v2-ink-2);
}

.cm-a-lot-compte { font-size: 12.5px; font-weight: 900; margin-right: 2px; }

.cm-a-case {
    width: 16px;
    height: 16px;
    accent-color: var(--v2-accent);
    cursor: pointer;
}

/* Un lien à l'intérieur d'une cellule, quand la ligne entière est déjà
   cliquable. Il doit se distinguer de son voisinage sans se déguiser en bouton :
   ce qui l'attend n'est pas la fiche du compte, mais un filtre sur la liste.
   D'où la couleur d'accent et le soulignement au survol, la grammaire du lien.

   Sur mobile, la cible tactile est portée à 32 px de haut : sous le doigt, un
   texte de 12 px ne se vise pas, et l'atteindre par erreur ouvre la fiche —
   l'inverse de ce qu'on voulait. */
.cm-a-lien-cellule {
    display: inline-block;
    max-width: 100%;
    color: var(--v2-accent);
    font-weight: 700;
    text-align: left;
    cursor: pointer;
    background: none;
    border: 0;
    padding: 0;
}
.cm-a-lien-cellule:hover { text-decoration: underline; }
.cm-a-lien-cellule:focus-visible {
    outline: 2px solid var(--v2-accent);
    outline-offset: 2px;
    border-radius: 4px;
}

@media (max-width: 1023px) {
    .cm-a-lien-cellule { min-height: 32px; display: inline-flex; align-items: center; }
}

/* ==========================================================================
   6. Étiquettes, jauges, listes
   ========================================================================== */

.cm-a-etiquette {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 7px;
    border-radius: 7px;
    border: 1px solid transparent;
    font-size: 10px;
    font-weight: 900;
    letter-spacing: .04em;
    text-transform: uppercase;
    white-space: nowrap;
}

.cm-a-etiquette[data-ton="ok"] {
    background: color-mix(in srgb, var(--cm-a-ok) 13%, transparent);
    border-color: color-mix(in srgb, var(--cm-a-ok) 28%, transparent);
    color: var(--cm-a-ok);
}
.cm-a-etiquette[data-ton="veille"] {
    background: color-mix(in srgb, var(--cm-a-veille) 15%, transparent);
    border-color: color-mix(in srgb, var(--cm-a-veille) 30%, transparent);
    color: var(--cm-a-veille);
}
.cm-a-etiquette[data-ton="alerte"] {
    background: color-mix(in srgb, var(--cm-a-alerte) 13%, transparent);
    border-color: color-mix(in srgb, var(--cm-a-alerte) 28%, transparent);
    color: var(--cm-a-alerte);
}
.cm-a-etiquette[data-ton="accent"] {
    background: var(--v2-accent-soft);
    border-color: color-mix(in srgb, var(--v2-accent) 25%, transparent);
    color: var(--v2-accent);
}
.cm-a-etiquette[data-ton="neutre"] {
    background: var(--v2-surface-2);
    border-color: var(--v2-line);
    color: var(--v2-ink-3);
}

/* Pastille de présence. */
.cm-a-point {
    flex: none;
    width: 8px;
    height: 8px;
    border-radius: 999px;
    background: var(--v2-line-strong);
}

.cm-a-point[data-en-ligne="oui"] {
    background: var(--cm-a-ok);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--cm-a-ok) 22%, transparent);
}

/* Ligne « libellé — valeur ». L'unité de base des panneaux de détail. */
.cm-a-ligne {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    padding: 5px 0;
    border-bottom: 1px dashed var(--v2-line);
}

.cm-a-ligne:last-child { border-bottom: 0; }

.cm-a-ligne-cle {
    font-size: 12px;
    font-weight: 700;
    color: var(--v2-ink-3);
    flex: none;
}

.cm-a-ligne-valeur {
    font-size: 12.5px;
    font-weight: 800;
    color: var(--v2-ink);
    text-align: right;
    overflow-wrap: anywhere;
}

/* Jauge classée : un intitulé, une valeur, une barre proportionnelle. */
.cm-a-jauge + .cm-a-jauge { margin-top: 11px; }

.cm-a-jauge-tete {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 5px;
}

.cm-a-jauge-nom {
    font-size: 12px;
    font-weight: 700;
    color: var(--v2-ink-2);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cm-a-jauge-valeur {
    font-size: 12px;
    font-weight: 900;
    color: var(--v2-ink);
    font-variant-numeric: tabular-nums;
    flex: none;
}

.cm-a-jauge-piste {
    height: 7px;
    border-radius: 999px;
    background: var(--v2-surface-2);
    overflow: hidden;
}

.cm-a-jauge-remplissage {
    height: 100%;
    border-radius: 999px;
    background: linear-gradient(90deg,
        var(--cm-a-serie-1),
        color-mix(in srgb, var(--cm-a-serie-1) 55%, var(--cm-a-serie-6)));
    transition: width .5s cubic-bezier(.22, 1, .36, 1);
}

.cm-a-jauge-note {
    font-size: 10.5px;
    font-weight: 500;
    color: var(--v2-ink-3);
    margin-top: 3px;
}

/* ==========================================================================
   7. Graphiques
   ========================================================================== */

.cm-a-graphe { position: relative; width: 100%; }

.cm-a-graphe svg { display: block; width: 100%; height: auto; overflow: visible; }

.cm-a-grille-trait {
    stroke: var(--cm-a-grille);
    stroke-width: 1;
    shape-rendering: crispEdges;
}

.cm-a-axe-texte {
    font-size: 10px;
    font-weight: 700;
    fill: var(--v2-ink-3);
}

.cm-a-serie-trait {
    fill: none;
    stroke-width: 2.25;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* La période précédente : même forme, tracée en pointillé et à demi effacée.
   Une seconde couleur pleine ferait croire à une seconde mesure, alors qu'il
   s'agit de la même vue à un autre moment. */
.cm-a-serie-fantome {
    fill: none;
    stroke-width: 1.75;
    stroke-dasharray: 3 4;
    opacity: .45;
}

.cm-a-curseur-trait {
    stroke: var(--cm-a-curseur);
    stroke-width: 1;
    stroke-dasharray: 3 3;
}

.cm-a-point-actif {
    stroke: var(--v2-surface);
    stroke-width: 2.5;
}

/* Infobulle des graphiques. Positionnée en JavaScript, donc en absolu dans le
   conteneur ; `pointer-events: none` pour qu'elle ne se dérobe pas sous le
   curseur qui la fait apparaître. */
.cm-a-bulle {
    position: absolute;
    z-index: 10;
    min-width: 118px;
    padding: 8px 10px;
    border-radius: 10px;
    background: var(--v2-ink);
    color: #fff;
    font-size: 11.5px;
    font-weight: 700;
    line-height: 1.45;
    box-shadow: var(--v2-shadow-2);
    pointer-events: none;
    opacity: 0;
    transform: translate(-50%, -112%);
    transition: opacity .12s;
}

html.dark .cm-a-bulle { background: #05070f; border: 1px solid var(--v2-line-strong); }

.cm-a-bulle[data-visible="oui"] { opacity: 1; }

.cm-a-bulle-date {
    font-size: 10px;
    font-weight: 900;
    letter-spacing: .06em;
    text-transform: uppercase;
    opacity: .65;
    margin-bottom: 3px;
}

.cm-a-bulle-ligne {
    display: flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
}

.cm-a-bulle-pastille {
    width: 7px;
    height: 7px;
    border-radius: 2px;
    flex: none;
}

.cm-a-bulle-valeur { margin-left: auto; font-weight: 900; font-variant-numeric: tabular-nums; }

/* Légende. */
.cm-a-legende {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 16px;
    margin-top: 10px;
}

.cm-a-legende-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 11.5px;
    font-weight: 700;
    color: var(--v2-ink-2);
    background: none;
    border: 0;
    padding: 0;
    cursor: pointer;
}

.cm-a-legende-item[aria-pressed="false"] { opacity: .38; }

.cm-a-legende-marque { width: 10px; height: 10px; border-radius: 3px; flex: none; }

/* Table de chaleur des cohortes. */
.cm-a-chaleur-case {
    padding: 6px 4px;
    text-align: center;
    font-size: 11px;
    font-weight: 800;
    border-radius: 6px;
    font-variant-numeric: tabular-nums;
    color: var(--v2-ink);
}

/* ==========================================================================
   8. Squelettes de chargement
   ========================================================================== */

/* Un panneau vide pendant deux secondes se lit comme un panneau cassé. Le
   squelette dit « ça arrive », et surtout il dit *quelle forme* ça aura — la
   page ne saute donc pas au moment où les données se posent. */
.cm-a-squelette {
    border-radius: 8px;
    background: linear-gradient(
        90deg,
        var(--v2-surface-2) 0%,
        color-mix(in srgb, var(--v2-line) 60%, var(--v2-surface-2)) 50%,
        var(--v2-surface-2) 100%);
    background-size: 200% 100%;
    animation: cm-a-luire 1.4s ease-in-out infinite;
}

@keyframes cm-a-luire {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

@media (prefers-reduced-motion: reduce) {
    .cm-a-squelette { animation: none; }
}

/* ==========================================================================
   9. Messages empilés
   ========================================================================== */

.cm-a-messages {
    position: fixed;
    z-index: 90;
    right: 14px;
    bottom: 14px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    width: min(370px, calc(100vw - 28px));
    pointer-events: none;
}

.cm-a-message {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 11px 13px;
    border-radius: 13px;
    border: 1px solid var(--v2-line);
    background: var(--v2-surface);
    box-shadow: var(--v2-shadow-2);
    font-size: 13px;
    font-weight: 600;
    color: var(--v2-ink);
    pointer-events: auto;
    animation: cm-a-entrer .22s cubic-bezier(.22, 1, .36, 1);
}

@keyframes cm-a-entrer {
    from { opacity: 0; transform: translateY(10px) scale(.98); }
    to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    .cm-a-message { animation: none; }
}

.cm-a-message[data-ton="succes"] { border-left: 3px solid var(--cm-a-ok); }
.cm-a-message[data-ton="erreur"] { border-left: 3px solid var(--cm-a-alerte); }
.cm-a-message[data-ton="veille"] { border-left: 3px solid var(--cm-a-veille); }
.cm-a-message[data-ton="info"]   { border-left: 3px solid var(--v2-accent); }

.cm-a-message-fermer {
    margin-left: auto;
    flex: none;
    border: 0;
    background: none;
    color: var(--v2-ink-3);
    font-size: 15px;
    line-height: 1;
    cursor: pointer;
    padding: 0 2px;
}

/* ==========================================================================
   10. Fenêtres modales et palette
   ========================================================================== */

.cm-a-voile-modale {
    position: fixed;
    inset: 0;
    z-index: 80;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: 5vh 14px 14px;
    background: rgb(5 7 18 / .55);
    backdrop-filter: blur(3px);
    overflow-y: auto;
}

.cm-a-modale {
    position: relative;
    width: 100%;
    background: var(--v2-surface);
    border: 1px solid var(--v2-line);
    border-radius: 18px;
    box-shadow: var(--v2-shadow-2);
    animation: cm-a-modale-entrer .18s cubic-bezier(.22, 1, .36, 1);
}

@keyframes cm-a-modale-entrer {
    from { opacity: 0; transform: translateY(-8px) scale(.985); }
    to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    .cm-a-modale { animation: none; }
}

.cm-a-modale-tete {
    position: sticky;
    top: 0;
    z-index: 2;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 14px;
    padding: 16px 18px;
    background: var(--v2-surface);
    border-bottom: 1px solid var(--v2-line);
    border-radius: 18px 18px 0 0;
}

.cm-a-modale-corps { padding: 18px; }

.cm-a-modale-pied {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    flex-wrap: wrap;
    padding: 14px 18px;
    border-top: 1px solid var(--v2-line);
}

.cm-a-fermer {
    flex: none;
    width: 30px;
    height: 30px;
    border: 0;
    border-radius: 999px;
    background: var(--v2-surface-2);
    color: var(--v2-ink-3);
    font-size: 15px;
    font-weight: 900;
    cursor: pointer;
}

.cm-a-fermer:hover { background: var(--v2-line); color: var(--v2-ink); }

/* --- Palette de commandes ------------------------------------------------- */

.cm-a-palette-champ {
    width: 100%;
    padding: 15px 18px;
    border: 0;
    border-bottom: 1px solid var(--v2-line);
    background: transparent;
    color: var(--v2-ink);
    font-size: 15px;
    font-weight: 600;
    outline: none;
}

.cm-a-palette-liste { max-height: 56vh; overflow-y: auto; padding: 6px; }

.cm-a-palette-groupe {
    padding: 10px 12px 4px;
    font-size: 10px;
    font-weight: 900;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--v2-ink-3);
}

.cm-a-palette-item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 9px 12px;
    border: 0;
    border-radius: 10px;
    background: transparent;
    color: var(--v2-ink-2);
    font-size: 13.5px;
    font-weight: 700;
    text-align: left;
    cursor: pointer;
}

.cm-a-palette-item[data-actif="oui"] { background: var(--v2-accent-soft); color: var(--v2-accent); }

.cm-a-palette-note {
    margin-left: auto;
    font-size: 11px;
    font-weight: 600;
    color: var(--v2-ink-3);
}

/* Touche de clavier, telle qu'on l'écrit dans une aide. */
.cm-a-touche {
    display: inline-block;
    min-width: 19px;
    padding: 1px 5px;
    border: 1px solid var(--v2-line-strong);
    border-bottom-width: 2px;
    border-radius: 5px;
    background: var(--v2-surface-2);
    color: var(--v2-ink-2);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 10.5px;
    font-weight: 700;
    text-align: center;
    line-height: 1.5;
}

/* ==========================================================================
   11. Panneau latéral, onglets et fiche d'un compte
   ========================================================================== */

/* --- Le panneau latéral ---------------------------------------------------
 *
 * Une fiche s'ouvre depuis une liste, et l'on enchaîne presque toujours sur la
 * suivante : « les trois comptes de ce collège », « les cinq inscriptions
 * d'hier ». Une fenêtre centrée masque justement la liste dont on vient, si
 * bien qu'on la referme pour retrouver sa place, puis on rouvre. Collé au bord,
 * le panneau laisse les lignes visibles à gauche.
 *
 * Il occupe toute la hauteur : la tête, les onglets et les actions restent en
 * place, seul le contenu de l'onglet défile. C'est ce qui met les actions à
 * portée sans avoir à descendre deux écrans et demi.
 */
.cm-a-voile-modale[data-variante="panneau"] {
    align-items: stretch;
    justify-content: flex-end;
    padding: 0;
    overflow: hidden;
}

.cm-a-voile-modale[data-variante="panneau"] .cm-a-modale {
    display: flex;
    flex-direction: column;
    height: 100%;
    border-radius: 0;
    border-width: 0 0 0 1px;
    animation: cm-a-panneau-entrer .2s cubic-bezier(.22, 1, .36, 1);
}

.cm-a-voile-modale[data-variante="panneau"] .cm-a-modale-tete,
.cm-a-voile-modale[data-variante="panneau"] .cm-a-fiche-tete { border-radius: 0; }

@keyframes cm-a-panneau-entrer {
    from { opacity: 0; transform: translateX(28px); }
    to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    .cm-a-voile-modale[data-variante="panneau"] .cm-a-modale { animation: none; }
}

/* Sur téléphone, un tiroir de 540 px collé à droite laisserait une bande
   inutilisable à gauche : il prend toute la largeur. `!important` parce que la
   largeur est posée en style en ligne par `ouvrirModale`. */
@media (max-width: 700px) {
    .cm-a-voile-modale[data-variante="panneau"] .cm-a-modale {
        max-width: none !important;
        border-left-width: 0;
    }
}

/* --- Onglets --------------------------------------------------------------- */

.cm-a-onglets {
    display: flex;
    gap: 2px;
    padding: 0 12px;
    background: var(--v2-surface);
    border-bottom: 1px solid var(--v2-line);
    overflow-x: auto;
    scrollbar-width: none;
}

.cm-a-onglets::-webkit-scrollbar { display: none; }

.cm-a-onglet {
    flex: none;
    padding: 11px 10px 9px;
    border: 0;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    background: none;
    color: var(--v2-ink-3);
    font-size: 12.5px;
    font-weight: 800;
    white-space: nowrap;
    cursor: pointer;
}

.cm-a-onglet:hover { color: var(--v2-ink); }

.cm-a-onglet[aria-selected="true"] {
    color: var(--v2-accent);
    border-bottom-color: var(--v2-accent);
}

.cm-a-onglet-panneau { padding: 16px 18px 20px; }
.cm-a-onglet-panneau:focus { outline: none; }

/* Dans un panneau latéral, le contenu de l'onglet est la seule zone qui
   défile ; ailleurs, c'est la fenêtre entière. */
.cm-a-voile-modale[data-variante="panneau"] .cm-a-onglets-vue {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
}

/* --- Tête de fiche --------------------------------------------------------- */

.cm-a-fiche-tete {
    display: flex;
    align-items: flex-start;
    gap: 13px;
    padding: 15px 16px 14px 18px;
    background: var(--v2-surface);
    border-bottom: 1px solid var(--v2-line);
    border-radius: 18px 18px 0 0;
}

.cm-a-avatar {
    flex: none;
    width: 44px;
    height: 44px;
    border-radius: 14px;
    display: grid;
    place-items: center;
    background: var(--v2-accent-soft);
    color: var(--v2-accent);
    font-size: 15px;
    font-weight: 900;
    letter-spacing: .5px;
}

/* Un compte effacé ou suspendu se reconnaît avant d'avoir lu la pastille. */
.cm-a-avatar[data-ton="alerte"] {
    background: color-mix(in srgb, var(--cm-a-alerte) 14%, transparent);
    color: var(--cm-a-alerte);
}

.cm-a-fiche-nom {
    font-size: 16px;
    font-weight: 900;
    letter-spacing: -.01em;
    color: var(--v2-ink);
    line-height: 1.25;
}

.cm-a-fiche-mail {
    font-size: 12.5px;
    font-weight: 600;
    color: var(--v2-ink-3);
    word-break: break-all;
}

.cm-a-fiche-pastilles {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    margin-top: 8px;
}

/* Les deux ou trois chiffres qui comptent, en face du nom. Ils passent sous la
   tête quand la place manque plutôt que d'écraser l'adresse. */
.cm-a-fiche-chiffres {
    display: flex;
    gap: 16px;
    flex-wrap: wrap;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px dashed var(--v2-line);
}

.cm-a-fiche-chiffre-valeur {
    display: block;
    font-size: 17px;
    font-weight: 900;
    letter-spacing: -.02em;
    color: var(--v2-ink);
    font-variant-numeric: tabular-nums;
}

.cm-a-fiche-chiffre-libelle {
    display: block;
    font-size: 10px;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--v2-ink-3);
    margin-top: 1px;
}

/* --- Frise chronologique --------------------------------------------------- */

/* On ne cherche pas « quels appareils », on cherche « depuis quand ça ne marche
   plus » : une liste répond à la première question, une frise à la seconde. */
.cm-a-frise {
    position: relative;
    padding-left: 18px;
}

.cm-a-frise::before {
    content: '';
    position: absolute;
    left: 4px;
    top: 7px;
    bottom: 7px;
    width: 2px;
    border-radius: 2px;
    background: var(--v2-line);
}

.cm-a-frise-item { position: relative; }
.cm-a-frise-item + .cm-a-frise-item { margin-top: 14px; }

.cm-a-frise-puce {
    position: absolute;
    left: -18px;
    top: 5px;
    width: 10px;
    height: 10px;
    border-radius: 999px;
    background: var(--v2-line-strong);
    box-shadow: 0 0 0 3px var(--v2-surface);
}

.cm-a-frise-item[data-vif="oui"] .cm-a-frise-puce { background: var(--cm-a-ok); }

.cm-a-frise-quand {
    font-size: 12px;
    font-weight: 900;
    color: var(--v2-ink);
}

.cm-a-frise-quoi {
    font-size: 12.5px;
    font-weight: 600;
    color: var(--v2-ink-2);
    margin-top: 1px;
}

/* --- Pied de fiche et actions sensibles ------------------------------------ */

.cm-a-fiche-pied {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 12px 18px;
    background: var(--v2-surface);
    border-top: 1px solid var(--v2-line);
    padding-bottom: max(12px, env(safe-area-inset-bottom));
}

.cm-a-fiche-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

/* L'emplacement du lien d'activation attend vide la plupart du temps : sans
   ceci, il ouvrirait un espace au-dessus des boutons pour ne rien montrer. */
.cm-a-fiche-pied > div:empty { display: none; }

/* Repliées, et derrière un intitulé qui annonce la couleur : « Renvoyer la
   validation » et « Supprimer (RGPD) » étaient deux boutons voisins de même
   taille, à un pixel de distance et à un monde d'écart. */
.cm-a-repli {
    border: 1px solid var(--v2-line);
    border-radius: 12px;
    background: var(--v2-surface-2);
}

.cm-a-repli > summary {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 12px;
    font-size: 11.5px;
    font-weight: 800;
    color: var(--cm-a-alerte);
    cursor: pointer;
    list-style: none;
}

.cm-a-repli > summary::-webkit-details-marker { display: none; }
.cm-a-repli > summary::after { content: '▾'; margin-left: auto; font-size: 10px; }
.cm-a-repli[open] > summary::after { content: '▴'; }

.cm-a-repli-corps {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 0 12px 12px;
}

/* ==========================================================================
   12. Divers
   ========================================================================== */

.cm-a-vide {
    padding: 40px 18px;
    text-align: center;
    font-size: 13px;
    font-weight: 600;
    color: var(--v2-ink-3);
}

.cm-a-mono {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 11.5px;
}

.cm-a-detail {
    margin-top: 8px;
    padding: 10px 12px;
    border-radius: 10px;
    background: var(--v2-surface-2);
    border: 1px solid var(--v2-line);
    white-space: pre-wrap;
    overflow-x: auto;
}

/* La barre de navigation du bas, sur téléphone : les cinq rubriques les plus
   consultées, à portée de pouce. Le reste passe par le tiroir. */
.cm-a-barre-bas {
    position: fixed;
    inset: auto 0 0 0;
    z-index: 40;
    display: flex;
    background: color-mix(in srgb, var(--v2-surface) 92%, transparent);
    backdrop-filter: blur(10px);
    border-top: 1px solid var(--v2-line);
    padding-bottom: env(safe-area-inset-bottom);
}

@media (min-width: 1024px) { .cm-a-barre-bas { display: none; } }

.cm-a-barre-bas-item {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    padding: 7px 2px 6px;
    border: 0;
    background: none;
    color: var(--v2-ink-3);
    font-size: 9.5px;
    font-weight: 800;
    cursor: pointer;
}

.cm-a-barre-bas-item[aria-current="page"] { color: var(--v2-accent); }

/* Le contenu ne doit pas finir sous la barre du bas. */
@media (max-width: 1023px) { .cm-a-contenu { padding-bottom: 96px; } }

/* Le focus doit rester visible partout : cette console se pilote au clavier. */
.cm-a-corps :focus-visible {
    outline: 2px solid var(--v2-accent);
    outline-offset: 2px;
    border-radius: 6px;
}

/* ═══════════════════════════════════════════════════════════════════════════
   Assistance — la liste des conversations et le fil
   ═══════════════════════════════════════════════════════════════════════════

   Les couleurs viennent des jetons `--v2-*` et `--cm-a-*`, comme partout dans
   cette feuille, et jamais d'utilitaires Tailwind : le mode sombre de la
   console est bâti sur ces jetons, et un `bg-white` écrit ici resterait blanc
   sur fond sombre sans que rien ne le signale. */

/* --- Un élément de la liste ---------------------------------------------- */

.cm-a-fil-item {
    display: flex;
    flex-direction: column;
    gap: 4px;
    width: 100%;
    padding: 12px 14px;
    text-align: left;
    background: var(--v2-surface);
    border: 1px solid var(--v2-line);
    border-radius: 12px;
    cursor: pointer;
    transition: border-color .12s, background .12s;
}

.cm-a-fil-item:hover { border-color: var(--v2-line-strong); background: var(--v2-surface-2); }

.cm-a-fil-item[data-choisie="oui"] {
    border-color: var(--v2-accent);
    background: var(--v2-accent-soft);
}

.cm-a-fil-item-nom {
    font-size: 13px;
    font-weight: 800;
    color: var(--v2-ink);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Le sujet, coupé à deux lignes : c'est la première phrase d'un message, et
   elle peut faire quatre cents caractères. */
.cm-a-fil-item-sujet {
    font-size: 12px;
    font-weight: 500;
    line-height: 1.4;
    color: var(--v2-ink-2);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.cm-a-fil-item-date {
    font-size: 11px;
    font-weight: 600;
    color: var(--v2-ink-3);
}

/* Un point plein plutôt qu'un chiffre : dans une liste, « il y a du nouveau »
   est la seule information qu'on lit d'un coup d'œil. Le compte exact est dans
   l'infobulle, pour qui le cherche. */
.cm-a-fil-point {
    width: 8px;
    height: 8px;
    flex-shrink: 0;
    border-radius: 999px;
    background: var(--cm-a-alerte);
}

/* --- L'assistance sur téléphone ------------------------------------------
 *
 * On répond à une demande d'assistance depuis un téléphone au moins aussi
 * souvent que depuis un bureau — c'est le lien Discord reçu le soir qui ouvre
 * cet écran. Deux endroits y coûtaient cher en hauteur, c'est-à-dire en
 * défilement avant d'atteindre ce qu'on est venu faire : la rangée d'actions du
 * fil, qui s'empilait sur trois lignes, et les huit réponses toutes prêtes, qui
 * en occupaient quatre. */

/* Le retour à la liste n'a de sens que là où la liste est cachée, c'est-à-dire
   sous le point de bascule des deux colonnes. */
@media (min-width: 1024px) {
    .cm-a-action-retour { display: none; }
}

/* Deux actions par ligne plutôt qu'une, chacune centrée : la rangée passe de
   trois lignes à deux, et les cibles restent larges. */
@media (max-width: 640px) {
    .cm-a-action-fil {
        flex: 1 1 calc(50% - 4px);
        justify-content: center;
        text-align: center;
    }
}

/* Les réponses types : enveloppées au large, une rangée qui défile à
   l'horizontale sur téléphone. Empilées, elles repoussaient le champ de saisie
   sous la ligne de flottaison — or c'est le champ qu'on vient chercher, les
   puces ne sont qu'un raccourci. */
.cm-a-reponses {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
}

@media (max-width: 640px) {
    .cm-a-reponses {
        flex-wrap: nowrap;
        overflow-x: auto;
        padding-bottom: 4px;
        scrollbar-width: thin;
        -webkit-overflow-scrolling: touch;
    }
    .cm-a-reponses > * { flex: 0 0 auto; }

    /* Sans quoi rien ne défile.
     *
     * Une carte est un élément de grille, et un élément de grille vaut
     * `min-width: auto` : il grandit pour contenir son contenu au lieu de le
     * laisser déborder. La rangée de puces élargissait donc la carte entière, et
     * c'est la page qui partait en travers — le fil, la saisie et la vue de
     * l'écran avec elle. Rendre la carte compressible ramène le débordement là
     * où il est traité, c'est-à-dire dans le conteneur qui sait défiler. */
    .cm-a-carte { min-width: 0; }
}

/* --- Le fil de la conversation ------------------------------------------- */

.cm-a-fil {
    display: flex;
    flex-direction: column;
    gap: 10px;
    /* Une hauteur bornée, et le champ de saisie toujours visible dessous : sans
       elle, une conversation de trente messages pousse le champ hors de l'écran
       et l'on répond en aveugle après avoir fait défiler. */
    max-height: min(52vh, 460px);
    overflow-y: auto;
    padding: 14px;
    background: var(--v2-surface-2);
    border: 1px solid var(--v2-line);
    border-radius: 12px;
}

.cm-a-fil-ligne {
    display: flex;
    flex-direction: column;
    gap: 3px;
    max-width: 78%;
}

.cm-a-fil-ligne[data-sens="nous"] { align-self: flex-end; align-items: flex-end; }
.cm-a-fil-ligne[data-sens="eux"]  { align-self: flex-start; align-items: flex-start; }

.cm-a-fil-bulle {
    padding: 9px 13px;
    border-radius: 14px;
    font-size: 13px;
    font-weight: 500;
    line-height: 1.5;
    /* Le texte vient d'un champ libre : les retours à la ligne comptent, et un
       mot de trois cents caractères ne doit pas élargir la carte entière. */
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.cm-a-fil-ligne[data-sens="nous"] .cm-a-fil-bulle {
    background: var(--v2-accent);
    color: #fff;
    border-bottom-right-radius: 5px;
}

.cm-a-fil-ligne[data-sens="eux"] .cm-a-fil-bulle {
    background: var(--v2-surface);
    color: var(--v2-ink);
    border: 1px solid var(--v2-line);
    border-bottom-left-radius: 5px;
}

.cm-a-fil-heure {
    font-size: 10px;
    font-weight: 600;
    color: var(--v2-ink-3);
    padding: 0 4px;
}

.cm-a-fil-vide,
.cm-a-fil-aide {
    font-size: 12px;
    font-weight: 500;
    color: var(--v2-ink-3);
}

.cm-a-fil-vide { text-align: center; padding: 18px 0; }

/* L'accusé de lecture, sous notre dernier message, du côté de nos bulles. */
.cm-a-fil-vu {
    align-self: flex-end;
    margin-top: -6px;
    padding: 0 4px;
    font-size: 10px;
    font-weight: 700;
    color: var(--v2-ink-3);
}

.cm-a-fil-vu[data-etat="lu"] {
    color: var(--v2-accent);
}

/* « Untel écrit… ». Toujours présent dans le DOM et simplement masqué : le
   créer et le détruire toutes les trois secondes ferait sauter la hauteur du
   fil, donc la position de défilement, pendant qu'on lit. */
.cm-a-fil-frappe {
    align-self: flex-start;
    padding: 6px 13px;
    border-radius: 14px;
    border: 1px solid var(--v2-line);
    background: var(--v2-surface);
    font-size: 12px;
    font-weight: 600;
    font-style: italic;
    color: var(--v2-ink-3);
}

/* --- La vue en direct sur l'écran d'un enseignant ------------------------- */

/*
 * Un plan de classe dessiné à partir d'une description, jamais d'une image :
 * des rangs, des états de place et des contraintes — voir
 * `js/admin/vue-directe.js`. Aucun nom n'y arrive, et il n'y a donc aucune
 * règle ici pour en afficher un.
 */
.cm-a-vue {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 12px 14px;
    background: var(--v2-surface-2);
    border: 1px solid var(--v2-line);
    border-radius: 12px;
}

.cm-a-vue-tete {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
}

.cm-a-vue-titre {
    font-size: 12px;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--v2-ink-3);
}

.cm-a-vue-actions {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.cm-a-vue-note {
    font-size: 12px;
    font-weight: 600;
    color: var(--v2-ink-2);
}

.cm-a-vue-resume {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: 0 18px;
}

/* La salle. Les colonnes se partagent la largeur disponible et les cases
   restent carrées : un plan étiré en hauteur ne ressemble plus à ce que
   l'enseignant a sous les yeux, et c'est pourtant la seule chose qu'on lui
   demande de reconnaître. */
.cm-a-vue-grille {
    display: grid;
    gap: 4px;
}

.cm-a-vue-place {
    position: relative;
    aspect-ratio: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    border-radius: 6px;
    border: 1px solid var(--v2-line);
    background: var(--v2-surface);
    overflow: hidden;
}

.cm-a-vue-place[data-etat="occupee"] {
    background: var(--v2-accent-soft);
    border-color: var(--v2-accent);
}

/* Bloquée et allée se distinguent de « libre » autrement que par la couleur :
   l'une est barrée, l'autre n'a pas de bordure du tout. */
.cm-a-vue-place[data-etat="bloquee"] {
    background: repeating-linear-gradient(
        45deg,
        var(--cm-a-grille) 0 4px,
        transparent 4px 8px
    );
    border-style: dashed;
}

.cm-a-vue-place[data-etat="allee"] {
    background: transparent;
    border: none;
}

/* Place imposée à la main. Le trait plein double le trait de l'état : c'est une
   information qui se superpose à lui, pas qui le remplace. */
.cm-a-vue-place[data-fixe="oui"] { outline: 2px solid var(--cm-a-serie-3); outline-offset: -2px; }

/* Une place occupée s'ouvre : elle porte son paramétrage, et c'est lui qu'on
   vient lire quand on demande pourquoi l'algorithme place ainsi. */
.cm-a-vue-place[role="button"] { cursor: pointer; }

.cm-a-vue-place[data-choisie="oui"] {
    outline: 2px solid var(--v2-accent);
    outline-offset: 1px;
}

.cm-a-vue-detail {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-top: 10px;
    padding: 10px 12px;
    border-radius: 10px;
    border: 1px solid var(--v2-line);
    background: var(--v2-surface-2);
}

.cm-a-vue-rang {
    font-size: 12px;
    font-weight: 800;
    line-height: 1;
    color: var(--v2-ink);
}

.cm-a-vue-traits {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 1px;
}

.cm-a-vue-trait {
    font-size: 9px;
    font-weight: 800;
    line-height: 1;
    padding: 1px 2px;
    border-radius: 3px;
    background: var(--v2-surface);
    color: var(--v2-ink-2);
}

.cm-a-vue-trait[data-trait="pap"],
.cm-a-vue-trait[data-trait="vision"] { color: var(--cm-a-alerte); }
.cm-a-vue-trait[data-trait="aesh"]   { color: var(--cm-a-serie-6); }
.cm-a-vue-trait[data-trait="bavard"] { color: var(--cm-a-veille); }

/* Le tableau, en bas comme dans l'application : l'orientation doit être celle
   de l'écran qu'on décrit, sans quoi on donne des indications à l'envers. */
.cm-a-vue-tableau {
    margin-top: 6px;
    padding: 4px 0;
    text-align: center;
    font-size: 10px;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--v2-ink-3);
    background: var(--v2-surface);
    border: 1px solid var(--v2-line);
    border-radius: 6px;
}

/* ==========================================================================
   13. Campagnes — éditeur, compteur, aperçu
   ========================================================================== */

/* L'éditeur de message : une barre d'outils et une zone de saisie, dans le
   même cadre qu'un champ. Ce qu'on y voit n'est pas le rendu final — le
   serveur harmonise la mise en forme à l'envoi — mais il doit s'en approcher
   assez pour qu'un titre ait l'air d'un titre. */
.cm-a-editeur {
    border: 1px solid var(--v2-line-strong);
    border-radius: 12px;
    background: var(--v2-surface);
    overflow: hidden;
    transition: border-color .15s, box-shadow .15s;
}

.cm-a-editeur:focus-within {
    border-color: var(--v2-accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--v2-accent) 18%, transparent);
}

.cm-a-editeur-barre {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 2px;
    padding: 6px 8px;
    border-bottom: 1px solid var(--v2-line);
    background: var(--v2-surface-2);
}

.cm-a-editeur-outil {
    min-width: 30px;
    height: 28px;
    padding: 0 8px;
    border: 1px solid transparent;
    border-radius: 7px;
    background: none;
    color: var(--v2-ink-2);
    font-size: 12px;
    font-weight: 800;
    cursor: pointer;
    transition: background-color .12s, color .12s;
}

.cm-a-editeur-outil:hover {
    background: var(--v2-accent-soft);
    color: var(--v2-accent);
}

.cm-a-editeur-sep {
    width: 1px;
    height: 18px;
    margin: 0 5px;
    background: var(--v2-line-strong);
}

.cm-a-editeur-zone {
    min-height: 300px;
    padding: 16px 18px;
    outline: none;
    font-size: 14px;
    line-height: 1.6;
    color: var(--v2-ink);
    overflow-wrap: anywhere;
}

.cm-a-editeur-zone:empty::before {
    content: attr(data-placeholder);
    white-space: pre-line;
    color: var(--v2-ink-3);
    pointer-events: none;
}

.cm-a-editeur-zone h2 { font-size: 20px; font-weight: 900; margin: 20px 0 10px; letter-spacing: -.01em; }
.cm-a-editeur-zone h3 { font-size: 16px; font-weight: 900; margin: 16px 0 6px; }
.cm-a-editeur-zone p  { margin: 0 0 12px; }
.cm-a-editeur-zone ul, .cm-a-editeur-zone ol { margin: 0 0 12px; padding-left: 24px; }
.cm-a-editeur-zone ul { list-style: disc; }
.cm-a-editeur-zone ol { list-style: decimal; }
.cm-a-editeur-zone li { margin: 0 0 4px; }
.cm-a-editeur-zone a { color: var(--v2-accent); text-decoration: underline; }
.cm-a-editeur-zone a.cta {
    display: inline-block;
    padding: 10px 22px;
    border-radius: 10px;
    background: var(--v2-accent);
    color: #fff;
    font-weight: 800;
    text-decoration: none;
}
.cm-a-editeur-zone blockquote {
    margin: 0 0 12px;
    padding: 10px 14px;
    border-left: 3px solid var(--v2-accent);
    background: var(--v2-surface-2);
    color: var(--v2-ink-2);
    border-radius: 0 8px 8px 0;
}
.cm-a-editeur-zone hr { border: 0; border-top: 1px solid var(--v2-line-strong); margin: 18px 0; }
.cm-a-editeur-zone img { max-width: 100%; height: auto; border-radius: 8px; display: block; margin: 12px 0; }

/* Le compteur de destinataires : un chiffre qu'on regarde avant de cliquer. */
.cm-a-compteur {
    padding: 16px 18px;
    border-radius: 14px;
    background: var(--v2-surface-2);
    border: 1px solid var(--v2-line);
    text-align: center;
}

.cm-a-compteur-valeur {
    font-size: 38px;
    font-weight: 900;
    line-height: 1;
    letter-spacing: -.02em;
    color: var(--v2-accent);
    font-variant-numeric: tabular-nums;
}

.cm-a-compteur-legende {
    margin-top: 4px;
    margin-bottom: 10px;
    font-size: 10.5px;
    font-weight: 900;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--v2-ink-3);
}

/* L'aperçu du message, dans son bac à sable. Le fond est celui de l'email —
   clair quoi qu'il arrive : une boîte de réception ne suit pas notre thème. */
.cm-a-apercu {
    width: 100%;
    height: 68vh;
    border: 1px solid var(--v2-line);
    border-radius: 12px;
    background: #f1f5f9;
}

