/* Polices embarquées : aucun appel sortant. Barlow reprend les lettres
   ouvertes de la signalétique ; sa variante resserrée signe les titres et
   les compteurs sans comprimer les formulaires. Licence dans polices/OFL.txt. */
@font-face {
    font-family: "Barlow"; font-style: normal; font-weight: 400; font-display: swap;
    src: url("polices/Barlow-Regular.woff2") format("woff2");
}
@font-face {
    font-family: "Barlow"; font-style: normal; font-weight: 600; font-display: swap;
    src: url("polices/Barlow-SemiBold.woff2") format("woff2");
}
@font-face {
    font-family: "Barlow"; font-style: normal; font-weight: 700; font-display: swap;
    src: url("polices/Barlow-Bold.woff2") format("woff2");
}
@font-face {
    font-family: "Barlow Semi Condensed"; font-style: normal; font-weight: 600; font-display: swap;
    src: url("polices/BarlowSemiCondensed-SemiBold.woff2") format("woff2");
}

/*
 * Socle visuel Atlas.
 *
 * Contraintes de conception, issues de l'usage réel en atelier :
 *  - Cibles tactiles de 48 px minimum : la saisie se fait debout, parfois avec
 *    des gants, sur un iPad posé sur une aile.
 *  - Aucune interaction dépendant du survol ni du clic droit — inatteignables
 *    au doigt. Tout ce qui est actionnable est visible en permanence.
 *  - Contraste élevé : l'éclairage d'un atelier est mauvais et l'écran est
 *    souvent vu de biais.
 *  - Aucune dimension fixe en pixels sur les conteneurs : la même page sert un
 *    écran de bureau et une tablette.
 */

/* ===========================================================================
   SOCLE DE TOKENS
   ---------------------------------------------------------------------------
   Une seule couche décide de l'apparence d'Atlas. Aucune couleur ne s'écrit
   plus en dur dans une règle : elle se nomme par ce qu'elle SIGNIFIE (danger,
   vigilance, action) et non par ce qu'elle vaut. C'est ce qui rend un thème
   possible — et un changement d'arbitrage bon marché.

   Deux thèmes RÉELLEMENT dessinés, pas une inversion automatique : le mode
   sombre a ses propres valeurs, choisies pour l'ardoise, et le mode clair les
   siennes, choisies pour le papier. Les deux passent les mêmes seuils de
   contraste (4,5:1 pour le texte courant, 3:1 pour les gros caractères et les
   contours d'interface) — un atelier est mal éclairé et l'écran est vu de
   biais, la lisibilité n'est pas un supplément.

   Le thème suit le système tant que l'utilisateur n'a rien choisi ; son choix,
   une fois posé, est conservé (voir le bouton de bascule dans la barre).
   =========================================================================== */

:root {
    color-scheme: light;

    /* Surfaces d'un poste de pilotage : l'ardoise structure, le bleu guide,
       le papier froid laisse lire les documents pendant toute la journée. */
    --mh-fond: #f2f5f8;
    --mh-fond-2: #e9eef4;
    --mh-surface: #ffffff;       /* carte, tableau, panneau */
    --mh-surface-haute: #ffffff; /* surface élevée : panneau latéral, popover */
    /* Le fond d'un bouton neutre ne suit ni la surface ni le fond : sur le
       papier il doit ressortir du blanc, sur l'ardoise il doit ressortir du
       noir. Deux valeurs, un seul nom. */
    --mh-bouton-fond: #ffffff;
    --mh-bouton-fond-survol: #e9eef4;

    /* --- Texte — trois niveaux d'encre, bleu-ardoise très sombre --- */
    --mh-texte: #172b40;
    --mh-texte-doux: #4b6075;
    --mh-texte-tenu: #596e81;

    /* --- Lignes — filets froids et discrets --- */
    --mh-bord: rgba(23, 34, 43, .12);
    --mh-bord-fort: rgba(23, 34, 43, .26);

    /* Le bleu reste l'action principale. Sa saturation distingue le geste
       utile ; les teintes métier gardent leurs sens et leurs libellés. */
    --mh-action: #245de2;
    --mh-action-survol: #194abe;
    --mh-action-encre: #ffffff;
    --mh-action-doux: rgba(36, 93, 226, .10);
    --mh-accent: #a6854e;                       /* bronze liseré (non-texte) */
    --mh-accent-texte: #8a6a2e;                 /* bronze lisible : 5:1 sur blanc */
    --mh-accent-doux: rgba(166, 133, 78, .16);

    /* --- États ------------------------------------------------------------
       Chaque famille a un ton PLEIN (texte, liseré) et un ton DOUX (fond de
       pastille). Le doux est translucide : il se compose aussi bien sur une
       surface que sur un creux, sans jamais avoir à exister en deux versions. */
    --mh-succes: #2f6b4f;        --mh-succes-doux: rgba(47, 107, 79, .13);
    --mh-vigilance: #8a5a1e;     --mh-vigilance-doux: rgba(138, 90, 30, .14);
    --mh-danger: #8c3a38;        --mh-danger-doux: rgba(140, 58, 56, .13);
    --mh-information: #2458b5;   --mh-information-doux: rgba(36, 88, 181, .10);
    --mh-neutre: #52606a;        --mh-neutre-doux: rgba(23, 34, 43, .07);   /* 5,0:1 sur le fond doux — 5c6a74 donnait 4,3 (axe, 05/09/2026) */
    --mh-mauve: #57429e;         --mh-mauve-doux: rgba(87, 66, 158, .13);

    /* Profondeur graduée : file de travail, commande pressable, panneau. */
    --mh-ombre: 0 2px 3px rgba(23, 43, 64, .025), 0 8px 24px rgba(23, 43, 64, .035);
    --mh-ombre-haute: 0 14px 48px rgba(12, 30, 52, .22);
    --mh-survol: rgba(23, 34, 43, .045);
    --mh-voile: rgba(17, 24, 32, .5);
    --mh-ombre-defilement: rgba(23, 34, 43, .22);

    /* --- Chrome : barre de navigation et écrans d'entrée -------------------
       L'ardoise navale de la barre est l'identité d'Atlas : elle ne change PAS
       avec le thème. En clair elle coiffe la page, en sombre elle s'en détache
       par un liseré. Un seul jeu de valeurs pour les deux. */
    --mh-chrome: #142334;
    --mh-chrome-2: #1d3349;
    --mh-chrome-texte: #f5f9ff;
    --mh-chrome-texte-doux: #a8bbcf;
    --mh-chrome-bord: rgba(169, 199, 212, .14);
    --mh-chrome-action: #82b1ff;
    --mh-chrome-selection: #263f5c;
    --mh-depart-action: #3978f6;

    /* La plaque d'immatriculation est la clé d'entrée du métier : elle doit
       rester un OBJET détaché du fond, pas une suite de caractères. En clair
       c'est une plaque sombre ; en sombre, la même plaque prise un cran plus
       clair que la surface — sans quoi elle s'y dissoudrait. */
    --mh-plaque-fond: #1b2530;
    --mh-plaque-texte: #f2eee7;

    /* --- Typographie — cinq niveaux utiles, plus un pour les chiffres ------
       Au-delà, les tailles se ressemblent et la hiérarchie se dissout. */
    --mh-t-xs: .75rem;      /* étiquette en capitales, méta */
    --mh-t-sm: .875rem;     /* texte secondaire */
    --mh-t-md: 1rem;        /* corps */
    --mh-t-lg: 1.25rem;     /* titre de section, de panneau */
    --mh-t-xl: 2.125rem;    /* titre de page */
    --mh-t-chiffre: 2.125rem; /* la valeur qu'on vient lire de loin */

    --mh-police: "Barlow", "Segoe UI", system-ui, sans-serif;
    --mh-police-titre: "Barlow Semi Condensed", "Bahnschrift", "Segoe UI", sans-serif;
    --mh-police-serif: var(--mh-police-titre); /* alias des anciens écrans */
    --mh-police-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;

    /* --- Trame d'espacement — sept valeurs, multiples de 4 px --- */
    --mh-e-1: .25rem;
    --mh-e-2: .5rem;
    --mh-e-3: .75rem;
    --mh-e-4: 1rem;
    --mh-e-5: 1.5rem;
    --mh-e-6: 2rem;
    --mh-e-7: 3rem;

    /* Les champs s'emboîtent dans les panneaux ; les cartes de départ ont
       une silhouette propre. Tous les objets n'ont pas le même rayon. */
    --mh-r-sm: 5px;
    --mh-r-md: 9px;
    --mh-r-lg: 14px;
    --mh-r-plein: 999px;   /* réservé aux pastilles-capsules d'état */

    /* --- Cible tactile : la saisie se fait debout, parfois avec des gants --- */
    --mh-cible: 48px;

    /* --- Focus ------------------------------------------------------------
       Un seul motif partout : un trait d'accent PLUS un halo. Le trait suffit
       sur fond clair, le halo le rattrape sur les fonds colorés. */
    --mh-focus-anneau: 0 0 0 3px var(--mh-action-doux);
    --mh-focus-trait: 2px solid var(--mh-action);
    --mh-duree-geste: 150ms;
    --mh-courbe-geste: cubic-bezier(.2, .8, .2, 1);
}

/* Les prérequis sont un chemin vers la première facture, avec la même
   hiérarchie et les mêmes surfaces que le reste de l'outil. */
.mh-actions-accueil { display: flex; flex-wrap: wrap; gap: .5rem; margin-bottom: 1rem; }
.mh-preparation {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
    gap: .75rem; padding: 1rem; margin-bottom: 1rem;
    color: var(--mh-texte); background: var(--mh-information-doux);
    border: 1px solid var(--mh-bord-fort); border-radius: var(--mh-rayon, .5rem);
}
.mh-preparation > div { flex: 1 1 18rem; min-width: 0; }
.mh-preparation p { margin: .4rem 0 0; }
.mh-saisie-groupe { border: 0; padding: 0; margin: 0; min-width: 0; }
/* Replier conserve la saisie dans le DOM ; un display:flex du composant
   ne doit pas annuler l'attribut natif de masquage. */
.mh [hidden] { display: none !important; }
.mh-recherche-resultats .mh-choix-creer .mh-recherche-titre { color: var(--mh-texte); }
@media (max-width: 32rem) {
    .mh-preparation .mh-bouton, .mh-actions-accueil .mh-bouton { flex: 1 1 auto; }
}

/* --- Thème sombre ---------------------------------------------------------
   Valeurs propres, pas une inversion : l'ardoise (#14161d) n'est pas le
   négatif du papier, et le miel s'y éclaircit pour rester lisible (7,6:1).
   Deux portes vers ce bloc : la préférence système tant que rien n'a été
   choisi, et le choix explicite. La règle « :not([data-theme="clair"]) »
   garantit qu'un choix « clair » gagne contre un système sombre. */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="clair"]) {
        color-scheme: dark;

        --mh-fond: #101c2a;
        --mh-fond-2: #203247;
        --mh-surface: #182a3c;
        --mh-surface-haute: #203247;
        --mh-bouton-fond: #203247;
        --mh-bouton-fond-survol: #294057;

        --mh-texte: #edf4fe;
        --mh-texte-doux: #b8c9dc;
        --mh-texte-tenu: #a0b5cb;

        --mh-bord: rgba(169, 199, 212, .13);
        --mh-bord-fort: rgba(169, 199, 212, .26);

        --mh-action: #98bdff;
        --mh-action-survol: #bbd4ff;
        --mh-action-encre: #142334;
        --mh-action-doux: rgba(152, 189, 255, .12);
        --mh-accent: #d3a24b;
        --mh-accent-texte: #d3a24b;
        --mh-accent-doux: rgba(211, 162, 75, .14);

        --mh-succes: #6fa383;        --mh-succes-doux: rgba(111, 163, 131, .15);
        --mh-vigilance: #d9a85c;     --mh-vigilance-doux: rgba(217, 168, 92, .15);
        --mh-danger: #c97b72;        --mh-danger-doux: rgba(201, 123, 114, .15);
        --mh-information: #a9c7d4;   --mh-information-doux: rgba(169, 199, 212, .14);
        --mh-neutre: #8a949e;        --mh-neutre-doux: rgba(189, 197, 205, .08);
        --mh-mauve: #b3a2e8;         --mh-mauve-doux: rgba(179, 162, 232, .15);

        --mh-ombre: 0 1px 2px rgba(0, 0, 0, .34);
        --mh-ombre-haute: 0 14px 44px rgba(0, 0, 0, .6);
        --mh-survol: rgba(233, 240, 245, .05);
        --mh-voile: rgba(6, 10, 14, .7);
        --mh-ombre-defilement: rgba(0, 0, 0, .5);

        --mh-plaque-fond: #232f3b;
        --mh-plaque-texte: #f2eee7;
    }
}

:root[data-theme="sombre"] {
    color-scheme: dark;

    --mh-fond: #101c2a;
    --mh-fond-2: #203247;
    --mh-surface: #182a3c;
    --mh-surface-haute: #203247;
    --mh-bouton-fond: #203247;
    --mh-bouton-fond-survol: #294057;

    --mh-texte: #edf4fe;
    --mh-texte-doux: #b8c9dc;
    --mh-texte-tenu: #a0b5cb;

    --mh-bord: rgba(169, 199, 212, .13);
    --mh-bord-fort: rgba(169, 199, 212, .26);

    --mh-action: #98bdff;
    --mh-action-survol: #bbd4ff;
    --mh-action-encre: #142334;
    --mh-action-doux: rgba(152, 189, 255, .12);
    --mh-accent: #d3a24b;
    --mh-accent-texte: #d3a24b;
    --mh-accent-doux: rgba(211, 162, 75, .14);

    --mh-succes: #6fa383;        --mh-succes-doux: rgba(111, 163, 131, .15);
    --mh-vigilance: #d9a85c;     --mh-vigilance-doux: rgba(217, 168, 92, .15);
    --mh-danger: #c97b72;        --mh-danger-doux: rgba(201, 123, 114, .15);
    --mh-information: #a9c7d4;   --mh-information-doux: rgba(169, 199, 212, .14);
    --mh-neutre: #8a949e;        --mh-neutre-doux: rgba(189, 197, 205, .08);
    --mh-mauve: #b3a2e8;         --mh-mauve-doux: rgba(179, 162, 232, .15);

    --mh-ombre: 0 1px 2px rgba(0, 0, 0, .34);
    --mh-ombre-haute: 0 14px 44px rgba(0, 0, 0, .6);
    --mh-survol: rgba(233, 240, 245, .05);
    --mh-voile: rgba(6, 10, 14, .7);
    --mh-ombre-defilement: rgba(0, 0, 0, .5);

    --mh-plaque-fond: #232f3b;
    --mh-plaque-texte: #f2eee7;
}

/* --- Noms hérités ---------------------------------------------------------
   Une centaine de règles nomment encore les anciennes variables. Elles ne
   sont PAS réécrites à la main en une passe — §7 de la commande : une
   substitution mécanique de 87 couleurs rend toute régression inattribuable.
   Elles deviennent des alias : chaque règle existante suit désormais le
   thème sans avoir été touchée, et la migration nominale se fait par lots. */
:root {
    --mh-encre: var(--mh-texte);
    --mh-encre-douce: var(--mh-texte-doux);
    --mh-accent-sombre: var(--mh-action-survol);
    --mh-accent-pale: var(--mh-accent-doux);
    --mh-alerte: var(--mh-vigilance);
    --mh-danger-pale: var(--mh-danger-doux);
    --mh-rayon: var(--mh-r-md);
}

.mh {
    color: var(--mh-texte);
    font-family: var(--mh-police);
    font-size: var(--mh-t-md);
    line-height: 1.55;
}

/* --- Liens ----------------------------------------------------------------
   Un lien dans le corps du texte se souligne : la couleur seule ne suffit pas
   à qui ne la distingue pas. Les liens QUI SONT des surfaces (tuile, alerte,
   ligne de résultat) portent leur propre dessin et s'excluent d'ici.

   Ils ne sont PAS miel. Le miel est la couleur de l'action principale ; plus
   il est rare, plus il vaut. Un lien de texte relève de l'information — c'est
   le rôle qu'a repris le bleu historique d'Atlas. */
.mh a:not([class]) {
    color: var(--mh-information);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.mh a:not([class]):hover { text-decoration-thickness: 2px; }

/* Le focus se voit PARTOUT, sans exception : un clavier qui se perd dans une
   liste de vingt-cinq lignes ne revient pas. */
.mh a:focus-visible,
.mh button:focus-visible,
.mh [tabindex]:focus-visible {
    outline: var(--mh-focus-trait);
    outline-offset: 2px;
}

.mh h2, .mh h3 { font-family: var(--mh-police-titre); letter-spacing: -.01em; }

.mh-icone { display: block; flex: 0 0 auto; }

/* Ce qui est cliquable réagit, mais sobrement et jamais au détriment de qui
   souffre du mouvement. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
        scroll-behavior: auto !important;
    }
}

/* --- En-tête de page ---------------------------------------------------- */

/* L'en-tête de page a maigri de 8 px le 10 août : mesuré au banc, la première
   DONNÉE d'un écran arrivait à 189 px du haut sur desktop et 361 px sur
   téléphone. Chaque pixel d'ossature est un pixel de moins pour ce que
   l'utilisateur est venu lire. */
.mh-entete {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 1rem;
}

.mh-entete h1 {
    font-family: var(--mh-police-titre);
    font-size: var(--mh-t-xl);
    font-weight: 600;
    letter-spacing: -.025em;
    margin: 0;
    text-wrap: balance;
}

.mh-compte {
    color: var(--mh-texte-doux);
    font-size: var(--mh-t-sm);
    font-variant-numeric: tabular-nums;
}

/* --- Barre d'outils ----------------------------------------------------- */

.mh-outils {
    display: flex;
    flex-wrap: wrap;
    gap: var(--mh-e-3);
    margin-bottom: 1.25rem;
}

/* Une liste déroulante posée directement dans une barre d'outils n'est pas
   dans un .mh-champ : sans cette règle elle garde le dessin du navigateur et
   détonne à côté des boutons — visible au banc sur la barre des factures. */
.mh-outils select {
    min-height: var(--mh-cible);
    padding: 0 .75rem;
    font-family: inherit;
    font-size: var(--mh-t-md);
    color: var(--mh-texte);
    background: var(--mh-bouton-fond);
    border: 1px solid var(--mh-bord);
    border-radius: var(--mh-r-md);
    cursor: pointer;
}

.mh-outils select:focus-visible { outline: var(--mh-focus-trait); outline-offset: 2px; }

.mh-recherche {
    flex: 1 1 18rem;
    position: relative;
}

.mh-recherche input {
    width: 100%;
    min-height: var(--mh-cible);
    padding: 0 var(--mh-e-4) 0 2.75rem;
    font-size: var(--mh-t-md);
    font-family: inherit;
    color: var(--mh-texte);
    background: var(--mh-surface);
    border: 1px solid var(--mh-bord-fort);
    border-radius: var(--mh-r-md);
}

.mh-recherche input:focus {
    outline: none;
    border-color: var(--mh-action);
    box-shadow: var(--mh-focus-anneau);
}

.mh-recherche svg {
    position: absolute;
    left: .9rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--mh-texte-doux);
    pointer-events: none;
}

/* --- Boutons ------------------------------------------------------------ */

.mh-bouton {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--mh-e-2);
    min-height: var(--mh-cible);
    padding: 0 1.25rem;
    font-size: var(--mh-t-md);
    font-weight: 600;
    font-family: inherit;
    color: var(--mh-texte);
    background: var(--mh-bouton-fond);
    border: 1px solid var(--mh-bord);
    border-radius: var(--mh-r-md);
    cursor: pointer;
    text-decoration: none;
    box-shadow: 0 1px 2px var(--mh-bord);
    transition: background-color var(--mh-duree-geste), border-color var(--mh-duree-geste),
                color var(--mh-duree-geste), transform var(--mh-duree-geste) var(--mh-courbe-geste), box-shadow var(--mh-duree-geste);
}

.mh-bouton:hover { background: var(--mh-bouton-fond-survol); border-color: var(--mh-bord-fort); }
.mh-bouton:active:not(:disabled) { transform: translateY(1px); box-shadow: none; }

/* Un seul motif de focus dans tout Atlas : trait d'accent + halo. Il se voit
   sur le papier comme sur l'ardoise, et sur les fonds pleins des boutons
   d'action où un simple liseré se perdrait. */
.mh-bouton:focus-visible {
    outline: var(--mh-focus-trait);
    outline-offset: 2px;
}

/* L'action principale : pleine, UNE par écran ou par panneau.
   Sa rareté est ce qui la rend évidente — multipliée, elle ne dit plus rien. */
.mh-bouton--primaire {
    color: var(--mh-action-encre);
    background: var(--mh-action);
    border-color: var(--mh-action);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 3px 8px var(--mh-action-doux);
}

.mh-bouton--primaire:hover { background: var(--mh-action-survol); border-color: var(--mh-action-survol); }

/* Action secondaire d'une liste dense : lisible, mais qui ne réclame pas.
   Sans elle, vingt-cinq lignes de tableau portent cent boutons de même
   poids et l'œil n'a plus rien à quoi se raccrocher. */
.mh-bouton--discret {
    box-shadow: none;
    background: transparent;
    border-color: transparent;
    color: var(--mh-texte-doux);
    font-weight: 550;
}

.mh-bouton--discret:hover {
    background: var(--mh-survol);
    border-color: var(--mh-bord);
    color: var(--mh-texte);
}

/* Taille réduite : le dessin se resserre là où la souris suffit — dans une
   ligne de tableau dense, au bureau. */
.mh-bouton--petit {
    min-height: 38px;
    padding: 0 var(--mh-e-3);
    font-size: var(--mh-t-sm);
}

/* ARBITRAGE TACTILE : 38 px n'est PAS la norme mobile. Sur un téléphone, un
   bouton compact redevient une cible de 44 px — mesuré au banc sur
   « Réessayer » de la file d'emails, qui est une vraie action et se pressait
   au doigt à 38 px. Le dessin reste resserré, seule la hauteur cède. */
@media (max-width: 40rem) {
    .mh-bouton--petit { min-height: 44px; }
}

.mh-bouton--danger { color: var(--mh-danger); border-color: var(--mh-danger); background: transparent; }
.mh-bouton--danger:hover { background: var(--mh-danger-doux); border-color: var(--mh-danger); color: var(--mh-danger); }

.mh-bouton:disabled { opacity: .5; cursor: not-allowed; box-shadow: none; }
.mh-bouton:disabled:hover { border-color: var(--mh-bord); background: var(--mh-bouton-fond); }

/* --- Tableau ------------------------------------------------------------ */

/* « position: relative » n'est pas décoratif : sans lui, le cadre ne fournit
   aucun bloc conteneur, et les intitulés en « position: absolute » destinés
   aux lecteurs d'écran (.mh-visuellement-cache, dans l'en-tête de la colonne
   d'actions) se placent par rapport au bloc RACINE. Ils échappent alors au
   découpage du cadre : un span de 1 px se retrouvait à 969 px et faisait
   défiler LA PAGE de 170 px sur /factures à 800 px de large — mesuré au banc
   sur factures, ordres et catalogue, entre 512 px (bascule en fiches) et
   1 010 px. Le tableau, lui, défilait déjà correctement dans son cadre. */
.mh-tableau-cadre {
    position: relative;
    background: var(--mh-surface);
    border: 1px solid var(--mh-bord);
    border-radius: var(--mh-r-lg);
    box-shadow: var(--mh-ombre);
    overflow-x: auto;
}

.mh-tableau {
    width: 100%;
    border-collapse: collapse;
    font-size: .95rem;
}

.mh-tableau th {
    padding: .75rem 1rem;
    text-align: left;
    font-size: var(--mh-t-sm);
    font-weight: 600;
    letter-spacing: .01em;
    color: var(--mh-texte-doux);
    background: var(--mh-fond-2);
    border-bottom: 1px solid var(--mh-bord);
    white-space: nowrap;
}

.mh-tableau td {
    padding: .8rem 1rem;
    border-bottom: 1px solid var(--mh-bord);
    vertical-align: middle;
}

.mh-tableau tbody tr:last-child td { border-bottom: none; }
.mh-tableau tbody tr:hover { background: var(--mh-survol); }
.mh-tableau tbody tr { transition: background-color var(--mh-duree-geste); }
.mh-tableau tbody tr:focus-within { background: var(--mh-action-doux); }

.mh-principal { font-weight: 600; }
.mh-secondaire { color: var(--mh-texte-doux); font-size: var(--mh-t-sm); }
/* Une cellule de montant, d'unité ou de taux ne se coupe jamais : à 768 px,
   « 54,90 € » devenait « 54,90 / € » (audit du 05/09/2026). */
.mh-nombre { font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }

/* Plaque d'immatriculation — c'est la clé d'entrée du métier, elle doit se
   repérer instantanément dans une liste. */
.mh-plaque {
    display: inline-block;
    padding: .3rem .6rem;
    font-family: var(--mh-police-mono);
    font-size: .95rem;
    font-weight: 650;
    letter-spacing: .06em;
    text-transform: uppercase;
    background: var(--mh-plaque-fond);
    color: var(--mh-plaque-texte);
    border-radius: var(--mh-r-sm);
    border-left: 4px solid var(--mh-depart-action);
    box-shadow: inset 0 0 0 1px var(--mh-chrome-bord);
    white-space: nowrap;
}

.mh-actions { display: flex; gap: .5rem; justify-content: flex-end; }

.mh-etiquette {
    display: inline-block;
    padding: .2rem .6rem;
    font-size: var(--mh-t-xs);
    font-weight: 600;
    border-radius: var(--mh-r-plein);
    background: var(--mh-neutre-doux);
    color: var(--mh-neutre);
}

.mh-etiquette--fournisseur { background: var(--mh-vigilance-doux); color: var(--mh-vigilance); }

/* --- États -------------------------------------------------------------- */

.mh-vide {
    padding: var(--mh-e-7) var(--mh-e-6);
    text-align: center;
    color: var(--mh-texte-doux);
    border-radius: var(--mh-r-lg);
    background: var(--mh-surface);
    border: 1px dashed var(--mh-bord-fort);
}

.mh-vide p { margin: 0 0 1.25rem; font-size: 1.05rem; }
.mh-vide p:last-child { margin-bottom: 0; }

/* Un message porte sa couleur par son LISERÉ GAUCHE et son texte, pas par un
   aplat criard : sur l'ardoise comme sur le papier, le fond reste une teinte
   douce translucide et le sens vient du bord et du mot. */
.mh-message {
    display: flex;
    gap: var(--mh-e-3);
    padding: var(--mh-e-4) 1.25rem;
    margin-bottom: 1.25rem;
    border-radius: var(--mh-r-md);
    border: 1px solid var(--mh-bord);
    border-left: 4px solid var(--mh-neutre);
    background: var(--mh-fond-2);
    color: var(--mh-texte);
    font-size: .975rem;
}

.mh-message--erreur { background: var(--mh-danger-doux); border-color: var(--mh-bord); border-left-color: var(--mh-danger); }
.mh-message--succes { background: var(--mh-succes-doux); border-color: var(--mh-bord); border-left-color: var(--mh-succes); }
.mh-message--succes::before {
    content: ""; flex: 0 0 1.3rem; width: 1.3rem; height: 1.3rem; margin-top: .15rem;
    background: var(--mh-succes);
    /* Coche purement visuelle : le texte du serveur reste l'annonce accessible. */
    clip-path: polygon(14% 44%, 36% 66%, 84% 18%, 96% 30%, 36% 90%, 2% 56%);
}
/* Utilisée depuis longtemps par les écrans (émission, relance, seed) mais
   jamais définie : le bandeau se fondait dans le blanc. Attrapé au navigateur. */
.mh-message--attention { background: var(--mh-vigilance-doux); border-color: var(--mh-bord); border-left-color: var(--mh-vigilance); }
.mh-message--information { background: var(--mh-information-doux); border-color: var(--mh-bord); border-left-color: var(--mh-information); }

/* --- Aide des raccourcis clavier ---------------------------------------- */

.mh-raccourcis {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 1001;
    background: var(--mh-surface-haute);
    border: 1px solid var(--mh-bord);
    border-radius: var(--mh-r-lg);
    box-shadow: var(--mh-ombre-haute);
    padding: var(--mh-e-5) var(--mh-e-6);
    min-width: 22rem;
}

.mh-raccourcis h2 { margin: 0 0 1rem; font-size: 1.1rem; }

.mh-raccourcis table { border-collapse: collapse; margin-bottom: .75rem; }

.mh-raccourcis td { padding: .3rem .75rem .3rem 0; }

/* --- Planning d'atelier -------------------------------------------------- */

.mh-planning td { vertical-align: top; min-width: 7rem; }

/* La semaine affichée, sous les flèches qui la changent : c'est le seul
   repère qui bouge quand l'atelier est calme. */
.mh-planning-semaine {
    display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
    margin: .6rem 0 .2rem; font-size: 1.02rem;
}

.mh-planning-absent { background: repeating-linear-gradient(
    -45deg, transparent, transparent 6px, var(--mh-neutre-doux) 6px, var(--mh-neutre-doux) 12px); }

.mh-planning-aujourdhui { background: var(--mh-action-doux); box-shadow: inset 0 3px var(--mh-action); }

.mh-planning-ordre {
    display: block;
    margin: .15rem 0;
    padding: .45rem .6rem;
    border-left: 3px solid var(--mh-information);
    border-radius: var(--mh-r-sm);
    background: var(--mh-fond-2);
    font-size: .85rem;
    text-decoration: none;
    color: var(--mh-texte);
    white-space: nowrap;
}

.mh-planning-ordre:hover { background: var(--mh-action-doux); }

.mh-raccourcis kbd {
    display: inline-block;
    min-width: 1.6rem;
    padding: .1rem .4rem;
    border: 1px solid var(--mh-bord-fort);
    border-bottom-width: 2px;
    border-radius: var(--mh-r-sm);
    background: var(--mh-fond-2);
    font-family: inherit;
    font-size: .9rem;
    text-align: center;
}

/* --- Formulaire en panneau latéral -------------------------------------- */

.mh-voile {
    position: fixed;
    inset: 0;
    background: var(--mh-voile);
    z-index: 40;
}

.mh-panneau {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: min(34rem, 100vw);
    background: var(--mh-surface-haute);
    border-left: 1px solid var(--mh-bord);
    box-shadow: var(--mh-ombre-haute);
    z-index: 50;
    display: flex;
    flex-direction: column;
}

.mh-panneau-entete {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 1.25rem 1.5rem;
    border-bottom: 1px solid var(--mh-bord);
    background: var(--mh-surface);
    box-shadow: inset 0 3px var(--mh-action);
}

.mh-panneau-entete h2 { margin: 0; font-family: var(--mh-police-titre); font-size: 1.5rem; font-weight: 600; }

.mh-panneau-corps { flex: 1; overflow-y: auto; padding: 1.5rem; }

.mh-panneau-pied {
    display: flex;
    gap: .75rem;
    justify-content: flex-end;
    padding: 1.25rem 1.5rem;
    border-top: 1px solid var(--mh-bord);
    background: var(--mh-fond-2);
}

.mh-fermer {
    display: flex;
    align-items: center;
    justify-content: center;
    width: var(--mh-cible);
    height: var(--mh-cible);
    background: none;
    border: none;
    border-radius: var(--mh-r-md);
    cursor: pointer;
    color: var(--mh-texte-doux);
}

.mh-fermer:hover { background: var(--mh-survol); color: var(--mh-texte); }
.mh-fermer:focus-visible { outline: var(--mh-focus-trait); outline-offset: 2px; }

/* --- Champs ------------------------------------------------------------- */

.mh-champ { margin-bottom: 1.25rem; }

.mh-champ label {
    display: block;
    margin-bottom: .4rem;
    font-size: var(--mh-t-sm);
    font-weight: 600;
}

.mh-champ .mh-aide {
    display: block;
    margin-top: .3rem;
    font-size: var(--mh-t-sm);
    color: var(--mh-texte-doux);
    font-weight: 400;
}

.mh-champ input,
.mh-champ select,
.mh-champ textarea {
    width: 100%;
    min-height: var(--mh-cible);
    padding: .625rem .875rem;
    font-size: var(--mh-t-md);
    font-family: inherit;
    color: var(--mh-texte);
    background: var(--mh-surface);
    border: 1px solid var(--mh-bord-fort);
    border-radius: var(--mh-r-md);
}

.mh-champ textarea { min-height: 5.5rem; resize: vertical; }
.mh-champ :is(input, select, textarea) {
    transition: border-color var(--mh-duree-geste), box-shadow var(--mh-duree-geste), background-color var(--mh-duree-geste);
}
.mh-champ :is(input, select, textarea):hover:not(:disabled):not(:focus) { border-color: var(--mh-texte-tenu); }

.mh-champ input:focus,
.mh-champ select:focus,
.mh-champ textarea:focus {
    outline: none;
    border-color: var(--mh-action);
    box-shadow: var(--mh-focus-anneau);
}

.mh-champ input:disabled,
.mh-champ select:disabled,
.mh-champ textarea:disabled {
    background: var(--mh-fond-2);
    color: var(--mh-texte-doux);
}

.mh-champ input::placeholder,
.mh-champ textarea::placeholder,
.mh-recherche input::placeholder { color: var(--mh-texte-doux); opacity: 1; }

.mh-champ input.mh-plaque-saisie {
    font-family: var(--mh-police-mono);
    font-size: 1.15rem;
    font-weight: 650;
    letter-spacing: .08em;
    text-transform: uppercase;
}

.mh-duo { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }

@media (max-width: 32rem) {
    .mh-duo { grid-template-columns: 1fr; }
}

.mh-obligatoire { color: var(--mh-danger); }

/* --- Accueil ------------------------------------------------------------ */

.mh-tuiles {
    display: grid;
    /* « min(…, 100%) » et non « 15rem » seul : une largeur minimale en rem
       grandit avec la police. À 200 %, 15rem valent 480 px et la grille
       débordait d'un téléphone de 390 px — l'utilisateur qui agrandit le
       texte pour mieux lire se retrouvait à faire défiler horizontalement.
       La colonne ne descend plus jamais sous la largeur disponible. */
    grid-template-columns: repeat(auto-fit, minmax(min(13rem, 100%), 1fr));
    gap: .875rem;
    margin-bottom: 2rem;
}

/* Le libellé PASSE AVANT la valeur — l'inverse de ce qu'Atlas faisait.
   Un chiffre de 2,25 rem posé en tête se lit avant qu'on sache de quoi il
   parle, et quatre tuiles hautes mangeaient l'écran avant la première chose
   à faire (« compteurs trop hauts », recette du 10 août). On lit maintenant
   la question, puis la réponse — et la carte tient en deux fois moins de
   hauteur sans qu'aucun chiffre ne rétrécisse au point d'être illisible. */
.mh-tuile {
    display: block;
    padding: .9rem 1.1rem;
    background: var(--mh-surface);
    border: 1px solid var(--mh-bord);
    border-radius: var(--mh-r-lg);
    box-shadow: var(--mh-ombre);
    text-decoration: none;
    color: inherit;
    transition: border-color .12s;
}

.mh-tuile--lien:hover { border-color: var(--mh-action); background: var(--mh-action-doux); }
.mh-tuile:focus-visible { outline: var(--mh-focus-trait); outline-offset: 2px; }

.mh-tuile-titre {
    font-size: var(--mh-t-sm);
    font-weight: 600;
    color: var(--mh-texte-doux);
}

.mh-tuile-valeur {
    margin-top: .3rem;
    font-family: var(--mh-police-titre);
    font-size: 2rem;
    font-weight: 600;
    line-height: 1.15;
    letter-spacing: -.01em;
    font-variant-numeric: tabular-nums;
}

/* La précision qui suit le chiffre : marge, nombre de factures, ordres
   ouverts. Elle ne concurrence jamais la valeur. */
.mh-tuile-suite {
    margin-top: .2rem;
    color: var(--mh-texte-doux);
    font-size: var(--mh-t-sm);
    line-height: 1.35;
}

/* Une tuile qui MÈNE quelque part le dit. Le chevron n'est pas décoratif :
   sans lui, rien ne distingue les tuiles cliquables des autres. Il reste en
   teinte de texte — cinq chevrons miel sur une même rangée feraient de
   l'accent un motif de fond. */
.mh-tuile--lien .mh-tuile-titre::after {
    content: " →";
    color: var(--mh-texte-doux);
    font-weight: 700;
}

/* --- Sections d'un formulaire long ---------------------------------------
   La fiche véhicule compte une trentaine de champs. Sans regroupement visible,
   elle devient un mur illisible et la saisie s'allonge — or l'objectif est de
   rester sous les trente secondes pour les cas courants. Les sections suivent
   l'ordre dans lequel l'information arrive : ce qu'on a sous les yeux d'abord,
   ce qu'on lit sur la carte grise ensuite. */

.mh-section {
    margin: 1.75rem 0 1rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--mh-bord);
}

.mh-section:first-of-type { margin-top: 0; padding-top: 0; border-top: none; }

/* Un panneau de saisie porte trois à cinq de ces intitulés, sur quinze
   écrans : en miel, l'accent devenait la couleur ordinaire des formulaires. */
.mh-section-titre {
    margin: 0 0 1rem;
    font-size: var(--mh-t-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .1em;
    color: var(--mh-texte-doux);
}

.mh-trio { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 1rem; }

@media (max-width: 32rem) {
    .mh-trio { grid-template-columns: 1fr; }
}

/* --- Badges d'échéance ---------------------------------------------------
   Une date seule oblige l'utilisateur à calculer de tête. La couleur porte
   l'information, mais jamais seule : le texte reste explicite, pour rester
   lisible en cas de daltonisme comme sur un écran délavé d'atelier. */

.mh-echeance {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: .25rem .6rem;
    font-size: var(--mh-t-xs);
    font-weight: 600;
    border-radius: var(--mh-r-plein);
    white-space: nowrap;
}

.mh-echeance--ok { background: var(--mh-succes-doux); color: var(--mh-succes); }
.mh-echeance--proche { background: var(--mh-vigilance-doux); color: var(--mh-vigilance); }
.mh-echeance--expire { background: var(--mh-danger-doux); color: var(--mh-danger); }
.mh-echeance--vide { color: var(--mh-texte-doux); }

.mh-etiquette--entreprise { background: var(--mh-mauve-doux); color: var(--mh-mauve); }

/* --- États d'un ordre de réparation --------------------------------------
   Le statut est l'information la plus consultée d'une liste d'OR : c'est elle
   qui dit ce qu'il reste à faire. Chaque état a sa couleur, mais le libellé
   reste toujours écrit. */

.mh-etat {
    display: inline-block;
    padding: .25rem .7rem;
    font-size: var(--mh-t-xs);
    font-weight: 700;
    letter-spacing: .01em;
    border-radius: var(--mh-r-plein);
    white-space: nowrap;
}

.mh-etat--nouveau     { background: var(--mh-neutre-doux); color: var(--mh-neutre); }
.mh-etat--encours     { background: var(--mh-information-doux); color: var(--mh-information); }
.mh-etat--termine     { background: var(--mh-succes-doux); color: var(--mh-succes); }
.mh-etat--facturable  { background: var(--mh-vigilance-doux); color: var(--mh-vigilance); }
.mh-etat--facture     { background: var(--mh-mauve-doux); color: var(--mh-mauve); }

.mh-etats { display: flex; flex-wrap: wrap; gap: .5rem; }

.mh-etiquette--prestation { background: var(--mh-succes-doux); color: var(--mh-succes); }

/* Panneau élargi : un ordre de réparation porte un tableau de lignes, qui ne
   tient pas dans la largeur d'un formulaire. */
.mh-panneau--large { width: min(52rem, 100vw); }

/* --- Totaux --------------------------------------------------------------
   Alignés à droite et en chiffres tabulaires : c'est un bloc que l'on compare
   du regard à un devis papier ou à une facture fournisseur.

   L'ARGENT SE LIT DE LOIN. Le total est ce qu'on annonce au client, au
   téléphone ou au comptoir : il ne se lit pas dans la même graisse qu'une
   ventilation de TVA. Le bloc entier prend une surface à lui, et la dernière
   ligne un corps de titre — c'est la seule chose de l'écran qu'on cherche
   sans lire. */

.mh-totaux {
    margin-left: auto;
    width: min(22rem, 100%);
    padding: .75rem 1rem;
    background: var(--mh-fond-2);
    border: 1px solid var(--mh-bord);
    border-radius: var(--mh-r-md);
    font-variant-numeric: tabular-nums;
}

.mh-totaux > div {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 2rem;
    padding: .3rem 0;
}

.mh-totaux span { color: var(--mh-texte-doux); }

.mh-totaux-final {
    border-top: 2px solid var(--mh-texte);
    margin-top: .4rem;
    padding-top: .6rem !important;
    font-family: var(--mh-police-titre);
    font-size: 1.5rem;
    font-weight: 700;
    letter-spacing: -.02em;
}

.mh-totaux-final span { color: var(--mh-texte); font-size: var(--mh-t-sm); }

/* Ce qui RESTE à encaisser est une autre question que ce qui a été facturé —
   et c'est celle qu'on pose au comptoir. Elle prend la couleur de sa
   réponse : rouge tant qu'il reste dû, verte une fois soldée. */
/* Trois situations, trois couleurs, et le rouge n'est PAS le cas courant :
   une facture émise hier avec trente jours de délai n'est ni une erreur ni un
   danger. Peindre en rouge tout reste dû aurait rendu la couleur muette — un
   garage en a toujours. Le rouge se réserve à l'échéance dépassée, que le
   modèle porte réellement. */
.mh-totaux-reste { border-top: 1px solid var(--mh-bord); margin-top: .4rem; padding-top: .5rem !important; }
.mh-totaux-reste strong { font-size: 1.15rem; font-weight: 700; color: var(--mh-information); }
.mh-totaux-reste--retard strong { color: var(--mh-danger); }
.mh-totaux-reste--solde strong { color: var(--mh-succes); }

/* États d'un devis. Couleurs distinctes de celles des ordres : les deux listes
   se consultent à la suite, et une même couleur pour des sens différents
   induirait en erreur. */
.mh-etat--devis-brouillon { background: var(--mh-neutre-doux); color: var(--mh-neutre); }
.mh-etat--devis-envoye    { background: var(--mh-information-doux); color: var(--mh-information); }
.mh-etat--devis-accepte   { background: var(--mh-succes-doux); color: var(--mh-succes); }
.mh-etat--devis-refuse    { background: var(--mh-danger-doux); color: var(--mh-danger); }
.mh-etat--devis-expire    { background: var(--mh-vigilance-doux); color: var(--mh-vigilance); }

/* États d'une facture. */
.mh-etat--fac-brouillon { background: var(--mh-neutre-doux); color: var(--mh-neutre); }
.mh-etat--fac-emise     { background: var(--mh-information-doux); color: var(--mh-information); }
.mh-etat--fac-payee     { background: var(--mh-succes-doux); color: var(--mh-succes); }
.mh-etat--fac-annulee   { background: var(--mh-danger-doux); color: var(--mh-danger); }

/* File des emails — un échec ne ressemble jamais à un envoi réussi.
   Palette identique aux autres familles d'états (le texte reste porteur
   du sens : la couleur n'est jamais seule). */
.mh-etat--email-enattente       { background: var(--mh-neutre-doux); color: var(--mh-neutre); }
.mh-etat--email-encours         { background: var(--mh-information-doux); color: var(--mh-information); }
.mh-etat--email-envoye          { background: var(--mh-succes-doux); color: var(--mh-succes); }
.mh-etat--email-echectemporaire { background: var(--mh-vigilance-doux); color: var(--mh-vigilance); }
.mh-etat--email-echecdefinitif  { background: var(--mh-danger-doux); color: var(--mh-danger); }

.mh-etiquette--avoir { background: var(--mh-vigilance-doux); color: var(--mh-vigilance); margin-left: .5rem; }

/* Fiche en pleine page — pour les écrans de saisie longue qui ne sont pas des
   panneaux latéraux. */
.mh-fiche {
    max-width: 46rem;
    background: var(--mh-surface);
    border: 1px solid var(--mh-bord);
    border-radius: var(--mh-r-lg);
    box-shadow: var(--mh-ombre);
    padding: 1.75rem;
}

.mh-barre-action {
    display: flex;
    justify-content: flex-end;
    gap: .75rem;
    margin-top: 1.75rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--mh-bord);
}

/* --- Alertes du tableau de bord ------------------------------------------
   Chaque alerte est cliquable et mène à l'écran où l'on agit. Une alerte sans
   action possible n'est qu'une source d'anxiété : l'utilisateur apprend à les
   ignorer, et les vraies se perdent avec les autres. */

.mh-alertes {
    display: grid;
    /* Même raison que .mh-tuiles : 19rem débordent dès 125 % de police. */
    grid-template-columns: repeat(auto-fill, minmax(min(19rem, 100%), 1fr));
    gap: .75rem;
}

.mh-alerte {
    display: block;
    padding: .875rem 1rem;
    background: var(--mh-surface);
    border: 1px solid var(--mh-bord);
    border-left: 4px solid var(--mh-neutre);
    border-radius: var(--mh-r-md);
    text-decoration: none;
    color: inherit;
    transition: border-color .12s, background-color .12s;
}

.mh-alerte:hover { border-color: var(--mh-action); background: var(--mh-survol); }
.mh-alerte:focus-visible { outline: var(--mh-focus-trait); outline-offset: 2px; }

.mh-alerte--urgent     { border-left-color: var(--mh-danger); }
.mh-alerte--attention  { border-left-color: var(--mh-vigilance); }
.mh-alerte--information{ border-left-color: var(--mh-information); }

.mh-alerte-cat {
    font-size: var(--mh-t-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .09em;
    color: var(--mh-texte-doux);
}

.mh-alerte--urgent .mh-alerte-cat    { color: var(--mh-danger); }
.mh-alerte--attention .mh-alerte-cat { color: var(--mh-vigilance); }

.mh-alerte-titre { font-weight: 600; margin-top: .2rem; }
.mh-alerte-detail { font-size: var(--mh-t-sm); color: var(--mh-texte-doux); margin-top: .15rem; }

.mh-tuile--alerte { border-color: var(--mh-danger); }
.mh-tuile--alerte .mh-tuile-valeur { color: var(--mh-danger); }

.mh-code {
    background: var(--mh-chrome);
    color: var(--mh-chrome-texte);
    padding: .875rem 1rem;
    border-radius: var(--mh-r-md);
    font-family: var(--mh-police-mono);
    font-size: .85rem;
    overflow-x: auto;
    white-space: pre;
}


/* ---------------------------------------------------------------------------
   Recherche globale
   ---------------------------------------------------------------------------
   Placée dans la barre de navigation, donc sur fond sombre. Les résultats
   s'affichent sur fond clair : ils appartiennent au contenu, pas au menu.
--------------------------------------------------------------------------- */

/* La recherche est le chemin le plus court vers un véhicule ou un client —
   le diagnostic le disait, et elle était comprimée à 29 px par dix-sept
   destinations. Elle prend maintenant TOUT l'espace que la barre laisse
   libre, entre les raccourcis du quotidien et les outils. */
.mh-recherche-globale {
    position: relative;
    flex: 1 1 12rem;
    min-width: 8rem;
    max-width: 30rem;
    margin-left: auto;
}

.mh-recherche-globale input {
    width: 100%;
    /* 44 px minimum : une cible tactile plus petite se rate au doigt, et cet
       écran s'utilise sur une tablette d'atelier. */
    min-height: 44px;
    padding: .5rem .85rem;
    border-radius: var(--mh-r-md);
    border: 1px solid var(--mh-chrome-bord);
    background: rgba(255, 255, 255, .06);
    color: var(--mh-chrome-texte);
    font-family: inherit;
    font-size: .95rem;
}

.mh-recherche-globale input::placeholder { color: var(--mh-chrome-texte-doux); opacity: 1; }

.mh-recherche-globale input:focus {
    outline: var(--mh-focus-trait);
    outline-offset: 1px;
    background: rgba(255, 255, 255, .12);
}

/* Sous la liste, pour capter le clic extérieur sans bloquer le reste. */
.mh-recherche-voile {
    position: fixed;
    inset: 0;
    z-index: 40;
}

.mh-recherche-resultats {
    position: absolute;
    z-index: 41;
    top: calc(100% + .4rem);
    right: 0;
    /* Le champ peut se resserrer ; ses résultats, non. « AB-123-CD — Renault
       Clio IV » ne se lit pas dans 140 px. Ils s'alignent à droite du champ
       pour ne jamais sortir de l'écran. */
    min-width: min(26rem, calc(100vw - 2rem));
    max-height: 60vh;
    overflow-y: auto;
    background: var(--mh-surface-haute);
    border: 1px solid var(--mh-bord);
    border-radius: var(--mh-r-md);
    box-shadow: var(--mh-ombre-haute);
}

.mh-recherche-ligne {
    display: grid;
    grid-template-columns: 5.5rem 1fr;
    gap: .1rem .75rem;
    width: 100%;
    padding: .6rem .85rem;
    border: 0;
    border-bottom: 1px solid var(--mh-bord);
    background: transparent;
    text-align: left;
    cursor: pointer;
    font-family: inherit;
    color: var(--mh-texte);
}

.mh-recherche-ligne:last-child { border-bottom: 0; }
.mh-recherche-ligne:hover { background: var(--mh-survol); }
.mh-recherche-ligne:focus-visible { background: var(--mh-survol); outline: var(--mh-focus-trait); outline-offset: -2px; }

/* Suggestion active au clavier (↓ ↑ puis Entrée) : la teinte du survol. */
.mh-recherche-ligne--active { background: var(--mh-survol); }
.mh-tableau tr.mh-ligne--active td { background: var(--mh-survol); }

.mh-recherche-type {
    grid-row: span 2;
    align-self: center;
    font-size: var(--mh-t-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--mh-texte-doux);
}

.mh-recherche-titre { font-weight: 600; }

.mh-recherche-detail {
    font-size: var(--mh-t-sm);
    color: var(--mh-texte-doux);
}

.mh-recherche-vide {
    padding: .9rem;
    color: var(--mh-texte-doux);
    font-size: var(--mh-t-sm);
}

@media (max-width: 40rem) {
    /* Sur téléphone, la recherche passe sur sa propre rangée, pleine largeur :
       c'est le geste le plus fréquent, il mérite mieux qu'un reste de place
       entre un logo et trois boutons. */
    .mh-recherche-globale {
        flex: 1 1 100%;
        max-width: none;
        min-width: 0;
        order: 10;
        margin: 0 1rem .6rem;
    }
}


/* ---------------------------------------------------------------------------
   Bandeau de licence
   ---------------------------------------------------------------------------
   Pleine largeur, au-dessus du contenu. La couleur porte l'urgence, mais le
   texte reste explicite : un écran délavé ou un daltonisme ne doivent pas
   effacer l'information.
--------------------------------------------------------------------------- */

.mh-bandeau-licence {
    padding: .55rem 1.25rem;
    font-size: var(--mh-t-sm);
    line-height: 1.4;
    border-bottom: 1px solid var(--mh-bord);
}

.mh-bandeau-licence--information {
    background: var(--mh-information-doux);
    color: var(--mh-information);
}

.mh-bandeau-licence--attention {
    background: var(--mh-vigilance-doux);
    color: var(--mh-vigilance);
}

.mh-bandeau-licence--urgent {
    background: var(--mh-danger-doux);
    color: var(--mh-danger);
    font-weight: 600;
}

/* --- Pièces jointes ------------------------------------------------------
   Le composant s'affiche dans un panneau latéral étroit et sur tablette en
   atelier. Un tableau y déborderait ; chaque document occupe donc une ligne
   qui se replie sous les 30 rem, plutôt que de pousser ses actions hors du
   champ derrière une barre de défilement horizontale. */

.mh-pieces {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .5rem;
}

.mh-piece {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    padding: .75rem 1rem;
    background: var(--mh-surface);
    border: 1px solid var(--mh-bord);
    border-radius: var(--mh-r-md);
}

.mh-piece-info {
    display: flex;
    flex-direction: column;
    gap: .25rem;
    min-width: 0;
    flex: 1 1 14rem;
}

/* Un nom de fichier venu d'un téléphone n'a ni espace ni limite de longueur :
   sans coupure explicite, il élargit la ligne et repousse les boutons. */
.mh-piece-nom { overflow-wrap: anywhere; }

/* --- Pagination ----------------------------------------------------------
   Barre commune à toutes les listes. Le rang est écrit à gauche parce que
   « 51–75 sur 1 240 » répond à une question que « page 3 » laisse ouverte :
   combien reste-t-il ? */

.mh-pagination {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: .75rem;
    margin-top: 1rem;
    padding: .5rem .25rem;
    color: var(--mh-texte-doux);
    font-size: var(--mh-t-sm);
}

.mh-pagination-rang { font-variant-numeric: tabular-nums; }

.mh-pagination-boutons {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .35rem;
}

/* Les quatre flèches portent un seul caractère : leur remplissage horizontal
   de 1,25 rem — dessiné pour « Enregistrer » — les rendait aussi larges qu'un
   bouton de mot. À 320 px la barre débordait de 21 px et la page entière
   se balayait latéralement (mesuré au banc, présent avant ce lot). Elles
   deviennent carrées, et gardent 44 px de côté : la cible tactile ne se
   négocie pas. */
.mh-pagination-boutons .mh-bouton {
    min-width: 44px;
    min-height: 44px;
    padding: 0 .5rem;
}

.mh-pagination-position {
    padding: 0 .5rem;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Un bouton désactivé doit se voir désactivé : sans cela l'utilisateur clique
   sur « suivant » en boucle au bout de la liste, et croit à un blocage. */
.mh-pagination .mh-bouton:disabled {
    opacity: .4;
    cursor: default;
}

/* Liste de suggestions d'adresses (ChampAdresse) : ancrée sous le champ,
   au-dessus du reste, même langage visuel que les tableaux. */
.mh-suggestions {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 30;
    margin: 0;
    padding: 0;
    list-style: none;
    background: var(--mh-surface-haute);
    border: 1px solid var(--mh-bord);
    border-radius: 0 0 var(--mh-r-md) var(--mh-r-md);
    box-shadow: var(--mh-ombre-haute);
    max-height: 16rem;
    overflow-y: auto;
}

.mh-suggestions li {
    padding: .45rem .7rem;
    cursor: pointer;
}

.mh-suggestions li:hover {
    background: var(--mh-survol);
}

/* --- Cases et boutons radio dans un libellé en flex -----------------------
   Sans ceci, la case est un élément flex comme un autre : elle se laisse
   comprimer par le texte voisin, d'autant plus que la description est
   longue. Constaté en recette réelle sur téléphone — les cinq rôles avaient
   leurs ronds à cinq abscisses différentes, chacun décalé de son libellé.
   La case garde désormais sa taille propre ; seul le texte s'adapte. */
.mh-champ input[type="radio"],
.mh-champ input[type="checkbox"],
label input[type="radio"],
label input[type="checkbox"] {
    flex: 0 0 auto;
    /* INDISPENSABLE : la règle générale des formulaires met tous les champs à
       « width: 100% ». Une case héritait donc de 263 px de large et poussait
       son propre libellé hors de l'écran — c'était la cause réelle du
       désalignement constaté en recette, et non un simple problème
       d'espacement. */
    width: auto;
}

/* Corollaire indispensable : si la case ne se comprime plus, c'est le texte
   voisin qui doit occuper le reste ET pouvoir revenir à la ligne.
   « min-width: 0 » seul le faisait collapser à zéro — le texte sortait alors
   d'une boîte de largeur nulle, plus loin qu'avant. Il faut les deux :
   « flex: 1 » pour prendre la place disponible, « min-width: 0 » pour
   descendre sous la largeur du plus long mot. */
.mh-champ input[type="radio"] + span,
.mh-champ input[type="checkbox"] + span,
label input[type="radio"] + span,
label input[type="checkbox"] + span {
    flex: 1 1 auto;
    min-width: 0;
}

/* ---- Retours de formulaire (recette terrain, août 2026) ------------------ */

/* Bannière d'erreur à demeure dans un panneau : entre le corps et le pied,
   donc visible sans défilement, à côté du bouton pressé.
   Le succès obéit à la même règle : une réussite annoncée derrière le calque
   n'est pas une réussite annoncée. */
.mh-panneau-erreur,
.mh-panneau-succes {
    margin: .75rem 1.5rem 0;
    flex-shrink: 0;
}

/* Ce qui suit la réussite : l'état obtenu, le geste d'après. Sur sa propre
   ligne — collé au titre, il se lirait comme une seule phrase interminable. */
.mh-succes-suite {
    display: block;
    margin-top: .25rem;
    font-weight: 400;
}

/* Champ dont la saisie bloque l'enregistrement : le liseré désigne le champ,
   le message sous le champ dit quoi faire. Jamais l'un sans l'autre. */
.mh-champ--invalide input,
.mh-champ--invalide select,
.mh-champ--invalide textarea {
    border-color: var(--mh-danger);
    outline: none;
    box-shadow: 0 0 0 3px var(--mh-danger-doux);
}

.mh-champ-probleme {
    display: block;
    margin-top: .3rem;
    font-size: var(--mh-t-sm);
    color: var(--mh-danger);
}

/* Indice non bloquant : la saisie est inhabituelle mais peut être légitime
   (VIN court d'un véhicule ancien, adresse e-mail interne). On prévient,
   on n'empêche pas. */
.mh-champ-indice {
    display: block;
    margin-top: .3rem;
    font-size: var(--mh-t-sm);
    color: var(--mh-vigilance);
}

/* ---- Tableaux larges sur écran étroit (recette terrain, août 2026) ------- */

/* Le cadre défile horizontalement depuis toujours — mais rien ne le disait :
   à 390 px, la liste des devis se coupait proprement après trois colonnes et
   le bouton « Ouvrir » vivait hors écran, indevinable (3 reproductions par
   l'audit externe). Les ombres de défilement sont l'indice : elles
   n'apparaissent que du côté où du contenu se cache, et disparaissent au
   bout de course. Technique des dégradés attachés (local/scroll) — aucune
   ligne de JavaScript. */
.mh-tableau-cadre {
    background:
        linear-gradient(to right, var(--mh-surface) 30%, transparent) left,
        linear-gradient(to left, var(--mh-surface) 30%, transparent) right,
        radial-gradient(farthest-side at 0 50%, var(--mh-ombre-defilement), transparent) left,
        radial-gradient(farthest-side at 100% 50%, var(--mh-ombre-defilement), transparent) right;
    background-repeat: no-repeat;
    background-size: 3rem 100%, 3rem 100%, .875rem 100%, .875rem 100%;
    background-attachment: local, local, scroll, scroll;
    background-color: var(--mh-surface);
}

/* L'ombre vit sur le cadre : les cellules doivent la laisser transparaître.
   L'en-tête garde son fond — l'indice se lit sur les lignes. */
.mh-tableau tbody tr:hover { background: var(--mh-survol); }

/* La ligne entière ouvre le document : sur téléphone, le bouton « Ouvrir »
   de la dernière colonne est à un écran de distance — la ligne, elle, est
   sous le doigt. Le bouton reste, pour la découvrabilité au premier regard. */
.mh-ligne-cliquable { cursor: pointer; }

/* Colonne d'action COLLÉE à droite — lignes de devis et d'ordre.
   Le remède de la ligne cliquable ne vaut que pour les listes : une ligne de
   document ne s'ouvre pas, et « Retirer » restait la dernière colonne d'un
   tableau à défilement horizontal. À 390 px il fallait deviner que l'action
   existait, puis faire défiler pour l'atteindre — d'où « je n'ai pas trouvé
   comment enlever une ligne » en recette. La colonne reste maintenant à vue,
   quelle que soit la position du défilement. */
.mh-tableau--action-collee th:last-child,
.mh-tableau--action-collee td:last-child {
    position: sticky;
    right: 0;
    /* Opaque par nécessité : le contenu défile DESSOUS. C'est l'exception à la
       règle « les cellules laissent passer l'ombre du cadre ». */
    background: var(--mh-surface);
    box-shadow: -6px 0 6px -6px var(--mh-ombre-defilement);
}

/* Le survol doit suivre jusque dans la colonne collée, sinon la ligne paraît
   se couper en deux. Même teinte, composée sur le fond opaque. */
.mh-tableau--action-collee tbody tr:hover td:last-child {
    background: linear-gradient(var(--mh-survol), var(--mh-survol)),
                var(--mh-surface);
}

/* --- Rapports ------------------------------------------------------------
   L'essentiel d'abord : les totaux de l'année en indicateurs compacts,
   AVANT le tableau. Sur téléphone, c'est souvent la seule chose cherchée. */
.mh-kpis {
    display: grid;
    /* min(…, 100%) : en très grande police, une carte ne déborde jamais. */
    grid-template-columns: repeat(auto-fit, minmax(min(10rem, 100%), 1fr));
    gap: .75rem;
    margin-bottom: 1rem;
}

.mh-kpi {
    background: var(--mh-fond-2);
    border: 1px solid var(--mh-bord);
    border-radius: var(--mh-r-md);
    padding: .6rem .9rem;
}

.mh-kpi span {
    display: block;
    font-size: var(--mh-t-xs);
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--mh-texte-doux);
}

.mh-kpi strong {
    font-family: var(--mh-police-titre);
    font-size: var(--mh-t-lg);
    font-variant-numeric: tabular-nums;
}

/* Tableau qui devient FICHES sous 32rem — le retour de recette : « un
   tableau desktop scrollable » sur téléphone. Chaque ligne devient une
   petite fiche : la première cellule fait titre, les autres s'empilent en
   deux colonnes avec leur libellé (data-libelle). Rien n'est masqué, le
   balayage horizontal disparaît. Au-delà de 32rem, tableau inchangé. */
@media (max-width: 32rem) {
    .mh-tableau--fiches thead { display: none; }

    .mh-tableau--fiches tr {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: .15rem .9rem;
        padding: .65rem .9rem;
        border-bottom: 1px solid var(--mh-bord);
    }

    .mh-tableau--fiches td {
        display: block;
        padding: 0;
        border: none;
        text-align: left;
    }

    .mh-tableau--fiches td:first-child {
        grid-column: 1 / -1;
        font-weight: 650;
    }

    .mh-tableau--fiches td[data-libelle]::before {
        content: attr(data-libelle);
        display: block;
        font-size: .68rem;
        font-weight: 700;
        letter-spacing: .08em;
        text-transform: uppercase;
        color: var(--mh-texte-doux);
    }

    /* Une cellule annoncée pleine largeur (message, total) s'étale. */
    .mh-tableau--fiches td.mh-fiche-large { grid-column: 1 / -1; }

    /* Les pastilles d'état et d'échéance sont en « nowrap » : c'est ce qui
       les empêche de se couper en deux dans une colonne de tableau. Dans une
       FICHE, la colonne fait la moitié d'un téléphone — « 08/09/2026 · dans
       29 j » y débordait de 89 px (mesuré au banc sur Véhicules à 320 px).
       Elles peuvent revenir à la ligne ; c'est la carte qui commande. */
    .mh-tableau--fiches .mh-echeance,
    .mh-tableau--fiches .mh-etat,
    .mh-tableau--fiches .mh-etiquette { white-space: normal; }

    /* Une plaque, elle, ne se coupe JAMAIS : « AB-123 » suivi de « CD » à la
       ligne ne se lit plus comme une immatriculation. */
    .mh-tableau--fiches .mh-plaque { white-space: nowrap; }
}

/* --- Densité mobile (§14 de la recette) ----------------------------------
   « Sur téléphone, Atlas paraît trop gros. » Le remède n'est PAS une police
   plus petite : ce sont les espaces — paddings, marges, hauteurs — qui se
   resserrent sous 32rem. Les cibles tactiles gardent leurs 48px
   (--mh-cible) : on densifie l'information, pas les doigts. */
@media (max-width: 32rem) {
    .mh-entete { margin-bottom: 1rem; gap: .5rem; }
    .mh-entete h1 { font-size: 1.4rem; }

    .mh-outils { margin-bottom: 1rem; gap: .5rem; }

    .mh-section { margin: 1.25rem 0 .75rem; padding-top: .9rem; }

    .mh-tableau th { padding: .6rem .75rem; }
    .mh-tableau td { padding: .6rem .75rem; }

    .mh-panneau-corps { padding: 1rem; }
    .mh-champ { margin-bottom: 1rem; }

    .mh-message { padding: .75rem 1rem; margin-bottom: 1rem; }

    .mh-tuile { padding: 1rem; }
    .mh-tuiles { gap: .75rem; }

    /* L'état vide n'a pas besoin d'un écran entier pour dire « rien ». */
    .mh-vide { padding: 2rem 1rem; }
}

/* Message à contenu riche (titre, liste, boutons) : les enfants s'empilent.
   Sans cela, .mh-message étant un flex en ligne, un avertissement structuré
   se faisait écraser en colonnes illisibles sur téléphone — constaté sur la
   confirmation d'émission de facture à 390 px. */
.mh-message--bloc {
    flex-direction: column;
    align-items: stretch;
}

/* ---- Choisir ou créer (recette terrain, août 2026) ----------------------- */

/* Le champ de ChoixCatalogue vit DANS un formulaire de panneau : il reprend
   l'apparence des champs (contrairement à la recherche globale, sombre dans
   la barre). Les résultats réutilisent la liste déroulante de la recherche
   globale — même geste, même rendu. */
.mh-choix { position: relative; }
.mh-choix > div > .mh-bouton { margin-top: .5rem; }
.mh-choix .mh-recherche-resultats > .mh-bouton { margin: .5rem; }

.mh-choix input {
    width: 100%;
    min-height: var(--mh-cible);
    padding: .625rem .875rem;
    font-size: var(--mh-t-md);
    font-family: inherit;
    color: var(--mh-texte);
    background: var(--mh-surface);
    border: 1px solid var(--mh-bord-fort);
    border-radius: var(--mh-r-md);
}

.mh-choix input:focus {
    outline: none;
    border-color: var(--mh-action);
    box-shadow: var(--mh-focus-anneau);
}

/* Les résultats du choix se posent au-dessus du contenu du panneau. */
.mh-choix .mh-recherche-resultats { z-index: 60; max-height: 40vh; }
.mh-choix .mh-recherche-voile { z-index: 55; }

/* La ligne de création se distingue : c'est une porte, pas un résultat. */
.mh-choix-creer { background: var(--mh-accent-doux); font-weight: 600; color: var(--mh-accent-texte); }
.mh-choix-creer:hover, .mh-choix-creer:focus-visible { background: var(--mh-accent-doux); }

/* Mini-formulaire de création rapide, encadré dans le panneau. */
.mh-mini-formulaire {
    margin-top: .75rem;
    padding: 1rem;
    background: var(--mh-fond-2);
    border: 1px solid var(--mh-bord);
    border-radius: var(--mh-r-md);
}

.mh-mini-actions {
    display: flex;
    gap: .75rem;
    justify-content: flex-end;
    margin-top: .75rem;
}

.mh-bascule { display: flex; gap: .5rem; flex-wrap: wrap; }

/* Bouton-lien : une action discrète qui déplie sans peser. */
/* Bouton-lien : une action discrète, mais une ACTION. Dessiné à 28 px de
   haut, il tombait sous le seuil tactile (mesuré au banc sur « Voir les 6
   autres ») : discret ne veut pas dire hors d'atteinte au doigt. Le trait
   reste léger, la cible fait 44 px. */
.mh-bouton--lien {
    justify-content: flex-start;
    background: none;
    border: 0;
    padding: .55rem 0;
    min-height: 44px;
    color: var(--mh-action);
    cursor: pointer;
    font-family: inherit;
    font-size: .925rem;
    font-weight: 600;
}
.mh-bouton--lien:hover { text-decoration: underline; background: none; border-color: transparent; }
.mh-bouton--lien:focus-visible { outline: var(--mh-focus-trait); outline-offset: 2px; }

/* ---- Repère couleur (catalogue personnalisé) ----------------------------- */

.mh-couleurs { display: flex; gap: .5rem; flex-wrap: wrap; }

.mh-couleur {
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    border: 2px solid transparent;
    cursor: pointer;
    padding: 0;
}

.mh-couleur--aucune {
    background: var(--mh-surface);
    border-color: var(--mh-bord-fort);
    color: var(--mh-texte-doux);
    font-size: var(--mh-t-md);
    line-height: 1;
}

.mh-couleur--choisie {
    outline: 2px solid var(--mh-action);
    outline-offset: 2px;
}

/* La pastille dans une liste ou une proposition. */
.mh-pastille {
    display: inline-block;
    width: .65rem;
    height: .65rem;
    border-radius: 50%;
    margin-right: .4rem;
    vertical-align: baseline;
}


/* ---------------------------------------------------------------------------
   Bascule jour / nuit
   ---------------------------------------------------------------------------
   Le thème suit le système tant que rien n'a été choisi. Le premier clic pose
   un choix explicite, conservé sur ce poste (localStorage) : sur un poste
   d'atelier partagé, chacun retrouve l'écran qu'il a réglé, sans compte ni
   aller-retour serveur. Aucune donnée métier n'est touchée.

   Bouton HTML ordinaire, piloté par délégation depuis atlas.js : il doit
   fonctionner AVANT la connexion et AVANT que le circuit Blazor soit établi.
--------------------------------------------------------------------------- */

.mh-bascule-theme {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .45rem;
    min-width: 44px;
    min-height: 44px;
    padding: 0 .7rem;
    background: transparent;
    border: 1px solid var(--mh-chrome-bord);
    border-radius: var(--mh-r-plein);
    color: var(--mh-chrome-texte-doux);
    font-family: inherit;
    font-size: var(--mh-t-sm);
    cursor: pointer;
    white-space: nowrap;
}

.mh-bascule-theme:hover { color: var(--mh-chrome-texte); border-color: var(--mh-action); }
.mh-bascule-theme:focus-visible { outline: var(--mh-focus-trait); outline-offset: 2px; }

.mh-bascule-theme svg { flex: none; }

/* Le bouton annonce CE QUE LE CLIC FERA — « Mode nuit » quand on est en
   clair — parce que c'est la question que se pose la main qui s'approche.
   Les deux libellés sont dans le DOM ; le CSS n'en montre qu'un, choisi par
   le thème courant. Aucune écriture de texte par script : rien à traduire
   deux fois, rien qui clignote au chargement.

   Le bouton reste caché tant que le script n'a pas confirmé qu'il répondra :
   un bouton mort est pire que pas de bouton. */
.mh-bascule-theme { display: none; }
.mh-theme-pret .mh-bascule-theme { display: inline-flex; }

.mh-bascule-theme .mh-vers-clair,
.mh-bascule-theme .mh-vers-sombre { display: none; align-items: center; gap: .45rem; }

/* En sombre, le clic ramène au jour. */
:root[data-theme="sombre"] .mh-bascule-theme .mh-vers-clair { display: inline-flex; }
:root[data-theme="clair"] .mh-bascule-theme .mh-vers-sombre { display: inline-flex; }

/* Aucun choix posé : c'est le système qui décide de ce que le clic fera. */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme]) .mh-bascule-theme .mh-vers-clair { display: inline-flex; }
}

@media (prefers-color-scheme: light) {
    :root:not([data-theme]) .mh-bascule-theme .mh-vers-sombre { display: inline-flex; }
}

/* Le mot cède la place à l'icône dans la barre — À TOUTES LES LARGEURS.
   Mesuré : avec « Mode jour » et « Déconnexion » écrits, le bloc d'outils
   faisait 490 px et recouvrait quatre destinations à 1 440 px. Le soleil et
   la porte de sortie sont universels ; l'intitulé complet reste porté par
   aria-label ET par title, et le mot de la licence, lui, reste écrit —
   c'est le seul des trois qui ne se devine pas.

   Si la barre retrouve de la place (lot Navigation), rendre les mots est une
   ligne : supprimer ce bloc. */
.mh-bascule-theme .mh-bascule-mot,
.mh-session .mh-session-mot { display: none; }

.mh-bascule-theme { padding: 0; }


/* ---------------------------------------------------------------------------
   Bandeau d'urgence — « qu'est-ce que je dois faire maintenant ? »
   ---------------------------------------------------------------------------
   Vingt-quatre cartes strictement identiques ne hiérarchisent rien : l'œil
   n'a nulle part où se poser et l'utilisateur apprend à tout ignorer. Ce
   bandeau extrait ce qui est URGENT, le nomme, et mène là où l'on agit. Il
   n'existe que s'il y a une urgence : un bandeau permanent redeviendrait du
   décor au bout d'une semaine.
--------------------------------------------------------------------------- */

.mh-urgence {
    display: grid;
    grid-template-columns: minmax(11rem, 15rem) 1fr;
    gap: var(--mh-e-4) var(--mh-e-5);
    margin-bottom: var(--mh-e-5);
    padding: var(--mh-e-4) 1.25rem;
    background: var(--mh-surface);
    border: 1px solid var(--mh-bord);
    border-left: 5px solid var(--mh-danger);
    border-radius: var(--mh-r-lg);
    box-shadow: var(--mh-ombre);
}

@media (max-width: 48rem) {
    .mh-urgence { grid-template-columns: 1fr; gap: var(--mh-e-3); }
}

.mh-urgence-cat {
    font-size: var(--mh-t-xs);
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--mh-danger);
}

.mh-urgence-compte {
    font-family: var(--mh-police-titre);
    font-size: 1.9rem;
    font-weight: 650;
    line-height: 1.1;
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
}

.mh-urgence-suite { color: var(--mh-texte-doux); font-size: var(--mh-t-sm); }

.mh-urgence-liste { display: flex; flex-direction: column; gap: .35rem; }

/* Chaque ligne est un lien vers l'écran où l'on agit. Une urgence sans porte
   de sortie n'est qu'une source d'anxiété. */
.mh-urgence-ligne {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: .2rem .6rem;
    padding: .5rem .6rem;
    border-radius: var(--mh-r-md);
    text-decoration: none;
    color: inherit;
}

.mh-urgence-ligne:hover { background: var(--mh-survol); }
.mh-urgence-ligne:focus-visible { outline: var(--mh-focus-trait); outline-offset: 1px; }

.mh-urgence-ligne strong { font-weight: 600; }
.mh-urgence-ligne span { color: var(--mh-texte-doux); font-size: var(--mh-t-sm); }

.mh-urgence-ligne em {
    flex: none;
    font-style: normal;
    font-size: var(--mh-t-xs);
    font-weight: 700;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--mh-danger);
}

/* Rien d'urgent : le dire clairement vaut mieux qu'un vide qu'on interprète
   comme un écran qui n'a pas fini de charger. */
.mh-calme {
    display: flex;
    align-items: center;
    gap: var(--mh-e-3);
    margin-bottom: var(--mh-e-5);
    padding: .8rem 1.1rem;
    background: var(--mh-succes-doux);
    border: 1px solid var(--mh-bord);
    border-left: 5px solid var(--mh-succes);
    border-radius: var(--mh-r-lg);
    font-size: .975rem;
}

.mh-calme strong { font-weight: 650; }

/* ---------------------------------------------------------------------------
   Groupes d'une liste d'alertes
   ---------------------------------------------------------------------------
   Huit contrôles techniques à la suite se lisent comme un mur. Regroupés sous
   leur catégorie, avec leur nombre, ils redeviennent une information : « huit
   contrôles techniques », qu'on traite ou qu'on remet à plus tard EN BLOC.
--------------------------------------------------------------------------- */

.mh-groupe { margin-bottom: var(--mh-e-5); }

.mh-groupe-titre {
    display: flex;
    align-items: baseline;
    gap: .5rem;
    margin: 0 0 var(--mh-e-3);
    font-family: var(--mh-police-titre);
    font-size: .95rem;
    font-weight: 650;
}

.mh-groupe-compte {
    font-size: var(--mh-t-xs);
    font-weight: 700;
    letter-spacing: .04em;
    padding: .1rem .5rem;
    border-radius: var(--mh-r-plein);
    background: var(--mh-neutre-doux);
    color: var(--mh-neutre);
    font-variant-numeric: tabular-nums;
}

.mh-groupe--urgent .mh-groupe-compte { background: var(--mh-danger-doux); color: var(--mh-danger); }
.mh-groupe--attention .mh-groupe-compte { background: var(--mh-vigilance-doux); color: var(--mh-vigilance); }

/* ---------------------------------------------------------------------------
   Sélecteur segmenté
   ---------------------------------------------------------------------------
   Cinq filtres écrits en cinq boutons, dont l'actif portait le remplissage de
   l'ACTION PRINCIPALE : le catalogue offrait donc deux « boutons pleins »
   côte à côte — « Tout » et « Nouvel article » — qui ne font pas du tout la
   même chose. Un segment est UN objet à plusieurs positions : il ne peut plus
   se confondre avec une action.
--------------------------------------------------------------------------- */

.mh-segment {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 2px;
    padding: 3px;
    background: var(--mh-fond-2);
    border: 1px solid var(--mh-bord);
    border-radius: var(--mh-r-md);
}

.mh-segment button {
    min-height: 42px;
    padding: 0 .85rem;
    background: transparent;
    border: 0;
    border-radius: var(--mh-r-sm);
    color: var(--mh-texte-doux);
    font-family: inherit;
    font-size: var(--mh-t-sm);
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
}

.mh-segment button:hover { color: var(--mh-texte); background: var(--mh-survol); }
.mh-segment button:focus-visible { outline: var(--mh-focus-trait); outline-offset: -2px; }

/* La position choisie prend la surface et l'accent — jamais le remplissage
   plein de l'action principale. */
.mh-segment button[aria-pressed="true"] {
    background: var(--mh-surface);
    color: var(--mh-action);
    box-shadow: var(--mh-ombre);
}

.mh-segment .mh-segment-compte {
    margin-left: .35rem;
    font-variant-numeric: tabular-nums;
    opacity: .8;
}

/* ---------------------------------------------------------------------------
   Menu d'actions d'une ligne
   ---------------------------------------------------------------------------
   Le bouton reste VISIBLE en permanence — il ne dépend ni du survol ni du
   clic droit, tous deux inatteignables au doigt. Ce qu'il replie, ce sont les
   actions SECONDAIRES : à vingt-cinq lignes, cinq boutons par ligne faisaient
   cent trente-quatre cibles pour un écran dont le sujet est la DONNÉE.
--------------------------------------------------------------------------- */

.mh-actions-ligne { display: flex; justify-content: flex-end; }

.mh-menu-bouton {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 0;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--mh-r-md);
    color: var(--mh-texte-doux);
    cursor: pointer;
}

.mh-menu-bouton:hover { background: var(--mh-survol); border-color: var(--mh-bord); color: var(--mh-texte); }
.mh-menu-bouton:focus-visible { outline: var(--mh-focus-trait); outline-offset: 2px; }
.mh-menu-bouton[aria-expanded="true"] { background: var(--mh-action-doux); border-color: var(--mh-action); color: var(--mh-action); }

/* Le voile capte le clic extérieur sans rien bloquer d'autre — même
   mécanique que la recherche globale. */
.mh-menu-voile { position: fixed; inset: 0; z-index: 60; }

.mh-menu {
    position: absolute;
    right: 0;
    z-index: 61;
    min-width: 15rem;
    padding: .3rem;
    background: var(--mh-surface-haute);
    border: 1px solid var(--mh-bord);
    border-radius: var(--mh-r-md);
    box-shadow: var(--mh-ombre-haute);
    text-align: left;
}

.mh-menu button {
    display: block;
    width: 100%;
    min-height: 44px;
    padding: 0 .75rem;
    background: transparent;
    border: 0;
    border-radius: var(--mh-r-sm);
    color: var(--mh-texte);
    font-family: inherit;
    font-size: var(--mh-t-sm);
    font-weight: 550;
    text-align: left;
    cursor: pointer;
}

.mh-menu button:hover { background: var(--mh-survol); }
.mh-menu button:focus-visible { outline: var(--mh-focus-trait); outline-offset: -2px; }

/* La destruction se tient À DISTANCE des gestes courants : séparée par un
   trait, en bas, et de la couleur qui l'annonce. On ne supprime pas par
   inadvertance ce qui ne se récupère pas. */
.mh-menu-separation {
    margin: .3rem .25rem;
    border: 0;
    border-top: 1px solid var(--mh-bord);
}

/* Une RAISON, pas une action : elle explique pourquoi un geste n'est pas
   offert. Elle était portée par un « title » au survol — donc invisible au
   doigt, sur un écran qui s'utilise aussi sur tablette. */
.mh-menu-raison {
    display: block;
    padding: .5rem .75rem;
    color: var(--mh-texte-doux);
    font-size: var(--mh-t-sm);
    line-height: 1.4;
}

.mh-menu button.mh-menu-danger { color: var(--mh-danger); }
.mh-menu button.mh-menu-danger:hover { background: var(--mh-danger-doux); }

/* La cellule d'action porte le menu : c'est elle le repère de position. */
.mh-cellule-actions { position: relative; }

/* FILET POUR LES LISTES COURTES. Sur quelques lignes, le cadre est plus bas
   que le menu et le découpe — quel que soit le sens d'ouverture. Le temps
   qu'un menu soit déplié, le cadre se réserve la hauteur nécessaire ; il la
   rend en se refermant.

   La valeur est MESURÉE, pas estimée. Sur l'écran Équipe — trois personnes,
   menu de cinq entrées — le cadre naturel fait 336 px et la troisième ligne
   ouvre son menu de 442 à 684 px : il faut donc 485 px de cadre. 32 rem en
   font 512. Au-dessus de cinq lignes le cadre dépasse déjà cette hauteur et
   la règle ne s'applique plus : elle ne coûte rien aux longues listes. */
.mh-tableau-cadre:has(.mh-menu) { min-height: 32rem; }

/* En fiches (téléphone), le menu s'ancre au bord de la carte et non à une
   cellule de tableau qui n'existe plus visuellement. */
@media (max-width: 32rem) {
    .mh-menu { right: .5rem; min-width: 13rem; }
}


/* Le menu déplié sur les dernières lignes s'ouvre vers le haut : le cadre du
   tableau défile (overflow-x: auto), donc découpe aussi le débordement
   vertical. Voir VersLeHaut dans CataloguePage. */
.mh-menu--haut { bottom: calc(100% - .5rem); }

/* Un intitulé destiné aux seuls lecteurs d'écran. La colonne d'actions n'a
   pas de titre visible — mais une colonne sans nom n'est pas annoncée. */
.mh-visuellement-cache {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* Un article désactivé reste lisible — l'historique ne bouge pas — mais ne
   doit pas se confondre avec ce qui se propose encore. */
.mh-ligne-inactive .mh-principal,
.mh-ligne-inactive td { color: var(--mh-texte-doux); }

/* En fiches, la ligne d'action tient au bord droit de la carte, sous les
   valeurs — c'est le pied de la fiche, pas une colonne. */
@media (max-width: 32rem) {
    .mh-tableau--fiches .mh-cellule-actions { margin-top: .25rem; }
    .mh-tableau--fiches .mh-actions-ligne { justify-content: flex-end; }
}


/* ---------------------------------------------------------------------------
   Outils de la barre — licence, apparence, session
   ---------------------------------------------------------------------------
   Ce ne sont pas des destinations : ce sont des réglages. Rassemblés en un
   seul bloc, ANCRÉ à droite de la barre.

   Pourquoi l'ancrage. Mesuré au banc : la barre porte ~2 130 px de contenu
   pour 1 440 px disponibles, et défile horizontalement. Posés en bout de file,
   ces trois réglages étaient hors d'atteinte sans balayage à l'aveugle — dont
   la DÉCONNEXION, sur un poste d'atelier partagé. Le collage les garde à vue
   quelle que soit la position du défilement, même technique que la colonne
   d'action des tableaux larges.
--------------------------------------------------------------------------- */

.mh-nav-outils {
    display: flex;
    align-items: center;
    gap: .4rem;
    margin-left: auto;
    padding: 0 1.5rem 0 .25rem;
    position: sticky;
    right: 0;
    z-index: 2;
    background: var(--mh-chrome);
}

/* La barre tient désormais dans une grille : aucun voile ne masque le bord
   de la recherche, même lorsque le nom de session occupe toute sa place. */

/* ---------------------------------------------------------------------------
   Jeton de licence
   ---------------------------------------------------------------------------
   La forme discrète de l'information de licence : un point, un mot, un lien.
   Elle remplace une bande pleine largeur de 38 px (58 à 77 px sur téléphone)
   qui coiffait CHAQUE écran pour annoncer qu'il n'y avait rien à faire.
--------------------------------------------------------------------------- */

.mh-jeton-licence {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    min-height: 44px;
    padding: 0 .7rem;
    border: 1px solid var(--mh-chrome-bord);
    border-radius: var(--mh-r-plein);
    color: var(--mh-chrome-texte-doux);
    font-size: var(--mh-t-sm);
    text-decoration: none;
    white-space: nowrap;
}

.mh-jeton-licence:hover { color: var(--mh-chrome-texte); border-color: var(--mh-chrome-texte-doux); }
.mh-jeton-licence:focus-visible { outline: var(--mh-focus-trait); outline-offset: 2px; }

/* La clé plutôt qu'un point : sur écran étroit il ne reste qu'elle, et un
   point nu ne dit rien. Le mot l'accompagne dès qu'il y a la place, et
   l'intitulé accessible le porte en toutes circonstances. */
.mh-jeton-licence svg { flex: none; }

/* ---------------------------------------------------------------------------
   Barre étroite : une seule rangée d'outils
   ---------------------------------------------------------------------------
   Mesuré au banc AVANT ce lot : 183 px de barre à 390 et 320 px — trois
   rangées empilées (marque + menu, puis session, puis recherche), plus 58 à
   77 px de bandeau de licence. Soit ~240 px d'ossature avant le titre de la
   page. Les mots cèdent, les cibles restent à 44 px.
--------------------------------------------------------------------------- */

/* Le seuil vient du banc : c'est à 72rem que le bloc d'outils, la recherche
   et le bouton de carte cessent de tenir sur une rangée. */
@media (max-width: 72rem) {
    .mh-nav-outils { gap: .35rem; }
    .mh-bascule-theme { padding: 0 .6rem; }
    .mh-jeton-licence .mh-jeton-mot,
    .mh-session .mh-session-nom { display: none; }

    .mh-jeton-licence { padding: 0 .8rem; }
}

/* Sous 24rem, la marque garde son écrou et perd son mot : à 320 px, trois
   cibles de 44 px, un menu et un logo, c'est exactement ce qui tient. À 390,
   « Atlas » reste écrit. */
@media (max-width: 24rem) {
    .mh-marque-texte { display: none; }
}


/* ---------------------------------------------------------------------------
   Panneau latéral : le verrou de défilement arrière, MESURÉ PUIS RETIRÉ
   ---------------------------------------------------------------------------
   Symptôme réel : la molette fait défiler la liste DERRIÈRE le panneau ouvert.
   On croit faire défiler le formulaire, et c'est la page qui bouge.

   Remède tenté le 10 août : « body:has(.mh-panneau) { overflow: hidden } ».
   Purement déclaratif, aucun JavaScript à défaire. Mesuré au banc — et REJETÉ.

   Pourquoi. L'élément qui défile ici est la racine ; l'« overflow » du corps
   s'y propage. Le poser à « hidden » rend la page non défilable, donc ramène
   la position à ZÉRO : ouvrir un article en bas d'une liste de vingt-cinq
   lignes renvoyait la liste en haut, et la refermer la laissait là. Mesuré :
   400 px → 0. Le remède coûtait plus cher que le symptôme.

   « overflow: clip » a le même effet, et figer le contenu en « position:
   fixed » perd également le point de lecture. La voie propre est le top layer
   du navigateur — un vrai <dialog> ouvert par showModal(), qui verrouille le
   fond SANS toucher à sa position. C'est une reprise des quinze panneaux
   d'Atlas : elle appartient au lot des formulaires, pas à celui du chrome.

   D'ici là, le symptôme demeure et il est documenté plutôt que masqué.
--------------------------------------------------------------------------- */


/* Un nom long ne doit pas repousser la déconnexion hors de l'écran : il se
   tronque, le titre complet reste au survol et l'intitulé accessible du
   bouton le porte en entier. */
.mh-session-nom {
    /* 10rem débordaient de 10 px à 1280 avec un nom long et Licence · 365 j.
       La réserve garde également la place des échéances à plusieurs années. */
    max-width: 8rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}


/* ===========================================================================
   CARTE DES DESTINATIONS
   ---------------------------------------------------------------------------
   Voir CarteNavigation.razor pour le pourquoi. Ici : comment elle se pose.

   Elle vit dans l'en-tête collant, en position absolue sous la barre — donc
   toujours calée sur la hauteur RÉELLE de celle-ci, qui gagne une rangée sur
   téléphone. Une hauteur écrite en dur se serait décollée au premier
   changement de largeur.
   =========================================================================== */

.mh-carte-bouton {
    display: inline-flex;
    align-items: center;
    gap: .45rem;
    flex: none;
    min-height: 44px;
    padding: 0 .85rem;
    background: transparent;
    border: 1px solid var(--mh-chrome-bord);
    border-radius: var(--mh-r-md);
    color: var(--mh-chrome-texte);
    font-family: inherit;
    font-size: .95rem;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
}

.mh-carte-bouton:hover { border-color: var(--mh-action); }
.mh-carte-bouton:focus-visible { outline: var(--mh-focus-trait); outline-offset: 2px; }

/* Ouverte, la porte se voit ouverte. */
.mh-carte-bouton[aria-expanded="true"] {
    background: var(--mh-action-doux);
    border-color: var(--mh-action);
}

.mh-carte-voile {
    position: fixed;
    inset: 0;
    z-index: 29;
    background: var(--mh-voile);
}

.mh-carte {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 31;
    background: var(--mh-surface-haute);
    border-bottom: 1px solid var(--mh-bord);
    box-shadow: var(--mh-ombre-haute);
    /* Sur un petit écran, la carte défile plutôt que de dépasser du bas :
       « Licence », dernière de la dernière colonne, doit rester atteignable. */
    max-height: 78vh;
    overflow-y: auto;
    overscroll-behavior: contain;
}

.mh-carte-corps {
    display: grid;
    /* Quatre colonnes au bureau, deux sur tablette, une sur téléphone. Les
       groupes et leur ordre ne changent jamais : seule la grille change. */
    grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
    gap: var(--mh-e-5) var(--mh-e-6);
    max-width: 80rem;
    margin: 0 auto;
    padding: var(--mh-e-5) 1.5rem var(--mh-e-6);
}

.mh-carte-titre {
    margin: 0;
    font-family: var(--mh-police-titre);
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--mh-texte);
}

/* Une phrase par groupe : elle dit à quoi sert la famille, pas ce que
   contient chaque écran. Sans elle, quatre intitulés abstraits ne rangent
   rien — « Suivi » ne veut dire quelque chose qu'une fois qu'on sait que
   c'est ce qu'on RELIT. */
.mh-carte-aide {
    margin: .35rem 0 .75rem;
    color: var(--mh-texte-doux);
    font-size: var(--mh-t-sm);
    line-height: 1.4;
}
@media (min-width: 40rem) {
    .mh-carte-aide { min-height: 2.8em; }
}

.mh-carte-liens { display: flex; flex-direction: column; gap: 2px; }
.mh-carte-identite { display: inline-flex; align-items: center; gap: .65rem; min-width: 0; }
.mh-carte-icone { color: var(--mh-texte-tenu); }
.mh-carte-libelle { white-space: normal; }
.mh-carte-lien.active .mh-carte-icone { color: var(--mh-action); }

.mh-carte-lien {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--mh-e-3);
    min-height: 46px;
    padding: 0 .7rem;
    border-radius: var(--mh-r-md);
    border-left: 3px solid transparent;
    color: var(--mh-texte);
    font-weight: 550;
    text-decoration: none;
}

.mh-carte-lien:hover { background: var(--mh-survol); }
.mh-carte-lien:focus-visible { outline: var(--mh-focus-trait); outline-offset: -2px; }

/* Où l'on est déjà. Le liseré porte l'accent, le fond reste sobre : la carte
   compte dix-sept entrées, un aplat coloré y ferait tache. */
.mh-carte-lien.active {
    border-left-color: var(--mh-action);
    background: var(--mh-action-doux);
    font-weight: 700;
}

.mh-carte-touche {
    flex: none;
    padding: .1rem .4rem;
    border: 1px solid var(--mh-bord);
    border-bottom-width: 2px;
    border-radius: var(--mh-r-sm);
    background: var(--mh-fond-2);
    color: var(--mh-texte-doux);
    font-family: var(--mh-police-mono);
    font-size: .72rem;
    white-space: nowrap;
}

@media (max-width: 40rem) {
    .mh-carte-corps { padding: var(--mh-e-4) 1rem var(--mh-e-5); gap: var(--mh-e-4); }
    .mh-carte-aide { margin-bottom: .5rem; }
    /* Le mot cède l'espace à l'icône ; l'intitulé accessible le porte. */
    .mh-carte-bouton { padding: 0 .7rem; }
    .mh-carte-bouton .mh-carte-mot { display: none; }
    /* Le raccourci clavier ne sert à rien sur un téléphone. */
    .mh-carte-touche { display: none; }
}


/* ---------------------------------------------------------------------------
   Où l'on EST, puis ce qu'on peut FAIRE
   ---------------------------------------------------------------------------
   Un état n'est pas une action. L'ordre de réparation présentait les deux dans
   le même objet — quatre boutons de même poids, dont l'actuel portait la
   couleur de l'action principale — et trois d'entre eux menaient à un refus
   certain. Les deux notions sont désormais séparées à l'œil : une pastille
   pour l'état, des boutons pour ce qui suit, sous deux intitulés distincts.
--------------------------------------------------------------------------- */

.mh-etape {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--mh-e-4) var(--mh-e-6);
    padding: var(--mh-e-3) var(--mh-e-4);
    background: var(--mh-fond-2);
    border: 1px solid var(--mh-bord);
    border-radius: var(--mh-r-md);
}

/* Le trait vertical sépare l'état de sa suite : sans lui, les deux blocs se
   lisent comme une seule rangée de choses cliquables. */
.mh-etape-suite {
    flex: 1 1 16rem;
    padding-left: var(--mh-e-4);
    border-left: 2px solid var(--mh-bord);
}

@media (max-width: 40rem) {
    .mh-etape-suite {
        flex-basis: 100%;
        padding: var(--mh-e-3) 0 0;
        border-left: 0;
        border-top: 2px solid var(--mh-bord);
    }
}

.mh-etape-libelle {
    display: block;
    margin-bottom: .35rem;
    font-size: var(--mh-t-xs);
    font-weight: 700;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: var(--mh-texte-doux);
}

/* L'état, ici, se lit de loin : c'est la réponse à « où en est cette
   voiture ? », posée vingt fois par jour. */
.mh-etape .mh-etat { font-size: var(--mh-t-md); padding: .35rem .9rem; }

.mh-etape-mot { margin: 0; color: var(--mh-texte-doux); font-size: var(--mh-t-sm); line-height: 1.45; }

/* Les identifiants de documents — DEV, OR, FAC — sont des RÉFÉRENCES qu'on
   dicte au téléphone et qu'on compare à un papier. Le chiffre tabulaire du
   monospace est fait pour ça, et c'est déjà le langage des plaques.

   La classe est POSÉE, jamais déduite du fait qu'on est dans un panneau :
   « Nouvel article » ou « Modifier le client » sont des titres, pas des
   références, et le monospace les rendrait illisibles. */
.mh-reference {
    font-family: var(--mh-police-mono);
    font-size: 1.15rem;
    letter-spacing: .01em;
}


/* Seconde rangée d'un panneau : les outils, sous les gestes qui engagent.
   Séparée par un trait fin, elle dit « voici les copies » sans les mettre au
   même rang que ce qui change l'état d'un document comptable. */
.mh-outils-second {
    margin-top: .6rem;
    padding-top: .6rem;
    border-top: 1px solid var(--mh-bord);
    align-items: center;
}

/* Ce qui engage la comptabilité se tient à distance des copies. */
.mh-outils-separation {
    flex: none;
    width: 1px;
    height: 1.6rem;
    margin: 0 .35rem;
    background: var(--mh-bord-fort);
}


/* ---------------------------------------------------------------------------
   Panneau en dialogue natif
   ---------------------------------------------------------------------------
   Le navigateur pose un <dialog> modal dans son TOP LAYER : hors de tout
   découpage, focus piégé, page derrière inerte, focus rendu à la fermeture.
   Ce qui reste à écrire ici n'est que la remise à zéro de ses valeurs par
   défaut — marge automatique, bordure, largeur et hauteur maximales — et le
   fond, qui remplace le voile fait main.
--------------------------------------------------------------------------- */

dialog.mh-panneau {
    /* Le dialogue est positionné par le navigateur : on lui rend les
       coordonnées du panneau d'Atlas. */
    margin: 0 0 0 auto;
    max-width: none;
    max-height: none;
    padding: 0;
    border: 0;
    border-left: 1px solid var(--mh-bord);
    color: var(--mh-texte);
    overflow: visible;

    /* INDISPENSABLE, et mesuré. La feuille du navigateur donne au dialogue une
       hauteur « fit-content » qui l'emporte sur l'étirement de « top: 0 ;
       bottom: 0 » : la fiche véhicule s'ouvrait sur 3 219 px de haut dans une
       fenêtre de 900, et son pied — « Annuler », « Enregistrer » — se trouvait
       hors écran, inatteignable. La hauteur est donc posée explicitement.
       « dvh » plutôt que « vh » : sur un téléphone, la barre d'adresse du
       navigateur mange une partie de « vh » et le pied repasse sous le pouce. */
    height: 100vh;
    height: 100dvh;
}

dialog.mh-panneau::backdrop {
    background: var(--mh-voile);
}

/* Le panneau retient un clic hors de lui quand une saisie est en cours
   (atlas.js) : un léger recul dit que le geste a été vu, pas ignoré. */
.mh-panneau--retenu { animation: mh-retenu .32s ease; }
@keyframes mh-retenu {
    0%, 100% { transform: translateX(0); }
    30% { transform: translateX(-.4rem); }
    65% { transform: translateX(.25rem); }
}

/* Sans cela, le corps de la page continue de défiler sous un dialogue modal
   dans certains navigateurs. La règle ne s'applique QUE tant qu'un dialogue
   est ouvert — et, contrairement au verrou tenté le 10 août, elle ne touche
   pas l'élément qui défile : la position de la liste est conservée. */
html:has(dialog.mh-panneau[open]) { overflow: hidden; }


/* ---------------------------------------------------------------------------
   Note repliable — ce qui est vrai, utile, et rare
   ---------------------------------------------------------------------------
   Le diagnostic a mesuré 2 959 mots d'aide dans Atlas. Le réflexe serait de
   couper ; ce serait perdre des règles que l'interface ne peut PAS montrer —
   ce qu'un rapport compte, ce qu'un export ne contient jamais, ce qu'une
   restauration écrase.

   Ces textes-là ne disparaissent pas : ils cessent d'être lus À CHAQUE
   OUVERTURE. Un <details> natif — pas une infobulle, pas un survol : une
   information importante ne dépend jamais d'un survol, et un lecteur d'écran
   la trouve comme n'importe quel contenu.

   Ce qui NE se replie jamais : un avertissement avant un geste irréversible,
   un prérequis, ce qui change la décision au moment où on la prend.
--------------------------------------------------------------------------- */

.mh-note {
    margin: 0 0 var(--mh-e-4);
    border: 1px solid var(--mh-bord);
    border-radius: var(--mh-r-md);
    background: var(--mh-fond-2);
    font-size: var(--mh-t-sm);
}

.mh-note > summary {
    display: flex;
    align-items: center;
    gap: .5rem;
    min-height: 44px;
    padding: 0 .9rem;
    color: var(--mh-texte-doux);
    font-weight: 600;
    cursor: pointer;
    list-style: none;
}

.mh-note > summary::-webkit-details-marker { display: none; }

/* Le chevron dit qu'il y a quelque chose dessous, et de quel côté. */
.mh-note > summary::before {
    content: "";
    flex: none;
    width: .45rem;
    height: .45rem;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: rotate(-45deg);
    transition: transform .15s;
}

.mh-note[open] > summary::before { transform: rotate(45deg); }
.mh-note > summary:hover { color: var(--mh-texte); }
.mh-note > summary:focus-visible { outline: var(--mh-focus-trait); outline-offset: -2px; }

.mh-note-corps {
    padding: 0 .9rem .8rem;
    color: var(--mh-texte-doux);
    line-height: 1.5;
}

.mh-note-corps p { margin: 0 0 .5rem; }
.mh-note-corps p:last-child { margin-bottom: 0; }


/* Le champ de collage d'une clé de licence ne s'affiche qu'avec la note qui
   l'annonce : ensemble ils forment le chemin exceptionnel, et le déplier à
   moitié n'aurait aucun sens. Pas une ligne de JavaScript — c'est le
   <details> natif qui commande, par le sélecteur de voisinage. */
.mh-champ--replie,
.mh-note:not([open]) ~ .mh-champ--replie,
.mh-note:not([open]) ~ button { display: none; }

.mh-note[open] ~ .mh-champ--replie { display: block; }
.mh-note[open] ~ button { display: inline-flex; }

/* --- Poste de départ : quatre gestes, puis le travail réel ---------------
   Le bloc ardoise est la signature de l'accueil. Les chiffres ne jouent
   aucune scène d'entrée : une valeur métier se lit tout de suite. */
.mh-accueil-entete { align-items: center; margin-bottom: 1.35rem; }
.mh-accueil-identite, .mh-accueil-date { display: flex; align-items: center; gap: .7rem; }
.mh-accueil-symbole { color: var(--mh-action); display: flex; }
.mh-accueil-date { color: var(--mh-texte-doux); font-size: .95rem; }
.mh-accueil-date span::first-letter { text-transform: uppercase; }

.mh-depart-accueil {
    display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
    padding: .65rem; gap: .5rem; margin-bottom: 1.5rem;
    background: var(--mh-chrome); border: 1px solid var(--mh-chrome-bord);
    border-radius: 19px; box-shadow: var(--mh-ombre);
}
.mh-depart-accueil:empty { display: none; }
.mh-action-accueil {
    display: flex; align-items: center; gap: 1rem; padding: 1.35rem 1.1rem;
    min-width: 0; min-height: 112px; position: relative;
    border: 1px solid transparent; border-radius: 12px;
    color: var(--mh-chrome-texte); background: var(--mh-chrome-2); text-decoration: none;
    transition: background-color var(--mh-duree-geste), border-color var(--mh-duree-geste),
                transform var(--mh-duree-geste) var(--mh-courbe-geste);
}
.mh-action-accueil--devis { background: var(--mh-action); color: var(--mh-action-encre); }
.mh-action-accueil-icone {
    display: grid; place-items: center; width: 46px; height: 50px; flex: 0 0 46px;
    color: var(--mh-chrome-action); border: 1px solid var(--mh-chrome-bord); border-radius: 10px;
    transition: transform 220ms var(--mh-courbe-geste);
}
.mh-action-accueil--devis .mh-action-accueil-icone { color: inherit; border-color: currentColor; }
.mh-action-accueil-texte { min-width: 0; display: flex; flex-direction: column; gap: .3rem; }
.mh-action-accueil-texte strong { font-family: var(--mh-police-titre); font-size: 1.35rem; font-weight: 600; line-height: 1.1; }
.mh-action-accueil-texte small { font-size: .82rem; color: var(--mh-chrome-texte-doux); line-height: 1.35; }
.mh-action-accueil--devis small { color: inherit; }
.mh-action-accueil:hover { background: var(--mh-chrome-selection); border-color: var(--mh-chrome-action); }
.mh-action-accueil--devis:hover { background: var(--mh-action-survol); }
.mh-action-accueil:focus-visible { outline: 2px solid var(--mh-chrome-action); outline-offset: 3px; }
.mh-action-accueil:active { transform: scale(.985); }
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
    .mh-action-accueil:hover .mh-action-accueil-icone { transform: rotate(-6deg); }
}

.mh-priorites-accueil { display: block; padding: 1rem 1.25rem .75rem; border-left-width: 3px; }
.mh-priorites-entete { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.mh-priorites-entete h2 { font-size: 1.25rem; font-weight: 600; margin: 0; }
.mh-priorites-icone { color: var(--mh-danger); }
.mh-priorites-entete .mh-urgence-compte {
    font-family: var(--mh-police); font-size: .85rem; padding: .2rem .5rem;
    background: var(--mh-danger-doux); color: var(--mh-danger); border-radius: var(--mh-r-plein);
}
.mh-priorites-liste { list-style: none; padding: .5rem 0 0; margin: 0; }
.mh-priorites-liste .mh-urgence-ligne { display: grid; grid-template-columns: 9rem 1fr auto; align-items: center; padding: .6rem 0; gap: .75rem; }
.mh-priorites-liste .mh-priorite-categorie { color: var(--mh-danger); font-size: .85rem; font-weight: 600; }
.mh-priorite-texte { display: flex; align-items: baseline; flex-wrap: wrap; gap: .15rem .75rem; }
.mh-priorite-texte strong { color: var(--mh-texte); }
.mh-priorite-ouvrir { color: var(--mh-texte-doux); }
.mh-calme-accueil { border-left-width: 3px; }
.mh-calme-icone { color: var(--mh-succes); }
.mh-calme-accueil p { margin: 0; color: var(--mh-texte-doux); font-size: .9rem; }

.mh-activite-accueil { margin-bottom: 2rem; display: grid; grid-template-columns: minmax(0, 1fr) minmax(16rem, .52fr); gap: 1rem; }
.mh-activite-accueil:not(:has(.mh-activite-financiere)) { grid-template-columns: 1fr; }
.mh-activite-operationnelle { grid-template-columns: repeat(3, minmax(0, 1fr)); margin: 0; gap: .75rem; }
.mh-activite-operationnelle:empty { display: none; }
.mh-activite-accueil:has(.mh-activite-operationnelle:empty) { grid-template-columns: 1fr; }
.mh-activite-operationnelle .mh-tuile { padding: 1.1rem 1.15rem 1.25rem; }
.mh-tuile-entete { display: flex; align-items: center; justify-content: space-between; gap: .5rem; }
.mh-tuile-entete .mh-icone { color: var(--mh-texte-tenu); }
.mh-activite-operationnelle .mh-tuile-valeur { margin-top: .6rem; font-size: 2.75rem; }
.mh-activite-operationnelle .mh-tuile--lien .mh-tuile-titre::after { display: none; }
.mh-activite-operationnelle .mh-tuile--atelier { border-top: 3px solid var(--mh-action); }
.mh-activite-operationnelle .mh-tuile--atelier .mh-icone { color: var(--mh-action); }
.mh-activite-operationnelle .mh-tuile--devis { border-top: 3px solid var(--mh-bord-fort); }
.mh-activite-operationnelle .mh-tuile--encaissement { border-top: 3px solid var(--mh-bord-fort); }
.mh-activite-operationnelle .mh-tuile--alerte { border-top-color: var(--mh-danger); }
.mh-activite-financiere {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-content: center;
    gap: .75rem 0; border: 1px solid var(--mh-bord); border-radius: var(--mh-r-lg); background: var(--mh-fond-2);
    padding: 1rem 0;
}
.mh-activite-financiere .mh-tuile { border: 0; border-radius: 0; background: transparent; box-shadow: none; padding: 0 1rem; }
.mh-activite-financiere .mh-tuile--mois { border-left: 1px solid var(--mh-bord-fort); }
.mh-activite-financiere .mh-tuile-valeur { font-size: 2rem; }
.mh-activite-marge {
    grid-column: 1 / -1; display: flex; align-items: baseline; gap: .3rem .5rem; flex-wrap: wrap;
    border-top: 1px solid var(--mh-bord); padding: .6rem 1rem 0; font-size: .85rem; color: var(--mh-texte-doux);
}
.mh-activite-marge strong { color: var(--mh-texte); font-variant-numeric: tabular-nums; }
.mh-activite-marge small { flex-basis: 100%; }

.mh-travail-entete { align-items: center; }
.mh-travail-entete h2 { margin: 0; font-size: 1.65rem; font-weight: 600; display: flex; align-items: center; gap: .65rem; }
.mh-travail-entete .mh-compte { font-family: var(--mh-police); padding: .1rem .55rem; border-radius: var(--mh-r-plein); background: var(--mh-fond-2); }
.mh-travail-groupe { border: 1px solid var(--mh-bord); border-radius: var(--mh-r-lg); background: var(--mh-surface); overflow: hidden; }
.mh-travail-groupe .mh-groupe-titre { padding: .9rem 1.1rem; margin: 0; background: var(--mh-fond-2); font-size: 1.05rem; }
.mh-travail-liste { display: flex; flex-direction: column; list-style: none; padding: 0; margin: 0; gap: 0; }
.mh-travail-liste li + li { border-top: 1px solid var(--mh-bord); }
.mh-travail-ligne { display: grid; grid-template-columns: 7.5rem 1fr auto; align-items: center; gap: 1rem; border: 0; border-radius: 0; padding: .9rem 1.1rem; }
.mh-travail-ligne .mh-alerte-cat { text-transform: none; letter-spacing: 0; font-size: .82rem; }
.mh-travail-ligne-texte { display: flex; flex-direction: column; min-width: 0; }
.mh-travail-ligne .mh-alerte-titre { margin: 0; font-weight: 600; }
.mh-travail-ouvrir { color: var(--mh-texte-tenu); }
.mh-travail-groupe > .mh-bouton { margin: .5rem 1rem; }
.mh-travail-vide-icone { display: grid; place-items: center; width: 56px; height: 56px; margin: 0 auto 1rem; border-radius: 50%; color: var(--mh-succes); background: var(--mh-succes-doux); }
.mh-travail-actualiser[aria-busy="true"] .mh-icone { animation: mh-actualisation 900ms linear infinite; }
@keyframes mh-actualisation { to { transform: rotate(360deg); } }

@media (max-width: 68rem) {
    .mh-depart-accueil { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .mh-action-accueil { min-height: 90px; padding: 1rem; }
    .mh-activite-accueil { grid-template-columns: 1fr; }
    .mh-activite-financiere { grid-template-columns: 1fr 1fr 1fr; align-items: center; }
    .mh-activite-marge { grid-column: auto; border-top: 0; border-left: 1px solid var(--mh-bord); padding-top: 0; }
}
@media (max-width: 40rem) {
    .mh-accueil-entete { gap: .45rem; }
    .mh-accueil-date { font-size: .875rem; }
    .mh-accueil-symbole { display: none; }
    .mh-depart-accueil { padding: .4rem; gap: .4rem; border-radius: 15px; }
    .mh-action-accueil { flex-direction: column; align-items: flex-start; gap: .65rem; padding: 1rem .8rem; }
    .mh-action-accueil-icone { width: 36px; height: 36px; flex-basis: 36px; border: 0; border-radius: 0; place-items: start; }
    .mh-action-accueil-texte strong { font-size: 1.15rem; }
    .mh-action-accueil-texte small { font-size: .8rem; }
    .mh-priorites-accueil { padding: .8rem 1rem; }
    .mh-priorites-liste .mh-urgence-ligne { grid-template-columns: 1fr auto; gap: .2rem; }
    .mh-priorite-categorie { grid-column: 1 / -1; }
    .mh-activite-operationnelle { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .mh-activite-operationnelle .mh-tuile { padding: .85rem; }
    .mh-activite-operationnelle .mh-tuile:last-child:nth-child(odd) { grid-column: 1 / -1; }
    .mh-activite-operationnelle .mh-tuile-valeur { font-size: 2.25rem; }
    .mh-activite-financiere { grid-template-columns: 1fr 1fr; }
    .mh-activite-marge { grid-column: 1 / -1; border-left: 0; border-top: 1px solid var(--mh-bord); padding-top: .6rem; }
    .mh-travail-ligne { grid-template-columns: 1fr auto; gap: .2rem .5rem; padding: .8rem 1rem; }
    .mh-travail-ligne .mh-alerte-cat { grid-column: 1 / -1; }
}

/* ------------------------------------------------------ Accessibilité */

/* Texte présent pour les lecteurs d'écran, invisible à l'écran : un en-tête de
   colonne « Actions », un titre de page de connexion. Le retirer du flux
   (display: none) le retirerait aussi de l'accessibilité — d'où le rognage. */
.mh-invisible {
    position: absolute; width: 1px; height: 1px;
    padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* AU DOIGT, LES CIBLES FONT 44 PX. Mesuré le 05/09/2026 en 390 px : les filtres
   segmentés faisaient 42 px, les ordres du planning 27 px, les pastilles de
   couleur 32 px. La densité du bureau ne change pas. */
@media (pointer: coarse) {
    .mh-segment button { min-height: 44px; }
    .mh-planning-ordre { min-height: 44px; display: flex; align-items: center; }
    .mh-couleur { width: 44px; height: 44px; }
    .mh-fermer { min-width: 44px; }
    .mh-jeton-licence { min-width: 44px; min-height: 44px; }
}

/* Règlements : une saisie annulée reste lisible, barrée, avec son motif ;
   la contre-passation qui l'annule se distingue sans couleur seule (texte
   « Saisie annulée » / « Annulation de saisie »). KNOWN_ISSUES §8.2. */
.mh-reglements td { vertical-align: top; }
.mh-reglements td.mh-secondaire { min-width: 14rem; }
.mh-reglement--annule td { color: var(--mh-texte-doux); }
.mh-reglement--annule s { text-decoration-thickness: 2px; }
.mh-reglement--contre-passation td { background: var(--mh-fond-2); }
.mh-reglement-etat { margin-top: .25rem; color: var(--mh-texte); }
@media (max-width: 32rem) {
    .mh-reglements td.mh-secondaire { min-width: 0; }
}
