/* ==========================================================================
   ARTAWEB — Administration · admin-ecrans.css
   --------------------------------------------------------------------------
   Écrans : Pages, Traductions, Tableau de bord, Blog, Agenda, poignées, onglets.

   CE FICHIER EST UNE PART D'UN TOUT. `admin.css` faisait 8 026 lignes et
   274 Ko : impossible à parcourir, impossible à situer. Il a été DÉCOUPÉ le
   2026-09-09 — découpé, pas réécrit : la concaténation des cinq parts, dans
   l'ordre où adminStylesheetLinks() les charge, redonne l'original CARACTÈRE
   POUR CARACTÈRE. L'audit le demandait dans ces termes : « le découper, oui ;
   le réécrire, non — le risque dépasse largement le gain ».

   L'ORDRE COMPTE. Ces feuilles se surchargent l'une l'autre ; les charger
   dans un autre ordre change le rendu. Elles sont donc listées en UN seul
   endroit : adminStylesheetLinks(), dans includes/admin-assets.php.
   ========================================================================== */

/* =========================================================================
   ADMIN PAGES — refonte : ligne repliable + poignée drag + onglets
   ========================================================================= */

.admin-page { display: block; }

/* Sous-pages : conteneur triable propre (tri « même niveau uniquement »),
   légèrement indenté et relié visuellement au parent. */
.admin-pages__children {
    display: flex;
    flex-direction: column;
    gap: var(--ad-space-3);
    margin: var(--ad-space-3) 0 0 var(--ad-space-5);
    padding-left: var(--ad-space-4);
    /* Même teinte que le rail d'une page : le filet dit « ce qui suit est encore
       du niveau 1 », au lieu d'un gris qui ne se rattachait à rien. */
    border-left: 2px solid color-mix(in srgb, var(--ad-lvl1) 40%, var(--ad-border));
}

/* En-tête : poignée · nom (grandit) · contrôles (à droite). Il ne se clique plus : seul [Réglages] déplie. */
.admin-page-row__head { cursor: default; }

.admin-page-row__drag {
    cursor: grab;
    color: var(--ad-text-mute);
    display: inline-flex;
    flex: 0 0 auto;
    padding: 2px;
}
.admin-page-row__drag:active { cursor: grabbing; }

.admin-page-row__toggle {
    flex: 1 1 auto;
    min-width: 0;
    display: inline-flex;
    align-items: center;
    gap: var(--ad-space-2);
    flex-wrap: wrap;
    background: none;
    border: 0;
    padding: 0;
    margin: 0;
    text-align: left;
    cursor: default;
    font: inherit;
    font-weight: 650;
    color: var(--ad-text);
}
.admin-page-row__toggle code { font-weight: 400; }

/* --- Page DÉPLIÉE ---------------------------------------------------------
   Le chevron pivotait, et c'était tout : une page ouverte restait une carte
   blanche parmi des cartes blanches. Mêmes signaux qu'un composant en édition,
   pour que « ouvert » se reconnaisse partout de la même façon : halo, ombre
   montée d'un cran, en-tête teinté, rail épaissi. */
.admin-page-row.is-open {
    box-shadow: var(--ad-open-ring), var(--ad-shadow-md);
    border-left-width: 7px;
}
.admin-page-row.is-open .admin-page-row__head {
    background: var(--ad-open-bg);
    /* Débordement contrôlé du padding de la carte, pour que la teinte aille
       jusqu'aux bords sans réécrire la structure. */
    margin: calc(var(--ad-space-4) * -1) calc(var(--ad-space-4) * -1) 0;
    padding: var(--ad-space-4);
    border-radius: var(--ad-r-lg) var(--ad-r-lg) 0 0;
}

.admin-page-row__controls {
    display: inline-flex;
    align-items: center;
    gap: var(--ad-space-3);
    flex-wrap: wrap;
    margin-left: auto;
}
.admin-page-row__parent {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: var(--ad-fs-sm);
    color: var(--ad-text-soft);
    white-space: nowrap;
}
.admin-page-row__parent select { width: auto; min-width: 8.5rem; }

/* --- L'ARBRE DE CARTES (chantier 88) ---------------------------------------
   Chaque sous-page se rattache au trait de sa page par un petit trait
   horizontal : l'arbre se lit d'un coup d'œil. */
.admin-pages__children > .admin-page { position: relative; }
.admin-pages__children > .admin-page::before {
    content: "";
    position: absolute;
    top: 1.6rem;
    left: calc(var(--ad-space-4) * -1 - 2px);
    width: var(--ad-space-4);
    border-top: 2px solid color-mix(in srgb, var(--ad-lvl1) 40%, var(--ad-border));
}
/* LES SOUS-PAGES SE REPLIENT (2026-10-20). `hidden` doit gagner sur le `display: flex` du conteneur. */
.admin-pages__children[hidden] { display: none; }
.admin-page-row__branche {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    min-width: 22px;
    min-height: 22px;
    padding: 0;
    border: 0;
    background: none;
    color: var(--ad-text-mute);
    font: inherit;
    font-size: var(--ad-fs-sm);
    cursor: pointer;
}
.admin-page-row__branche:hover { color: var(--ad-text); }
.admin-page-row__branche-chev { display: inline-flex; transition: transform var(--ad-trans) ease; }
.admin-page-row__branche[aria-expanded="false"] .admin-page-row__branche-chev { transform: rotate(-90deg); }
/* « N sous-pages », à côté de l'adresse, quand la branche est repliée. */
.admin-page-row__sous-nb { display: none; }
.admin-page.is-repliee > .admin-page-row .admin-page-row__sous-nb { display: inline-flex; }
/* Tout replier / tout déplier, au-dessus de l'arbre. */
.admin-pages__branches { display: flex; justify-content: flex-end; gap: var(--ad-space-2); margin-bottom: var(--ad-space-3); }

/* Dans les réglages, la page parente vient en tête de « Titre et adresse ». */
.admin-page-panel > .admin-page-row__parent { margin-bottom: var(--ad-space-3); }

/* Le menu « … » : l'aperçu, l'éditeur visuel, l'export, la copie, la suppression. */
.admin-page-menu { position: relative; }
.admin-page-menu > summary { list-style: none; cursor: pointer; font-weight: 700; letter-spacing: .05em; }
.admin-page-menu > summary::-webkit-details-marker { display: none; }
.admin-page-menu__liste {
    position: absolute;
    right: 0;
    top: calc(100% + 4px);
    z-index: 20;
    min-width: 13rem;
    display: flex;
    flex-direction: column;
    padding: var(--ad-space-1);
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-r-md, 8px);
    background: var(--ad-bg);
    box-shadow: var(--ad-shadow-md);
}
.admin-page-menu__liste > a,
.admin-page-menu__liste > button {
    display: flex;
    align-items: center;
    gap: var(--ad-space-2);
    width: 100%;
    padding: 7px var(--ad-space-3);
    border: 0;
    border-radius: 6px;
    background: none;
    font: inherit;
    font-size: var(--ad-fs-sm);
    color: var(--ad-text);
    text-align: left;
    text-decoration: none;
    cursor: pointer;
}
.admin-main .admin-page-menu__liste > a { color: var(--ad-text); }
.admin-page-menu__liste > a:hover,
.admin-page-menu__liste > button:hover { background: var(--ad-bg-sunk); text-decoration: none; }
.admin-page-menu__liste > .is-danger { color: var(--ad-danger, #b91c1c); }

/* Corps déplié : onglets + panneaux. Fond légèrement creusé et rail de rattachement,
   pour que les sections (cartes blanches) se détachent de leur page parente. */
.admin-page-row__body {
    margin-top: var(--ad-space-4);
    /* Le bas valait 0 : la dernière section touchait le bord du fond teinté
       (mesuré au banc d'essai — 0px entre `.admin-page-sections` et le bas de
       `.admin-page-row__body`), et la liste semblait coupée plutôt que finie.
       Le même écart qu'en haut, pas davantage. */
    padding: var(--ad-space-3) 0 var(--ad-space-3) var(--ad-space-3);
    border-top: 1px solid var(--ad-border);
    border-left: 3px solid color-mix(in srgb, var(--ad-lvl1) 35%, var(--ad-border));
    background: var(--ad-bg-alt);
    border-radius: 0 0 0 var(--ad-r-sm);
}
.admin-page-tabs {
    display: flex;
    gap: var(--ad-space-1);
    border-bottom: 1px solid var(--ad-border);
    margin-bottom: var(--ad-space-4);           /* air onglets ↔ contenu */
    flex-wrap: wrap;
}
/* Mêmes valeurs que `.admin-tab` et les ancres de la Charte : voir « UN SEUL
   ONGLET » dans admin-socle.css. */
.admin-page-tab {
    background: none;
    border: 0;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    padding: 7px var(--ad-space-3);
    font: inherit;
    font-size: var(--ad-fs-sm);
    font-weight: 600;
    color: var(--ad-text-mute);
    cursor: pointer;
    transition: color var(--ad-trans) ease, border-color var(--ad-trans) ease;
}
.admin-page-tab:hover { color: var(--ad-text); }
.admin-page-tab.is-active {
    color: var(--ad-accent);
    border-bottom-color: var(--ad-accent);
}

.admin-page-panel { display: none; }
.admin-page-panel.is-active { display: block; }

/* L'ONGLET « MODULE » : séparé des réglages de la page par une barre, avec son pictogramme ; un choix à la fois. */
.admin-page-tabs__sep { align-self: center; width: 1px; height: 1.2em; margin: 0 var(--ad-space-2); background: var(--ad-border); }
.admin-page-tab--module { display: inline-flex; align-items: center; gap: 6px; }
.admin-module-sub[hidden] { display: none; }
.admin-module-choix {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    gap: var(--ad-space-2);
    margin-bottom: var(--ad-space-4);
}
.admin-module-choix__item {
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: var(--ad-space-2);
    align-items: center;
    padding: var(--ad-space-2) var(--ad-space-3);
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-r-sm);
    cursor: pointer;
}
.admin-module-choix__item small { grid-column: 2; color: var(--ad-text-mute); }
.admin-module-choix__item:has(input:checked) { border-color: var(--ad-accent); background: var(--ad-bg-sunk); }

/* Liste explicative dans une carte (puces + interligne lisible). Sert au rappel
   « ce que ce site dépose » des Réglages ; réutilisable partout ailleurs. */
.admin-list {
    margin: var(--ad-space-2) 0;
    padding-left: 1.2em;
    list-style: disc;
}
.admin-list li + li { margin-top: var(--ad-space-2); }
.admin-list li { line-height: 1.55; }

/* Variante FIGÉE : la rangée d'onglets reste sous l'en-tête quand on fait
   défiler le panneau (écran Réglages). Elle déborde jusqu'aux bords de la zone
   de contenu — sinon la bande translucide laisse voir le texte glisser dans
   les marges. (La Charte avait une barre d'ancres jumelle, .design-anchors ;
   elle est passée aux onglets le 2026-10-20.)
   Le fond translucide n'est pas décoratif : sans lui, le contenu défilerait
   VISIBLEMENT derrière les onglets. */
.admin-page-tabs--sticky {
    position: sticky;
    top: var(--ad-header-h);
    z-index: 6;
    background: color-mix(in srgb, var(--ad-bg) 92%, transparent);
    -webkit-backdrop-filter: saturate(180%) blur(8px);
    backdrop-filter: saturate(180%) blur(8px);
    /* Le débord vers le HAUT n'est pas ici : il est accordé plus bas, et
       seulement quand rien ne précède la barre. Voir « LE DÉBORD VERS LE HAUT ». */
    margin: 0 calc(-1 * var(--ad-space-6)) var(--ad-space-5);
    padding: var(--ad-space-1) var(--ad-space-6) 0;
    overflow-x: auto;              /* beaucoup d'onglets sur petit écran */
    flex-wrap: nowrap;
    scrollbar-width: thin;
}
.admin-page-tabs--sticky .admin-page-tab {
    white-space: nowrap;
    padding-bottom: 9px;
}
/* =========================================================================
   LE DÉBORD VERS LE HAUT — LA RÈGLE, ET POURQUOI CELLE-CI APRÈS TROIS AUTRES
   =========================================================================

   Le problème. Une barre collante (les onglets de Réglages et de SEO/GEO, les
   ancres de la Charte) remonte de --ad-space-6 pour épouser le haut de la zone
   de contenu. Quand un message la précède — « Réglages sauvegardés », « Charte
   enregistrée » —, ce débord lui GRIMPE DESSUS : la barre est translucide et en
   z-index 6, le message n'a pas de z-index, on lit donc la confirmation AU
   TRAVERS des onglets. Mesuré le 2026-09-18 sur la Charte : 20 px avalés.

   TROIS CORRECTIFS ONT PRÉCÉDÉ CELUI-CI, ET ILS ONT TOUS CÉDÉ AU MÊME ENDROIT.
     1. `.admin-alert + .admin-tabs-wrap` — dépendait d'une ADJACENCE. Sur
        seo.php un <form> s'intercale : les deux ne sont même pas frères.
     2. `.admin-content:has(> .admin-alert) …--sticky` — dépendait de la
        PLACE DE L'ALERTE, enfant direct. Une alerte emballée échappait.
     3. Aucune ne couvrait `.design-anchors`, qui porte pourtant la même marge
        négative et le même z-index, dans une AUTRE feuille.

   Chacune décrivait une forme du balisage. Le balisage bouge ; la règle casse ;
   on la répare une forme plus loin. Ce n'est pas un bug qui revient, c'est le
   même bug qu'on déplace.

   CE QUI CHANGE ICI, ET C'EST TOUT.
   Le débord n'est plus le DÉFAUT, il est l'EXCEPTION. La marge haute vaut zéro
   dans la déclaration de base ; elle n'est rendue négative que si le bloc
   portant la barre est le PREMIER enfant de la zone de contenu — donc s'il n'y
   a, par construction, rien au-dessus sur quoi grimper.

   Pourquoi c'est solide là où le reste ne l'était pas :
     · on n'interroge NI la nature NI la place de ce qui précède, seulement le
       fait qu'il y ait quelque chose. Un message, un fil d'ariane, un encart à
       venir : tous protégés sans qu'on les nomme ;
     · la profondeur n'entre pas en compte — le descendant est libre. Sur
       seo.php et settings.php la chaîne est form > .admin-tabs-wrap > barre, et
       `.admin-tabs-wrap` n'est même pas premier dans son <form> (un champ caché
       le précède) : un `:first-child` posé sur la barre aurait échoué aussi ;
     · SI UNE FORME INCONNUE APPARAÎT, on perd le débord — un léger blanc en
       haut — au lieu d'avaler un message. Le repli tombe du bon côté, ce qui
       était la vraie erreur des trois versions précédentes.

   La barre d'ancres de la Charte (.design-anchors), jumelle de celle-ci et
   cause du point 3, a disparu le 2026-10-20 : la Charte est passée aux onglets. */
.admin-content > *:first-child .admin-page-tabs--sticky,
.admin-content > .admin-page-tabs--sticky:first-child {
    /* La VARIABLE du rembourrage, jamais la constante : les deux doivent être
       égales à toute largeur, et deux nombres écrits séparément finissent
       toujours par diverger — c'est ce qui cachait la barre sous l'en-tête en
       dessous de 768px. */
    margin-top: calc(-1 * var(--ad-content-pt));
}

/* UN MESSAGE EN TÊTE N'EST PLUS REMONTÉ (2026-10-19). Il l'était à 12 px du
   titre, contre 36 px pour tout le reste : un écran qui s'ouvrait sur un message
   jaune paraissait « collé en haut » (relevé par Patrick). Tous les écrans
   commencent désormais au même rembourrage, message ou non. */
@media (max-width: 900px) {
    /* La zone de contenu a moins de marge : le débord doit suivre. */
    .admin-page-tabs--sticky {
        margin-inline: calc(-1 * var(--ad-space-3));
        padding-inline: var(--ad-space-3);
    }
}

.admin-page-title-field {
    display: flex;
    align-items: center;
    gap: var(--ad-space-2);
}
.admin-page-title-field__lang {
    flex: 0 0 auto;
    font-size: var(--ad-fs-badge);
    font-weight: 700;
    letter-spacing: .06em;
    color: var(--ad-text-mute);
    background: var(--ad-bg-sunk);
    border-radius: var(--ad-r-xs);
    padding: 3px 7px;
}
/* Slug traduit, DANS le panneau de langue (contrairement au slug de la langue
   par défaut, qui vit sous les onglets car il est commun à toute la page). */
.admin-page-trslug {
    margin-top: var(--ad-space-3);
    padding-top: var(--ad-space-3);
    border-top: 1px dashed var(--ad-border);
}
.admin-page-trslug__field {
    display: flex;
    align-items: center;
    gap: var(--ad-space-2);
    white-space: nowrap;   /* « Slug DE » ne se coupe pas en deux lignes */
}
.admin-page-trslug__field .admin-form__input { flex: 1 1 auto; }

.admin-page-slug-row {
    display: flex;
    align-items: center;
    gap: var(--ad-space-3);
    flex-wrap: wrap;
    margin-top: var(--ad-space-3);
    padding-top: var(--ad-space-3);
    border-top: 1px dashed var(--ad-border);
}
.admin-page-slug-row__field {
    display: flex;
    align-items: center;
    gap: var(--ad-space-2);
    white-space: nowrap;   /* « Slug FR (URL) » tient sur une ligne */
    font-size: var(--ad-fs-sm);
    color: var(--ad-text-soft);
}
.admin-page-slug-row__field input { width: auto; min-width: 12rem; }

@media (max-width: 640px) {
    .admin-page-row__controls { margin-left: 0; width: 100%; }
    .admin-page-row__parent select { min-width: 0; }
}

/* ----------------------------------------------------------
   Indicateur d'enregistrement global (feedback auto-save)
   Bandeau flottant discret en bas à droite, piloté par
   window.AdminSave (admin.js) : saving / saved / error.
   ---------------------------------------------------------- */
.save-status {
    position: fixed;
    right: 20px;
    bottom: 20px;
    z-index: 1000;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px;
    border-radius: var(--ad-r-pill);
    font-size: var(--ad-fs-sm);
    font-weight: 600;
    background: var(--ad-surface);
    color: var(--ad-text);
    border: 1px solid var(--ad-border);
    box-shadow: var(--ad-shadow-md);
    opacity: 0;
    transform: translateY(6px);
    pointer-events: none;
    /* Caché, il sort aussi du clavier (audit du 2026-10-23, TAB-12) : son bouton d'action (« Rester connecté »)
       restait, invisible, au bout du parcours. `visibility` bascule après le fondu. */
    visibility: hidden;
    transition: opacity var(--ad-trans) ease, transform var(--ad-trans) ease, visibility 0s linear var(--ad-trans);
}
.save-status.is-visible { opacity: 1; transform: translateY(0); visibility: visible; transition: opacity var(--ad-trans) ease, transform var(--ad-trans) ease, visibility 0s; }

.save-status__icon { position: relative; width: 14px; height: 14px; flex: 0 0 auto; }

/* En cours : spinner */
.save-status--saving { color: var(--ad-text-soft); }
.save-status--saving .save-status__icon {
    border: 2px solid var(--ad-border);
    border-top-color: var(--ad-accent);
    border-radius: 50%;
    animation: save-spin .6s linear infinite;
}
@keyframes save-spin { to { transform: rotate(360deg); } }

/* Enregistré : pastille verte + coche */
.save-status--saved { color: var(--ad-success); border-color: #bfe0cd; }
.save-status--saved .save-status__icon { border-radius: 50%; background: var(--ad-success); }
.save-status--saved .save-status__icon::after {
    content: '';
    position: absolute;
    left: 5px; top: 2px;
    width: 3px; height: 7px;
    border: solid #fff;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}

/* Échec : pastille rouge + point d'exclamation */
/* « Enregistré, mais… » — ni succès muet, ni erreur. Le texte est plus long
   qu'un « Enregistré » : on laisse la bulle respirer. */
.save-status--notice {
    color: var(--ad-warn);
    border-color: #e8d8a8;
    background: var(--ad-warn-sf);
    max-width: min(38rem, calc(100vw - 3rem));
    text-align: left;
    line-height: 1.35;
}
.save-status--notice .save-status__icon {
    border-radius: 50%;
    background: var(--ad-warn);
    flex: 0 0 auto;
}
/* Les deux `font-size` ci-dessous sont sous le plancher de 12,5 px, et c'est
   voulu : ce n'est pas du texte, c'est un « ! » dessiné dans une pastille de
   14 px. Le porter à 12,5 le ferait déborder de son rond. Cf. --ad-fs-badge. */
.save-status--notice .save-status__icon::after {
    content: '!';
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 10px;
    font-weight: 700;
}
.save-status--error { color: var(--ad-danger); border-color: #f2c6c2; background: var(--ad-danger-sf); }
.save-status--error .save-status__icon { border-radius: 50%; background: var(--ad-danger); }
.save-status--error .save-status__icon::after {
    content: '!';
    position: absolute;
    inset: 0;
    color: #fff;
    font-size: 11px;
    font-weight: 700;
    line-height: 14px;
    text-align: center;
}

/* Un message d'échec porte désormais sa RAISON (« Ce nom existe déjà ») :
   il a la même largeur de lecture que l'avertissement. */
.save-status--error {
    max-width: min(38rem, calc(100vw - 3rem));
    text-align: left;
    line-height: 1.35;
}

/* Un message à lire reste jusqu'à ce qu'on le ferme (chantier 51) : il reçoit
   donc les clics — le bandeau éphémère, lui, les laisse passer à la page. */
.save-status.is-persistent { pointer-events: auto; padding-right: 6px; }
/* Chantier 55 : un message qui propose un geste (« Rester connecté »). */
.save-status__action { margin-left: .75rem; flex-shrink: 0; white-space: nowrap; }

.save-status__close {
    flex: 0 0 auto;
    align-self: flex-start;
    width: 28px;
    height: 28px;
    margin: -4px 0 -4px 4px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: inherit;
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
    opacity: .7;
}
.save-status__close[hidden] { display: none; }
.save-status__close:hover { opacity: 1; background: rgba(0, 0, 0, .07); }
.save-status__close:focus-visible { opacity: 1; outline: 2px solid currentColor; outline-offset: 1px; }

@media (prefers-reduced-motion: reduce) {
    .save-status--saving .save-status__icon { animation: none; }
}

/* ============================================================
   Audit des traductions (admin/translations.php)
   ============================================================ */
.admin-i18n__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--ad-space-4);
    flex-wrap: wrap;
}
.admin-i18n__head h2,
.admin-i18n__head h3 { margin: 0; display: flex; align-items: center; gap: var(--ad-space-2); font-size: var(--ad-fs-lg, 1.05rem); }
.admin-i18n__head code {
    font-size: var(--ad-fs-sm);
    background: var(--ad-bg-sunk);
    padding: 2px 7px;
    border-radius: var(--ad-r-xs);
}
.admin-i18n__score { color: var(--ad-text-soft); font-size: var(--ad-fs-sm); }
.admin-i18n__score strong { color: var(--ad-danger); font-size: 1.25em; }
.admin-i18n__done { color: var(--ad-success); font-weight: 700; }

.admin-i18n__bar {
    position: relative;
    height: 8px;
    background: var(--ad-bg-sunk);
    border-radius: var(--ad-r-pill);
    overflow: hidden;
    margin: var(--ad-space-3) 0 var(--ad-space-1);
}
.admin-i18n__bar-fill {
    display: block;
    height: 100%;
    border-radius: var(--ad-r-pill);
    transition: width var(--ad-trans, .25s) ease;
    background: var(--ad-accent);
}
.admin-i18n__bar-fill.is-complete { background: var(--ad-success); }
.admin-i18n__bar-fill.is-high     { background: var(--ad-success); }
.admin-i18n__bar-fill.is-mid      { background: var(--ad-warn); }
.admin-i18n__bar-fill.is-low      { background: var(--ad-danger); }
.admin-i18n__pct {
    margin: 0 0 var(--ad-space-3);
    font-size: var(--ad-fs-sm);
    color: var(--ad-text-mute);
}

.admin-i18n__tools {
    display: flex; align-items: center; gap: var(--ad-space-2);
    margin: var(--ad-space-3) 0 var(--ad-space-2);
}
.admin-i18n__tools .admin-form__hint { margin: 0; }

.admin-i18n__group {
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-r-sm);
    margin-top: var(--ad-space-3);
    background: var(--ad-surface);
}
.admin-i18n__group > summary {
    display: flex;
    align-items: center;
    gap: var(--ad-space-3);
    padding: var(--ad-space-3) var(--ad-space-4);
    cursor: pointer;
    font-weight: 600;
    list-style: none;
}
.admin-i18n__group > summary::-webkit-details-marker { display: none; }
.admin-i18n__group-title { flex: 1 1 auto; }
.admin-i18n__group-count {
    font-size: var(--ad-fs-sm);
    font-weight: 700;
    color: var(--ad-danger);
    background: var(--ad-danger-sf);
    padding: 2px 9px;
    border-radius: var(--ad-r-pill);
}
.admin-i18n__group-link,
.admin-i18n__item-link {
    font-size: var(--ad-fs-sm);
    font-weight: 600;
    color: var(--ad-accent);
    text-decoration: none;
    white-space: nowrap;
}
.admin-i18n__group-link:hover,
.admin-i18n__item-link:hover { text-decoration: underline; }

.admin-i18n__items { margin: 0; padding: 0 0 var(--ad-space-2); list-style: none; }
.admin-i18n__item {
    display: flex;
    align-items: baseline;
    gap: var(--ad-space-3);
    padding: var(--ad-space-2) var(--ad-space-4);
    border-top: 1px solid var(--ad-border);
    flex-wrap: wrap;
}
.admin-i18n__item-label { font-weight: 600; }
.admin-i18n__item-ref {
    color: var(--ad-text-soft);
    font-style: italic;
    flex: 1 1 240px;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.admin-i18n__item-detail {
    font-size: var(--ad-fs-sm);
    color: var(--ad-warn);
    font-weight: 600;
}
.admin-i18n__item-link { margin-left: auto; }

/* LES TEXTES PRÉCIS d'un élément (2026-10-19) : sous la ligne, pleine largeur.
   Le nom du texte tel qu'on le cherche à l'écran, puis le texte lui-même. Pour
   un texte « à revoir » : avant / maintenant / traduction, l'un sous l'autre. */
.admin-i18n__textes {
    flex: 1 1 100%;
    margin: 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: var(--ad-space-2);
}
.admin-i18n__textes > li {
    display: grid;
    gap: 2px;
    padding: var(--ad-space-2) var(--ad-space-3);
    background: var(--ad-bg-sunk);
    border-radius: var(--ad-r-sm);
}
.admin-i18n__texte-nom { font-size: var(--ad-fs-sm); font-weight: 600; color: var(--ad-text-soft); }
.admin-i18n__texte { quotes: "« " " »"; color: var(--ad-text); overflow-wrap: anywhere; }
.admin-i18n__diff { overflow-wrap: anywhere; }
.admin-i18n__diff del { color: var(--ad-danger); background: var(--ad-danger-sf); text-decoration: line-through; padding: 0 2px; border-radius: 2px; }
.admin-i18n__diff ins { color: var(--ad-text); background: color-mix(in srgb, var(--ad-success, #2e7d32) 22%, transparent); text-decoration: none; padding: 0 2px; border-radius: 2px; font-weight: 600; }
.admin-i18n__texte--traduction { color: var(--ad-text-soft); }
/* Dans la traduction, le passage retiré de l'original qu'on y retrouve : c'est là qu'il faut reprendre. */
.admin-i18n__texte--traduction mark { background: color-mix(in srgb, var(--ad-warn, #b26a00) 25%, transparent); color: var(--ad-text); padding: 0 2px; border-radius: 2px; font-weight: 600; }
.admin-i18n__compare {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 4px var(--ad-space-3);
    margin: 4px 0 0;
}
.admin-i18n__compare dt { font-size: var(--ad-fs-sm); color: var(--ad-text-mute); }
.admin-i18n__compare dd { margin: 0; }
@media (max-width: 600px) {
    .admin-i18n__compare { grid-template-columns: 1fr; }
    .admin-i18n__compare dd { margin-bottom: var(--ad-space-2); }
}

/* Petit tag « (optionnel) » à côté d'un label de réglage. */
.admin-form__optional {
    font-weight: 400;
    font-size: var(--ad-fs-sm, .8rem);
    color: var(--ad-text-mute, #99a);
}

/* ============================================================
   Tableau de bord — l'accueil (2026-09-27)
   Le seul fond sombre de l'écran : il tire sur l'accent du site, assombri à
   gauche là où se trouve le texte, pour que le blanc reste lisible quel que
   soit l'accent choisi (un jaune clair compris).
   ============================================================ */
.dash-hello {
    position: relative;
    overflow: hidden;
    margin-bottom: var(--ad-space-5);
    padding: var(--ad-space-6) var(--ad-space-6) var(--ad-space-5);
    border-radius: var(--ad-r-lg);
    color: #fff;
    background:
        radial-gradient(circle at 92% 0%, color-mix(in srgb, var(--ad-accent) 55%, transparent), transparent 55%),
        linear-gradient(120deg, color-mix(in srgb, var(--ad-accent) 22%, #0e1013) 0%, color-mix(in srgb, var(--ad-accent) 45%, #0e1013) 60%, color-mix(in srgb, var(--ad-accent) 70%, #0e1013) 100%);
    box-shadow: var(--ad-shadow-md);
}
.dash-hello__repere {
    margin: 0;
    font-size: var(--ad-fs-label);
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    opacity: .72;
}
/* Deux classes : `body.admin-body h2` (0,1,2) donne sa couleur à tous les titres. */
.dash-hello .dash-hello__salut { margin: var(--ad-space-1) 0 0; font-size: var(--ad-fs-2xl); font-weight: 700; letter-spacing: -.02em; color: #fff; border: 0; padding: 0; }
.dash-hello__phrase {
    margin: var(--ad-space-2) 0 0;
    max-width: 52rem;
    font-size: var(--ad-fs-xl);
    font-weight: 700;
    line-height: 1.3;
    letter-spacing: -.015em;
}
.dash-hello__phrase em { font-style: normal; color: color-mix(in srgb, var(--ad-accent) 35%, #fff); }
.dash-hello__suite { margin: var(--ad-space-2) 0 0; opacity: .8; }
.dash-hello__actions { display: flex; flex-wrap: wrap; gap: var(--ad-space-2); margin-top: var(--ad-space-4); }
body.admin-body .dash-hello .dash-hello__btn {
    background: rgba(255, 255, 255, .12);
    border-color: rgba(255, 255, 255, .24);
    color: #fff;
    box-shadow: none;
}
body.admin-body .dash-hello .dash-hello__btn:hover { background: rgba(255, 255, 255, .22); border-color: rgba(255, 255, 255, .4); color: #fff; }
body.admin-body .dash-hello .dash-hello__btn--plein,
body.admin-body .dash-hello .dash-hello__btn--plein:hover { background: #fff; border-color: #fff; color: #16181d; }
.dash-hello__btn svg { width: 16px; height: 16px; }

/* La file et la santé, côte à côte ; l'une sous l'autre sur écran étroit. */
.dash-focus {
    display: grid;
    grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
    gap: var(--ad-space-5);
    align-items: start;
    margin-bottom: var(--ad-space-5);
}
.dash-focus--seul { grid-template-columns: minmax(0, 1fr); }
.dash-focus > .admin-card { margin-bottom: 0; }
.dash-focus__main { display: flex; flex-direction: column; gap: var(--ad-space-5); min-width: 0; }
.dash-focus__main > .admin-card { margin-bottom: 0; }

/* ============================================================
   Tableau de bord — les chiffres (2026-09-27). Choix : dashboardChiffres().
   Quatre au plus ; le premier est en vedette (fond de l'accent adouci).
   Deux par rangée, sous la file : quatre tuiles tombent en carré, et un
   nombre impair laisse la dernière prendre toute la largeur.
   ============================================================ */
.dash-kpis {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--ad-space-4);
}
.dash-kpi:last-child:nth-child(odd) { grid-column: 1 / -1; }
.dash-kpi {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    padding: var(--ad-space-4) var(--ad-space-5);
    background: var(--ad-bg);
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-r-lg);
    box-shadow: var(--ad-shadow-sm);
    color: var(--ad-text);
    text-decoration: none;
    transition: border-color .12s ease, box-shadow .12s ease, transform .12s ease;
}
.dash-kpi:hover { border-color: var(--ad-border-str); box-shadow: var(--ad-shadow-md); transform: translateY(-1px); text-decoration: none; }
.dash-kpi:focus-visible { outline: 2px solid var(--ad-accent); outline-offset: 2px; box-shadow: 0 0 0 3px var(--ad-focus); }
.dash-kpi--vedette { background: var(--ad-accent-sf); border-color: color-mix(in srgb, var(--ad-accent) 25%, var(--ad-border)); }
.dash-kpi__label {
    font-size: var(--ad-fs-label);
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--ad-text-mute);
}
.dash-kpi__valeur {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 2px var(--ad-space-2);
    font-size: var(--ad-fs-2xl);
    font-weight: 800;
    letter-spacing: -.03em;
    line-height: 1.15;
    overflow-wrap: anywhere;
}
/* La tuile est un lien : sans couleur propre, la valeur hériterait de celle
   des liens de l'administration. Deux classes pour passer `body.admin-body a`. */
.dash-kpi .dash-kpi__valeur { color: var(--ad-text); }
/* Le titre d'un événement est un texte, pas un nombre : plus petit, deux lignes au plus. */
.dash-kpi--evenement .dash-kpi__valeur {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: var(--ad-fs-lg);
    letter-spacing: -.01em;
    margin-top: 4px;
}
.dash-kpi__tendance { font-size: var(--ad-fs-xs); font-weight: 700; letter-spacing: 0; }
.dash-kpi__tendance.is-hausse { color: var(--ad-success); }
.dash-kpi__tendance.is-baisse { color: var(--ad-danger); }
.dash-kpi__note { font-size: var(--ad-fs-xs); color: var(--ad-text-mute); }
.dash-kpi .viz-etincelle,
.dash-kpi .viz-barrettes { display: block; width: 100%; height: 30px; margin-top: auto; padding-top: var(--ad-space-2); overflow: visible; }
.dash-kpi .viz-etincelle polyline { fill: none; stroke: var(--ad-accent); stroke-width: 1.6; stroke-linejoin: round; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.dash-kpi .viz-etincelle circle { display: none; }   /* étirée : le point serait une ellipse */
.dash-kpi .viz-barrettes rect { fill: color-mix(in srgb, var(--ad-accent) 30%, var(--ad-bg)); }
.dash-kpi .viz-barrettes rect.is-dernier { fill: var(--ad-accent); }
.dash-kpi__jauge {
    display: block;
    height: 6px;
    margin-top: auto;
    border-radius: var(--ad-r-pill);
    background: var(--ad-bg-sunk);
    overflow: hidden;
}
.dash-kpi__note + .dash-kpi__jauge { margin-top: var(--ad-space-2); }
.dash-kpi__jauge > span { display: block; height: 100%; border-radius: inherit; background: var(--ad-accent); }
.dash-kpi__jauge.is-plein > span { background: var(--ad-secondary); }

/* ============================================================
   Tableau de bord — le bas de page (2026-09-27) : dernières demandes,
   agenda à venir, contenu en cours, liens rares.
   Chaque ligne est un lien entier : la cible fait toute la largeur.
   ============================================================ */
.dash-bas {
    display: grid;
    grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
    gap: var(--ad-space-5);
    align-items: start;
    margin-bottom: var(--ad-space-5);
}
.dash-bas--seul { grid-template-columns: minmax(0, 1fr); }
.dash-bas > .admin-card,
.dash-bas__cote > .admin-card { margin-bottom: 0; }
.dash-bas__cote { display: flex; flex-direction: column; gap: var(--ad-space-5); min-width: 0; }

.dash-liste { padding: 0; overflow: hidden; }
.dash-liste__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--ad-space-3);
    padding: var(--ad-space-5) var(--ad-space-6) var(--ad-space-3);
}
.dash-liste__head h2 { margin: 0; }
.dash-liste__head a { font-size: var(--ad-fs-xs); font-weight: 600; white-space: nowrap; }
.dash-liste__vide { margin: 0; padding: 0 var(--ad-space-6) var(--ad-space-5); color: var(--ad-text-mute); }
.dash-liste ul { list-style: none; margin: 0; padding: 0; }
.dash-liste li > a {
    display: grid;
    align-items: center;
    gap: var(--ad-space-3);
    padding: var(--ad-space-3) var(--ad-space-6);
    border-top: 1px solid var(--ad-border);
    color: var(--ad-text);
    text-decoration: none;
}
.dash-liste li > a:hover { background: var(--ad-bg-alt); text-decoration: none; }
.dash-liste li > a:focus-visible { outline: 2px solid var(--ad-accent); outline-offset: 2px; box-shadow: inset 0 0 0 3px var(--ad-focus); }
.dash-liste strong { display: block; font-size: var(--ad-fs-sm); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dash-liste small { display: block; font-size: var(--ad-fs-xs); color: var(--ad-text-mute); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dash-liste time { font-size: var(--ad-fs-xs); color: var(--ad-text-mute); white-space: nowrap; text-align: right; }

/* Dernières demandes : initiales, nom, formulaire, moment. */
.dash-demandes li > a { grid-template-columns: 36px minmax(0, 1fr) auto; }
.dash-demandes__avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    background: var(--ad-bg-sunk);
    color: var(--ad-text-soft);
    font-size: var(--ad-fs-xs);
    font-weight: 700;
}
.dash-demandes__texte { min-width: 0; }
.dash-demandes .is-nouvelle .dash-demandes__avatar { background: var(--ad-accent); color: #fff; }
.dash-demandes .is-nouvelle strong::after {
    content: "";
    display: inline-block;
    width: 7px;
    height: 7px;
    margin-left: 7px;
    border-radius: 50%;
    background: var(--ad-accent);
    vertical-align: middle;
}

/* Agenda : pavé de date, titre, heure et remplissage. */
.dash-agenda li > a { grid-template-columns: 46px minmax(0, 1fr); }
.dash-agenda__date {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 5px 0;
    border-radius: var(--ad-r-sm);
    background: var(--ad-bg-sunk);
    line-height: 1.1;
}
.dash-agenda__date b { font-size: var(--ad-fs-lg); font-weight: 800; }
.dash-agenda__date small { font-size: 11px; font-weight: 600; text-transform: uppercase; }
.dash-agenda__texte { min-width: 0; }
.dash-agenda .dash-kpi__jauge { margin-top: 6px; }

/* Contenu en cours : icône, titre, état, moment. */
.dash-contenus li > a { grid-template-columns: 18px minmax(0, 1fr) auto auto; }
.dash-contenus__icone { color: var(--ad-text-mute); display: grid; }
.dash-contenus__icone svg { width: 16px; height: 16px; }
.dash-contenus__titre { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--ad-fs-sm); }

/* « Réglages en un coup d'œil » (2026-10-22) : les douze thèmes en colonnes
   d'au moins 180 px (deux sur téléphone), le nom puis trois ou quatre mots. La pastille dit le ton — vert en
   ordre, orange un geste, gris un choix. Ce qui demande un geste est en tête. */
.dash-reglages { margin-bottom: var(--ad-space-5); }
.dash-reglages .dash-reglages__liste {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    column-gap: var(--ad-space-3);
    padding: 0 var(--ad-space-4) var(--ad-space-3);
}
.dash-reglages li > a {
    grid-template-columns: 9px minmax(0, 1fr);
    align-items: start;
    gap: var(--ad-space-2);
    padding: 6px var(--ad-space-2);
    border-top: 0;
    border-radius: var(--ad-r-sm);
}
.dash-reglages__pastille { width: 9px; height: 9px; margin-top: .35em; border-radius: 50%; background: var(--ad-border-str); }
.dash-reglages .is-ok .dash-reglages__pastille { background: var(--ad-success); }
.dash-reglages .is-alerte .dash-reglages__pastille { background: var(--ad-warn); box-shadow: 0 0 0 3px var(--ad-warn-sf); }
.dash-reglages__texte { min-width: 0; }
.dash-reglages__texte b { display: block; font-size: var(--ad-fs-xs); font-weight: 600; color: var(--ad-text-soft); }
.dash-reglages .dash-reglages__texte small { white-space: normal; }
.dash-reglages .is-alerte b,
.dash-reglages .is-alerte small { color: var(--ad-warn); }

/* « Vos modules » (2026-10-22) : une case par module qui a du contenu, le
   chiffre qui le résume, et ce qui attend. Un module vide n'a pas de case :
   son nom va sur la ligne « Aussi disponibles ». */
.dash-modules { margin-bottom: var(--ad-space-5); }
.dash-modules .dash-modules__grille {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
    gap: var(--ad-space-3);
    padding: 0 var(--ad-space-6) var(--ad-space-5);
}
.dash-modules .dash-module {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
    height: 100%;
    padding: var(--ad-space-3) var(--ad-space-4);
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-r-lg);
    transition: border-color .12s ease, box-shadow .12s ease;
}
.dash-modules .dash-module:hover { border-color: var(--ad-border-str); box-shadow: var(--ad-shadow-sm); }
.dash-modules .dash-module.is-traiter { border-color: color-mix(in srgb, var(--ad-warn) 35%, var(--ad-border)); }
.dash-module__tete { display: flex; align-items: center; gap: var(--ad-space-2); min-width: 0; }
.dash-module__icone { display: grid; color: var(--ad-text-mute); }
.dash-module__icone svg, .dash-module__icone .lt-icon { width: 18px; height: 18px; }
.dash-module__nom { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--ad-fs-sm); font-weight: 600; }
/* Ce qui attend : la pastille, puis la première ligne en clair, sur deux lignes au plus. */
.dash-module__traiter { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; min-width: 0; margin-top: 2px; }
.dash-modules .dash-module__traiter small {
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
    max-width: 100%; white-space: normal; overflow: hidden;
}
.dash-module__chiffre { font-size: var(--ad-fs-xs); color: var(--ad-text-mute); }
.dash-module__chiffre b { font-size: var(--ad-fs-lg); font-weight: 700; color: var(--ad-text); }
.dash-modules .dash-module__eteint { color: var(--ad-text-soft); font-style: italic; }
.dash-modules__endormis {
    margin: 0;
    padding: var(--ad-space-3) var(--ad-space-6);
    border-top: 1px solid var(--ad-border);
    font-size: var(--ad-fs-xs);
    color: var(--ad-text-mute);
}

/* Le pied (2026-10-22) : la version d'Artaweb et la licence, en une ligne
   discrète. Elle remplace le coin Version (carte en haut de page) et les liens
   « Autres écrans ». La licence ne prend de couleur qu'à l'approche de l'échéance. */
.dash-pied {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ad-space-2) var(--ad-space-5);
    margin: 0 0 var(--ad-space-5);
    padding: 0 var(--ad-space-2);
    font-size: var(--ad-fs-xs);
    color: var(--ad-text-mute);
}
.dash-pied a { color: var(--ad-text-mute); text-decoration: none; border-bottom: 1px dotted var(--ad-border-str); }
.dash-pied a:hover { color: var(--ad-text); border-bottom-color: currentColor; }
.dash-pied a.is-warn { color: var(--ad-warn); font-weight: 600; }
.dash-pied a.is-danger { color: var(--ad-danger); font-weight: 600; }

/* ============================================================
   LA SYNTHÈSE D'UN MODULE (2026-10-21) — adminChiffres(), adminATraiter(),
   adminSyntheseListe(), admin-functions.php. Née dans les Galeries photo,
   commune depuis : l'onglet d'accueil de chaque module porte le même habit,
   celui des chiffres et des listes du tableau de bord (dash-kpi, dash-liste).
   Lu de haut en bas par ordre d'urgence : quatre chiffres sur une rangée, ce
   qui attend un geste, puis deux listes courtes côte à côte.
   ============================================================ */
.admin-synthese__chiffres { grid-template-columns: repeat(4, minmax(0, 1fr)); margin-bottom: var(--ad-space-5); }
.admin-synthese__chiffres .dash-kpi:last-child:nth-child(odd) { grid-column: auto; }
/* Le chiffre qui attend un geste : teinté d'orange, comme le compteur de son onglet. */
.dash-kpi--alerte {
    background: var(--ad-warn-sf);
    border-color: color-mix(in srgb, var(--ad-warn) 30%, var(--ad-border));
}
.dash-kpi--alerte .dash-kpi__valeur { color: var(--ad-warn); }
.admin-count--alerte { background: var(--ad-warn-sf); color: var(--ad-warn); }

.admin-synthese__traiter { margin-bottom: var(--ad-space-5); }
.admin-synthese__paire {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--ad-space-5);
    margin-bottom: var(--ad-space-5);
    align-items: start;
}
.admin-synthese__paire > .admin-card { margin-bottom: 0; }

/* Les rangées : un repère (puce, vignette, initiales), le texte, la date ou la flèche. */
.admin-synthese__gestes li > a,
.admin-synthese__liste li > a { grid-template-columns: auto minmax(0, 1fr) auto; }
.admin-synthese__puce { width: 9px; height: 9px; border-radius: 50%; background: var(--ad-text-mute); }
.admin-synthese__puce.is-warn   { background: var(--ad-warn); box-shadow: 0 0 0 3px var(--ad-warn-sf); }
.admin-synthese__puce.is-danger { background: var(--ad-danger); box-shadow: 0 0 0 3px var(--ad-danger-sf); }
.admin-synthese__fleche { color: var(--ad-text-mute); transition: transform var(--ad-trans); }
.admin-synthese__gestes li > a:hover .admin-synthese__fleche { transform: translateX(3px); color: var(--ad-accent); }
.admin-synthese__serein { display: flex; align-items: center; gap: var(--ad-space-2); }
.admin-synthese__serein span {
    display: grid; place-items: center; width: 22px; height: 22px; border-radius: 50%;
    background: var(--ad-success-sf); color: var(--ad-success); font-weight: 700; font-size: var(--ad-fs-xs);
}
.admin-synthese__plus { margin: 0; padding: var(--ad-space-3) var(--ad-space-6); border-top: 1px solid var(--ad-border); font-size: var(--ad-fs-xs); font-weight: 600; }
.admin-synthese__mini {
    display: block; width: 40px; height: 30px; overflow: hidden;
    border-radius: var(--ad-r-xs); background: var(--ad-bg-sunk);
}
.admin-synthese__mini img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Une ligne avec des gestes à droite (« Voir sur le site ») : le lien de la
   ligne garde toute la largeur restante, les gestes restent hors de lui. */
.admin-synthese__liste li.admin-synthese__ligne--actions {
    display: flex; align-items: center; gap: var(--ad-space-3);
    border-top: 1px solid var(--ad-border);
}
.admin-synthese__ligne--actions > a { flex: 1 1 auto; min-width: 0; border-top: 0; }
.admin-synthese__actions { display: flex; flex: 0 0 auto; gap: var(--ad-space-2); padding-right: var(--ad-space-6); }
.admin-synthese__sous-titre { margin-top: calc(-1 * var(--ad-space-2)); }
.admin-synthese__liens { display: inline-flex; flex-wrap: wrap; gap: var(--ad-space-3); }
/* Le repère d'un document (icône), à la taille des vignettes. */
.admin-synthese__icone {
    display: grid; place-items: center; width: 32px; height: 32px; border-radius: var(--ad-r-sm);
    background: var(--ad-accent-sf); color: var(--ad-accent);
}
.admin-synthese__icone.is-manque { background: var(--ad-danger-sf); color: var(--ad-danger); }
.admin-synthese__icone .lt-icon, .admin-synthese__icone svg { width: 16px; height: 16px; }

/* Les initiales d'une personne (adminInitiales()) : la pastille des
   « Dernières demandes » du tableau de bord, en plus petit. */
.admin-initiales {
    display: grid; place-items: center; flex: 0 0 auto;
    width: 32px; height: 32px; border-radius: 50%;
    background: var(--ad-accent-sf); color: var(--ad-accent);
    font-size: var(--ad-fs-xs); font-weight: 700;
}

@media (max-width: 1100px) {
    .dash-bas { grid-template-columns: minmax(0, 1fr); }
    .admin-synthese__chiffres { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .admin-synthese__paire { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 640px) {
    .admin-synthese__actions { padding-right: var(--ad-space-4); }
    .admin-synthese__actions .btn__label { display: none; }
    .dash-liste__head { padding: var(--ad-space-4) var(--ad-space-4) var(--ad-space-2); }
    .dash-liste li > a { padding: var(--ad-space-3) var(--ad-space-4); }
    .dash-liste__vide { padding: 0 var(--ad-space-4) var(--ad-space-4); }
    .dash-modules .dash-modules__grille { padding: 0 var(--ad-space-4) var(--ad-space-4); }
    .dash-modules__endormis { padding-left: var(--ad-space-4); padding-right: var(--ad-space-4); }
    .dash-reglages .dash-reglages__liste { grid-template-columns: repeat(2, minmax(0, 1fr)); padding: 0 var(--ad-space-2) var(--ad-space-3); }
    .dash-contenus li > a { grid-template-columns: 18px minmax(0, 1fr) auto; }
    .dash-contenus time { display: none; }
}

/* ============================================================
   Tableau de bord — la santé du site (2026-09-27). Calcul : dashboardSante().
   ============================================================ */
.dash-sante { padding: var(--ad-space-5) var(--ad-space-6); }
.dash-sante__top { display: flex; align-items: center; gap: var(--ad-space-4); }
.dash-sante__top h2 { margin: 0; border: 0; padding: 0; }
.dash-sante__mot { margin: 2px 0 0; color: var(--ad-text-mute); font-size: var(--ad-fs-sm); }
.dash-sante__anneau {
    --teinte: var(--ad-success);
    flex: none;
    width: 92px;
    height: 92px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    background: conic-gradient(var(--teinte) calc(var(--score) * 1%), var(--ad-bg-sunk) 0);
}
.dash-sante__anneau--warn  { --teinte: #d99a0b; }
.dash-sante__anneau--error { --teinte: var(--ad-danger); }
.dash-sante__anneau > span {
    width: 72px;
    height: 72px;
    border-radius: 50%;
    background: var(--ad-bg);
    display: grid;
    place-content: center;
    text-align: center;
    line-height: 1;
}
.dash-sante__anneau b { font-size: 26px; font-weight: 800; letter-spacing: -.03em; }
.dash-sante__anneau small { font-size: 11px; color: var(--ad-text-mute); margin-top: 3px; }
.dash-sante__liste {
    list-style: none;
    margin: var(--ad-space-4) 0 0;
    padding: 0;
    display: grid;
    gap: 6px;
    font-size: var(--ad-fs-xs);
}
.dash-sante__liste li { display: flex; align-items: center; gap: var(--ad-space-2); color: var(--ad-text-soft); }
.dash-sante__liste li > span[aria-hidden] {
    flex: none;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    font-size: 11px;
    font-weight: 700;
}
.dash-sante__liste .is-ok > span[aria-hidden] { background: var(--ad-success-sf); color: var(--ad-success); }
.dash-sante__liste .is-ko { color: var(--ad-text); font-weight: 600; }
.dash-sante__liste .is-ko > span[aria-hidden] { background: var(--ad-warn-sf); color: var(--ad-warn); }
/* Échecs en tête (2026-10-22) : le bloquant en rouge, le reste en orange ; la ligne
   mène à l'écran qui la règle, ou dit qui la règle. */
.dash-sante__liste .is-bloquant > span[aria-hidden] { background: var(--ad-danger-sf, #fde8e8); color: var(--ad-danger); }
.dash-sante__liste .is-ko { flex-wrap: wrap; }
/* Le libellé prend la place qui reste à côté du « ! » : long, il passait SOUS lui. */
.dash-sante__liste .is-ko > a,
.dash-sante__liste .is-ko > span:not([aria-hidden]) { flex: 1 1 0; min-width: 0; }
.dash-sante__liste .is-ko a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.dash-sante__liste .is-ko a:hover { color: var(--ad-accent); }
.dash-sante__par { flex-basis: 100%; padding-left: calc(18px + var(--ad-space-2)); font-weight: 400; color: var(--ad-text-mute); }
.dash-sante__ok { margin-top: var(--ad-space-3); font-size: var(--ad-fs-xs); }
.dash-sante__ok > summary { cursor: pointer; color: var(--ad-text-mute); }
.dash-sante__ok .dash-sante__liste { margin-top: var(--ad-space-2); }

@media (max-width: 1100px) {
    .dash-focus { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 640px) {
    .dash-kpis { grid-template-columns: minmax(0, 1fr); }
    .dash-hello { padding: var(--ad-space-5) var(--ad-space-4) var(--ad-space-4); }
    .dash-hello .dash-hello__salut { font-size: var(--ad-fs-xl); }
    .dash-hello__phrase { font-size: var(--ad-fs-lg); }
    .dash-sante { padding: var(--ad-space-4); }
}

/* ============================================================
   Tableau de bord — la file « À faire maintenant » (2026-09-26)
   Remplace les bandeaux empilés. Registre : admin/includes/dashboard-data.php.
   La carte n'a pas de marge intérieure : les lignes vont d'un bord à l'autre,
   et le filet de gravité (dégradé à gauche) touche le cadre.
   ============================================================ */
.dash-todo { padding: 0; overflow: hidden; }
.dash-todo__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--ad-space-4);
    flex-wrap: wrap;
    padding: var(--ad-space-5) var(--ad-space-6) var(--ad-space-3);
}
.dash-todo__head h2 { margin: 0; }
.dash-todo__head .admin-muted { font-size: var(--ad-fs-xs); }
.dash-todo__list { list-style: none; margin: 0; padding: 0; }
.dash-todo__item {
    display: grid;
    grid-template-columns: 36px 1fr auto;
    gap: var(--ad-space-4);
    align-items: center;
    padding: var(--ad-space-3) var(--ad-space-6);
    border-top: 1px solid var(--ad-border);
}
.dash-todo__icon {
    width: 36px;
    height: 36px;
    border-radius: var(--ad-r-sm);
    display: grid;
    place-items: center;
}
.dash-todo__icon svg { width: 18px; height: 18px; }
.dash-todo__text { min-width: 0; }
.dash-todo__text strong { display: block; font-size: var(--ad-fs-md); }
.dash-todo__text small { display: block; color: var(--ad-text-mute); font-size: var(--ad-fs-xs); line-height: 1.45; margin-top: 2px; }

/* Les trois niveaux : la couleur de la pastille dit la gravité, le fond teinté
   n'est réservé qu'au bloquant — sinon plus rien ne ressort. */
.dash-todo__item--bloquant { background: linear-gradient(90deg, var(--ad-danger-sf), transparent 65%); }
.dash-todo__item--bloquant .dash-todo__icon { background: var(--ad-danger-sf); color: var(--ad-danger); box-shadow: inset 0 0 0 1px #f2c6c2; }
.dash-todo__item--traiter  .dash-todo__icon { background: var(--ad-warn-sf);   color: var(--ad-warn); }
.dash-todo__item--suggestion .dash-todo__icon { background: var(--ad-bg-sunk); color: var(--ad-text-soft); }

.dash-todo__calme {
    display: flex;
    align-items: center;
    gap: var(--ad-space-2);
    margin: 0;
    padding: var(--ad-space-3) var(--ad-space-6) var(--ad-space-5);
    color: var(--ad-success);
    font-weight: 600;
}
.dash-todo__calme svg { width: 18px; height: 18px; }

.dash-todo__more { border-top: 1px dashed var(--ad-border-str); }

/* Les boutons d'une ligne : l'action, et « Ne plus rappeler » pour un rappel
   masquable (DASHBOARD_RAPPELS_MASQUABLES). Le second reste discret : il écarte,
   il ne règle rien. */
.dash-todo__actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--ad-space-2); }
.dash-todo__rappel { display: contents; margin: 0; }
body.admin-body .dash-todo__masquer { color: var(--ad-text-mute); border-color: transparent; }
body.admin-body .dash-todo__masquer:hover { color: var(--ad-text); border-color: var(--ad-btn-bd); }

/* Un rappel masqué se dit, en une ligne, avec de quoi le réafficher. */
.dash-todo__masque {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--ad-space-2);
    margin: 0;
    padding: var(--ad-space-3) var(--ad-space-6);
    border-top: 1px dashed var(--ad-border-str);
    font-size: var(--ad-fs-xs);
    color: var(--ad-text-mute);
}
.dash-todo__masque svg { width: 15px; height: 15px; flex: none; }
.dash-todo__reafficher {
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    font-weight: 600;
    color: var(--ad-accent);
    text-decoration: underline;
    text-underline-offset: 2px;
    cursor: pointer;
}
.dash-todo__reafficher:hover { color: var(--ad-accent-h); }
.dash-todo__reafficher:focus-visible { outline: 2px solid var(--ad-accent); outline-offset: 2px; box-shadow: 0 0 0 3px var(--ad-focus); border-radius: 3px; }
.dash-todo__more summary {
    cursor: pointer;
    padding: var(--ad-space-3) var(--ad-space-6);
    font-size: var(--ad-fs-xs);
    color: var(--ad-text-mute);
}
.dash-todo__more summary:hover { color: var(--ad-text); }
.dash-todo__more[open] summary { color: var(--ad-text); font-weight: 600; }

@media (max-width: 640px) {
    .dash-todo__head { padding: var(--ad-space-4) var(--ad-space-4) var(--ad-space-2); }
    .dash-todo__item { grid-template-columns: 32px 1fr; padding: var(--ad-space-3) var(--ad-space-4); }
    .dash-todo__actions { grid-column: 2; justify-content: flex-start; }
    .dash-todo__masque { padding-left: var(--ad-space-4); padding-right: var(--ad-space-4); }
    .dash-todo__more summary, .dash-todo__calme { padding-left: var(--ad-space-4); padding-right: var(--ad-space-4); }
}

/* =========================================================================
   BLOG — /admin/blog.php (hub) + /admin/blog-post.php (éditeur d'article)
   ========================================================================= */

/* --- Utilitaires de formulaire partagés ---------------------------------- */
.admin-grid-2 {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: var(--ad-space-4);
}

.admin-checks {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ad-space-2) var(--ad-space-5);
    margin: var(--ad-space-3) 0;
}

.admin-subtitle {
    /* margin-top généreux ET padding-top : le padding ne « collapse » pas avec
       la marge du bloc précédent, l'espace au-dessus est donc toujours réel. */
    margin: var(--ad-rythme-groupe) 0 16px;
    padding-top: 28px;
    padding-bottom: 0;
    border-top: 1px solid var(--ad-border);
    border-bottom: 0;
    /* taille et trait d'accent : admin-socle.css, « TROIS NIVEAUX DE TITRE » (2026-10-22) */
}
.admin-subtitle:first-child {
    margin-top: 0;
    padding-top: 0;
    border-top: 0;
}

.admin-fieldset {
    margin: var(--ad-space-4) 0 0;
    padding: var(--ad-space-3) var(--ad-space-4);
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-r-md);
}
.admin-fieldset > legend {
    padding: 0 var(--ad-space-2);
    font-size: var(--ad-fs-sm);
    font-weight: 600;
    color: var(--ad-text-soft);
}
.admin-fieldset[disabled] { opacity: .6; }

/* Variante « nue » : sert uniquement de conteneur désactivable autour de
   plusieurs cartes (droits insuffisants) — sans cadre ni marge propres. */
.admin-fieldset--plain {
    margin: 0;
    padding: 0;
    border: 0;
}

/* Précision de contexte DANS le titre d'une carte (« page de rubrique »,
   « article ouvert »). Distinct de .admin-card__sub, qui est un sous-titre
   de bloc placé SOUS le titre. */
.admin-card__note {
    margin-left: var(--ad-space-2);
    font-size: var(--ad-fs-sm);
    font-weight: 400;
    color: var(--ad-text-mute);
}
.admin-card__note::before { content: '— '; }


.admin-code {
    padding: var(--ad-space-3);
    background: var(--ad-bg-sunk);
    border-radius: var(--ad-r-sm);
    font-size: var(--ad-fs-sm);
    overflow-x: auto;
}

.admin-inline-form { display: inline-flex; gap: var(--ad-space-1); }

/* --- Filtres de la liste d'articles --------------------------------------- */
.admin-blog-filters {
    align-items: center;
    gap: var(--ad-space-3);
    padding-bottom: var(--ad-space-4);
    margin-bottom: var(--ad-space-4);
    border-bottom: 1px solid var(--ad-border);
}
.admin-blog-filters .admin-form__inline-field input { width: auto; }

/* --- Liste d'articles ----------------------------------------------------- */
.admin-blog-list {
    display: flex;
    flex-direction: column;
    gap: var(--ad-space-2);
}

.admin-blog-row {
    display: flex;
    align-items: center;
    gap: var(--ad-space-3);
    padding: var(--ad-space-2) var(--ad-space-3);
    background: var(--ad-bg);
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-r-md);
    transition: border-color var(--ad-trans) ease, box-shadow var(--ad-trans) ease;
}
.admin-blog-row:hover {
    border-color: var(--ad-border-str);
    box-shadow: var(--ad-shadow-sm);
}

.admin-blog-row__main {
    display: flex;
    align-items: center;
    gap: var(--ad-space-3);
    flex: 1 1 auto;
    min-width: 0;
    color: inherit;
    text-decoration: none;
}

.admin-blog-row__thumb {
    flex: 0 0 auto;
    width: 56px;
    height: 40px;
    border-radius: var(--ad-r-sm);
    overflow: hidden;
    background: var(--ad-bg-sunk);
    display: flex;
    align-items: center;
    justify-content: center;
}
.admin-blog-row__thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.admin-blog-row__thumb-empty { color: var(--ad-text-mute); }

.admin-blog-row__text { min-width: 0; }
.admin-blog-row__title {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.admin-blog-row__main:hover .admin-blog-row__title { color: var(--ad-accent); }

.admin-blog-row__sub {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--ad-space-1) var(--ad-space-2);
    margin-top: 3px;
}
.admin-blog-row__date { font-size: var(--ad-fs-xs); color: var(--ad-text-mute); }

.admin-blog-row__actions {
    display: flex;
    align-items: center;
    gap: var(--ad-space-1);
    flex: 0 0 auto;
}

@media (max-width: 700px) {
    .admin-blog-row { flex-wrap: wrap; }
    .admin-blog-row__actions { width: 100%; justify-content: flex-end; }
}

/* --- Catégories ----------------------------------------------------------- */
.admin-blog-cats, .admin-ev-cats {
    display: flex;
    flex-direction: column;
    gap: var(--ad-space-2);
    margin-bottom: var(--ad-space-4);
}

.admin-blog-cat, .admin-ev-cat {
    background: var(--ad-bg);
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-r-md);
}
.admin-blog-cat.is-dragging, .admin-ev-cat.is-dragging { opacity: .5; }
.admin-blog-cat.is-open, .admin-ev-cat.is-open { border-color: var(--ad-border-str); }

.admin-blog-cat__head, .admin-ev-cat__head {
    display: flex;
    align-items: center;
    gap: var(--ad-space-2);
    padding: var(--ad-space-2) var(--ad-space-3);
}

.admin-blog-cat__drag, .admin-ev-cat__drag {
    flex: 0 0 auto;
    color: var(--ad-text-mute);
    cursor: grab;
    display: inline-flex;
}

.admin-blog-cat__toggle, .admin-ev-cat__toggle {
    display: flex;
    align-items: center;
    gap: var(--ad-space-2);
    flex: 1 1 auto;
    min-width: 0;
    padding: 0;
    background: none;
    border: 0;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
}
.admin-blog-cat__chev, .admin-ev-cat__chev {
    display: inline-flex;
    color: var(--ad-text-mute);
    transition: transform var(--ad-trans) ease;
}
.admin-blog-cat.is-open .admin-blog-cat__chev, .admin-ev-cat.is-open .admin-ev-cat__chev { transform: rotate(180deg); }
.admin-blog-cat__name, .admin-ev-cat__name { font-weight: 600; }

.admin-blog-cat__controls, .admin-ev-cat__controls {
    display: flex;
    align-items: center;
    gap: var(--ad-space-2);
    flex: 0 0 auto;
}

.admin-blog-cat__body, .admin-ev-cat__body {
    padding: var(--ad-space-3) var(--ad-space-4) var(--ad-space-4);
    border-top: 1px solid var(--ad-border);
}

/* --- Boutons personnalisables d'un article -------------------------------- */
.admin-links {
    display: flex;
    flex-direction: column;
    gap: var(--ad-space-3);
    margin-bottom: var(--ad-space-3);
}

.admin-link-row {
    padding: var(--ad-space-3);
    background: var(--ad-bg-alt);
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-r-md);
}

.admin-link-row__grid,
.admin-link-row__labels {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--ad-space-3);
}
.admin-link-row__labels {
    margin-top: var(--ad-space-3);
    padding-top: var(--ad-space-3);
    border-top: 1px dashed var(--ad-border);
}

/* Les champs du répéteur prennent la largeur disponible (le style « inline »
   global fixe une largeur de 6rem, trop étroite pour une URL ou un titre). */
.admin-link-row .admin-form__inline-field {
    flex-direction: column;
    align-items: stretch;
    gap: 3px;
    flex: 1 1 200px;
    min-width: 0;
}

.admin-link-row .admin-form__inline-field > span {
    font-size: var(--ad-fs-xs);
    font-weight: 600;
    color: var(--ad-text-mute);
}
.admin-link-row .admin-form__inline-field input { width: 100%; }
.admin-link-row__labels > .btn { flex: 0 0 auto; }

/* Groupe de cases à cocher nommé (ex. « Informations affichées sous le titre »).
   Sert à lever l'ambiguïté quand deux groupes portent les mêmes libellés dans
   des contextes différents (liste d'articles vs page d'un article). */
.admin-checkgroup {
    margin: 28px 0 0;   /* un groupe : de l'air avant lui (12 px jusqu'au 2026-10-22) */
    padding: 0;
    border: 0;
}
/* Sa légende est un intertitre de groupe : admin-socle.css, « TROIS NIVEAUX DE TITRE ». */
.admin-checkgroup .admin-checks { margin-top: var(--ad-space-2); }
/* Groupe neutralisé (ex. liste de pages du fil d'ariane en portée « toutes les
   pages ») : grisé pour signaler que les cases ne sont pas prises en compte. */
.admin-checkgroup[disabled] { opacity: .45; }
.admin-checkgroup[disabled] .admin-form__check { cursor: not-allowed; }

/* Terme défini par une infobulle (« slug », « bloc », « texte alternatif »…).
   Le soulignement pointillé signale qu'une explication est disponible.
   La bulle s'affiche au survol ET au focus clavier — l'attribut `title` natif,
   lui, est invisible au clavier comme au tactile. Le tabindex="0" posé par
   adminTerm() la rend aussi accessible d'une tape sur mobile.
   Définitions : helpGlossary(), dans admin/includes/help-content.php. */
.admin-term {
    position: relative;
    text-decoration: none;
    border-bottom: 1px dotted currentColor;
    cursor: help;
}
.admin-term:focus-visible {
    outline: 2px solid var(--ad-accent); outline-offset: 2px;
    border-radius: 2px;
    box-shadow: 0 0 0 3px var(--ad-focus);
}
.admin-term__bubble {
    position: absolute;
    inset-inline-start: 0;
    bottom: calc(100% + 7px);
    z-index: 70;
    width: max-content;
    max-width: min(280px, 70vw);
    padding: 8px 10px;
    background: var(--ad-text);
    border-radius: var(--ad-r-sm);
    box-shadow: var(--ad-shadow-md);
    color: #fff;
    /* Ces trois lignes sont indispensables : plusieurs libellés de formulaire
       sont en majuscules espacées, la bulle en hériterait. */
    text-transform: none;
    letter-spacing: 0;
    text-align: left;
    font-size: var(--ad-fs-xs);
    font-weight: 400;
    line-height: 1.45;
    white-space: normal;
    pointer-events: none; /* ne bloque jamais le clic sur ce qu'elle recouvre */
    /* FERMÉE, ELLE N'EXISTE PAS (2026-09-28). Elle était `visibility: hidden` :
       invisible, mais toujours là, absolue et large de 280px à partir du début
       du terme. Un terme près du bord droit poussait donc une boîte invisible
       hors de l'écran, et la page s'élargissait d'autant — /admin/help.php
       mesurait 909px dans une fenêtre de 800, et un téléphone la réduisait
       entière pour la faire tenir. `display: none` la retire de la mise en page.
       Ouverte, js/admin-help.js la mesure (placerBulle()) : au survol ou au
       focus, :hover / :focus l'ont déjà affichée. */
    display: none;
    opacity: 1;
    transform: none;
    transition: opacity .12s, transform .12s;
}
.admin-term:hover .admin-term__bubble,
.admin-term:focus .admin-term__bubble,
.admin-term:focus-within .admin-term__bubble {
    display: block;
}
/* Le fondu d'apparition : l'état de départ d'une bulle qui vient de paraître.
   (La disparition, elle, est immédiate.) */
@starting-style {
    .admin-term:hover .admin-term__bubble,
    .admin-term:focus .admin-term__bubble,
    .admin-term:focus-within .admin-term__bubble {
        opacity: 0;
        transform: translateY(3px);
    }
    .admin-term--flip:hover .admin-term__bubble,
    .admin-term--flip:focus .admin-term__bubble,
    .admin-term--flip:focus-within .admin-term__bubble {
        transform: translateY(-3px);
    }
}
/* Variante pour un terme situé en haut d'une zone : bulle en dessous. */
.admin-term--flip .admin-term__bubble {
    top: calc(100% + 7px);
    bottom: auto;
}
@media (prefers-reduced-motion: reduce) {
    .admin-term__bubble { transition: none; }
}

/* Matrice de droits (permissions.php) : table capacités × profils + interrupteurs */
.perm-table { border-collapse: collapse; width: 100%; min-width: 480px; }
.perm-table th, .perm-table td { padding: 10px 14px; border-bottom: 1px solid var(--ad-border); text-align: center; }
.perm-table thead th { font-size: var(--ad-fs-sm); color: var(--ad-text-mute); font-weight: 600; }
.perm-table tbody th[scope="row"] { text-align: left; font-weight: 600; color: var(--ad-text); white-space: nowrap; }
.perm-table__dev { color: var(--ad-text-mute); }
.perm-locked { display: inline-flex; color: var(--ad-success); }
.perm-locked svg { width: 18px; height: 18px; }
/* La bascule mesure 22 px de haut : deux de moins que les 24 exigés par WCAG
   2.5.8. L'étiquette qui la porte reçoit la hauteur manquante — la bascule
   garde son dessin, le doigt gagne sa cible. */
.perm-switch { display: inline-flex; align-items: center; min-height: 24px; cursor: pointer; }
.perm-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.perm-switch__track {
    width: 40px; height: 22px; border-radius: 999px;
    background: var(--ad-bg-sunk); border: 1px solid var(--ad-border);
    position: relative; transition: background var(--ad-trans) ease, border-color var(--ad-trans) ease;
}
.perm-switch__thumb {
    position: absolute; top: 2px; left: 2px; width: 16px; height: 16px;
    border-radius: 50%; background: #fff; box-shadow: var(--ad-shadow-sm);
    transition: transform var(--ad-trans) ease;
}
.perm-switch input:checked + .perm-switch__track { background: var(--ad-accent); border-color: var(--ad-accent); }
.perm-switch input:checked + .perm-switch__track .perm-switch__thumb { transform: translateX(18px); }
.perm-switch input:focus-visible + .perm-switch__track { outline: 2px solid var(--ad-accent); outline-offset: 2px; }
/* Encart « cas particuliers » réservés au développeur (non configurables) */
.perm-devonly { list-style: none; margin: var(--ad-space-2) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--ad-space-2); }
.perm-devonly li { display: flex; align-items: center; gap: var(--ad-space-2); font-size: var(--ad-fs-sm); }
.perm-devonly__lock { display: inline-flex; flex: 0 0 auto; color: var(--ad-accent); }
.perm-devonly__lock svg { width: 16px; height: 16px; }
.perm-devonly__where { color: var(--ad-text-mute); }

/* Utilitaire lecteur d'écran (masqué visuellement) */
.sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* ============================================================
   MODULE AGENDA — écran Agenda
   Les lignes repliables (catégories, lieux, salles) réutilisent les règles
   .admin-blog-cat* ci-dessus : seules les spécificités sont ici.
   ============================================================ */

/* Une salle est en retrait sous son lieu, avec un filet de rattachement. */
.admin-ev-cat--room {
    margin-left: var(--ad-space-5);
    border-left: 3px solid var(--ad-border-str);
}

/* --- Éditeur de champs métier d'une catégorie ----------------------------- */
.admin-ev-fields {
    margin-top: var(--ad-space-2);
}

.admin-ev-fields__list {
    display: flex;
    flex-direction: column;
    gap: var(--ad-space-3);
    margin-bottom: var(--ad-space-3);
}

.admin-ev-fields__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--ad-space-3);
}

.admin-ev-fields__preset {
    display: inline-flex;
    align-items: center;
    gap: var(--ad-space-2);
    margin-left: auto;
}

.admin-ev-field {
    padding: var(--ad-space-3);
    background: var(--ad-bg-alt);
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-r-md);
}

.admin-ev-field__grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: var(--ad-space-2) var(--ad-space-3);
    align-items: end;
}

.admin-ev-field__cell {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}
.admin-ev-field__cell--end {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--ad-space-2);
}
.admin-ev-field__cell-label {
    font-size: var(--ad-fs-xs);
    color: var(--ad-text-mute);
}

.admin-ev-field__langs {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ad-space-2);
    margin-top: var(--ad-space-3);
}
.admin-ev-field__lang {
    display: flex;
    align-items: center;
    gap: var(--ad-space-1);
    flex: 1 1 180px;
    min-width: 0;
}
.admin-ev-field__lang-code {
    flex: 0 0 auto;
    font-size: var(--ad-fs-xs);
    font-weight: 600;
    color: var(--ad-text-mute);
}
.admin-ev-field__lang input { min-width: 0; }

.admin-ev-field__options {
    margin-top: var(--ad-space-3);
    padding-top: var(--ad-space-3);
    border-top: 1px solid var(--ad-border);
}

/* Sur petit écran, la ligne repliable (blog ET agenda) passe sur deux niveaux :
   nom + badges d'abord, contrôles alignés à droite en dessous. Sans cela, les
   badges et les boutons se chevauchent dès que le titre est un peu long. */
@media (max-width: 700px) {
    .admin-blog-cat__head, .admin-ev-cat__head { flex-wrap: wrap; }
    /* flex-basis:0 -> le libellé occupe la place RESTANTE à côté de la poignée
       et fait passer ses badges à la ligne, au lieu de descendre en bloc. */
    .admin-blog-cat__toggle, .admin-ev-cat__toggle { flex-wrap: wrap; flex-basis: 0; }
    .admin-blog-cat__controls, .admin-ev-cat__controls {
        width: 100%;
        justify-content: flex-end;
    }
    .admin-ev-cat--room { margin-left: var(--ad-space-3); }
}

/* --- Grille de séances (éditeur d'un événement) --------------------------- */
.admin-occs {
    display: flex;
    flex-direction: column;
    gap: var(--ad-space-2);
    margin-bottom: var(--ad-space-3);
}

.admin-occ {
    padding: var(--ad-space-2) var(--ad-space-3);
    background: var(--ad-bg-alt);
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-r-md);
}

.admin-occ__main {
    display: grid;
    /* Date · Heures · Durée · Journée · Salle · Version · Statut · ✕
       « Heures » reste la plus large : c'est là qu'on tape le plus. Durée et
       journée entière sont étroites — un nombre et une case à cocher. */
    grid-template-columns:
        9.5rem minmax(10rem, 1.5fr) 6.5rem 6rem
        minmax(8rem, 1fr) minmax(7rem, .8fr) minmax(8rem, .8fr) auto;
    gap: var(--ad-space-2);
    align-items: end;
}

/* Journée entière cochée : heures et durée restent lisibles mais visiblement
   hors jeu — les masquer ferait sauter la grille à chaque clic. */
.admin-occ__cell.is-off { opacity: .45; }

.admin-occ__check {
    display: flex;
    align-items: center;
    gap: 6px;
    /* Aligne la case sur la ligne de base des champs voisins. */
    min-height: 38px;
    font-size: var(--ad-fs-xs);
    white-space: nowrap;
}
.admin-occ__check input { flex: 0 0 auto; }

.admin-occ__cell {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}
.admin-occ__cell--wide { grid-column: 1 / -1; }

.admin-occ__label {
    font-size: var(--ad-fs-xs);
    color: var(--ad-text-mute);
}

.admin-occ__del { align-self: end; }

.admin-occ__more {
    margin-top: var(--ad-space-2);
    padding-top: var(--ad-space-2);
    border-top: 1px dashed var(--ad-border);
}
.admin-occ__more > summary {
    cursor: pointer;
    font-size: var(--ad-fs-xs);
    color: var(--ad-text-mute);
}
.admin-occ__grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: var(--ad-space-2);
    margin-top: var(--ad-space-2);
}

@media (max-width: 1200px) {
    /* Huit colonnes ne tiennent plus : on laisse la grille se replier. */
    .admin-occ__main { grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); }
}
@media (max-width: 900px) {
    .admin-occ__main { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
    .admin-occ__del { justify-self: end; }
}

/* --- Programme (agenda → onglet Programme) -------------------------------- */
.admin-prog-day { margin-bottom: var(--ad-space-4); }

.admin-prog-day__title {
    display: flex;
    align-items: center;
    gap: var(--ad-space-2);
    margin: 0 0 var(--ad-space-2);
    padding-bottom: var(--ad-space-1);
    font-size: var(--ad-fs-sm);
    /* Pas de text-transform : le nom du jour arrive déjà capitalisé de PHP, et
       en français le nom du mois s'écrit en minuscules (« Jeudi 3 septembre »). */
    border-bottom: 1px solid var(--ad-border);
}

.admin-prog {
    display: flex;
    align-items: center;
    gap: var(--ad-space-3);
    padding: var(--ad-space-2) var(--ad-space-3);
    border-bottom: 1px solid var(--ad-border);
}
.admin-prog:hover { background: var(--ad-bg-alt); }

.admin-prog__time {
    flex: 0 0 auto;
    min-width: 3.2rem;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}

.admin-prog__title {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: inherit;
    text-decoration: none;
}
.admin-prog__title:hover { color: var(--ad-accent); }

.admin-prog__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--ad-space-1);
    flex: 0 1 auto;
}

.admin-prog__actions {
    display: flex;
    align-items: center;
    gap: var(--ad-space-1);
    flex: 0 0 auto;
}

/* Un statut n'est jamais porté par la seule couleur : la pastille l'écrit en
   toutes lettres. La rature et l'opacité ne font que renforcer la lecture. */
.admin-prog.is-cancelled .admin-prog__time,
.admin-prog.is-cancelled .admin-prog__title { text-decoration: line-through; }
.admin-prog.is-cancelled { opacity: .6; }
.admin-prog.is-soldout .admin-prog__time { opacity: .75; }

@media (max-width: 700px) {
    .admin-prog { flex-wrap: wrap; }
    .admin-prog__title { flex: 1 1 60%; }
    .admin-prog__meta,
    .admin-prog__actions { width: 100%; }
    .admin-prog__actions { justify-content: flex-end; }
}

/* --- Import d'un programme ------------------------------------------------ */
.admin-steps {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ad-space-2);
    list-style: none;
    margin: 0 0 var(--ad-space-4);
    padding: 0;
    counter-reset: none;
}
.admin-steps__item {
    padding: var(--ad-space-1) var(--ad-space-3);
    font-size: var(--ad-fs-sm);
    color: var(--ad-text-mute);
    background: var(--ad-bg-alt);
    border: 1px solid var(--ad-border);
    border-radius: 999px;
}
.admin-steps__item.is-active {
    color: var(--ad-text);
    font-weight: 600;
    border-color: var(--ad-accent);
    box-shadow: inset 0 -2px 0 var(--ad-accent);
}
.admin-steps__item.is-done { opacity: .7; }

/* Correspondance des colonnes : intitulé du fichier → destination. */
.admin-map {
    display: flex;
    flex-direction: column;
    gap: var(--ad-space-2);
}
.admin-map__row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    gap: var(--ad-space-3);
    align-items: center;
    padding: var(--ad-space-2) var(--ad-space-3);
    background: var(--ad-bg-alt);
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-r-md);
}
.admin-map__col { min-width: 0; }
.admin-map__sample {
    display: block;
    font-size: var(--ad-fs-xs);
    color: var(--ad-text-mute);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.admin-map__arrow { color: var(--ad-text-mute); }
.admin-map__target select { width: 100%; }

@media (max-width: 700px) {
    .admin-map__row { grid-template-columns: 1fr; }
    .admin-map__arrow { display: none; }
}

/* Rapport chiffré de l'import. */
.admin-report {
    list-style: none;
    margin: 0;
    padding: 0;
}
.admin-report li {
    padding: var(--ad-space-1) 0;
    border-bottom: 1px solid var(--ad-border);
}
.admin-report li:last-child { border-bottom: 0; }
.admin-report li.is-error strong { color: var(--ad-danger, #c0392b); }
.admin-report--errors li { border-bottom: 0; padding: 2px 0; }

/* Aperçu : le tableau défile dans sa propre boîte, jamais la page. */
.admin-preview-wrap {
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-r-md);
}
.admin-preview {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--ad-fs-sm);
    white-space: nowrap;
}
.admin-preview th,
.admin-preview td {
    padding: var(--ad-space-1) var(--ad-space-3);
    text-align: left;
    border-bottom: 1px solid var(--ad-border);
}
.admin-preview th {
    font-size: var(--ad-fs-label);
    font-weight: var(--ad-fw-label);
    color: var(--ad-text-mute);
    text-transform: uppercase;
    letter-spacing: var(--ad-ls-label);
    background: var(--ad-bg-alt);
}
.admin-preview tbody tr:last-child td { border-bottom: 0; }

/* Rappel d'un réglage sans effet dans la configuration courante. Le texte
   l'écrit ; la couleur ne fait que renforcer. */
.admin-form__hint--warn {
    display: block;
    margin-top: 4px;
    color: var(--ad-text);
    font-weight: 500;
}

/* ============================================================
   POIGNÉES DE RÉORDONNANCEMENT — état clavier

   Les poignées sont devenues des boutons atteignables au clavier
   (cf. AdminCore.wireKeyboardReorder, js/admin-core.js). Elles étaient
   auparavant `aria-hidden` et hors du parcours de tabulation : réordonner
   une liste était impossible sans souris.

   Elles ont donc besoin d'un anneau de focus — sans quoi on tabule dans
   une liste sans savoir où l'on se trouve.
   ============================================================ */
body.admin-body [role="button"].admin-block__drag:focus-visible,
body.admin-body [role="button"].admin-row__drag:focus-visible,
body.admin-body [role="button"].admin-section-row__drag:focus-visible,
body.admin-body [role="button"].admin-page-row__drag:focus-visible,
body.admin-body [role="button"].admin-blog-cat__drag:focus-visible,
body.admin-body [role="button"].admin-ev-cat__drag:focus-visible,
body.admin-body [role="button"].fb-field__drag:focus-visible,
body.admin-body [role="button"][data-media-drag]:focus-visible {
    outline: 2px solid var(--ad-accent);
    outline-offset: 2px;
    border-radius: 4px;
    /* La poignée est souvent d'un gris très clair au repos : au focus elle
       doit se voir sans qu'on la survole. */
    opacity: 1;
    color: var(--ad-accent);
}

/* ============================================================
   ONGLETS — focus visible

   Les onglets appliquent désormais le « tabindex mobile » : un seul
   entre dans le parcours de tabulation, les flèches circulent entre eux
   (cf. AdminCore.wireTabs, js/admin-core.js). Sans anneau de focus, on
   navigue à l'aveugle dans le jeu d'onglets — ni .admin-page-tab, ni
   .admin-lang-tab, ni .fb-langtab n'en avaient.
   ============================================================ */
body.admin-body .admin-page-tab:focus-visible,
body.admin-body .admin-lang-tab:focus-visible,
body.admin-body .fb-langtab:focus-visible {
    outline: 2px solid var(--ad-accent);
    /* Vers l'intérieur : un onglet est collé à son voisin et à son panneau,
       un décalage positif ferait chevaucher deux anneaux. */
    outline-offset: -2px;
    border-radius: 4px;
}


/* Pastille « brouillon » d'un média : il est employé, mais uniquement dans des
   éléments dépubliés — donc visible nulle part sur le site public. Il compte
   quand même comme utilisé : le supprimer casserait le contenu à sa
   publication. Voir admin/media.php. */
.admin-media-item__draft {
    /* `align-self` et `width` : la fiche est une COLONNE flex, où un
       `inline-block` s'étire sur toute la largeur — la pastille devenait un
       bandeau. Elle doit épouser son texte. */
    display: inline-block;
    align-self: flex-start;
    width: fit-content;
    margin-left: 0;
    margin-top: 2px;
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--ad-warn-sf, #fdf6e3);
    color: var(--ad-warn, #8a6d00);
    border: 1px solid #ecd79a;
    font-size: var(--ad-fs-badge, 11px);
    text-transform: none;
    letter-spacing: 0;
    vertical-align: middle;
}

/* ============================================================
   ÉCRAN « CODE DU SITE » — la zone d'édition
   ============================================================
   Une feuille de style ne se lit pas comme une phrase : l'alignement des
   accolades et l'indentation portent le sens. D'où la police à pas fixe, les
   tabulations à 4 et le retour à la ligne DÉSACTIVÉ (`wrap="off"` sur le
   textarea) — une règle longue se lit en défilant, pas coupée au milieu d'un
   sélecteur.

   `tab-size` et non un remplacement des tabulations : ce que l'exploitant a
   écrit est enregistré tel quel. L'éditeur affiche, il ne reformate pas. */
.code-editor__zone {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 13px;
    line-height: 1.55;
    tab-size: 4;
    white-space: pre;
    overflow-x: auto;
    min-height: 26rem;
    resize: vertical;
}

/* Pastille « fichier absent » : la fiche existe en base, le fichier n'est plus
   sur le disque (retiré par FTP, par un déploiement, par une reprise de
   sauvegarde). Elle emprunte la forme de .admin-media-item__draft — même
   gabarit, mêmes contraintes flex, voir le commentaire ci-dessus — et n'en
   change que la couleur : rouge, parce qu'il n'y a rien à attendre, là où
   « brouillon » annonce quelque chose à venir. Voir admin/media.php. */
.admin-media-item__missing {
    display: inline-block;
    align-self: flex-start;
    width: fit-content;
    margin-left: 0;
    margin-top: 2px;
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--ad-danger-sf, #fdeceb);
    color: var(--ad-danger, #b3261e);
    border: 1px solid #f0c3bf;
    font-size: var(--ad-fs-badge, 11px);
    text-transform: none;
    letter-spacing: 0;
    vertical-align: middle;
}


/* ----------------------------------------------------------
   Charte — rapatrier une police Google Fonts
   Un encadré posé sous les trois choix de police : c'est en lisant
   « — Google Fonts » qu'on veut en sortir, pas trois écrans plus loin.
   ---------------------------------------------------------- */
.design-font-dl {
    margin-top: var(--ad-space-5);
    padding: var(--ad-space-4);
    border: 1px dashed var(--ad-border);
    border-radius: var(--ad-r-md);
    background: var(--ad-bg-alt);
}
.design-font-dl__titre {
    margin: 0 0 var(--ad-space-2);
    font-size: var(--ad-fs-md);
    font-weight: 650;
}
.design-font-dl__intro {
    margin: 0 0 var(--ad-space-3);
    font-size: var(--ad-fs-sm);
    color: var(--ad-text-mute);
    max-width: 68ch;
}
.design-font-dl__ligne {
    display: flex;
    align-items: center;
    gap: var(--ad-space-2);
    flex-wrap: wrap;
    margin-bottom: var(--ad-space-3);
}
.design-font-dl__ligne .design-field__input { flex: 0 1 240px; }
.design-font-dl__case {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: var(--ad-fs-sm);
    white-space: nowrap;
    cursor: pointer;
}
.design-font-dl__case em { color: var(--ad-text-mute); font-style: normal; }
.design-font-dl__subs {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin: var(--ad-space-2) 0 var(--ad-space-3);
}
.design-font-dl__resultat {
    padding: var(--ad-space-3);
    border-radius: var(--ad-r-sm);
    background: var(--ad-bg);
    border: 1px solid var(--ad-border);
    font-size: var(--ad-fs-sm);
}
.design-font-dl__resultat[hidden] { display: none; }
.design-font-dl__resultat.is-error {
    border-color: var(--ad-danger, #b42318);
    color: var(--ad-danger, #b42318);
}
.design-font-dl__resultat p { margin: 0 0 var(--ad-space-2); }

/* Le nom de la famille, en tête du résultat : c'est le sujet de tout ce qui suit. */
.design-font-dl__nom {
    font-size: var(--ad-fs-base);
    padding-bottom: var(--ad-space-2);
    border-bottom: 1px solid var(--ad-border);
}
/* La nature de la police — variable, graisse unique, ou la liste des graisses.
   Détachée du reste : c'est la phrase qui dit si la question suivante a un sens. */
.design-font-dl__nature { color: var(--ad-text-mute); }
.design-font-dl__nature strong { color: var(--ad-text); }

/* ===========================================================================
   MISES À JOUR — LA BANDE D'ÉTAT ET D'ACTION, EN HAUT DE L'ÉCRAN
   ===========================================================================
   Deux ou trois colonnes selon ce qu'il y a à faire : la version du cœur, la
   base, et le ménage d'installation quand il reste des fichiers. `auto-fit`
   plutôt qu'un nombre fixe — c'est le contenu qui décide du compte, et une
   troisième colonne vide serait un trou dans la page. */
.admin-maj-etat {
    display: grid;
    /* 210px : mesuré le 2026-09-16, c'est le seuil qui laisse tenir TROIS
       colonnes dans la zone de contenu de l'admin (≈700 px utiles) quand il y a
       trois choses à dire. À 260px la troisième tombait seule à la ligne. */
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: var(--ad-space-3);
    margin-bottom: var(--ad-space-4);
}
.admin-maj-tuile {
    display: flex;
    flex-direction: column;
    gap: var(--ad-space-2);
    padding: var(--ad-space-4);
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-r);
    background: var(--ad-card-bg, #fff);
}
/* Une tuile qui attend un clic se distingue par son bord, pas par un fond
   criard : plusieurs peuvent l'être à la fois, et trois aplats de couleur
   côte à côte ne hiérarchisent plus rien. */
.admin-maj-tuile.is-action {
    border-color: var(--ad-primary, #2f6fed);
    box-shadow: inset 3px 0 0 var(--ad-primary, #2f6fed);
}
.admin-maj-tuile__titre {
    margin: 0;
    font-size: var(--ad-fs-sm);
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--ad-text-mute);
}
.admin-maj-tuile__etat { margin: 0; font-size: var(--ad-fs-lg, 1.125rem); }
.admin-maj-tuile__etat--ko { color: var(--ad-danger, #b42318); font-weight: 600; }
.admin-maj-tuile__dit { margin: 0; font-size: var(--ad-fs-sm); color: var(--ad-text-mute); }
.admin-maj-tuile__dit--ok { color: var(--ad-success, #067647); }
.admin-maj-tuile__dit strong { color: var(--ad-text); }
/* Le bouton en pied de tuile, aligné d'une tuile à l'autre quel que soit le
   nombre de lignes de texte au-dessus. */
.admin-maj-tuile form { margin-top: auto; }
.admin-maj-tuile form .btn { width: 100%; }
/* La ligne de contexte en pied de tuile : un chiffre qui situe, pas une action.
   Plus petite et plus pâle que l'état, pour ne pas concurrencer le bouton. */
.admin-maj-tuile__note {
    margin: 0;
    font-size: var(--ad-fs-xs, .75rem);
    color: var(--ad-text-mute);
}

/* ===========================================================================
   AJOUTER UNE PAGE — la nature se choisit avant, pas trois écrans plus loin
   ===========================================================================
   Le formulaire tenait sur une ligne (parent, nom, slug, URL externe) et ne
   disait rien de ce que la page pouvait être. Trois natures exclusives, donc
   trois choix lisibles, et les champs de chacune révélés à la demande. */
.admin-page-new {
    display: flex;
    flex-direction: column;
    gap: var(--ad-space-3);
}
.admin-page-new__ligne {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--ad-space-3);
}
@media (max-width: 840px) {
    .admin-page-new__ligne { grid-template-columns: 1fr; }
}
.admin-page-new__champ {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}

.admin-page-new__types {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: var(--ad-space-2);
    margin: 0;
    padding: 0;
    border: 0;
}
.admin-page-new__types legend {
    padding: 0 0 var(--ad-space-2);
}
/* Chaque nature est une CARTE cliquable, pas une puce dans une liste : elle
   porte un nom et la phrase qui dit quand la choisir. Le bord marque celle qui
   est retenue — `:has()` est déjà l'idiome de cette feuille. */
.admin-page-new__type {
    display: grid;
    grid-template-columns: auto 1fr;
    grid-template-areas: "radio nom" "radio dit";
    gap: 2px var(--ad-space-2);
    padding: var(--ad-space-3);
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-r-sm);
    cursor: pointer;
}
.admin-page-new__type:hover { border-color: var(--ad-field-bd-h); }
.admin-page-new__type:has(input:checked) {
    border-color: var(--ad-primary, #2f6fed);
    box-shadow: inset 2px 0 0 var(--ad-primary, #2f6fed);
}
.admin-page-new__type input { grid-area: radio; align-self: center; }
.admin-page-new__type-nom { grid-area: nom; font-weight: 600; font-size: var(--ad-fs-md); }
.admin-page-new__type-dit {
    grid-area: dit;
    font-size: var(--ad-fs-xs, .75rem);
    line-height: 1.4;
    color: var(--ad-text-mute);
}

.admin-page-new__detail[hidden] { display: none; }
.admin-page-new__detail {
    padding: var(--ad-space-3);
    border-radius: var(--ad-r-sm);
    background: var(--ad-bg-soft, var(--ad-bg));
    border: 1px solid var(--ad-border);
}
.admin-page-new__actions { display: flex; gap: var(--ad-space-2); }

/* Ajouter une section : le formulaire révélé, pas une ligne toujours ouverte. */
.admin-section-add {
    margin-top: var(--ad-space-3);
    padding: var(--ad-space-4);
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-r-md);
    background: var(--ad-bg);
}
.admin-section-add[hidden] { display: none; }
/* Le formulaire révélé passe sur SA ligne, sous le bouton « + Nouvelle section » : les deux sont frères dans une rangée
   flexible (`.admin-tabs`), et il se rangeait à droite du bouton dès que la largeur le permettait (2026-10-21). */
.admin-tabs > .admin-section-add { flex: 1 0 100%; }
.admin-section-add__form { display: flex; flex-direction: column; gap: var(--ad-space-3); }
.admin-section-add__champ {
    display: flex;
    flex-direction: column;
    gap: 4px;
    /* Un nom de section est court : un champ pleine largeur suggérerait une
       phrase. 380px tient largement « Nos engagements pour la région ». */
    max-width: 380px;
}
.admin-section-add__actions { display: flex; gap: var(--ad-space-2); }

/* ---------------------------------------------------------------------------
   DOCUMENTS LÉGAUX — la teinte des lignes.

   Tout l'objet de cet écran est de faire VOIR un écart. Sans teinte, il donne
   les bonnes réponses dans un tableau où rien ne ressort — ce qui revient à ne
   rien dire à quelqu'un qui survole. Constaté à l'écran le 2026-09-22 : les
   neuf lignes étaient rigoureusement identiques, « À retirer » compris.

   PORTÉE LIMITÉE à `.legal-etat` : `is-warn` et `is-ok` existent ailleurs pour
   d'autres éléments, et les redéfinir globalement irait les déranger.

   Les couleurs viennent des jetons de l'administration — `-sf` est la SURFACE,
   `--ad-warn` le texte — jamais d'une valeur écrite ici : elles suivent donc
   le thème.
   --------------------------------------------------------------------------- */
.legal-etat tr.is-danger { background: var(--ad-danger-sf); }
.legal-etat tr.is-warn   { background: var(--ad-warn-sf); }
.legal-etat tr.is-danger .legal-etat__faire { color: var(--ad-danger); }
.legal-etat tr.is-warn   .legal-etat__faire { color: var(--ad-warn); }
.legal-etat__faire { font-weight: 600; white-space: nowrap; }
/* « Inactive », « Non mesurable » : dits plus bas que « Active », sans disparaître. */
.legal-etat .legal-etat__doux { color: var(--ad-text-mute); }

/* LES GROUPES ET L'EN-TÊTE FIXE (2026-10-21). Les lignes qui demandent un geste
   d'abord, puis celles qui sont en ordre ; les fonctions inutilisées se replient.
   L'en-tête reste sous la barre de l'administration (sticky, --ad-header-h)
   tant que le tableau défile : la boîte à défilement horizontal, qui l'en
   empêcherait, n'est posée que sous 860 px — en quatre colonnes, le tableau
   tient en largeur sur un ordinateur. */
/* `.admin-table` coupe ce qui dépasse (angles arrondis) : un en-tête collant s'y
   accrochait au tableau lui-même et descendait sur la première ligne. */
.admin-table.legal-etat { overflow: visible; }
/* Largeurs fixes : le tableau replié (fonctions inutilisées) s'aligne sur le premier. */
.legal-etat { table-layout: fixed; width: 100%; }
.legal-etat thead th:nth-child(1) { width: 32%; }
.legal-etat thead th:nth-child(2) { width: 16%; }
.legal-etat thead th:nth-child(3) { width: 27%; }
.legal-etat thead th {
    position: sticky;
    top: var(--ad-header-h);
    z-index: 1;
    background: var(--ad-bg);
    box-shadow: inset 0 -1px 0 var(--ad-border);
}
.legal-etat tr.legal-etat__groupe th {
    padding-top: var(--ad-space-4);
    font-size: var(--ad-fs-xs);
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--ad-text-mute);
    background: transparent;
}
.legal-etat__repli { margin-top: var(--ad-space-4); }
.legal-etat__repli > summary {
    cursor: pointer;
    padding: var(--ad-space-2) 0;
    font-size: var(--ad-fs-sm);
    font-weight: 600;
    color: var(--ad-text-mute);
}
.legal-etat__repli > summary:hover { color: var(--ad-text); }
@media (max-width: 860px) {
    .legal-etat-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
    .legal-etat { table-layout: auto; min-width: 560px; }
    .legal-etat thead th { position: static; }
}

/* Le repère « Service extérieur » sous le libellé : il distingue les fonctions
   qui font parler quelqu'un de celles qui ne décrivent qu'une pratique. */
.legal-etat .admin-form__hint { display: block; margin: .15rem 0 0; font-size: .82em; }

/* L'aperçu d'un paragraphe avant écriture : un encadré sobre, qui doit se lire
   comme du texte de page et non comme un réglage. Portée limitée, tokens de
   l'administration — il suit donc le thème. */
.legal-apercu {
    border: 1px solid var(--ad-border);
    border-left: 3px solid var(--ad-accent);
    border-radius: var(--ad-radius, 6px);
    padding: .9rem 1.1rem;
    margin: .4rem 0 1.2rem;
    background: var(--ad-bg-alt);
}
.legal-apercu p:first-child { margin-top: 0; }
.legal-apercu p:last-child  { margin-bottom: 0; }
/* Ce qui PART du texte (une phrase devenue fausse, un paragraphe retiré) : barré,
   pour que l'aperçu montre tout le changement et pas seulement l'ajout. */
.legal-apercu--retire {
    border-left-color: var(--ad-danger, #b42318);
    text-decoration: line-through;
    opacity: .8;
}


/* ==========================================================================
   ÉCRAN ACCESSIBILITÉ
   --------------------------------------------------------------------------
   La carte de tête met FACE À FACE ce qu'une machine tranche et ce qu'elle ne
   tranchera jamais. Les deux colonnes sont de même poids, volontairement : la
   seconde n'est pas une note en bas de page, c'est la moitié du sujet, et
   c'est elle qui empêche de lire cet écran comme un certificat.
   ========================================================================== */
.a11y-portee {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: var(--ad-space-3);
    margin-top: var(--ad-space-3);
}
.a11y-portee__col {
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-radius);
    padding: var(--ad-space-3);
    background: var(--ad-bg-alt);
}
/* Le liseré ne dit pas « attention » : il dit « autre nature ». D'où la teinte
   neutre appuyée plutôt qu'un rouge — rien n'est en faute dans cette colonne. */
.a11y-portee__col--hors { border-left: 3px solid var(--ad-border-str); }
.a11y-portee__col h3 {
    margin: 0 0 var(--ad-space-2);
    font-size: var(--ad-fs-label);
    text-transform: uppercase;
    letter-spacing: var(--ad-ls-label);
    color: var(--ad-text-soft);
}
.a11y-portee__col ul { margin: 0; padding-left: 1.1rem; }
.a11y-portee__col li { margin-bottom: 3px; font-size: var(--ad-fs-sm); line-height: 1.35; }
.a11y-preambule p { max-width: var(--ad-measure); }

/* Le verdict d'une carte : l'icône ET le mot, jamais la couleur seule
   (WCAG 1.4.1) — un écran qui mesure l'accessibilité serait mal venu de n'être
   lisible qu'en vision trichromate. */
.a11y-verdict {
    display: flex;
    align-items: center;
    gap: var(--ad-space-2);
    margin: var(--ad-space-3) 0 var(--ad-space-2);
    font-size: var(--ad-fs-md);
}
.a11y-verdict svg { flex: 0 0 auto; width: 1.15rem; height: 1.15rem; }
.a11y-verdict--ok { color: var(--ad-success); }
.a11y-verdict--ko { color: var(--ad-warn); }

/* Corriger et voir dans la Charte, côte à côte sous la liste. */
.a11y-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ad-space-2); margin-top: var(--ad-space-3); }
.a11y-actions form { margin: 0; }
#contraste { scroll-margin-top: calc(var(--ad-header-h) + var(--ad-space-3)); }

.a11y-liste { margin: 0 0 var(--ad-space-3); padding: 0; list-style: none; }
.a11y-liste li {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--ad-space-2);
    padding: 5px 0;
    border-bottom: 1px solid var(--ad-border);
    font-size: var(--ad-fs-sm);
}
.a11y-liste li:last-child { border-bottom: none; }
.a11y-liste__mode,
.a11y-liste__reste { color: var(--ad-text-mute); font-size: var(--ad-fs-xs); }
.a11y-liste__val {
    font-family: var(--ad-font-mono);
    font-size: var(--ad-fs-mono);
    font-variant-numeric: tabular-nums;
    color: var(--ad-text-soft);
}
.a11y-liste__dit { color: var(--ad-warn); font-size: var(--ad-fs-xs); }
.a11y-liste__lien { margin-left: auto; font-size: var(--ad-fs-xs); }

/* Le texte de la déclaration, relu AVANT d'être posé. Un `<details>` plutôt
   qu'un panneau toujours ouvert : la carte doit rester parcourable d'un
   regard, et ce texte fait quinze lignes. */
.a11y-apercu {
    margin: var(--ad-space-3) 0;
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-radius);
    background: var(--ad-bg-alt);
}
.a11y-apercu > summary {
    padding: var(--ad-space-2) var(--ad-space-3);
    cursor: pointer;
    font-size: var(--ad-fs-sm);
    font-weight: 600;
    color: var(--ad-text-soft);
}
.a11y-apercu__corps {
    padding: 0 var(--ad-space-3) var(--ad-space-3);
    max-width: var(--ad-measure);
    font-size: var(--ad-fs-sm);
    line-height: 1.5;
}
.a11y-apercu__corps h2 {
    margin: var(--ad-space-3) 0 var(--ad-space-1);
    font-size: var(--ad-fs-md);
}
.a11y-apercu__corps h2:first-child { margin-top: 0; }
.a11y-apercu__corps p { margin: 0 0 var(--ad-space-2); }

.a11y-declaration__form { margin-top: var(--ad-space-3); }
.a11y-declaration__form .admin-form__input { max-width: 26rem; }
.a11y-declaration__form .btn { margin-top: var(--ad-space-2); }

/* Le constat d'une ligne du contrôle page par page : la liste de ce qui a été
   trouvé, écrite dans la case. La colonne des pages a sa part fixe, le constat
   prend le reste — c'est lui qu'on lit —, et la liste perd sa marge pour ne
   pas creuser la ligne. */
.a11y-constat { min-width: 16rem; }
/* Contrôle page par page : une case à revoir se voit sans survol (2026-10-04). */
[data-audit-cell].is-warn { color: var(--ad-warn); font-weight: 600; }
[data-audit-cell].is-warn::before { content: "⚠ "; }
.audit-cellule__note { display: block; margin-top: 2px; font-weight: 400; font-size: var(--ad-fs-xs); color: var(--ad-text-soft); }
[data-audit-a11y] td:first-child { width: 34%; }
.a11y-constat ul { margin: 0; padding-left: 1.1em; }
.a11y-constat li + li { margin-top: var(--ad-space-1); }
/* Une adresse longue se coupe plutôt que de pousser le tableau hors de l'écran. */
[data-audit-a11y] td code { overflow-wrap: anywhere; }

/* Un onglet qui est un LIEN — il change d'écran, il n'ouvre pas un panneau.
   Employé par la bascule « SEO / GEO ↔ Accessibilité » : deux pages, une seule
   entrée de menu. Le soulignement est retiré, la barre active le remplace. */
.admin-page-tab--lien { text-decoration: none; display: inline-block; }
/* Un lien hérite de `.admin-main a` (couleur d'accent), plus précis que
   `.admin-page-tab` : sans cette reprise, les onglets inactifs étaient tous
   orange et ne se distinguaient plus de l'onglet actif. */
.admin-main .admin-page-tab--lien { color: var(--ad-text-mute); }
.admin-main .admin-page-tab--lien:hover { color: var(--ad-text); text-decoration: none; }
.admin-main .admin-page-tab--lien.is-active { color: var(--ad-accent); }
.admin-page-tabs--ecrans { margin-bottom: var(--ad-space-4); }   /* 16 px sous TOUTE barre d'onglets */

/* « Réinstaller cette version », replié quand le site sait que ses fichiers
   sont ceux du paquet publié. Il reste atteignable — un site qui n'a retenu
   aucune empreinte ne peut pas savoir, et on ne lui ôte pas le chemin. */
.admin-maj-tuile__repli { margin-top: var(--ad-space-2); }
.admin-maj-tuile__repli > summary {
    cursor: pointer;
    font-size: var(--ad-fs-xs);
    color: var(--ad-text-mute);
}
.admin-maj-tuile__repli > summary:hover { color: var(--ad-text); }
.admin-maj-tuile__repli[open] > summary { margin-bottom: var(--ad-space-2); }

/* ===========================================================================
   MISE À JOUR — L'EN-TÊTE, LES ONGLETS, LE JOURNAL, LA CHRONOLOGIE (2026-10-03)
   ===========================================================================
   L'en-tête dit l'état avant la mécanique : un grand numéro, une pastille, quatre
   faits. Sa couleur tient dans un filet à gauche et un fond à peine teinté — la
   pastille porte le message, le reste ne fait que l'accompagner. */
.admin-maj-entete {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--ad-space-4) var(--ad-space-6);
    padding: var(--ad-space-5) var(--ad-space-6);
    margin-bottom: var(--ad-space-4);
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-r-lg);
    background: var(--ad-bg);
    box-shadow: var(--ad-shadow-sm), inset 4px 0 0 var(--maj-ton, var(--ad-success));
    --maj-ton: var(--ad-success);
}
.admin-maj-entete--action { --maj-ton: var(--ad-accent); }
.admin-maj-entete--ko     { --maj-ton: var(--ad-danger); }
.admin-maj-entete__corps {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: baseline;
    column-gap: var(--ad-space-4);
    min-width: 0;
}
.admin-maj-entete__sur {
    grid-column: 1 / -1;
    margin: 0;
    font-size: var(--ad-fs-label);
    font-weight: var(--ad-fw-label);
    letter-spacing: var(--ad-ls-label);
    text-transform: uppercase;
    color: var(--ad-text-mute);
}
.admin-maj-entete__version {
    margin: 0;
    font-size: 2.6rem;
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
    color: var(--ad-text);
}
.admin-maj-entete__pastille { margin: 0; align-self: center; }
.admin-maj-entete__faits {
    grid-column: 1 / -1;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ad-space-1) var(--ad-space-4);
    margin: var(--ad-space-2) 0 0;
    padding: 0;
    list-style: none;
    font-size: var(--ad-fs-sm);
    color: var(--ad-text-soft);
}
/* Pas de point médian entre les faits : à la ligne, il ouvrait la seconde. Le
   filet à gauche de chacun sépare aussi bien, et tombe avec lui. */
.admin-maj-entete__faits li { padding-left: var(--ad-space-3); border-left: 2px solid var(--ad-border); line-height: 1.3; }
.admin-maj-entete__geste {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: var(--ad-space-2);
    max-width: 22rem;
    text-align: right;
}
.admin-maj-entete__geste form { margin: 0; }
.admin-maj-entete__dispo { margin: 0; font-size: var(--ad-fs-md); }
.admin-maj-entete__note { margin: 0; font-size: var(--ad-fs-xs); color: var(--ad-text-mute); }
.admin-maj-entete__geste .admin-maj-tuile__repli { margin: 0; }
@media (max-width: 720px) {
    .admin-maj-entete { padding: var(--ad-space-4); }
    .admin-maj-entete__version { font-size: 2rem; }
    .admin-maj-entete__geste { align-items: stretch; text-align: left; max-width: none; width: 100%; }
}

.admin-maj-pastille {
    display: inline-flex;
    align-items: center;
    gap: .45em;
    padding: 4px 12px 4px 10px;
    border-radius: var(--ad-r-pill);
    font-size: var(--ad-fs-sm);
    font-weight: 600;
    white-space: nowrap;
}
.admin-maj-pastille::before {
    content: "";
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: currentColor;
}
.admin-maj-pastille--ok     { background: var(--ad-success-sf); color: var(--ad-success); }
.admin-maj-pastille--action { background: var(--ad-accent-sf);  color: var(--ad-accent-h); }
.admin-maj-pastille--ko     { background: var(--ad-danger-sf);  color: var(--ad-danger); }

/* Le compteur dans un onglet : collé au libellé, sans le faire sauter de ligne. */
.admin-maj-onglets .admin-page-tab .admin-badge { margin-left: .35em; vertical-align: 1px; padding-block: 0; line-height: 18px; }   /* sans gonfler l'onglet : 37 px comme les autres */

/* Une liste de noms techniques (migrations, tables) : compacte, sans tableau. */
.admin-maj-liste {
    margin: var(--ad-space-2) 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: 2px;
    font-size: var(--ad-fs-sm);
}

.admin-maj-version + .admin-maj-version { margin-top: var(--ad-space-4); }
.admin-maj-detail {
    cursor: pointer;
    font-size: var(--ad-fs-sm);
    color: var(--ad-text-soft);
    margin: var(--ad-space-2) 0;
}

/* LE JOURNAL, UNE VERSION PAR REPLI : le titre suffit à retrouver une version,
   et la page cesse de grandir à chaque publication. */
.admin-maj-journal { border-top: 1px solid var(--ad-border); }
.admin-maj-journal__version { border-bottom: 1px solid var(--ad-border); }
.admin-maj-journal__version > summary {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--ad-space-1) var(--ad-space-3);
    padding: var(--ad-space-3) 0;
    cursor: pointer;
    list-style: none;
}
.admin-maj-journal__version > summary::-webkit-details-marker { display: none; }
.admin-maj-journal__version > summary::before {
    content: "›";
    width: 1em;
    color: var(--ad-text-mute);
    transition: transform var(--ad-trans) ease;
}
.admin-maj-journal__version[open] > summary::before { transform: rotate(90deg); }
.admin-maj-journal__num { font-weight: 700; font-variant-numeric: tabular-nums; min-width: 4.2em; }
.admin-maj-journal__titre { color: var(--ad-text-soft); }
.admin-maj-journal__date { margin-left: auto; font-size: var(--ad-fs-xs); color: var(--ad-text-mute); font-variant-numeric: tabular-nums; }
.admin-maj-journal__version > :not(summary) { margin-left: 1.6em; }
.admin-maj-journal__version > ul { margin-bottom: var(--ad-space-3); }

/* LA CHRONOLOGIE : une ligne verticale, un point par événement. Le point d'une
   mise à jour est plein, celui d'une évolution de la base est creux — on lit
   d'un coup d'œil où sont les vraies mises à jour. */
.admin-maj-chrono {
    position: relative;
    margin: var(--ad-space-4) 0 0;
    padding: 0;
    list-style: none;
}
.admin-maj-chrono__item {
    position: relative;
    display: grid;
    grid-template-columns: 11.5rem 1fr;
    gap: var(--ad-space-1) var(--ad-space-5);
    padding: 0 0 var(--ad-space-4) var(--ad-space-5);
}
/* Le fil : de point en point, jamais sous le dernier. */
.admin-maj-chrono__item:not(:last-child)::after {
    content: "";
    position: absolute;
    left: 5px;
    top: 14px;
    bottom: -2px;
    width: 2px;
    background: var(--ad-border);
}
.admin-maj-chrono__item::before {
    content: "";
    position: absolute;
    left: 0;
    top: 5px;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: var(--ad-accent);
    box-shadow: 0 0 0 3px var(--ad-bg);
    z-index: 1;
}
.admin-maj-chrono__item--base::before {
    background: var(--ad-bg);
    border: 2px solid var(--ad-border-str);
}
.admin-maj-chrono__item--restauration::before { background: var(--ad-secondary); }
.admin-maj-chrono__date {
    margin: 0;
    font-size: var(--ad-fs-sm);
    font-weight: 600;
    color: var(--ad-text);
    font-variant-numeric: tabular-nums;
}
.admin-maj-chrono__date span { margin-left: .4em; font-weight: 400; color: var(--ad-text-mute); }
.admin-maj-chrono__corps { min-width: 0; font-size: var(--ad-fs-sm); }
.admin-maj-chrono__corps p { margin: 0; }
.admin-maj-chrono__corps summary { cursor: pointer; color: var(--ad-text-soft); }
.admin-maj-chrono__titre { font-size: var(--ad-fs-md); }
.admin-maj-chrono__sauvegarde {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--ad-space-2) var(--ad-space-3);
    margin-top: var(--ad-space-1);
}
.admin-maj-chrono__sauvegarde form { margin: 0; }
.admin-maj-chrono__plus > summary {
    cursor: pointer;
    margin: 0 0 var(--ad-space-3) var(--ad-space-5);
    font-size: var(--ad-fs-sm);
    color: var(--ad-text-soft);
}
.admin-maj-chrono__plus > .admin-maj-chrono { margin-top: 0; }
@media (max-width: 720px) {
    .admin-maj-chrono__item { grid-template-columns: 1fr; }
}

/* Le bulletin « Ce qu'il y a à faire » de l'écran SEO a laissé la place aux
   tuiles d'état (.admin-etat, plus bas) le 2026-10-20. */

/* ===========================================================================
   LES DEUX GROUPES DE L'ÉCRAN SEO — « ce que vous décidez » / « ce que le CMS
   mesure ». Nés de la fusion des onglets SEO et GEO (2026-09-23).
   ===========================================================================
   Le titre de groupe est un <p>, PAS un <h2> : les cartes en portent déjà, et
   deux niveaux au même rang brouilleraient le plan du document. C'est la
   <section aria-labelledby> qui donne le repère aux outils d'assistance. */

.admin-groupe { display: block; margin-bottom: var(--ad-space-5); }
.admin-groupe__titre {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--ad-space-2);
    margin: 0 0 var(--ad-space-3);
    padding-left: var(--ad-space-1);
    font-size: var(--ad-fs-xs);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ad-text-mute);
}
.admin-groupe__note {
    font-size: var(--ad-fs-xs);
    font-weight: 400;
    letter-spacing: 0;
    text-transform: none;
    color: var(--ad-text-mute);
}


/* ===========================================================================
   LES CONTRÔLES REPLIÉS DE L'ÉCRAN SEO (2026-09-23, phase 4).
   ===========================================================================
   Un contrôle fermé ne montre que son verdict ; il s'ouvre quand on veut
   savoir LESQUELS. Les réglages, eux, restent ouverts : un réglage se
   cherche, un constat se lit. */

.admin-controle > summary {
    cursor: pointer;
    list-style: none;                 /* le triangle par défaut, remplacé plus bas */
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--ad-space-2);
}
.admin-controle > summary::-webkit-details-marker { display: none; }

/* NOTRE PROPRE CHEVRON, PARCE QU'IL DOIT TOURNER. Le triangle natif ne se
   place pas dans une ligne en flex sans casser l'alignement de la ligne de
   base. `content` porte un caractère décoratif : il est masqué aux outils
   d'assistance par `aria-hidden` impossible en CSS — d'où `::before` sur le
   summary, que les lecteurs d'écran ignorent déjà (contenu engendré). */
.admin-controle > summary::before {
    content: '';
    flex: 0 0 auto;
    align-self: center;               /* la ligne est en `baseline` : un carré tourné n'en a pas */
    width: 0.45rem;
    height: 0.45rem;
    border-right: 2px solid var(--ad-text-mute);
    border-bottom: 2px solid var(--ad-text-mute);
    transform: rotate(-45deg);
    transition: transform .15s ease;
}
.admin-controle[open] > summary::before { transform: rotate(45deg); }
@media (prefers-reduced-motion: reduce) {
    .admin-controle > summary::before { transition: none; }
}

/* Le <h2> perd son filet tant que le contrôle est fermé : un trait sous un
   titre annonce un contenu, et il n'y en a pas. */
body.admin-body .admin-controle > summary h2 {
    flex: 1 1 auto;
    margin: 0;
    padding-bottom: 0;
    border-bottom: 0;
}
.admin-controle[open] > summary {
    margin-bottom: var(--ad-space-3);
    padding-bottom: var(--ad-space-2);
    border-bottom: 1px solid var(--ad-border);
}

.admin-controle__verdict {
    flex: 0 0 auto;
    font-size: var(--ad-fs-xs);
    color: var(--ad-text-soft);
}
.admin-controle__verdict--alerte { color: var(--ad-warn);    font-weight: 600; }
.admin-controle__verdict--ok     { color: var(--ad-success); }

/* Le bouton d'aide vit DANS le summary : son clic ne doit pas replier le
   contrôle (js/admin-seo.js l'arrête). Ce curseur dit qu'il fait autre chose
   que la ligne qui le porte. */
.admin-controle > summary .help-tip { cursor: help; }

@media (max-width: 639.98px) {
    .admin-controle__verdict { width: 100%; padding-left: calc(0.5rem + var(--ad-space-2)); }
}

/* ===========================================================================
   LE FILTRE DU TABLEAU DES TITRES (2026-09-23, phase 5).
   ===========================================================================
   Deux groupes de boutons qui masquent des lignes déjà rendues : l'état
   (à corriger / tout) et la langue.

   LE MÊME DESSIN QUE LA BARRE DE LANGUES qui vit dix centimètres plus haut sur
   cet écran (`.admin-lang-tabs`, admin-socle.css) : un creux clair, l'actif en
   noir. Deux sélecteurs segmentés d'aspect différent sur la même page
   suggéreraient qu'ils ne font pas la même sorte de chose.

   L'ACTIF EST NOIR, PAS DE LA COULEUR DE MARQUE. Celle du site peut être
   claire — du texte blanc dessus ne se lirait pas —, et c'est exactement la
   raison déjà écrite pour la barre de langues. */

.admin-filtres {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--ad-space-3);
    margin-bottom: var(--ad-space-3);
}
.admin-filtres__groupe {
    display: flex;
    flex-wrap: wrap;
    gap: 2px;
    background: var(--ad-bg-sunk);
    padding: 2px;
    border-radius: var(--ad-r-sm);
    width: fit-content;
}
.admin-filtre {
    display: inline-flex;
    align-items: center;
    gap: 0.4em;
    padding: 6px 14px;
    font-size: var(--ad-fs-label);
    font-weight: var(--ad-fw-label);
    border: none;
    border-radius: var(--ad-r-xs);
    background: transparent;
    color: var(--ad-text-soft);
    cursor: pointer;
    transition: background .12s ease, color .12s ease;
}
.admin-filtre:hover { color: var(--ad-text); background: rgba(0,0,0,.05); }
.admin-filtre.is-active,
.admin-filtre.is-active:hover { background: var(--ad-text); color: #fff; }

/* Le nombre est une INDICATION, pas une étiquette à part : il suit le mot,
   dans la même teinte affaiblie, et passe au blanc avec lui quand le bouton
   est actif. */
.admin-filtre__n { opacity: .65; font-variant-numeric: tabular-nums; }

.admin-filtres__compte {
    margin: 0;
    font-size: var(--ad-fs-xs);
    color: var(--ad-text-soft);
}

@media (prefers-reduced-motion: reduce) {
    .admin-filtre { transition: none; }
}

/* =========================================================================
   RÉGLAGES — LA COLONNE DES THÈMES (2026-10-01)
   =========================================================================
   Neuf onglets ne tenaient plus sur une ligne : la barre défilait de côté et
   l'on ne voyait pas tous les thèmes. Ils passent dans une colonne à gauche,
   chacun avec son icône et une ligne qui dit ce qu'il contient. Même moteur
   d'onglets (.admin-page-tabs, js/admin.js) : un seul formulaire, un seul
   « Enregistrer », on passe d'un thème à l'autre sans recharger — donc sans
   rien perdre de ce qu'on n'a pas encore enregistré.

   Grille : la colonne occupe la première piste sur toute la hauteur ; tout le
   reste (message, panneaux) va dans la seconde, sans avoir à l'emballer.
   Sur téléphone, la liste devient l'ACCUEIL des Réglages : on touche un thème,
   il s'ouvre, « ← Réglages » ramène à la liste (js/admin-reglages.js). */
.reglages {
    display: grid;
    grid-template-columns: 232px minmax(0, 1fr);
    column-gap: var(--ad-space-6);
    align-items: start;
}
.reglages > * { grid-column: 2; }
.reglages > .reglages-nav {
    grid-column: 1;
    grid-row: 1 / span 40;
    position: sticky;
    top: calc(var(--ad-header-h) + var(--ad-space-3));
    flex-direction: column;
    flex-wrap: nowrap;
    gap: 2px;
    border-bottom: 0;
    margin: 0;
}
.reglages-nav__item {
    display: flex;
    align-items: flex-start;
    gap: var(--ad-space-3);
    width: 100%;
    text-align: left;
    margin: 0;
    padding: 9px var(--ad-space-3);
    border: 0;
    border-radius: var(--ad-r-md);
    color: var(--ad-text-soft);
}
.reglages-nav__item:hover { background: var(--ad-bg-alt); color: var(--ad-text); }
/* Le thème ouvert : fond doux, trait d'accent à gauche, TEXTE EN ENCRE.
   Le titre était en --ad-accent-dk, que son nom fait croire plus foncé : c'est
   l'accent ÉCLAIRCI pour la barre latérale sombre. Orange pâle sur fond orange
   pâle, illisible (relevé par Patrick le 2026-10-01). L'accent ne colore plus
   que l'icône et le trait, en --ad-accent-h, la variante assombrie. */
.reglages-nav__item.is-active {
    background: var(--ad-accent-sf);
    color: var(--ad-text);
    box-shadow: inset 3px 0 0 var(--ad-accent);
}
.reglages-nav__item.is-active .reglages-nav__icone { color: var(--ad-accent-h); }
.reglages-nav__icone { flex: none; display: inline-flex; padding-top: 1px; }
.reglages-nav__icone svg { width: 18px; height: 18px; }
.reglages-nav__texte { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.reglages-nav__titre { line-height: 1.3; }
.reglages-nav__ligne {
    font-size: var(--ad-fs-xs);
    font-weight: 400;
    line-height: 1.35;
    color: var(--ad-text-mute);
}
.reglages-nav__item.is-active .reglages-nav__ligne { color: var(--ad-text-soft); }
/* Un thème qui demande un geste : icône ⚠ et couleur d'avertissement. */
.reglages-nav__ligne.is-alerte,
.reglages-nav__item.is-active .reglages-nav__ligne.is-alerte { color: var(--ad-warn); font-weight: 600; }
.reglages-nav__ligne svg { width: 13px; height: 13px; margin-right: 4px; vertical-align: -2px; }
.reglages-retour { display: none; }

@media (max-width: 900px) {
    .reglages { display: block; }
    .reglages > .reglages-nav { position: static; }
    .reglages-nav__item { padding: var(--ad-space-3); border-bottom: 1px solid var(--ad-border); border-radius: 0; }
    /* Sur la liste, rien n'est « ouvert » : ni fond, ni trait d'onglet actif. */
    .reglages-nav__item.is-active { background: none; box-shadow: none; color: inherit; border-bottom-color: var(--ad-border); }
    .reglages-nav__item.is-active .reglages-nav__icone { color: inherit; }
    .reglages-nav__icone svg { width: 20px; height: 20px; }
    /* Accueil : la liste seule. Thème ouvert : le panneau seul, et le retour. */
    .reglages.is-accueil > :not(.reglages-nav) { display: none; }
    .reglages:not(.is-accueil) > .reglages-nav { display: none; }
    .reglages:not(.is-accueil) > .reglages-retour {
        display: inline-flex;
        align-items: center;
        gap: 6px;
        margin-bottom: var(--ad-space-4);
        padding: 6px 0;
        border: 0;
        background: none;
        font: inherit;
        font-weight: 600;
        color: var(--ad-accent);
        cursor: pointer;
    }
    .reglages-retour svg { width: 16px; height: 16px; }
}

/* ==========================================================================
   TEXTES D'USINE (admin/textes-usine.php, migration 0082)
   Une ligne par texte : où il apparaît, le texte d'usine de la langue, le
   champ de remplacement. Un texte remplacé porte un liseré d'accent ; un texte
   à revoir (l'usine a changé depuis), un liseré d'alerte.
   ========================================================================== */
.textes-usine__groupe { margin-top: var(--ad-space-4); }
.textes-usine__liste { display: grid; gap: var(--ad-space-3); }
.textes-usine__ligne {
    display: grid;
    gap: var(--ad-space-1);
    padding: var(--ad-space-3);
    border: 1px solid var(--ad-border);
    border-left-width: 3px;
    border-radius: var(--ad-r-sm);
    background: var(--ad-surface);
}
.textes-usine__ligne.is-remplace { border-left-color: var(--ad-accent); }
.textes-usine__ligne.is-a-revoir { border-left-color: var(--ad-warn); }
.textes-usine__ou { font-weight: 600; }
.textes-usine__usine { margin: 0; color: var(--ad-text-soft); font-size: var(--ad-fs-sm); }
.textes-usine__etiquette {
    display: inline-block;
    margin-right: var(--ad-space-1);
    font-size: var(--ad-fs-badge);
    text-transform: uppercase;
    letter-spacing: var(--ad-ls-label);
    color: var(--ad-text-mute);
}
.textes-usine .admin-form__error { margin: 0; color: var(--ad-danger); font-size: var(--ad-fs-sm); }
.textes-usine__alerte {
    margin: 0;
    padding: var(--ad-space-2);
    border-radius: var(--ad-r-sm);
    background: var(--ad-warn-sf);
    font-size: var(--ad-fs-sm);
}
.textes-usine__familles {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ad-space-2);
    margin-bottom: var(--ad-space-4);
}
.textes-usine__famille {
    display: inline-flex;
    align-items: center;
    gap: var(--ad-space-1);
    padding: var(--ad-space-1) var(--ad-space-3);
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-r-pill);
    background: var(--ad-surface);
    color: var(--ad-text);
    text-decoration: none;
}
.textes-usine__famille.is-active { border-color: var(--ad-accent); background: var(--ad-accent-sf); font-weight: 600; }
.textes-usine__a-revoir {
    padding: 0 var(--ad-space-1);
    border-radius: var(--ad-r-pill);
    background: var(--ad-warn-sf);
    font-size: var(--ad-fs-badge);
}

/* =========================================================================
   SONDAGES ET QUIZ (admin/sondage.php, chantier 77) — une question par
   cadre, ses réponses possibles en liste lettrée, la jauge des résultats.
   ========================================================================= */
.sondage-resume p { margin: 0 0 var(--ad-space-1); }
.sondage-q {
    margin: var(--ad-space-3) 0;
    padding: var(--ad-space-3);
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-r-sm);
    background: var(--ad-bg-alt);
    scroll-margin-top: 6rem;
}
.sondage-q > legend { padding: 0 var(--ad-space-1); font-weight: 600; }
.sondage-options {
    display: flex;
    flex-direction: column;
    gap: var(--ad-space-1);
    margin: var(--ad-space-2) 0;
    padding: 0;
    list-style: none;
}
.sondage-option {
    display: grid;
    grid-template-columns: 1.5rem minmax(0, 1fr) auto auto;
    gap: var(--ad-space-2);
    align-items: center;
}
.sondage-option__lettre { font-weight: 600; color: var(--ad-text-mute); text-align: center; }
.sondage-option__juste { margin: 0; white-space: nowrap; }
.sondage-q__actions { display: flex; flex-wrap: wrap; gap: var(--ad-space-1); margin-bottom: var(--ad-space-2); }
.sondage-table { margin-bottom: var(--ad-space-3); }
.sondage-jauge {
    display: inline-block;
    width: 6rem;
    height: 0.5rem;
    margin-right: var(--ad-space-1);
    border-radius: var(--ad-r-pill);
    vertical-align: middle;
    background: linear-gradient(to right, var(--ad-accent) 0 var(--part, 0%), var(--ad-bg-sunk) var(--part, 0%) 100%);
}
@media (max-width: 640px) {
    .sondage-option { grid-template-columns: 1.5rem minmax(0, 1fr); }
    .sondage-option__juste, .sondage-option .btn { grid-column: 2; justify-self: start; }
}

/* =========================================================================
   RÉGLAGES D'UN POP-UP (admin/popup.php) — des groupes comme ceux d'une
   section ; chaque choix sur sa ligne (les cases étaient en ligne et se
   mêlaient d'une option à l'autre) ; un champ dépendant (data-montrer-si)
   s'indente sous l'option qui l'ouvre.
   ========================================================================= */
.popup-reglages .admin-form__check { display: flex; width: fit-content; margin: var(--ad-space-1) 0; }
.popup-reglages .admin-secset__group-title { margin-bottom: var(--ad-space-2); }
.popup-reglages .admin-secset__grid,
.popup-reglages [data-montrer-si] { margin-top: var(--ad-space-2); }
.popup-reglages .admin-secset__hint { margin-top: var(--ad-space-1); }

/* =========================================================================
   EXPORTER / IMPORTER — onglet de Réglages (admin/includes/echange-vue.php)
   Deux cartes d'export côte à côte (admin-grid-2), la carte d'import dessous.
   Chaque élément a son air : le champ, la case, le bouton ne se touchent plus.
   ========================================================================= */
.echange-grille { align-items: stretch; margin-bottom: var(--ad-space-4); }
.echange-grille > .admin-card { margin: 0; }
.echange-carte { display: flex; flex-direction: column; gap: var(--ad-space-3); }
.echange-carte > * { margin-top: 0; margin-bottom: 0; }
body.admin-body .echange-carte__titre {
    margin: 0;
    padding-bottom: var(--ad-space-2);
    border-bottom: 1px solid var(--ad-border);
    font-size: var(--ad-fs-lg);
    font-weight: 600;
}
.echange-carte .admin-form__select,
.echange-fichier { width: 100%; }
.echange-actions { display: flex; flex-wrap: wrap; gap: var(--ad-space-2); }
/* Le bouton descend au bas de la carte : les deux cartes d'export alignent le leur. */
.echange-grille .echange-actions { margin-top: auto; padding-top: var(--ad-space-2); }

/* Les familles : une grille — la case, puis le nom sur une ligne et sa
   description DESSOUS, qui s'aligne sur le nom et non sous la case. */
.echange-familles { margin: 0; padding: 0; border: 0; display: grid; gap: var(--ad-space-3); }
.echange-familles > legend { margin-bottom: var(--ad-space-2); padding: 0; }
.echange-famille {
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: var(--ad-space-2);
    row-gap: 2px;
    align-items: baseline;
    cursor: pointer;
}
.echange-famille > input { grid-row: 1 / span 2; margin: 0; align-self: start; transform: translateY(3px); cursor: pointer; }
.echange-famille__nom { font-weight: 600; }
.echange-famille__detail { grid-column: 2; font-size: var(--ad-fs-sm); color: var(--ad-text-mute); line-height: 1.45; }


/* ===========================================================================
   LES TUILES D'ÉTAT (2026-10-20) — Référencement, Moteurs IA, Accessibilité.
   ===========================================================================
   Quatre constats en tête d'onglet. Fond teinté selon l'état, puce ronde, un
   titre court, une ligne, un geste. La tuile entière est le lien. */
.admin-etat {
    list-style: none;
    margin: 0 0 var(--ad-space-5);
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: var(--ad-space-3);
}
.admin-etat__tuile { margin: 0; min-width: 0; }
.admin-etat__lien {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    column-gap: var(--ad-space-3);
    row-gap: 2px;
    height: 100%;
    padding: 16px 18px;
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-r-md);
    background: var(--ad-bg);
    color: var(--ad-text);
    text-decoration: none;
    box-shadow: var(--ad-shadow-sm);
    transition: border-color var(--ad-trans) ease, box-shadow var(--ad-trans) ease, transform var(--ad-trans) ease;
}
.admin-main a.admin-etat__lien { color: var(--ad-text); text-decoration: none; }
a.admin-etat__lien:hover { border-color: var(--ad-border-str); box-shadow: var(--ad-shadow-md); transform: translateY(-1px); }
a.admin-etat__lien:focus-visible { outline: 2px solid var(--ad-accent); outline-offset: 2px; }
.admin-etat__puce {
    grid-row: 1 / span 3;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 15px;
    line-height: 1;
}
.admin-etat__titre { font-weight: 600; font-size: var(--ad-fs-md); line-height: 1.3; }
.admin-etat__texte { font-size: var(--ad-fs-sm); color: var(--ad-text-soft); line-height: 1.45; }
.admin-etat__texte strong { color: var(--ad-text); }
.admin-etat__action { margin-top: 6px; font-size: var(--ad-fs-sm); font-weight: 600; color: var(--ad-accent); }
.admin-etat__tuile--ok      .admin-etat__puce { background: var(--ad-success-sf); color: var(--ad-success); }
.admin-etat__tuile--alerte  .admin-etat__puce { background: var(--ad-warn-sf);    color: var(--ad-warn); }
.admin-etat__tuile--attente .admin-etat__puce { background: var(--ad-bg-sunk);    color: var(--ad-text-mute); }
.admin-etat__tuile--neutre  .admin-etat__puce { background: var(--ad-accent-sf);  color: var(--ad-accent); }
.admin-etat__tuile--alerte .admin-etat__lien { border-color: color-mix(in srgb, var(--ad-warn) 35%, var(--ad-border)); }
/* Sur téléphone : deux tuiles par rangée, resserrées — le bandeau tient dans
   l'écran au lieu de le remplir. */
@media (max-width: 600px) {
    .admin-etat { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--ad-space-2); }
    .admin-etat__lien { grid-template-columns: 1fr; padding: 12px; row-gap: 4px; }
    .admin-etat__puce { grid-row: auto; width: 24px; height: 24px; font-size: 13px; }
    .admin-etat__titre { font-size: var(--ad-fs-sm); }
    .admin-etat__texte, .admin-etat__action { font-size: var(--ad-fs-xs); }
}
@media (prefers-reduced-motion: reduce) {
    .admin-etat__lien { transition: none; }
    a.admin-etat__lien:hover { transform: none; }
}

/* LA SAISIE ET SON APERÇU, CÔTE À CÔTE (Référencement). Les champs à gauche,
   l'aperçu Google à droite, qui reste en vue pendant qu'on écrit. Sous 1100 px,
   l'aperçu repasse sous les champs. */
.seo-duo { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); gap: var(--ad-space-5); align-items: start; }
.seo-duo__apercu { position: sticky; top: calc(var(--ad-header-h) + var(--ad-space-4)); }
.seo-duo__apercu .seo-serp { margin-top: 0; }
@media (max-width: 1100px) { .seo-duo { grid-template-columns: 1fr; } .seo-duo__apercu { position: static; } }

/* Un repli secondaire DANS une carte (partage social, réglages avancés). */
.admin-repli-sec { margin-top: var(--ad-space-4); border-top: 1px solid var(--ad-border); padding-top: var(--ad-space-3); }
.admin-repli-sec > summary { cursor: pointer; font-weight: 600; color: var(--ad-text); list-style-position: inside; }
.admin-repli-sec[open] > summary { margin-bottom: var(--ad-space-3); }
.admin-repli-sec > summary small { font-weight: 400; color: var(--ad-text-mute); margin-left: .4em; }

/* DEUX CHOIX CÔTE À CÔTE (robots d'IA) : chaque question dans son encadré. */
.geo-choix { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--ad-space-4); }
.geo-choix__q { border: 1px solid var(--ad-border); border-radius: var(--ad-r-md); padding: var(--ad-space-4); background: var(--ad-bg-alt); }
.geo-choix__q .admin-form__label { font-size: var(--ad-fs-md); }

/* ----------------------------------------------------------
   Charte — la copie obligatoire des polices (2026-10-20)
   L'état de la copie sous chaque liste, les polices à copier
   (site mis à jour) et celles qu'aucune charte ne nomme plus.
   ---------------------------------------------------------- */
.design-font-etat {
    margin: var(--ad-space-1) 0 0;
    font-size: var(--ad-fs-sm);
    color: var(--ad-text-mute);
}
.design-font-etat[hidden] { display: none; }
.design-font-etat.is-ok { color: var(--ad-success); }
.design-font-etat.is-error { color: var(--ad-danger, #b42318); }
.design-polices-alerte,
.design-polices-inutiles {
    margin-bottom: var(--ad-space-4);
    padding: var(--ad-space-3) var(--ad-space-4);
    border-radius: var(--ad-r-md);
    border: 1px solid var(--ad-border);
    background: var(--ad-bg-alt);
    font-size: var(--ad-fs-sm);
}
.design-polices-alerte { border-color: var(--ad-warn); background: var(--ad-warn-sf); }
.design-polices-alerte p,
.design-polices-inutiles p { margin: 0 0 var(--ad-space-2); max-width: 68ch; }
.design-polices-liste {
    margin: 0 0 var(--ad-space-3);
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.design-polices-liste__etat { color: var(--ad-text-mute); }
.design-polices-inutiles__actions {
    display: flex;
    align-items: center;
    gap: var(--ad-space-2);
    flex-wrap: wrap;
}
.design-polices-inutiles__actions[hidden] { display: none; }

/* ----- LA BASCULE DE VUE D'UN ONGLET (2026-10-22) -----
   Agenda › Événements : « Par date | Par événement ». Deux liens en pastille, à gauche en tête de l'onglet :
   deux façons de lire la même liste, pas deux onglets de plus. */
.admin-vues {
    display: inline-flex;
    gap: 2px;
    margin: 0 0 var(--ad-space-3);
    padding: 3px;
    border: 1px solid var(--ad-border);
    border-radius: 999px;
    background: var(--ad-bg);
}
.admin-vues__choix {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 14px;
    border-radius: 999px;
    color: var(--ad-text-mute);
    font-size: var(--ad-fs-sm);
    font-weight: 600;
    text-decoration: none;
}
.admin-vues__choix .lt-icon { width: 15px; height: 15px; }
.admin-vues__choix:hover { color: var(--ad-text); background: var(--ad-bg-sunk); }
.admin-vues__choix.is-active { background: var(--ad-accent); color: #fff; }
.admin-vues__choix.is-active .admin-count { background: rgba(255, 255, 255, .25); color: #fff; }

/* La carte de création qu'ouvre « + Nouvel article », « + Nouvel événement »… (adminCarteCreationDebut()) :
   le liseré d'accent dit qu'elle vient du bouton d'en-tête, et qu'elle n'appartient à aucun onglet. */
.admin-creation { border-left: 3px solid var(--ad-accent); }

/* LA BANDE TEINTÉE (2026-10-22, essai demandé par Patrick) : derrière la carte, une bande légèrement teintée
   sur toute la largeur de la zone de travail — « une zone s'ouvre ». Une ombre portée sans flou, immense, que
   `clip-path` borne à 18 px au-dessus et au-dessous de la carte : pas de balisage en plus, et elle se déplie
   avec la carte. */
.admin-creation {
    --creation-bande: color-mix(in srgb, var(--ad-accent) 7%, var(--ad-bg-sunk, #f1f3f6));
    box-shadow: 0 0 0 100vmax var(--creation-bande);
    clip-path: inset(-18px -100vmax -22px);
    /* Plus d'air APRÈS la bande (Patrick) : la bande déborde de 22 px, la carte suivante vient 28 px plus bas. */
    margin-bottom: calc(22px + var(--ad-space-5, 24px));
}
/* En tête de l'écran (aucun message au-dessus), la bande monte JUSQU'À l'en-tête : plus de liseré clair entre
   les deux (Patrick, 2026-10-22). */
.admin-content > .admin-creation:first-child { clip-path: inset(calc(-1 * var(--ad-content-pt, 32px)) -100vmax -22px); }
.admin-main { overflow-x: clip; }

/* ELLE SE DÉPLIE, ELLE NE SURGIT PAS (2026-10-22, avec Patrick : « classe ou kitsch ? »). Classe tant que c'est
   bref et sobre : la place s'ouvre (la hauteur passe de 0 à sa taille, la page glisse dessous au lieu de sauter),
   la carte descend de quelques pixels en apparaissant — 400 ms, une courbe qui ralentit à l'arrivée, aucun rebond.
   `@starting-style` donne l'état de départ quand `hidden` tombe ; `interpolate-size` laisse animer jusqu'à
   `height: auto` (Chrome) — ailleurs, seuls le fondu et le glissement jouent, et c'est très bien ainsi. Rien
   pour qui a demandé moins de mouvement. */
@media (prefers-reduced-motion: no-preference) {
    .admin-creation {
        interpolate-size: allow-keywords;
        overflow: clip;
        /* 0,4 s (Patrick, 2026-10-22 : « augmente à 0,4 »). */
        transition: height .4s cubic-bezier(.2, .7, .2, 1), opacity .32s ease, transform .4s cubic-bezier(.2, .7, .2, 1),
                    padding .4s cubic-bezier(.2, .7, .2, 1), margin .4s cubic-bezier(.2, .7, .2, 1);
    }
    @starting-style {
        .admin-creation:not([hidden]) {
            height: 0;
            padding-top: 0;
            padding-bottom: 0;
            margin-bottom: 0;
            opacity: 0;
            transform: translateY(-10px);
        }
    }
}
