/* ==============================================================================
   ÉCOLE NUMÉRIQUE — LA FEUILLE DE STYLE. Il n'y en a qu'une.
   ==============================================================================

   POURQUOI CE FICHIER EST SEUL (12 septembre 2026, S-2026-09-12-0300-ct6)

   Il y en avait quatre : `style.css`, `system.css`, `docs.css`, `tailwind.css`.
   Chacun surchargeait le précédent, et `style.css` contenait à lui seul trois
   habillages empilés — « atelier », « verre », « Platinum ». Résultat mesuré :
   une couleur se décidait à QUATRE étages (`:root`, puis `body.sys.plat`, puis
   les sections `.plat`, puis `html.docs`), et changer un bleu demandait trois
   essais. Frédéric : « plus rien n'a de sens pour moi ». Il avait raison, et ce
   n'était pas une impression : 2 650 lignes sur 4 700 ne servaient qu'à habiller.

   Elles sont parties. Ce qui reste, c'est l'application. La règle tient en une
   phrase, et c'est la seule chose à retenir de ce fichier :

       UNE COULEUR, UN RAYON, UNE OMBRE SE DÉCIDENT ICI, AU §1, ET NULLE PART
       AILLEURS. Le reste du fichier ne fait que s'en servir.

   Si tu te retrouves à écrire une couleur en dur plus bas, ou à ajouter un
   sélecteur pour en battre un autre, c'est le signe qu'on recommence — arrête-toi
   et corrige le jeton.

   L'ancien habillage Macintosh reste dans l'historique git (commit 1c4bc1a et
   avant). Rien n'est perdu, tout est retirable de là si le besoin revient.

   ------------------------------------------------------------------------------
   PLAN
     §1  Les jetons — clair, puis sombre. Le seul endroit où une valeur est choisie.
     §2  Base, remises à zéro, réglages téléphone
     §3  Pastilles d'icônes
     §4  Cockpit Admin
     §5  En-tête et barre latérale
     §6  Cartes, vue détail, résultats, secrets masqués
     §7  Mode Guidé
     §8  Mode Pointage, modales, tiroirs, toast, mascotte
     §9  Accueil
     §10 Le mobilier : barre du haut, cadre de page, panneaux, onglet latéral
     §11 Correctifs téléphone, contacts d'école, `.hidden`
   ============================================================================== */

/* ==============================================================================
   §1. LES JETONS
   ------------------------------------------------------------------------------
   RETHÉMÉ le 16/09/2026 (demande explicite de Frédéric, après mise en garde) :
   les valeurs viennent maintenant du tableau de bord `ecoles/` (dossier réseau
   des écoles), pas de la documentation Claude. Les jetons restent NOMMÉS
   `--ctp-*` pour ne rien casser des ~2900 lignes qui les consomment — seule la
   valeur change, jamais le nom. Fonds, texte, marque, rayons, ombres et
   caractères viennent d'`ecoles/_dashboard/index.html`. Les teintes d'état sans
   équivalent direct côté `ecoles/` (`--ctp-teal`, `--ctp-blue`, `--ctp-mauve`,
   `--ctp-lavender`, `--ctp-sky`) sont **laissées à leurs valeurs d'origine**,
   relevées sur platform.claude.com/docs — inventer une teinte à leur place
   aurait contredit la règle de ce fichier.

   Chaque teinte est doublée d'un triplet `-rgb` : le fichier s'en sert pour poser
   des transparences (`rgb(var(--ctp-blue-rgb) / .12)`), ce qu'une valeur `#rrggbb`
   ne permet pas.
   ============================================================================== */
:root {
    color-scheme: light;

    /* Les fonds, du plus clair au plus creusé — repris de `--surface` / `--paper`
       / `--sunken` dans ecoles/_dashboard/index.html. */
    --ctp-base:    #FFFFFF;   --ctp-base-rgb:    255 255 255;
    --ctp-mantle:  #F2F4F7;   --ctp-mantle-rgb:  242 244 247;
    --ctp-crust:   #E7E9EE;   --ctp-crust-rgb:   231 233 238;

    /* Les surfaces : ce sont AUSSI les filets. Ce langage n'a pas de bordure
       épaisse ni de biseau — un trait de 1 px en --ctp-surface1, et c'est tout.
       Repris de `--sunken-2` / `--line` / `--line-strong` côté ecoles/. */
    --ctp-surface0: #DCDFE6;  --ctp-surface0-rgb: 220 223 230;
    --ctp-surface1: #D7DAE1;  --ctp-surface1-rgb: 215 218 225;
    --ctp-surface2: #B9BEC9;  --ctp-surface2-rgb: 185 190 201;

    /* Le texte, du plus appuyé au plus effacé — ecoles/ n'a que 3 paliers
       (`--ink` / `--ink-muted` / `--ink-faint`) ; `--ctp-subtext0` est interpolé
       entre les deux derniers pour garder les 4 paliers d'origine de ce fichier. */
    --ctp-text:     #14181F;
    --ctp-subtext1: #4B5262;
    --ctp-subtext0: #63697A;
    --ctp-overlay0: #7B8293;
    --icon-ink:     var(--ctp-text);

    /* LES ACCENTS. Un seul porte la marque (--ctp-peach) ; les autres ne servent
       qu'à distinguer un état — réussi, en attente, en erreur — et jamais à
       décorer. RETHÉMÉ le 16/09/2026 : `--ctp-peach/red/green/emerald/yellow`
       viennent d'ecoles/ (`--accent`, `--danger`, `--ok`, `--warn`). Aucun
       équivalent direct côté ecoles/ pour `--ctp-teal/sky/blue/mauve/lavender` :
       laissés à leur valeur d'origine (documentation Claude) plutôt
       qu'inventés — contraire à la règle de ce fichier sinon. Contraste à
       revérifier avec les contrôles habituels avant publication. */
    --ctp-peach:    #D72B2B;  --ctp-peach-rgb:    215 43 43;
    --ctp-red:      #B23B3B;  --ctp-red-rgb:      178 59 59;
    --ctp-green:    #1F7A5C;  --ctp-green-rgb:    31 122 92;
    --ctp-emerald:  #1F7A5C;
    --ctp-yellow:   #9A6B12;
    --ctp-teal:     #0F5C6B;  --ctp-teal-rgb:     15 92 107;
    --ctp-blue:     #2470CC;  --ctp-blue-rgb:     36 112 204;
    --ctp-sky:      #0F5C6B;
    --ctp-mauve:    #6B4FBB;  --ctp-mauve-rgb:    107 79 187;
    --ctp-lavender: #6B4FBB;  --ctp-lavender-rgb: 107 79 187;

    /* LES RAYONS. 6 / 10 / 16 px — repris de `--radius-s/m/l` côté ecoles/.
       Remplace l'échelle 4/6/8 d'origine (voir note ci-dessus : rethémé le
       16/09/2026, décision assumée de Frédéric malgré la mise en garde). */
    --r-xs: 6px;
    --r-sm: 10px;
    --r-md: 16px;
    --r-pill: 9999px;

    /* LES OMBRES. Deux, très basses — mêmes deux paliers que `--shadow-card`
       (ecoles/), qui combine ces deux couches en une seule valeur là-bas. */
    --shadow-1: 0 1px 2px rgba(20, 24, 31, .05);
    --shadow-2: 0 6px 20px rgba(20, 24, 31, .06);
    --glass-2:  var(--shadow-2);   /* survivance d'un habillage retiré */

    /* LES CARACTÈRES — repris d'ecoles/ : Fraunces (titres), Public Sans (texte
       courant), IBM Plex Mono (code/chiffres). Chargées par Google Fonts dans
       `index.html` et `admin.html` — dégradent proprement sur le repli si hors
       ligne, comme avant. */
    --f-sans:  "Public Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
    --f-serif: "Fraunces", Georgia, "Times New Roman", Times, serif;
    --f-mono:  "IBM Plex Mono", "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* LE THÈME SOMBRE. Une couleur lisible sur clair ne l'est presque jamais sur
   sombre : les accents ont leurs propres valeurs, ils ne sont pas « la même
   teinte en plus foncé ». C'est le seul autre endroit où une valeur est choisie,
   et il redéclare EXACTEMENT les mêmes jetons — jamais un de plus. */
html.dark {
    color-scheme: dark;

    /* RETHÉMÉ le 16/09/2026, comme le bloc clair ci-dessus — mêmes sources,
       mêmes teintes sans équivalent laissées telles quelles. */
    --ctp-base:    #14171C;   --ctp-base-rgb:    20 23 28;
    --ctp-mantle:  #10131A;   --ctp-mantle-rgb:  16 19 26;
    --ctp-crust:   #0C0E13;   --ctp-crust-rgb:   12 14 19;

    --ctp-surface0: #1A1E25;  --ctp-surface0-rgb: 26 30 37;
    --ctp-surface1: #2B303A;  --ctp-surface1-rgb: 43 48 58;
    --ctp-surface2: #3A404C;  --ctp-surface2-rgb: 58 64 76;

    --ctp-text:     #E8EAEE;
    --ctp-subtext1: #A2A9B8;
    --ctp-subtext0: #8B93A3;
    --ctp-overlay0: #767D8C;
    --icon-ink:     var(--ctp-text);

    --ctp-peach:    #F0524F;  --ctp-peach-rgb:    240 82 79;
    --ctp-red:      #E58080;  --ctp-red-rgb:      229 128 128;
    --ctp-green:    #54C89A;  --ctp-green-rgb:    84 200 154;
    --ctp-emerald:  #54C89A;
    --ctp-yellow:   #E0B84D;
    --ctp-teal:     #5CB8B2;  --ctp-teal-rgb:     92 184 178;
    --ctp-blue:     #6FA8E8;  --ctp-blue-rgb:     111 168 232;
    --ctp-sky:      #5CB8B2;
    --ctp-mauve:    #B08CF0;  --ctp-mauve-rgb:    176 140 240;
    --ctp-lavender: #B08CF0;  --ctp-lavender-rgb: 176 140 240;

    --shadow-1: 0 1px 2px rgba(0, 0, 0, .30);
    --shadow-2: 0 10px 30px rgba(0, 0, 0, .35);
    --glass-2:  var(--shadow-2);
}

/* ==========================================================================
   Global Base & Responsive Resets
   ========================================================================== */

/* ==============================================================================
   §2. BASE ET REMISE À ZÉRO
   ------------------------------------------------------------------------------
   CE BLOC N'EST PAS DÉCORATIF, IL EST PORTEUR. C'est `tailwind.css` qui fournissait
   la remise à zéro du navigateur ; en la supprimant le 12/09/2026, tout le site est
   repassé en `content-box` et la page est partie à 1 124 px de large dans un écran
   de 390. Les 2 000 lignes de mise en page qui suivent supposent TOUTES `border-box`
   — c'est-à-dire qu'une largeur inclut son rembourrage et son filet. Ne pas retirer.
   ============================================================================== */
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font-family: var(--f-sans); font-size: 14px; line-height: 1.5; }
img, svg, video, canvas { max-width: 100%; }
img, svg, video, canvas { display: block; }
/* Les commandes n'héritent pas des caractères de la page : les navigateurs leur
   imposent la police du système. On le corrige une fois pour toutes. */
button, input, select, textarea { font: inherit; color: inherit; }
button { background: none; border: 0; padding: 0; cursor: pointer; }
table { border-collapse: collapse; }
/* L'ATTRIBUT `hidden` DU HTML L'EMPORTE, TOUJOURS. Le navigateur ne lui donne
   qu'un `display: none` d'agent utilisateur : n'importe quelle règle de classe le
   bat. Constaté le 12/09/2026 — `.ep-panneau { display: flex }` rendait le panneau
   « Écoles proches » invisible mais TOUJOURS PRÉSENT, plein écran, interceptant
   tous les clics de la page. Le symptôme n'était pas un panneau visible, c'était
   une page qui ne répondait plus. */
[hidden] { display: none !important; }
a { color: var(--ctp-blue); }
/* La sélection au clavier doit se voir, partout et sans exception. */
:focus-visible { outline: 2px solid var(--ctp-blue); outline-offset: 2px; }

html {
    scroll-behavior: smooth;
    -webkit-tap-highlight-color: transparent;
}

body {
    background-color: var(--ctp-mantle);
    color: var(--ctp-text);
    min-height: 100vh;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}
/* Polices : Figtree pour l'interface, JetBrains Mono pour les valeurs à copier (repli système) */
body.font-sans, .leaflet-container {
    font-family: "Figtree", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
    font-feature-settings: "ss01";
}
.copy-badge, .markdown-body code, .markdown-body pre {
    font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
}
h1, h2, h3 { letter-spacing: -0.01em; }
/* Lignes fines : les bordures Tailwind (border-ctp-surface0) restent à 1px ; aucune bordure épaisse */
a:focus-visible, button:focus-visible { outline: 2px solid var(--ctp-peach); outline-offset: 2px; }

/* Ergonomie mobile & zones cliquables (minimum 44px) */
.touch-target {
    min-height: 44px;
    min-width: 44px;
}

/* Custom scrollbar Catppuccin */
::-webkit-scrollbar {
    width: 6px;
    height: 6px;
}
::-webkit-scrollbar-track {
    background: var(--ctp-mantle);
}
::-webkit-scrollbar-thumb {
    background: var(--ctp-surface1);
    border-radius: 9999px;
}
::-webkit-scrollbar-thumb:hover {
    background: var(--ctp-overlay0);
}

/* Filtre actif : fond neutre à peine plus clair, texte plein, comme une puce sélectionnée */
.filter-btn.active {
    background-color: var(--ctp-surface0);
    color: var(--ctp-text);
    font-weight: 600;
    box-shadow: inset 0 0 0 1px var(--ctp-surface1);
}

.filter-btn:not(.active) {
    color: var(--ctp-subtext0);
}
.filter-btn:not(.active):hover {
    background-color: var(--ctp-surface0);
    color: var(--ctp-text);
}

/* Cartes : panneau à peine plus clair que la page, bordure fine, ombre discrète au survol */
.procedure-card {
    background-color: var(--ctp-base);
    border-color: var(--ctp-surface0);
    box-shadow: var(--shadow-1);
    transition: box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out;
    content-visibility: auto;
    contain-intrinsic-size: 0 160px;
}
.procedure-card:hover {
    border-color: var(--ctp-surface2);
    box-shadow: var(--shadow-2);
}

/* Badge cliquable pour copier rapidement (IPs, passerelles, mots de passe) */
.copy-badge {
    cursor: pointer;
    user-select: none;
    transition: all 0.15s ease-in-out;
}
.copy-badge:hover {
    filter: brightness(1.1);
}
.copy-badge:active {
    transform: scale(0.96);
}


/* Bascule Liste / Guidé / Pointage */
.mode-btn {
    color: var(--ctp-subtext0);
    transition: all 0.15s ease-in-out;
}
.mode-btn:hover {
    color: var(--ctp-text);
    background-color: var(--ctp-surface0);
}
.mode-btn.active {
    background-color: var(--ctp-surface1);
    color: var(--ctp-text);
    font-weight: 600;
}

/* Mode guidé : le stepper */
.stepper {
    display: flex;
    align-items: flex-start;
    list-style: none;
    padding: 0;
    margin: 0;
}
.stepper li {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    position: relative;
    font-size: 0.75rem;
    color: var(--ctp-subtext0);
}
.stepper li:not(:last-child)::after {
    content: '';
    position: absolute;
    top: 0.55rem;
    left: 50%;
    width: 100%;
    height: 2px;
    background: var(--ctp-surface0);
}
.stepper li .dot {
    position: relative;
    z-index: 1;
    width: 1.25rem;
    height: 1.25rem;
    border-radius: 9999px;
    border: 2px solid var(--ctp-surface1);
    background: var(--ctp-base);
    transition: all 0.2s;
}
.stepper li.done .dot, .stepper li.active .dot {
    border-color: var(--ctp-peach);
    background: var(--ctp-peach);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--ctp-peach) 22%, transparent);
}
.stepper li:not(:last-child)::after { height: 1px; top: 0.6rem; }
.stepper li.done::after { background: var(--ctp-peach); }
.stepper li.active { color: var(--ctp-text); font-weight: 600; }
.stepper li .label { margin-top: 0.5rem; text-align: center; font-size: 0.75rem; }

/* Contenu Markdown Odoo Knowledge (Responsive & Scrollable) */
div.markdown-body {
    overflow-x: auto;
    width: 100%;
    color: var(--ctp-text);
}
.markdown-body ul {
    list-style-type: disc;
    padding-left: 1.25rem;
    margin-top: 0.5rem;
    margin-bottom: 0.5rem;
}
.markdown-body strong {
    font-weight: 600;
    color: var(--ctp-text);
}
.markdown-body h2, .markdown-body h3, .markdown-body h4 {
    font-weight: 700;
    margin: 1rem 0 0.5rem;
    color: var(--ctp-text);
}
.markdown-body h2 { font-size: 1.15rem; }
.markdown-body h3 { font-size: 1.05rem; }
.markdown-body h4 { font-size: 1rem; }
.markdown-body p { margin: 0.5rem 0; line-height: 1.5; }
.markdown-body ol {
    list-style-type: decimal;
    padding-left: 1.25rem;
    margin: 0.5rem 0;
}
.markdown-body a {
    color: var(--ctp-blue);
    text-decoration: underline;
    text-underline-offset: 2px;
}
.markdown-body pre {
    background: var(--ctp-crust);
    color: var(--ctp-text);
    padding: 0.75rem 1rem;
    border-radius: 0.5rem;
    border: 1px solid var(--ctp-surface0);
    overflow-x: auto;
    font-size: 0.8rem;
    margin: 0.75rem 0;
    white-space: pre;
}
.markdown-body code {
    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
    font-size: 0.85em;
}
.markdown-body :not(pre) > code {
    background: var(--ctp-surface0);
    color: var(--ctp-text);
    padding: 0.15rem 0.35rem;
    border-radius: 0.375rem;
}
.markdown-body table {
    border-collapse: collapse;
    margin: 0.75rem 0;
    font-size: 0.825rem;
    width: 100%;
    min-width: 100%;
}
.markdown-body th, .markdown-body td {
    border: 1px solid var(--ctp-surface0);
    padding: 0.4rem 0.6rem;
    text-align: left;
    vertical-align: top;
}
.markdown-body th {
    background: var(--ctp-mantle);
    font-weight: 600;
    color: var(--ctp-text);
}
.markdown-body tr:nth-child(even) td {
    background: color-mix(in srgb, var(--ctp-mantle) 60%, transparent);
}
.markdown-body hr {
    border: 0;
    border-top: 1px solid var(--ctp-surface0);
    margin: 1rem 0;
}
.markdown-body blockquote {
    border-left: 2px solid var(--ctp-surface2);
    padding-left: 0.75rem;
    color: var(--ctp-subtext0);
    font-style: italic;
}

/* Captures d'écran des fiches importées d'Odoo Knowledge : chaque image devient un petit volet
   repliable (même famille que .mat-details) plutôt qu'une image en pleine largeur plantée dans le
   texte — une capture de 1100 px de large casserait le mobile first (règle 5) si elle s'affichait
   grande d'emblée. Fermé par défaut, elle s'ouvre au clic sur son intitulé. */
.cap-details {
    margin: 0.65rem 0;
    border: 1px solid var(--ctp-surface1);
    border-radius: var(--r-md);
    background: var(--ctp-mantle);
    overflow: hidden;
}
.cap-summary {
    padding: 0 12px;
    background: var(--ctp-base);
}
.cap-details[open] .cap-summary { border-bottom: 1px solid var(--ctp-surface1); }
.cap-body { padding: 12px; }
.cap-link {
    display: block;
    border-radius: var(--r-sm);
    border: 1px solid var(--ctp-surface1);
    overflow: hidden;
    background: var(--ctp-base);
}
.cap-img {
    display: block;
    width: 100%;
    height: auto;
    cursor: zoom-in;
}

/* Styles du module de Pointage / Déplacements */
.touch-action-manipulation { touch-action: manipulation; }
.drawer-transition { transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1); }

/* Isolation du contexte d'empilement (stacking context) pour que la carte et ses contrôles glissent proprement SOUS le header sticky */
.tracker-map-wrapper {
    position: relative;
    isolation: isolate;
    z-index: 10;
}

.leaflet-container {
    font-family: inherit;
    z-index: 1 !important;
    width: 100%;
    height: 100%;
}
.leaflet-control-attribution { display: none !important; }

.leaflet-popup-content-wrapper, .leaflet-popup-tip {
    background: var(--ctp-base) !important;
    color: var(--ctp-text) !important;
    border: 1px solid var(--ctp-surface0) !important;
    border-radius: 0.625rem !important;
    box-shadow: var(--shadow-2) !important;
}

.custom-school-pin {
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Optimisation des performances de rendu mobile & 4G */
#cardsContainer > div {
    content-visibility: auto;
    contain-intrinsic-size: 0 160px;
}

/* ==========================================================================
   Pastilles d'icônes : trait fin de 1 px, fond neutre, couleur réservée au pictogramme
   ========================================================================== */

.bordered-icon-box {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-width: 1px;
    border-style: solid;
    border-radius: 0.625rem;
    transition: background-color 0.2s, border-color 0.2s, color 0.2s;
    flex-shrink: 0;
}

/* Sizing variants */
.bordered-icon-xs {
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 0.5rem;
    font-size: 0.7rem;
    border-width: 1px;
}
.bordered-icon-sm {
    width: 2.125rem;
    height: 2.125rem;
    border-radius: 0.625rem;
    font-size: 0.875rem;
    border-width: 1px;
}
.bordered-icon-md {
    width: 2.625rem;
    height: 2.625rem;
    border-radius: 0.75rem;
    font-size: 1.1rem;
    border-width: 1px;
}
.bordered-icon-lg {
    width: 3.125rem;
    height: 3.125rem;
    border-radius: 0.875rem;
    font-size: 1.35rem;
    border-width: 1px;
}
.bordered-icon-xl {
    width: 3.75rem;
    height: 3.75rem;
    border-radius: 1rem;
    font-size: 1.65rem;
    border-width: 1px;
}

/* Color palettes matching Catppuccin tokens */
.bordered-icon-slate {
    background-color: var(--ctp-surface0);
    border-color: var(--ctp-surface1);
    color: var(--ctp-subtext0);
}

.bordered-icon-blue {
    background-color: color-mix(in srgb, var(--ctp-blue) 8%, var(--ctp-base));
    border-color: color-mix(in srgb, var(--ctp-blue) 28%, var(--ctp-surface0));
    color: var(--ctp-blue);
}

.bordered-icon-indigo {
    background-color: color-mix(in srgb, var(--ctp-lavender) 8%, var(--ctp-base));
    border-color: color-mix(in srgb, var(--ctp-lavender) 28%, var(--ctp-surface0));
    color: var(--ctp-lavender);
}

.bordered-icon-emerald {
    background-color: color-mix(in srgb, var(--ctp-green) 8%, var(--ctp-base));
    border-color: color-mix(in srgb, var(--ctp-green) 28%, var(--ctp-surface0));
    color: var(--ctp-green);
}

.bordered-icon-sky {
    background-color: color-mix(in srgb, var(--ctp-sky) 8%, var(--ctp-base));
    border-color: color-mix(in srgb, var(--ctp-sky) 28%, var(--ctp-surface0));
    color: var(--ctp-sky);
}

.bordered-icon-rose {
    background-color: color-mix(in srgb, var(--ctp-red) 8%, var(--ctp-base));
    border-color: color-mix(in srgb, var(--ctp-red) 28%, var(--ctp-surface0));
    color: var(--ctp-red);
}

.bordered-icon-amber {
    background-color: color-mix(in srgb, var(--ctp-peach) 8%, var(--ctp-base));
    border-color: color-mix(in srgb, var(--ctp-peach) 28%, var(--ctp-surface0));
    color: var(--ctp-peach);
}

.bordered-icon-purple {
    background-color: color-mix(in srgb, var(--ctp-mauve) 8%, var(--ctp-base));
    border-color: color-mix(in srgb, var(--ctp-mauve) 28%, var(--ctp-surface0));
    color: var(--ctp-mauve);
}

.bordered-icon-white {
    background-color: rgba(255, 255, 255, 0.12);
    border-color: rgba(255, 255, 255, 0.3);
    color: #ffffff;
}

/* Survol et état actif : pas de mouvement, seulement le trait qui s'affirme */
.procedure-card:hover .bordered-icon-box {
    border-color: var(--ctp-surface2);
}
.filter-btn.active .bordered-icon-box {
    background-color: var(--ctp-base);
    border-color: var(--ctp-surface1);
    color: var(--ctp-text);
}

/* Pixellove Map Pin Vectors */
.pixellove-pin {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: transform 0.2s cubic-bezier(0.16, 1, 0.3, 1);
}
.pixellove-pin:hover {
    transform: scale(1.15);
    z-index: 1000 !important;
}
.pixellove-pin-school .pixellove-pin-inner {
    width: 26px;
    height: 26px;
    background: var(--ctp-base);
    color: var(--ctp-text);
    border: 1px solid var(--ctp-surface2);
    border-radius: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    box-shadow: 0 3px 8px rgba(0, 0, 0, 0.35);
}
.dark .pixellove-pin-school .pixellove-pin-inner {
    box-shadow: 0 3px 8px rgba(0, 0, 0, 0.6);
}

.pixellove-pin-user .pixellove-pin-inner {
    width: 22px;
    height: 22px;
    background: var(--ctp-peach);
    color: var(--ctp-base);
    border: 2px solid var(--ctp-base);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--ctp-peach) 40%, transparent), 0 3px 8px rgba(0, 0, 0, 0.3);
    animation: pulseUserPin 2s infinite;
}
.dark .pixellove-pin-user .pixellove-pin-inner {
    color: var(--ctp-crust);
}
@keyframes pulseUserPin {
    0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--ctp-peach) 60%, transparent), 0 3px 8px rgba(0, 0, 0, 0.3); }
    70% { box-shadow: 0 0 0 8px color-mix(in srgb, var(--ctp-peach) 0%, transparent), 0 3px 8px rgba(0, 0, 0, 0.3); }
    100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--ctp-peach) 0%, transparent), 0 3px 8px rgba(0, 0, 0, 0.3); }
}


/* --- Mascotte et panneau de l'assistant (mobile first, REPRISE.md §15) --- */
.mascot-sticker {
    position: fixed; right: 14px; bottom: calc(14px + env(safe-area-inset-bottom, 0px)); z-index: 60;
    width: 60px; height: 60px; padding: 0; border: 1px solid var(--ctp-surface1); border-radius: 8px; cursor: pointer;
    background: var(--ctp-base); box-shadow: var(--shadow-2);
    display: flex; align-items: center; justify-content: center;
    animation: mascot-float 3.2s ease-in-out infinite;
    transition: transform .15s ease;
}
.mascot-sticker svg { width: 32px; height: 32px; }   /* marque Claude : cadre carré */
.mascot-sticker:hover { transform: scale(1.06); }
.mascot-sticker:active { transform: scale(.94); }
.mascot-sticker:focus-visible, .mascot-close:focus-visible, .mascot-open:focus-visible { outline: 2px solid var(--ctp-peach); outline-offset: 2px; }
.mascot-sticker[aria-expanded="true"] { animation: none; }
@keyframes mascot-float { 0%, 100% { translate: 0 0; } 50% { translate: 0 -5px; } }
.claude-mark { width: 20px; height: 20px; }   /* marque Claude dans une tuile Outils */
.mascot-backdrop { position: fixed; inset: 0; z-index: 61; background: rgba(17, 17, 27, .45); }
.mascot-panel {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 62;
    padding: 20px 20px calc(20px + env(safe-area-inset-bottom, 0px));
    background: var(--ctp-base); color: var(--ctp-text);
    border: 1px solid var(--ctp-surface1); border-bottom: 0; border-radius: 8px 18px 0 0;
    box-shadow: 0 -10px 30px rgba(0, 0, 0, .2);
    display: flex; flex-direction: column; align-items: center; text-align: center; gap: 10px;
    animation: mascot-rise .22s ease-out;
}
@keyframes mascot-rise { from { translate: 0 24px; opacity: 0; } to { translate: 0 0; opacity: 1; } }
/* Carte de confirmation "hors zone" (remplace le confirm() natif, 8 sept. 2026) : même famille d'animation. */
.card-pop-in { animation: card-pop-in .22s ease-out; }
@keyframes card-pop-in { from { translate: 0 8px; opacity: 0; scale: .96; } to { translate: 0 0; opacity: 1; scale: 1; } }
.mascot-big { width: 72px; height: 72px; animation: mascot-float 3.2s ease-in-out infinite; }
.mascot-close {
    position: absolute; top: 10px; right: 10px; width: 44px; height: 44px; border: 0; border-radius: 8px;
    background: transparent; color: var(--ctp-subtext0); cursor: pointer; font-size: 18px;
}
.mascot-close:hover { background: var(--ctp-surface0); color: var(--ctp-text); }
.mascot-open {
    display: flex; align-items: center; justify-content: center; gap: 10px;
    width: 100%; min-height: 48px; margin-top: 4px; padding: 0 18px; border-radius: 8px;
    background: var(--ctp-peach); color: #ffffff; font-weight: 600; text-decoration: none;
}
.dark .mascot-open { color: #1c1c1c; } /* blanc sur orange clair 4,9:1 ; graphite sur orange sombre 5,5:1 */
.mascot-open:hover { filter: brightness(1.05); }
@media (min-width: 640px) {
    .mascot-sticker { right: 22px; bottom: 22px; }
    .mascot-panel { left: auto; right: 22px; bottom: 96px; width: 340px; border-radius: 8px; border-bottom: 1px solid var(--ctp-surface1); box-shadow: var(--shadow-2); }
    .mascot-backdrop { display: none; } /* fermeture au clic extérieur gérée en JS, sans calque qui avale le clic */
}
@media (prefers-reduced-motion: reduce) {
    .mascot-sticker, .mascot-big, .mascot-panel { animation: none; }
}

/* --- Relevé de frais mensuel : impression de la seule modale --- */
@media print {
    body * { visibility: hidden !important; }
    #modalFrais, #modalFrais * { visibility: visible !important; }
    #modalFrais { position: absolute !important; inset: 0 !important; display: block !important; background: #ffffff !important; padding: 0 !important; }
    #fraisFeuille { max-height: none !important; border: 0 !important; box-shadow: none !important; border-radius: 0 !important; color: #000 !important; background: #fff !important; }
    #fraisFeuille * { color: #000 !important; background: transparent !important; border-color: #999 !important; }
    #fraisTable th, #fraisTable td { border-bottom: 1px solid #ccc; }
    .frais-noprint { display: none !important; }
}

/* --- Missions terrain & Agenda --- */
.mission-card {
    transition: transform 0.15s ease, border-color 0.15s ease;
}
.mission-card:active {
    transform: scale(0.99);
}


.leaflet-div-icon.resto-marker { background: transparent; border: none; }

/* ==========================================================================
   Cockpit Admin (admin.html) — Palier 3, étape 2 (REPRISE.md §20) : classes maison remplaçant les
   utilitaires. Valeurs = celles de Tailwind 3.4 pour un rendu identique (text-sm 14/20, rounded-lg 8,
   p-4 16, transition 150 ms cubic-bezier(.4,0,.2,1)…). Mobile-first : tout tient dès 320 px.
   ========================================================================== */
.admin-header {
    position: sticky; top: 0; z-index: 10;
    background-color: rgb(var(--ctp-base-rgb) / .95);
    backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
    border-bottom: 1px solid var(--ctp-surface0);
    padding: 12px 16px;
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
.admin-header-title { display: flex; align-items: center; gap: 8px; min-width: 0; }
.admin-header-title h1 { font-size: 16px; line-height: 24px; font-weight: 600; margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.admin-back-link {
    flex-shrink: 0; min-height: 44px; display: flex; align-items: center; gap: 6px;
    padding: 0 12px; border-radius: 8px; font-size: 14px; line-height: 20px; color: var(--ctp-subtext0);
    transition: color .15s cubic-bezier(.4, 0, .2, 1), background-color .15s cubic-bezier(.4, 0, .2, 1);
}
.admin-back-link:hover { color: var(--ctp-text); background-color: var(--ctp-surface0); }

.admin-main { padding: 16px; max-width: 42rem; margin: 0 auto; display: flex; flex-direction: column; gap: 16px; }

.admin-card { border-radius: 8px; border: 1px solid var(--ctp-surface0); background-color: var(--ctp-base); padding: 16px; }
.admin-btn-row { display: flex; flex-wrap: wrap; gap: 8px; }   /* Maintenance : Enregistrer + Forcer la sauvegarde (§31) */

/* Fraîcheur des données + séquence de rafraîchissement, bas du Cockpit Admin (§33) */
.fraicheur-head { display: flex; align-items: center; gap: 14px; padding: 12px; border-radius: 8px; border: 1px solid var(--ctp-surface0); background-color: var(--ctp-mantle); }
.fraicheur-jours { flex-shrink: 0; width: 56px; height: 56px; border-radius: 8px; display: grid; place-items: center; font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 20px; font-weight: 700; }
.fraicheur-head--green .fraicheur-jours { color: var(--ctp-green); background-color: rgb(var(--ctp-green-rgb) / .12); border: 1px solid rgb(var(--ctp-green-rgb) / .3); }
.fraicheur-head--peach .fraicheur-jours { color: var(--ctp-peach); background-color: rgb(var(--ctp-peach-rgb) / .12); border: 1px solid rgb(var(--ctp-peach-rgb) / .3); }
.fraicheur-head--red .fraicheur-jours { color: var(--ctp-red); background-color: rgb(var(--ctp-red-rgb) / .12); border: 1px solid rgb(var(--ctp-red-rgb) / .3); }
.fraicheur-tx { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.fraicheur-tx b { font-size: 14px; line-height: 20px; color: var(--ctp-text); font-weight: 600; }
.fraicheur-tx span { font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); }
.fraicheur-seq { margin-top: 12px; border: 1px solid var(--ctp-surface0); border-radius: 8px; overflow: hidden; }
.fraicheur-seq > summary { min-height: 44px; display: flex; align-items: center; padding: 10px 12px; cursor: pointer; font-size: 13px; font-weight: 600; color: var(--ctp-subtext1); list-style: none; }
.fraicheur-seq > summary::-webkit-details-marker { display: none; }
.fraicheur-seq > summary::before { content: '▸'; margin-right: 8px; color: var(--ctp-subtext0); }
.fraicheur-seq[open] > summary::before { content: '▾'; }
.fraicheur-seq > summary:hover { background-color: var(--ctp-surface0); }
.fraicheur-list { margin: 0; padding: 0 14px 14px 32px; display: flex; flex-direction: column; gap: 14px; }
.fraicheur-list li { color: var(--ctp-text); }
.fraicheur-list b { font-size: 13px; line-height: 18px; }
.fraicheur-list p { margin: 2px 0 8px; font-size: 12px; line-height: 17px; color: var(--ctp-subtext0); }
.fraicheur-lien { display: inline-flex; text-decoration: none; }
.fraicheur-cmd { display: flex; align-items: flex-start; gap: 8px; background-color: var(--ctp-crust); border: 1px solid var(--ctp-surface0); border-radius: 8px; padding: 8px 10px; }
.fraicheur-cmd code { flex: 1; min-width: 0; font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; line-height: 16px; color: var(--ctp-subtext1); overflow-x: auto; white-space: pre-wrap; overflow-wrap: anywhere; }
.fraicheur-copy { flex-shrink: 0; min-height: 28px; padding: 0 10px; border-radius: 6px; border: 1px solid var(--ctp-surface1); background-color: var(--ctp-base); color: var(--ctp-subtext1); font-size: 11px; font-weight: 600; cursor: pointer; font-family: inherit; }
.fraicheur-copy:hover { color: var(--ctp-text); border-color: var(--ctp-surface2); }
.admin-card-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.admin-card-head .admin-card-title { margin-bottom: 0; }
.admin-card-title { font-size: 14px; line-height: 20px; font-weight: 600; color: var(--ctp-subtext1); margin: 0 0 8px; display: flex; align-items: center; gap: 8px; }
.admin-loading, .admin-muted { font-size: 14px; line-height: 20px; color: var(--ctp-subtext0); }
.admin-caption { font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); margin: 0; }
.admin-caption--lead { margin-bottom: 12px; }
.admin-caption--after { margin-top: 6px; }
.admin-error { font-size: 14px; line-height: 20px; color: var(--ctp-red); }
.admin-error--lead { margin-bottom: 8px; }
.admin-status { margin-top: 8px; font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); }
.admin-gap-top { margin-top: 8px; }

/* Interrupteur (Mode Maintenance) : case à cocher cachée, piste + bouton en ::after */
.admin-switch { display: inline-flex; align-items: center; cursor: pointer; min-height: 44px; }
.admin-switch-input { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
.admin-switch-track { position: relative; width: 44px; height: 24px; border-radius: 9999px; background-color: var(--ctp-surface0); transition: background-color .15s cubic-bezier(.4, 0, .2, 1); }
.admin-switch-track::after { content: ''; position: absolute; top: 2px; left: 2px; width: 20px; height: 20px; border-radius: 9999px; background-color: #ffffff; transition: transform .15s cubic-bezier(.4, 0, .2, 1); }
.admin-switch-input:checked + .admin-switch-track { background-color: var(--ctp-peach); }
.admin-switch-input:checked + .admin-switch-track::after { transform: translateX(20px); }
.admin-switch-input:focus-visible + .admin-switch-track { outline: 2px solid var(--ctp-peach); outline-offset: 2px; }

.admin-grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.admin-stat { font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; font-weight: 700; font-size: 24px; line-height: 32px; }
.admin-stat--xl { font-size: 30px; line-height: 36px; }
.admin-stat--green { color: var(--ctp-green); }
.admin-stat--red { color: var(--ctp-red); }
.admin-stat-row { display: flex; align-items: baseline; gap: 8px; }
.admin-bar-track { margin-top: 8px; height: 8px; border-radius: 9999px; background-color: var(--ctp-surface0); overflow: hidden; }
.admin-bar-fill { height: 100%; background-color: var(--ctp-peach); transition: all .3s cubic-bezier(.4, 0, .2, 1); }

.admin-icon-btn {
    min-height: 44px; min-width: 44px; display: flex; align-items: center; justify-content: center;
    border-radius: 8px; color: var(--ctp-subtext0);
    transition: color .15s cubic-bezier(.4, 0, .2, 1), background-color .15s cubic-bezier(.4, 0, .2, 1);
}
.admin-icon-btn:hover { color: var(--ctp-text); background-color: var(--ctp-surface0); }
.admin-icon-btn:active { transform: scale(.95); }

/* Flux « Activité en direct » */
.admin-live { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; line-height: 16px; color: var(--ctp-green); font-weight: 400; }
.admin-live-dot { width: 6px; height: 6px; border-radius: 9999px; background-color: var(--ctp-green); animation: admin-pulse 2s cubic-bezier(.4, 0, .6, 1) infinite; }
@keyframes admin-pulse { 50% { opacity: .5; } }
.admin-feed { list-style: none; margin: 0; padding: 0 4px 0 0; display: flex; flex-direction: column; gap: 6px; max-height: 24rem; overflow-y: auto; font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; line-height: 16px; }
.admin-feed-item { border-radius: 8px; border: 1px solid var(--ctp-surface0); padding: 6px 8px; display: flex; align-items: center; gap: 8px; }
.admin-feed-meta { color: var(--ctp-subtext0); flex-shrink: 0; }
.admin-feed-text { color: var(--ctp-text); overflow-wrap: break-word; flex: 1 1 0%; min-width: 0; }
.admin-badge { display: inline-flex; align-items: center; padding: 2px 6px; border-radius: 4px; flex-shrink: 0; border: 1px solid transparent; }
.admin-badge--red { color: var(--ctp-red); background-color: rgb(var(--ctp-red-rgb) / .15); border-color: rgb(var(--ctp-red-rgb) / .3); }
.admin-badge--green { color: var(--ctp-green); background-color: rgb(var(--ctp-green-rgb) / .15); border-color: rgb(var(--ctp-green-rgb) / .3); }
.admin-badge--peach { color: var(--ctp-peach); background-color: rgb(var(--ctp-peach-rgb) / .15); border-color: rgb(var(--ctp-peach-rgb) / .3); }

/* Liste des admins + formulaire */
.admin-admins-list { list-style: none; margin: 0 0 12px; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.admin-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; border-radius: 8px; border: 1px solid var(--ctp-surface0); padding: 8px 12px; font-size: 14px; line-height: 20px; }
.admin-row > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.admin-row-remove {
    flex-shrink: 0; min-height: 36px; min-width: 36px; display: flex; align-items: center; justify-content: center;
    border-radius: 6px; color: var(--ctp-red);
    transition: color .15s cubic-bezier(.4, 0, .2, 1), background-color .15s cubic-bezier(.4, 0, .2, 1);
}
.admin-row-remove:hover { background-color: rgb(var(--ctp-red-rgb) / .15); }
.admin-form { display: flex; gap: 8px; }
.admin-input, .admin-textarea {
    border-radius: 8px; border: 1px solid var(--ctp-surface1); background-color: var(--ctp-mantle);
    color: var(--ctp-text); font-size: 16px; line-height: 20px; font-family: inherit;
}
.admin-input { flex: 1 1 0%; min-width: 0; min-height: 44px; padding: 0 12px; }
.admin-textarea { width: 100%; padding: 8px 12px; resize: none; display: block; }
.admin-input::placeholder, .admin-textarea::placeholder { color: var(--ctp-subtext0); }
.admin-input:focus { outline: none; border-color: var(--ctp-mauve); }
.admin-textarea:focus { outline: none; border-color: var(--ctp-peach); }
.admin-btn {
    min-height: 44px; padding: 0 16px; border-radius: 8px; font-size: 14px; line-height: 20px; font-weight: 600;
    border: 1px solid transparent; transition: all .15s cubic-bezier(.4, 0, .2, 1);
}
.admin-btn:active { transform: scale(.95); }
.admin-btn--mauve { color: var(--ctp-mauve); background-color: rgb(var(--ctp-mauve-rgb) / .15); border-color: rgb(var(--ctp-mauve-rgb) / .3); }
.admin-btn--mauve:hover { background-color: rgb(var(--ctp-mauve-rgb) / .25); }
.admin-btn--peach { color: var(--ctp-peach); background-color: rgb(var(--ctp-peach-rgb) / .15); border-color: rgb(var(--ctp-peach-rgb) / .3); }
.admin-btn--peach:hover { background-color: rgb(var(--ctp-peach-rgb) / .25); }

.ic-mauve { color: var(--ctp-mauve); }
.ic-peach { color: var(--ctp-peach); }
.ic-green { color: var(--ctp-green); }
.ic-red { color: var(--ctp-red); }

/* ==========================================================================
   En-tête + sidebar d'index.html — Palier 3, étape 2 (REPRISE.md §20). Classes maison, valeurs
   Tailwind 3.4 reprises à l'identique. Mobile-first : base = 320 px, puis 640 (sm) et 768 (md).
   Inclut le correctif petits écrans du 9 septembre (rangée modes + pastilles).
   ========================================================================== */
.wrap { width: 100%; margin-left: auto; margin-right: auto; padding-left: 12px; padding-right: 12px; }
@media (min-width: 640px)  { .wrap { max-width: 640px;  padding-left: 16px; padding-right: 16px; } }
@media (min-width: 768px)  { .wrap { max-width: 768px;  padding-left: 24px; padding-right: 24px; } }
@media (min-width: 1024px) { .wrap { max-width: 1024px; } }
@media (min-width: 1280px) { .wrap { max-width: 1280px; } }
@media (min-width: 1536px) { .wrap { max-width: 1536px; } }

.site-header {
    position: sticky; top: 0; z-index: 50;
    background-color: var(--ctp-crust); color: var(--ctp-text);
    border-bottom: 1px solid var(--ctp-surface0);
    box-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);
    transition: color .2s cubic-bezier(.4, 0, .2, 1), background-color .2s cubic-bezier(.4, 0, .2, 1), border-color .2s cubic-bezier(.4, 0, .2, 1);
}
.site-header-inner { padding-top: 10px; padding-bottom: 10px; display: flex; flex-direction: column; justify-content: space-between; align-items: stretch; gap: 10px; }
@media (min-width: 640px) { .site-header-inner { padding-top: 12px; padding-bottom: 12px; gap: 12px; } }
@media (min-width: 768px) { .site-header-inner { padding-top: 16px; padding-bottom: 16px; flex-direction: row; align-items: center; gap: 16px; } }

.brand-row { display: flex; align-items: center; justify-content: space-between; width: 100%; gap: 8px; }
@media (min-width: 640px) { .brand-row { gap: 16px; } }
@media (min-width: 768px) { .brand-row { width: auto; } }
@media (min-width: 640px) { .brand { gap: 12px; } }
@media (min-width: 640px) { .brand-logo { height: 40px; } }
.dark .brand-logo { filter: invert(1); }
@media (min-width: 640px) { .brand-title { font-size: 18px; line-height: 28px; } }
@media (min-width: 768px) { .brand-title { font-size: 20px; line-height: 28px; } }
@media (min-width: 640px) { .brand-sub { font-size: 12px; line-height: 16px; } }
.btn-accueil {
    min-height: 44px; padding: 8px 14px; border-radius: 8px; flex-shrink: 0;
    background-color: var(--ctp-surface0); color: var(--ctp-text); border: 1px solid var(--ctp-surface1);
    font-size: 12px; line-height: 16px; font-weight: 600; white-space: nowrap;
    display: flex; align-items: center; gap: 8px; transition: all .15s cubic-bezier(.4, 0, .2, 1);
}
.btn-accueil:hover { background-color: var(--ctp-surface1); }
.btn-accueil:active { transform: scale(.95); }
@media (min-width: 640px) { .btn-accueil { font-size: 14px; line-height: 20px; } }

/* Variantes de couleur des boîtes d'icône de l'en-tête (complètent bordered-icon-*) */
.ib-home { border-color: rgb(var(--ctp-peach-rgb) / .4); background-color: var(--ctp-base); color: var(--ctp-peach); }
.ib-muted { border-color: var(--ctp-surface1); background-color: var(--ctp-surface0); color: var(--ctp-subtext0); }
.ib-muted-base { border-color: var(--ctp-surface1); background-color: var(--ctp-base); color: var(--ctp-subtext0); }
.ib-plain { border-color: transparent; color: currentColor; }
.ib-theme { border-color: var(--ctp-surface1); background-color: var(--ctp-surface0); color: var(--ctp-yellow); }
.theme-btn:hover .ib-theme { border-color: var(--ctp-peach); }
/* Tailles d'icône FontAwesome */
.i-9 { font-size: 9px; }
.i-10 { font-size: 10px; }
.i-xs { font-size: 12px; line-height: 16px; }
.i-sm { font-size: 14px; line-height: 20px; }

.tools-row { width: 100%; display: flex; flex-direction: column; align-items: stretch; gap: 8px; }
@media (min-width: 640px) { .tools-row { flex-direction: row; align-items: center; gap: 12px; } }
@media (min-width: 768px) { .tools-row { flex: 1 1 0%; max-width: 42rem; } }
.search { position: relative; width: 100%; min-width: 0; }
.search-ic { position: absolute; top: 0; bottom: 0; left: 0; padding-left: 12px; display: flex; align-items: center; pointer-events: none; }
.search-input {
    min-height: 44px; display: block; width: 100%; padding: 8px 44px 8px 44px;
    border: 1px solid var(--ctp-surface0); border-radius: 8px; font-size: 14px; line-height: 20px;
    background-color: var(--ctp-surface0); color: var(--ctp-text);
    transition: color .2s cubic-bezier(.4, 0, .2, 1), background-color .2s cubic-bezier(.4, 0, .2, 1), border-color .2s cubic-bezier(.4, 0, .2, 1);
}
/* Trouvé le 15/09/2026 (S-2026-09-15-0415-des), signalé par Frédéric sur une capture :
   `--scan` restait à 36px du bord même quand `--clear` (right:0) est masqué par défaut — 36px
   de vide flottant à droite du bouton caméra, mesuré (boîte du champ à x=264, bouton à x=228).
   Et l'inverse était vrai quand `--clear` s'affiche : 36 contre 44 de large, 8px de recouvrement
   entre les deux zones cliquables. `:has()` réserve la place seulement quand `--clear` existe
   vraiment ; le padding du champ suit la même logique (44px avec un seul bouton, 88px avec deux). */
.search-input::placeholder { color: var(--ctp-subtext0); }
.search-input:focus { outline: none; background-color: var(--ctp-base); color: var(--ctp-text); border-color: transparent; box-shadow: 0 0 0 2px var(--ctp-blue); }
.search:has(.search-btn--clear:not(.hidden)) .search-input { padding-right: 88px; }
.search-btn { position: absolute; top: 0; bottom: 0; display: flex; align-items: center; justify-content: center; min-height: 44px; min-width: 44px; color: var(--ctp-subtext0); }
.search-btn:hover { color: var(--ctp-text); }
.search-btn:focus { outline: none; }
/* AUDIT 10/09/2026, constat 04 — la règle ci-dessus pèse 0-2-0 et écrasait
   `button:focus-visible` (0-1-1) : le bouton de scan n'avait AUCUN repère au clavier. On la
   laisse en place pour le clic, et on rétablit le contour pour la navigation au clavier. */
.search-btn:focus-visible { outline: 2px solid var(--ctp-peach); outline-offset: 2px; }
.search-btn--scan { right: 0; }
.search:has(.search-btn--clear:not(.hidden)) .search-btn--scan { right: 44px; }
.search-btn--clear { right: 0; padding-right: 12px; }

.mode-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-shrink: 0; flex-wrap: wrap; }
@media (min-width: 640px) { .mode-row { justify-content: flex-end; } }
.mode-toggle { flex: 1 1 0%; min-width: 0; display: flex; border-radius: 8px; background-color: var(--ctp-surface0); padding: 4px; font-size: 12px; line-height: 16px; border: 1px solid var(--ctp-surface1); }
@media (min-width: 640px) { .mode-toggle { flex: 0 1 auto; font-size: 14px; line-height: 20px; } }
.mode-btn {
    min-height: 44px; flex: 1 1 0%; min-width: 0; padding: 6px 10px; border-radius: 8px; white-space: nowrap;
    display: flex; align-items: center; justify-content: center; gap: 6px;
    transition: color .15s cubic-bezier(.4, 0, .2, 1), background-color .15s cubic-bezier(.4, 0, .2, 1);
}
@media (min-width: 640px) { .mode-btn { flex: 0 1 auto; padding: 6px 12px; } }
/* Petits écrans (< 420 px) : la rangée ne pouvait ni rétrécir ni passer à la ligne → texte seul, puis icône seule */
@media (max-width: 419px) {
    .mode-row { gap: 6px; }
    .mode-btn { padding-left: 6px; padding-right: 6px; gap: 4px; }
    .mode-btn .bordered-icon-box { display: none; }
}
@media (max-width: 349px) {
    .mode-btn .bordered-icon-box { display: inline-flex; }
    .mode-btn span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; }
}
.chip {
    min-height: 44px; min-width: 44px; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
    border-radius: 8px; border: 1px solid var(--ctp-surface1); background-color: var(--ctp-surface0); color: var(--ctp-text);
    font-size: 12px; line-height: 16px; font-weight: 700; letter-spacing: .05em; user-select: none;
}
.chip--off { opacity: .5; }
.chip--btn { cursor: pointer; font-family: inherit; padding: 0 10px; }
.chip--btn:hover { border-color: var(--ctp-peach); color: var(--ctp-peach); }
/* Modale Compte / déconnexion (9 septembre 2026) */
.compte-avatar { width: 44px; height: 44px; flex-shrink: 0; border-radius: 8px; display: grid; place-items: center; font-weight: 800; letter-spacing: .05em; color: var(--ctp-peach); background-color: rgb(var(--ctp-peach-rgb) / .14); border: 1px solid rgb(var(--ctp-peach-rgb) / .35); }
.compte-body { display: flex; flex-direction: column; gap: 10px; padding: 12px 0 4px; }
.compte-row { display: flex; flex-direction: column; gap: 2px; font-size: 13px; line-height: 18px; color: var(--ctp-text); }
.compte-k { font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 10px; line-height: 14px; letter-spacing: .08em; text-transform: uppercase; color: var(--ctp-subtext0); }
.compte-note { margin: 4px 0 0; font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); }
.compte-foot { display: flex; justify-content: flex-end; gap: 8px; flex-wrap: wrap; }
.compte-foot .btn-go--sm { min-height: 44px; }
.compte-foot .btn-go:disabled { opacity: .5; cursor: not-allowed; filter: none; }
/* Scan photo : historique des 3 dernières photos (9 septembre 2026) */
.scan-list { display: flex; flex-direction: column; gap: 10px; padding: 12px 0 4px; max-height: 60vh; overflow: auto; }
.scan-item { display: grid; grid-template-columns: 72px minmax(0, 1fr); gap: 10px 12px; padding: 10px; border-radius: 8px; border: 1px solid var(--ctp-surface0); background-color: var(--glass-2); }
.dark .scan-item { background-color: rgb(255 255 255 / .05); }
.scan-thumb { width: 72px; height: 72px; object-fit: cover; border-radius: 8px; border: 1px solid var(--ctp-surface1); grid-row: span 2; }
.scan-info { min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.scan-date { font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 10px; line-height: 14px; letter-spacing: .06em; color: var(--ctp-subtext0); }
.scan-res { font-size: 13px; line-height: 18px; color: var(--ctp-text); overflow-wrap: anywhere; }
.scan-res code { font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; font-weight: 600; }
.scan-ok { color: var(--ctp-green); font-weight: 600; }
.scan-ko { color: var(--ctp-subtext0); }
.scan-plus { font-size: 11px; color: var(--ctp-subtext0); }
.scan-tokens { display: flex; flex-wrap: wrap; gap: 4px; }
.scan-token { min-height: 28px; padding: 2px 8px; border-radius: 6px; border: 1px solid var(--ctp-surface1); background: none; color: var(--ctp-subtext1); font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; cursor: pointer; }
.scan-token:hover { border-color: var(--ctp-peach); color: var(--ctp-peach); }
.scan-actions { grid-column: 2; display: flex; flex-wrap: wrap; gap: 6px; }
.scan-actions .btn-neutral--xs { min-height: 40px; display: inline-flex; align-items: center; gap: 6px; }
.scan-vide { margin: 0; font-size: 13px; line-height: 18px; color: var(--ctp-subtext0); }
.chip--admin { color: var(--ctp-mauve); transition: border-color .15s cubic-bezier(.4, 0, .2, 1); }
.chip--admin:hover { border-color: var(--ctp-mauve); }
.theme-btn { min-height: 44px; min-width: 44px; flex-shrink: 0; color: var(--ctp-text); padding: 4px; border-radius: 8px; display: flex; align-items: center; justify-content: center; transition: transform .15s cubic-bezier(.4, 0, .2, 1); }
.theme-btn:focus { outline: none; }
.theme-btn:focus-visible { outline: 2px solid var(--ctp-peach); outline-offset: 2px; }
.theme-btn:active { transform: scale(.9); }

/* Zone principale : sidebar + résultats */
.site-main { padding-top: 16px; padding-bottom: 16px; display: flex; flex-direction: column; gap: 24px; flex-grow: 1; }
@media (min-width: 640px)  { .site-main { padding-top: 24px; padding-bottom: 24px; } }
@media (min-width: 768px)  { .site-main { padding-top: 32px; padding-bottom: 32px; flex-direction: row; gap: 32px; } }
@media (min-width: 1024px) { .site-main { padding-left: 32px; padding-right: 32px; } }
.sidebar { width: 100%; display: flex; flex-direction: column; gap: 16px; }
@media (min-width: 640px)  { .sidebar { gap: 24px; } }
@media (min-width: 768px)  { .sidebar { width: 33.333333%; } }
@media (min-width: 1024px) { .sidebar { width: 25%; } }
.results { width: 100%; }
@media (min-width: 768px)  { .results { width: 66.666667%; } }
@media (min-width: 1024px) { .results { width: 75%; } }
.panel { background-color: var(--ctp-base); border-radius: 8px; border: 1px solid var(--ctp-surface0); padding: 16px; transition: color .2s cubic-bezier(.4, 0, .2, 1), background-color .2s cubic-bezier(.4, 0, .2, 1), border-color .2s cubic-bezier(.4, 0, .2, 1); }
@media (min-width: 640px) { .panel { padding: 20px; } }
.panel-title { margin: 0 0 12px; font-size: 12px; line-height: 16px; font-weight: 700; color: var(--ctp-subtext0); text-transform: uppercase; letter-spacing: .05em; }
.filter-list { display: flex; flex-direction: column; gap: 8px; }
.filter-btn { min-height: 44px; display: flex; align-items: center; gap: 12px; width: 100%; text-align: left; padding: 10px 14px; border-radius: 8px; transition: all .15s cubic-bezier(.4, 0, .2, 1); }
.filter-btn--parent { justify-content: space-between; gap: 8px; }
.filter-btn-main { display: flex; align-items: center; gap: 12px; min-width: 0; }
.filter-label { font-weight: 600; font-size: 14px; line-height: 20px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.filter-chevron { font-size: 12px; line-height: 16px; flex-shrink: 0; transition: transform .2s cubic-bezier(.4, 0, .2, 1); }
.rotate-180 { transform: rotate(180deg); }   /* hook basculé par script.js sur le chevron des sous-menus */
.submenu { display: flex; flex-direction: column; gap: 4px; padding: 0 4px 0 16px; margin: 4px 0 8px 20px; border-left: 2px solid var(--ctp-surface0); }
.sub-filter-btn {
    min-height: 44px; text-align: left; font-size: 12px; line-height: 16px; padding: 8px 10px; border-radius: 8px;
    color: var(--ctp-subtext0); display: flex; align-items: center; gap: 8px;
    transition: color .15s cubic-bezier(.4, 0, .2, 1), background-color .15s cubic-bezier(.4, 0, .2, 1);
}
@media (min-width: 640px) { .sub-filter-btn { font-size: 14px; line-height: 20px; } }
.sub-filter-btn:hover { color: var(--ctp-peach); background-color: var(--ctp-surface0); }
.sub-filter-btn.active { font-weight: 700; color: var(--ctp-blue); background-color: rgb(var(--ctp-blue-rgb) / .1); }
/* Sous-menu Matériel regroupé par famille + filtre texte (9 septembre 2026, script.js LOT_FAMILLES) */
.submenu-search { min-height: 44px; width: 100%; padding: 8px 12px; border-radius: 6px; border: 1px solid var(--ctp-surface1); background-color: var(--ctp-mantle); color: var(--ctp-text); font-size: 16px; line-height: 20px; margin-bottom: 2px; }
.submenu-search::placeholder { color: var(--ctp-subtext0); }
.submenu-search:focus { outline: none; border-color: transparent; box-shadow: 0 0 0 2px var(--ctp-blue); }
.submenu-group { border-radius: 6px; }
.submenu-group-title { min-height: 44px; display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 8px 10px; border-radius: 8px; cursor: pointer; list-style: none; font-size: 13px; line-height: 16px; font-weight: 700; color: var(--ctp-subtext1); user-select: none; }
.submenu-group-title::-webkit-details-marker { display: none; }
.submenu-group-title::before { content: ''; width: 6px; height: 6px; border-right: 2px solid currentColor; border-bottom: 2px solid currentColor; transform: rotate(-45deg); margin-right: 4px; flex-shrink: 0; transition: transform .2s cubic-bezier(.4, 0, .2, 1); }
.submenu-group[open] > .submenu-group-title::before { transform: rotate(45deg); }
.submenu-group-title > span:first-of-type { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.submenu-group-title:hover { background-color: var(--ctp-surface0); color: var(--ctp-text); }
.submenu-group-count { font-size: 11px; line-height: 16px; font-weight: 600; color: var(--ctp-subtext0); background-color: var(--ctp-surface0); border-radius: 9999px; padding: 0 7px; }
.submenu-group > .sub-filter-btn { margin-left: 8px; }
.quick-links { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; font-size: 14px; line-height: 20px; }
.quick-link { min-height: 44px; color: var(--ctp-peach); display: flex; align-items: center; gap: 10px; padding: 4px 8px; border-radius: 8px; transition: color .15s cubic-bezier(.4, 0, .2, 1), background-color .15s cubic-bezier(.4, 0, .2, 1); }
.quick-link:hover { text-decoration: underline; background-color: var(--ctp-surface0); }


/* ==========================================================================
   Cartes, vue détail, bandeau VPN, résultats, cartes matériel, widget secret — Palier 3, étape 2
   (REPRISE.md §20). Valeurs Tailwind 3.4 reprises à l'identique, sauf : écart de grille 16 px sous 640 px
   (24 au-dessus), et icônes SVG animées à la place des icônes FontAwesome dans la boîte de chaque carte.
   ========================================================================== */
.cards-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; }
@media (min-width: 640px)  { .cards-grid { gap: 24px; } }
@media (min-width: 1280px) { .cards-grid:not(.cards-grid--single) { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.procedure-card { border-width: 1px; border-style: solid; border-radius: 8px; overflow: hidden; display: flex; flex-direction: column; height: 100%; }
.procedure-card--link { cursor: pointer; transition: all .2s cubic-bezier(.4, 0, .2, 1); }
.procedure-card--link:hover { border-color: var(--ctp-peach); }
.card-head { padding: 16px; border-bottom: 1px solid var(--ctp-surface0); display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; }
@media (min-width: 640px) { .card-head { padding: 20px; } }
/* `flex-start`, pas `center`. La pastille fait 50 px, une ligne de titre en fait 24 :
   centrer la pastille sur un titre qui court sur trois lignes la fait descendre au
   milieu du bloc, à 38 px sous la première ligne — elle n'a plus l'air d'appartenir
   au titre. Mesuré le 12/09/2026 sur 11 cartes. Alignée en haut, elle reste la
   vignette du titre, quel que soit le nombre de lignes.
   Les couples titre + sous-titre d'UNE ligne chacun (`.home-entry`,
   `.wizard-choice-btn`) gardent `center` : là, la pastille se cale sur le couple
   entier et c'est juste — vérifié à l'écran, ce n'est pas le même cas. */
.card-head-main { display: flex; align-items: flex-start; gap: 12px; min-width: 0; }
/* `flex: 1 1 0` et pas `auto` : sans cela le bloc du titre se rétrécit sur la
   largeur de son texte au lieu de prendre la place libre à côté du pictogramme.
   Mesuré le 12/09/2026 — 197 px de titre sur 292 disponibles. Ça passait avant
   par accident, parce que Geneva rendait le même texte plus large que la police
   d'aujourd'hui : le défaut était là depuis le début, caché par une police. */
.card-head-text { min-width: 0; flex: 1 1 0%; }
.card-title { margin: 0; font-weight: 700; color: var(--ctp-text); font-size: 16px; line-height: 1.375; transition: color .15s cubic-bezier(.4, 0, .2, 1); }
@media (min-width: 640px) { .card-title { font-size: 18px; } }
.procedure-card--link:hover .card-title { color: var(--ctp-peach); }
/* Numéro de lot discret, sur la ligne du titre. Chasse fixe comme les autres références du site
   (numéro de série, FI) ; ne prend pas la couleur bleue au survol de la carte. */
.card-lot-ref { margin-left: 8px; font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; line-height: 16px; font-weight: 500; letter-spacing: .02em; color: var(--ctp-subtext0); white-space: nowrap; }
.procedure-card--link:hover .card-lot-ref { color: var(--ctp-subtext0); }
.card-badges { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; margin-top: 4px; }
.badge { display: inline-block; font-size: 12px; line-height: 16px; font-weight: 600; padding: 2px 8px; border-radius: 4px; border: 1px solid transparent; text-transform: uppercase; letter-spacing: .05em; }
.badge-etat { display: inline-block; font-size: 12px; line-height: 16px; font-weight: 700; padding: 4px 10px; border-radius: 9999px; white-space: nowrap; flex-shrink: 0; border: 1px solid transparent; }

/* ==============================================================================
   TÉLÉPHONE : LE TITRE DE CARTE ÉCRASÉ PAR LE BADGE (11 septembre 2026)
   ------------------------------------------------------------------------------
   Signalé par Frédéric, capture d'écran d'un Samsung à l'appui — et c'est elle qui
   a montré le défaut, aucune de mes mesures ne l'avait attrapé.

   LE DÉFAUT. `.card-head` est une rangée flex : à gauche `.card-head-main`
   (pictogramme + titre), à droite `.badge-etat`. Or le badge est en
   `white-space: nowrap` ET `flex-shrink: 0` — il ne se comprime jamais. Sur
   « Commandable jusqu'au 05-10-2026 » il fait **232 px**. À 412 px de large, une
   fois retirés le remplissage (32), la gouttière (12) et le pictogramme (64), il
   reste **48 px** pour le titre. Mesuré : `.card-title` à 48 px, donc
   « LOT / 27A / - / Tablette / 10" / iPad » — un mot par ligne, sur six lignes.

   POURQUOI MES CONTRÔLES NE L'ONT PAS VU. Je vérifiais `scrollWidth` : il n'y a
   AUCUN débordement horizontal ici, la rangée tient dans l'écran. Elle tient
   justement parce que le titre a été écrasé. **Un contrôle de débordement ne voit
   pas un écrasement** — c'est la même famille d'erreur que « mesurer la présence
   au lieu de l'effet » du 10/09, appliquée à la largeur.

   LE CORRECTIF. Sous 640 px, la rangée passe à la ligne et le titre prend toute la
   largeur : le badge descend au-dessous. On ne touche ni à `nowrap` ni à
   `flex-shrink` du badge — une pastille coupée en deux lignes est pire — et le
   dessin au-dessus de 640 px est inchangé.
   ============================================================================== */
@media (max-width: 639px) {
    .card-head { flex-wrap: wrap; }
    .card-head-main { flex: 1 1 100%; }
    .card-head > .badge-etat { align-self: flex-start; }
}

.badge--lavender { background-color: rgb(var(--ctp-lavender-rgb) / .15); color: var(--ctp-lavender); border-color: rgb(var(--ctp-lavender-rgb) / .3); }
.badge--green    { background-color: rgb(var(--ctp-green-rgb) / .15);    color: var(--ctp-green);    border-color: rgb(var(--ctp-green-rgb) / .3); }
.badge--red      { background-color: rgb(var(--ctp-red-rgb) / .15);      color: var(--ctp-red);      border-color: rgb(var(--ctp-red-rgb) / .3); }
.badge--peach    { background-color: rgb(var(--ctp-peach-rgb) / .15);    color: var(--ctp-peach);    border-color: rgb(var(--ctp-peach-rgb) / .3); }
.badge--mauve    { background-color: rgb(var(--ctp-mauve-rgb) / .15);    color: var(--ctp-mauve);    border-color: rgb(var(--ctp-mauve-rgb) / .3); }
.badge--blue     { background-color: rgb(var(--ctp-blue-rgb) / .15);     color: var(--ctp-blue);     border-color: rgb(var(--ctp-blue-rgb) / .3); }
.badge--teal     { background-color: rgb(var(--ctp-teal-rgb) / .15);     color: var(--ctp-teal);     border-color: rgb(var(--ctp-teal-rgb) / .3); }
.badge--neutral  { background-color: rgb(var(--ctp-surface1-rgb) / .4);  color: var(--ctp-subtext1); border-color: rgb(var(--ctp-surface2-rgb) / .5); }
.badge-etat.badge--neutral { color: var(--ctp-subtext0); border-color: rgb(var(--ctp-surface2-rgb) / .4); }
.lot-badge { display: inline-flex; align-items: center; gap: 4px; margin: 4px 0 0 4px; font-size: 11px; line-height: 16px; font-weight: 600; padding: 2px 8px; border-radius: 4px; border: 1px solid rgb(var(--ctp-peach-rgb) / .4); background-color: rgb(var(--ctp-peach-rgb) / .15); color: var(--ctp-peach); }
a.lot-badge:hover { text-decoration: underline; }
.lot-badge-name { font-weight: 400; color: var(--ctp-subtext1); }
.ticket-link { min-height: 44px; padding: 8px 12px; display: inline-flex; align-items: center; gap: 8px; font-size: 12px; line-height: 16px; font-weight: 600; color: var(--ctp-subtext0); border-radius: 8px; transition: color .15s cubic-bezier(.4, 0, .2, 1), background-color .15s cubic-bezier(.4, 0, .2, 1); }
.ticket-link:hover { color: var(--ctp-peach); background-color: var(--ctp-surface0); }
.ticket-link:hover .bordered-icon-box { border-color: var(--ctp-peach); color: var(--ctp-peach); }
/* Fiches jumelles (9 septembre 2026, maquette « scindée ») : vignette coupée en deux volets, fiche à deux colonnes */
.dual-badge { display: inline-flex; flex-shrink: 0; border: 1px solid var(--ctp-surface1); border-radius: 9999px; overflow: hidden; font-size: 11px; line-height: 16px; font-weight: 700; }
.dual-badge > span { padding: 3px 8px; }
.dual-badge-ko { color: var(--ctp-red); background-color: rgb(var(--ctp-red-rgb) / .14); }
.dual-badge-ok { color: var(--ctp-green); background-color: rgb(var(--ctp-green-rgb) / .14); }
.card-split { display: grid; grid-template-columns: 1fr 1fr; flex-grow: 1; }
.card-half { min-height: 96px; min-width: 0; padding: 12px 12px 14px; display: flex; flex-direction: column; align-items: flex-start; gap: 6px; text-align: left; font: inherit; color: var(--ctp-text); background: none; border: 0; cursor: pointer; transition: background-color .15s cubic-bezier(.4, 0, .2, 1); }
.card-half + .card-half { border-left: 1px solid var(--ctp-surface0); }
.card-half--mat { background: linear-gradient(180deg, rgb(var(--ctp-red-rgb) / .10), transparent 70%); }
.card-half--log { background: linear-gradient(180deg, rgb(var(--ctp-green-rgb) / .10), transparent 70%); }
.card-half--mat:hover { background-color: rgb(var(--ctp-red-rgb) / .08); }
.card-half--log:hover { background-color: rgb(var(--ctp-green-rgb) / .08); }
.card-half-h { font-weight: 700; font-size: 14px; line-height: 20px; display: flex; align-items: center; gap: 8px; }
.volet-dot { width: 10px; height: 10px; border-radius: 9999px; flex-shrink: 0; background-color: var(--ctp-subtext0); }
.card-half--mat .volet-dot, .detail-pane--mat .volet-dot { background-color: var(--ctp-red); }
.card-half--log .volet-dot, .detail-pane--log .volet-dot { background-color: var(--ctp-green); }
.card-half-ex { font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); }
.card-half-go { margin-top: auto; font-size: 12px; line-height: 16px; font-weight: 600; display: inline-flex; align-items: center; gap: 4px; }
.card-half--mat .card-half-go { color: var(--ctp-red); }
.card-half--log .card-half-go { color: var(--ctp-green); }
.card-foot--split { justify-content: flex-start; gap: 4px; }
/* Modèle réellement déployé, pré-rédigé sous « Recherche IA » (10 septembre 2026) : gras italique, pour
   qu'on voie d'un coup d'œil ce qui part dans la requête et qu'on puisse le corriger dans Google.
   Sur sa propre ligne : le pied de carte est en flex-wrap, rien ne déborde en 390 px. */
.ia-modele { display: block; font-style: italic; font-weight: 700; font-size: 11px; line-height: 14px;
             color: var(--ctp-subtext0); margin-top: 1px; max-width: 22ch; overflow: hidden;
             text-overflow: ellipsis; white-space: nowrap; }
.ia-link { align-items: flex-start; }
.ia-link:hover { color: var(--ctp-peach); }
.ia-link:hover .bordered-icon-box { border-color: var(--ctp-peach); color: var(--ctp-peach); }
.detail-split { display: grid; grid-template-columns: 1fr 1fr; flex-grow: 1; }
.detail-pane { min-width: 0; padding: 16px 14px; display: flex; flex-direction: column; gap: 10px; overflow-wrap: anywhere; }
.detail-pane + .detail-pane { border-left: 1px solid var(--ctp-surface0); }
.detail-pane.is-focus { background-color: rgb(var(--ctp-peach-rgb) / .06); box-shadow: inset 0 3px 0 var(--ctp-peach); }
.detail-pane-h { margin: 0; font-size: 14px; line-height: 20px; font-weight: 700; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding-bottom: 8px; border-bottom: 2px solid; }
.detail-pane--mat .detail-pane-h { border-color: var(--ctp-red); }
.detail-pane--log .detail-pane-h { border-color: var(--ctp-green); }
.detail-pane .detail-desc { margin: 0; }
.detail-pane .detail-md { flex-grow: 1; }
.detail-ticket--pane { margin-top: auto; padding-top: 8px; }
/* Colonnes étroites (170 px en 390 px) : listes et blocs markdown resserrés dans les volets */
.detail-pane .detail-md { padding: 12px; }
.detail-pane .markdown-body ul, .detail-pane .markdown-body ol { padding-left: 16px; }
.detail-pane .markdown-body p, .detail-pane .markdown-body li { font-size: 13px; line-height: 1.5; }
@media (min-width: 640px) { .detail-pane { padding: 20px; } .detail-pane .detail-md { padding: 16px; } .detail-pane .markdown-body p, .detail-pane .markdown-body li { font-size: 14px; } }

.card-body { padding: 16px; flex-grow: 1; }
@media (min-width: 640px) { .card-body { padding: 20px; } }
.card-desc { margin: 0; font-size: 14px; line-height: 1.625; color: var(--ctp-subtext0); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.card-foot { padding: 12px 16px; background-color: rgb(var(--ctp-mantle-rgb) / .7); border-top: 1px solid var(--ctp-surface0); display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 8px; margin-top: auto; }
@media (min-width: 640px) { .card-foot { padding: 12px 20px; } }
.card-more { min-height: 44px; padding: 4px 8px; display: inline-flex; align-items: center; gap: 6px; color: var(--ctp-peach); font-size: 14px; line-height: 20px; font-weight: 600; }
.procedure-card--link:hover .card-more { text-decoration: underline; }
.card-more-arrow { transition: transform .15s cubic-bezier(.4, 0, .2, 1); }
.procedure-card--link:hover .card-more-arrow { transform: translateX(4px); }

/* Icônes SVG animées (boîte de gauche des cartes) */
/* Dessins des vignettes (bibliothèque du 10 septembre 2026, script.js). viewBox 48 : les épaisseurs
   sont exprimées dans cet espace, d'où 2.6 là où l'ancien viewBox 24 demandait 1.75. */
.ki { width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; overflow: visible; }
.ki .body, .ki .det { fill: none; stroke: currentColor; }
.ki .acc { stroke: var(--ctp-peach); stroke-width: 3; fill: none; }
.ki .acc-f { fill: var(--ctp-peach); stroke: none; }
.ki .dot { fill: currentColor; stroke: none; }
.ki .screen { fill: none; stroke: none; }
.ki [pathLength] { stroke-dasharray: 100; stroke-dashoffset: 100; }
.ki .pop { fill: currentColor; stroke: none; transform-origin: center; transform: scale(0); }
.ki .acc, .ki .acc-f { transform-origin: center; }
.ki .glow { fill: currentColor; stroke: none; opacity: 0; }
.ki-go .ki [pathLength] { animation: ki-draw .7s cubic-bezier(.19, 1, .22, 1) forwards; animation-delay: var(--d, 0ms); }
.ki-go .ki .pop { animation: ki-pop .45s cubic-bezier(.34, 1.56, .64, 1) forwards; animation-delay: calc(600ms + var(--d, 0ms)); }
.ki-go .ki .acc, .ki-go .ki .acc-f { animation: ki-pop .45s cubic-bezier(.34, 1.56, .64, 1) backwards; animation-delay: calc(560ms + var(--d, 0ms)); }
.ki-go .ki .glow { animation: ki-glow 1.1s ease forwards; animation-delay: 650ms; }
.procedure-card--link:hover .ki, .procedure-card--link:active .ki { animation: ki-nudge .5s cubic-bezier(.19, 1, .22, 1); }
@keyframes ki-draw { to { stroke-dashoffset: 0; } }
@keyframes ki-pop { to { transform: scale(1); } }
@keyframes ki-glow { 40% { opacity: .28; } to { opacity: .14; } }
@keyframes ki-nudge { 30% { transform: translateY(-3px); } 60% { transform: translateY(1px); } to { transform: none; } }
@media (prefers-reduced-motion: reduce) {
    .ki [pathLength] { stroke-dashoffset: 0; animation: none !important; }
    .ki .pop { transform: none; animation: none !important; }
    .ki .glow { opacity: .14; animation: none !important; }
    .procedure-card--link:hover .ki, .procedure-card--link:active .ki { animation: none; }
}

/* Vue détail */
.detail-back { margin-bottom: 16px; }
.btn-back { min-height: 44px; padding: 8px 16px; border-radius: 8px; background-color: var(--ctp-base); border: 1px solid var(--ctp-surface0); color: var(--ctp-peach); font-weight: 600; display: flex; align-items: center; gap: 8px; font-size: 14px; line-height: 20px; transition: color .15s cubic-bezier(.4, 0, .2, 1), background-color .15s cubic-bezier(.4, 0, .2, 1); }
.btn-back:hover { background-color: var(--ctp-surface0); }
.procedure-card--static { transition: color .2s cubic-bezier(.4, 0, .2, 1), background-color .2s cubic-bezier(.4, 0, .2, 1), border-color .2s cubic-bezier(.4, 0, .2, 1); }
.detail-body { padding: 16px; flex-grow: 1; }
@media (min-width: 640px) { .detail-body { padding: 24px; } }
.detail-desc { margin: 0 0 16px; font-size: 14px; line-height: 1.625; color: var(--ctp-subtext0); font-style: italic; }
.detail-concerne { margin: 0 0 16px; font-size: 12px; line-height: 16px; color: var(--ctp-subtext1); }
.detail-label { text-transform: uppercase; letter-spacing: .05em; font-weight: 600; }
.detail-label--muted { font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); }
.detail-md { background-color: var(--ctp-mantle); border-radius: 8px; padding: 16px; font-size: 14px; line-height: 20px; color: var(--ctp-text); border: 1px solid var(--ctp-surface0); overflow-x: auto; }
@media (min-width: 640px) { .detail-md { padding: 20px; } }
.detail-foot { padding: 16px; background-color: var(--ctp-mantle); border-top: 1px solid var(--ctp-surface0); display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between; align-items: center; margin-top: auto; }
@media (min-width: 640px) { .detail-foot { padding: 16px 24px; } }
.detail-ticket { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.detail-ticket-value { font-size: 14px; line-height: 20px; font-weight: 700; color: var(--ctp-text); background-color: var(--ctp-base); padding: 6px 12px; border-radius: 8px; border: 1px solid var(--ctp-surface0); }

/* En-tête des résultats et état vide */
.results-head { margin-bottom: 16px; display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 8px; }
.results-title { margin: 0; font-size: 20px; line-height: 28px; font-weight: 700; color: var(--ctp-text); }
@media (min-width: 640px) { .results-title { font-size: 24px; line-height: 32px; } }
.results-count { font-size: 12px; line-height: 16px; font-weight: 600; color: var(--ctp-subtext0); background-color: var(--ctp-surface0); padding: 4px 12px; border-radius: 9999px; border: 1px solid var(--ctp-surface1); }
@media (min-width: 640px) { .results-count { font-size: 14px; line-height: 20px; } }
.no-results { text-align: center; padding: 40px 16px; background-color: var(--ctp-base); border-radius: 8px; border: 1px solid var(--ctp-surface0); transition: color .2s, background-color .2s, border-color .2s; }
@media (min-width: 640px) { .no-results { padding: 64px 24px; } }
.no-results-ic { margin: 0 auto 12px; }
.i-xl { font-size: 20px; line-height: 28px; }
.no-results-ic .i-xl { color: var(--ctp-subtext0); }
.no-results-title { margin: 0; font-size: 16px; line-height: 24px; font-weight: 700; color: var(--ctp-text); }
@media (min-width: 640px) { .no-results-title { font-size: 18px; line-height: 28px; } }
.no-results-text { margin: 4px 0 0; font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); }
@media (min-width: 640px) { .no-results-text { font-size: 14px; line-height: 20px; } }

/* Bandeau VPN */
.vpn-bar { margin-bottom: 16px; font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); background-color: var(--ctp-base); border: 1px solid var(--ctp-surface0); border-radius: 8px; transition: color .2s, background-color .2s, border-color .2s; }
.vpn-summary { min-height: 44px; padding: 0 14px; display: flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; list-style: none; }
.vpn-summary::-webkit-details-marker { display: none; }
@media (min-width: 640px) { .vpn-summary { padding: 0 16px; } }
.vpn-title { font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--ctp-text); }
.vpn-sub { display: none; color: var(--ctp-subtext0); }
@media (min-width: 640px) { .vpn-sub { display: inline; } }
.vpn-chevron { font-size: 10px; color: var(--ctp-subtext0); margin-left: auto; transition: transform .15s cubic-bezier(.4, 0, .2, 1); }
.vpn-bar[open] .vpn-chevron { transform: rotate(180deg); }
.vpn-body { padding: 0 14px 14px; display: flex; flex-wrap: wrap; align-items: center; column-gap: 12px; row-gap: 8px; overflow-x: auto; }
@media (min-width: 640px) { .vpn-body { padding: 0 16px 16px; } }
.vpn-item { white-space: nowrap; display: inline-flex; align-items: center; gap: 4px; }
.vpn-links { display: flex; align-items: center; gap: 4px; }
@media (min-width: 640px) { .vpn-links { margin-left: auto; } }
.vpn-link { min-height: 44px; color: var(--ctp-peach); display: flex; align-items: center; gap: 6px; padding: 4px 8px; border-radius: 8px; white-space: nowrap; transition: color .15s cubic-bezier(.4, 0, .2, 1), background-color .15s cubic-bezier(.4, 0, .2, 1); }
.vpn-link:hover { text-decoration: underline; background-color: var(--ctp-surface0); }
.vpn-link--strong { font-weight: 600; }

/* Widget secret (valeur masquée + œil) et badges à copier */
.secret-holder { display: inline-flex; align-items: center; gap: 4px; vertical-align: middle; margin-top: -8px; margin-bottom: -8px; }
.copy-badge--secret { font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--ctp-text); background-color: var(--ctp-surface0); padding: 0 8px; min-height: 36px; border-radius: 8px; border: 1px solid var(--ctp-surface1); display: inline-flex; align-items: center; gap: 6px; transition: all .15s cubic-bezier(.4, 0, .2, 1); }
.vpn-item .copy-badge--secret { padding: 0 10px; }
.copy-badge--secret:hover { background-color: var(--ctp-surface1); }
.copy-badge--secret:active { transform: scale(.95); }
.secret-toggle { min-height: 44px; min-width: 44px; display: inline-flex; align-items: center; justify-content: center; border-radius: 8px; color: var(--ctp-subtext0); transition: color .15s cubic-bezier(.4, 0, .2, 1), background-color .15s cubic-bezier(.4, 0, .2, 1); }
.secret-toggle:hover { color: var(--ctp-text); background-color: var(--ctp-surface0); }
.copy-badge--serial { font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; font-weight: 600; color: var(--ctp-text); background-color: var(--ctp-surface0); padding: 0 12px; border-radius: 8px; border: 1px solid var(--ctp-surface1); display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 48px; font-size: 16px; line-height: 24px; word-break: break-all; width: 100%; transition: all .15s cubic-bezier(.4, 0, .2, 1); }
.copy-badge--serial:hover { background-color: var(--ctp-surface1); }
.op-70 { opacity: .7; }
.op-80 { opacity: .8; }

/* Cartes « Matériel » (recherche universelle) et lignes d'équipement */
.mat-card { background-color: var(--ctp-base); border-radius: 8px; border: 1px solid var(--ctp-surface0); padding: 16px; display: flex; flex-direction: column; }
@media (min-width: 640px) { .mat-card { padding: 20px; } }
.mat-card-head { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 8px; }
.mat-card-text { min-width: 0; }
.mat-card-name { font-size: 14px; line-height: 20px; font-weight: 700; color: var(--ctp-text); }
.mat-card-sub { font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); }
.mat-item { padding: 12px 0; border-top: 1px solid var(--ctp-surface0); display: flex; flex-direction: column; gap: 8px; }
.mat-item-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
/* Liens des cartes matériel (9 septembre 2026, §27) : Fiche Odoo + ticket par école, Pannes courantes par équipement */
.mat-card-links { display: flex; flex-wrap: wrap; gap: 4px 8px; margin: 2px 0 6px; }
.mat-item-links { display: flex; flex-wrap: wrap; gap: 4px 8px; }
.mat-item-links .ticket-link { min-height: 36px; padding: 4px 8px; }

/* Parc installé d'un appareil (9 septembre 2026, §29) : « N écoles équipées », filtre, lignes vers Odoo */
.parc { margin-top: 16px; border: 1px solid var(--ctp-surface0); border-radius: 8px; background-color: var(--ctp-mantle); overflow: hidden; }
.parc-summary { min-height: 52px; padding: 8px 14px; display: flex; align-items: center; gap: 10px; cursor: pointer; list-style: none; user-select: none; font-weight: 700; font-size: 14px; line-height: 20px; color: var(--ctp-text); }
.parc-summary::-webkit-details-marker { display: none; }
.parc-summary:hover { background-color: var(--ctp-surface0); }
.parc-summary .min0 { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.parc-sub { font-size: 12px; line-height: 16px; font-weight: 400; color: var(--ctp-subtext0); }
.parc[open] .mat-chevron { transform: rotate(180deg); }
.parc-body { padding: 0 10px 10px; display: flex; flex-direction: column; gap: 8px; }
.parc-search { min-height: 44px; width: 100%; padding: 8px 12px; border-radius: 6px; border: 1px solid var(--ctp-surface1); background-color: var(--ctp-base); color: var(--ctp-text); font-size: 16px; line-height: 20px; font-family: inherit; }
.parc-search::placeholder { color: var(--ctp-subtext0); }
.parc-search:focus { outline: none; border-color: transparent; box-shadow: 0 0 0 2px var(--ctp-blue); }
.parc-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; max-height: 340px; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.parc-link { min-height: 48px; display: flex; align-items: center; gap: 10px; padding: 6px 10px; border-radius: 6px; border: 1px solid transparent; color: var(--ctp-text); text-decoration: none; transition: background-color .15s cubic-bezier(.4, 0, .2, 1), border-color .15s cubic-bezier(.4, 0, .2, 1); }
.parc-link:hover { background-color: var(--ctp-surface0); border-color: var(--ctp-surface1); }
.parc-fi { font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; line-height: 16px; font-weight: 600; color: var(--ctp-subtext0); flex-shrink: 0; width: 62px; }
.parc-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.parc-nom { font-size: 13px; line-height: 18px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.parc-ville { font-size: 11px; line-height: 15px; color: var(--ctp-subtext0); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.parc-n { font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; line-height: 16px; font-weight: 700; color: var(--ctp-emerald, var(--ctp-green)); background-color: rgb(var(--ctp-green-rgb) / .12); border: 1px solid rgb(var(--ctp-green-rgb) / .3); border-radius: 999px; padding: 2px 8px; flex-shrink: 0; }
.parc-empty { margin: 4px 0 0; font-size: 13px; line-height: 18px; color: var(--ctp-subtext0); text-align: center; }
.detail-parc { padding: 0 16px 16px; }
@media (min-width: 640px) { .detail-parc { padding: 0 20px 20px; } }
.mat-item-name { font-size: 16px; line-height: 24px; font-weight: 700; color: var(--ctp-text); }
.mat-item-lot { font-size: 11px; line-height: 16px; font-weight: 600; text-transform: uppercase; letter-spacing: .025em; padding: 2px 8px; border-radius: 6px; background-color: var(--ctp-surface0); color: var(--ctp-subtext1); border: 1px solid var(--ctp-surface1); }
.mat-warranty { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; line-height: 20px; font-weight: 600; }
.mat-warranty--ok { color: var(--ctp-green); }
.mat-warranty--ko { color: var(--ctp-red); }


/* ==========================================================================
   Mode Guidé (#wizard) — Palier 3, étape 2 (REPRISE.md §20). Valeurs Tailwind 3.4 reprises à l'identique ;
   états sélectionnés via .is-selected (posé par script.js) au lieu de listes d'utilitaires conditionnelles.
   ========================================================================== */
.wizard { width: 100%; }
.wizard-panel { background-color: var(--ctp-base); border-radius: 8px; border: 1px solid var(--ctp-surface0); padding: 16px; transition: color .2s cubic-bezier(.4, 0, .2, 1), background-color .2s cubic-bezier(.4, 0, .2, 1), border-color .2s cubic-bezier(.4, 0, .2, 1); }
@media (min-width: 640px) { .wizard-panel { padding: 24px; } }
@media (min-width: 768px) { .wizard-panel { padding: 32px; } }
.wizard-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 24px; }
.wizard-head-left { display: flex; align-items: center; gap: 12px; }
.wizard-title-row { display: flex; align-items: center; gap: 10px; }
.wizard-restart { min-height: 44px; font-size: 12px; line-height: 16px; color: var(--ctp-peach); display: flex; align-items: center; gap: 6px; padding: 4px 8px; border-radius: 8px; transition: color .15s cubic-bezier(.4, 0, .2, 1), background-color .15s cubic-bezier(.4, 0, .2, 1); }
@media (min-width: 640px) { .wizard-restart { font-size: 14px; line-height: 20px; } }
.wizard-restart:hover { text-decoration: underline; background-color: var(--ctp-surface0); }
.wizard-stepper { margin-bottom: 32px; }
.wizard-question { margin: 0 0 24px; text-align: center; font-size: 16px; line-height: 24px; font-weight: 600; color: var(--ctp-text); }
@media (min-width: 640px) { .wizard-question { font-size: 18px; line-height: 28px; } }
.wizard-nav { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-top: 32px; padding-top: 20px; border-top: 1px solid var(--ctp-surface0); }
.wizard-btn { min-height: 44px; padding: 8px 16px; border-radius: 8px; font-size: 14px; line-height: 20px; font-weight: 600; transition: all .15s cubic-bezier(.4, 0, .2, 1); }
.wizard-btn:disabled { opacity: .4; cursor: not-allowed; }
.wizard-btn--prev { border: 1px solid var(--ctp-surface1); background-color: var(--ctp-surface0); color: var(--ctp-text); }
.wizard-btn--prev:hover:not(:disabled) { background-color: var(--ctp-surface1); }
.wizard-btn--prev i { margin-right: 6px; }
.wizard-btn--next { background-color: var(--ctp-peach); color: #ffffff; }
.wizard-btn--next:hover:not(:disabled) { opacity: .95; }
.wizard-btn--next i { margin-left: 6px; }
.wizard-counter { font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); font-weight: 500; text-align: center; }

.wizard-grid { display: grid; grid-template-columns: minmax(0, 1fr); }
.wizard-grid--domains { gap: 14px; }
.wizard-grid--subs { gap: 12px; }
@media (min-width: 640px) { .wizard-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.wizard-choice-btn, .wizard-sub-btn, .wizard-item-btn {
    width: 100%; text-align: left; border: 1px solid var(--ctp-surface0); background-color: var(--ctp-mantle);
    display: flex; align-items: center; transition: all .15s cubic-bezier(.4, 0, .2, 1);
}
.wizard-choice-btn:hover, .wizard-sub-btn:hover, .wizard-item-btn:hover { background-color: var(--ctp-surface0); }
.wizard-choice-btn { min-height: 64px; padding: 16px; border-radius: 8px; gap: 14px; }
.wizard-choice-btn.is-selected { border-color: var(--ctp-blue); background-color: rgb(var(--ctp-blue-rgb) / .1); box-shadow: 0 0 0 2px var(--ctp-blue); }
.wizard-choice-ic { transition: transform .15s cubic-bezier(.4, 0, .2, 1); }
.wizard-choice-btn:hover .wizard-choice-ic { transform: scale(1.05); }
.wizard-choice-text { min-width: 0; flex: 1 1 0%; }
.wizard-choice-title { font-weight: 700; font-size: 14px; line-height: 20px; color: var(--ctp-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (min-width: 640px) { .wizard-choice-title { font-size: 16px; line-height: 24px; } }
.wizard-choice-desc { margin-top: 2px; font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wizard-choice-arrow { font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); flex-shrink: 0; transition: transform .15s cubic-bezier(.4, 0, .2, 1); }
.wizard-choice-btn:hover .wizard-choice-arrow { transform: translateX(4px); }
.wizard-sub-btn, .wizard-item-btn { min-height: 52px; padding: 14px; border-radius: 8px; gap: 12px; }
.wizard-sub-btn.is-selected { border-color: var(--ctp-blue); background-color: rgb(var(--ctp-blue-rgb) / .1); }
.wizard-sub-title { font-weight: 700; font-size: 12px; line-height: 16px; color: var(--ctp-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (min-width: 640px) { .wizard-sub-title { font-size: 14px; line-height: 20px; } }
.wizard-sub-title--block { display: block; }
/* Étape Équipement : nom du lot sur deux lignes au plus, icône SVG tracée (9 septembre 2026) */
.wizard-sub-title--wrap { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; white-space: normal; overflow: hidden; }
.wizard-sub-ic { flex-shrink: 0; }
.wizard-sub-ic .ki { width: 20px; height: 20px; }
.wizard-sub-btn:hover .ki, .wizard-sub-btn:active .ki { animation: ki-nudge .5s cubic-bezier(.19, 1, .22, 1); }
.wizard-sub-count { font-size: 11px; line-height: 16px; color: var(--ctp-subtext0); }
.wizard-list { display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; max-height: 50vh; overflow-y: auto; padding-right: 4px; }
.wizard-item-btn { justify-content: space-between; }
.wizard-item-main { display: flex; align-items: center; gap: 12px; min-width: 0; }
.wizard-item-go { font-size: 12px; line-height: 16px; color: var(--ctp-peach); font-weight: 600; flex-shrink: 0; }
.wizard-empty { text-align: center; padding: 40px 0; color: var(--ctp-subtext0); }
.wizard-empty-ic { margin: 0 auto 8px; }
.i-base { font-size: 16px; line-height: 24px; }
.wizard-empty-text { margin: 0; font-size: 14px; line-height: 20px; font-weight: 600; color: var(--ctp-text); }
.wizard-empty-btn { margin-top: 16px; font-size: 12px; line-height: 16px; font-weight: 700; }
.wizard-results { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; max-height: 60vh; overflow-y: auto; padding-right: 4px; }
@media (min-width: 768px) { .wizard-results { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.wizard-result { padding: 16px; border-radius: 8px; background-color: var(--ctp-mantle); border: 1px solid var(--ctp-surface0); display: flex; flex-direction: column; justify-content: space-between; gap: 12px; }
.wizard-result-head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.wizard-result-title { margin: 0; font-weight: 700; font-size: 14px; line-height: 1.375; color: var(--ctp-text); }
.wizard-result-desc { margin: 0; font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.wizard-result-btn { min-height: 44px; width: 100%; padding: 8px 12px; border-radius: 8px; background-color: var(--ctp-surface0); color: var(--ctp-peach); font-size: 12px; line-height: 16px; font-weight: 700; display: flex; align-items: center; justify-content: center; gap: 8px; transition: color .15s cubic-bezier(.4, 0, .2, 1), background-color .15s cubic-bezier(.4, 0, .2, 1); }
.wizard-result-btn:hover { background-color: var(--ctp-surface1); }


/* ==========================================================================
   Mode Pointage, modales, tiroirs, toast, pied de page, mascotte, modale d'import Odoo — Palier 3,
   étape 2 (REPRISE.md §20). Valeurs Tailwind 3.4 reprises à l'identique. Hooks conservés parce que
   basculés par le JS ou des onclick inline : .translate-x-full, .opacity-0, .animate-pulse.
   Corrige au passage : .bordered-icon-peach (utilisée sans règle depuis l'origine) et la feuille de la
   modale Odoo qui restait hors écran sur téléphone (translate-y-full jamais retiré).
   ========================================================================== */
.tracker { width: 100%; display: flex; flex-direction: column; gap: 16px; }
.tracker-panel { background-color: var(--ctp-base); border-radius: 8px; border: 1px solid var(--ctp-surface0); padding: 14px; display: flex; flex-direction: column; gap: 16px; transition: color .2s cubic-bezier(.4, 0, .2, 1), background-color .2s cubic-bezier(.4, 0, .2, 1), border-color .2s cubic-bezier(.4, 0, .2, 1); }
@media (min-width: 640px) { .tracker-panel { padding: 20px; } }
@media (min-width: 768px) { .tracker-panel { padding: 24px; } }
.tracker-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding-bottom: 12px; border-bottom: 1px solid var(--ctp-surface0); }
.tracker-head-left { display: flex; align-items: center; gap: 10px; }
.tracker-title { margin: 0; font-size: 18px; line-height: 1.25; font-weight: 700; color: var(--ctp-text); }
@media (min-width: 640px) { .tracker-title { font-size: 20px; } }
.net-badge { margin: 2px 0 0; font-size: 12px; line-height: 16px; font-weight: 600; display: flex; align-items: center; gap: 6px; }
.net-badge--on { color: var(--ctp-green); }
.net-badge--off { color: var(--ctp-peach); }
.net-dot { width: 8px; height: 8px; border-radius: 9999px; display: inline-block; }
.net-dot--on { background-color: var(--ctp-green); animation: ping 1s cubic-bezier(0, 0, .2, 1) infinite; }
.net-dot--off { background-color: var(--ctp-peach); }
.net-dot--mr { margin-right: 4px; }
@keyframes ping { 75%, 100% { transform: scale(2); opacity: 0; } }
.tracker-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.tbtn {
    min-height: 44px; padding: 8px 14px; border-radius: 8px;
    background-color: var(--ctp-surface0); color: var(--ctp-text); border: 1px solid var(--ctp-surface1);
    font-size: 12px; line-height: 16px; font-weight: 600;
    display: flex; align-items: center; gap: 8px; transition: all .15s cubic-bezier(.4, 0, .2, 1);
}
.tbtn:hover { background-color: var(--ctp-surface1); }
.tbtn:active { transform: scale(.95); }
@media (min-width: 640px) { .tbtn { font-size: 14px; line-height: 20px; } }
.tbtn--peach { background-color: rgb(var(--ctp-peach-rgb) / .15); color: var(--ctp-peach); border-color: rgb(var(--ctp-peach-rgb) / .3); font-size: 12px; line-height: 16px; font-weight: 700; }
.tbtn--peach:hover { background-color: rgb(var(--ctp-peach-rgb) / .15); }
.gps-band { background-color: var(--ctp-mantle); border: 1px solid var(--ctp-surface0); border-radius: 8px; padding: 14px; display: flex; flex-direction: column; justify-content: space-between; gap: 12px; }
@media (min-width: 640px) { .gps-band { padding: 16px; flex-direction: row; align-items: center; } }
.gps-main { min-width: 0; flex: 1 1 0%; }
.gps-row { display: flex; align-items: center; gap: 8px; font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); margin-bottom: 2px; }
.gps-school { font-size: 14px; line-height: 20px; font-weight: 700; color: var(--ctp-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (min-width: 640px) { .gps-school { font-size: 16px; line-height: 24px; } }
.gps-details { font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-top: 2px; }
.gps-side { flex-shrink: 0; display: flex; align-items: center; gap: 8px; }
.dist-badge { display: inline-block; padding: 4px 10px; border-radius: 9999px; font-size: 12px; line-height: 16px; font-weight: 700; border: 1px solid transparent; }
.dist-badge--peach { background-color: rgb(var(--ctp-peach-rgb) / .15); color: var(--ctp-peach); border-color: rgb(var(--ctp-peach-rgb) / .3); }
.dist-badge--green { background-color: rgb(var(--ctp-green-rgb) / .15); color: var(--ctp-green); border-color: rgb(var(--ctp-green-rgb) / .3); }
.dist-badge--neutral { background-color: var(--ctp-surface0); color: var(--ctp-subtext0); border-color: var(--ctp-surface1); }
.btn-peach { min-height: 44px; padding: 0 14px; border-radius: 8px; background-color: var(--ctp-peach); color: #ffffff; font-weight: 600; font-size: 14px; line-height: 20px; display: inline-flex; align-items: center; gap: 8px; transition: transform .15s cubic-bezier(.4, 0, .2, 1); }
.dark .btn-peach { color: #1c1c1c; }
.btn-peach:active { transform: scale(.95); }
.btn-peach--sm { padding: 0 12px; font-size: 12px; line-height: 16px; gap: 6px; }
.btn-peach--wide { padding: 0 16px; }
.btn-peach--nowrap { white-space: nowrap; }
.btn-peach--bold-xs { font-size: 12px; line-height: 16px; font-weight: 700; padding: 8px 16px; }
.btn-neutral { min-height: 44px; padding: 0 16px; border-radius: 8px; background-color: var(--ctp-surface0); border: 1px solid var(--ctp-surface1); color: var(--ctp-text); font-weight: 600; font-size: 14px; line-height: 20px; display: inline-flex; align-items: center; gap: 8px; transition: background-color .15s cubic-bezier(.4, 0, .2, 1); }
.btn-neutral:hover { background-color: var(--ctp-surface1); }
.btn-neutral--xs { padding: 8px 16px; font-size: 12px; line-height: 16px; border-color: transparent; }
.gps-materiel { background-color: var(--ctp-mantle); border: 1px solid var(--ctp-surface0); border-radius: 8px; padding: 4px 14px; }
@media (min-width: 640px) { .gps-materiel { padding: 4px 16px; } }
.tracker-map-wrapper { width: 100%; height: 380px; border-radius: 8px; overflow: hidden; border: 1px solid var(--ctp-surface0); box-shadow: inset 0 2px 4px 0 rgb(0 0 0 / .05); }
@media (min-width: 640px) { .tracker-map-wrapper { height: 450px; } }
@media (min-width: 768px) { .tracker-map-wrapper { height: 500px; } }
.tracker-map { width: 100%; height: 100%; background-color: var(--ctp-crust); }
.map-ctl { position: absolute; z-index: 20; display: flex; }
.map-ctl--tl { top: 12px; left: 12px; }
.map-ctl--tr { top: 12px; right: 12px; }
.map-ctl--actions { top: 64px; left: 12px; flex-direction: column; gap: 8px; }
.map-resto-btn { min-height: 44px; height: 44px; width: 44px; border-radius: 8px; background-color: rgb(var(--ctp-base-rgb) / .95); box-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1); border: 1px solid var(--ctp-surface1); font-size: 20px; line-height: 28px; display: flex; align-items: center; justify-content: center; transition: transform .15s cubic-bezier(.4, 0, .2, 1); }
.map-resto-btn:hover { transform: scale(1.05); }
.map-switch { border-radius: 8px; background-color: rgb(var(--ctp-base-rgb) / .95); box-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1); border: 1px solid var(--ctp-surface1); padding: 2px; font-size: 12px; line-height: 16px; }
.map-switch-btn { min-height: 44px; padding: 8px 12px; border-radius: 8px; font-weight: 500; color: var(--ctp-subtext0); display: flex; align-items: center; gap: 6px; transition: all .15s cubic-bezier(.4, 0, .2, 1); }
.map-switch-btn:hover { color: var(--ctp-text); }
.map-switch-btn.is-on { font-weight: 700; background-color: var(--ctp-blue); color: var(--ctp-base); }
.map-switch-btn.is-on:hover { color: var(--ctp-base); }

/* Interrupteur jour/nuit du fond de carte (§34) : pastille qui glisse avec un léger dépassement
   élastique et s'étire pendant le mouvement — effet « liquide » discret, coupé si l'utilisateur
   a demandé moins d'animations. Par défaut la carte suit le thème du site ; toucher l'interrupteur
   fige le choix jusqu'au prochain changement de thème. */
.map-dn { position: relative; flex-shrink: 0; width: 54px; height: 30px; margin-left: 2px; border-radius: 999px; border: 1px solid var(--ctp-surface1); background-color: var(--ctp-surface0); cursor: pointer; padding: 0; overflow: hidden; }
.map-dn-rail { position: absolute; inset: 0; border-radius: inherit; background-image: linear-gradient(120deg, #3b4a6b, #1c2438); opacity: 0; transition: opacity .35s cubic-bezier(.4, 0, .2, 1); }
.map-dn.is-night .map-dn-rail { opacity: 1; }
.map-dn-knob { position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: 999px; display: grid; place-items: center; color: #b7791f; background-color: #ffffff; box-shadow: 0 1px 3px rgb(0 0 0 / .35);
    transition: left .45s cubic-bezier(.6, -0.28, .3, 1.3), width .3s cubic-bezier(.4, 0, .2, 1), color .35s cubic-bezier(.4, 0, .2, 1), background-color .35s cubic-bezier(.4, 0, .2, 1); }
.map-dn.is-night .map-dn-knob { left: 27px; color: #e8eaf2; background-color: #2a3350; }
.map-dn:active .map-dn-knob { width: 28px; }
.map-dn.is-night:active .map-dn-knob { left: 21px; }
.map-dn:focus-visible { outline: 2px solid var(--ctp-peach); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .map-dn-knob, .map-dn-rail { transition: none; } }
/* Demande du 10 septembre 2026 : le DESSIN passe en blanc sur fond sombre et en noir sur fond clair,
   la pastille gardant sa teinte de catégorie. Placée ici, donc après les règles `.bordered-icon-*` qui
   fixaient aussi la couleur du trait ; les trois règles qui suivent la battent volontairement. */
.bordered-icon-box { color: var(--icon-ink); }
.ib-onwhite { border-color: rgb(255 255 255 / .4); background-color: rgb(255 255 255 / .2); color: #ffffff; }
.ib-plain-border { border-color: var(--ctp-surface1); color: currentColor; }
.ib-muted-border { border-color: var(--ctp-surface1); color: var(--ctp-subtext0); }
.map-recenter { position: absolute; right: 12px; bottom: 12px; z-index: 20; min-height: 44px; min-width: 44px; width: 44px; height: 44px; border-color: var(--ctp-surface1); background-color: rgb(var(--ctp-base-rgb) / .95); color: var(--ctp-peach); box-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1); transition: all .15s cubic-bezier(.4, 0, .2, 1); }
.map-recenter:hover { background-color: var(--ctp-surface0); }
.map-recenter:active { transform: scale(.9); }
.btn-go { min-height: 44px; padding: 10px 16px; border-radius: 8px; color: #ffffff; font-weight: 700; font-size: 14px; line-height: 20px; display: flex; align-items: center; gap: 8px; transition: all .15s cubic-bezier(.4, 0, .2, 1); }
.btn-go--arrivee { background-image: linear-gradient(to right, #059669, #0d9488); box-shadow: 0 4px 6px -1px rgb(6 78 59 / .3), 0 2px 4px -2px rgb(6 78 59 / .3); }
.btn-go--depart { background-image: linear-gradient(to right, #d97706, #ea580c); box-shadow: 0 4px 6px -1px rgb(124 45 18 / .3), 0 2px 4px -2px rgb(124 45 18 / .3); }
.btn-go:hover { box-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1); filter: brightness(1.1); }
.btn-go:active { transform: scale(.95); filter: brightness(.95); }
.btn-go--sm { display: inline-flex; padding: 0 12px; font-size: 12px; line-height: 16px; gap: 6px; box-shadow: none; }
.btn-go--sm:active { background-image: linear-gradient(to right, #047857, #0f766e); filter: none; }
.btn-go.is-flash { box-shadow: 0 0 0 4px var(--ctp-green); }
.horszone { width: 220px; background-color: var(--ctp-base); border: 1px solid rgb(var(--ctp-peach-rgb) / .4); border-radius: 8px; box-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1); padding: 12px; }
.horszone-row { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.horszone-text { font-size: 12px; line-height: 1.375; font-weight: 600; color: var(--ctp-text); }
.horszone-btns { display: flex; gap: 8px; }
.horszone-btn { flex: 1 1 0%; min-height: 38px; border-radius: 8px; font-size: 12px; line-height: 16px; font-weight: 700; display: flex; align-items: center; justify-content: center; gap: 6px; transition: transform .15s cubic-bezier(.4, 0, .2, 1); }
.horszone-btn:active { transform: scale(.95); }
.horszone-btn--oui { background-color: var(--ctp-peach); color: #ffffff; }
.horszone-btn--non { background-color: var(--ctp-surface0); color: var(--ctp-text); }
.map-detail { background-color: var(--ctp-mantle); border: 1px solid var(--ctp-surface0); border-radius: 8px; padding: 14px; }
@media (min-width: 640px) { .map-detail { padding: 16px; } }
.map-detail-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.map-detail-name { font-weight: 700; color: var(--ctp-text); font-size: 14px; line-height: 1.375; margin-top: 4px; }
@media (min-width: 640px) { .map-detail-name { font-size: 16px; } }
.map-detail-addr { font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); margin-top: 2px; }
.link-xs { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; line-height: 16px; color: var(--ctp-peach); margin-bottom: 8px; }
.link-xs:hover { text-decoration: underline; }
.min0 { min-width: 0; }
.row-2 { display: flex; align-items: center; gap: 8px; }
.row-15 { display: flex; align-items: center; gap: 6px; }
.grow-min { min-width: 0; flex: 1 1 0%; }
.stack-2 > * + * { margin-top: 2px; }
.self-center { align-self: center; flex-shrink: 0; }
.ib-top { margin-top: 2px; }
.ib-empty { margin: 0 auto 8px; color: var(--ctp-subtext0); }
.ib-center-peach { margin: 0 auto; color: var(--ctp-peach); }
.fi-chip { padding: 2px 6px; border-radius: 4px; background-color: rgb(var(--ctp-blue-rgb) / .15); color: var(--ctp-blue); font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; line-height: 16px; font-weight: 700; border: 1px solid rgb(var(--ctp-blue-rgb) / .3); }
.fi-name { font-weight: 700; color: var(--ctp-text); font-size: 14px; line-height: 1.375; }
.fi-name--trunc, .fi-addr--trunc { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fi-addr { font-size: 11px; line-height: 16px; color: var(--ctp-subtext0); margin-top: 4px; }
.ecole-item { padding: 12px; border-radius: 8px; background-color: var(--ctp-mantle); border: 1px solid var(--ctp-surface0); }
.drawer-count { margin: 0 0 8px; font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); }
.fi-choice { min-height: 52px; width: 100%; text-align: left; padding: 12px; border-radius: 8px; background-color: var(--ctp-mantle); border: 1px solid var(--ctp-surface0); display: flex; align-items: flex-start; gap: 12px; transition: all .15s cubic-bezier(.4, 0, .2, 1); }
@media (min-width: 640px) { .fi-choice { padding: 14px; } }
.fi-choice:hover { background-color: var(--ctp-surface0); }
.fi-choice:active { background-color: var(--ctp-surface1); }

/* Modales (relevé de frais, choix du FI) */
.modal { position: fixed; inset: 0; background-color: rgb(0 0 0 / .75); display: flex; align-items: flex-end; justify-content: center; padding: 0; }
@media (min-width: 640px) { .modal { align-items: center; padding: 16px; } }
.modal--frais { z-index: 220; }
.modal--fi { z-index: 210; }
.modal-sheet { background-color: var(--ctp-base); border: 1px solid var(--ctp-surface0); width: 100%; border-radius: 8px 16px 0 0; box-shadow: 0 25px 50px -12px rgb(0 0 0 / .25); display: flex; flex-direction: column; }
@media (min-width: 640px) { .modal-sheet { border-radius: 8px; } }
.modal-sheet--frais { max-width: 42rem; max-height: 92vh; }
.modal-sheet--fi { max-width: 32rem; max-height: 85vh; padding: 16px; }
@media (min-width: 640px) { .modal-sheet--fi { padding: 24px; } }
.modal-head { padding: 16px; border-bottom: 1px solid var(--ctp-surface0); display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.modal-body { flex: 1 1 0%; overflow: auto; padding: 16px; }
.modal-foot { padding: 16px; border-top: 1px solid var(--ctp-surface0); display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; }
@media (min-width: 640px) { .modal-head, .modal-body, .modal-foot { padding: 20px; } }
.frais-sub { margin: 2px 0 0; font-size: 14px; line-height: 20px; color: var(--ctp-subtext0); }
.frais-table { width: 100%; font-size: 14px; line-height: 20px; border-collapse: collapse; }
.frais-table thead tr { text-align: left; font-size: 11px; line-height: 16px; text-transform: uppercase; letter-spacing: .05em; color: var(--ctp-subtext0); border-bottom: 1px solid var(--ctp-surface1); }
.frais-table th { padding: 8px 12px 8px 0; font-weight: 700; }
.frais-table tbody tr { border-bottom: 1px solid var(--ctp-surface0); }
.frais-table td { padding: 8px 12px 8px 0; }
.frais-table th:last-child, .frais-table td:last-child { padding-right: 0; }
.frais-table td.frais-empty { padding: 24px 0; text-align: center; color: var(--ctp-subtext0); }
.mono { font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; }
.nowrap { white-space: nowrap; }
.frais-total { margin: 16px 0 0; font-size: 14px; line-height: 20px; font-weight: 700; color: var(--ctp-text); }
.frais-note { margin: 4px 0 0; font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); }
.fi-head { display: flex; align-items: center; justify-content: space-between; padding-bottom: 12px; border-bottom: 1px solid var(--ctp-surface0); }
.fi-head-left { display: flex; align-items: center; gap: 12px; }
.fi-title { margin: 0; font-weight: 700; color: var(--ctp-text); font-size: 14px; line-height: 20px; }
@media (min-width: 640px) { .fi-title { font-size: 16px; line-height: 24px; } }
.fi-sub { margin: 0; font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); }
.fi-intro { margin: 12px 0; font-size: 12px; line-height: 16px; color: var(--ctp-text); }
.fi-action { font-weight: 700; }
.fi-action--blue { color: var(--ctp-blue); }
.fi-action--green { color: var(--ctp-green); }
.fi-action--peach { color: var(--ctp-peach); }
.fi-list { display: flex; flex-direction: column; gap: 8px; overflow-y: auto; margin: 8px 0; padding-right: 4px; max-height: 50vh; }
.fi-foot { padding-top: 12px; border-top: 1px solid var(--ctp-surface0); margin-top: auto; display: flex; justify-content: flex-end; }

/* Tiroirs (Historique, Agenda, Liste des écoles) */
.drawer { position: fixed; top: 0; bottom: 0; right: 0; width: 100%; max-width: 28rem; background-color: var(--ctp-base); border-left: 1px solid var(--ctp-surface0); z-index: 200; display: flex; flex-direction: column; box-shadow: 0 25px 50px -12px rgb(0 0 0 / .25); }
.translate-x-full { transform: translateX(100%); }   /* hook basculé par script.js (ouverture/fermeture) */
.drawer-head { padding: 16px; border-bottom: 1px solid var(--ctp-surface0); display: flex; align-items: center; justify-content: space-between; background-color: var(--ctp-mantle); }
.drawer-title { margin: 0; font-weight: 700; color: var(--ctp-text); font-size: 14px; line-height: 20px; display: flex; align-items: center; gap: 10px; }
.drawer-head-btns { display: flex; align-items: center; gap: 6px; }
.close-x { min-height: 44px; min-width: 44px; display: flex; align-items: center; justify-content: center; padding: 8px; color: var(--ctp-subtext0); transition: color .15s cubic-bezier(.4, 0, .2, 1), background-color .15s cubic-bezier(.4, 0, .2, 1); }
.close-x:hover { color: var(--ctp-text); }
.close-x--nopad { padding: 0; flex-shrink: 0; }
.close-x--peach { color: var(--ctp-peach); }
.close-x--hover { border-radius: 8px; }
.close-x--hover:hover { background-color: var(--ctp-surface0); }
.drawer-tools { padding: 16px; border-bottom: 1px solid var(--ctp-surface0); background-color: rgb(var(--ctp-mantle-rgb) / .5); display: flex; flex-direction: column; gap: 8px; }
.drawer-tools--tight { padding: 12px; display: block; }
.drawer-label { font-size: 11px; line-height: 16px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--ctp-subtext0); }
.drawer-label--block { display: block; font-size: 12px; margin-bottom: 8px; }
.field { min-height: 44px; border-radius: 8px; border: 1px solid var(--ctp-surface1); font-size: 14px; line-height: 20px; color: var(--ctp-text); padding: 0 12px; font-family: inherit; }
.field--grow { flex: 1 1 0%; min-width: 0; background-color: var(--ctp-base); }
.field--full { width: 100%; background-color: var(--ctp-surface0); padding: 8px 12px; }
.field--full:focus { outline: none; box-shadow: 0 0 0 2px var(--ctp-blue); }
.drawer-list { flex: 1 1 0%; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 10px; }
.drawer-list--tight { gap: 8px; }
.drawer-list-inner { display: flex; flex-direction: column; gap: 10px; }
.drawer-list-inner--mb { margin-bottom: 20px; }
.drawer-empty { text-align: center; font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); padding: 40px 0; }
.drawer-empty--stack { padding: 40px 16px; display: flex; flex-direction: column; align-items: center; gap: 12px; }
.empty-title { font-weight: 700; color: var(--ctp-text); font-size: 14px; line-height: 20px; }
.note { padding: 12px; margin-bottom: 8px; border-radius: 8px; font-size: 12px; line-height: 16px; }
.note--peach { background-color: rgb(var(--ctp-peach-rgb) / .15); border: 1px solid rgb(var(--ctp-peach-rgb) / .3); color: var(--ctp-peach); }
.hist-item { padding: 12px; background-color: var(--ctp-mantle); border: 1px solid var(--ctp-surface0); border-radius: 8px; display: flex; align-items: flex-start; gap: 12px; }
@media (min-width: 640px) { .hist-item { padding: 14px; } }
.hist-row { display: flex; align-items: center; justify-content: space-between; gap: 4px; }
.hist-row--xs { font-size: 12px; line-height: 16px; }
.hist-action { font-weight: 700; font-size: 12px; line-height: 16px; color: var(--ctp-text); }
.hist-time { font-size: 10px; line-height: 15px; color: var(--ctp-subtext0); }
.hist-nom { font-size: 12px; line-height: 16px; color: var(--ctp-text); font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-top: 2px; }
.hist-meta { font-size: 10px; line-height: 15px; color: var(--ctp-subtext0); margin-top: 2px; }
@media (min-width: 640px) { .hist-nom { font-size: 14px; line-height: 20px; } .hist-meta { font-size: 12px; line-height: 16px; } }
.agenda-tabs { padding: 8px; border-bottom: 1px solid var(--ctp-surface0); background-color: var(--ctp-mantle); display: flex; gap: 4px; font-size: 12px; line-height: 16px; }
.agenda-tab { min-height: 44px; flex: 1 1 0%; padding: 8px 12px; border-radius: 8px; font-weight: 500; color: var(--ctp-subtext0); display: flex; align-items: center; justify-content: center; gap: 6px; transition: all .15s cubic-bezier(.4, 0, .2, 1); }
.agenda-tab:hover { color: var(--ctp-text); }
.agenda-tab.is-on { font-weight: 700; background-color: var(--ctp-blue); color: var(--ctp-base); }
.agenda-tab.is-on:hover { color: var(--ctp-base); }
.agenda-tab-count { margin-left: 4px; padding: 2px 6px; border-radius: 9999px; font-size: 10px; line-height: 15px; background-color: rgb(255 255 255 / .3); color: #ffffff; font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; }
.agenda-date { padding: 16px; border-bottom: 1px solid var(--ctp-surface0); background-color: rgb(var(--ctp-mantle-rgb) / .5); }
.agenda-group { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }
.agenda-group-title { font-size: 12px; line-height: 16px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; display: flex; align-items: center; gap: 6px; margin-bottom: 8px; }
.agenda-group-title--between { justify-content: space-between; padding: 0 4px; margin-bottom: 0; }
.count-pill { font-size: 11px; line-height: 16px; font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; padding: 2px 8px; border-radius: 9999px; background-color: var(--ctp-surface0); color: var(--ctp-text); }
.mission-card { padding: 12px; background-color: var(--ctp-mantle); border: 1px solid var(--ctp-surface0); border-radius: 8px; display: flex; flex-direction: column; gap: 10px; }
@media (min-width: 640px) { .mission-card { padding: 14px; } }
.mission-card:hover { border-color: var(--ctp-surface1); }
.mission-head { display: flex; align-items: flex-start; gap: 12px; }
.mission-row { display: flex; align-items: center; justify-content: space-between; gap: 4px; font-size: 12px; line-height: 16px; }
.mission-type { font-weight: 700; color: var(--ctp-peach); text-transform: uppercase; letter-spacing: .025em; font-size: 11px; line-height: 16px; }
.mission-date { font-size: 11px; line-height: 16px; font-weight: 700; color: var(--ctp-subtext0); }
.mission-school { font-weight: 700; font-size: 12px; line-height: 16px; color: var(--ctp-text); }
@media (min-width: 640px) { .mission-school { font-size: 14px; line-height: 20px; } }
.mission-fi { font-size: 11px; line-height: 16px; font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--ctp-blue); font-weight: 600; }
.mission-fi--base { font-size: 12px; font-weight: 700; }
.mission-nom { font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); font-weight: 500; }
.mission-contact { font-size: 11px; line-height: 16px; color: var(--ctp-subtext1); display: flex; align-items: center; gap: 6px; margin-top: 2px; }
.mission-foot { display: flex; align-items: center; justify-content: flex-end; gap: 8px; padding-top: 4px; border-top: 1px solid rgb(var(--ctp-surface0-rgb) / .6); }
.mini-badge { padding: 2px 8px; border-radius: 9999px; font-size: 10px; line-height: 15px; font-weight: 700; border: 1px solid transparent; }
.mini-badge--red { background-color: rgb(var(--ctp-red-rgb) / .2); color: var(--ctp-red); border-color: rgb(var(--ctp-red-rgb) / .3); }
.mini-badge--green { background-color: rgb(var(--ctp-green-rgb) / .2); color: var(--ctp-green); border-color: rgb(var(--ctp-green-rgb) / .3); }
.mini-badge--neutral { background-color: var(--ctp-surface1); color: var(--ctp-subtext0); font-weight: 600; }
.animate-pulse { animation: pulse 2s cubic-bezier(.4, 0, .6, 1) infinite; }   /* hook basculé par script.js (bouton resto) */
@keyframes pulse { 50% { opacity: .5; } }
.backdrop { position: fixed; inset: 0; background-color: rgb(0 0 0 / .6); z-index: 190; }
.toast { position: fixed; top: 20px; left: 50%; transform: translate(-50%, 0); z-index: 300; background-color: var(--ctp-crust); border: 1px solid var(--ctp-surface1); color: var(--ctp-text); font-size: 12px; line-height: 16px; padding: 10px 16px; border-radius: 8px; box-shadow: 0 25px 50px -12px rgb(0 0 0 / .25); display: flex; align-items: center; gap: 8px; pointer-events: none; transition: all .3s cubic-bezier(.4, 0, .2, 1); opacity: 1; }
.toast--out { opacity: 0; transform: translate(-50%, -16px); }
.is-flash-peach { box-shadow: 0 0 0 2px var(--ctp-peach); }
.ic-blue { color: var(--ctp-blue); }
.ic-muted { color: var(--ctp-subtext0); }
.i-lg { font-size: 18px; line-height: 28px; }
.i-2xl { font-size: 24px; line-height: 32px; }
.bordered-icon-peach { background-color: color-mix(in srgb, var(--ctp-peach) 8%, var(--ctp-base)); border-color: color-mix(in srgb, var(--ctp-peach) 28%, var(--ctp-surface0)); color: var(--ctp-peach); }

/* Pied de page, mascotte */
.site-footer { background-color: var(--ctp-crust); border-top: 1px solid var(--ctp-surface0); margin-top: auto; transition: color .2s cubic-bezier(.4, 0, .2, 1), background-color .2s cubic-bezier(.4, 0, .2, 1), border-color .2s cubic-bezier(.4, 0, .2, 1); }
.site-footer-inner { padding: 24px 16px; text-align: center; font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); }
/* Dates de mise à jour des bases : très discret sous le pied de page (§33) */
/* --ctp-overlay0 donnait 2,14:1 en clair et 3,62:1 en sombre pour un texte de 10 px (axe-core,
   10 septembre 2026). --ctp-subtext0 monte à 4,72:1 et 7,76:1, au-dessus des 4,5:1 exigés. */
.site-footer-maj { margin: 6px 0 0; font-size: 10px; line-height: 14px; color: var(--ctp-subtext0); font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: .01em; }
.site-footer-maj:empty { display: none; }
@media (min-width: 640px) { .site-footer-inner { font-size: 14px; line-height: 20px; } }
.mascot-title { margin: 0; font-size: 18px; line-height: 28px; font-weight: 700; color: var(--ctp-text); }
.mascot-text { margin: 0; font-size: 14px; line-height: 20px; color: var(--ctp-subtext0); }

/* Modale d'import Odoo */
.omodal { position: fixed; inset: 0; z-index: 100; display: flex; align-items: flex-end; justify-content: center; padding: 0; transition: opacity .3s cubic-bezier(.4, 0, .2, 1); }
@media (min-width: 640px) { .omodal { align-items: center; padding: 16px; } }
.opacity-0 { opacity: 0; }   /* hook basculé par script.js et des onclick inline (modale Odoo) */
.omodal-backdrop { position: fixed; inset: 0; background-color: rgb(var(--ctp-crust-rgb) / .8); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); }
.omodal-sheet { position: relative; background-color: var(--ctp-base); width: 100%; max-width: 28rem; box-shadow: 0 25px 50px -12px rgb(0 0 0 / .25); display: flex; flex-direction: column; max-height: 90vh; border-radius: 8px 16px 0 0; transform: translateY(100%); transition: transform .3s cubic-bezier(.4, 0, .2, 1); }
@media (min-width: 640px) { .omodal-sheet { width: 90%; max-height: 85vh; border-radius: 8px; transform: none; } }
.omodal:not(.opacity-0) .omodal-sheet { transform: none; }   /* sur téléphone, la feuille remonte à l'ouverture (avant : restait hors écran) */
.omodal-head { padding: 16px; border-bottom: 1px solid var(--ctp-surface0); display: flex; align-items: center; justify-content: space-between; position: sticky; top: 0; background-color: var(--ctp-base); z-index: 10; border-radius: 8px 16px 0 0; }
.omodal-title { margin: 0; font-weight: 700; color: var(--ctp-text); font-size: 18px; line-height: 28px; display: flex; align-items: center; gap: 12px; }
.omodal-body { padding: 20px; overflow-y: auto; }
.omodal-intro { font-size: 14px; line-height: 20px; color: var(--ctp-subtext0); margin-bottom: 16px; }
.omodal-list { list-style: disc; padding-left: 20px; margin: 8px 0 0; color: var(--ctp-text); font-weight: 500; font-size: 12px; line-height: 16px; }
.omodal-list li + li { margin-top: 4px; }
.dropzone { border: 2px dashed var(--ctp-surface1); border-radius: 8px; padding: 32px; text-align: center; transition: border-color .15s cubic-bezier(.4, 0, .2, 1), background-color .15s cubic-bezier(.4, 0, .2, 1); cursor: pointer; position: relative; overflow: hidden; background-color: var(--ctp-mantle); }
.dropzone:hover, .dropzone.is-dragover { border-color: var(--ctp-peach); }
.dropzone.is-dragover { background-color: var(--ctp-surface0); }
.dropzone-input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; z-index: 10; }
.dropzone-ic { margin: 0 auto 12px; transition: transform .15s cubic-bezier(.4, 0, .2, 1); }
.dropzone:hover .dropzone-ic { transform: scale(1.1); }
.dropzone-title { font-weight: 700; color: var(--ctp-text); margin-bottom: 4px; }
.dropzone-sub { font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; }
.fb { margin-top: 16px; font-size: 14px; line-height: 20px; padding: 12px; border-radius: 8px; border: 1px solid transparent; }
.fb i { margin-right: 8px; }
.fb--neutral { background-color: var(--ctp-surface0); border-color: var(--ctp-surface1); color: var(--ctp-text); }
.fb--ok { background-color: rgb(var(--ctp-green-rgb) / .2); border-color: rgb(var(--ctp-green-rgb) / .3); color: var(--ctp-green); font-weight: 500; }
.fb--ko { background-color: rgb(var(--ctp-red-rgb) / .2); border-color: rgb(var(--ctp-red-rgb) / .3); color: var(--ctp-red); font-weight: 500; }


/* Corps d'index.html (anciennement utilitaires sur <body>) et bloc « matériel inventorié » du Pointage */
.site-body { display: flex; flex-direction: column; min-height: 100vh; transition: color .2s cubic-bezier(.4, 0, .2, 1), background-color .2s cubic-bezier(.4, 0, .2, 1); }
.site-body ::selection { background-color: rgb(var(--ctp-blue-rgb) / .2); color: var(--ctp-blue); }
.mat-summary { min-height: 44px; display: flex; align-items: center; gap: 10px; cursor: pointer; list-style: none; user-select: none; font-size: 14px; line-height: 20px; font-weight: 600; color: var(--ctp-text); }
.mat-summary::-webkit-details-marker { display: none; }
.mat-summary-sub { display: block; font-size: 12px; line-height: 16px; font-weight: 400; color: var(--ctp-subtext0); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mat-chevron { font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); margin-left: auto; transition: transform .15s cubic-bezier(.4, 0, .2, 1); }
.mat-details[open] .mat-chevron { transform: rotate(180deg); }
.mat-list { margin: 4px 0 0; padding: 0; list-style: none; }

/* Bascule d'affichage manipulée par script.js et admin.html (classList.add/remove('hidden')). Doublon volontaire
   de l'utilitaire de tailwind.css. DOIT rester la dernière règle : à spécificité égale, elle doit l'emporter sur les
   classes maison qui posent display:flex/grid (ex. .submenu, .chip, .admin-grid-2). */
/* Icônes SVG inline injectées dans les <i class="fa-…"> par le bloc FA_PATHS de script.js (9 septembre 2026).
   Même métrique que la police FontAwesome : hauteur 1em, largeur proportionnelle, alignement -0.125em. */
i[class*="fa-"] { display: inline-block; height: 1em; line-height: 1; vertical-align: -0.125em; flex-shrink: 0; }
i[class*="fa-"] > svg { display: block; height: 1em; }
.fa-spin { animation: fa-spin 2s linear infinite; }
@keyframes fa-spin { to { transform: rotate(360deg); } }

/* ==========================================================================
   Accueil (9 septembre 2026) — six blocs, mobile first, rendus par renderHome() dans script.js
   ========================================================================== */
.home { width: 100%; display: flex; flex-direction: column; gap: 16px; }
#homeBody { display: flex; flex-direction: column; gap: 16px; }
.home-sec-h { display: flex; align-items: baseline; justify-content: space-between; padding: 0 2px; margin-top: 4px; }
.home-sec-h h2 { margin: 0; font-size: 11px; line-height: 16px; letter-spacing: .08em; text-transform: uppercase; color: var(--ctp-subtext0); font-weight: 700; }
/* « Matériel › » était en --ctp-blue jusqu'au 15/09/2026, alors que le même rôle (lien secondaire
   « voir plus / ouvrir ») est en pêche sur l'écran Fiches depuis toujours. Signalé par Frédéric,
   corrigé ici et à 25 autres endroits du même type (survols de tuiles, bouton retour, bouton
   Suivant de l'assistant) — liste complète dans AUDIT.md, S-2026-09-15-*-des. Le bleu reste pour
   les vrais états : focus clavier, sélection de texte, choix courant (`.is-on`/`.is-selected`),
   et les palettes catégorielles (badges, `.fi-action--*`, `.bordered-icon-*`). */
.home-sec-h a { font-size: 12px; line-height: 16px; color: var(--ctp-peach); font-weight: 600; text-decoration: none; min-height: 32px; display: inline-flex; align-items: center; }
.home-today { background-color: var(--ctp-base); border: 1px solid var(--ctp-surface0); border-radius: 8px; overflow: hidden; display: flex; flex-direction: column; gap: 12px; padding-bottom: 12px; }
.home-today-top { padding: 14px 14px 0; display: flex; gap: 12px; align-items: flex-start; }
.home-avatar { width: 44px; height: 44px; flex-shrink: 0; border-radius: 8px; display: grid; place-items: center; font-weight: 700; color: var(--ctp-peach); background-color: rgb(var(--ctp-peach-rgb) / .08); border: 1px solid rgb(var(--ctp-peach-rgb) / .35); }
/* Fond passé de .14 à .08 le 10 septembre 2026 : à .14 le texte tombait à 4,46:1 en clair, quatre
   centièmes sous le seuil. Éclaircir le fond en clair et l'assombrir en sombre : les deux gagnent. */
.home-hello { font-weight: 700; font-size: 16px; line-height: 1.2; min-width: 0; flex: 1; }
.home-hello small { display: block; font-weight: 400; font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); margin-top: 2px; }
.home-gps { font-size: 11px; line-height: 16px; color: var(--ctp-subtext0); display: flex; align-items: center; gap: 5px; white-space: nowrap; flex-shrink: 0; }
.home-gps i { width: 7px; height: 7px; border-radius: 9999px; background-color: var(--ctp-surface2); }
.home-gps.is-on { color: var(--ctp-green); }
.home-gps.is-on i { background-color: var(--ctp-green); }
.home-near { margin: 0 14px; padding: 12px; border-radius: 8px; background-color: var(--ctp-mantle); border: 1px solid var(--ctp-surface0); }
.home-k { font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 10px; line-height: 14px; letter-spacing: .08em; text-transform: uppercase; color: var(--ctp-subtext0); }
.home-near-n { font-weight: 700; margin-top: 2px; color: var(--ctp-text); }
.home-near-a { font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); }
.home-near-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 10px; }
.home-near-row .btn-go--sm, .home-near-row .btn-peach--sm { min-height: 44px; }
.home-mat-badge { display: inline-flex; align-items: center; gap: 4px; min-height: 28px; }
.home-missions { padding: 0 14px; display: flex; flex-direction: column; gap: 4px; }
.home-mission { display: flex; gap: 10px; align-items: center; min-height: 44px; }
.home-mission-h { font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; line-height: 16px; color: var(--ctp-subtext1); width: 46px; flex-shrink: 0; }
.home-mission-h.is-late { color: var(--ctp-red); font-weight: 600; }
.home-mission-m { flex: 1; min-width: 0; }
.home-mission-m b { display: block; font-size: 13px; line-height: 18px; color: var(--ctp-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.home-mission-m span { font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.home-mission-go { min-height: 44px; padding: 0 10px; border: 0; background: none; font: inherit; font-size: 12px; font-weight: 700; color: var(--ctp-peach); cursor: pointer; }
.home-entries { display: grid; grid-template-columns: 1fr; gap: 10px; }
@media (min-width: 768px) { .home-entries { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.home-entry { display: flex; align-items: center; gap: 12px; padding: 12px 14px; min-height: 64px; background-color: var(--ctp-base); border: 1px solid var(--ctp-surface0); border-radius: 8px; text-align: left; font: inherit; color: var(--ctp-text); cursor: pointer; transition: border-color .15s cubic-bezier(.4, 0, .2, 1), background-color .15s cubic-bezier(.4, 0, .2, 1); }
.home-entry:hover { border-color: var(--ctp-peach); }
.home-entry:disabled { opacity: .5; cursor: not-allowed; }
.home-entry-tx { flex: 1; min-width: 0; }
.home-entry-tx b { display: block; font-size: 15px; line-height: 20px; }
.home-entry-tx span { font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); display: block; }
.home-chev { color: var(--ctp-subtext0); font-size: 12px; }
.home-devices { display: flex; gap: 8px; overflow-x: auto; padding: 2px 2px 6px; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.home-devices::-webkit-scrollbar { display: none; }
.home-dev { flex: 0 0 auto; min-height: 44px; display: flex; align-items: center; gap: 8px; padding: 6px 12px 6px 6px; border-radius: 9999px; background-color: var(--ctp-base); border: 1px solid var(--ctp-surface0); font: inherit; font-weight: 600; font-size: 13px; color: var(--ctp-text); white-space: nowrap; cursor: pointer; }
.home-dev:hover { border-color: var(--ctp-peach); }
.home-dev-ic { width: 30px; height: 30px; border-radius: 9999px; display: grid; place-items: center; border: 1px solid; }
.home-dev-ic .ki { width: 16px; height: 16px; }
.home-duo { display: inline-flex; margin-left: 2px; }
.home-duo i { width: 7px; height: 7px; border-radius: 9999px; display: inline-block; }
.home-duo i:first-child { background-color: var(--ctp-red); margin-right: 3px; }
.home-duo i:last-child { background-color: var(--ctp-green); }
.home-domains { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
@media (min-width: 768px) { .home-domains { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.home-dom { background-color: var(--ctp-base); border: 1px solid var(--ctp-surface0); border-radius: 8px; padding: 12px; min-height: 96px; display: flex; flex-direction: column; align-items: flex-start; gap: 8px; text-align: left; font: inherit; color: var(--ctp-text); cursor: pointer; }
.home-dom:hover { border-color: var(--ctp-peach); }
.home-dom b { font-size: 13px; line-height: 1.2; }
.home-cnt { margin-top: auto; font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); }
.home-cnt em { font-style: normal; font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--ctp-text); font-weight: 600; }
.home-subs { margin-top: auto; display: flex; gap: 6px; flex-wrap: wrap; }
.home-subs span { font-size: 11px; line-height: 16px; padding: 4px 8px; border-radius: 9999px; background-color: var(--ctp-mantle); border: 1px solid var(--ctp-surface0); color: var(--ctp-subtext1); min-height: 28px; display: inline-flex; align-items: center; }
.home-subs span:hover { border-color: var(--ctp-peach); color: var(--ctp-peach); }
.home-tools { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
@media (min-width: 768px) { .home-tools { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
.home-tool { background-color: var(--ctp-base); border: 1px solid var(--ctp-surface0); border-radius: 8px; padding: 10px 6px 8px; min-height: 78px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; text-align: center; font: inherit; color: var(--ctp-text); text-decoration: none; cursor: pointer; }
.home-tool:hover { border-color: var(--ctp-peach); }
.home-tool.is-on { border-color: var(--ctp-blue); background-color: rgb(var(--ctp-blue-rgb) / .08); }
.home-tool span { font-size: 11px; line-height: 1.15; font-weight: 600; }
#homeVpn .vpn-bar { margin-bottom: 0; }
.home-watch { background-color: var(--ctp-base); border: 1px solid var(--ctp-surface0); border-radius: 8px; padding: 8px 14px; display: flex; flex-direction: column; }
.home-watch-l { display: flex; align-items: center; gap: 10px; min-height: 36px; font-size: 13px; line-height: 18px; color: var(--ctp-text); }
.home-dot { width: 9px; height: 9px; border-radius: 9999px; flex-shrink: 0; }
.home-watch-l em { font-style: normal; font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; font-weight: 600; }
.home-watch-l a { margin-left: auto; color: var(--ctp-peach); font-size: 12px; font-weight: 600; text-decoration: none; white-space: nowrap; min-height: 36px; display: inline-flex; align-items: center; }
.home-all { text-align: center; padding: 2px 0 8px; }
.home-all a { color: var(--ctp-peach); font-weight: 600; text-decoration: none; font-size: 13px; min-height: 44px; display: inline-flex; align-items: center; }

/* ==============================================================================
   RÉCUPÉRÉ DE LA SECTION « VERRE » (12/09/2026)
   ------------------------------------------------------------------------------
   Cette section-là était un habillage, et elle est partie avec les autres — mais
   elle contenait AUSSI de vrais composants, rangés là par commodité : l'en-tête
   d'accueil, les grandes cartes, les jauges, et surtout `.visually-hidden`.
   Les emporter a coûté cher et le symptôme n'avait aucun rapport avec l'apparence :
   sans `.visually-hidden`, le `<h1>` du site, censé mesurer 1 px, en mesurait 745.
   Il gonflait le bloc de marque, écrasait le champ de recherche à 22 px, et
   l'`<input>` — qui ne peut pas descendre sous ses 124 px de rembourrage — débordait
   par-dessus les boutons de mode : la page ne répondait plus aux clics.
   Trois tests sont tombés là-dessus, aucun ne parlait de style.
   ============================================================================== */
/* Transition de thème douce, ombres et tracés SVG compris */
*, *::before, *::after { transition: background-color .3s ease, color .3s ease, border-color .3s ease, box-shadow .3s ease, fill .3s ease, stroke .3s ease; }
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition: none !important; } }

/* Accueil : en-tête, et sur grand écran deux colonnes (gauche 400 px ; droite : grandes cartes + jauges) */
.home-hero { position: relative; overflow: hidden; padding: 20px 18px; border-radius: 18px; border: 1px solid var(--ctp-surface0); background-color: var(--ctp-base); }
.home-hero::after { content: ""; position: absolute; inset: 0; background: linear-gradient(100deg, transparent 55%, rgb(var(--ctp-green-rgb) / .10) 80%, rgb(var(--ctp-peach-rgb) / .10)); pointer-events: none; }
.home-hero > * { position: relative; z-index: 1; }
.home-hero h1 { margin: 0 0 4px; font-size: 24px; line-height: 1.1; font-weight: 800; letter-spacing: -.01em; text-wrap: balance; }
.home-hero p { margin: 0; color: var(--ctp-subtext0); font-size: 13px; line-height: 18px; max-width: 60ch; }
.home-hero p b { color: var(--ctp-text); font-weight: 600; }
/* Colonne droite : sur petit écran on ne garde que les jauges — les grandes cartes de catégorie
   doublonnent le bloc « Par domaine » juste au-dessus (§32, jauges demandées aussi sur mobile). */
.home-side { display: flex; flex-direction: column; gap: 16px; }
.home-side .home-big { display: none; }
/* LA GRILLE D'ACCUEIL. Celle d'origine était `grid-template-areas: "left right"` et visait
   `.home-left` / `.home-side` — deux conteneurs que la refonte Platinum a remplacés par
   `.home-bureau` et ses panneaux `.plat-fen`, sans que la règle suive. Mesuré sur 1 280 px :
   tout l'accueil tassé dans la colonne de 400 px, et les 700 px de droite occupés par un seul
   lien. La grille suit maintenant le contenu réel, et se remplit d'elle-même : `auto-fill`
   prend autant de colonnes que la largeur en autorise, sans point de rupture à maintenir. */
.home-bureau {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(330px, 1fr));
    gap: 16px;
    align-items: start;
}
/* Les deux panneaux longs (« Aujourd'hui », « Fiches par catégorie ») tiennent deux colonnes
   quand il y en a assez — et une seule sinon, sans quoi ils déborderaient sur téléphone. */
@media (min-width: 1024px) { .plat-fen--large { grid-column: span 2; } }

@media (min-width: 1100px) {
    .home-hero h1 { font-size: 34px; }
    .home-hero p { font-size: 14px; line-height: 20px; }
    .home-side .home-big { display: flex; }
    .home-tools { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .home-domains { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .home-entries { grid-template-columns: 1fr; }
}
.home-big { padding: 22px; display: flex; flex-direction: column; gap: 14px; min-height: 220px; border-radius: 18px; border: 1px solid var(--ctp-surface0); background-color: var(--ctp-base); text-align: left; font: inherit; color: var(--ctp-text); cursor: pointer; }
.home-big--tall { grid-row: span 2; min-height: 300px; }
.home-big h3 { margin: 0; font-size: 22px; line-height: 1.15; font-weight: 800; letter-spacing: -.01em; }
.home-big .home-big-meta { color: var(--ctp-subtext0); font-size: 13px; line-height: 18px; }
.home-big .home-big-meta em { font-style: normal; font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--ctp-text); font-weight: 600; }
.home-big ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.home-big li { display: flex; align-items: center; gap: 10px; min-height: 40px; padding: 0 10px; border-radius: 10px; background-color: var(--glass-2); border: 1px solid var(--ctp-surface0); font-size: 13px; font-weight: 500; }
.dark .home-big li { background-color: rgb(255 255 255 / .06); }
.home-big li .home-dot { width: 8px; height: 8px; }
.home-big li span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.home-big li small { margin-left: auto; color: var(--ctp-subtext0); font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; white-space: nowrap; }
.home-big li.home-big-more { background: none; border-style: dashed; color: var(--ctp-subtext0); justify-content: center; font-weight: 600; }
.home-big .bordered-icon-box { width: 52px; height: 52px; border-radius: 14px; }
.home-big .ki { width: 26px; height: 26px; }
/* Jauges : emplacement réservé (valeurs réelles), à affiner à la fin */
.home-gauge { padding: 18px; display: flex; align-items: center; gap: 16px; position: relative; border-radius: 18px; border: 1px solid var(--ctp-surface0); background-color: var(--ctp-base); }
.home-side > * { min-width: 0; }
.home-gauge-tx { min-width: 0; overflow-wrap: anywhere; }
.home-big { min-width: 0; }
.home-big h3, .home-big .home-big-meta { overflow-wrap: anywhere; }
.gauge { width: 100px; height: 100px; flex-shrink: 0; position: relative; }
.gauge svg { width: 100%; height: 100%; transform: rotate(135deg); }
.gauge .gauge-track { fill: none; stroke: var(--ctp-surface1); stroke-width: 9; stroke-linecap: round; }
.gauge .gauge-val { fill: none; stroke: url(#homeGradAlert); stroke-width: 9; stroke-linecap: round; }
.gauge .gauge-num { position: absolute; inset: 0; display: grid; place-items: center; font-size: 28px; font-weight: 800; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.home-gauge-tx b { display: block; font-size: 16px; line-height: 20px; }
.home-gauge-tx span { display: block; color: var(--ctp-subtext0); font-size: 13px; line-height: 18px; }
.home-gauge-tx .home-k { display: block; margin-top: 6px; overflow-wrap: anywhere; }

/* Masquage visuel sans masquage pour les lecteurs d'écran (motif standard). */
.visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
           clip: rect(0, 0, 0, 0); clip-path: inset(50%); white-space: nowrap; border: 0; }

.hidden { display: none; }





/* ==============================================================================
   §10. LE MOBILIER — barre du haut, cadre de page, panneaux, onglet latéral
   ------------------------------------------------------------------------------
   Les noms de classes commencent par `plat-` et `ep-` : c'est l'héritage de
   l'habillage Macintosh, et ils sont gardés EXPRÈS. `script.js` (5 252 lignes) les
   écrit à la main dans le HTML qu'il fabrique ; les renommer voudrait dire toucher
   la génération du HTML et les 92 tests, pour ne rien changer à l'écran. Un nom
   d'héritage coûte une ligne d'explication ; un renommage coûte un chantier et
   un risque. On garde les noms, on change ce qu'ils dessinent.

   Ce qu'ils dessinent maintenant : une barre d'application, un cadre de page, des
   panneaux à filet. Pas de biseau, pas d'ombre portée dure, pas de rayures.

   RIEN N'EST RETIRÉ. Chacune de ces pièces porte une commande — la barre ouvre les
   menus, la corbeille porte la file d'attente des pointages, la fenêtre enroulée
   mène au Cockpit Admin, la case de gauche ramène à l'accueil. En masquer une
   supprimerait une fonction, pas une décoration.
   ============================================================================== */

/* `.plat` ne porte plus rien. Elle servait à reposer toute la palette sur chaque
   section — c'était le cœur du problème : quatre étages de couleur au lieu d'un.
   La classe reste dans le HTML (12 endroits), elle n'a simplement plus de règle.
   Ne pas lui en redonner : c'est par là que la complexité reviendrait. */

/* ── LA BARRE DU HAUT ────────────────────────────────────────────────────────── */
.plat-menubar {
    position: sticky; top: 0; z-index: 1200;
    display: flex; align-items: center; gap: 2px;
    height: 38px; padding: 0 8px;
    background: var(--ctp-mantle);
    border-bottom: 1px solid var(--ctp-surface1);
    font-family: var(--f-sans); font-size: 14px;
}
.plat-menu {
    display: inline-flex; align-items: center; gap: 6px;
    height: 28px; padding: 0 10px;
    border: 0; border-radius: var(--r-sm);
    background: transparent; color: var(--ctp-text);
    font: inherit; cursor: pointer;
}
.plat-menu:hover, .plat-menu[aria-expanded="true"] { background: var(--ctp-surface0); }
/* La pomme arc-en-ciel était le signe le plus fort qui restait, et ce logo n'est
   pas le nôtre. Le bouton et son nom accessible ne bougent pas ; le dessin devient
   un chevron de menu. */
.plat-menu--pomme svg { display: none; }
.plat-menu--pomme::before { content: "\2630"; font-size: 15px; line-height: 1; }
.plat-menubar-fin {
    margin-left: auto; display: flex; align-items: center; gap: 10px;
    padding-right: 4px; color: var(--ctp-subtext0); font-size: 13px;
    font-variant-numeric: tabular-nums;
}

/* Le menu déroulant */
.plat-tombant {
    position: absolute; z-index: 1300; min-width: 210px; padding: 4px;
    background: var(--ctp-base);
    border: 1px solid var(--ctp-surface1); border-radius: var(--r-md);
    box-shadow: var(--shadow-2);
}
.plat-tombant button {
    display: flex; align-items: center; gap: 10px; width: 100%;
    min-height: 36px; padding: 0 10px;
    border: 0; border-radius: var(--r-sm);
    background: transparent; color: var(--ctp-text);
    font-family: var(--f-sans); font-size: 14px; text-align: left; cursor: pointer;
}
.plat-tombant button:hover:not(:disabled) { background: var(--ctp-surface0); }
.plat-tombant button:disabled { color: var(--ctp-overlay0); cursor: default; }
.plat-racc { margin-left: auto; color: var(--ctp-overlay0); font-size: 12px; }

/* ── LE CADRE DE PAGE ────────────────────────────────────────────────────────── */
.plat-corps { min-height: 100vh; background: var(--ctp-mantle); }
.plat-fenetre {
    /* `width: 100%` ET `min-width: 0`, pas seulement `max-width`. `<body>` est un
       conteneur flex : un enfant y prend la largeur de SON CONTENU, plafonnée par
       `max-width` — il ne remplit pas, et il ne descend pas sous son min-content.
       Sans ces deux lignes, le cadre restait à 1 100 px dans un écran de 420 et la
       moitié droite de la page était coupée. Mesuré, deux fois. */
    width: 100%; min-width: 0;
    max-width: 1100px; margin: 0 auto;
    background: var(--ctp-base);
    border-left: 1px solid var(--ctp-surface1);
    border-right: 1px solid var(--ctp-surface1);
    min-height: calc(100vh - 38px);
}
@media (max-width: 767px) {
    /* Sur téléphone la page occupe tout l'écran : un cadre n'y servirait qu'à
       manger deux pixels de large sur les seuls qui comptent. */
    .plat-fenetre { border-left: 0; border-right: 0; }
}
.plat-fenetre-corps { padding: 0; }

/* L'en-tête de page. C'était une barre de titre à six traits noirs ; c'est un
   en-tête, avec le nom du mode courant — le seul endroit où il est annoncé. */
.plat-titre {
    display: flex; align-items: center; gap: 8px;
    padding: 10px 14px;
    background: var(--ctp-base);
    border-bottom: 1px solid var(--ctp-surface1);
}
.plat-nom {
    font-family: var(--f-serif); font-size: 17px; font-weight: 400;
    color: var(--ctp-text); letter-spacing: -.01em;
}
/* Les rayures de la barre de titre n'existent pas dans ce langage. Les `<span>`
   restent dans le HTML et deviennent des espaceurs. */
.plat-rayures { flex: 1; }
/* Les cases : seule celle de gauche agit (retour à l'accueil), les deux autres
   sont décoratives et le HTML les marque `aria-hidden`. */
.plat-case {
    width: 22px; height: 22px; flex: none;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--ctp-surface1); border-radius: var(--r-xs);
    background: var(--ctp-base); color: var(--ctp-subtext0);
    padding: 0; cursor: default;
}
button.plat-case { cursor: pointer; }
button.plat-case:hover { background: var(--ctp-surface0); }
.plat-case i { display: block; width: 8px; height: 8px; border: 1px solid var(--ctp-overlay0); border-radius: 1px; }

/* ── LES PANNEAUX (« Aujourd'hui », « Par domaine »…) ────────────────────────── */
.plat-fen {
    background: var(--ctp-base);
    border: 1px solid var(--ctp-surface1); border-radius: var(--r-md);
    margin-bottom: 14px; overflow: hidden;
}
.plat-fen .plat-titre {
    background: var(--ctp-mantle);
    padding: 8px 12px;
}
/* Le nom d'un panneau n'est pas un titre éditorial : petites capitales grises,
   comme les intertitres de la documentation. */
.plat-fen .plat-nom {
    font-family: var(--f-sans); font-size: 12px; font-weight: 600;
    letter-spacing: .06em; text-transform: uppercase; color: var(--ctp-subtext0);
}
.plat-fen-corps { padding: 12px; }
.plat-fen-ranger, .plat-fen-shade, .plat-fen-zoom { display: none; }
.plat-poignee { display: none; }

/* ── LA BARRE D'OUTILS DE LA CARTE ───────────────────────────────────────────── */
.plat-strip {
    display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
    padding: 8px; background: var(--ctp-mantle);
    border-bottom: 1px solid var(--ctp-surface1);
}
.plat-mod {
    display: inline-flex; align-items: center; gap: 6px;
    min-height: 34px; padding: 0 10px;
    border: 1px solid var(--ctp-surface1); border-radius: var(--r-sm);
    background: var(--ctp-base); color: var(--ctp-text);
    font-family: var(--f-sans); font-size: 13px; cursor: pointer;
}
.plat-mod:hover { background: var(--ctp-surface0); }
.plat-mod.is-on, .plat-mod.is-night { background: var(--ctp-text); color: var(--ctp-base); border-color: var(--ctp-text); }
.plat-lib { font-size: 12px; }

/* ── LE BUREAU : deux raccourcis, devenus deux boutons de la barre ───────────── */
.plat-enroulee, .plat-corbeille {
    position: fixed; right: 12px; z-index: 900;
    display: inline-flex; align-items: center; gap: 8px;
    min-height: 34px; padding: 0 12px;
    border: 1px solid var(--ctp-surface1); border-radius: var(--r-sm);
    background: var(--ctp-base); color: var(--ctp-text);
    font-family: var(--f-sans); font-size: 13px; cursor: pointer;
    box-shadow: var(--shadow-1);
}
.plat-enroulee { top: 50px; }
.plat-corbeille { top: 92px; }
.plat-enroulee:hover, .plat-corbeille:hover { background: var(--ctp-surface0); }
/* Le fût cannelé de la Corbeille du Finder et la barre de la fenêtre enroulée
   sont du dessin d'un autre langage : on garde le bouton, pas le dessin. */
.plat-corbeille svg, .plat-enroulee-barre { display: none; }
.plat-corbeille-n {
    min-width: 18px; height: 18px; padding: 0 5px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: var(--r-pill);
    background: var(--ctp-peach); color: #fff; font-size: 11px; font-weight: 600;
}
@media (max-width: 767px) { .plat-enroulee, .plat-corbeille { display: none; } }

/* ── L'ONGLET « ÉCOLES PROCHES » ─────────────────────────────────────────────── */
.ep-languette {
    position: fixed; right: 0; top: 50%; transform: translateY(-50%); z-index: 800;
    display: flex; flex-direction: column; align-items: center; gap: 4px;
    width: 26px; padding: 10px 0;
    border: 1px solid var(--ctp-surface1); border-right: 0;
    border-radius: var(--r-sm) 0 0 var(--r-sm);
    background: var(--ctp-base); color: var(--ctp-subtext0);
    font-size: 10px; letter-spacing: .08em; cursor: pointer;
    writing-mode: vertical-rl; text-orientation: mixed;
}
.ep-languette:hover { background: var(--ctp-surface0); }
.ep-rayures { display: none; }
.ep-panneau {
    position: fixed; right: 0; top: 0; bottom: 0; z-index: 1100;
    width: min(340px, 92vw); display: flex; flex-direction: column;
    background: var(--ctp-base);
    border-left: 1px solid var(--ctp-surface1);
    box-shadow: var(--shadow-2);
}
/* Sur ordinateur, `.plat-menubar` est sticky à `top:0` avec z-index 1200 —
   supérieur aux 1100 du panneau. `.ep-panneau` posé lui aussi à `top:0` se
   fait donc recouvrir sur ses 38 premiers pixels : son propre titre et son
   bouton de fermeture passent derrière la barre, invisibles (signalé le
   16/09/2026, capture d'écran). Sur téléphone, `.plat-menubar` est masquée
   (media query plus bas) : `top:0` y reste correct, ne pas y toucher. */
@media (min-width: 768px) {
    .ep-panneau { top: 38px; }
}
.ep-titre {
    display: flex; align-items: center; gap: 8px; padding: 12px 14px;
    border-bottom: 1px solid var(--ctp-surface1);
    font-family: var(--f-serif); font-size: 16px;
}
.ep-fermer {
    margin-left: auto; width: 30px; height: 30px;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--ctp-surface1); border-radius: var(--r-sm);
    background: var(--ctp-base); color: var(--ctp-subtext0); cursor: pointer;
}
.ep-corps { flex: 1; overflow-y: auto; padding: 8px; }
.ep-vide { padding: 24px 14px; text-align: center; color: var(--ctp-subtext0); font-size: 13px; }
.ep-nom { display: flex; align-items: center; gap: 10px; padding: 10px; border-radius: var(--r-sm); }
.ep-nom:hover { background: var(--ctp-surface0); }
.ep-vignette {
    width: 34px; height: 34px; flex: none;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--ctp-surface1); border-radius: var(--r-sm);
    color: var(--ctp-subtext0);
}
.ep-nom-ecole { font-size: 14px; font-weight: 600; color: var(--ctp-text); }
.ep-ville { font-size: 12px; color: var(--ctp-subtext0); }
.ep-fi, .ep-dist {
    font-family: var(--f-sans); font-size: 11px; color: var(--ctp-subtext0);
}
.ep-dist { margin-left: auto; white-space: nowrap; }
.ep-compte { color: var(--ctp-subtext0); font-size: 12px; }
.ep-pied { padding: 10px 14px; border-top: 1px solid var(--ctp-surface1); font-size: 12px; color: var(--ctp-subtext0); }

/* ==============================================================================
   TÉLÉPHONE : LE PIED DE PAGE PASSAIT SOUS LA PASTILLE FLOTTANTE (11/09/2026)
   ------------------------------------------------------------------------------
   Même capture. `.mascot-sticker` est en `position: fixed`, coin bas-droit, 60 px
   plus 14 px de marge : elle occupe donc les **74 px** du bas de l'écran, quoi
   qu'on fasse défiler. Arrivé en bas de page, le texte centré du pied passait
   dessous, et « 288 écoles · éc… » disparaissait derrière elle.

   On réserve la hauteur au pied plutôt que de déplacer la pastille : sa position
   est un choix d'interface, l'illisibilité n'en est pas un. Sous 640 px seulement,
   là où le pied est étroit et le texte centré atteint le bord droit.

   PLACÉ EN FIN DE FICHIER, ET C'EST NÉCESSAIRE : `.site-footer-inner` est défini
   plus haut avec la MÊME spécificité (0-1-0). Écrit avant, ce correctif perdait en
   silence — mesuré, `padding-bottom` restait à 24 px. Une media query ne change pas
   la spécificité, seulement les conditions d'application.
   ============================================================================== */
@media (max-width: 639px) {
    .site-footer-inner { padding-bottom: calc(88px + env(safe-area-inset-bottom, 0px)); }
}   /* ← refermeture ajoutée le 11/09/2026 : ce bloc était ouvert jusqu'à la fin du fichier */


/* ==============================================================================
   TÉLÉPHONE : LA LANGUETTE AFFINÉE ET LA PASTILLE RÉDUITE (11 septembre 2026)
   ------------------------------------------------------------------------------
   Décidé par Frédéric après sa capture d'écran du Samsung : les deux éléments
   FIXES du site mangeaient du texte. Ils restent volontairement en place — ce
   sont des choix d'interface — mais ils cessent de coûter de la lecture.

   PLACÉ EN FIN DE FICHIER, comme le correctif du pied : `.ep-languette` et
   `.mascot-sticker` sont définis plus haut à la même spécificité, et une règle
   plus tardive l'emporte. Écrit à côté d'eux, ceci perdrait en silence.

   1. LA LANGUETTE « ÉCOLES PROCHES » : 44 px → 26 px.
   Ce qui mangeait la largeur, ce n'est pas le texte mais les DEUX bandes de
   rayures décoratives qui l'encadrent : en `writing-mode: vertical-rl`, un
   `flex-direction: column` se déploie à l'HORIZONTALE, donc rayures + texte +
   rayures étaient posés côte à côte sur les 44 px. On retire le décor, on garde
   le libellé — et la languette passe à 26 px sans rien perdre de lisible.

   L'ÉCART À LA RÈGLE 5, ASSUMÉ ET CHIFFRÉ. Le commentaire d'origine justifiait
   les 44 px par la cible tactile. La languette fait désormais **26 × 132 px** :
   sous les 44 px de largeur, mais très au-dessus du minimum WCAG 2.2 AA de
   24 × 24 px, et sa SURFACE (3 432 px²) reste supérieure à celle d'un carré de
   44 px (1 936 px²). C'est le même arbitrage que la barre de menus à 26 px, et
   le même chiffre : voir la règle 5 de `DEMARRAGE.md`.

   2. LA PASTILLE FLOTTANTE : 60 px → 44 px.
   Elle masquait le texte des cartes pendant le défilement. Réduite au minimum
   de la règle 5 — donc au plus petit format encore défendable — plutôt que
   rendue translucide : un bouton translucide masquerait ENCORE le texte tout en
   rendant sa propre icône moins lisible. On perdrait des deux côtés.
   Surface masquée : 3 600 px² → 1 936 px², soit **46 % de moins**.
   ============================================================================== */
@media (max-width: 639px) {
    .ep-languette { width: 26px; padding: 8px 0; gap: 4px; }
    .ep-languette .ep-rayures { display: none; }

    .mascot-sticker { width: 44px; height: 44px; border-radius: 8px; }
    .mascot-sticker svg { width: 24px; height: 24px; }
}

/* ==============================================================================
   CONTACTS D'ÉCOLE — 11 septembre 2026, chantier S-2026-09-11-1429-ct
   ------------------------------------------------------------------------------
   Écrit EN FIN DE FICHIER, comme les correctifs de mise en page : à spécificité
   égale, la règle la plus tardive l'emporte, et `.ticket-link` (ligne 1054) fixe
   déjà `min-height: 44px` — une hauteur écrite plus haut se ferait manger.

   MOBILE FIRST. Un nom de personne et un courriel ne se coupent pas comme un
   nom d'école : `overflow-wrap: anywhere` sur `.ct-liens .ticket-link span`,
   sinon « secretariat@... » pousse la carte hors de l'écran à 390 px. Les deux
   liens d'appel gardent les 44 px de la règle 5 — c'est le geste le plus utile
   de tout l'écran quand on cherche un contact : on l'appelle.
   ============================================================================== */
.ct-list { list-style: none; margin: 4px 0 0; padding: 0; }
.ct-item { padding: 10px 0; border-top: 1px solid var(--ctp-surface0); display: flex; flex-direction: column; gap: 4px; }
.ct-item:first-child { border-top: none; }
.ct-ligne { display: flex; align-items: center; gap: 10px; }
.ct-ligne .min0 { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.ct-nom { font-size: 15px; line-height: 20px; font-weight: 700; color: var(--ctp-text); overflow-wrap: anywhere; }
.ct-role { font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); overflow-wrap: anywhere; }
.ct-demo { flex-shrink: 0; font-size: 11px; line-height: 16px; font-weight: 600; text-transform: uppercase; letter-spacing: .025em; padding: 2px 8px; border-radius: 6px; background-color: var(--ctp-surface0); color: var(--ctp-subtext1); border: 1px solid var(--ctp-surface1); }
/* « à revérifier » : même gabarit que la mention « exemple », mais c'est un avertissement — il
   apparaît seul, un contact ne peut pas être à la fois un exemple et une saisie périmée. */
.ct-vieux { flex-shrink: 0; font-size: 11px; line-height: 16px; font-weight: 600; text-transform: uppercase; letter-spacing: .025em; padding: 2px 8px; border-radius: 6px; background-color: rgb(var(--ctp-peach-rgb) / .15); color: var(--ctp-peach); border: 1px solid rgb(var(--ctp-peach-rgb) / .35); }
.ct-liens { display: flex; flex-wrap: wrap; gap: 4px 8px; }
.ct-liens .ticket-link { padding: 6px 10px; max-width: 100%; }
.ct-liens .ticket-link span { min-width: 0; overflow-wrap: anywhere; }
.ct-card .ct-list { margin-bottom: 4px; }
.ct-details + .mat-details { border-top: 1px solid var(--ctp-surface0); }

/* Cockpit — formulaire « Contacts des écoles » (S-2026-09-11-1429-ct).
   `.admin-form` est un flex d'une seule ligne : à six champs, les quatre saisies
   seraient écrasées à 40 px sur un téléphone. On enroule, et chaque champ garde
   une base large pour occuper toute la ligne en 390 px. `.admin-row > span`
   coupe le texte sur une ligne (règle 762) : les deux lignes d'un contact
   demandent donc de rétablir `white-space: normal` sur cette ligne-là. */
.admin-form--contact { flex-wrap: wrap; }
.admin-form--contact .admin-input { flex: 1 1 220px; }
.admin-row--contact { align-items: flex-start; }
.admin-row--contact > span { white-space: normal; overflow: visible; display: flex; flex-direction: column; gap: 2px; }
.admin-row--contact small { font-size: 12px; line-height: 16px; }
/* Nom, rôle et mention « exemple » sur une même ligne : dans le flex en colonne de la rangée,
   chacun formait sinon son propre bloc, et la pastille s'étirait sur toute la largeur. */
.admin-row--contact .ct-ligne-nom { display: block; }
.admin-row--contact .ct-demo { display: inline-block; vertical-align: baseline; }

/* Coordonnées d'établissement (S-2026-09-11-1429-ct) : téléphone et courriel de l'école,
   sous la fiche de la Map et dans le bandeau du mode Pointage. Les liens réutilisent
   `.ticket-link` et ses 44 px ; il ne reste que l'enveloppe et le nom du FI. */
.ec-coord { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; padding: 6px 0; }
.ec-coord-nom { flex-basis: 100%; font-size: 12px; line-height: 16px; font-weight: 700; color: var(--ctp-subtext0); overflow-wrap: anywhere; }
.ec-coord .ticket-link span { min-width: 0; overflow-wrap: anywhere; }

/* ==============================================================================
   `.hidden` REDEVIENT UNE CLASSE UTILITAIRE — 11 septembre 2026 (S-...-1429-ct)
   ------------------------------------------------------------------------------
   TROUVÉ EN ÉCRIVANT UN TEST, pas en relisant : Playwright annonçait « visible »
   un élément qui portait pourtant `class="hidden"`. La cause est une question de
   SPÉCIFICITÉ, la même famille que les trois correctifs perdus en silence du
   10 septembre. `.hidden` de tailwind.css pèse 0-1-0 ; `.plat .btn-peach`,
   `.plat .chip`, `.plat .tbtn` pèsent 0-2-0 et l'emportent. Comme `<body>` porte
   `plat`, TOUTE la famille des boutons de l'habillage ignorait `.hidden`.

   CE QUI ÉTAIT AFFICHÉ ALORS QUE LE CODE LE MASQUAIT — mesuré dans les trois
   modes, et ce n'est pas une liste théorique :
     - `#btnAdminCockpit`, le bouton du Cockpit Admin, que `script.js` masque
       pour qui n'est pas administrateur. Aucune brèche : la vraie protection est
       Cloudflare Access, et le Cockpit reste derrière (DEMARRAGE.md). Mais
       l'intention du code était défaite, et le jour où les deux agents seront
       ajoutés, ils verraient un bouton qui ne mène qu'à un refus ;
     - `#btnSyncQueue`, proposé même sans pointage en attente ;
     - `#btnItineraire` et `#btnAppelEcole` avant toute détection, avec `href="#"`.

   `!important` est ici le bon outil et non un aveu : une classe utilitaire dont
   le seul rôle est de masquer doit gagner contre toute règle de composant, quelle
   que soit sa spécificité — c'est ce que fait `.!hidden` de tailwind. Sans lui, il
   faudrait ajouter une exception à chaque nouveau sélecteur `.plat …`, et la
   prochaine serait oubliée.

   VÉRIFIÉ DANS LES DEUX SENS : les quatre éléments passent à `display: none`, et
   aucun autre élément de la page ne change (les seuls `.hidden` qui restaient
   affichés étaient ces quatre-là, relevés dans les trois modes).
   ============================================================================== */
.hidden { display: none !important; }

/* ── Ressources : PDF de procédure par matériel (11 septembre 2026, S-2026-09-11-1605-res) ──────────
   EN FIN DE FICHIER, et ce n'est pas une commodité : la règle du 10/09 vient de trois correctifs qui
   avaient perdu EN SILENCE parce qu'ils étaient écrits avant la règle qu'ils devaient corriger, à
   spécificité égale. Une media query ne change pas la spécificité.

   La fenêtre elle-même réutilise .modal / .modal-sheet--fi : rien de neuf à styler pour le cadre.
   Elle s'ouvre en RETIRANT .hidden, jamais par une règle d'affichage écrite ici — `.hidden` porte
   `!important` depuis le chantier contacts et gagnerait de toute façon.

   Mobile first : la liste tient dans 390 px, chaque ligne fait au moins 56 px de haut (au-dessus des
   44 px de la règle 5, parce qu'on y vise un nom de fichier et pas une icône), et c'est la LISTE qui
   défile, pas la page — une fenêtre dont le fond défile fait perdre le bouton Fermer. */

.res-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.res-list--modal { padding: 10px 14px; max-height: 46vh; overflow-y: auto; -webkit-overflow-scrolling: touch; }

.res-item { margin: 0; }
.res-dl {
    min-height: 56px; display: flex; align-items: center; gap: 10px; padding: 8px 10px;
    border-radius: 6px; border: 1px solid var(--ctp-surface0); background-color: var(--ctp-base);
    color: var(--ctp-text); text-decoration: none;
    transition: background-color .15s cubic-bezier(.4, 0, .2, 1), border-color .15s cubic-bezier(.4, 0, .2, 1);
}
.res-dl:hover { background-color: var(--ctp-surface0); border-color: var(--ctp-surface1); }
.res-dl:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--ctp-blue); }

/* min-width:0 sur le conteneur ET sur l'enfant : sans les deux, un nom de fichier long ne se coupe
   pas, il POUSSE la ligne et la taille du texte s'écrase. Le défaut du 11/09 au matin (titre de carte
   réduit à 26 px par un badge non compressible) était exactement celui-là, et aucune mesure de
   débordement ne le voit : la ligne tient dans l'écran PRÉCISÉMENT parce qu'elle a été comprimée. */
.res-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.res-nom { font-size: 14px; line-height: 19px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.res-meta { font-size: 11px; line-height: 15px; color: var(--ctp-subtext0); }

/* Le lien « Cheatsheet » des cartes. 44 px, PAS 36 : mesuré le 11/09, mon `min-height: 36px`
   d'origine donnait une cible RÉELLE de 40 px dans le pied de carte — sous le minimum de la règle 5,
   dont la seule exception arbitrée est la barre de menus. Le voisin `.ticket-link` n'imposait rien,
   donc rien ne l'aurait signalé. */
.res-link { min-height: 44px; }

/* Cheatsheet : le lien doit être DISCRET (demande de Frédéric, 11/09) — présent sans concurrencer
   « Créer un ticket », qui reste l'action principale d'une fiche. Libellé en 12 px et en teinte
   secondaire, cible tactile inchangée à 44 px : discret ne veut pas dire difficile à viser. */
/* DISCRÉTION : elle ne peut PAS venir de la couleur dans l'habillage actuel. Mesuré le 11/09 —
   `system.css` (System 6/7) redéfinit les jetons en noir et blanc, donc `--ctp-subtext0` vaut
   #ffffff, exactement comme `--ctp-text` : la règle ci-dessous ne change rien à l'écran aujourd'hui.
   Elle est conservée parce qu'elle reprendra son effet au retour au thème Platinum. La discrétion
   réelle vient donc de l'icône (un document, pas un dossier) et du mot, pas de la teinte. */
.res-link span { font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); }
.res-link:hover span { color: var(--ctp-text); }

/* ── Cockpit : formulaire de dépôt aligné, zone de glisser-déposer, décor de terminal ─────────────
   11 septembre 2026, sur capture d'écran de Frédéric : « c'est pas très aligné tout ça ».
   Il avait raison, et la cause est nette — `.admin-form` est un simple `display: flex` sans base de
   largeur. À quatre contrôles de longueurs très différentes (un menu déroulant long, une saisie, un
   champ fichier au libellé imposé par le navigateur, un bouton), chacun se réduisait à sa guise :
   « Rattacher à », « Nom du modè », « Choisir un fichi ». Un flex sans `flex-basis` ne répartit pas,
   il rogne. On passe donc en GRILLE, où c'est la colonne qui commande, pas le contenu. */

/* `minmax(0, 1fr)` et NON `1fr` : `1fr` vaut `minmax(auto, 1fr)`, dont le minimum est le
   min-content de la colonne. Le menu déroulant porte « Rattacher à un modèle de matériel » : sa
   largeur minimale imposait une colonne de 442 px dans une carte de 358 px, et sept éléments
   sortaient de l'écran en 390 px. Mesuré le 11/09. C'est la même famille que les `min-width: 0`
   des cartes — en version grille, et tout aussi invisible à la lecture. */
.admin-form--ressource { display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; align-items: stretch; }
.admin-form--ressource .admin-input { width: 100%; min-height: 44px; }
.admin-form--ressource .admin-btn { min-height: 44px; }
/* Deux colonnes seulement à partir de 640 px : en 390 px, deux champs côte à côte redonneraient
   exactement le défaut qu'on corrige. La zone de dépôt et le bouton gardent toute la largeur. */
@media (min-width: 640px) {
    .admin-form--ressource { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
    .admin-form--ressource .res-drop,
    .admin-form--ressource .admin-btn { grid-column: 1 / -1; }
}

/* Zone de dépôt. Le champ fichier natif est retiré de l'affichage mais RESTE dans la page et reste
   focalisable : c'est lui qui porte `required` et la validation du navigateur. `display: none`
   l'aurait rendu infocalisable et aurait cassé la navigation au clavier. */
.res-drop {
    display: flex; align-items: center; gap: 12px; padding: 14px 16px; min-height: 88px;
    border: 2px dashed var(--ctp-surface1); border-radius: 8px;
    background-color: var(--ctp-mantle); color: var(--ctp-text); cursor: pointer;
    transition: border-color .15s cubic-bezier(.4, 0, .2, 1), background-color .15s cubic-bezier(.4, 0, .2, 1);
}
.res-drop:hover { border-color: var(--ctp-text); background-color: var(--ctp-surface0); }
.res-drop input[type="file"] { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.res-drop:focus-within { outline: none; box-shadow: 0 0 0 2px var(--ctp-blue); }
/* Pendant le survol d'un fichier : trait plein et fond marqué. La classe est posée par le JS, pas
   par `:hover` — un glisser ne déclenche pas `:hover` sur tous les navigateurs. */
.res-drop--actif { border-style: solid; border-color: var(--ctp-text); background-color: var(--ctp-surface0); }
.res-drop--charge { border-style: solid; }
.res-drop-icone { flex-shrink: 0; display: inline-flex; }
.res-drop-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.res-drop-txt b { font-size: 14px; line-height: 19px; }
/* min-width:0 au-dessus ET coupure ici : un nom de fichier long doit s'abréger, pas élargir la
   zone — c'est le défaut « titre écrasé » du 11/09 au matin, dans un autre costume. */
#resDropSous { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Décor de terminal pour l'activité en direct. Il ne change RIEN au contenu : même liste, mêmes
   identifiants, mêmes classes `admin-feed`. C'est un cadre, et il porte son propre défilement —
   le flux s'allonge sans pousser le reste du Cockpit vers le bas. */
.term { border: 1px solid var(--ctp-surface1); border-radius: 8px; overflow: hidden; background-color: var(--ctp-crust); }
.term-bar {
    display: flex; align-items: center; gap: 7px; padding: 8px 12px;
    background-color: var(--ctp-surface0); border-bottom: 1px solid var(--ctp-surface1);
}
.term-dot { width: 11px; height: 11px; border-radius: 50%; border: 1px solid var(--ctp-surface1); flex-shrink: 0; }
/* Pastilles décoratives : en System 6/7 les couleurs sont ramenées au noir et blanc, elles restent
   donc lisibles comme trois ronds. Elles ne portent aucune information — `aria-hidden` dans le HTML. */
.term-dot--rouge { background-color: #ff5f57; }
.term-dot--jaune { background-color: #febc2e; }
.term-dot--vert { background-color: #28c840; }
.term-titre {
    margin-left: 6px; font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 11px; line-height: 16px; color: var(--ctp-subtext0);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.term-corps {
    padding: 10px 12px; max-height: 340px; overflow-y: auto; -webkit-overflow-scrolling: touch;
    font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px;
}
.term-corps .admin-feed { font-family: inherit; }

/* ── Menu des lots : repli sur le côté après un choix (11 septembre 2026) ─────────────────────────
   Demande de Frédéric : « quand je choisis un thème dans le menu, c'est rude, je dois descendre moi
   même en scrollant ». Sur téléphone, `.sidebar` fait 100 % de large et se place AU-DESSUS des
   résultats : choisir un lot laissait donc l'écran sur le menu, et il fallait faire défiler tout le
   reste pour voir ce qu'on venait de demander.

   Le repli ne concerne QUE le téléphone. Au-dessus de 768 px la barre est une colonne latérale à
   côté des résultats — la replier n'apporterait rien et retirerait un repère. */
@media (max-width: 767px) {
    .sidebar {
        transition: transform .28s cubic-bezier(.4, 0, .2, 1), opacity .22s ease,
                    max-height .28s cubic-bezier(.4, 0, .2, 1), margin-bottom .28s ease;
        max-height: 400vh;
    }
    /* `max-height` ET `transform` : la translation donne le mouvement « vers la gauche » demandé,
       mais seule la hauteur libère réellement la place — une translation seule laisserait un trou. */
    .sidebar--replie {
        transform: translateX(-16px);
        opacity: 0;
        max-height: 0;
        margin-bottom: 0;
        overflow: hidden;
        pointer-events: none;
        /* `visibility: hidden` est ce qui retire le menu de l'ordre de tabulation ET des lecteurs
           d'écran. Il est ICI, dans le bloc borné au téléphone, et non posé par le JS : au-delà de
           768 px il cesse de s'appliquer tout seul. Une garde portée par le JS survivait au
           changement de largeur et laissait un menu visible mais mort. */
        visibility: hidden;
    }
    .filtres-rappel {
        display: inline-flex; align-items: center; gap: 8px;
        min-height: 44px; padding: 0 14px; margin-bottom: 12px;
        border: 1px solid var(--ctp-surface1); border-radius: 6px;
        background-color: var(--ctp-mantle); color: var(--ctp-subtext0);
        font-size: 13px; line-height: 18px; font-family: inherit; cursor: pointer;
        transition: color .15s cubic-bezier(.4, 0, .2, 1), background-color .15s cubic-bezier(.4, 0, .2, 1);
    }
    .filtres-rappel:hover { color: var(--ctp-text); background-color: var(--ctp-surface0); }
    .filtres-rappel:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--ctp-blue); }
}
/* Au-dessus de 768 px le bouton n'a pas lieu d'être, même si le JS lui retirait `hidden`. */
@media (min-width: 768px) { .filtres-rappel { display: none; } }

/* `prefers-reduced-motion` est ACTIF sur le poste de développement : sans cette garde, le repli
   aurait été livré sans jamais avoir été vu en mouvement. Le pli reste, l'animation disparaît —
   c'est bien le résultat qui compte, pas le trajet. */
@media (prefers-reduced-motion: reduce) {
    .sidebar { transition: none; }
}

/* Réseau et niveau d'enseignement (S-2026-09-11-2132-ct4) : une ligne discrète sous l'adresse,
   sur la carte « école » de la recherche et dans la fiche de la Map. Le bandeau du mode Pointage
   l'affiche en texte, dans sa ligne de détails existante. */
.ec-meta { font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); margin-top: 2px; overflow-wrap: anywhere; }
/* La ligne réseau/niveau du bandeau de Pointage : elle ENROULE au lieu de se faire couper.
   `.gps-details` juste au-dessus est en `nowrap` + ellipsis, ce qui convient à une adresse — pas
   à « Subventionné provincial · Promotion sociale secondaire », qui se retrouvait tronqué à 390 px. */
.gps-meta { font-size: 12px; line-height: 16px; color: var(--ctp-subtext0); margin-top: 2px; overflow-wrap: anywhere; }

/* ==============================================================================
   SECRETS MASQUÉS : LE WIDGET RENTRE DANS SA LIGNE — 11 septembre 2026 (ct5)
   ------------------------------------------------------------------------------
   Signalé par une capture de Frédéric : sur la fiche « Outils & Téléchargements »,
   le badge de phpIPAM passait PAR-DESSUS la ligne « IP Connexion VPN ».

   LA CAUSE, chiffrée. `.secret-holder` (ligne 1195) porte
   `margin-top: -8px; margin-bottom: -8px`. Son contenu mesure 44 px (l'œil, qui
   respecte la cible tactile de la règle 5) ; avec 16 px de marges négatives, il
   n'en déclare que **28** à sa ligne — exactement la hauteur mesurée du `<li>`.
   Le widget est donc TIRÉ HORS de sa ligne et déborde de 4 px en haut et 4 px en
   bas, sur les lignes voisines. Aucun billet ne justifiait ces marges : un
   raccourci pour resserrer la prose, dont personne n'avait mesuré le prix.

   POURQUOI ON NE RÉTRÉCIT PAS PLUTÔT LE WIDGET. Ce serait l'autre façon de le
   faire rentrer — mais l'œil fait 44 px parce que la règle 5 l'exige, et les
   seules exceptions à cette règle sont arbitrées par Frédéric (barre de menus,
   languette). On ne s'en octroie pas une nouvelle pour gagner 16 px de prose.

   CE QUE ÇA COÛTE, ET C'EST ASSUMÉ : une ligne portant un secret passe de 28 à
   44 px. Sur la fiche concernée, deux lignes sur quatre — soit 32 px de plus en
   tout. Un texte un peu plus aéré contre deux lignes qui ne se chevauchent plus.

   La barre VPN n'est pas touchée : elle utilise `.copy-badge--secret` SANS
   `.secret-holder` (pas d'œil), donc sans ces marges.
   ============================================================================== */
.secret-holder { margin-top: 0; margin-bottom: 0; }

/* ==============================================================================
   PROPOSITION — allègement du secret masqué DANS LA PROSE (non arbitré)
   ------------------------------------------------------------------------------
   Portée volontairement réduite à `.markdown-body` : la barre VPN, les fiches
   matériel et les numéros de série gardent exactement leur apparence actuelle.
   Ce qui change, et pourquoi :
     - le badge perd son cadre et passe de 36 à 28 px : dans un texte de 16 px,
       un rectangle bordé de 36 px lit comme un bouton, pas comme une valeur ;
     - l'œil perd son carré, mais PAS sa cible tactile : 44 px conservés par
       `padding`, seul le glyphe rapetisse. La règle 5 porte sur la zone
       touchable, pas sur le dessin ;
     - l'écart badge-œil passe de 4 à 2 px, pour que le groupe se lise comme un
       seul objet — et que la barre finale d'une URL (« …/ ») ne paraisse plus
       abandonnée derrière un bouton.
   ============================================================================== */
.markdown-body .copy-badge--secret { min-height: 28px; padding: 0 6px; }
.markdown-body .secret-holder { gap: 2px; }
.markdown-body .secret-toggle { min-width: 44px; min-height: 44px; background: none; }
.markdown-body .secret-toggle i { font-size: 12px; }

/* ==============================================================================
   §12. LE RETOUR À L'APPUI
   ------------------------------------------------------------------------------
   C'était `system.css` qui le fournissait à toute la famille des touches ; en le
   supprimant le 12/09/2026, plus une seule commande ne réagissait sous le doigt.
   Trouvé par `tests/presse-sombre.spec.js`, pas à l'œil : au clavier et à la
   souris ça ne se remarque pas, sur un écran tactile en plein soleil c'est le
   SEUL retour qu'on ait — rien ne dit sinon que l'appareil a compris.

   Une seule règle, un seul geste : le fond descend d'un ton. Pas de déplacement,
   pas d'ombre qui s'enfonce — ce langage n'a pas de relief à donner.
   ============================================================================== */
.btn-go:active, .btn-peach:active, .btn-neutral:active, .btn-accueil:active,
.tbtn:active, .chip:active, .theme-btn:active, .admin-btn:active,
.wizard-btn:active, .wizard-choice-btn:active, .horszone-btn:active,
.mode-btn:active, .filter-btn:active, .sub-filter-btn:active,
.plat-mod:active, .plat-case:active, .plat-menu:active {
    background-color: var(--ctp-surface2);
    background-image: none;
}
/* En sombre, `--ctp-surface2` est un gris foncé : le fond pressé reste sombre,
   la touche ne « clignote » pas en blanc. Vérifié par la mesure de luminance. */

/* ==============================================================================
   §13. LES COMMANDES REMISES À LEUR PLACE (12/09/2026)
   ------------------------------------------------------------------------------
   Audit demandé par Frédéric après le passage à la feuille unique. Trois pièces
   du mobilier ne tenaient plus debout une fois le Bureau Macintosh retiré.
   ============================================================================== */

/* LES CASES DÉCORATIVES DE LA BARRE DE TITRE. Il y en a trois : celle de gauche
   ramène à l'accueil (`<button id="btnAppFermer">`), les deux de droite sont des
   `<span aria-hidden="true">` — les boutons Agrandir et Enrouler d'une fenêtre
   Macintosh, qui n'ont jamais rien commandé. Sur un Bureau, ils faisaient sens ;
   ici, ce sont deux carrés vides. Le sélecteur les vise par leur balise, donc il
   ne peut pas atteindre celle qui agit. */
span.plat-case { display: none; }

/* Celle qui agit reçoit un vrai signe : une flèche de retour, pas un carré vide. */
button.plat-case { width: auto; min-width: 30px; height: 30px; gap: 6px; }
button.plat-case i { display: none; }
button.plat-case::before {
    content: "\2190";                 /* ← */
    font-size: 15px; line-height: 1; color: var(--ctp-subtext0);
}
button.plat-case:hover::before { color: var(--ctp-text); }

/* LE RACCOURCI COCKPIT ADMIN EST RETIRÉ DU BUREAU. Il n'est pas supprimé : la
   même commande est dans le menu ☰ (« Cockpit Admin », script.js MENUS.pomme),
   avec la même condition d'affichage. Deux boutons pour une commande, dont un
   qui flottait par-dessus la page, c'est un de trop. */
.plat-enroulee { display: none; }

/* LA CORBEILLE MONTE DANS LA BARRE. Elle porte le nombre de pointages en attente
   d'envoi : c'est une information d'état, sa place est près de l'heure et des
   initiales, pas en pastille flottante au milieu de l'écran. Décalée à gauche de
   `.plat-menubar-fin`, qui fait une centaine de pixels. */
.plat-corbeille {
    top: 4px; right: 118px;
    min-height: 30px; padding: 0 10px;
    box-shadow: none; background: transparent; border-color: transparent;
    color: var(--ctp-subtext0); font-size: 13px;
}
.plat-corbeille:hover { background: var(--ctp-surface0); border-color: var(--ctp-surface1); }
.plat-corbeille-nom { display: none; }
/* Sans son libellé, le bouton a besoin d'un dessin : une flèche vers le haut, qui
   dit « en attente d'envoi » mieux qu'une corbeille ne l'a jamais dit. */
.plat-corbeille::before { content: "\21E7"; font-size: 14px; line-height: 1; }
@media (max-width: 767px) { .plat-corbeille { display: none; } }

/* LA BARRE DE L'APPLICATION S'EFFACE. Elle affichait le mode courant en serif de
   17 px — au même rang visuel que le titre du panneau juste en dessous, qui dit
   souvent la même chose : « Map » deux fois en mode Pointage, « Accueil » deux
   fois. On ne la retire pas : elle porte le retour à l'accueil, et son
   `role="region"` nomme la fenêtre pour les lecteurs d'écran. On la démote au rang
   de chrome — compacte, grise, en sans — pour qu'elle cesse d'être lue comme un
   titre. Le titre du panneau reste le seul du niveau titre, et il est le plus
   informatif : en mode Pointage, il porte la commune détectée. */
.plat-titre--app { padding: 5px 12px; background: var(--ctp-mantle); }
.plat-titre--app .plat-nom {
    font-family: var(--f-sans); font-size: 12px; font-weight: 500;
    letter-spacing: .02em; color: var(--ctp-subtext0);
}
.plat-titre--app button.plat-case { width: 26px; min-width: 26px; height: 26px; }

/* ==============================================================================
   §14. LA BARRE D'ONGLETS (12/09/2026, lot 5/6)
   ------------------------------------------------------------------------------
   Six entrées, deux positions, un seul DOM. Au bureau elles s'écrivent en clair
   dans l'en-tête ; sous 768 px, le MÊME groupe passe en barre au bas de l'écran,
   là où le pouce arrive — avec des gants et en plein soleil, c'est ce qui se vise
   le mieux, et c'est le seul argument qui compte ici.

   ON DÉPLACE, ON NE DUPLIQUE PAS. Deux jeux de boutons portant
   `.mode-btn[data-mode="liste"]` et `page.click()` de Playwright — qui n'est pas
   strict — cliquerait le premier du DOM : sept fichiers de tests deviendraient
   dépendants d'un ordre que personne n'a écrit.
   ============================================================================== */
:root {
    /* Zéro au bureau : les trois `bottom:` plus bas s'en servent sans condition. */
    --barre-onglets: 0px;
}

.tab-btn {
    min-height: 44px; flex: 1 1 0%; min-width: 0; padding: 6px 10px;
    border-radius: var(--r-md); white-space: nowrap;
    display: flex; align-items: center; justify-content: center; gap: 6px;
    color: var(--ctp-subtext0);
    transition: color .15s cubic-bezier(.4, 0, .2, 1), background-color .15s cubic-bezier(.4, 0, .2, 1);
}
@media (min-width: 640px) { .tab-btn { flex: 0 1 auto; padding: 6px 12px; } }
.tab-btn:hover { color: var(--ctp-text); }
/* Même traitement que `.mode-btn.active` : l'entrée courante est un aplat d'encre.
   Deux entrées de la même barre ne peuvent pas se signaler de deux façons. */
.tab-btn.active { background: var(--ctp-base); color: var(--ctp-text); box-shadow: var(--shadow-1); }

@media (max-width: 767px) {
    :root { --barre-onglets: calc(56px + env(safe-area-inset-bottom, 0px)); }

    .mode-toggle {
        position: fixed; left: 0; right: 0; bottom: 0;
        z-index: 70;      /* au-dessus de la mascotte (60/62), sous toutes les surcouches :
                             .omodal 100, .backdrop 190, .drawer 200, .modal--fi 210,
                             .modal--frais 220, .ep-panneau 1100. */
        margin: 0; border-radius: 0; padding: 4px 4px env(safe-area-inset-bottom, 0px);
        border: 0; border-top: 1px solid var(--ctp-surface1);
        background: var(--ctp-mantle);
        justify-content: space-around;
    }
    .mode-toggle .mode-btn, .mode-toggle .tab-btn {
        flex: 1 1 0%; flex-direction: column; gap: 2px;
        min-height: 52px; padding: 4px 2px; font-size: 11px; border-radius: var(--r-sm);
    }
    /* La rangée qui contenait les onglets ne doit pas garder leur place en haut. */
    .mode-row { justify-content: flex-end; }
}

/* LA MASCOTTE REMONTE. C'est la SEULE collision réelle : `.plat-corbeille` est à
   `top: 92px` et masquée sous 767 px, `#epLanguette` est à mi-hauteur — vérifié,
   ma première table les accusait à tort. */
.mascot-sticker { bottom: calc(14px + var(--barre-onglets) + env(safe-area-inset-bottom, 0px)); }
.mascot-panel { bottom: var(--barre-onglets); }

/* LA GOUTTIÈRE DU PIED EXISTE DÉJÀ, en fin de fichier (§ « le pied passait sous la
   pastille flottante ») : 88 px réservés sous 639 px, soit la hauteur d'une barre
   d'onglets. On ne la déplace pas — son commentaire explique qu'une règle de même
   spécificité définie plus haut la battait en silence. On l'étend seulement aux
   largeurs intermédiaires, jusqu'au point où la barre repasse en haut. */
/* LA GOUTTIÈRE GRANDIT DE LA HAUTEUR DE LA BARRE. Les 88 px d'origine étaient calculés
   pour une pastille posée à 14 px du bas ; elle est maintenant 56 px plus haut, donc le
   texte du pied repassait dessous — quatre tests l'ont dit avant que je le voie.
   On repart de la mesure d'origine et on y ajoute la barre, au lieu de réécrire un nombre :
   si la barre change de hauteur, la gouttière suit. */
@media (max-width: 767px) {
    .site-footer-inner { padding-bottom: calc(88px + var(--barre-onglets) + env(safe-area-inset-bottom, 0px)); }
}

/* LE CHAMP DE RECHERCHE GARDE SA PLACE. Constaté à 1 280 px en posant les six entrées
   dans l'en-tête : `.mode-row` ne rétrécit pas (`flex-shrink: 0`), la navigation est
   passée de trois à cinq entrées, et `.search` — qui n'avait qu'un `width: 100%` — s'est
   fait comprimer jusqu'à son icône, l'`<input>` débordant par-dessus les onglets. Un
   `<input>` ne descend jamais sous la somme de son rembourrage (124 px ici), donc il
   déborde au lieu de rétrécir : le symptôme n'est pas un champ étroit, c'est une
   navigation qu'on ne peut plus cliquer.
   Une base de 260 px et l'autorisation de passer à la ligne : au besoin la navigation
   descend sous la recherche plutôt que de la manger. */
/* SOUS 640 px, `.tools-row` EST EN COLONNE — et dans un conteneur en colonne, `flex-basis`
   s'applique à la HAUTEUR. Écrites sans garde, ces deux lignes donnaient 260 px de HAUT au
   champ de recherche sur téléphone, et les icônes — positionnées en absolu de `top: 0` à
   `bottom: 0` — s'étiraient avec lui : un trou noir de 260 px au milieu de l'en-tête.
   Vu sur l'appareil de Frédéric, pas par un test : les tests ne mesuraient que le
   débordement HORIZONTAL. */
@media (min-width: 640px) {
    .tools-row { flex-wrap: wrap; }
    .search { flex: 1 1 260px; }
}

/* LA ZONE TACTILE DES PETITES COMMANDES (12/09/2026). Mesuré après coup : la flèche de
   retour accueil de la barre d'application faisait 26 × 26 px, et la corbeille 36 × 30 —
   deux cibles sous les 44 px de la règle 5 de DEMARRAGE.md, et les deux introduites par
   mes propres lots. La flèche est la commande la plus utilisée du site : c'est la pire
   place pour une cible trop petite.
   On garde le dessin et on agrandit la PRISE, par un pseudo-élément transparent : changer
   la taille visible ferait grossir la barre de chrome, qu'on venait justement d'affiner. */
button.plat-case, .plat-corbeille { position: relative; }
button.plat-case::after, .plat-corbeille::after {
    content: ""; position: absolute;
    top: 50%; left: 50%; transform: translate(-50%, -50%);
    width: 44px; height: 44px;
}

/* ==============================================================================
   §15. LE HAUT DE L'ÉCRAN SUR TÉLÉPHONE (12/09/2026)
   ------------------------------------------------------------------------------
   Constaté sur l'appareil de Frédéric : CINQ rangées empilées avant le contenu,
   pour très peu de chose, et trois doublons dedans.

   Ce qui part, et pourquoi — aucune information n'est perdue :
   - LE BANDEAU D'ÉTAT. Il affiche l'heure et les initiales de l'agent. L'heure est
     déjà celle d'Android, à deux centimètres au-dessus ; les initiales sont sur la
     pastille `#agentChip`, dans la même vue. On affichait deux fois la même chose,
     sur une rangée entière.
   - LE BOUTON « ACCUEIL ». Depuis le lot 5, l'accueil est le premier onglet de la
     barre du bas — au pouce. Un second bouton en haut de l'écran, plus difficile à
     atteindre, ne sert plus qu'à prendre de la place.

   Ce qui reste tient en deux rangées : le titre de l'écran avec son retour, puis la
   recherche et les trois pastilles SUR LA MÊME LIGNE. C'est possible maintenant que
   les boutons de mode sont descendus : il ne reste que trois pastilles à loger.
   ============================================================================== */
@media (max-width: 767px) {
    .plat-menubar { display: none; }

    .brand-row { gap: 0; }

    /* Recherche et pastilles sur une seule ligne. */
    .tools-row { flex-direction: row; align-items: center; gap: 8px; }
    .search { flex: 1 1 auto; min-width: 0; }
    .mode-row { flex: 0 0 auto; gap: 6px; }

    /* DES PASTILLES DE MÊME TAILLE. « FL » porte du texte, les deux autres une icône :
       sans taille imposée, la première était nettement plus large et la rangée
       paraissait bancale. 44 px, la cible tactile de la règle 5. */
    .mode-row .chip, .mode-row .theme-btn {
        min-height: 44px; min-width: 44px; padding: 0 8px;
        display: inline-flex; align-items: center; justify-content: center;
    }
}

/* LE COCKPIT CESSE D'ÊTRE VIOLET. `.chip--admin` était en `--ctp-mauve` — décoratif,
   et contraire à la règle du §1 : un seul accent porte la marque, les autres ne
   distinguent qu'un ÉTAT. Le Cockpit n'est pas un état, c'est une destination, et ce
   violet jurait entre deux pastilles neutres. Il est déjà masqué pour qui n'y a pas
   droit : il n'a pas besoin de crier en plus. */
.chip--admin { color: var(--ctp-subtext0); }
.chip--admin:hover { color: var(--ctp-text); border-color: var(--ctp-surface2); }

/* LA LOUPE DÉCORATIVE LAISSE LA PLACE AU TEXTE. Mesuré à 360 px : le champ fait 228 px
   et 124 lui sont pris par le rembourrage réservé aux icônes — il restait 104 px de
   texte, soit « Rechercher : mo ». La loupe de gauche est purement décorative
   (`pointer-events: none`) : un champ dont le libellé commence par « Rechercher » n'a
   pas besoin qu'on lui dessine une loupe. L'appareil photo, lui, reste : il déclenche
   le scan de lot, et c'est une commande. */
@media (max-width: 767px) {
    .search-ic { display: none; }
    .search-input { padding-left: 14px; }
}

/* ==============================================================================
   §16. LES TICKETS ODOO — RESTAURÉS (12/09/2026)
   ------------------------------------------------------------------------------
   Ces quatorze règles existaient (ancienne feuille, l. 2869-2882). Je les ai
   emportées à la table rase : elles étaient rangées dans l'intervalle de la section
   « Silkscreen », que j'ai supprimé d'un bloc. Sans elles, le balisage — pourtant
   correct, avec date, sujet et école en éléments distincts — retombait en liste à
   puces brute, tout collé sur une ligne. Frédéric l'a vu sur son téléphone.

   TROISIÈME FOIS QUE CE PIÈGE SE REFERME cette nuit, après `.visually-hidden` et le
   reste de la section « verre » : dans ce fichier, de vrais composants étaient rangés
   à l'intérieur de sections d'habillage. Supprimer un habillage en bloc emporte donc
   du fonctionnel, et rien ne le signale — ni une erreur, ni un test.

   Restaurées telles quelles, avec une seule adaptation : sur téléphone, la date passe
   AU-DESSUS du sujet au lieu d'être à côté. À 360 px, une grille à deux colonnes
   laissait au sujet moins de la moitié de la ligne, et il était coupé à l'ellipse
   presque à chaque fois. Sobre à dessein : c'est une information de contexte, pas une
   alerte. Un ticket ouvert se distingue par un filet à gauche, pas par une couleur.
   ============================================================================== */
.tk-bloc { margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--ctp-surface0); }
.tk-titre { font-size: 12px; font-weight: 700; color: var(--ctp-subtext1); margin-bottom: 6px; }
.tk-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.tk-item {
    display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 2px 8px; align-items: baseline;
    font-size: 13px; padding: 8px 10px;
    border-left: 2px solid transparent; background: var(--ctp-mantle); border-radius: var(--r-sm);
}
.tk-item--ouvert { border-left-color: var(--ctp-peach); }
.tk-date {
    font-family: var(--f-mono); font-size: 11px; color: var(--ctp-subtext0); white-space: nowrap;
}
.tk-sujet { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ctp-text); }
.tk-etape, .tk-ecole { font-size: 11px; color: var(--ctp-subtext0); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tk-list--home .tk-ecole { grid-column: 2; }
.tk-vide { margin: 0; font-size: 13px; color: var(--ctp-subtext0); }
.tk-pied { margin-top: 10px; font-size: 11px; color: var(--ctp-subtext0); }
.tk-pied--vieux { color: var(--ctp-peach); }

/* Sous 480 px, la date prend sa propre ligne : à deux colonnes, le sujet gardait moins
   de la moitié de la largeur et finissait coupé à presque chaque ticket. */
@media (max-width: 480px) {
    .tk-item { grid-template-columns: minmax(0, 1fr); }
    .tk-date { grid-column: 1; }
    .tk-sujet { white-space: normal; overflow: visible; font-weight: 600; line-height: 1.35; }
    .tk-list--home .tk-ecole { grid-column: 1; }
}

/* ==============================================================================
   §17. LES FICHES RÉCENTES — DE VRAIES TUILES (12/09/2026)
   ------------------------------------------------------------------------------
   Quatrième composant dépouillé par la table rase, trouvé comme les trois autres :
   par Frédéric, sur son téléphone. `.home-recente` n'avait plus AUCUNE règle — la
   pastille flottait au-dessus d'une ligne de texte nue, sans cadre ni séparation.
   Les anciennes règles employaient les jetons Platinum (`--face`, `--cadre`, `--lum`),
   disparus avec l'habillage : elles ne pouvaient pas être reprises telles quelles.
   Elles ont été supprimées sans être remplacées, ce qui est le vrai défaut.

   Deux colonnes plutôt qu'une liste : ce sont des raccourcis vers ce qu'on vient de
   consulter, on les reconnaît d'un coup d'œil à leur pictogramme. Les empiler en
   pleine largeur gâchait la moitié de l'écran pour un titre de trois mots.
   ============================================================================== */
.home-recentes {
    margin-top: 12px; padding-top: 12px;
    border-top: 1px solid var(--ctp-surface1);
}
.home-recentes-h {
    display: block; margin-bottom: 8px;
    font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
    color: var(--ctp-subtext0);
}
/* La grille se remplit d'elle-même : deux colonnes sur un téléphone, davantage si la
   place le permet. Pas de point de rupture à maintenir. */
.home-recentes { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }
.home-recentes-h { grid-column: 1 / -1; margin-bottom: 0; }

/* LA PASTILLE AU-DESSUS, PAS À CÔTÉ. Mesuré : côte à côte, il ne restait qu'une
   centaine de pixels au titre, et « Renouvellement » — un seul mot de 14 lettres —
   se coupait en plein milieu quel que soit le réglage de césure. Empilée, la pastille
   rend au texte toute la largeur de la tuile. C'est aussi ce à quoi ressemble une
   tuile : un pictogramme, puis son libellé dessous. */
.home-recente {
    display: flex; flex-direction: column; align-items: flex-start; gap: 7px;
    min-height: 78px; padding: 10px; width: 100%;
    text-align: left; cursor: pointer;
    background: var(--ctp-base);
    border: 1px solid var(--ctp-surface1); border-radius: var(--r-md);
    color: var(--ctp-text); font-size: 13px; font-weight: 600; line-height: 1.25;
    transition: background-color .15s cubic-bezier(.4, 0, .2, 1), border-color .15s cubic-bezier(.4, 0, .2, 1);
}
.home-recente:hover { background: var(--ctp-surface0); border-color: var(--ctp-surface2); }
.home-recente:active { background: var(--ctp-surface1); }
.home-recente-ic { flex: 0 0 auto; }
/* Deux lignes au plus, puis l'ellipse : un titre de fiche peut être long
   (« LOT 27A - Tablette 10" iPad »), et une tuile qui grandit avec son texte casse
   l'alignement de toute la grille. */
.home-recente-t {
    min-width: 0; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    /* `break-word` et pas `anywhere` : le second coupait « Renouvellemen/t de
       certificat » en plein mot. On ne brise un mot que s'il ne tient vraiment pas. */
    overflow: hidden; overflow-wrap: break-word;
}

/* ==============================================================================
   §18. UNE SEULE HAUTEUR DANS L'EN-TÊTE (12/09/2026)
   ------------------------------------------------------------------------------
   « Mets tout ensemble, taille uniforme. » Mesuré à 1 280 px : recherche 44,
   onglets 44, pastilles 44… et le CONTENEUR de la navigation à 54, parce qu'il
   ajoutait 4 px de rembourrage et 1 px de cadre de chaque côté. Un seul élément
   décalé de 10 px, et toute la rangée paraît de travers.

   Le cadre du conteneur ne servait à rien : l'entrée courante porte déjà son propre
   aplat. On le retire, tout tombe à 44.
   ============================================================================== */
@media (min-width: 768px) {
    .mode-toggle { padding: 0; border: 0; background: transparent; }
}

/* « ACCUEIL » N'APPARAÎT PLUS DEUX FOIS. Le bouton de l'en-tête et le premier onglet
   de la navigation menaient au même endroit et se touchaient presque — visible d'un
   coup d'œil sur grand écran. Le bouton part à TOUTES les largeurs (il n'était masqué
   que sur téléphone jusqu'ici) ; l'onglet reste, il est dans la barre avec les autres.
   On masque le BOUTON, pas sa rangée : elle porte le seul <h1> de la page en
   `.visually-hidden`, et la masquer ferait tomber `page-has-heading-one` chez axe. */
.brand-row .btn-home { display: none; }

/* LA RANGÉE DE MARQUE NE PREND PLUS DE PLACE. Une fois son bouton retiré, elle ne
   contient plus que le <h1> en `.visually-hidden` — mais elle gardait `width: 100%`
   et réservait 628 px sur grand écran : un vide à gauche, et tout le reste poussé à
   droite. On la laisse dans le flux pour l'arbre d'accessibilité, sans lui donner de
   largeur. La recherche et la navigation reprennent alors toute la ligne. */
.brand-row { width: auto; flex: 0 0 auto; }

/* ET LE PLAFOND DE LARGEUR SAUTE. `.tools-row` était plafonnée à 42 rem et
   `.site-header-inner` est en `space-between` : avec une rangée de marque désormais
   vide à gauche, tout le contenu se retrouvait collé à droite avec un vide de 600 px
   à côté. Le plafond avait un sens quand la marque occupait la gauche ; il n'en a
   plus. La recherche et la navigation prennent la ligne entière. */
@media (min-width: 768px) {
    .tools-row { max-width: none; flex: 1 1 auto; }
    .site-header-inner { justify-content: flex-start; }
}

/* ==============================================================================
   §19. FEEDBACK TERRAIN — RESTAURÉ (12/09/2026)
   ------------------------------------------------------------------------------
   Cinquième composant dépouillé par la table rase, et le premier trouvé par une
   MESURE plutôt que par l'œil de Frédéric : le contrôle 21 de `verifs.js`, écrit
   juste après, recense les classes posées par le HTML et par `script.js` qui n'ont
   aucune règle. Les cinq classes de cette modale y sont apparues d'un coup.

   Sobre : ce n'est pas un formulaire, c'est un mot qu'on écrit debout dans un couloir.
   ============================================================================== */
.fb-label { display: block; font-size: 12px; font-weight: 700; color: var(--ctp-subtext1); margin-bottom: 6px; }
.fb-texte {
    width: 100%; min-height: 110px; resize: vertical; font: inherit;
    font-size: 16px;   /* 16 px : SEUIL iOS. En dessous, Safari zoome sur le champ au premier appui. */
    color: var(--ctp-text); background: var(--ctp-base); border: 1px solid var(--ctp-surface1);
    border-radius: var(--r-md); padding: 10px 12px; line-height: 1.45;
}
.fb-texte:focus { outline: 2px solid var(--ctp-blue); outline-offset: 1px; }
.fb-texte::placeholder { color: var(--ctp-overlay0); }

/* Relecture des feedbacks dans le Cockpit */
.fb-msg {
    padding: 8px 10px; border-left: 2px solid var(--ctp-green);
    background: var(--ctp-mantle); border-radius: var(--r-md); margin-bottom: 8px;
}
.fb-msg-meta { font-size: 11px; color: var(--ctp-subtext0); margin-bottom: 3px; }
.fb-msg-texte { font-size: 13px; color: var(--ctp-text); white-space: pre-wrap; overflow-wrap: anywhere; }
