/* ===========================================================================
   EASYSALES — FEUILLE DE MODULE (.vnt-*)

   POURQUOI UNE FEUILLE DE MODULE ET NON UNE FEUILLE PAR ÉCRAN
     La règle du dépôt est « un écran, une feuille » (CLAUDE.md), avec son
     exception écrite : « une classe employée par deux écrans ou plus remonte ».
     Le portage d'EasySales au gabarit (2026-09-08) a fait passer une vingtaine
     d'écrans du balisage Bootstrap (.md-card, .row g-2, .progress, .badge bg-*)
     à la trame .mx-* — et ce qui restait à écrire après ce passage était, à
     chaque fois, LE MÊME PEU : une colonne de montants alignée à droite, une
     grille de deux cartes côte à côte, une table plafonnée qui défile. Vingt
     feuilles d'écran auraient été vingt copies de ces cinquante lignes, et
     elles auraient divergé comme .apv-* et .cso-* l'ont fait avant elles.

     Le précédent est easypaie.css puis easyconso.css : une feuille par module,
     préfixe propre, ses propres paliers responsive. C'est le quatrième cas du
     dépôt et il est traité comme les trois autres.

   CE QUI N'EST PAS ICI, ET N'A PAS À Y ÊTRE
     Tout ce que le gabarit porte déjà. La trame de page, les boutons, la carte,
     la bande d'indicateurs, les barres de répartition, les pastilles d'état, la
     table de fiche, le bloc d'alerte, le groupe segmenté, la modale : ce sont
     .mx-* et rien d'autre. Une classe .vnt- qui redirait l'une d'elles serait
     une divergence en attente.

   AUCUNE COULEUR LITTÉRALE. Tout passe par les jetons --et-* de
   easytech-theme.css — thème sombre compris, sans une ligne de plus.
   =========================================================================== */

/* ---------------------------------------------------------------------------
   1. ALIGNEMENT DES CELLULES

   .mx-tbl th force text-align:left (0,1,1 en spécificité). Un simple
   .vnt-droite (0,1,0) ne le battrait pas : d'où la portée par .mx-tbl, qui
   monte à 0,2,0. La forme nue reste définie pour les rares emplois hors table.
   --------------------------------------------------------------------------- */
.vnt-droite { text-align: right; }
.vnt-centre { text-align: center; }
.mx-tbl .vnt-droite { text-align: right; }
.mx-tbl .vnt-centre { text-align: center; }

/* Le libellé d'un mois arrive en minuscules du serveur — « janvier » — et se lit
   en tête de rangée comme un intitulé, donc capitalisé. C'est une règle de
   RENDU, pas de donnée : le serveur n'a pas à choisir la casse d'un affichage. */
.vnt-capitale { text-transform: capitalize; }

/* ---------------------------------------------------------------------------
   2. UN MONTANT NÉGATIF DANS UNE TABLE

   Le gabarit a .mx-fait-val.est-negatif et .mx-ind.est-negatif, mais rien pour
   une CELLULE : une marge négative en liste n'avait donc que .text-danger de
   Bootstrap, c'est-à-dire --et-danger posé en `color:`. La charte l'interdit —
   « une couleur d'état n'est jamais écrite en color: » — et la mesure lui donne
   raison ici plus qu'ailleurs : --et-danger rend 4,83:1 sur blanc mais 4,13:1
   sur --et-rang, le fond d'une rangée SURVOLÉE. Un chiffre de liste passe donc
   sous AA au moment précis où on pose le curseur dessus pour le lire.
   L'encre du rang, elle, tient sur les trois fonds.
   --------------------------------------------------------------------------- */
.vnt-negatif { color: var(--et-danger-ink); }

/* Son pendant positif — la variation de CA « +12,4 % vs N-1 ». Même raison,
   même rang : --et-succes rend 3,30:1 sur blanc, c'est-à-dire au-dessus du seuil
   GRAPHIQUE (3:1) et en dessous du seuil de TEXTE (4,5:1). Il passe comme barre,
   pas comme chiffre. */
.vnt-positif { color: var(--et-succes-ink); }

/* ---------------------------------------------------------------------------
   3. RANGÉE EN ANOMALIE — le pendant `danger` de .mx-tbl tr.est-alerte

   Le gabarit n'a que l'ambre (est-terne, est-alerte). EasySales a besoin du
   cran au-dessus : un dépassement de plafond et une facture échue ne sont pas
   « à surveiller », ils sont hors des clous. Même forme exactement — aplat pâle
   plus liseré à gauche — pour que les deux se lisent comme deux degrés d'une
   même chose et non comme deux inventions.

   LE LISERÉ N'EST PAS DÉCORATIF : en thème sombre l'aplat rouge pâle descend à
   quelques pour cent du fond, et c'est lui qui reste.
   --------------------------------------------------------------------------- */
.mx-tbl tbody tr.vnt-rang-danger td { background: var(--et-danger-badge-bg); }
.mx-tbl tbody tr.vnt-rang-danger td:first-child { box-shadow: inset 3px 0 0 var(--et-danger); }

/* ---------------------------------------------------------------------------
   4. GRILLE DE DEUX CARTES CÔTE À CÔTE

   Remplace le `row g-3 / col-12 col-xl-7 / col-12 col-xl-5` de Bootstrap, qui
   écrivait des largeurs en douzièmes dans le balisage de la page. Ici la
   répartition est une règle de feuille, et le palier vient de l'échelle retenue
   (docs/conventions-responsive.md) et non du `xl` de Bootstrap — lequel tombe à
   1200 px, une valeur que le dépôt n'emploie nulle part ailleurs.
   --------------------------------------------------------------------------- */
.vnt-cols {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 12px;
    align-items: start;
}

/* Sous 1024 px, deux tables de quatre colonnes côte à côte donnent des colonnes
   de montants trop étroites pour leur propre en-tête : elles passent l'une sous
   l'autre. C'est le palier de l'échelle, celui du rail et des cibles tactiles. */
@media (max-width: 1024px) {
    .vnt-cols { grid-template-columns: minmax(0, 1fr); }
}

/* ---------------------------------------------------------------------------
   5. RESPIRATIONS

   Deux, et deux seulement — la bande d'indicateurs au-dessus du contenu, et le
   demi-cran d'une seconde ligne dans une cellule. Tout autre écart est celui du
   gabarit et ne se réécrit pas ici.
   --------------------------------------------------------------------------- */
.vnt-espace { margin-bottom: 12px; }
.vnt-espace-mince { margin-top: 4px; }

/* Deux pastilles dans une même cellule (« facturation » et « livraison ») se
   touchaient : le gabarit ne prévoit pas la pastille en série. */
.mx-pastille + .mx-pastille { margin-left: 4px; }
.mx-tbl-fort > .mx-pastille { margin-left: 6px; }

/* ---------------------------------------------------------------------------
   6. TABLE PLAFONNÉE

   Un classement — articles les plus vendus, marge par client — n'a pas de fin :
   il en tient trente à l'écran et les suivants défilent DANS la carte, sans
   emporter la page. L'en-tête reste posé pendant le défilement, sans quoi la
   colonne de droite cesse d'avoir un nom au bout de dix rangées.
   --------------------------------------------------------------------------- */
.vnt-defile { max-height: 30rem; overflow-y: auto; }

/* La variante COURTE sert les vignettes d'un tableau de bord, où quatre listes
   se partagent la hauteur d'écran : au-delà de 22 rem, la quatrième passe sous
   la ligne de flottaison et le tableau de bord cesse d'en être un. */
.vnt-defile-court { max-height: 22rem; overflow-y: auto; }

.vnt-defile .mx-tbl thead th,
.vnt-defile-court .mx-tbl thead th { position: sticky; top: 0; z-index: 1; }

/* ---------------------------------------------------------------------------
   7. LARGEURS DE COLONNES QUE LA TABLE NE DEVINE PAS

   Une jauge n'a pas de contenu à mesurer : sans largeur imposée elle se réduit
   à son minimum et la rangée devient illisible. Une colonne de boutons de fin
   de rangée, symétriquement, ne doit pas prendre plus que ses boutons.
   --------------------------------------------------------------------------- */
.vnt-col-jauge { width: 22%; min-width: 120px; }
.vnt-col-actions { width: 92px; }
.vnt-col-case { width: 2.4rem; }
.vnt-col-niveau { width: 70px; }

/* Une colonne de SAISIE se dimensionne sur son champ, pas sur son contenu : un
   « 1 » ne doit pas donner une case plus étroite qu'un « 1000 », sans quoi la
   colonne bouge à chaque frappe. */
.vnt-col-saisie { width: 8rem; }

/* RANGÉE DE TOTAUX. Le gabarit ne décrit que thead et tbody : un tfoot y prend
   le rembourrage des cellules et rien d'autre, si bien que la ligne des totaux
   se lit comme une rangée de données de plus. Elle reprend le fond du bandeau —
   le même repli d'un ton que .mx-carte-tete — et son filet haut.

   PORTÉE PAR UNE CLASSE, et non par le sélecteur `.mx-tbl tfoot` : ce dernier
   habillerait tous les .mx-tbl de l'application depuis une feuille de module,
   c'est-à-dire une décision de gabarit prise depuis un module. */
.mx-tbl .vnt-totaux td {
    background: var(--et-surface-2);
    border-top: 1px solid var(--et-hairline);
    border-bottom: 0;
}

/* ---------------------------------------------------------------------------
   8. CONTRÔLES POSÉS DANS UNE BARRE D'OUTILS OU UN BANDEAU DE CARTE

   .mx-input et .mx-select prennent 100 % de leur conteneur — c'est ce qu'il faut
   dans la grille dense d'une fiche, et jamais dans une barre d'outils, où un
   sélecteur d'exercice n'a que quatre chiffres à montrer.
   --------------------------------------------------------------------------- */
.vnt-annee { width: 6.5rem; }
.vnt-mois { width: 9rem; }
.vnt-recherche { width: 15rem; max-width: 100%; }

/* Le sélecteur de client porte « CODE — Raison sociale » : à 6 rem il ne montre
   que le code, c'est-à-dire ce qu'on ne cherche pas. */
.vnt-choix-client { width: 20rem; max-width: 100%; }

/* Poussé au bout du bandeau de carte, qui est un flex. `margin-left:auto` en
   ligne aurait fait l'affaire ; nommé, il ne se recopie pas de travers. */
.vnt-tete-fin { margin-left: auto; }

/* Un bouton qui prend toute la largeur de son conteneur — le « Transformer » au
   pied d'une carte de kanban, seul geste de sa rangée. Nommé plutôt que .w-100
   de Bootstrap : le gabarit n'emprunte pas ses utilitaires. */
.vnt-large { width: 100%; }

/* Une colonne de boutons de fin de rangée qui en porte trois — « Avoir »,
   « Entrée », « Remplacement » sur un retour résolu — ne doit pas les couper en
   deux lignes au milieu d'un mot. */
.vnt-nowrap { white-space: nowrap; }

/* Un champ et son bouton sur une même rangée de la grille dense — « ajouter une
   pièce » et son « + ». Le bouton ne s'étire pas : il fait sa largeur, le champ
   prend le reste. */
.vnt-rang-champ { display: flex; align-items: center; gap: 8px; }
.vnt-rang-champ > .mx-input { flex: 1 1 auto; min-width: 0; }
.vnt-rang-champ > .mx-btn { flex: none; }

/* Un message de LOT arrive en plusieurs lignes — « FV-0031 : passerelle
   injoignable » par facture en échec. Les jointer d'un espace en ferait un
   paragraphe illisible ; le bloc d'alerte du gabarit, lui, ne préjuge pas du
   nombre de lignes de son texte. */
.vnt-prelignes { white-space: pre-line; }

/* ---------------------------------------------------------------------------
   8bis. LISTE DE SUGGESTIONS SOUS UN CHAMP DE RECHERCHE

   Remplace le .list-group de Bootstrap, qui apportait son rayon, son ombre et
   son bleu de survol. Trois écrans du module cherchent un article de la même
   façon — modèles de devis, marchés, facturation périodique — et la liste est
   la même à chaque fois : un code en mono, un libellé, et la rangée entière
   cliquable.

   ELLE EST PLAFONNÉE ET DÉFILE : une recherche à deux lettres ramène un
   catalogue, et une liste sans plafond pousserait le reste du formulaire hors
   de l'écran à chaque frappe.
   --------------------------------------------------------------------------- */
.vnt-suggestions {
    margin-top: 4px;
    max-height: 200px; overflow-y: auto;
    border: 1px solid var(--et-hairline);
    background: var(--et-surface);
}
.vnt-suggestion {
    display: flex; align-items: baseline; gap: 8px;
    width: 100%; padding: 5px 10px;
    border: 0; border-bottom: 1px solid var(--et-hairline);
    background: var(--et-surface); color: var(--et-ink);
    font-family: inherit; font-size: 13px; text-align: left; cursor: pointer;
}
.vnt-suggestion:last-child { border-bottom: 0; }
.vnt-suggestion:hover { background: var(--et-rang); }
.vnt-suggestion:focus-visible { outline: 2px solid var(--et-form-blue); outline-offset: -2px; }

/* ---------------------------------------------------------------------------
   9. CLASSE ABC — UNE IDENTITÉ, PAS UN ÉTAT

   A, B et C disent le POIDS d'un client dans le portefeuille, pas sa santé : un
   client « C » ne va pas mal. Les trois portaient pourtant .bg-success /
   .bg-warning / .bg-light, c'est-à-dire les couleurs d'état de la charte —
   et le tableau se lisait alors comme un feu tricolore que le calcul ne dit
   nulle part.

   Les trois teintes viennent donc de la palette d'identité, --et-cat-1..3, DANS
   L'ORDRE, et l'écran les nomme par PaletteCategorielle plutôt que d'écrire un
   hexadécimal. Elles arrivent ici par --vnt-abc, sur le patron de --vig
   d'easycompta-vignette.css : la feuille tient la forme, l'écran choisit le
   rang.

   LA TEINTE EST UN REPÈRE, PAS UN APLAT SOUS DU TEXTE. La lettre reste en
   encre : à 12 px, une lettre blanche sur --et-cat-2 (olive) ou --et-cat-7 (or)
   ne tient pas le seuil AA, et un aplat par classe aurait fait trois pastilles
   dont une illisible.
   --------------------------------------------------------------------------- */
.vnt-abc {
    display: inline-block;
    min-width: 22px;
    padding: 1px 6px;
    border: 1px solid var(--et-hairline);
    border-left: 3px solid var(--vnt-abc, var(--et-cat-1));
    background: var(--et-surface-2);
    font-family: var(--et-font-mono); font-size: 12px; font-weight: 600;
    color: var(--et-ink); text-align: center; line-height: 18px;
}

/* ---------------------------------------------------------------------------
   10. PALIERS — geometry only, et rien d'autre

   Recette à 390 / 768 / 1280 / 1600 px, paliers pris dans l'échelle retenue
   (docs/conventions-responsive.md §2). Aucune couleur ici : un palier impose
   une géométrie, jamais une apparence.

   LA RÈGLE TACTILE (docs/cibles-tactiles.md) : sous 1024 px, aucune cible
   interactive ne descend sous 44 px, et une cible ne rétrécit jamais. Les
   contrôles de barre d'outils de ces écrans — sélecteur d'exercice, champ de
   recherche — sont des .mx-input / .mx-select de 34 px : ils montent.
   --------------------------------------------------------------------------- */
@media (max-width: 1024px) {
    .vnt-annee, .vnt-mois, .vnt-recherche, .vnt-choix-client { min-height: 44px; }
    .mx-tbl .vnt-col-actions .mx-btn { min-width: 44px; min-height: 44px; }
    .vnt-suggestion { min-height: 44px; }
}

/* Sous 720 px — le palier de la grille dense du gabarit — un champ de recherche
   de 15 rem occupe la moitié de la barre d'outils. Il prend la largeur, ce qui
   le remet sur sa propre ligne plutôt que de comprimer le titre. */
@media (max-width: 720px) {
    .vnt-recherche { width: 100%; }
    .vnt-col-jauge { width: auto; min-width: 88px; }
}
