/* =============================================================================
   FlotteCar — système de design
   =============================================================================
   IDENTITÉ : un instrument de gestion, calme et lisible.

   Le parti pris est la sobriété. Un gestionnaire de flotte ouvre cet outil
   vingt fois par jour ; il doit y trouver ses chiffres sans être agressé.
   La couleur ne sert donc qu'à dire quelque chose — jamais à décorer.

   Deux couleurs de marque seulement, celles de REFONTE_V3.md :
     Slate 900  #0f172a   structure, texte, barre latérale
     Teal 600   #0d9488   accent unique : actif, primaire, liens

   Trois teintes sémantiques, volontairement DÉSATURÉES. Un rouge vif et un
   vert vif côte à côte sur la même page donnent une impression de désordre —
   c'est exactement ce qu'il fallait corriger. Elles se lisent ici comme des
   nuances, pas comme des alarmes.

   L'orange ne sert plus qu'à UNE chose : le renouvellement d'abonnement.
   C'est la seule action de nature différente de toutes les autres.

   ICÔNES : réservées aux endroits où elles portent une information que le
   texte ne porte pas — la cloche de notification, le menu mobile, la loupe
   de recherche. La navigation est typographique, comme le prévoit
   REFONTE_V3.md : « PAS d'icônes partout ».
   ============================================================================= */

/* --- Jetons ---------------------------------------------------------------- */
:root {
    /* =========================================================================
       1. SURFACES — LA HIÉRARCHIE, PAS UNE COULEUR DE PLUS
       =========================================================================
       LE DÉFAUT MESURÉ. Le fond de page valait #f7f8f9 et les cartes #ffffff :
       un rapport de contraste de **1,06:1**. En dessous de 1,10 deux surfaces
       ne se distinguent pas — une carte blanche sur ce fond ne tenait que par
       son filet. D'où l'impression de page vide : fond blanc, carte blanche,
       carte blanche, et rien qui structure le regard.

       Le nouveau fond est à 1,17:1 de la surface. Les cartes se posent enfin
       DESSUS au lieu de s'y dissoudre, et l'œil trouve les blocs sans lire.

       Les neutres ne sont pas gris mais TEINTÉS TEAL (teinte ~193, chroma très
       basse). C'est ce qui fait qu'un produit se reconnaît sans être vert :
       la couleur de marque est présente partout, à dose homéopathique, dans le
       gris lui-même. Un gris neutre à côté d'un accent teal paraît sale.

       Quatre plans, et pas un de plus :
         fond-creux   ce qui est EN DESSOUS  — gouttières, zones inertes
         fond         le plan de travail
         surface      ce qui porte du contenu — cartes, panneaux
         surface-alt  ce qui est POSÉ SUR une surface — en-tête de tableau
    */
    --fond-creux: #dfe7ea;
    --fond:       #e8eef0;
    --surface:    #ffffff;
    --surface-alt:#f3f7f8;

    --trait:      #d5dee1;
    --trait-fin:  #e6edef;

    /* =========================================================================
       2. ENCRE — quatre niveaux, tous vérifiés
       =========================================================================
       Contrastes calculés, pas estimés : 17,9 / 9,5 / 5,3 / 3,1 sur blanc.
       `encre-pale` valait 2,95:1 et tombait donc sous le minimum de 3:1 pour
       du texte large — un libellé secondaire qu'on ne peut pas lire n'est pas
       discret, il est absent.
    */
    --encre:      #0f172a;
    --encre-moy:  #3b4756;
    --encre-doux: #5f6d7a;
    --encre-pale: #7d8994;

    /* =========================================================================
       3. TEAL — la marque, et ses trois emplois distincts
       =========================================================================
       `--accent` est la couleur de MARQUE : marqueurs, filets actifs, icônes,
       traits de graphique. Sur blanc elle donne 3,74:1 — assez pour une forme,
       PAS pour du texte ni pour un bouton plein.

       `--accent-fonce` (5,01:1) est donc la couleur des BOUTONS PLEINS et des
       liens. Confondre les deux met du blanc sur du teal trop clair : lisible
       sur un écran de bureau, illisible au soleil sur un téléphone — et c'est
       exactement là que cette application sert.

       `--accent-sombre` sert au texte POSÉ SUR un fond teal pâle (6,3:1).
    */
    --accent:       #0d9488;
    --accent-fonce: #0a6f66;
    --accent-sombre:#0b544e;
    --accent-pale:  #dcf0ee;
    --accent-voile: #eef8f7;

    /* =========================================================================
       4. ÉTATS — quatre, chacun avec son fond pâle assorti
       =========================================================================
       Chaque couleur d'état est lisible SUR SON PROPRE fond pâle (≥ 4,5:1).
       C'est la seule façon d'écrire un statut dans une pastille sans que le
       texte s'efface. `positif` et `attention` échouaient à 4,3 et 4,0.

       `info` est NOUVEAU. Il manquait : tout ce qui n'était ni bon ni mauvais
       — « réservation », « planifié », « en cours » — empruntait le teal de
       marque, et l'accent cessait alors de vouloir dire quelque chose.
    */
    --positif:        #2b7354;
    --positif-pale:   #e2f0e9;
    --attention:      #8a5f22;
    --attention-pale: #f8eeda;
    --critique:       #a03a33;
    --critique-pale:  #f9e6e4;
    --info:           #2a5c8a;
    --info-pale:      #e5eef7;

    /* Orange : renouvellement d'abonnement, et rien d'autre.
       Blanc sur orange donne 3,02:1 — insuffisant. L'orange porte donc de
       l'ENCRE (5,92:1), jamais du blanc. */
    --cta:       #ea7317;
    --cta-fonce: #d1620d;

    /* =========================================================================
       5. RAYONS, OMBRES, MOUVEMENT
       ========================================================================= */
    --rayon:       10px;
    --rayon-champ: 7px;
    --rayon-badge: 5px;

    /* Les ombres sont TEINTÉES de la même encre que le texte : une ombre grise
       neutre sur un fond teinté se voit comme une salissure. */
    --ombre:      0 1px 2px rgba(15, 42, 46, .05), 0 1px 3px rgba(15, 42, 46, .04);
    --ombre-haute:0 4px 14px rgba(15, 42, 46, .10);
    --ombre-panneau: 0 8px 32px rgba(15, 42, 46, .16);

    --transition: 150ms ease;
    --transition-lent: 240ms cubic-bezier(.2, .8, .2, 1);

    /* =========================================================================
       6. TYPOGRAPHIE — le barème existait, il n'était pas nommé
       =========================================================================
       Chaque page rechoisissait ses tailles. Nommées, elles deviennent une
       décision unique. L'échelle est serrée à dessein : c'est un outil de
       gestion, pas une page d'accueil, et deux points d'écart suffisent à
       hiérarchiser quand la graisse et la couleur travaillent aussi.
    */
    --t-micro:  10px;   /* mentions légales, unités */
    --t-petit:  11.5px; /* libellés de tableau, notes */
    --t-corps:  12.5px; /* le texte courant de l'application */
    --t-lu:     14px;   /* paragraphes vraiment destinés à être lus */
    --t-titre:  15px;   /* titres de carte et de section */
    --t-page:   19px;   /* titre de page */
    --t-chiffre:22px;   /* une mesure qu'on lit de loin */
    --t-heros:  28px;   /* le chiffre unique d'un écran */

    /* =========================================================================
       7. ESPACEMENT — une échelle de 4, nommée
       ========================================================================= */
    --e-1: 4px;
    --e-2: 8px;
    --e-3: 12px;
    --e-4: 16px;
    --e-5: 20px;
    --e-6: 24px;
    --e-8: 32px;

    --barre: 232px;
    --entete: 56px;

    --police: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
              'Helvetica Neue', Arial, sans-serif;
}

/* --- Réinitialisation ------------------------------------------------------ */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

/* =============================================================================
   LES TEINTES DE SURFACE — ce qui manquait pour que le produit ait une couleur
   =============================================================================
   LE CONSTAT

   L'application n'avait que des pastilles d'ÉTAT : vert « payé », rouge « en
   retard », ambre « à faire ». Utiles, minuscules, et c'est tout. Partout
   ailleurs : blanc sur blanc. D'où « ça manque de couleur » — ce n'est pas une
   question de goût, c'est qu'aucun bloc n'était identifiable au premier coup
   d'œil. Sur un écran de vingt lignes grises, on lit tout ou on ne lit rien.

   CE QU'ON AJOUTE, ET CE QUE ÇA CHANGE

   Six familles, et chacune VEUT DIRE quelque chose. La couleur n'est pas une
   décoration posée après coup, c'est un raccourci de lecture : on apprend en
   deux jours que le bleu-teal est l'argent et que le rouge est ce qui bloque,
   et on cesse de lire les titres.

     teal    la marque, l'argent qui rentre, ce qui va bien
     bleu    l'information, le planning, ce qui est prévu
     vert    ce qui est fait, à jour, conforme
     ambre   ce qui approche, ce qui attend une action
     rouge   ce qui bloque, ce qui est dépassé
     violet  les gens — chauffeurs, clients, accès

   TROIS INTENSITÉS PAR FAMILLE, PAS DIX

     --t-<nom>-voile   fond de tuile, très pâle
     --t-<nom>-pale    fond de pastille d'icône
     --t-<nom>         le trait et le texte, lisible sur les deux (≥ 4,5:1)

   Toutes les paires texte/fond ont été calculées, pas estimées.
   ========================================================================== */

:root {
    --t-teal:       #0a6f66;
    --t-teal-pale:  #d3ece9;
    --t-teal-voile: #edf7f6;

    --t-bleu:       #245c96;
    --t-bleu-pale:  #dbe8f5;
    --t-bleu-voile: #eff5fb;

    --t-vert:       #2b7354;
    --t-vert-pale:  #d9eee4;
    --t-vert-voile: #eef8f3;

    --t-ambre:      #8a5f22;
    --t-ambre-pale: #f6e8cd;
    --t-ambre-voile:#fdf6ea;

    --t-rouge:      #a03a33;
    --t-rouge-pale: #f6dedb;
    --t-rouge-voile:#fdf0ee;

    --t-violet:     #5a4a95;
    --t-violet-pale:#e3dff3;
    --t-violet-voile:#f2f0fa;

    --t-neutre:     #4a5763;
    --t-neutre-pale:#e3e9ec;
    --t-neutre-voile:#f2f6f7;
}

/* -----------------------------------------------------------------------------
   LA PASTILLE D'ICÔNE
   --------------------------------------------------------------------------
   Un rond de couleur douce avec une icône dedans. C'est LE motif qui
   distingue une application d'un tableau administratif, et il ne coûte rien :
   36 px, une teinte, un trait.
   -------------------------------------------------------------------------- */
.ico-pastille {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    flex: none;
    border-radius: 11px;
    background: var(--t-neutre-pale);
    color: var(--t-neutre);
}
.ico-pastille.est-teal   { background: var(--t-teal-pale);   color: var(--t-teal); }
.ico-pastille.est-bleu   { background: var(--t-bleu-pale);   color: var(--t-bleu); }
.ico-pastille.est-vert   { background: var(--t-vert-pale);   color: var(--t-vert); }
.ico-pastille.est-ambre  { background: var(--t-ambre-pale);  color: var(--t-ambre); }
.ico-pastille.est-rouge  { background: var(--t-rouge-pale);  color: var(--t-rouge); }
.ico-pastille.est-violet { background: var(--t-violet-pale); color: var(--t-violet); }

.ico-pastille.est-grande { width: 46px; height: 46px; border-radius: 15px; }
.ico-pastille.est-ronde  { border-radius: 50%; }

.ico { flex: none; vertical-align: middle; }

/* -----------------------------------------------------------------------------
   LA TUILE TEINTÉE — un bloc qui porte un chiffre et mène quelque part
   --------------------------------------------------------------------------
   Remplace la carte blanche pour tout ce qui est un INDICATEUR. Une carte
   blanche dit « voici un conteneur » ; une tuile teintée dit « voici un fait,
   et il est de cette nature-là ».

   Elle porte toujours un lien. Un indicateur qui ne mène nulle part n'est pas
   un indicateur, c'est une décoration — c'est la règle qui gouverne tout cet
   écran.
   -------------------------------------------------------------------------- */
.tuile-t {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 13px 14px;
    border-radius: 14px;
    background: var(--t-neutre-voile);
    border: 1px solid transparent;
    text-decoration: none;
    color: inherit;
    min-width: 0;
    transition: transform var(--transition), box-shadow var(--transition);
}
.tuile-t:hover { transform: translateY(-1px); box-shadow: var(--ombre-haute); }
.tuile-t:active { transform: translateY(0); }

.tuile-t.est-teal   { background: var(--t-teal-voile);   border-color: var(--t-teal-pale); }
.tuile-t.est-bleu   { background: var(--t-bleu-voile);   border-color: var(--t-bleu-pale); }
.tuile-t.est-vert   { background: var(--t-vert-voile);   border-color: var(--t-vert-pale); }
.tuile-t.est-ambre  { background: var(--t-ambre-voile);  border-color: var(--t-ambre-pale); }
.tuile-t.est-rouge  { background: var(--t-rouge-voile);  border-color: var(--t-rouge-pale); }
.tuile-t.est-violet { background: var(--t-violet-voile); border-color: var(--t-violet-pale); }

.tuile-t-tete { display: flex; align-items: center; gap: 9px; }
.tuile-t-titre {
    flex: 1;
    min-width: 0;
    font-size: var(--t-petit);
    font-weight: 600;
    letter-spacing: .01em;
    color: var(--encre-moy);
}

.tuile-t-n {
    font-size: 24px;
    font-weight: 650;
    line-height: 1.05;
    letter-spacing: -.025em;
    font-variant-numeric: tabular-nums;
    color: var(--encre);
}
.tuile-t.est-teal   .tuile-t-n { color: var(--t-teal); }
.tuile-t.est-bleu   .tuile-t-n { color: var(--t-bleu); }
.tuile-t.est-vert   .tuile-t-n { color: var(--t-vert); }
.tuile-t.est-ambre  .tuile-t-n { color: var(--t-ambre); }
.tuile-t.est-rouge  .tuile-t-n { color: var(--t-rouge); }
.tuile-t.est-violet .tuile-t-n { color: var(--t-violet); }

/* Le zéro s'efface. Un compteur à zéro ne doit pas attirer l'œil qui cherche
   un problème — et une tuile rouge annonçant « 0 panne » est un contresens. */
.tuile-t.est-vide { background: var(--surface-alt); border-color: var(--trait-fin); }
.tuile-t.est-vide .tuile-t-n { color: var(--encre-pale); font-weight: 500; }
.tuile-t.est-vide .ico-pastille { background: var(--trait-fin); color: var(--encre-pale); }

.tuile-t-detail { font-size: var(--t-petit); color: var(--encre-doux); line-height: 1.35; }

.tuile-t-lien {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-top: 2px;
    font-size: var(--t-petit);
    font-weight: 600;
    color: var(--encre-moy);
}
.tuile-t:hover .tuile-t-lien { color: var(--encre); }
.tuile-t-lien .ico { transition: transform var(--transition); }
.tuile-t:hover .tuile-t-lien .ico { transform: translateX(2px); }

/* --- LA SITUATION : l'argent en grand, ce qui presse en couleurs ------------
   ELLE VIT DANS app.css ET NON DANS tableau.css. La feuille du tableau de bord
   n'est chargee que sur l'accueil ; ce motif sert maintenant aussi au compte de
   resultat, et il servira ailleurs. La regle du projet est explicite : tout ce
   qui sert sur plus d'une page appartient a app.css — sinon la seconde page
   rend le balisage SANS AUCUN de ces styles, ce qui donne exactement ce qu'on
   vient de corriger : un bloc heros pleine largeur et deux tuiles empilees. */
.tb-situation {
    display: grid;
    grid-template-columns: minmax(0, 320px) minmax(0, 1fr);
    gap: 14px;
    margin-bottom: 14px;
}

.tb-tuiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr));
    gap: 12px;
    align-content: start;
}

@media (max-width: 900px) {
/* --- LA SITUATION SUR TELEPHONE --------------------------------------------
   Le heros passe en pleine largeur et prend la tete de l'ecran : c'est la
   premiere chose qu'on voit en ouvrant l'application, comme la tuile de
   revenus d'une application bancaire. Les quatre tuiles passent a deux
   colonnes — quatre en ligne donneraient 90 px chacune, ou le chiffre tient
   mais pas le libelle. */
.tb-situation { grid-template-columns: minmax(0, 1fr); gap: var(--m-3); margin-bottom: var(--m-3); }

.heros { border-radius: var(--rayon-carte); padding: var(--m-4); }
.heros-n { font-size: 30px; }

.tb-tuiles { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--m-2); }
.tuile-t { padding: 11px 12px; gap: 8px; border-radius: var(--rayon-champ); }
.tuile-t-n { font-size: 20px; }
.ico-pastille { width: 30px; height: 30px; border-radius: 9px; }

}

/* -----------------------------------------------------------------------------
   LE BLOC HÉROS — l'argent, en grand, et il est la seule chose colorée en plein
   --------------------------------------------------------------------------
   UN SEUL aplat saturé par écran. C'est ce qui lui donne son point d'ancrage :
   l'œil s'y pose d'abord, puis balaie le reste. Deux aplats et il n'y a plus
   de premier regard.

   Le dégradé est ici et nulle part ailleurs — même exception que la colonne de
   navigation.
   -------------------------------------------------------------------------- */
.heros {
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: 16px 18px 18px;
    border-radius: 16px;
    background: linear-gradient(135deg, #0b7d73 0%, #0a5f5a 55%, #0d4a4f 100%);
    color: #fff;
}

.heros-tete { display: flex; align-items: center; gap: 10px; }
.heros-titre {
    flex: 1;
    min-width: 0;
    font-size: 13px;
    font-weight: 600;
    /* 0,92 et non 0,82 : mesure, le blanc a 82 % sur le premier arret du
       degrade tombe a 3,92:1, sous le minimum de 4,5. Un libelle de 13 px
       qu'on ne lit pas au soleil ne sert a rien. */
    color: rgba(255, 255, 255, .92);
}

.heros-periode {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 11px;
    border-radius: 999px;
    background: rgba(255, 255, 255, .14);
    color: #fff;
    font-size: 12px;
    font-weight: 600;
    text-decoration: none;
}
.heros-periode:hover { background: rgba(255, 255, 255, .24); }

.heros-n {
    font-size: 34px;
    font-weight: 650;
    line-height: 1;
    letter-spacing: -.03em;
    font-variant-numeric: tabular-nums;
}
.heros-n .heros-unite { font-size: 15px; font-weight: 500; opacity: .7; margin-left: 4px; }

.heros-delta {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 12px;
    font-weight: 600;
    color: #fff;
}
.heros-delta.est-baisse { color: #ffc9a8; }

/* Les deux sous-blocs : recettes et dépenses, chacun cliquable. */
.heros-duo { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }

.heros-case {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 11px 13px;
    border-radius: 12px;
    background: rgba(255, 255, 255, .11);
    color: #fff;
    text-decoration: none;
}
.heros-case:hover { background: rgba(255, 255, 255, .2); }
.heros-case-l {
    display: flex; align-items: center; gap: 5px;
    font-size: 11.5px; font-weight: 600; color: rgba(255, 255, 255, .92);
}
.heros-case-l .ico { opacity: .7; }
.heros-case-n { font-size: 18px; font-weight: 650; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.heros-case-n .heros-unite { font-size: 11px; }

/* La jauge d'atteinte : une barre fine, pas un anneau. Elle dit une
   proportion, elle n'a pas à occuper 60 px. */
.heros-jauge { height: 3px; border-radius: 2px; background: rgba(255, 255, 255, .2); overflow: hidden; }
.heros-jauge span { display: block; height: 100%; background: #fff; border-radius: 2px; }

/* -----------------------------------------------------------------------------
   LES ACTIONS RAPIDES — de gros ronds colorés, et c'est assumé
   --------------------------------------------------------------------------
   Les gestes du quotidien : encaisser, ajouter, planifier. Ils étaient
   éparpillés dans cinq pages ; ici ils sont à un tap, avec une couleur qu'on
   reconnaît avant de lire le libellé.

   Grande cible : 46 px de pastille dans une tuile d'au moins 88 px de haut.
   C'est ce qu'on vise au pouce, en marchant, dans une cour de garage.
   -------------------------------------------------------------------------- */
.actions-rapides {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
    gap: 10px;
}

.action-rapide {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    gap: 8px;
    padding: 14px 8px 12px;
    border-radius: 14px;
    background: var(--surface);
    border: 1px solid var(--trait-fin);
    text-decoration: none;
    color: var(--encre-moy);
    text-align: center;
    min-width: 0;
    transition: transform var(--transition), border-color var(--transition);
}
.action-rapide:hover { transform: translateY(-2px); border-color: var(--trait); }
.action-rapide:active { transform: translateY(0); }

.action-rapide-l {
    font-size: 11.5px;
    font-weight: 600;
    line-height: 1.25;
    max-width: 100%;
    overflow-wrap: anywhere;
}

/* -----------------------------------------------------------------------------
   L'ÉTAT VIDE — une ligne, et c'est tout
   --------------------------------------------------------------------------
   CE QU'ON AVAIT :

     « Rien en attente. Papiers a jour, aucun retour depasse, aucun entretien
       en souffrance. »

   Trois propositions pour dire que tout va bien, quatre lignes sur un
   telephone. Le vide etait devenu plus bavard que le plein.

   PUIS UNE PASTILLE D'ICONE ET UNE SECONDE LIGNE, ce qui n'etait guere mieux :
   un rond vert de 34 px pour annoncer qu'il n'y a RIEN a voir attire l'oeil
   sur le seul bloc de l'ecran qui ne demande aucune action.

   Un etat vide a UN travail : dire en un coup d'oeil qu'il n'y a rien. Une
   ligne suffit.
   -------------------------------------------------------------------------- */
.vide-mini {
    padding: 18px 14px;
    text-align: center;
}
.vide-mini-t {
    font-size: 12.5px;
    font-weight: 500;
    color: var(--encre-pale);
}

/* -----------------------------------------------------------------------------
   Deux cibles, deux rendus — et UNE seule source de donnees
   --------------------------------------------------------------------------
   Une liste s'ecrit une fois, dans la vue, sous forme de lignes. Elle se rend
   ensuite en TABLEAU sur un ecran large et en RANGEES sur un telephone. Ce ne
   sont pas deux gabarits a tenir d'accord : c'est la meme boucle.

   Recopier la liste dans deux blocs de HTML serait la garantie qu'ils
   divergent au premier changement — une colonne ajoutee d'un cote, oubliee de
   l'autre, et le telephone ment.
   -------------------------------------------------------------------------- */
.sur-mobile { display: none !important; }

/* -----------------------------------------------------------------------------
   L'ATTRIBUT `hidden` DOIT GAGNER — partout
   --------------------------------------------------------------------------
   `hidden` est un attribut natif : le navigateur lui applique `display: none`
   depuis SA feuille de style, dont la specificite est la plus faible qui soit.
   N'importe quelle regle de classe la bat — `.btn { display: inline-flex }`,
   `.modale-corps { display: flex }`, `.barre-selection { display: flex }`.

   CE DEFAUT EST APPARU CINQ FOIS DANS CE DEPOT :

     • la barre de selection des vehicules, visible en permanence avec zero
       ligne cochee — trois boutons destructeurs en travers d'une liste ;
     • les trois vues de la modale d'encaissement, affichees ensemble ;
     • le « Precedent » et les DEUX boutons primaires concurrents du formulaire
       vehicule, tous visibles sur la premiere etape ;
     • et deux fois sur des panneaux de la carte.

   A chaque fois le JavaScript etait juste : il posait bien `hidden`. C'est le
   CSS qui l'ignorait. Une seule regle, ici, ferme la famille entiere.

   `!important` est justifie : on affirme une regle du navigateur contre des
   classes qui, legitimement, declarent un `display`. Sans lui il faudrait
   enumerer chaque composant — et en oublier un. */
[hidden] { display: none !important; }

body {
    margin: 0;
    font-family: var(--police);
    font-size: 14px;
    line-height: 1.55;
    color: var(--encre);
    background: var(--fond);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 { margin: 0; font-weight: 650; line-height: 1.25; letter-spacing: -.011em; }
p { margin: 0 0 12px; }
p:last-child { margin-bottom: 0; }

a { color: var(--accent); text-decoration: none; transition: color var(--transition); }
a:hover { color: var(--accent-fonce); }

img { max-width: 100%; height: auto; }

:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 4px;
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .01ms !important;
        transition-duration: .01ms !important;
    }
}

/* =============================================================================
   Mise en page
   ============================================================================= */
.coque { display: flex; min-height: 100vh; }

.contenu {
    flex: 1;
    min-width: 0;              /* sans quoi un tableau large pousse la page */
    display: flex;
    flex-direction: column;
}

.zone { flex: 1; padding: 20px 22px 32px; max-width: 1400px; width: 100%; }

/* Trois paliers, pas un seul. Passer de 22 px a 14 px d un coup a 640 px
   laissait la tranche 641-900 px avec des marges de bureau sur un ecran de
   tablette, et 360 px n avait aucun palier a lui. */
@media (max-width: 900px) { .zone { padding: 16px 16px 28px; } }
@media (max-width: 640px) { .zone { padding: 12px 12px 24px; } }
@media (max-width: 400px) { .zone { padding: 10px 10px 20px; } }

/* --- Barre latérale -------------------------------------------------------- */
.barre {
    width: var(--barre);
    flex: none;
    background: var(--encre);
    color: #b9c0cc;
    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100vh;
    z-index: 30;
}

.barre-logo {
    flex: none;
    padding: 17px 20px 16px;
    font-weight: 700;
    font-size: 16px;
    letter-spacing: -.02em;
    color: #fff;
}

/* min-height: 0 est indispensable, pas cosmétique.
   Sans lui, un élément flex refuse de se réduire sous la hauteur de son
   contenu : avec une quinzaine d'entrées de menu, la navigation débordait
   et recouvrait le pied de barre. C'était le chevauchement constaté. */
.barre-nav {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 4px 12px 12px;
}

.barre-nav::-webkit-scrollbar { width: 6px; }
.barre-nav::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, .1); border-radius: 3px; }

/* Trait de partage entre le quotidien, a plat, et les sections repliables.
   Une simple ligne dit « au-dessus ce que vous ouvrez tous les jours, en
   dessous le reste » sans qu'on ait a l'ecrire. */
.barre-separateur {
    height: 1px;
    background: rgba(255, 255, 255, .07);
    margin: 12px 10px;
}

/* --- Sections repliables --------------------------------------------------- */
/* <details> et non un script : le repli fonctionne sans JavaScript, il est
   accessible au clavier et annonce correctement par un lecteur d'ecran. */
.barre-section { margin-bottom: 2px; }

.barre-section-tete {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 7px 10px;
    border-radius: var(--rayon-champ);
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: #5d6675;
    cursor: pointer;
    list-style: none;
    user-select: none;
    transition: color var(--transition), background var(--transition);
}
.barre-section-tete::-webkit-details-marker { display: none; }
.barre-section-tete:hover { color: #99a2b0; background: rgba(255, 255, 255, .04); }

/* Le chevron est dessine en CSS plutot qu'en SVG : c'est le seul repere
   graphique de la colonne, et il porte une information que le texte ne porte
   pas — deplie ou replie. */
.barre-section-tete::before {
    content: '';
    flex: none;
    width: 5px; height: 5px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: rotate(-45deg);
    margin-left: 2px;
    transition: transform var(--transition);
}
.barre-section[open] > .barre-section-tete::before { transform: rotate(45deg); }
.barre-section[open] > .barre-section-tete { color: #8a93a3; }

.barre-section-corps { padding-top: 1px; }

/* Ancien intertitre non repliable, conserve pour les vues qui l'emploient
   encore hors de la barre principale. *

/* Navigation typographique : pas d'icône. Le repère visuel est la barre
   verticale teal de l'élément actif, comme spécifié dans REFONTE_V3.md. */
.barre-lien {
    /* L'icone et le libelle sur une rangee. La colonne ne portait que du texte :
       treize lignes de meme graisse, meme couleur, meme place — on la relisait
       a chaque fois. Une icone se reconnait en vision peripherique, un mot non. */
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 7px 10px;
    margin-bottom: 1px;
    border-radius: var(--rayon-champ);
    color: #b9c0cc;
    font-size: 13.5px;
    font-weight: 450;
    position: relative;
    transition: background var(--transition), color var(--transition);
}

.barre-lien:hover { background: rgba(255, 255, 255, .05); color: #fff; }

.barre-lien-l { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* L'icone est plus sourde que le texte : elle guide, elle ne crie pas. Elle
   s'allume au survol et sur l'entree active — c'est la seule couleur de la
   colonne, et elle marque ou l'on est. */
.barre-ico { color: #7d8899; transition: color var(--transition); }
.barre-lien:hover .barre-ico { color: #b9c0cc; }
.barre-lien.est-actif .barre-ico { color: var(--accent); }

.barre-lien.est-actif { background: rgba(13, 148, 136, .13); color: #fff; font-weight: 550; }

.barre-lien.est-actif::before {
    content: '';
    position: absolute;
    left: -12px;
    top: 5px;
    bottom: 5px;
    width: 3px;
    border-radius: 0 3px 3px 0;
    background: var(--accent);
}

.barre-compteur {
    /* En flux, apres le libelle. Le `float: right` datait du temps ou le lien
       etait un bloc de texte : dans une rangee flex il n'a plus aucun effet et
       le compteur se collait a l'icone. */
    order: 2;
    flex: none;
    background: var(--accent);
    color: #fff;
    font-size: 10.5px;
    font-weight: 700;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 9px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-top: 1px;
}

.barre-pied {
    flex: none;                /* ne se comprime jamais */
    padding: 13px 16px;
    border-top: 1px solid rgba(255, 255, 255, .07);
}

.barre-entreprise {
    font-size: 12.5px;
    color: #8d96a5;
    margin-bottom: 7px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;       /* un nom long ne casse plus la mise en page */
}

/* --- Barre supérieure ------------------------------------------------------ */
.entete {
    height: var(--entete);
    flex: none;
    background: var(--surface);
    border-bottom: 1px solid var(--trait);
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 0 28px;
    position: sticky;
    top: 0;
    z-index: 20;
}

@media (max-width: 640px) { .entete { padding: 0 16px; } }

.fil {
    font-size: 13px;
    color: var(--encre-doux);
    display: flex;
    gap: 7px;
    align-items: center;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
}
.fil a { color: var(--encre-doux); }
.fil a:hover { color: var(--accent); }
.fil-actuel {
    color: var(--encre);
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* --- La recherche globale, en en-tete ---------------------------------------
   L'en-tete ne portait qu'un fil d'Ariane et trois boutons : 56 px de haut
   pour presque rien, sur chacune des 53 pages. Il porte maintenant ce qu'on
   cherche depuis n'importe ou.

   Elle prend la place disponible mais s'arrete a 420 px : au-dela, un champ
   de recherche devient une invitation a taper une phrase, alors qu'on y met
   une immatriculation. */
.entete-recherche {
    flex: 1 1 auto;
    max-width: 420px;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 8px;
    height: 34px;
    padding: 0 11px;
    border: 1px solid var(--trait);
    border-radius: 999px;
    background: var(--fond);
    color: var(--encre-pale);
    transition: border-color var(--transition), background var(--transition);
}
.entete-recherche:focus-within {
    border-color: var(--accent);
    background: var(--surface);
    box-shadow: 0 0 0 3px var(--accent-pale);
}

.entete-recherche-champ {
    flex: 1;
    min-width: 0;
    border: 0;
    background: none;
    font-family: inherit;
    font-size: 13px;
    color: var(--encre);
    outline: none;
}
.entete-recherche-champ::placeholder { color: var(--encre-pale); }

/* Le champ n'a pas sa place sur un ecran etroit : la barre d'application
   mobile a sa propre recherche, et deux champs se disputeraient la rangee. */
@media (max-width: 900px) { .entete-recherche { display: none; } }

.entete-actions { margin-left: auto; display: flex; align-items: center; gap: 12px; flex: none; }

.avatar {
    width: 30px; height: 30px;
    border-radius: 50%;
    background: var(--accent-pale);
    color: var(--accent-fonce);
    font-size: 11.5px;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.cloche { position: relative; color: var(--encre-doux); display: inline-flex; }
.cloche:hover { color: var(--encre); }
.cloche svg { width: 18px; height: 18px; }

.menu-mobile { display: none; background: none; border: 0; color: var(--encre-moy); padding: 6px; cursor: pointer; }
.menu-mobile svg { width: 20px; height: 20px; }

@media (max-width: 960px) {
    .menu-mobile { display: inline-flex; }
    .barre {
        position: fixed;
        left: 0; top: 0; bottom: 0;
        z-index: 60;
        transform: translateX(-100%);
        transition: transform var(--transition);
    }
    .barre.est-ouverte { transform: translateX(0); }
    .voile {
        position: fixed; inset: 0;
        background: rgba(15, 23, 42, .4);
        z-index: 50;
        opacity: 0;
        transition: opacity var(--transition);
    }
    .voile.est-visible { opacity: 1; }
}

/* =============================================================================
   Composants
   ============================================================================= */

/* --- En-tête de page ------------------------------------------------------- */
.page-tete {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    margin-bottom: 22px;
    flex-wrap: wrap;
}

.page-titre { font-size: 21px; font-weight: 650; letter-spacing: -.018em; }
.page-sous-titre { font-size: 13px; font-weight: 400; color: var(--encre-doux); margin-top: 2px; }
.page-tete-actions { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }

/* --- Cartes ---------------------------------------------------------------- */
.carte {
    background: var(--surface);
    border: 1px solid var(--trait);
    border-radius: var(--rayon);
    box-shadow: var(--ombre);
}

/* Carte d'action destructrice : le cadre teinté prévient sans crier. */
.carte.est-danger { border-color: #eddcda; }
/* Encart de récapitulatif dans un formulaire : posé sur le fond de page pour
   se distinguer des champs sans introduire une carte de plus. */
.carte.est-encart { background: var(--fond); box-shadow: none; }
/* Carte dont le contenu touche les bords — une carte Leaflet, par exemple :
   sans overflow caché, la tuile déborde des coins arrondis. */
.carte.est-pleine { overflow: hidden; }

.carte-tete {
    padding: 10px 14px;
    border-bottom: 1px solid var(--trait-fin);
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;           /* boutons et badges passent à la ligne au lieu de se chevaucher */
}

.carte-titre { font-size: 13.5px; font-weight: 600; letter-spacing: -.005em; }
.carte-corps { padding: 15px; }
.carte-pied { padding: 10px 14px; border-top: 1px solid var(--trait-fin); background: #fcfcfd; }

/* Corps dense : pour les cartes qui empilent des lignes de fiche plutot que
   du texte. 18 px de tous cotes autour d une liste de six lignes fait une
   carte deux fois plus haute que son contenu. */
.carte-corps.est-serre { padding: 12px 14px; }

@media (max-width: 640px) {
    .carte-tete  { padding: 9px 12px; }
    .carte-corps { padding: 12px; }
    .carte-corps.est-serre { padding: 10px 12px; }
    .carte-pied  { padding: 9px 12px; }
}

/* --- Statistiques ---------------------------------------------------------- */
.stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 14px;
    margin-bottom: 22px;
}

.stat {
    background: var(--surface);
    border: 1px solid var(--trait);
    border-radius: var(--rayon);
    box-shadow: var(--ombre);
    padding: 15px 17px;
    min-width: 0;              /* autorise le contenu à se réduire dans la grille */
}

.stat-label {
    font-size: 11.5px;
    font-weight: 550;
    letter-spacing: .03em;
    color: var(--encre-doux);
    margin-bottom: 5px;
}

.stat-valeur {
    font-size: 23px;
    font-weight: 650;
    letter-spacing: -.028em;
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
    /* Un montant à sept chiffres ne doit ni déborder ni couper la carte. */
    overflow-wrap: anywhere;
}

.stat-detail { font-size: 12px; color: var(--encre-doux); margin-top: 4px; line-height: 1.4; }
.stat-valeur.est-positif { color: var(--positif); }
.stat-valeur.est-negatif { color: var(--critique); }
.stat-valeur.est-accent  { color: var(--accent-fonce); }

/* --- Boutons --------------------------------------------------------------- */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 8px 14px;
    border: 1px solid transparent;
    border-radius: var(--rayon-champ);
    font-family: inherit;
    font-size: 13px;
    font-weight: 550;
    line-height: 1.4;
    cursor: pointer;
    white-space: nowrap;
    transition: background var(--transition), border-color var(--transition), color var(--transition);
}

.btn-primaire { background: var(--accent); color: #fff; }
.btn-primaire:hover { background: var(--accent-fonce); color: #fff; }

/* Le seul usage de l'orange : renouveler un abonnement. */
.btn-action { background: var(--cta); color: #fff; }
.btn-action:hover { background: var(--cta-fonce); color: #fff; }

.btn-neutre { background: var(--surface); color: var(--encre-moy); border-color: var(--trait); }
.btn-neutre:hover { background: var(--fond); color: var(--encre); border-color: #d8dbe1; }

.btn-danger { background: var(--surface); color: var(--critique); border-color: #eddcda; }
.btn-danger:hover { background: var(--critique-pale); }

.btn-petit { padding: 5px 10px; font-size: 12px; }
.btn-large { padding: 11px 20px; font-size: 14px; }
.btn-plein { width: 100%; }

.btn:disabled, .btn[aria-disabled='true'] { opacity: .5; cursor: not-allowed; }

/* --- Formulaires ----------------------------------------------------------- */
.champ { margin-bottom: 15px; min-width: 0; }

.champ-label {
    display: block;
    font-size: 12.5px;
    font-weight: 500;
    color: var(--encre-moy);
    margin-bottom: 5px;
}

.champ-label .requis { color: var(--critique); }
.champ-label.est-case { display: flex; align-items: center; gap: 8px; cursor: pointer; }

.champ-saisie,
.champ-select,
.champ-zone {
    width: 100%;
    padding: 8px 11px;
    border: 1px solid var(--trait);
    border-radius: var(--rayon-champ);
    font-family: inherit;
    font-size: 13.5px;
    color: var(--encre);
    background: var(--surface);
    transition: border-color var(--transition), box-shadow var(--transition);
}

.champ-saisie:focus,
.champ-select:focus,
.champ-zone:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(13, 148, 136, .1);
}

.champ-saisie::placeholder { color: var(--encre-pale); }
.champ-zone { min-height: 84px; resize: vertical; }

.champ-select {
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%236b7684'%3E%3Cpath d='M4.5 6.5 8 10l3.5-3.5z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 9px center;
    background-size: 16px;
    padding-right: 30px;
}

.champ-aide { font-size: 12px; color: var(--encre-doux); margin-top: 5px; line-height: 1.45; }
.champ-saisie.est-invalide { border-color: var(--critique); }

.grille-champs {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: 0 15px;
}

/* --- Tableaux -------------------------------------------------------------- */
.tableau-boite {
    overflow-x: auto;
    border: 1px solid var(--trait);
    border-radius: var(--rayon);
    background: var(--surface);
    box-shadow: var(--ombre);
}

/* Tableau posé DANS une carte : la carte porte déjà le cadre et l'ombre,
   les redoubler dessine un liseré parasite au ras du bord. */
.tableau-boite.est-nue { border: 0; box-shadow: none; border-radius: 0; }

/* Lignes signalées par un fond plutôt que par un badge de plus : l'œil repère
   la ligne entière d'un coup, sans avoir à lire une colonne particulière. */
tr.est-non-lue { background: var(--accent-pale); }
tr.est-echue   { background: var(--attention-pale); }

/* Journee de versement jamais saisie. Rayures legeres plutot qu'un fond
   plein : la ligne existe sans avoir ete constatee, et le motif le dit mieux
   qu'une couleur unie qui la ferait passer pour un etat comme un autre. */
tr.est-non-saisi {
    background: repeating-linear-gradient(
        45deg,
        var(--attention-pale),
        var(--attention-pale) 6px,
        #fdfaf4 6px,
        #fdfaf4 12px
    );
}

.tableau { width: 100%; border-collapse: collapse; font-size: 13px; }

.tableau th {
    text-align: left;
    padding: 10px 15px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .04em;
    color: var(--encre-doux);
    background: #fcfcfd;
    border-bottom: 1px solid var(--trait);
    white-space: nowrap;
}

.tableau td {
    padding: 11px 15px;
    border-bottom: 1px solid var(--trait-fin);
    vertical-align: middle;
}

.tableau tbody tr:last-child td { border-bottom: 0; }
.tableau tbody tr { transition: background var(--transition); }
.tableau tbody tr:hover { background: #fbfbfc; }
.tableau tfoot td { background: #fcfcfd; border-top: 1px solid var(--trait); border-bottom: 0; }

.tableau .nombre { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.tableau .actions { text-align: right; white-space: nowrap; }

.cellule-titre { font-weight: 550; color: var(--encre); display: block; }
a.cellule-titre:hover { color: var(--accent); }
.cellule-detail { font-size: 12px; color: var(--encre-doux); margin-top: 1px; }

/* --- Badges ---------------------------------------------------------------- */
/* Fond très pâle, texte teinté : ils se lisent sans capter l'attention.
   C'était le principal responsable de l'impression de couleurs mélangées. */
.badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 8px;
    border-radius: var(--rayon-badge);
    font-size: 11.5px;
    font-weight: 550;
    line-height: 1.65;
    white-space: nowrap;
}

.badge-succes  { background: var(--positif-pale);   color: var(--positif); }
.badge-danger  { background: var(--critique-pale);  color: var(--critique); }
.badge-alerte  { background: var(--attention-pale); color: var(--attention); }
.badge-info    { background: var(--accent-pale);    color: var(--accent-fonce); }
.badge-accent  { background: var(--accent-pale);    color: var(--accent-fonce); }
.badge-neutre  { background: #f2f3f5;               color: var(--encre-doux); }

.point { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }

/* --- Messages -------------------------------------------------------------- */
.messages { display: flex; flex-direction: column; gap: 8px; margin-bottom: 20px; }

.message {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    padding: 11px 14px;
    border-radius: var(--rayon-champ);
    font-size: 13px;
    border: 1px solid transparent;
    line-height: 1.5;
}

/* Une barre latérale colorée de 3 px suffit à signaler la nature du message.
   Un fond saturé sur toute la largeur était trop bruyant. */
/* CES QUATRE NOMS SONT CONSTRUITS A L'EXECUTION : `partials/messages.php` ecrit
   `message-<?= $m['type'] ?>`, ou le type vient de Session::succes/erreur/alerte.
   Un balayage des classes inemployees ne les trouve donc PAS dans les vues — et
   supprimer `.message-erreur` rendrait tous les messages d'erreur gris. */
.message-succes { background: var(--positif-pale);   color: #2c6a4e; border-color: #d9ebe2; }
.message-erreur { background: var(--critique-pale);  color: #8f4640; border-color: #f0dedc; }
.message-alerte { background: var(--attention-pale); color: #85602f; border-color: #f0e5d2; }
.message-info   { background: var(--accent-pale);    color: var(--accent-fonce); border-color: #d3ebe7; }

.message svg { width: 16px; height: 16px; flex: none; margin-top: 2px; opacity: .8; }

/* --- État vide ------------------------------------------------------------- */
.vide { text-align: center; padding: 44px 24px; }
/* Dans une carte déjà dense — une colonne de fiche — le bloc vide ne doit pas
   occuper autant de place que dans un tableau pleine largeur. */
.vide.est-compacte { padding: 20px 0; }
.vide.est-compacte .vide-texte { margin-bottom: 0; }
.vide.est-compacte .vide-texte + .btn { margin-top: 14px; }
.vide-titre { font-size: 14.5px; font-weight: 600; margin-bottom: 5px; }
.vide-texte { font-size: 13px; color: var(--encre-doux); max-width: 400px; margin: 0 auto 16px; line-height: 1.55; }

/* --- Pagination ------------------------------------------------------------ */
.pagination { display: flex; align-items: center; gap: 4px; justify-content: center; margin-top: 20px; flex-wrap: wrap; }

.pagination a, .pagination span {
    min-width: 32px; height: 32px;
    padding: 0 9px;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--trait);
    border-radius: var(--rayon-champ);
    font-size: 13px;
    color: var(--encre-moy);
    background: var(--surface);
    transition: background var(--transition), border-color var(--transition);
}

.pagination a:hover { background: var(--fond); border-color: #d8dbe1; }
.pagination .est-actif { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600; }
.pagination .est-inactif { opacity: .35; pointer-events: none; }

/* --- Filtres et recherche --------------------------------------------------- */
/* Les raccourcis de periode : un groupe, pour que le telephone puisse les
   traiter autrement que les champs. Au bureau il se fond dans la rangee. */
.periode-raccourcis { display: contents; }

.filtres {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    align-items: flex-end;
    margin-bottom: 20px;
}

.filtres .champ { margin-bottom: 0; }
.recherche { position: relative; flex: 1 1 200px; min-width: 180px; max-width: 340px; }
.recherche .champ-saisie { padding-left: 32px; }
.recherche svg {
    position: absolute; left: 10px; top: 50%;
    transform: translateY(-50%);
    width: 15px; height: 15px;
    color: var(--encre-pale);
    pointer-events: none;
}

/* --- Onglets --------------------------------------------------------------- */
.onglets {
    display: flex;
    gap: 2px;
    border-bottom: 1px solid var(--trait);
    margin-bottom: 20px;
    overflow-x: auto;
}

.onglet {
    padding: 9px 14px;
    font-size: 13px;
    font-weight: 500;
    color: var(--encre-doux);
    border-bottom: 2px solid transparent;
    white-space: nowrap;
    transition: color var(--transition), border-color var(--transition);
}

.onglet:hover { color: var(--encre); }
.onglet.est-actif { color: var(--accent-fonce); border-bottom-color: var(--accent); font-weight: 600; }

/* Effectif porte par l'onglet : un filtre qui affiche son compte se lit sans
   l'ouvrir, et « 3 au garage » est une information en soi. */
.onglet-compte {
    display: inline-block;
    margin-left: 5px;
    padding: 0 6px;
    border-radius: 20px;
    background: var(--trait-fin);
    color: var(--encre-doux);
    font-size: 11px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.onglet.est-actif .onglet-compte { background: var(--accent-pale); color: var(--accent-fonce); }

/* --- Statistiques compactes ------------------------------------------------- */
/* Quatre chiffres dans un bandeau, sans la hauteur d'une tuile .stat. Sur une
   fiche deja dense, quatre tuiles pleines pousseraient le calendrier sous la
   ligne de flottaison. *

/* --- Bandeau de chiffres cles ----------------------------------------------- */
/* `.bandeau-chiffres` / `.bc-*` A ETE REMPLACE PAR `.an-kpis` / `.an-kpi`.
   Deux composants faisaient la meme chose — une bande d'indicateurs — avec deux
   vocabulaires, et le plus ancien defilait HORIZONTALEMENT sur telephone : la
   moitie des chiffres etait hors ecran, ce que MOBILE.md interdit depuis le
   portage. Un seul motif, en grille, sur les deux cibles.

   Seule la jauge survit, renommee. */
.an-kpi-jauge { height: 3px; background: var(--trait-fin); border-radius: 2px; margin-top: 5px; overflow: hidden; }
.an-kpi-jauge span { display: block; height: 100%; background: var(--accent); border-radius: 2px; }

/* --- Onglets de vue --------------------------------------------------------- */
/* Ils defilent horizontalement sur telephone plutot que de passer a la ligne :
   une rangee d'onglets sur trois lignes ne ressemble plus a des onglets. */
.onglets-vue {
    margin-bottom: 12px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    /* Sans cela, les onglets se compriment jusqu a devenir illisibles au lieu
       de defiler : flex-shrink par defaut l emporte sur overflow-x. */
    flex-wrap: nowrap;
}
.onglets-vue .onglet { flex: none; }
.onglets-vue::-webkit-scrollbar { display: none; }
.onglets-vue .onglet {
    background: none;
    border: 0;
    border-bottom: 2px solid transparent;
    font-family: inherit;
    cursor: pointer;
}

/* Pastille sur l'onglet : un probleme cache derriere un onglet ferme doit se
   signaler quand meme. */
.onglet-pastille {
    display: inline-block;
    margin-left: 5px;
    min-width: 17px;
    padding: 0 5px;
    border-radius: 20px;
    background: var(--critique);
    color: #fff;
    font-size: 10.5px;
    font-weight: 700;
    line-height: 17px;
    text-align: center;
}

/* Les onglets ne se cachent QUE si le script a pris la main. Sans lui, les
   sections restent toutes visibles et la page reste utilisable — la
   degradation est une page longue, pas une page amputee. */
.est-pilote .vue-onglet { display: none; }
.est-pilote .vue-onglet.est-visible { display: block; }
.vue-onglet:not(:last-child) { margin-bottom: 12px; }
.est-pilote .vue-onglet { margin-bottom: 0; }

/* --- Bandeau chauffeur ------------------------------------------------------ */
.tete-chauffeur {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 14px;
}
.tc-identite { flex: 1 1 190px; min-width: 0; }
.tc-soldes { display: flex; gap: 16px; flex-wrap: wrap; }
.tc-solde { display: flex; flex-direction: column; font-variant-numeric: tabular-nums; min-width: 0; }
.tc-label { font-size: 10.5px; color: var(--encre-doux); }
.tc-actions { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }

@media (max-width: 620px) {
    .tete-chauffeur { gap: 10px; }
    /* Les soldes passent en grille : en flex, « Verse » et « Dette » tenaient
       sur une ligne et « Fonds » tombait seul en dessous, decale. */
    .tc-soldes {
        display: grid;
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 8px;
        width: 100%;
        padding-top: 10px;
        border-top: 1px solid var(--trait-fin);
    }
    .tc-actions { width: 100%; }
}

/* --- Exploitation : calendrier et panneau d'action -------------------------- */
/* Le calendrier ne prend plus toute la largeur : il occupe une colonne et le
   panneau d'action lui repond. Sous 900 px ils s'empilent, calendrier en
   premier — on designe le jour avant de dire ce qu'on en fait. */
.exploitation-grille {
    display: grid;
    grid-template-columns: minmax(260px, 380px) minmax(0, 1fr);
    gap: 12px;
    align-items: start;
}
@media (max-width: 900px) { .exploitation-grille { grid-template-columns: 1fr; } }

/* Choix du geste : des pastilles cliquables plutot qu'une liste deroulante.
   Un menu deroulant cache les options et demande deux gestes la ou une
   rangee en demande un. */
.pj-choix { display: flex; flex-wrap: wrap; gap: 5px; }
.pj-option {
    padding: 5px 10px;
    border-radius: 20px;
    border: 1px solid var(--trait);
    background: var(--surface);
    font-family: inherit;
    font-size: 12.5px;
    color: var(--encre-moy);
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.pj-option:hover { border-color: var(--encre-pale); }
.pj-option.est-actif {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
    font-weight: 550;
}

/* --- Fiche compacte --------------------------------------------------------- */
/* Les caracteristiques techniques ne servent qu'a la revente ou a un controle.
   Elles occupaient autant de place que la dette du chauffeur ; deux colonnes
   serrees suffisent. */
.fiche-compacte { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 0 22px; margin: 0; }
.fiche-compacte > div {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 5px 0;
    border-bottom: 1px solid var(--trait-fin);
    font-size: 12.5px;
}
.fiche-compacte dt { color: var(--encre-doux); margin: 0; }
.fiche-compacte dd { margin: 0; font-weight: 550; text-align: right; overflow-wrap: anywhere; }

/* --- Calendrier des versements ---------------------------------------------- */
/* Sur un contrat journalier, ce qu'on cherche n'est pas un paiement : c'est le
   TROU. La suite de jours sans versement, celle qui grossit pendant qu'on
   regarde ailleurs. Une liste paginee la cache — chaque page semble normale.
   Une grille mensuelle la montre d'un coup d'oeil. */
.calendrier-versements {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 3px;
}
@media (max-width: 400px) { .calendrier-versements { gap: 2px; } }

.cv-tete {
    text-align: center;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .05em;
    color: var(--encre-pale);
    padding-bottom: 2px;
}

.cv-jour {
    aspect-ratio: 1 / 1;
    border-radius: var(--rayon-badge);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1px;
    font-size: 12px;
    background: var(--fond);
    border: 1px solid transparent;
    /* min-height fixe a 40 px : sur un ecran de 360 px, sept colonnes plus les
       gouttieres depassent la largeur disponible et la grille debordait. Le
       rapport 1/1 suffit a garder des cases prenables au pouce, et elles
       retrecissent avec l ecran au lieu de le pousser. */
    min-height: 34px;
}
.cv-numero { font-weight: 600; font-variant-numeric: tabular-nums; line-height: 1; }

/* Les cases actionnables sont des boutons : le clavier doit pouvoir les
   atteindre, et un lecteur d'ecran les annoncer comme cliquables. */
button.cv-jour { font-family: inherit; cursor: pointer; padding: 0; }
button.cv-jour:hover { outline: 1px solid var(--encre-pale); }
.cv-jour.est-choisie { outline: 2px solid var(--accent); outline-offset: -2px; }

.cv-jour.est-vide   { background: transparent; }
.cv-jour.est-futur  { background: transparent; border-color: var(--trait-fin); color: var(--encre-pale); }
.cv-jour.est-paye   { background: var(--positif-pale);   color: var(--positif); }
.cv-jour.est-partiel{ background: var(--attention-pale); color: var(--attention); }
.cv-jour.est-impaye { background: var(--critique-pale);  color: var(--critique); }
.cv-jour.est-off,
.cv-jour.est-repos  { background: var(--trait-fin); color: var(--encre-pale); }
.cv-jour.est-arret  { background: #f0eef6; color: #6b5f8a; }
.cv-jour.est-fonds  { background: var(--accent-pale); color: var(--accent-fonce); }

/* Le jour jamais saisi est raye plutot que colore : il n'a pas d'etat, il a
   une absence d'etat. Une couleur unie le ferait passer pour un statut comme
   un autre. */
.cv-jour.est-manquant {
    color: var(--critique);
    border: 1px dashed var(--critique);
    background: repeating-linear-gradient(
        45deg, var(--critique-pale), var(--critique-pale) 5px, #fff 5px, #fff 10px
    );
}

/* Puces de legende du calendrier. */
.cv-puce { width: 11px; height: 11px; border-radius: 3px; flex: none; display: inline-block; }
.cv-puce.est-paye     { background: var(--positif-pale);   border: 1px solid var(--positif); }
.cv-puce.est-impaye   { background: var(--critique-pale);  border: 1px solid var(--critique); }
.cv-puce.est-manquant { background: #fff; border: 1px dashed var(--critique); }
.cv-puce.est-arret    { background: #f0eef6; border: 1px solid #6b5f8a; }
.cv-puce.est-off      { background: var(--trait-fin); border: 1px solid var(--trait); }
.cv-puce.est-fonds    { background: var(--accent-pale); border: 1px solid var(--accent); }

/* --- Liste d'exploitation --------------------------------------------------- */
/* Onglets integres au haut d'une carte : le filtre appartient a la liste
   qu'il filtre, le detacher au-dessus le fait paraitre etranger. */
.onglets-carte {
    margin-bottom: 0;
    padding: 0 14px;
    border-bottom: 1px solid var(--trait);
}

.barre-recherche {
    padding: 10px 14px;
    border-bottom: 1px solid var(--trait-fin);
}
.barre-recherche-form { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.barre-recherche .recherche { flex: 1 1 240px; max-width: none; }

/* Jetons de filtre actif. Un filtre qu'on a oublie explique une liste vide :
   il doit rester visible, et se retirer d'un clic. */
.jetons-filtres {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
    padding: 9px 14px;
    border-bottom: 1px solid var(--trait-fin);
}
.jeton {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 8px;
    border-radius: 20px;
    background: var(--fond);
    border: 1px solid var(--trait);
    font-size: 12px;
    color: var(--encre-moy);
}
.jeton a { color: var(--encre-pale); font-size: 14px; line-height: 1; text-decoration: none; }
.jeton a:hover { color: var(--critique); }
.jeton-effacer { font-size: 12px; color: var(--encre-doux); }

/* Colonne de cases a cocher : etroite, et le clic ne doit pas suivre le lien
   de la ligne. */
.col-case { width: 34px; padding-right: 0 !important; }
.col-case input { cursor: pointer; }

tr.est-selectionnee { background: var(--accent-pale); }

/* Action de ligne en lien plutot qu'en bouton. Vingt boutons pleins dans une
   colonne font un mur de couleur ou l'oeil ne sait plus se poser ; le geste
   reste a un clic sans crier. */
.lien-action {
    font-size: 12.5px;
    font-weight: 550;
    color: var(--accent-fonce);
    white-space: nowrap;
}
.lien-action:hover { text-decoration: underline; }

/* Barre d'actions de groupe. Flottante et centree, elle n'apparait que quand
   quelque chose est selectionne : une barre toujours visible mais desactivee
   occupe de la place et n'apprend rien. */
/* `display: flex` bat l'attribut `hidden` du navigateur : la barre etait donc
   VISIBLE EN PERMANENCE, y compris avec zero ligne cochee, sur telephone comme
   au bureau. Une barre d'actions de masse posee en travers d'une liste qu'on
   consulte simplement — et trois boutons destructeurs a portee de pouce. */
.barre-selection[hidden] { display: none !important; }

.barre-selection {
    position: sticky;
    bottom: 14px;
    z-index: 20;
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin: 14px;
    padding: 9px 12px;
    border-radius: var(--rayon);
    background: var(--encre);
    box-shadow: var(--ombre-haute);
}
.barre-selection-compte { font-size: 12.5px; color: #c2c9d4; font-weight: 550; }
.barre-selection .btn-neutre {
    background: rgba(255, 255, 255, .1);
    border-color: rgba(255, 255, 255, .16);
    color: #fff;
}
.barre-selection .btn-neutre:hover { background: rgba(255, 255, 255, .18); }

/* Le traitement telephone est dans mobile.css : la barre y devient une barre
   collee au bas de l'ecran, au-dessus de la navigation. L'ancienne regle
   empilait les trois boutons en pleine largeur au milieu de la liste — trois
   fois 48 px de haut, poses entre deux vehicules. C'est exactement le reflexe
   « desktop retreci » qu'on ne veut plus. */

/* --- Le choix du mode d'exploitation ----------------------------------------
   TROIS CARTES PLUTOT QU'UNE LISTE DEROULANTE. Trois options cachees derriere
   un menu demandent de l'ouvrir pour les comparer ; posees a plat, le choix se
   fait d'un regard — et c'est LE champ qui commande tout le reste du
   formulaire : ce qu'on saisit ensuite en depend. */
.choix-mode {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr));
    gap: 8px;
    border: 0;
    padding: 0;
    margin: 0;
}
.choix-mode > legend { padding: 0; margin-bottom: 6px; }

.mode-carte {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    padding: 11px 12px;
    border: 1px solid var(--trait);
    border-radius: 11px;
    background: var(--surface);
    cursor: pointer;
    transition: border-color var(--transition), background var(--transition);
}
.mode-carte:hover { border-color: var(--accent); }

/* Le bouton radio reste VISIBLE : le masquer priverait du seul indicateur
   qu'un lecteur d'ecran et un clavier savent lire, et le cadre teinte seul ne
   suffit pas a dire « choisi » a qui ne distingue pas les couleurs. */
.mode-carte input { margin-top: 2px; accent-color: var(--accent-fonce); flex: none; }

.mode-corps { display: flex; flex-direction: column; min-width: 0; }
.mode-titre { font-size: 13.5px; font-weight: 600; color: var(--encre); }
.mode-detail { font-size: 11.5px; color: var(--encre-doux); line-height: 1.35; }

.mode-carte:has(input:checked) {
    border-color: var(--accent);
    background: var(--accent-voile);
    box-shadow: inset 0 0 0 1px var(--accent);
}

/* --- Le menu du compte -------------------------------------------------------
   <details> plutot qu'un script : le repli fonctionne sans JavaScript, se
   pilote au clavier et s'annonce correctement a un lecteur d'ecran, sans qu'on
   ait rien a declarer. C'est le meme choix que les sections de la colonne. */
.menu-compte { position: relative; }
.menu-compte > summary { list-style: none; cursor: pointer; }
.menu-compte > summary::-webkit-details-marker { display: none; }
.menu-compte > summary::marker { content: ''; }

.menu-compte[open] > summary { box-shadow: 0 0 0 3px var(--accent-pale); }

.menu-compte-panneau {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 70;
    min-width: 236px;
    padding: 5px;
    border: 1px solid var(--trait);
    border-radius: 12px;
    background: var(--surface);
    box-shadow: var(--ombre-panneau);
}

.menu-compte-tete {
    display: flex;
    flex-direction: column;
    padding: 8px 10px 10px;
    border-bottom: 1px solid var(--trait-fin);
    margin-bottom: 4px;
}
.menu-compte-nom { font-size: 13px; font-weight: 600; }
.menu-compte-role { font-size: 11.5px; color: var(--encre-pale); }

.menu-compte-lien {
    display: flex;
    align-items: center;
    gap: 9px;
    width: 100%;
    padding: 8px 10px;
    border: 0;
    border-radius: 8px;
    background: none;
    font-family: inherit;
    font-size: 13px;
    color: var(--encre-moy);
    text-decoration: none;
    text-align: left;
    cursor: pointer;
}
.menu-compte-lien:hover { background: var(--fond); color: var(--encre); }
.menu-compte-lien .ico { color: var(--encre-pale); }
.menu-compte-lien:hover .ico { color: var(--accent-fonce); }

/* La deconnexion est separee et sourde : c'est la seule action du menu qu'on
   ne veut pas presser par erreur en visant sa voisine. */
.menu-compte-lien.est-sortie {
    margin-top: 4px;
    border-top: 1px solid var(--trait-fin);
    border-radius: 0 0 8px 8px;
    color: var(--critique);
}
.menu-compte-lien.est-sortie:hover { background: var(--critique-pale); color: var(--critique); }
.menu-compte-lien.est-sortie .ico { color: var(--critique); }

/* --- Les suggestions de la recherche -----------------------------------------
   Elles se posent SOUS le champ, alignees sur lui, et prennent sa largeur : une
   liste plus etroite que son champ donne l'impression qu'elle appartient a
   autre chose. */
.entete-recherche { position: relative; }

.suggestions {
    position: absolute;
    top: calc(100% + 6px);
    left: 0; right: 0;
    z-index: 60;
    max-height: 320px;
    overflow-y: auto;
    padding: 4px;
    border: 1px solid var(--trait);
    border-radius: 12px;
    background: var(--surface);
    box-shadow: var(--ombre-panneau);
}

.suggestion {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: baseline;
    gap: 8px;
    padding: 8px 10px;
    border-radius: 8px;
    text-decoration: none;
    color: var(--encre);
    font-size: 13px;
}
/* Le survol ET la selection au clavier partagent le meme fond : deux etats
   distincts pour une meme intention font croire a deux choses differentes. */
.suggestion:hover,
.suggestion.est-vise { background: var(--accent-voile); }

.suggestion-genre {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--accent-fonce);
    background: var(--accent-pale);
    padding: 2px 6px;
    border-radius: 5px;
}
.suggestion-t { font-weight: 550; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.suggestion-d {
    font-size: 11.5px;
    color: var(--encre-pale);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* --- Hors ligne --------------------------------------------------------------
   En 3G ivoirienne la connexion tombe et revient sans prevenir. Sans signal,
   on remplit un formulaire, il echoue, et on croit l'application cassee. Le
   bandeau dit que le probleme est le reseau — et il part tout seul au retour.

   Il se pose EN BAS et non en haut : en haut il recouvrirait la barre
   d'application, donc le bouton retour, au moment precis ou l'on cherche a
   sortir de la page qui ne repond pas. */
.bandeau-reseau {
    position: fixed;
    left: 12px; right: 12px;
    bottom: calc(12px + env(safe-area-inset-bottom, 0px));
    z-index: 900;
    padding: 11px 14px;
    border-radius: 12px;
    background: var(--encre);
    color: #fff;
    font-size: 12.5px;
    font-weight: 500;
    line-height: 1.35;
    box-shadow: 0 6px 24px rgba(15, 42, 46, .3);
    animation: bandeau-monte 240ms cubic-bezier(.2, .8, .2, 1);
}
@keyframes bandeau-monte { from { transform: translateY(120%); } to { transform: translateY(0); } }

/* Sur telephone la barre de navigation flotte deja en bas : le bandeau se
   pose au-dessus d'elle plutot que par-dessus. */
@media (max-width: 900px) {
    .bandeau-reseau { bottom: calc(var(--nav-basse, 58px) + 22px + env(safe-area-inset-bottom, 0px)); }
}

/* --- Un bouton qui a parti le dit --------------------------------------------
   Un bouton d'envoi qui ne change pas d'aspect invite a recliquer. Sur un
   formulaire d'argent, recliquer c'est encaisser deux fois — et le reseau lent
   d'une cour de garage rend ce double clic tres probable.

   Le libelle NE CHANGE PAS : le remplacer par « Envoi… » fait sauter la
   largeur du bouton et deplace ce qui l'entoure. C'est l'opacite et le curseur
   qui parlent, plus un disque qui tourne. */
.btn.est-en-cours,
.btn-discret.est-en-cours {
    position: relative;
    color: transparent !important;
    pointer-events: none;
}
.btn.est-en-cours::after,
.btn-discret.est-en-cours::after {
    content: '';
    position: absolute;
    inset: 0;
    margin: auto;
    width: 15px; height: 15px;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    color: #fff;
    animation: tourne 620ms linear infinite;
}
.btn-neutre.est-en-cours::after,
.btn-discret.est-en-cours::after { color: var(--encre-moy); }

@keyframes tourne { to { transform: rotate(360deg); } }

/* Le mouvement disparait pour qui l'a demande. Une animation en boucle est
   exactement ce que `prefers-reduced-motion` vise. */
@media (prefers-reduced-motion: reduce) {
    .btn.est-en-cours::after, .btn-discret.est-en-cours::after { animation: none; }
    .bandeau-reseau { animation: none; }
}

/* --- Le raccourci, annonce ---------------------------------------------------
   Un raccourci que personne ne connait n'existe pas. La touche est dessinee
   dans le champ, et s'efface des qu'on y tape. */
.entete-recherche-touche {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 1px;
    padding: 1px 5px;
    border: 1px solid var(--trait);
    border-bottom-width: 2px;
    border-radius: 5px;
    background: var(--surface);
    color: var(--encre-pale);
    font-size: 10.5px;
    font-weight: 600;
    font-family: var(--police);
}
.entete-recherche:focus-within .entete-recherche-touche { display: none; }

/* --- En-tete de colonne triable ----------------------------------------------
   LA FLECHE N'APPARAIT QUE SUR LA COLONNE ACTIVE. Une fleche grise sur chaque
   en-tete transforme la ligne de titres en guirlande et on ne voit plus
   laquelle est active — ce qui est justement l'information utile. La
   possibilite de trier se decouvre au survol, comme partout ailleurs. */
.th-tri { padding: 0 !important; }
.th-tri > a {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 9px 10px;
    color: inherit;
    text-decoration: none;
    white-space: nowrap;
}
.th-tri.nombre > a { justify-content: flex-end; }
.th-tri > a:hover { color: var(--encre); background: var(--trait-fin); }

.th-tri-fleche { opacity: 0; font-size: 10px; transition: opacity var(--transition); }
.th-tri > a:hover .th-tri-fleche { opacity: .4; }
.th-tri.est-actif > a { color: var(--accent-fonce); font-weight: 650; }
.th-tri.est-actif .th-tri-fleche { opacity: 1; }

/* --- Tableau dense ---------------------------------------------------------- */
/* Une liste d'exploitation se parcourt, elle ne se lit pas ligne a ligne. Des
   lignes plus serrees font tenir vingt vehicules dans un ecran au lieu de
   douze, ce qui evite un defilement a chaque consultation. */
.tableau-dense th { padding-top: 9px; padding-bottom: 9px; }
.tableau-dense td { padding-top: 8px; padding-bottom: 8px; }
.tableau-dense .cellule-detail { margin-top: 1px; }

/* Signaux d'alerte empiles dans une cellule. */
.signaux { display: flex; flex-wrap: wrap; gap: 3px; align-items: center; }

/* --- Fiches (paires libellé / valeur) -------------------------------------- */
.fiche-ligne {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 16px;
    padding: 7px 0;
    border-bottom: 1px solid var(--trait-fin);
}
.fiche-ligne:last-child { border-bottom: 0; }
/* Quand la valeur est un badge et non du texte : centrer sur la hauteur,
   sinon le badge pend sous la ligne de base du libellé. */
.fiche-ligne.est-centree { align-items: center; padding: 9px 0; }
.fiche-ligne > span:last-child { min-width: 0; overflow-wrap: anywhere; }

/* --- Jauge ----------------------------------------------------------------- */
.jauge { height: 5px; background: var(--trait-fin); border-radius: 3px; overflow: hidden; margin-top: 6px; }
.jauge-barre { height: 100%; border-radius: 3px; transition: width var(--transition); }

/* --- Intertitre de section dans une carte ---------------------------------- */
/* Sépare les blocs d'un compte de résultat sans ajouter une carte de plus. */
.sous-titre {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--encre-doux);
    margin-bottom: 6px;
}
.sous-titre + * { margin-top: 0; }
.sous-titre:not(:first-child) { margin-top: 16px; }

/* --- Histogramme mensuel --------------------------------------------------- */
/* Douze mois côte à côte, recettes contre charges. Volontairement sans
   bibliothèque : deux div par mois suffisent, et rien à télécharger. */
.histo { display: flex; align-items: flex-end; gap: 6px; height: 180px; padding-top: 8px; }

.histo-mois {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    height: 100%;
    min-width: 0;
}

.histo-paire { flex: 1; display: flex; align-items: flex-end; gap: 2px; width: 100%; }

.histo-barre {
    flex: 1;
    border-radius: 2px 2px 0 0;
    min-height: 1px;
    transition: height var(--transition);
}
.histo-barre.est-recette { background: var(--accent); }
.histo-barre.est-charge  { background: var(--trait); }

.histo-label { font-size: 9.5px; color: var(--encre-doux); font-variant-numeric: tabular-nums; }

.legende { display: flex; gap: 12px; align-items: center; margin-top: 12px; font-size: 12px; color: var(--encre-moy); flex-wrap: wrap; }
.legende-item { display: inline-flex; align-items: center; gap: 5px; }
.legende-puce { width: 10px; height: 10px; border-radius: 2px; flex: none; }
.legende-puce.est-recette { background: var(--accent); }
.legende-puce.est-charge  { background: var(--trait); }
.legende-puce.est-confirmee { background: var(--accent-pale); }
.legende-puce.est-attente   { background: var(--attention-pale); }
/* Pastille dont la couleur vient de la base (zones GPS) : seule la teinte
   reste en ligne, le reste est ici. */
.legende-puce.est-zone { width: 12px; height: 12px; border-radius: 3px; }

/* --- Grilles --------------------------------------------------------------- */

.grille-2 {
    display: grid;
    grid-template-columns: minmax(280px, 340px) minmax(0, 1fr);
    gap: 14px;
    align-items: start;
}

@media (max-width: 900px) { .grille-2 { grid-template-columns: 1fr; } }

/* --- Liste d'actions (tableau de bord) ------------------------------------- */
/* Remplace la rangée de badges colorés : une liste se parcourt, une rangée
   de pastilles se subit. *

/* --- Page d'authentification ----------------------------------------------- */
/* =============================================================================
   LES ECRANS PUBLICS — connexion et inscription
   =============================================================================
   LES PROPORTIONS ETAIENT INVERSEES.

   `flex: 1` sur le panneau de gauche contre `max-width: 430px` a droite : sur
   un ecran de 1440, le visuel prenait mille pixels pour trois lignes de texte,
   et le FORMULAIRE — la seule chose qu'on vient faire ici — se retrouvait
   comprime dans une colonne de 430 px collee au bord droit. C'est la premiere
   page que voit un prospect, et elle donnait l'impression d'un encart publicitaire
   avec un formulaire en marge.

   La regle : le formulaire ne descend jamais sous 46 % de la largeur, et le
   visuel ne depasse jamais 54 %. Au-dela de 1500 px l'ensemble se centre au
   lieu de s'etirer — un champ de saisie de 700 px ne se lit pas mieux qu'un de
   400, il fait juste vide.
   ========================================================================== */
.auth { min-height: 100vh; display: flex; background: var(--surface); }

.auth-visuel {
    flex: 0 1 54%;
    background: var(--encre);
    color: #fff;
    padding: 48px 5vw;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.auth-visuel h2 { font-size: 27px; letter-spacing: -.024em; margin-bottom: 12px; max-width: 15ch; font-weight: 650; }
.auth-visuel p { color: #99a2b0; font-size: 14px; max-width: 42ch; line-height: 1.6; }

.auth-arguments { margin-top: 34px; display: flex; flex-direction: column; gap: 13px; }
.auth-argument { display: flex; gap: 11px; align-items: flex-start; font-size: 13.5px; color: #c2c9d4; }
.auth-argument::before {
    content: '';
    flex: none;
    width: 5px; height: 5px;
    margin-top: 8px;
    border-radius: 50%;
    background: var(--accent);
}

.auth-panneau {
    flex: 1 1 46%;
    padding: 44px 40px;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

/* Le contenu du formulaire se centre dans sa moitie et garde une largeur de
   lecture : c'est la colonne qui s'elargit, pas les champs. */
.auth-panneau > * { width: 100%; max-width: 420px; margin-left: auto; margin-right: auto; }

/* LE NOM DU PRODUIT, A LA TAILLE D'UN NOM DE PRODUIT. En 18 px il se lisait
   comme une etiquette de champ — sur la page d'inscription, c'est pourtant la
   seule chose qui dit chez qui on est. */
.auth-logo {
    font-size: 24px;
    font-weight: 700;
    letter-spacing: -.03em;
    margin-bottom: 26px;
    color: var(--encre);
}
.auth-titre { font-size: 21px; margin-bottom: 4px; font-weight: 650; }
.auth-intro { font-size: 13.5px; color: var(--encre-doux); margin-bottom: 24px; line-height: 1.55; }
.auth-bas { margin-top: 22px; font-size: 13px; color: var(--encre-doux); text-align: center; }

/* Le visuel a de la place : il peut en dire un peu plus. */
@media (min-width: 1100px) {
    .auth-visuel h2 { font-size: 34px; }
    .auth-visuel p  { font-size: 15px; }
}

@media (max-width: 900px) {
    .auth-visuel { display: none; }
    .auth-panneau { flex: 1 1 auto; padding: 28px 20px; }
}

/* --- Assistant par etapes -------------------------------------------------- */
/* Un formulaire de vehicule compte vingt-cinq champs. Presentes d'un bloc, ils
   font une page de defilement ou l'on ne sait plus ce qui reste a remplir.
   Decoupes en etapes, chacune tient dans un ecran et l'on voit ou l'on en est.

   Sans JavaScript, toutes les etapes restent visibles et le formulaire
   fonctionne comme avant : la degradation est un formulaire long, pas un
   formulaire casse. */
.assistant { max-width: 880px; }

.assistant-jauge {
    display: flex;
    align-items: center;
    gap: 0;
    margin-bottom: 22px;
    counter-reset: etape;
}

.assistant-etape-puce {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: none;
}

.assistant-numero {
    width: 26px; height: 26px;
    flex: none;
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-size: 12px;
    font-weight: 600;
    background: var(--surface);
    border: 1px solid var(--trait);
    color: var(--encre-pale);
    transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.assistant-libelle {
    font-size: 12.5px;
    color: var(--encre-pale);
    white-space: nowrap;
    transition: color var(--transition);
}

/* Etape courante */
.assistant-etape-puce.est-active .assistant-numero {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
}
.assistant-etape-puce.est-active .assistant-libelle { color: var(--encre); font-weight: 550; }

/* Etape deja franchie : la coche remplace le numero, ce qui distingue d'un
   coup d'oeil ce qui est fait de ce qui reste. */
.assistant-etape-puce.est-faite .assistant-numero {
    background: var(--accent-pale);
    border-color: var(--accent-pale);
    color: var(--accent-fonce);
    font-size: 0;
}
.assistant-etape-puce.est-faite .assistant-numero::after {
    /* ECHAPPEMENT CSS et non le caractere lui-meme : ecrit en clair, la coche
       s'etait corrompue en « ¹3 » lors d'un passage d'encodage, et l'etape
       franchie affichait deux caracteres sans signification. `¹3` traverse
       n'importe quelle conversion. */
    content: '¹3';
    font-size: 13px;
    line-height: 1;
}
.assistant-etape-puce.est-faite .assistant-libelle { color: var(--encre-moy); }

.assistant-trait {
    flex: 1 1 auto;
    height: 1px;
    background: var(--trait);
    margin: 0 10px;
    min-width: 12px;
}
.assistant-etape-puce.est-faite ~ .assistant-trait { background: var(--accent-pale); }

/* Sur mobile, seuls les numeros tiennent : les libelles passeraient a la
   ligne et la jauge occuperait un tiers de l'ecran. */
@media (max-width: 720px) {
    .assistant-libelle { display: none; }
    .assistant-trait { margin: 0 4px; }
}

.assistant-panneau { display: none; }
.assistant-panneau.est-visible { display: block; }

/* Sans JavaScript, aucun panneau ne porte est-visible : on les montre tous
   plutot que d'afficher une page vide. */
.assistant:not(.est-pilote) .assistant-panneau { display: block; margin-bottom: 14px; }
.assistant:not(.est-pilote) .assistant-jauge,
.assistant:not(.est-pilote) .assistant-pied { display: none; }
.assistant:not(.est-pilote) .assistant-final { display: block; }

.assistant-pied {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 18px;
    padding-top: 16px;
    border-top: 1px solid var(--trait);
}
.assistant-compte { font-size: 12.5px; color: var(--encre-doux); }

/* Encart de calcul en direct. Montrer ce qu'un capital represente par mois
   transforme deux nombres abstraits en une decision : l'exploitant voit
   immediatement si le vehicule peut se rembourser. */
.encart-calcul {
    background: var(--accent-pale);
    border-radius: var(--rayon-champ);
    padding: 10px 12px;
}
.encart-calcul .gras { color: var(--accent-fonce); font-variant-numeric: tabular-nums; }

/* --- Tunnel de prospection ------------------------------------------------- */
/* Des colonnes et non un tableau : un tunnel de vente se lit de gauche a
   droite, et la hauteur de chaque colonne dit d'un coup d'oeil ou les affaires
   s'accumulent. Un tableau trie par date ne montrerait jamais qu'on a douze
   propositions en attente et rien en negociation. */
.tunnel {
    display: grid;
    grid-template-columns: repeat(5, minmax(180px, 1fr));
    gap: 12px;
    align-items: start;
    overflow-x: auto;
    padding-bottom: 6px;
}
@media (max-width: 1100px) {
    .tunnel { grid-template-columns: repeat(5, minmax(200px, 1fr)); }
}

.tunnel-colonne {
    background: #fbfbfc;
    border: 1px solid var(--trait);
    border-radius: var(--rayon);
    padding: 10px;
    min-width: 0;
}

.tunnel-tete { display: flex; align-items: center; gap: 8px; }
.tunnel-titre {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--encre-doux);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}
.tunnel-compte {
    margin-left: auto;
    flex: none;
    background: var(--surface);
    border: 1px solid var(--trait);
    border-radius: 20px;
    padding: 0 7px;
    font-size: 11px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.tunnel-valeur {
    font-size: 11.5px;
    color: var(--encre-doux);
    font-variant-numeric: tabular-nums;
    margin-top: 2px;
}
.tunnel-cartes { display: flex; flex-direction: column; gap: 7px; margin-top: 10px; }
.tunnel-vide { text-align: center; color: var(--encre-pale); font-size: 13px; padding: 10px 0; }

/* Une affaire. Cliquable en entier : viser un lien de trois mots dans une
   carte de la taille d'un pouce est une source d'agacement quotidienne. */
.affaire {
    display: block;
    background: var(--surface);
    border: 1px solid var(--trait);
    border-radius: var(--rayon-champ);
    padding: 9px 10px;
    color: inherit;
    transition: border-color var(--transition), box-shadow var(--transition);
}
.affaire:hover { border-color: var(--accent); box-shadow: var(--ombre); }

/* Le liseré remplace un badge « en retard » : il se voit sans etre lu, et
   n'ajoute pas une ligne de texte a une carte deja dense. */
.affaire.est-en-retard { border-left: 3px solid var(--critique); }

.affaire-nom { font-size: 13px; font-weight: 600; line-height: 1.3; }
.affaire-detail { font-size: 11.5px; color: var(--encre-doux); margin-top: 2px; }
.affaire-pied {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 8px;
    margin-top: 6px;
    font-size: 12px;
    font-variant-numeric: tabular-nums;
}
.affaire-relance { font-size: 11px; color: var(--encre-doux); margin-top: 4px; }

/* --- Journal d'echanges ---------------------------------------------------- */
/* Un fil vertical : l'ordre chronologique est l'information principale. */
.fil { position: relative; padding-left: 18px; }
.fil::before {
    content: '';
    position: absolute;
    left: 4px; top: 6px; bottom: 6px;
    width: 1px;
    background: var(--trait);
}
.fil-entree { position: relative; padding: 0 0 16px; }
.fil-entree:last-child { padding-bottom: 0; }
.fil-entree::before {
    content: '';
    position: absolute;
    left: -18px; top: 5px;
    width: 9px; height: 9px;
    border-radius: 50%;
    background: var(--surface);
    border: 2px solid var(--accent);
}
.fil-tete { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.fil-resume { font-size: 13px; margin-top: 3px; line-height: 1.5; overflow-wrap: anywhere; }

/* --- Pilotage du moteur ---------------------------------------------------- */
/* Separe visiblement du reste de la fiche : c'est la seule commande de
   l'application qui agisse sur un vehicule reel, avec quelqu'un dedans. Le
   liseré teinté dit « ici, on ne clique pas distraitement ». */
.pilotage {
    border-top: 1px solid var(--trait);
    padding-top: 14px;
}
.pilotage .btn-danger { border-color: #eddcda; }
.pilotage .btn[disabled] { opacity: .45; cursor: not-allowed; }

/* --- Carte GPS ------------------------------------------------------------- */
.carte-gps { flex: 1; min-width: 0; }

/* Rejeu de parcours dans la page Historique. Hauteur fixe plutot que
   plein ecran : le tableau des journees doit rester atteignable sans
   defiler longuement. */
.carte-trajet { height: 420px; width: 100%; }
@media (max-width: 700px) { .carte-trajet { height: 300px; } }
.gps-liste { width: 290px; flex: none; border-right: 1px solid var(--trait); background: var(--surface); overflow-y: auto; }

/* Marqueur de véhicule sur la carte. Seule la couleur de fond reste posée par
   le script : elle dépend de l'état du boîtier, pas de la mise en forme. */
.marqueur {
    width: 26px; height: 26px;
    border-radius: 50%;
    border: 3px solid #fff;
    box-shadow: 0 1px 4px rgba(15, 23, 42, .4);
    display: flex; align-items: center; justify-content: center;
    color: #fff;
    font-size: 10px;
    font-weight: 700;
}

@media (max-width: 860px) { .gps-liste { display: none; } }

/* --- Calendrier ------------------------------------------------------------ */
.calendrier {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 1px;
    background: var(--trait);
    border: 1px solid var(--trait);
    border-radius: var(--rayon);
    overflow: hidden;
}

/* --- Utilitaires ----------------------------------------------------------- */
.muet { color: var(--encre-doux); }
.petit { font-size: 12px; }
.grand { font-size: 15px; }
.gras { font-weight: 600; }
.chiffres { font-variant-numeric: tabular-nums; }
.droite { text-align: right; }
.gauche { text-align: left; }
.majuscules { text-transform: uppercase; }
.centre { text-align: center; }
.nowrap { white-space: nowrap; }

.pile { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.rangee { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.rangee.est-centree { justify-content: center; }
.rangee.est-espacee { justify-content: space-between; }
.rangee.est-serree  { gap: 5px; }
.espace { flex: 1; }
.mb-6  { margin-bottom: 6px; }
.mb-8  { margin-bottom: 8px; }
.mb-12 { margin-bottom: 12px; }
.mb-16 { margin-bottom: 16px; }
.mb-24 { margin-bottom: 22px; }

@media (max-width: 640px) { .cache-mobile { display: none; } }

.sr-only {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* --- Impression ------------------------------------------------------------ */
/* =============================================================================
   FICHE VEHICULE — fonds, vidange, frise
   ============================================================================= */

/* --- Solde du fonds de garantie --------------------------------------------- */
/* Un seul chiffre en grand, parce qu'il n'y en a qu'un qui compte : ce que le
   chauffeur a encore devant lui. Les cumuls qui le composent se lisent en
   dessous, en lignes de fiche. */
.fonds-solde {
    display: flex;
    align-items: baseline;
    gap: 8px;
    flex-wrap: wrap;
    padding-bottom: 10px;
    margin-bottom: 4px;
    border-bottom: 1px solid var(--trait-fin);
}
.fonds-montant {
    font-size: 24px;
    font-weight: 680;
    letter-spacing: -.03em;
    font-variant-numeric: tabular-nums;
    overflow-wrap: anywhere;
}
.fonds-note { font-size: 11.5px; color: var(--encre-doux); }

/* --- Etat de la vidange ------------------------------------------------------ *

/* --- Frise des evenements ---------------------------------------------------- */
/* UNE FRISE, PAS UN TABLEAU. Un entretien, une amende et un depot de fonds
   n'ont pas les memes colonnes : les forcer dans une grille produirait des
   cases vides partout. Ici chaque ligne porte ce qu'elle a, et la pastille de
   couleur dit de quelle nature il s'agit sans ajouter une colonne. */
.frise { display: flex; flex-direction: column; }

.frise-mois {
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--encre-pale);
    padding: 12px 0 5px;
    position: sticky;
    top: 0;
    background: var(--surface);
    z-index: 1;
}
.frise-mois:first-child { padding-top: 0; }

.frise-ligne {
    display: flex;
    align-items: baseline;
    gap: 10px;
    padding: 6px 0;
    border-bottom: 1px solid var(--trait-fin);
    font-size: 12.5px;
    min-width: 0;
}
.frise-ligne:last-child { border-bottom: 0; }

.frise-date {
    flex: none;
    width: 40px;
    font-size: 11px;
    color: var(--encre-pale);
    font-variant-numeric: tabular-nums;
}

.frise-puce {
    flex: none;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--trait);
    /* baseline sur un element vide le colle en bas de ligne : ce decalage le
       remonte a hauteur du texte. */
    transform: translateY(-1px);
}
.frise-puce.est-entretien { background: var(--attention); }
.frise-puce.est-charge    { background: var(--critique); }
.frise-puce.est-location  { background: var(--positif); }
.frise-puce.est-amende    { background: #6b5f8a; }
.frise-puce.est-fonds     { background: var(--accent); }
.frise-puce.est-chauffeur { background: var(--encre-pale); }

.frise-corps { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.frise-titre { font-weight: 550; overflow-wrap: anywhere; }
.frise-detail { font-size: 11px; color: var(--encre-doux); overflow-wrap: anywhere; }

.frise-montant {
    flex: none;
    font-variant-numeric: tabular-nums;
    font-weight: 550;
    white-space: nowrap;
}

@media (max-width: 480px) {
    .frise-date { width: 34px; font-size: 10.5px; }
    .frise-ligne { gap: 7px; }
}

/* --- Utilitaires manquants --------------------------------------------------- */
.mt-12 { margin-top: 12px; }
.mb-10 { margin-bottom: 10px; }

/* Pile dense : pour un formulaire d'action ou 14 px entre chaque champ etire
   la carte bien au-dela de son contenu. */
.pile.est-serree { gap: 10px; }

/* Rangee de champs : les libelles ont des hauteurs differentes, un
   align-items: center laisserait les saisies en escalier. */
.rangee.est-bas { align-items: flex-end; }

/* =============================================================================
   LOCATIONS — nature du dossier, frise du calendrier
   ============================================================================= */

/* --- Choix reservation / location -------------------------------------------- */
/* Deux cartes cliquables plutot que deux boutons radio nus : la difference
   entre reserver et louer se joue sur une phrase, pas sur un mot. Un radio
   suivi d'un libelle court obligerait a deviner ce que chacun declenche. */
.choix-nature { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 10px; }

.nature-option {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 11px 13px;
    border: 1px solid var(--trait);
    border-radius: var(--rayon);
    cursor: pointer;
    transition: border-color var(--transition), background var(--transition);
}
.nature-option:hover { border-color: var(--encre-pale); }
.nature-option.est-actif { border-color: var(--accent); background: var(--accent-pale); }

/* Le radio reste dans le flux pour le clavier et les lecteurs d'ecran, mais
   n'occupe aucune place : c'est la carte entiere qui sert de cible. */
.nature-option input { position: absolute; opacity: 0; width: 0; height: 0; }
.nature-option:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Fermee, pas cachee. « A planifier » n'a aucun sens sur un plein de carburant,
   mais la retirer de la page ferait disparaitre une option au moment ou l'on
   change de nature — on croirait a un bug. Elle reste lisible et refuse le
   clic, ce qui apprend la regle au lieu de la subir. */
.nature-option.est-fermee {
    opacity: .42;
    cursor: not-allowed;
    background: var(--fond);
}
.nature-option.est-fermee:hover { border-color: var(--trait); }

.nature-titre { font-weight: 600; font-size: 13px; }
.nature-note  { font-size: 11.5px; color: var(--encre-doux); line-height: 1.45; }

/* --- Alertes ----------------------------------------------------------------
   Une liste d'alertes n'est pas un tableau : chaque ligne porte une action, et
   une action ne tient pas dans une cellule. D'ou des cartes fines, empilees,
   ou le geste suivant est a portee du regard qui vient de lire le message.
   ------------------------------------------------------------------------- */

/* Ce qui precede un vol se lit AVANT tout le reste, ou ne se lit pas. */
.bandeau-critique {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 10px 13px;
    margin-bottom: 12px;
    background: var(--critique-pale);
    border: 1px solid #eddcda;
    border-radius: var(--rayon);
    font-size: 12.5px;
    color: var(--critique);
    line-height: 1.45;
}
.bandeau-critique-n {
    flex: none;
    display: grid;
    place-items: center;
    min-width: 26px; height: 26px;
    padding: 0 6px;
    border-radius: 13px;
    background: var(--critique);
    color: #fff;
    font-size: 13px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.barre-alertes {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 12px;
}
.filtres-alertes { display: flex; flex-wrap: wrap; gap: 5px; flex: 1; min-width: 0; }

.puce-filtre {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    font-size: 12px;
    color: var(--encre-doux);
    background: var(--surface);
    border: 1px solid var(--trait);
    border-radius: 20px;
    transition: all var(--transition);
}
.puce-filtre:hover { color: var(--encre); border-color: var(--encre-pale); }
.puce-filtre.est-actif {
    background: var(--accent-pale);
    border-color: var(--accent);
    color: var(--accent-fonce);
}
.puce-n { font-weight: 600; font-variant-numeric: tabular-nums; }

.pile-alertes { display: flex; flex-direction: column; gap: 7px; }

.alerte {
    display: flex;
    background: var(--surface);
    border: 1px solid var(--trait);
    border-radius: var(--rayon);
    overflow: hidden;
}

/* Le rail porte la gravite. Un fond teinte sur quarante lignes fait une
   guirlande ou plus rien ne ressort ; un filet de 3 px se voit sans crier. */
.alerte-rail { flex: none; width: 3px; background: var(--encre-pale); }
.alerte.est-critique .alerte-rail { background: var(--critique); }
.alerte.est-alerte   .alerte-rail { background: var(--attention); }
.alerte.est-info     .alerte-rail { background: var(--encre-pale); }

/* Une alerte classee reste lisible mais recule : c'est de l'historique, pas
   du travail en attente. */
.alerte.est-classee { background: var(--fond); }
.alerte.est-classee .alerte-rail { opacity: .35; }

.alerte-corps { flex: 1; min-width: 0; padding: 9px 12px; }

.alerte-tete { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }
.alerte-type {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .02em;
    text-transform: uppercase;
    color: var(--encre-moy);
}
.alerte.est-critique .alerte-type { color: var(--critique); }
.alerte-vehicule { font-size: 12.5px; font-weight: 600; }
.alerte-vehicule .chiffres { font-weight: 400; font-size: 11.5px; margin-left: 5px; }
.alerte-quand { font-size: 11.5px; color: var(--encre-pale); white-space: nowrap; }

.alerte-message {
    margin: 3px 0 0;
    font-size: 12.5px;
    line-height: 1.45;
    color: var(--encre);
}

.alerte-classee {
    margin-top: 5px;
    font-size: 11.5px;
    color: var(--encre-pale);
}
.alerte-note { color: var(--encre-doux); font-style: italic; }

/* AGIR AVANT DE CLASSER : voir ou c'etait, appeler celui qui conduit, ouvrir
   l'historique. Les mettre ailleurs oblige a ouvrir un onglet et a perdre la
   ligne qu'on etait en train de traiter. */
/* Les trois gestes qui suivent la lecture d'une alerte, groupes : voir ou
   c'etait, appeler celui qui conduit, ouvrir l'historique. Le groupe existe
   pour le telephone, ou ils occupent leur propre rangee ; au bureau il se
   fond dans la rangee d'actions. */
.alerte-gestes { display: contents; }

.alerte-actions {
    display: flex;
    align-items: center;
    gap: 7px;
    flex-wrap: wrap;
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid var(--trait-fin);
}
.alerte-note-saisie {
    flex: 1;
    min-width: 150px;
    padding: 5px 9px;
    font-size: 12px;
}

/* LE TRAITEMENT TELEPHONE EST DANS mobile.css, PAS ICI.
   Ce bloc y forcait le champ de note sur sa propre ligne (`flex-basis: 100%`),
   ce qui donnait quatre rangees par alerte et deux alertes par ecran. C'est
   exactement la regle qu'on ne veut plus voir dans ce fichier : elle reduisait
   des tailles au lieu de repenser un geste, et elle se battait ensuite avec
   celle de mobile.css. */

/* --- Carte de suivi ---------------------------------------------------------
   Une carte de flotte se lit a la hauteur de l'ecran : reduire la vue pour
   loger une liste a cote fait perdre le contexte geographique, qui est la
   seule raison d'ouvrir cette page. La liste est donc une colonne fine, et la
   carte prend tout le reste.
   ------------------------------------------------------------------------- */
.gps-plan {
    display: grid;
    grid-template-columns: 292px minmax(0, 1fr);
    gap: 12px;
    /* 100vh moins l'en-tete, la tete de page et les onglets. Une hauteur fixe
       en pixels casserait des que le titre passe sur deux lignes. */
    height: calc(100vh - 210px);
    min-height: 460px;
}
.gps-plan:fullscreen { height: 100vh; min-height: 0; padding: 10px; background: var(--fond); }

.gps-flotte {
    display: flex;
    flex-direction: column;
    min-height: 0;
    background: var(--surface);
    border: 1px solid var(--trait);
    border-radius: var(--rayon);
    overflow: hidden;
}
.gps-flotte-tete { padding: 10px; border-bottom: 1px solid var(--trait-fin); }
.gps-recherche { padding: 7px 10px; font-size: 12.5px; }

/* Les compteurs SONT les filtres. Un bandeau qui annonce « 3 muets » sans
   permettre de les isoler oblige a parcourir toute la liste pour les
   retrouver — et sur cent vehicules on ne le fait pas. */
.gps-filtres { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 8px; }
.gps-filtre {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 8px;
    font-size: 11px;
    font-family: inherit;
    color: var(--encre-doux);
    background: var(--fond);
    border: 1px solid transparent;
    border-radius: 20px;
    cursor: pointer;
    transition: all var(--transition);
}
.gps-filtre:hover:not(:disabled) { border-color: var(--trait); color: var(--encre); }
.gps-filtre.est-actif { background: var(--accent-pale); border-color: var(--accent); color: var(--accent-fonce); }
.gps-filtre:disabled { opacity: .4; cursor: default; }
.gps-filtre-n { font-weight: 600; font-variant-numeric: tabular-nums; }

.gps-liste { flex: 1; overflow-y: auto; min-height: 0; }
.gps-vide { padding: 22px 14px; font-size: 12px; color: var(--encre-pale); text-align: center; }

.gps-ligne {
    display: block;
    width: 100%;
    text-align: left;
    padding: 8px 11px;
    border: 0;
    border-bottom: 1px solid var(--trait-fin);
    border-left: 2px solid transparent;
    background: none;
    font-family: inherit;
    cursor: pointer;
    transition: background var(--transition);
}
.gps-ligne:hover { background: var(--fond); }
.gps-ligne.est-choisie { background: var(--accent-pale); border-left-color: var(--accent); }
.gps-ligne.est-signalee { border-left-color: var(--critique); }

.gps-ligne-tete { display: flex; align-items: center; gap: 7px; }
.gps-ligne-nom {
    flex: 1;
    min-width: 0;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--encre);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.gps-ligne-bas {
    display: flex;
    align-items: baseline;
    gap: 7px;
    margin-top: 2px;
    font-size: 11px;
    color: var(--encre-pale);
}
.gps-ligne-bas .chiffres { flex: 1; min-width: 0; }
.gps-ligne-quand { white-space: nowrap; }
.gps-ligne-lieu {
    display: block;
    margin-top: 3px;
    font-size: 11px;
    color: var(--encre-doux);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* La vitesse porte l'etat : afficher « 62 km/h » a cote d'une pastille
   « En route » dit deux fois la meme chose et prend deux fois la place. */
.gps-jauge {
    padding: 1px 7px;
    border-radius: var(--rayon-badge);
    font-size: 10.5px;
    font-weight: 600;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
.gps-jauge.est-roule   { background: var(--positif-pale); color: var(--positif); }
.gps-jauge.est-ralenti { background: var(--attention-pale); color: var(--attention); }
.gps-jauge.est-arret   { background: var(--trait-fin); color: var(--encre-doux); }
.gps-jauge.est-muet    { background: var(--critique-pale); color: var(--critique); }
.gps-jauge.est-inconnu { background: var(--trait-fin); color: var(--encre-pale); }

.gps-flotte-pied {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 7px 11px;
    border-top: 1px solid var(--trait-fin);
    background: var(--fond);
}

/* Le pouls dit que le flux vit. Une carte figee et une carte a jour se
   ressemblent exactement quand rien ne bouge — et c'est precisement la nuit,
   quand rien ne devrait bouger, qu'on a besoin de faire la difference. */
.gps-pouls {
    width: 7px; height: 7px;
    border-radius: 50%;
    background: var(--positif);
    flex: none;
    animation: gps-battement 2.4s ease-in-out infinite;
}
.gps-pouls.est-perdu { background: var(--critique); animation: none; }
@keyframes gps-battement {
    0%, 100% { opacity: 1; }
    50%      { opacity: .25; }
}

.gps-scene { position: relative; min-width: 0; }
.gps-toile {
    height: 100%;
    border: 1px solid var(--trait);
    border-radius: var(--rayon);
    background: var(--fond);
}

/* L'outil de carte porte une icone ET un libelle au bureau — la place ne
   manque pas et un pictogramme seul se devine mal. Sur telephone le libelle
   disparait : quatre boutons de texte occupaient une rangee entiere au-dessus
   de la carte, sur l'ecran ou la carte est la seule chose qui compte. */
.gps-outil { display: inline-flex; align-items: center; gap: 6px; }
.gps-outil .ico { color: var(--encre-doux); }
.gps-outil:hover .ico { color: var(--accent-fonce); }

.gps-outils {
    position: absolute;
    top: 10px; right: 10px;
    z-index: 500;                 /* au-dessus des tuiles Leaflet (400) */
    display: flex;
    gap: 5px;
}
.gps-outil {
    padding: 5px 10px;
    font-size: 11.5px;
    font-family: inherit;
    color: var(--encre-moy);
    background: var(--surface);
    border: 1px solid var(--trait);
    border-radius: var(--rayon-champ);
    cursor: pointer;
    box-shadow: 0 1px 3px rgba(15, 23, 42, .12);
    transition: all var(--transition);
}
.gps-outil:hover:not(:disabled) { color: var(--encre); border-color: var(--encre-pale); }
.gps-outil.est-actif { background: var(--accent-pale); border-color: var(--accent); color: var(--accent-fonce); }
.gps-outil:disabled { opacity: .45; cursor: default; }

/* La fiche s'ouvre SUR la carte : le regard vient de cliquer un marqueur,
   deplacer sa reponse a l'autre bout de l'ecran fait perdre le fil. */
.gps-fiche {
    position: absolute;
    left: 10px; bottom: 10px;
    z-index: 500;
    width: min(320px, calc(100% - 20px));
    background: var(--surface);
    border: 1px solid var(--trait);
    border-radius: var(--rayon);
    box-shadow: 0 6px 20px rgba(15, 23, 42, .16);
    overflow: hidden;
}
.gps-fiche-tete {
    display: flex;
    align-items: baseline;
    gap: 7px;
    padding: 9px 11px;
    border-bottom: 1px solid var(--trait-fin);
}
.gps-fiche-nom { font-size: 13px; font-weight: 600; }
.gps-fermer {
    border: 0; background: none; cursor: pointer;
    font-size: 18px; line-height: 1; color: var(--encre-pale); padding: 0 2px;
}
.gps-fermer:hover { color: var(--encre); }

/* L'ALERTE EN TETE DE FICHE, ET ELLE SE NOMME.
   Un « 3 alertes » ne dit pas s'il s'agit d'un exces de vitesse ou d'une
   alimentation coupee — deux situations qui n'appellent pas la meme reaction.
   Le message de la derniere est donc la premiere ligne, et le compte passe en
   second. Le ton suit la gravite : une info en teal, une critique en rouge. */
.gps-fiche-alerte {
    display: block;
    padding: 7px 11px;
    background: var(--critique-pale);
    color: var(--critique);
    border-left: 3px solid var(--critique);
}
.gps-fiche-alerte.est-alerte {
    background: var(--attention-pale);
    color: var(--attention);
    border-left-color: var(--attention);
}
.gps-fiche-alerte-t {
    display: block;
    font-size: 11.5px; font-weight: 600; line-height: 1.35;
}
.gps-fiche-alerte-b {
    display: block;
    font-size: 10.5px; opacity: .82; margin-top: 1px;
}

.gps-fiche-corps { margin: 0; padding: 4px 11px; }
.gps-fiche-ligne {
    display: flex;
    gap: 10px;
    padding: 4px 0;
    font-size: 12px;
    border-bottom: 1px solid var(--trait-fin);
}
.gps-fiche-ligne:last-child { border-bottom: 0; }
.gps-fiche-ligne dt { flex: none; width: 84px; color: var(--encre-pale); }
.gps-fiche-ligne dd {
    flex: 1; min-width: 0; margin: 0; color: var(--encre);
    overflow: hidden; text-overflow: ellipsis;
}
.gps-fiche-pied {
    display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
    padding: 9px 11px; border-top: 1px solid var(--trait-fin); background: var(--fond);
}
/* LA COUPURE MOTEUR PREND SON PROPRE RANG. Sur la meme ligne que les trois
   autres actions, elle debordait d'une fiche de 320 px et se faisait rogner par
   l'`overflow: hidden` du cadre — un bouton a moitie visible qui, lui, coupe
   une voiture reelle. Pleine largeur, seul, et separe du reste. */
.gps-fiche-coupure {
    padding: 0 11px 9px;
    background: var(--fond);
}
/* DEUX ACTIONS SUR LE MONDE PHYSIQUE, COTE A COTE.
   Le klaxon alerte la rue, la coupure immobilise. La premiere est neutre, la
   seconde rouge : la couleur dit laquelle des deux est sans retour. */
.gps-fiche-coupure { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.gps-fiche-coupure .btn { width: 100%; justify-content: center; }
.gps-fiche-coupure .gps-fiche-note { grid-column: 1 / -1; }
.gps-fiche-note {
    display: block; margin-top: 4px;
    font-size: 10.5px; color: var(--encre-pale); text-align: center;
}

/* --- Marqueurs --------------------------------------------------------------
   Des divIcon et un transform CSS plutot qu'un plugin : le .htaccess coupe les
   CDN, et un parc depasse rarement la centaine de vehicules.
   ------------------------------------------------------------------------- */
/* --- LE MARQUEUR DE VEHICULE -------------------------------------------------
   CE QU'IL REMPLACE : un rond de 22 px borde de la couleur de l'etat. Sur
   soixante-douze points, soixante-douze ronds identiques — on ne savait ni qui
   roule, ni vers ou, ni a quelle vitesse sans ouvrir chaque fiche.

   Il porte maintenant TROIS informations sans qu'on clique : la direction par
   une pointe orientee sur le cap, la vitesse ecrite dans le disque, l'etat par
   la couleur. C'est ce qu'affiche n'importe quel outil de suivi de flotte, et
   pour une raison : ce sont les trois questions qu'on se pose devant un point.

   A l'arret, ni pointe ni chiffre : un cap fige et un « 0 » sont deux
   informations fausses. */
.gps-pion {
    display: grid;
    place-items: center;
    width: 30px; height: 30px;
    border-radius: 50%;
    background: var(--surface);
    /* Deux ombres : une portee pour detacher le pion du fond de carte, et un
       anneau blanc pour qu'il reste lisible sur une route ou une foret. */
    box-shadow: 0 0 0 2px rgba(255, 255, 255, .9), 0 2px 6px rgba(15, 42, 46, .4);
    position: relative;
    transition: transform var(--transition);
}
.gps-pion.est-choisi {
    transform: scale(1.3);
    z-index: 1000;
    box-shadow: 0 0 0 3px rgba(255, 255, 255, .95), 0 0 0 6px rgba(13, 148, 136, .35),
                0 3px 10px rgba(15, 42, 46, .45);
}

.gps-pion-point { width: 9px; height: 9px; border-radius: 50%; background: currentColor; }

/* LA VITESSE, DANS LE DISQUE. C'est la donnee qu'on cherche en regardant un
   point qui derape, et elle demandait deux clics. Chasse tabulaire pour que
   « 11 » et « 88 » occupent la meme largeur — sinon les pions dansent. */
.gps-pion-v {
    font-size: 10px;
    font-weight: 700;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    color: currentColor;
}

/* LA POINTE DE CAP, POSEE A L'EXTERIEUR DU DISQUE.
   Elle tourne AUTOUR du pion et non dedans : a l'interieur, un chevron de
   5 px se confondait avec le chiffre et disparaissait au dezoom. Dehors, elle
   se lit a l'echelle ou l'on voit toute la ville.

   `transform-origin` au centre du pion : c'est ce qui fait qu'elle orbite au
   lieu de pivoter sur elle-meme. */
.gps-pion-cap {
    position: absolute;
    top: -7px;
    left: 50%;
    width: 0; height: 0;
    margin-left: -5px;
    border-left: 5px solid transparent;
    border-right: 5px solid transparent;
    border-bottom: 8px solid currentColor;
    transform-origin: 5px 22px;
    filter: drop-shadow(0 0 1px rgba(255, 255, 255, .9));
}

.gps-pion.est-roule   { color: var(--positif);    border: 2px solid var(--positif); }
.gps-pion.est-ralenti { color: var(--attention);  border: 2px solid var(--attention); }
.gps-pion.est-arret   { color: var(--encre-doux); border: 2px solid var(--encre-doux); }
.gps-pion.est-muet    { color: var(--critique);   border: 2px solid var(--critique); }
.gps-pion.est-inconnu { color: var(--encre-pale); border: 2px dashed var(--encre-pale); }

/* Les coordonnees, copiables. On les lit pour les dicter au telephone ou les
   coller dans une application de navigation — les selectionner a la main dans
   une fiche etroite est le genre de friction qui fait renoncer. */
.gps-coord {
    display: block;
    width: 100%;
    margin-top: 8px;
    padding: 7px 10px;
    border: 1px dashed var(--trait);
    border-radius: 8px;
    background: var(--surface-alt);
    font-family: var(--police);
    font-size: 11.5px;
    font-variant-numeric: tabular-nums;
    letter-spacing: .02em;
    color: var(--encre-moy);
    cursor: pointer;
    text-align: center;
    transition: background var(--transition), color var(--transition);
}
.gps-coord:hover { border-color: var(--accent); color: var(--encre); }
.gps-coord.est-copie {
    background: var(--accent-pale);
    border-color: var(--accent);
    color: var(--accent-sombre);
}
.gps-coord.est-copie::after { content: ' — copie'; font-weight: 600; }

/* L'alerte de la fiche est un LIEN : « 3 alertes non lues » sans moyen de les
   lire oblige a quitter la carte et a perdre le point qu'on regardait. */
a.gps-fiche-alerte { text-decoration: none; }
a.gps-fiche-alerte:hover { filter: brightness(.97); }

/* Le point d'alerte se pose SUR le marqueur : une liste d'alertes a cote
   oblige a faire le lien soi-meme entre un nom et un point de la carte. */
.gps-pion-alerte {
    position: absolute;
    top: -2px; right: -2px;
    width: 8px; height: 8px;
    border-radius: 50%;
    background: var(--critique);
    border: 1.5px solid var(--surface);
}

/* Qui conduit, sur la ligne de flotte : c'est la premiere question qu'on se
   pose devant un point qui derape, et la chercher ailleurs fait perdre le
   vehicule des yeux. */
.gps-ligne-pilote {
    display: block;
    margin-top: 2px;
    font-size: 11px;
    color: var(--encre-moy);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Un boitier muet n'est pas un vehicule a l'arret : son point est la DERNIERE
   position transmise. Le bandeau le dit avant qu'on lise une adresse vieille
   de six heures comme une position actuelle. */
.gps-fiche-perdu {
    padding: 6px 11px;
    background: var(--critique-pale);
    color: var(--critique);
    font-size: 11.5px;
    font-weight: 600;
}

/* Le halo pulse pour dire « ce point a vieilli », sans exiger d'ouvrir la
   fiche pour le decouvrir. */
.gps-pion-halo {
    position: absolute;
    inset: -5px;
    border-radius: 50%;
    border: 1.5px solid var(--critique);
    opacity: .55;
    animation: gps-halo 2s ease-out infinite;
    pointer-events: none;
}
@keyframes gps-halo {
    0%   { transform: scale(.72); opacity: .6; }
    70%  { transform: scale(1.25); opacity: 0; }
    100% { transform: scale(1.25); opacity: 0; }
}

/* Le selecteur de fond, aux couleurs du reste : le style par defaut de
   Leaflet jure avec tout le tableau de bord. */
.leaflet-control-layers {
    border: 1px solid var(--trait) !important;
    border-radius: var(--rayon-champ) !important;
    box-shadow: 0 1px 3px rgba(15, 23, 42, .12) !important;
    font-size: 12px;
}
.leaflet-control-layers-list { padding: 3px 5px; }
.leaflet-control-layers label { font-size: 12px; color: var(--encre-moy); }

@media (max-width: 900px) {
    /* La liste passe AU-DESSUS et non a cote : deux colonnes de 150 px ne
       montrent ni une carte lisible ni une liste lisible. */
    .gps-plan {
        grid-template-columns: 1fr;
        grid-template-rows: 210px minmax(320px, 1fr);
        height: auto;
    }
    .gps-fiche { width: calc(100% - 20px); }
}

/* --- Le vehicule confie, en tete de fiche chauffeur -------------------------
   C'est la premiere chose qu'on vient verifier sur une fiche chauffeur : sur
   quoi roule-t-il en ce moment. Et c'est le pivot de tout le reste — amendes,
   alertes et entretiens se rattachent au vehicule qu'il conduisait A CETTE
   DATE, jamais a celui d'aujourd'hui.
   ------------------------------------------------------------------------- *

/* --- L'adresse du serveur, affichee et non demandee -------------------------
   En production, celle par laquelle on vient d'atteindre l'application EST
   celle que le boitier doit composer. Elle se detecte, elle ne se reclame pas.
   La voir en grand permet en plus de reperer d'un coup d'oeil qu'elle est
   fausse — avant d'envoyer quinze SMS avec.
   ------------------------------------------------------------------------- */
.adresse-vive {
    display: grid;
    grid-template-columns: minmax(0, auto) minmax(0, 1fr);
    grid-template-areas:
        'etiquette etiquette'
        'valeur    dit';
    align-items: center;
    gap: 3px 14px;
    padding: 12px 15px;
    margin-bottom: 12px;
    background: var(--accent-pale);
    border: 1px solid var(--accent);
    border-radius: var(--rayon);
}

/* Inutilisable : le ton change, mais la valeur reste lisible et en grand.
   La cacher priverait du seul indice permettant de comprendre pourquoi rien
   n'arrive. */
.adresse-vive.est-inutilisable {
    background: var(--critique-pale);
    border-color: #eddcda;
}

.adresse-etiquette {
    grid-area: etiquette;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--accent-fonce);
}
.adresse-vive.est-inutilisable .adresse-etiquette { color: var(--critique); }

.adresse-valeur {
    grid-area: valeur;
    font-size: 19px;
    font-weight: 700;
    color: var(--encre);
    line-height: 1.2;
    overflow-wrap: anywhere;
}

.adresse-dit {
    grid-area: dit;
    font-size: 11.5px;
    line-height: 1.5;
    color: var(--encre-moy);
    max-width: 62ch;
}
.adresse-vive.est-inutilisable .adresse-dit { color: var(--critique); }

/* Les adresses proposees mais pas encore adoptees : une ligne, une valeur,
   d'ou elle vient, et un bouton. */
.adresse-candidats { display: flex; flex-direction: column; gap: 5px; margin-bottom: 12px; }
.adresse-candidat {
    display: flex;
    align-items: center;
    gap: 9px;
    flex-wrap: wrap;
    padding: 7px 10px;
    background: var(--fond);
    border: 1px solid var(--trait-fin);
    border-radius: var(--rayon-champ);
    font-size: 12.5px;
}

@media (max-width: 560px) {
    /* La valeur passe au-dessus de son explication : cote a cote, une adresse
       de vingt caracteres et une phrase se partagent 150 px chacune et aucune
       ne se lit. */
    .adresse-vive {
        grid-template-columns: minmax(0, 1fr);
        grid-template-areas: 'etiquette' 'valeur' 'dit';
        gap: 4px;
    }
    .adresse-valeur { font-size: 17px; }
}

/* --- Poser un boitier : trois etapes ----------------------------------------
   Le mode d'emploi est sur la page ou l'on est quand on en a besoin. Un
   installateur devant un vehicule, boitier en main, n'ira pas chercher la
   syntaxe d'un SMS dans les reglages.
   ------------------------------------------------------------------------- */
.etapes-pose { display: flex; flex-direction: column; gap: 0; margin-bottom: 16px; }

.etape {
    display: grid;
    grid-template-columns: 30px minmax(0, 1fr);
    gap: 0 13px;
    position: relative;
    padding-bottom: 20px;
}
.etape:last-child { padding-bottom: 4px; }

/* Le filet relie les etapes : il dit que l'ORDRE compte. Poser le boitier
   avant d'avoir desactive le PIN de la SIM oblige a tout redemonter. */
.etape::before {
    content: '';
    position: absolute;
    left: 14px; top: 30px; bottom: 0;
    width: 1px;
    background: var(--trait);
}
.etape:last-child::before { display: none; }

.etape-num {
    display: grid;
    place-items: center;
    width: 29px; height: 29px;
    border-radius: 50%;
    background: var(--accent);
    color: #fff;
    font-size: 13px;
    font-weight: 700;
    position: relative;
    z-index: 1;
}

.etape-corps { min-width: 0; padding-top: 3px; }
.etape-titre { font-size: 14px; font-weight: 600; margin: 0 0 6px; }
.etape-dit {
    margin: 0 0 9px;
    font-size: 12.5px;
    line-height: 1.55;
    color: var(--encre-moy);
    max-width: 72ch;
}
.etape-dit:last-child { margin-bottom: 0; }
.etape-dit.muet { color: var(--encre-pale); }

.pose-formulaire {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
    gap: 0 14px;
    padding: 12px 13px 4px;
    background: var(--surface);
    border: 1px solid var(--trait);
    border-radius: var(--rayon);
    margin-bottom: 10px;
}
.pose-formulaire .champ { margin-bottom: 11px; }
.pose-formulaire .champ-label { display: block; }

@media (max-width: 560px) {
    /* La pastille reste, le filet disparait : sur une colonne unique il
       traverserait le texte plus qu'il ne relierait les etapes. */
    .etape { grid-template-columns: 26px minmax(0, 1fr); gap: 0 10px; }
    .etape-num { width: 25px; height: 25px; font-size: 12px; }
    .etape::before { left: 12px; top: 26px; }
}

/* --- Parametrage des boitiers, par marque -----------------------------------
   Un boitier ne se branche pas : on lui envoie un SMS qui lui dit ou emettre.
   La syntaxe change a chaque marque, et elle n'existait nulle part dans
   l'application — l'installateur devait la chercher dans une notice papier,
   sur le terrain, avec une adresse de serveur qu'il n'avait pas non plus.
   ------------------------------------------------------------------------- */
.jeu-onglets {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    border-bottom: 1px solid var(--trait-fin);
    margin-bottom: 12px;
}
.jeu-onglet {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 11px;
    font-size: 12px;
    font-family: inherit;
    color: var(--encre-doux);
    background: none;
    border: 0;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    cursor: pointer;
    transition: color var(--transition), border-color var(--transition);
}
.jeu-onglet:hover { color: var(--encre); }
.jeu-onglet.est-actif { color: var(--accent-fonce); border-bottom-color: var(--accent); font-weight: 600; }

/* Le point dit si le port de CE protocole repond. Sans lui, on choisit son
   onglet, on envoie trois SMS, et on decouvre le pare-feu une heure plus tard. */
.jeu-onglet-etat {
    width: 6px; height: 6px;
    border-radius: 50%;
    background: var(--critique);
    flex: none;
}
.jeu-onglet-etat.est-ouvert { background: var(--positif); }

.jeu-volet { display: none; }
.jeu-volet.est-actif { display: block; }

.proto-tete { display: flex; align-items: flex-start; gap: 10px; margin-bottom: 11px; }
.proto-modeles { font-size: 12.5px; font-weight: 600; line-height: 1.4; }

.sms-liste { margin: 0; padding-left: 18px; }
.sms-ligne {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 2px 10px;
    padding: 7px 0;
    border-bottom: 1px solid var(--trait-fin);
}
.sms-ligne:last-child { border-bottom: 0; }
.sms-titre { grid-column: 1 / -1; font-size: 11px; color: var(--encre-pale); }

/* Le SMS est du texte a recopier a l'identique : espaces et dieses compris.
   D'ou la police a chasse fixe et le retour a la ligne autorise — une commande
   coupee par un debordement invisible se recopie fausse. */
.sms-texte {
    font-family: ui-monospace, 'SFMono-Regular', 'Cascadia Mono', Menlo, Consolas, monospace;
    font-size: 12px;
    color: var(--encre);
    background: var(--fond);
    border: 1px solid var(--trait-fin);
    border-radius: var(--rayon-badge);
    padding: 4px 8px;
    overflow-wrap: anywhere;
    white-space: pre-wrap;
}
.sms-copier { white-space: nowrap; }

.proto-note {
    margin: 11px 0 0;
    font-size: 11.5px;
    line-height: 1.5;
    color: var(--encre-doux);
    max-width: 68ch;
}

/* --- Documents ---------------------------------------------------------------
   Une piece se reconnait a son apercu avant son nom : « carte_grise_2026.pdf »
   et « scan001.pdf » se ressemblent, la photo d'une carte grise et celle d'un
   pare-chocs non.
   ------------------------------------------------------------------------- */

/* Ce qui MANQUE, avant ce qui est la. On ne remarque pas l'absence d'une carte
   grise dans une liste de ce qui est present : on la remarque le jour du
   controle. */
.doc-manquants { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.doc-manquants-titre {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .03em;
    text-transform: uppercase;
    color: var(--critique);
}
.doc-puce-manquante {
    padding: 4px 10px;
    font-size: 12px;
    font-family: inherit;
    color: var(--critique);
    background: var(--critique-pale);
    border: 1px dashed #e0c4c1;
    border-radius: 20px;
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition);
}
.doc-puce-manquante:hover { background: #f7e4e2; border-style: solid; }

.doc-grille {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
    gap: 10px;
    padding: 12px 14px;
}

.doc-carte {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--trait);
    border-radius: var(--rayon);
    overflow: hidden;
    background: var(--surface);
    transition: border-color var(--transition), box-shadow var(--transition);
}
.doc-carte:hover { border-color: var(--encre-pale); box-shadow: var(--ombre); }

/* Le liseré porte l'échéance : une assurance périmée doit se voir sans lire. */
.doc-carte.est-perimee { border-color: #e0c4c1; box-shadow: inset 0 3px 0 var(--critique); }
.doc-carte.est-bientot { box-shadow: inset 0 3px 0 var(--attention); }

.doc-apercu {
    display: block;
    aspect-ratio: 16 / 10;
    background: var(--fond);
    overflow: hidden;
    position: relative;
}
.doc-apercu img { width: 100%; height: 100%; object-fit: cover; display: block; }

.doc-icone-pdf {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    color: var(--encre-pale);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .06em;
}

.doc-corps { padding: 9px 11px; flex: 1; min-width: 0; }

.doc-categorie {
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .03em;
    text-transform: uppercase;
    color: var(--accent-fonce);
}
.doc-nom {
    font-size: 13px;
    font-weight: 500;
    margin-top: 2px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.doc-meta { font-size: 11px; color: var(--encre-pale); margin-top: 3px; }

.doc-echeance { font-size: 11.5px; font-weight: 500; margin-top: 5px; color: var(--encre-doux); }
.doc-echeance.est-perimee { color: var(--critique); }
.doc-echeance.est-bientot { color: var(--attention); }

.doc-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 7px 11px;
    border-top: 1px solid var(--trait-fin);
    background: var(--fond);
}

.doc-ajout { border-top: 1px solid var(--trait-fin); }

/* La zone EST le label du champ : cliquer dessus ouvre le selecteur, et le
   glisser-deposer y fonctionne. Sur telephone elle ouvre l'appareil photo —
   c'est le geste reel : on photographie la carte grise, on ne la scanne pas. */
.doc-zone {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px;
    margin-bottom: 12px;
    border: 1.5px dashed var(--trait);
    border-radius: var(--rayon);
    background: var(--fond);
    cursor: pointer;
    transition: border-color var(--transition), background var(--transition);
}
.doc-zone:hover      { border-color: var(--accent); background: var(--accent-pale); }
.doc-zone.est-survolee { border-color: var(--accent); background: var(--accent-pale); }
.doc-zone.est-remplie  { border-style: solid; border-color: var(--accent); background: var(--accent-pale); }
.doc-zone.est-refusee  { border-color: var(--critique); background: var(--critique-pale); }

/* Le champ reste dans le flux pour le clavier et les lecteurs d'ecran, mais
   n'occupe aucune place : c'est la zone entiere qui sert de cible. */
.doc-zone input[type='file'] { position: absolute; opacity: 0; width: 0; height: 0; }
.doc-zone:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }

.doc-zone-icone {
    display: grid;
    place-items: center;
    width: 42px; height: 42px;
    flex: none;
    border-radius: 50%;
    background: var(--surface);
    color: var(--encre-doux);
    border: 1px solid var(--trait);
}
.doc-zone.est-remplie .doc-zone-icone { color: var(--accent-fonce); border-color: var(--accent); }
.doc-zone.est-refusee .doc-zone-icone { color: var(--critique); border-color: #e0c4c1; }

.doc-zone-texte { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.doc-zone-texte strong {
    font-size: 13.5px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.doc-zone-texte .muet { font-size: 11.5px; }

/* --- Controles de diagnostic ------------------------------------------------
   Une ligne par question tranchee, dans l'ordre du diagnostic : une ligne
   rompue rend les suivantes insignifiantes. Le point porte l'etat, le texte
   porte la MESURE — « 4 ports repondent », pas « OK ». Un diagnostic qui dit
   seulement oui ou non oblige a rouvrir un terminal pour savoir quoi corriger.
   ------------------------------------------------------------------------- */
.controle {
    display: grid;
    grid-template-columns: 9px minmax(0, auto) minmax(0, 1fr);
    align-items: baseline;
    gap: 9px;
    padding: 7px 0;
    border-bottom: 1px solid var(--trait-fin);
}
.controle:last-child { border-bottom: 0; }

.controle-etat {
    width: 7px; height: 7px;
    border-radius: 50%;
    background: var(--positif);
    align-self: center;
}
.controle.est-rompu .controle-etat { background: var(--critique); }

.controle-titre { font-size: 12.5px; font-weight: 600; white-space: nowrap; }
.controle-dit   { font-size: 11.5px; color: var(--encre-doux); line-height: 1.45; }
.controle.est-rompu .controle-dit { color: var(--critique); }

/* --- Marche a suivre --------------------------------------------------------
   Numerotee parce que l'ordre compte : poser le boitier avant d'avoir
   desactive le PIN de la SIM oblige a tout redemonter.
   ------------------------------------------------------------------------- */
.etapes { margin: 0; padding-left: 18px; }
.etapes li {
    font-size: 12px;
    line-height: 1.55;
    color: var(--encre-moy);
    margin-bottom: 7px;
}
.etapes li:last-child { margin-bottom: 0; }

/* --- Titre de section --------------------------------------------------------
   Plus discret qu'un titre de carte : il ordonne une suite de blocs sans
   pretendre en etre un lui-meme.
   ------------------------------------------------------------------------- */
.entete-section {
    display: flex;
    align-items: baseline;
    gap: 10px;
    flex-wrap: wrap;
    margin: 18px 0 9px;
}
.entete-section:first-child { margin-top: 0; }
.entete-section-titre {
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--encre-moy);
    white-space: nowrap;
}
.entete-section .petit { max-width: 78ch; line-height: 1.45; }

.champ-pleine-largeur { grid-column: 1 / -1; }
.champ-aligne-bas { display: flex; align-items: flex-end; }

/* --- Regles : des lignes qui se deplient ------------------------------------
   Une carte-formulaire par type tenait a sept regles ; a quinze elle donne un
   mur de champs, et sur un telephone chaque carte s'etire sur un ecran entier.
   Une regle se CONSULTE dix fois pour se regler une : la ligne montre ce qu'on
   vient verifier, les champs ne s'ouvrent que sur demande.
   ------------------------------------------------------------------------- */
.resume-regles {
    font-size: 12.5px;
    color: var(--encre-moy);
    margin-bottom: 14px;
}

.regles-liste {
    border: 1px solid var(--trait);
    border-radius: var(--rayon);
    background: var(--surface);
    overflow: hidden;
}

.regle-rangee {
    display: grid;
    grid-template-columns: 46px minmax(0, 1fr);
    align-items: start;
    border-bottom: 1px solid var(--trait-fin);
}
.regle-rangee:last-child { border-bottom: 0; }
.regle-rangee.est-active { box-shadow: inset 3px 0 0 var(--accent); }

/* Le bouton d'etat est un FORMULAIRE A PART, frere du <details> : un bouton
   dans un <summary> deplierait la ligne au lieu de basculer la regle. */
.regle-bascule { display: flex; align-items: center; justify-content: center; padding: 10px 0; }
.bascule-bouton {
    border: 0; background: none; padding: 0; cursor: pointer;
    display: block; line-height: 0;
}
.bascule-bouton.est-vide { cursor: default; opacity: .45; }
.bascule-bouton .bascule-piste {
    display: block;
    width: 30px; height: 17px;
    border-radius: 9px;
    background: var(--trait);
    position: relative;
    transition: background var(--transition);
}
.bascule-bouton .bascule-piste::after {
    content: '';
    position: absolute;
    top: 2px; left: 2px;
    width: 13px; height: 13px;
    border-radius: 50%;
    background: var(--surface);
    box-shadow: 0 1px 2px rgba(15, 23, 42, .3);
    transition: transform var(--transition);
}
.bascule-bouton[aria-pressed='true'] .bascule-piste { background: var(--accent); }
.bascule-bouton[aria-pressed='true'] .bascule-piste::after { transform: translateX(13px); }
.bascule-bouton:focus-visible .bascule-piste { outline: 2px solid var(--accent); outline-offset: 2px; }

.regle-detail { min-width: 0; }

.regle-somme {
    display: grid;
    grid-template-columns: minmax(120px, 1.1fr) minmax(0, 1.6fr) 92px 42px;
    align-items: center;
    gap: 10px;
    padding: 9px 12px 9px 0;
    cursor: pointer;
    list-style: none;
    transition: background var(--transition);
}
.regle-somme::-webkit-details-marker { display: none; }
.regle-somme:hover { background: var(--fond); }
.regle-detail[open] .regle-somme { background: var(--fond); }

.regle-nom {
    font-size: 12.5px;
    font-weight: 600;
    color: var(--encre);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.regle-seuil {
    font-size: 11.5px;
    color: var(--encre-doux);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* La gravite en texte et pas en couleur seule : quinze pastilles teintees
   feraient une guirlande, et un daltonien ne lirait rien du tout. */
.regle-gravite {
    font-size: 10.5px;
    font-weight: 600;
    text-align: center;
    padding: 1px 6px;
    border-radius: var(--rayon-badge);
    background: var(--trait-fin);
    color: var(--encre-doux);
    white-space: nowrap;
}
.regle-gravite.est-critique { background: var(--critique-pale); color: var(--critique); }
.regle-gravite.est-alerte   { background: var(--attention-pale); color: var(--attention); }

.regle-bilan {
    font-size: 12px;
    font-variant-numeric: tabular-nums;
    text-align: right;
    color: var(--encre-doux);
}
/* Une regle active a zero alerte en trente jours est soit bien reglee, soit
   cassee — et c'est le seul endroit ou la difference se voit. */
.regle-bilan.est-muette { color: var(--attention); }

.regle-panneau {
    padding: 4px 12px 13px 0;
    border-top: 1px solid var(--trait-fin);
}
.regle-role {
    margin: 10px 0 11px;
    font-size: 11.5px;
    line-height: 1.5;
    color: var(--encre-doux);
    max-width: 62ch;
}
.regle-champs {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(158px, 1fr));
    gap: 0 14px;
}
.regle-champs .champ { margin-bottom: 11px; }
.regle-champs .champ-label { display: block; }
.regle-champs .champ-saisie,
.regle-champs .champ-select { padding: 6px 9px; font-size: 12.5px; }
.regle-champs .champ-aide { display: block; font-size: 11px; margin-top: 4px; }

.regle-panneau-pied {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    padding-top: 4px;
}

@media (max-width: 720px) {
    /* Le seuil passe sous le nom, la gravite et le compteur restent en bout de
       ligne : ce sont eux qu'on balaie du regard, pas le detail du reglage. */
    .regle-somme {
        grid-template-columns: minmax(0, 1fr) 78px 34px;
        grid-template-areas:
            'nom gravite bilan'
            'seuil seuil seuil';
        gap: 2px 8px;
        padding-right: 10px;
    }
    .regle-nom     { grid-area: nom; }
    .regle-gravite { grid-area: gravite; }
    .regle-bilan   { grid-area: bilan; }
    .regle-seuil   { grid-area: seuil; white-space: normal; }
    .regle-rangee  { grid-template-columns: 40px minmax(0, 1fr); }
}

/* --- Jours de la semaine ----------------------------------------------------
   L'INDEX EST LA VALEUR STOCKEE : 0 = dimanche, comme EXTRACT(DOW). Ne pas
   reordonner pour commencer au lundi — c'est exactement ce qui a fait
   facturer le dimanche a un chauffeur et lui offrir le samedi.
   ------------------------------------------------------------------------- */
.jours-semaine { display: flex; gap: 4px; flex-wrap: wrap; }
.jour { cursor: pointer; }
.jour input { position: absolute; opacity: 0; width: 0; height: 0; }
.jour span {
    display: inline-block;
    min-width: 32px;
    padding: 4px 0;
    text-align: center;
    font-size: 11.5px;
    border: 1px solid var(--trait);
    border-radius: var(--rayon-badge);
    color: var(--encre-doux);
    transition: all var(--transition);
}
.jour.est-coche span,
.jour input:checked + span {
    background: var(--accent-pale);
    border-color: var(--accent);
    color: var(--accent-fonce);
}
.jour input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 1px; }

/* Le vide qu'il faut combler AVANT tout le reste. Reserve aux cas ou la page
   ne peut rien faire d'utile tant que l'utilisateur n'a pas agi. */
.est-mise-en-avant { border-color: var(--accent); box-shadow: inset 3px 0 0 var(--accent), var(--ombre); }

/* --- Recapitulatif de saisie -------------------------------------------------- */
.recap {
    margin-top: 12px;
    padding: 11px 13px;
    background: var(--fond);
    border-radius: var(--rayon);
    font-size: 12.5px;
}
.recap-ligne {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 3px 0;
    color: var(--encre-doux);
}
.recap-ligne.est-forte {
    border-top: 1px solid var(--trait);
    margin-top: 4px;
    padding-top: 7px;
    color: var(--encre);
    font-weight: 650;
    font-size: 14px;
}
.recap-valeur { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* --- Frise du calendrier ------------------------------------------------------ */
/* UNE LIGNE PAR VEHICULE, PAS UNE GRILLE MENSUELLE.
   La question posee devant ce calendrier n'est jamais « que se passe-t-il le
   14 ? » mais « ce vehicule est-il libre du 12 au 18 ? ». Une frise montre le
   trou d'un coup d'oeil la ou une grille oblige a sauter de case en case. */
.frise-boite { overflow-x: auto; -webkit-overflow-scrolling: touch; }

.frise-cal { min-width: 720px; }

.fc-ligne {
    display: grid;
    grid-template-columns: 150px minmax(0, 1fr);
    align-items: center;
    border-bottom: 1px solid var(--trait-fin);
}
.fc-ligne:last-child { border-bottom: 0; }

.fc-vehicule { padding: 7px 12px; min-width: 0; font-size: 12.5px; }

/* La piste porte les cases de fond ET les barres, sur les memes colonnes :
   c'est ce qui permet a une barre de couvrir exactement ses jours. */
.fc-piste {
    display: grid;
    grid-template-columns: repeat(var(--jours), minmax(0, 1fr));
    grid-auto-rows: minmax(26px, auto);
    position: relative;
    padding: 3px 0;
}

.fc-entete { border-bottom: 1px solid var(--trait); }
.fc-entete .fc-piste { padding: 0; }

.fc-jour {
    grid-row: 1;
    text-align: center;
    font-size: 10px;
    color: var(--encre-pale);
    padding: 5px 0;
    font-variant-numeric: tabular-nums;
}
.fc-jour.est-weekend { background: var(--fond); }
.fc-jour.est-aujourdhui { color: var(--accent-fonce); font-weight: 700; }

.fc-case {
    grid-row: 1;
    min-height: 26px;
    border-right: 1px solid var(--trait-fin);
    display: block;
}
.fc-case:hover { background: var(--accent-pale); }
.fc-case.est-weekend { background: var(--fond); }
.fc-case.est-aujourdhui { box-shadow: inset 2px 0 0 var(--accent); }

.fc-barre {
    grid-row: 1;
    height: 22px;
    margin: 2px 1px;
    border-radius: var(--rayon-badge);
    display: flex;
    align-items: center;
    padding: 0 7px;
    font-size: 11px;
    font-weight: 550;
    overflow: hidden;
    /* Sans cela la barre passe SOUS les cases de fond, qui sont declarees
       apres elle dans la grille. */
    position: relative;
    z-index: 1;
}
.fc-texte { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.fc-barre.est-reservee { background: var(--attention-pale); color: var(--attention); border: 1px solid var(--attention); }
.fc-barre.est-en-cours { background: var(--accent-pale);    color: var(--accent-fonce); border: 1px solid var(--accent); }
.fc-barre.est-terminee { background: var(--trait-fin);      color: var(--encre-doux);   border: 1px solid var(--trait); }

.legende-puce.est-reservee { background: var(--attention-pale); border: 1px solid var(--attention); }
.legende-puce.est-en-cours { background: var(--accent-pale);    border: 1px solid var(--accent); }
.legende-puce.est-terminee { background: var(--trait-fin);      border: 1px solid var(--trait); }

/* Separateur de journee dans la caisse : le rapprochement se fait jour par
   jour, une liste continue devient un bloc illisible. */
.ligne-groupe td {
    background: var(--fond);
    color: var(--encre-doux);
    text-transform: uppercase;
    letter-spacing: .04em;
    font-size: 10.5px;
}

/* Raccourci de periode actif dans la caisse. */
.btn.est-actif { border-color: var(--accent); color: var(--accent-fonce); background: var(--accent-pale); }

@media (max-width: 640px) {
    .fc-ligne { grid-template-columns: 110px minmax(0, 1fr); }
    .fc-vehicule { padding: 6px 8px; font-size: 11.5px; }
}

/* Option masquee par un filtre de recherche.
   L'attribut hidden seul ne suffit pas sur toutes les implementations de
   <select> : Safari l'ignore, la classe pose display:none qu'il respecte. */
/* Ligne annulee : sortie des comptes mais toujours lisible. Barree plutot que
   masquee — une somme qui a reellement transite par la caisse doit rester
   tracable, ne serait-ce que pour prouver au client qu'on la lui a rendue. */
tr.est-annulee { opacity: .55; }
tr.est-annulee td:last-child { text-decoration: line-through; }

/* Onglets d'un module : les pages soeurs qui encombraient la colonne de gauche.
   Posee sous le titre de page, la rangee dit ou l'on est dans le module sans
   qu'on ait a relire le menu. */
.onglets-module { margin: -4px 0 14px; }

option.est-masquee { display: none; }

/* =============================================================================
   TABLES D'EXPLOITATION — fines, sur une seule ligne
   =============================================================================
   Une table d'exploitation se BALAIE, elle ne se lit pas ligne à ligne : plus
   il en tient à l'écran, moins on fait défiler pour comparer. La hauteur vient
   du texte, pas de la gouttière — 3 px suffisent quand un filet d'un pixel
   sépare déjà deux lignes.

   RIEN NE PASSE À LA LIGNE. Une cellule qui déborde tronque avec des points de
   suspension. Un mot qui se replie casse l'alignement de toute la rangée et
   fait sauter la hauteur du simple au double, ce qui est exactement ce qui
   rendait ces tables illisibles.
   ============================================================================= */
.tableau-fin th {
    padding: 5px 10px;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--encre-pale);
    white-space: nowrap;
}

.tableau-fin td {
    padding: 4px 10px;
    font-size: 12px;
    line-height: 16px;
    vertical-align: middle;
    /* Une cellule ne se replie jamais : elle tronque. */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 0;
}

/* Les colonnes qui doivent garder leur largeur naturelle. */
.tableau-fin td.actions,
.tableau-fin td.nombre,
.tableau-fin th.nombre { max-width: none; width: 1%; }

.tableau-fin .cellule-titre {
    font-size: 12px;
    line-height: 16px;
    font-weight: 600;
    display: inline;
}
.tableau-fin .nombre { font-variant-numeric: tabular-nums; text-align: right; }

/* La précision À CÔTÉ du titre, jamais dessous : deux lignes empilées doublent
   la hauteur de la rangée pour une information secondaire. */
.cellule-suite {
    color: var(--encre-pale);
    font-size: 11px;
    font-weight: 400;
    margin-left: 7px;
}

/* --- État : une pastille discrète, à la Shopify ------------------------------ */
/* Un point, un mot, un fond gris très clair. Pas de couleur pleine : sur une
   colonne de dix lignes, dix pastilles colorées font une guirlande et plus
   rien ne ressort. Seul ce qui APPELLE UNE ACTION prend une teinte. */
.etat {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 1px 8px 1px 7px;
    border-radius: 8px;
    background: var(--trait-fin);
    color: var(--encre-moy);
    font-size: 11.5px;
    font-weight: 500;
    line-height: 16px;
    white-space: nowrap;
}
.etat::before {
    content: '';
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--encre-pale);
    flex: none;
}

/* Ce qui demande une action. La teinte est franche mais le texte reste sombre :
   un fond sature avec du texte clair se lit mal a 11 px. */
.etat.est-action  { background: #fdf0c4; color: #6b5518; }
.etat.est-action::before  { background: #b8860b; }

.etat.est-fait    { background: var(--positif-pale); color: var(--positif); }
.etat.est-fait::before    { background: var(--positif); }

.etat.est-arret   { background: #f0eef6; color: #6b5f8a; }
.etat.est-arret::before   { background: #6b5f8a; }

.etat.est-neutre  { background: var(--trait-fin); color: var(--encre-doux); }

/* --- Actions : grises tant que la ligne n'est pas survolée -------------------- */
/* Une colonne de boutons colorés attire l'œil sur l'action au lieu du chiffre
   qui la déclenche. */
.btn-discret {
    display: inline-block;
    padding: 1px 7px;
    border: 1px solid transparent;
    border-radius: var(--rayon-badge);
    background: none;
    font-family: inherit;
    font-size: 11.5px;
    line-height: 16px;
    font-weight: 500;
    color: var(--encre-pale);
    cursor: pointer;
    white-space: nowrap;
    transition: color var(--transition), background var(--transition), border-color var(--transition);
}
.tableau-action tr:hover .btn-discret { color: var(--encre-moy); }
.btn-discret:hover {
    background: var(--accent-pale);
    border-color: var(--accent);
    color: var(--accent-fonce);
}
/* Le clavier ne survole pas : sans ce focus visible, l'action serait
   introuvable en navigation au clavier. */
.btn-discret:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.tableau-action td.actions { white-space: nowrap; text-align: right; }

/* --- Signaler sans crier ------------------------------------------------------ */
/* Un fond rouge sur toute la ligne noie le texte et rend la table criarde dès
   qu'il y a trois alertes — au-delà, on cesse de la regarder. Un filet de 2 px
   à gauche suffit : l'œil le repère en balayant la colonne. */
/* PAS DE LISERE EN BORD DE RANGEE : voir tableau.css. Le montant du en rouge
   designe la ligne ET la somme ; une barre coloree en plus ne dit rien de
   nouveau et, quand la moitie des lignes la porte, ne designe plus rien. */
.tableau-fin tr.est-signalee { background: none; }
.tableau-fin tr.est-attention > td:first-child { box-shadow: inset 2px 0 0 var(--attention); }
.tableau-fin tr:hover > td { background: var(--fond); }

/* --- Table groupée : le véhicule écrit une seule fois -------------------------- */
/* Un véhicule porte huit obligations. À plat, son immatriculation revenait huit
   fois et l'œil ne voyait plus les véhicules, seulement une suite de lignes.
   Le filet ne se dessine qu'entre deux groupes, pour qu'un véhicule se lise
   comme un bloc. */
.tableau-groupe td { border-bottom: 0; }
.tableau-groupe tr.est-tete > td { border-top: 1px solid var(--trait); }
.tableau-groupe tbody tr:first-child > td { border-top: 0; }

.cellule-groupe {
    vertical-align: top !important;
    padding-top: 6px !important;
    white-space: nowrap;
    max-width: none !important;
}
/* Le survol porte sur la ligne, pas sur le groupe : surligner huit lignes parce
   qu'on passe sur une seule est deroutant. */
.tableau-groupe tr:hover > .cellule-groupe { background: none; }

/* Le filet d'alerte se pose sur la NATURE et non sur le véhicule : la cellule
   fusionnée couvre plusieurs lignes, et l'y mettre signalerait tout le groupe
   pour une seule échéance en retard. */
.tableau-groupe tr.est-signalee > td:first-child,
.tableau-groupe tr.est-attention > td:first-child { box-shadow: none; }
.tableau-groupe tr.est-signalee > .cellule-groupe + td { box-shadow: inset 2px 0 0 var(--critique); }
.tableau-groupe tr.est-attention > .cellule-groupe + td { box-shadow: inset 2px 0 0 var(--attention); }
/* Sur une ligne sans cellule de groupe, la nature est deja la premiere. */
.tableau-groupe tr.est-signalee:not(.est-tete) > td:first-child { box-shadow: inset 2px 0 0 var(--critique); }
.tableau-groupe tr.est-attention:not(.est-tete) > td:first-child { box-shadow: inset 2px 0 0 var(--attention); }

@media print {
    .barre, .entete, .page-tete-actions, .btn, .filtres, .onglets { display: none !important; }
    .zone { padding: 0; max-width: none; }
    .carte, .tableau-boite { border: 0; box-shadow: none; }
    body { background: #fff; }
}

/* =============================================================================
   Utilitaires ajoutés pour supprimer les styles en ligne répétés
   =============================================================================
   Chacune de ces classes remplaçait un style="…" recopié cinq à dix fois dans
   les vues. Une variante oubliée lors d'une modification suffisait à faire
   diverger deux pages censées se ressembler.
   ============================================================================= */

/* Tableau logé dans une carte : la carte porte déjà bordure et ombre. *

/* Formulaire inséré dans une carte, sans marge propre. */
.sans-marge { margin: 0 !important; }

/* Largeurs de champ dans une barre de filtres. */
.l-xs { min-width: 110px; }
.l-sm { min-width: 130px; }
.l-md { min-width: 165px; }
.l-lg { min-width: 200px; }
.l-flex { flex: 1 1 180px; min-width: 160px; }

/* Groupe d'actions aligné à droite dans une cellule de tableau. */
.actions-groupe { display: flex; justify-content: flex-end; gap: 5px; align-items: center; flex-wrap: wrap; }

/* Champs compacts intégrés dans une ligne de tableau. */
.champ-compact { padding: 4px 8px !important; font-size: 12px !important; }
.champ-compact.champ-select { padding-right: 22px !important; }

.w-56  { max-width: 56px; }
.w-90  { max-width: 90px; }
/* Select dont la largeur suit son contenu : dans une cellule de tableau, un
   select pleine largeur pousse la colonne bien au-delà de ce qu'elle mérite. */
.champ-select.est-auto { width: auto; }

/* Couleurs sémantiques appliquées au texte. */
.t-critique  { color: var(--critique); }
.t-positif   { color: var(--positif); }
.t-attention { color: var(--attention); }
.t-accent    { color: var(--accent-fonce); }

/* Espacements verticaux ponctuels. */
.mt-4  { margin-top: 4px; }
.mt-8  { margin-top: 8px; }
.mt-10 { margin-top: 10px; }
.mt-14 { margin-top: 14px; }
.mt-16 { margin-top: 16px; }
.mt-22 { margin-top: 22px; }
.mt-28 { margin-top: 28px; }
.my-24 { margin: 24px 0; }

/* Conteneur de formulaire : au-delà, les lignes deviennent trop longues à lire. */
.formulaire { max-width: 880px; }

/* Bloc centré verticalement dans la page — comptes suspendus, erreurs. */
.centre-page {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--surface);
}
.centre-page-boite { max-width: 460px; padding: 40px 32px; text-align: center; width: 100%; }
/* La trace d'une erreur 500 a besoin de largeur, sinon chaque frame se replie
   sur trois lignes et la pile devient illisible. */
.centre-page-boite.est-large { max-width: 860px; }
.centre-page-boite .auth-logo { margin-bottom: 24px; }

/* Code d'erreur HTTP. Gros, parce que c'est la seule information que
   l'utilisateur retiendra pour la rapporter. */
.erreur-code { font-size: 52px; font-weight: 800; line-height: 1; color: var(--accent); }
.erreur-code.est-critique { color: var(--critique); }

/* PASTILLE RONDE D'ILLUSTRATION — pages d'erreur et d'attente UNIQUEMENT.
   Ne pas reutiliser ce nom pour un statut de table : elle fait 56 px de
   diametre, et un statut portant cette classe ressortait en gros rond beige
   au milieu d'une rangee. Les statuts de table portent .etat. */
.pastille-ronde {
    width: 56px; height: 56px;
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    margin: 0 auto 16px;
    background: var(--attention-pale);
    color: var(--attention);
}

/* Bloc de trace technique, affiché hors production uniquement. */
.trace {
    overflow-x: auto;
    font-size: 11.5px;
    line-height: 1.6;
    background: var(--fond);
    padding: 12px;
    border-radius: 6px;
    margin: 0;
}

/* Page d'administration : pas de barre latérale, contenu centré. */
.page-admin { max-width: 1200px; margin: 0 auto; padding: 30px 26px 48px; }

/* =============================================================================
   LA BANDE D'INDICATEURS — six fiches s'en servent, elle vit donc ici
   =============================================================================
   Elle est nee dans la feuille du tableau de bord, puis l'analyse l'a reprise,
   puis les fiches chauffeur, vehicule, client et dossier. Une regle qui sert
   sur plus d'une page appartient a `app.css` : laissee dans une feuille de
   page, elle oblige chaque nouvelle page a declarer un style dont elle n'a
   besoin que pour trois classes — et le jour ou on l'oublie, la bande s'affiche
   sans mise en forme.

   PAS DE DESCRIPTION SOUS LE CHIFFRE, sauf quand elle porte une information
   que le nombre ne porte pas. « 2 560 000 — 0 course(s) + versements taxi »
   fait lire deux fois pour apprendre une fois.
   ========================================================================== */
/* --- LES INDICATEURS --------------------------------------------------------
   Six tuiles, et chacune porte son EVOLUTION. Un chiffre nu ne dit rien : la
   question n'est jamais « combien » mais « plus ou moins qu'avant ».
   -------------------------------------------------------------------------- */
/* MOBILE D'ABORD, ET C'EST LA SEULE FACON QUI TIENNE.
   Une regle `repeat(6, …)` ecrite ici sans borne gagne sur telephone contre
   celle de `mobile.css`, a specificite egale, parce que les feuilles de page
   sont chargees APRES elle — un `@media` n'ajoute aucune specificite. Mesure :
   la grille restait a six colonnes sur 390 px, chaque tuile a 58 px.
   La feuille de page part donc du plus petit et elargit vers le haut. */
/* `auto-fit` PLUTOT QU'UN NOMBRE DE COLONNES FIXE.
   Les fiches en portent quatre, l'analyse six, le dossier cinq : trois comptes
   figes auraient demande trois classes, et la quatrieme page aurait repris
   celle qui tombait le mieux plutot que la juste. La colonne ne descend jamais
   sous 150 px — en dessous, « 29 862 000 F » se replie. */
.an-kpis {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 10px;
    margin-top: 12px;
}
/* LA BORNE BASSE EST OBLIGATOIRE, ET C'EST UN PIEGE D'ORDRE DE CHARGEMENT.
   Les feuilles de page sont chargees APRES `mobile.css` : une regle ecrite ici
   sous `max-width: 1240px` ecrase celle que `mobile.css` pose sous
   `max-width: 900px`, alors meme qu'elle est moins specifique. Mesure : la
   grille restait a trois colonnes sur un ecran de 390 px, chaque tuile a
   118 px, et « 29 862 000 F » se repliait sur trois lignes.
   Toute regle de cette feuille qui touche a une taille doit donc s'arreter au
   seuil mobile. */
@media (min-width: 901px) { .an-kpi-n { font-size: 21px; } }

.an-kpi {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 11px 13px;
    background: var(--surface);
    border: 1px solid var(--trait);
    border-radius: var(--rayon);
    min-width: 0;
    text-decoration: none;
    color: inherit;
}
.an-kpi-l {
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .02em;
    text-transform: uppercase;
    color: var(--encre-pale);
}
.an-kpi-n {
    font-size: 18px;
    font-weight: 650;
    letter-spacing: -.02em;
    line-height: 1.15;
    font-variant-numeric: tabular-nums;
    color: var(--encre);
}
.an-kpi-u { font-size: 11px; font-weight: 500; color: var(--encre-pale); margin-left: 2px; }
.an-kpi-p { font-size: 10.5px; display: flex; align-items: baseline; gap: 5px; flex-wrap: wrap; }

.an-kpi.est-recette  .an-kpi-n { color: var(--accent-fonce); }
.an-kpi.est-depense  .an-kpi-n { color: var(--cta-fonce); }
.an-kpi.est-resultat { background: var(--accent-pale); border-color: var(--accent-pale); }
.an-kpi.est-creance:hover { border-color: var(--attention); }

/* L'EVOLUTION PORTE SON SENS, PAS SON SIGNE. Des depenses en hausse de 12 % ne
   se colorent pas comme des recettes en hausse de 12 % : le meme signe ne veut
   pas dire la meme chose, et une fleche verte sur une charge qui explose est un
   contresens. C'est la vue qui declare lequel des deux sens est bon. */
.ev {
    font-weight: 650;
    font-variant-numeric: tabular-nums;
    padding: 1px 5px;
    border-radius: var(--rayon-badge);
}
.ev.est-bon     { background: var(--positif-pale);   color: var(--positif); }
.ev.est-mauvais { background: var(--critique-pale);  color: var(--critique); }
.ev.est-neutre  { background: var(--fond);           color: var(--encre-doux); }

/* --- LA RANGEE D'ACTIONS D'UNE FICHE ----------------------------------------
   Appeler, relouer, imprimer : les gestes qu'on vient faire depuis une fiche.
   Enterres sous l'historique, ils obligent a faire defiler pour atteindre un
   bouton qu'on savait vouloir en ouvrant la page.
   -------------------------------------------------------------------------- */
.fiche-actions {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    margin-bottom: 10px;
}

/* Un indicateur qui porte une DATE ou un mot, pas un nombre : la chasse
   tabulaire et la taille du chiffre ne lui vont pas. */
.an-kpi-n.est-texte { font-size: 15px; font-weight: 600; letter-spacing: 0; }

/* --- LE BLOC REPLIABLE D'UN FORMULAIRE --------------------------------------
   Trois champs facultatifs sur huit : les afficher d'office fait paraitre le
   formulaire deux fois plus long qu'il n'est, et on les saute sans les lire.
   Replie, le formulaire tient dans un ecran ; ouvert, rien n'a bouge.
   -------------------------------------------------------------------------- */
.repli > summary {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    list-style: none;
    font-size: 12px;
    font-weight: 600;
    color: var(--accent-fonce);
    padding: 4px 0;
}
.repli > summary::-webkit-details-marker { display: none; }
.repli > summary::before {
    content: '+';
    display: inline-grid;
    place-items: center;
    width: 16px; height: 16px;
    border-radius: 4px;
    background: var(--accent-pale);
    font-size: 13px;
    line-height: 1;
}
.repli[open] > summary::before { content: '−'; }

/* Le choix de nature en version compacte : deux mots, pas deux paragraphes. */
.choix-nature.est-compact { gap: 8px; }
.choix-nature.est-compact .nature-option { padding: 9px 14px; }
.choix-nature.est-compact .nature-titre { font-size: 13px; }

/* La relance en un geste : un delai et un bouton, dans la cellule d'action.
   Ouvrir la fiche pour chaque relance fait quinze allers-retours par matinee —
   donc on ne relance pas. */
.relance-eclair { display: inline-flex; align-items: center; gap: 4px; }
.relance-eclair .champ-select {
    min-height: 26px;
    padding: 2px 20px 2px 6px;
    font-size: 11.5px;
    width: auto;
}

/* =============================================================================
   LA REPARTITION — quatre ecrans s'en servent, elle vit donc ici
   =============================================================================
   Nee dans la feuille du tableau de bord, reprise par l'analyse, les depenses,
   les rapports et le portefeuille du commercial. Laissee dans une feuille de
   page, elle obligeait chaque nouvelle page a declarer un style dont elle n'a
   besoin que pour quatre classes — et le jour ou on l'oublie, la repartition
   s'affiche en une seule ligne de texte au kilometre. Mesure : c'est exactement
   ce qui est arrive au portefeuille de /ma-performance.
   ========================================================================== */
/* --- LES REPARTITIONS -------------------------------------------------------
   La barre porte la PART, le chiffre porte la SOMME. Une proportion se lit en
   un trait, une somme se lit en chiffres — chacun fait ce qu'il sait faire.
   -------------------------------------------------------------------------- */
.an-bloc { padding: 9px 13px 11px; border-top: 1px solid var(--trait-fin); }
.an-bloc:first-of-type { border-top: 0; }
.an-bloc-t {
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .02em;
    text-transform: uppercase;
    color: var(--encre-pale);
    margin-bottom: 6px;
}
.an-part {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 56px 60px 32px;
    align-items: center;
    gap: 8px;
    padding: 3px 0;
    font-size: 11.5px;
}
.an-part-l { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.an-part-b { height: 5px; border-radius: 3px; background: var(--fond); overflow: hidden; }
.an-part-b > span { display: block; height: 100%; border-radius: 3px; }
.an-part-b.est-recette > span { background: var(--accent); }
.an-part-b.est-depense > span { background: var(--cta); }
.an-part-n { text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; }
.an-part-p { text-align: right; color: var(--encre-pale); font-variant-numeric: tabular-nums; }
@media (min-width: 901px) {
    .an-part { grid-template-columns: minmax(0, 1fr) 84px 62px 34px; }
}

.an-part-suite { font-size: 10.5px; color: var(--encre-pale); margin: -2px 0 5px; }
/* CHAQUE BARRE DE REPARTITION EST UN FILTRE. Annoncer qu'une nature pese 60 %
   sans permettre de l'isoler oblige a parcourir toute la liste — sur deux cents
   lignes, on ne le fait pas. */
.an-part-lien { text-decoration: none; color: inherit; border-radius: var(--rayon-champ); }
.an-part-lien:hover { background: var(--fond); }
.an-part-lien.est-actif { background: var(--accent-pale); }
.an-part-lien.est-actif .an-part-l { font-weight: 650; color: var(--accent-fonce); }

/* =============================================================================
   LE FILTRE D'ECRAN — l'analyse, la rentabilite, la performance
   =============================================================================
   Trois ecrans le portent, il vit donc ici. Laisse dans la feuille du tableau
   de bord, la page Performance l'a repris sans declarer le style : les
   raccourcis de periode se sont affiches en texte au kilometre, « Ce mois Mois
   dernier 3 mois Cette annee » sur une seule ligne. C'est le meme oubli qui
   avait aplati la repartition du portefeuille.
   ========================================================================== */
/* --- LE FILTRE --------------------------------------------------------------
   Il est en HAUT et il est COMPLET, parce qu'une analyse commence par
   restreindre. Un filtre qu'on doit deplier avant de s'en servir est un filtre
   qu'on n'ouvre pas : on se contente alors de la periode par defaut, et on
   passe a cote de la question qu'on venait poser.
   -------------------------------------------------------------------------- */
.an-filtre {
    background: var(--surface);
    border: 1px solid var(--trait);
    border-radius: var(--rayon);
    padding: 10px 12px;
}
.an-filtre-rang {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
}
@media (min-width: 901px) {
    .an-filtre-rang { flex-direction: row; flex-wrap: wrap; align-items: flex-end; }
}
.an-champ { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.an-champ > span {
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .02em;
    text-transform: uppercase;
    color: var(--encre-pale);
}
.an-champ .champ-saisie,
.an-champ .champ-select { min-width: 128px; }

.an-presets {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin-top: 9px;
    padding-top: 9px;
    border-top: 1px solid var(--trait-fin);
}
.an-preset {
    padding: 4px 10px;
    border-radius: var(--rayon-badge);
    border: 1px solid var(--trait);
    font-size: 11.5px;
    color: var(--encre-moy);
    text-decoration: none;
    white-space: nowrap;
}
.an-preset:hover { border-color: var(--encre-pale); color: var(--encre); }
.an-preset.est-actif {
    background: var(--accent-pale);
    border-color: var(--accent);
    color: var(--accent-fonce);
    font-weight: 600;
}
.an-portee { font-size: 11px; color: var(--encre-pale); font-variant-numeric: tabular-nums; }

@media (min-width: 901px) {
    .an-repli > summary { display: none; }
    .an-repli > .an-filtre-rang { display: flex; }
}

/* Le klaxon dans la file d'alertes : un geste qui agit sur le monde physique,
   mais qui ne met personne en danger. Ambre — ni neutre comme « Historique »,
   ni rouge comme la coupure. */
.btn-discret.est-alerte { color: var(--attention); font-weight: 600; }
.btn-discret.est-alerte:hover { background: var(--attention-pale); }
