/* ===========================================================================
   ÉCRAN DES DOCUMENTS DE VENTE — devis, commandes, bons de livraison,
   factures, avoirs (passation « EasySales — documents de vente »).

   UN ÉCRAN, UNE FEUILLE, UN <link>. Elle est chargée dans App.razor APRÈS
   modele-erp.css, et elle n'emporte QUE ce qui sert ici. Les cartes, les
   pastilles, les boutons, la modale, le formulaire dense, la bande de faits
   viennent du gabarit (.mx-*) et ne sont pas redéclarés.

   AUCUNE COULEUR EN DUR. Chaque teinte passe par un jeton --et-* de
   easytech-theme.css. C'est ce qui fait que le thème sombre suit sans une
   ligne de plus ici, et c'est la règle du dépôt depuis la bascule de charte.

   POURQUOI CET ÉCRAN A SA FEUILLE PLUTÔT QUE LA QUEUE DU GABARIT
   Il porte trois objets qui n'existent nulle part ailleurs et qu'il serait
   faux de généraliser : le FIL DU CYCLE (DV → CC → BL → FV), la GRILLE DE
   SAISIE à quatre types de rangée (article, section, commentaire, kit), et
   l'APERÇU A4 avec son filigrane. Les monter dans le gabarit obligerait tout
   écran de liste à porter leur poids.

   L'ÉCHELLE DE TEXTE EST CELLE DE LA RÉVISION DU 2026-09-02 : aucune fraction,
   rien sous 12 px. Cette feuille avait échappé au passage — elle portait
   17 sites en 11,5 et 12,5 px, plus un 17 px et deux 22 px. Ils sont alignés
   (12, 13, 18, 24), ce qui ne change pas la hiérarchie : --et-fs-tete (14 px)
   domine toujours --et-fs-cell (13 px), et une colonne se lit par son titre.
   La passation d'origine annonçait « 21/17/13,5/12,5/11,5/10,5 » — elle est
   antérieure à la révision, qui la supersède.

   SOMMAIRE
     1.  Trame des deux états
     2.  Liste — en-tête, onglets de type, indicateurs
     3.  Liste — facettes et tableau
     4.  Fiche — bandeau, versions, fil du cycle
     5.  Fiche — carte de résumé, jauge d'encours, popovers
     6.  Grille — barre d'outils, suggestions, sélection
     7.  Grille — les quatre types de rangée
     8.  Colonne latérale — contrôles, totaux, journal
     9.  Volet client
    10.  Aperçu de la pièce et filigrane
    10 bis. Circuit d'approbation
    10 ter. Le dossier — pièces jointes, envoi & suivi, fenêtre d'envoi
    11.  Paliers de largeur
    12.  Impression
   =========================================================================== */

/* ===========================================================================
   1. TRAME DES DEUX ÉTATS

   La liste et la fiche sont deux états d'un même écran, pas deux routes :
   revenir à la liste doit rendre ses filtres intacts. Elles partagent donc la
   trame, et ne divergent qu'à partir de l'en-tête.
   =========================================================================== */
.dev-ecran {
    font-family: var(--et-font);
    color: var(--et-ink);
    background: var(--et-surface-2);
    min-height: 100%;
}

/* L'EN-TÊTE EST COLLANT, le corps défile dessous. Sur un devis de quarante
   lignes, le numéro et le bouton d'engagement doivent rester atteignables :
   sans cela, valider demande de remonter tout le document. */
.dev-tete {
    position: sticky; top: 0; z-index: 12;
    background: var(--et-surface);
    border-bottom: 1px solid var(--et-hairline);
    padding: 14px 24px 0;
}
.dev-tete.est-fiche { padding-bottom: 14px; }

.dev-tete-in { max-width: 1600px; margin: 0 auto; }

.dev-surtitre { font-size: 12px; color: var(--et-muted); }
.dev-tete h1 {
    margin: 2px 0 0; font-size: 21px; font-weight: 700; letter-spacing: -.02em;
    color: var(--et-ink);
}

.dev-corps { max-width: 1600px; margin: 0 auto; padding: 18px 24px 26px; }

/* Le mot qui explique la carte, en pied. Même rôle que .mx-carte-pied — repris
   ici parce que les blocs de cet écran ne sont pas tous des .mx-carte. */
.dev-mention {
    padding: 10px 14px;
    background: var(--et-surface-3);
    border-top: 1px solid var(--et-hairline);
    font-size: 12px; color: var(--et-muted);
}
.dev-mention i { margin-right: 5px; }

/* ===========================================================================
   2. LISTE — onglets de type et bande d'indicateurs
   =========================================================================== */

/* Les cinq types du cycle, chacun avec son compteur. Un rang d'onglets et non
   un sélecteur : le compteur est l'information, et un sélecteur le cacherait
   derrière un clic. */
.dev-onglets {
    display: flex; flex-wrap: wrap; gap: 2px; margin-top: 14px;
}
.dev-onglet {
    display: inline-flex; align-items: center; gap: 8px;
    padding: 10px 14px;
    background: transparent; border: 0; border-bottom: 2px solid transparent;
    font-family: inherit; font-size: 14px; color: var(--et-muted);
    cursor: pointer; white-space: nowrap;
    transition: color .12s, border-color .12s;
}
.dev-onglet:hover { color: var(--et-form-blue-d); }
.dev-onglet.est-actif {
    color: var(--et-form-blue); font-weight: 700;
    border-bottom-color: var(--et-form-blue);
}
.dev-onglet-n {
    padding: 1px 7px; border-radius: var(--et-r-pill);
    background: var(--et-surface-2); color: var(--et-muted);
    font-family: var(--et-font-mono); font-size: 12px;
}
.dev-onglet.est-actif .dev-onglet-n { background: var(--et-tint); color: var(--et-form-blue-d); }

/* LA BANDE DE QUATRE INDICATEURS, propre au type courant. Le filet supérieur
   de 3 px porte le SENS de l'indicateur — c'est la seule couleur de la tuile,
   et elle se lit avant le chiffre. */
.dev-ind-grille {
    display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px;
    margin-bottom: 16px;
}
.dev-ind {
    background: var(--et-surface);
    border: 1px solid var(--et-hairline);
    border-top: 3px solid var(--et-form-blue);
    padding: 14px 16px; min-width: 0;
}
.dev-ind.sens-succes { border-top-color: var(--et-succes); }
.dev-ind.sens-alerte { border-top-color: var(--et-avertissement-mark); }
.dev-ind.sens-danger { border-top-color: var(--et-danger); }
.dev-ind.sens-neutre { border-top-color: var(--et-table-head); }

.dev-ind-lbl {
    display: flex; align-items: center; gap: 7px;
    font-size: 12px; font-weight: 600; text-transform: uppercase;
    letter-spacing: .06em; color: var(--et-muted);
}
.dev-ind-val {
    margin-top: 6px;
    font-family: var(--et-font-mono); font-size: 24px; font-weight: 600;
    letter-spacing: -.02em; font-variant-numeric: tabular-nums;
    color: var(--et-ink);
    /* Un montant à sept chiffres ne doit pas élargir sa tuile et déformer la
       rangée : il se rogne, la valeur exacte reste dans l'infobulle. */
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dev-ind-val.est-succes { color: var(--et-succes-ink); }
.dev-ind-val.est-alerte { color: var(--et-avertissement-ink); }
.dev-ind-val.est-danger { color: var(--et-danger-ink); }
.dev-ind-detail { margin-top: 2px; font-size: 12px; color: var(--et-muted); }

/* ===========================================================================
   3. LISTE — facettes et tableau

   Deux colonnes : un filtre latéral de 212 px et la table. Le filtre est une
   COLONNE et non une barre : les facettes portent leurs compteurs, et une
   barre les aurait repliées derrière un menu — c'est-à-dire cachées.
   =========================================================================== */
.dev-liste { display: grid; grid-template-columns: 212px minmax(0, 1fr); gap: 16px; align-items: start; }

.dev-filtre { background: var(--et-surface); border: 1px solid var(--et-hairline); }
.dev-filtre-tete {
    padding: 11px 14px; border-bottom: 1px solid var(--et-hairline);
    font-size: 12px; font-weight: 700; text-transform: uppercase;
    letter-spacing: .14em; color: var(--et-muted);
}
.dev-filtre-groupe { padding: 10px 10px 4px; }
.dev-filtre-lbl {
    padding: 0 4px 6px;
    font-size: 12px; font-weight: 700; text-transform: uppercase;
    letter-spacing: .1em; color: var(--et-inerte);
}
.dev-facette {
    display: flex; align-items: center; gap: 8px; width: 100%;
    padding: 7px 8px; margin-bottom: 2px;
    border: 0; background: transparent; border-radius: var(--et-r-btn);
    font-family: inherit; font-size: 13px; color: var(--et-ink);
    text-align: left; cursor: pointer;
}
.dev-facette:hover { background: var(--et-surface-2); }
.dev-facette.est-active { background: var(--et-tint); color: var(--et-form-blue-d); font-weight: 600; }
.dev-facette-puce { width: 8px; height: 8px; border-radius: 0; flex: none; background: var(--et-inerte); }
.dev-facette-puce.est-brouillon { background: var(--et-neutre); }
.dev-facette-puce.est-valide    { background: var(--et-form-blue); }
.dev-facette-puce.est-partiel   { background: var(--et-avertissement); }
.dev-facette-puce.est-solde     { background: var(--et-succes); }
.dev-facette-puce.est-annule    { background: var(--et-danger); }
.dev-facette-txt { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.dev-facette-n { font-family: var(--et-font-mono); font-size: 12px; color: var(--et-muted); }

.dev-filtre-bas {
    padding: 10px 14px 14px; margin-top: 6px;
    border-top: 1px solid var(--et-rang);
}
.dev-filtre-bas .dev-filtre-lbl { padding: 0 0 8px; }
.dev-filtre-bas .dev-filtre-lbl + .dev-filtre-lbl { padding-top: 14px; }

/* ---- La table ---- */
.dev-table-cadre { background: var(--et-surface); border: 1px solid var(--et-hairline); }
.dev-table-barre {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 14px; border-bottom: 1px solid var(--et-hairline);
    flex-wrap: wrap;
}
.dev-recherche { position: relative; flex: 1; max-width: 300px; min-width: 180px; }
.dev-recherche > i {
    position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
    color: var(--et-muted); font-size: 13px; pointer-events: none;
}
.dev-recherche input {
    width: 100%; height: 32px; padding: 0 10px 0 31px;
    font-family: inherit; font-size: 13px; color: var(--et-ink);
    background: var(--et-surface);
    border: 1px solid var(--et-form-border); border-radius: var(--et-r-btn);
    outline: none;
}
.dev-recherche input:focus { border-color: var(--et-form-blue); }
.dev-table-compte { font-size: 13px; color: var(--et-muted); }

.dev-defile { overflow-x: auto; }
.dev-table { width: 100%; min-width: 960px; font-size: 13px; border-collapse: collapse; }
.dev-table thead tr { background: var(--et-table-head); color: var(--et-sur-ardoise); }
.dev-table th {
    text-align: left; font-weight: 600; font-size: 12px;
    text-transform: uppercase; letter-spacing: .08em; padding: 9px 10px;
    white-space: nowrap;
}
.dev-table th.num, .dev-table td.num { text-align: right; }
.dev-table td { padding: 9px 10px; vertical-align: middle; }
.dev-table tbody tr {
    border-bottom: 1px solid var(--et-rang);
    cursor: pointer;
}
.dev-table tbody tr:hover { background: var(--et-tint); }
/* Une pièce en retard prend un fond, pas une couleur de texte : la ligne
   entière est en cause, pas l'une de ses cellules. */
.dev-table tbody tr.est-retard { background: var(--et-danger-badge-bg); }
.dev-table tbody tr.est-retard:hover { background: var(--et-tint); }

.dev-cell-num {
    font-family: var(--et-font-mono); font-size: 13px; font-weight: 600;
    color: var(--et-ink);
}
.dev-cell-sous { font-size: 12px; color: var(--et-muted); }
.dev-cell-fort { font-weight: 600; font-size: 13px; }
.dev-mono { font-family: var(--et-font-mono); font-variant-numeric: tabular-nums; }
.dev-du { color: var(--et-danger-ink); font-weight: 600; }
.dev-alerte-txt { font-size: 12px; margin-top: 2px; color: var(--et-danger-ink); font-weight: 600; }

/* LES JETONS DU CYCLE. Trois états et trois seulement : le type courant en
   plein ardoise, un maillon existant en teinte d'information, un maillon à
   créer en gris inerte. Un quatrième état rendrait la colonne illisible au
   survol d'un tableau de cinq cents lignes. */
.dev-chaine { display: flex; align-items: center; gap: 3px; }
.dev-jeton {
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 20px; border-radius: 0;
    font-family: var(--et-font-mono); font-size: 12px; font-weight: 700;
    background: var(--et-surface-2); color: var(--et-inerte);
}
.dev-jeton.est-fait { background: var(--et-tint); color: var(--et-form-blue-d); }
.dev-jeton.est-courant { background: var(--et-table-head); color: var(--et-surface); }

.dev-table-pied {
    display: flex; align-items: center; gap: 12px;
    padding: 11px 14px; border-top: 1px solid var(--et-hairline);
    background: var(--et-surface-3); font-size: 13px; color: var(--et-muted);
    flex-wrap: wrap;
}
.dev-pagination { margin-left: auto; display: inline-flex; border: 1px solid var(--et-form-border); }
.dev-pagination button {
    height: 30px; padding: 0 11px; border: 0; background: var(--et-surface);
    color: var(--et-ink); font-family: inherit; font-size: 13px; cursor: pointer;
}
.dev-pagination button + button { border-left: 1px solid var(--et-form-border); }
.dev-pagination button:disabled { color: var(--et-inerte); cursor: not-allowed; }
.dev-pagination button.est-actif { background: var(--et-table-head); color: var(--et-surface); }

/* ===========================================================================
   4. FICHE — bandeau, versions, fil du cycle
   =========================================================================== */
.dev-tete-rang {
    display: flex; align-items: flex-end; gap: 16px; margin-top: 8px; flex-wrap: wrap;
}
.dev-tete-txt { flex: 1 1 360px; min-width: 280px; }
.dev-tete-ligne { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

.dev-numero {
    margin: 0; font-family: var(--et-font-mono);
    font-size: 24px; font-weight: 700; letter-spacing: -.02em;
    white-space: nowrap; color: var(--et-ink);
}
.dev-filiation { font-size: 13px; color: var(--et-muted); }
.dev-filiation i { margin-right: 4px; }

.dev-versions { display: flex; align-items: center; gap: 6px; margin-top: 8px; flex-wrap: wrap; }
.dev-versions-lbl {
    font-size: 12px; font-weight: 600; text-transform: uppercase;
    letter-spacing: .08em; color: var(--et-muted);
}
.dev-version {
    display: inline-flex; align-items: baseline; gap: 6px;
    padding: 3px 10px; border-radius: var(--et-r-pill);
    border: 1px solid var(--et-hairline); background: var(--et-surface);
    font-family: inherit; font-size: 12px; color: var(--et-muted); cursor: pointer;
}
.dev-version.est-active { border-color: var(--et-form-blue); color: var(--et-form-blue-d); font-weight: 600; }
.dev-version-tag { font-family: var(--et-font-mono); font-weight: 600; }
.dev-version-montant { font-family: var(--et-font-mono); }

/* LE FIL DU CYCLE. Les maillons se touchent — bordure droite retirée sauf sur
   le dernier — pour se lire comme une seule frise et non comme cinq boutons. */
.dev-fil-cycle { display: flex; align-items: stretch; margin-top: 14px; flex-wrap: wrap; }
.dev-maillon {
    display: flex; align-items: center; gap: 8px;
    padding: 6px 14px 6px 12px;
    border: 1px solid var(--et-hairline); border-right: 0;
    background: var(--et-surface); color: var(--et-inerte);
}
.dev-maillon:last-of-type { border-right: 1px solid var(--et-hairline); }
.dev-maillon.est-fait { background: var(--et-tint); color: var(--et-form-blue-d); border-color: var(--et-info-bord); }
.dev-maillon.est-courant { background: var(--et-table-head); color: var(--et-surface); border-color: var(--et-table-head); }
.dev-maillon-lbl { font-size: 12px; font-weight: 600; line-height: 1.2; }
.dev-maillon-ref { font-size: 12px; font-family: var(--et-font-mono); opacity: .85; line-height: 1.2; }

/* Le bouton pointillé « Transformer en … » : il propose, il n'engage pas —
   d'où le trait interrompu plutôt que l'orange, qui est déjà pris par la
   validation. Un écran, un seul bouton orange. */
.dev-suite {
    display: inline-flex; align-items: center; gap: 6px;
    height: 44px; padding: 0 14px; margin-left: 8px;
    border: 1px dashed var(--et-form-blue); background: var(--et-surface);
    color: var(--et-form-blue); font-family: inherit; font-size: 13px;
    font-weight: 600; cursor: pointer;
}
.dev-suite:hover { background: var(--et-tint); }

/* LE BANDEAU DE DÉPASSEMENT. Un blocage DOUX : il dit ce qui cloche et laisse
   une issue nominative. Un refus sec renverrait le commercial au téléphone,
   et la décision ne serait consignée nulle part. */
/* ===========================================================================
   5. FICHE — carte de résumé, jauge d'encours, popovers
   =========================================================================== */
.dev-grille-fiche {
    display: grid; grid-template-columns: minmax(0, 1fr) 320px;
    gap: 16px; align-items: start;
}
.dev-colonne { min-width: 0; }
/* La colonne droite est COLLANTE : les contrôles et le total doivent rester
   sous les yeux pendant qu'on saisit la vingtième ligne. */
.dev-laterale { position: sticky; top: 92px; display: flex; flex-direction: column; gap: 12px; }

.dev-bloc { background: var(--et-surface); border: 1px solid var(--et-hairline); margin-bottom: 16px; }
.dev-laterale .dev-bloc { margin-bottom: 0; }
.dev-bloc-tete {
    display: flex; align-items: center; gap: 8px;
    padding: 11px 16px; border-bottom: 1px solid var(--et-hairline);
    font-size: 12px; font-weight: 700; text-transform: uppercase;
    letter-spacing: .12em; color: var(--et-muted);
}
.dev-bloc-tete .sur-titre { margin-left: auto; font-size: 12px; letter-spacing: 0; text-transform: none; font-weight: 400; }
.dev-bloc-corps { padding: 10px 16px 14px; }

.dev-resume { display: flex; align-items: flex-start; gap: 18px; padding: 14px 16px; flex-wrap: wrap; }
.dev-resume-client { display: flex; align-items: flex-start; gap: 12px; flex: 1 1 420px; min-width: 300px; }
.dev-initiales {
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px; border-radius: 50%; flex: none;
    background: var(--et-blue); color: var(--et-surface);
    font-size: 14px; font-weight: 700;
}
.dev-client-nom {
    padding: 0; border: 0; background: transparent; font-family: inherit;
    font-size: 18px; font-weight: 700; letter-spacing: -.02em;
    color: var(--et-form-blue-d); cursor: pointer;
    text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px;
}
.dev-client-nom:hover { color: var(--et-form-blue); }

/* Les cinq faits clés, en libellé/valeur. Ils ne sont pas dans un .mx-champ :
   ce n'est pas un formulaire, c'est une lecture — et le libellé à droite du
   gabarit dense n'a pas de sens sur une ligne de cinq colonnes. */
.dev-faits { display: flex; flex-wrap: wrap; gap: 10px 26px; margin-top: 8px; }
.dev-fait { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.dev-fait-lbl {
    font-size: 12px; font-weight: 700; text-transform: uppercase;
    letter-spacing: .11em; color: var(--et-inerte);
}
.dev-fait-val { font-size: 13px; color: var(--et-ink); }
.dev-fait-val.mono { font-family: var(--et-font-mono); }

.dev-sep-vert { width: 1px; align-self: stretch; background: var(--et-rang); }

/* LA JAUGE D'ENCOURS. Quatre pixels, pas davantage : c'est un signal, pas un
   graphique. Elle porte la seule chose qu'un commercial ne peut pas deviner —
   ce que la validation de CE document fera passer au plafond. */
.dev-encours { min-width: 210px; position: relative; flex: 0 1 260px; }
.dev-encours-rang { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.dev-encours-lbl {
    font-size: 12px; font-weight: 700; text-transform: uppercase;
    letter-spacing: .1em; color: var(--et-muted);
}
.dev-encours-val { font-family: var(--et-font-mono); font-size: 13px; font-weight: 600; }
.dev-jauge { height: 4px; margin-top: 5px; background: var(--et-piste); overflow: hidden; }
.dev-jauge > i { display: block; height: 100%; background: var(--et-form-blue); }
.dev-jauge.est-tendu > i { background: var(--et-avertissement); }
.dev-jauge.est-depasse > i { background: var(--et-danger); }
.dev-encours-legende { margin-top: 3px; font-size: 12px; color: var(--et-muted); }

.dev-liens { display: flex; flex-direction: column; gap: 2px; margin-top: 9px; padding-top: 8px; border-top: 1px solid var(--et-rang); }
.dev-lien {
    display: flex; align-items: center; gap: 7px; width: 100%;
    padding: 3px 0; border: 0; background: transparent;
    font-family: inherit; font-size: 12px; color: var(--et-form-blue-d);
    text-align: left; cursor: pointer;
}
.dev-lien:hover { color: var(--et-form-blue); }
.dev-lien-txt { flex: 1; text-decoration: underline; text-underline-offset: 2px; }
.dev-lien-resume { font-size: 12px; color: var(--et-inerte); }

/* LE POPOVER, ancré sous son lien. Il porte un petit formulaire — quatre
   groupes — plutôt qu'un onglet de plus : ce sont des conditions qu'on
   consulte, qu'on corrige, et qu'on referme. Un onglet les aurait rendues
   permanentes à l'écran alors qu'on les regarde deux fois par document. */
.dev-popover {
    position: absolute; top: calc(100% + 8px); left: 0; z-index: 40;
    width: 390px; max-width: 86vw; max-height: 66vh; overflow: auto;
    background: var(--et-surface);
    border: 1px solid var(--et-form-border);
    box-shadow: var(--et-ombre-flottant);
}
.dev-popover-tete {
    display: flex; align-items: center; gap: 8px;
    padding: 10px 14px; border-bottom: 1px solid var(--et-rang);
    background: var(--et-surface-3);
    font-size: 12px; font-weight: 700; text-transform: uppercase;
    letter-spacing: .12em; color: var(--et-muted);
}
.dev-popover-corps { padding: 12px 14px 14px; }
.dev-popover-lbl {
    font-size: 12px; font-weight: 600; text-transform: uppercase;
    letter-spacing: .07em; color: var(--et-inerte);
}
.dev-popover-lbl + * { margin-top: 5px; }
.dev-popover-sous { margin-top: 3px; font-size: 12px; color: var(--et-muted); }
.dev-popover-groupe + .dev-popover-groupe {
    margin-top: 12px; padding-top: 11px; border-top: 1px solid var(--et-surface-2);
}
.dev-popover-note {
    padding: 9px 11px; margin-top: 10px;
    background: var(--et-tint); color: var(--et-form-blue-d);
    font-size: 12px; line-height: 1.5;
}

/* Les conditions en chips : devise, délai, régime de taxe, validité. Elles se
   LISENT, elles ne se cliquent pas — c'est le popover qui les modifie. */
.dev-chips { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.dev-chip {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 3px 10px; border-radius: var(--et-r-pill);
    background: var(--et-surface-2); color: var(--et-muted);
    font-size: 12px; white-space: nowrap;
}
.dev-chip.est-info { background: var(--et-tint); color: var(--et-form-blue-d); }
.dev-chip.est-alerte { background: var(--et-avertissement-bg); color: var(--et-avertissement-ink); }
.dev-chip.est-danger { background: var(--et-danger-badge-bg); color: var(--et-danger-ink); }
.dev-chip .mono { font-family: var(--et-font-mono); }

.dev-objet {
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    padding: 10px 16px; border-top: 1px solid var(--et-rang);
}
.dev-objet input { flex: 1 1 320px; min-width: 200px; }

/* ===========================================================================
   6. GRILLE — barre d'outils, suggestions, sélection

   *** LA GRILLE EST CE QUI DÉCIDE DE L'ADOPTION ***
   Un code, Entrée, la ligne est là — comme en caisse. Si saisir vingt lignes
   demande soixante clics, le commercial retourne à son tableur.
   =========================================================================== */
.dev-grille-barre {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    padding: 11px 14px; border-bottom: 1px solid var(--et-hairline);
}
.dev-grille-outils { margin-left: auto; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

.dev-champ-article { position: relative; }
.dev-champ-article > i.bi-upc-scan {
    position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
    color: var(--et-muted); font-size: 12px; pointer-events: none;
}
.dev-champ-article input {
    width: 280px; max-width: 100%; height: 32px; padding: 0 10px 0 30px;
    font-family: inherit; font-size: 13px; color: var(--et-ink);
    background: var(--et-surface);
    border: 1px solid var(--et-form-border); border-radius: var(--et-r-btn);
    outline: none;
}
.dev-champ-article input:focus { border-color: var(--et-form-blue); }

/* La suggestion porte le prix au barème DE CE CLIENT, le stock, et le dernier
   prix qu'il a payé. C'est ce dernier chiffre qui évite d'ouvrir la fiche
   client dans un second onglet — et l'écart qui déclenche la discussion. */
.dev-suggestions {
    position: absolute; top: calc(100% + 5px); left: 0; z-index: 30;
    width: 430px; max-width: 92vw; max-height: 320px; overflow: auto;
    background: var(--et-surface);
    border: 1px solid var(--et-form-border);
    box-shadow: var(--et-ombre-flottant);
}
.dev-suggestion {
    display: block; width: 100%; padding: 8px 12px;
    border: 0; border-bottom: 1px solid var(--et-surface-2);
    background: transparent; text-align: left; cursor: pointer; font-family: inherit;
}
.dev-suggestion:hover, .dev-suggestion.est-survolee { background: var(--et-tint); }
.dev-sugg-rang { display: flex; align-items: baseline; gap: 8px; }
.dev-sugg-code { font-family: var(--et-font-mono); font-size: 13px; font-weight: 600; color: var(--et-ink); }
.dev-sugg-lib {
    flex: 1; min-width: 0; font-size: 13px; color: var(--et-ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dev-sugg-prix { font-family: var(--et-font-mono); font-size: 13px; font-weight: 600; white-space: nowrap; }
.dev-sugg-bas { display: flex; align-items: center; gap: 8px; margin-top: 3px; font-size: 12px; color: var(--et-muted); }
.dev-sugg-bas .sep { color: var(--et-form-border); }
.dev-sugg-stock.est-rupture { color: var(--et-danger-ink); font-weight: 600; }
.dev-sugg-ecart {
    margin-left: auto; padding: 1px 7px; border-radius: var(--et-r-pill);
    font-weight: 600; background: var(--et-surface-2); color: var(--et-muted);
}
.dev-sugg-ecart.est-hausse { background: var(--et-succes-bg); color: var(--et-succes-ink); }
.dev-sugg-ecart.est-baisse { background: var(--et-avertissement-bg); color: var(--et-avertissement-ink); }
.dev-sugg-aide { padding: 6px 12px; background: var(--et-surface-3); font-size: 12px; color: var(--et-inerte); }

/* Un menu déroulant de la barre — Colonnes, Section. */
.dev-menu { position: relative; }
.dev-menu-liste {
    position: absolute; top: calc(100% + 5px); right: 0; z-index: 20;
    min-width: 230px; padding: 5px 0;
    background: var(--et-surface); border: 1px solid var(--et-hairline);
    box-shadow: var(--et-ombre-menu);
}
.dev-menu-titre {
    padding: 7px 13px 6px;
    font-size: 12px; font-weight: 700; text-transform: uppercase;
    letter-spacing: .12em; color: var(--et-inerte);
}
.dev-menu-opt {
    display: flex; align-items: center; gap: 9px; width: 100%;
    padding: 7px 13px; border: 0; background: transparent;
    font-family: inherit; font-size: 13px; color: var(--et-ink);
    text-align: left; cursor: pointer;
}
.dev-menu-opt:hover { background: var(--et-tint); }
.dev-menu-opt .note { margin-left: auto; font-size: 12px; color: var(--et-inerte); }
.dev-menu-fond { position: fixed; inset: 0; z-index: 19; background: transparent; border: 0; }

/* LA BARRE DE SÉLECTION, qui n'apparaît qu'une case cochée. Elle porte les
   gestes de MASSE — dupliquer, remiser, taxer, retirer — que la rangée ne
   peut pas porter sans se remplir de boutons. */
.dev-selection {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    padding: 9px 14px;
    background: var(--et-tint); border-bottom: 1px solid var(--et-info-bord);
    font-size: 13px; color: var(--et-form-blue-d);
}
.dev-selection-n { font-weight: 600; }
.dev-selection .mx-btn { height: 28px; }

/* ===========================================================================
   7. GRILLE — les quatre types de rangée

   Article, SECTION, commentaire, kit. Chacun a son fond, et c'est ce qui rend
   la structure d'un devis de quarante lignes lisible sans la lire.
   =========================================================================== */
.dev-grille { width: 100%; min-width: 1120px; font-size: 13px; border-collapse: collapse; }

/* L'EN-TÊTE EST L'ARDOISE, COMME TOUTES LES AUTRES TABLES — et ce n'est pas
   qu'une question d'uniformité.

   Il était peint en --et-surface-2 / --et-muted, c'est-à-dire en clair, alors
   que la grille porte .tbl-ancree : lot03-tables-larges.css DOIT rendre la
   cellule figée OPAQUE, sans quoi les colonnes défilent au travers, et il la
   peint en --et-table-head — le fond que .table thead th porte partout
   ailleurs, comme son propre commentaire l'explique.

   Résultat sur le seul écran qui mélangeait les deux : un RECTANGLE ARDOISE
   derrière « Article », posé dans une bande claire, et l'encre --et-muted de
   la bande héritée par-dessus — un gris moyen sur un fond sombre. La liste de
   documents du même écran (.dev-table) était déjà à l'ardoise ; seule la
   grille de lignes ne l'était pas.

   L'encre est le PREMIER rang (--et-sur-ardoise-plein) : la charte le nomme
   pour « une tête de table », et il monte le contraste d'un cran par rapport
   au second rang, qui est celui des libellés. */
.dev-grille thead tr { background: var(--et-table-head); color: var(--et-sur-ardoise-plein); }
.dev-grille th {
    text-align: left; font-size: 12px; font-weight: 600;
    text-transform: uppercase; letter-spacing: .08em; padding: 8px 10px;
    white-space: nowrap;
    /* COLLANT EN HAUT DU CADRE. Un devis de chantier fait quarante lignes : une
       fois descendu à la quinzième, plus rien ne dit si la colonne qu'on lit
       est le prix ou le montant, et il faut remonter pour en être sûr. Posé sur
       th et non sur thead : sous border-collapse, un thead collant ne porte pas
       ses propres bordures. Le z-index reste SOUS celui de la cellule ancrée
       (4), pour que le coin haut-gauche reste lisible quand les deux se
       croisent. */
    position: sticky; top: 0; z-index: 3;
}
.dev-grille th.num, .dev-grille td.num { text-align: right; }
.dev-grille td { padding: 8px 10px; vertical-align: top; }
.dev-grille tbody tr { border-bottom: 1px solid var(--et-rang); }

.dev-poignee {
    padding: 8px 0 8px 12px !important;
    color: var(--et-inerte); font-family: var(--et-font-mono); font-size: 12px;
    white-space: nowrap; cursor: grab;
}
.dev-poignee i { color: var(--et-form-border); }
/* La rangée survolée pendant un glisser : un filet épais dit où elle tombera. */
.dev-grille tbody tr.est-cible { box-shadow: inset 0 2px 0 0 var(--et-form-blue); }
.dev-grille tbody tr.est-glissee { opacity: .5; }
.dev-grille tbody tr.est-selectionnee { background: var(--et-tint); }

.dev-rang-section { background: var(--et-surface-2); border-bottom: 1px solid var(--et-hairline) !important; }
.dev-section-titre {
    width: 100%; height: 26px; padding: 0;
    border: 0; background: transparent; font-family: inherit;
    font-size: 13px; font-weight: 700; text-transform: uppercase;
    letter-spacing: .06em; color: var(--et-table-head-encre); outline: none;
}
.dev-section-total { font-family: var(--et-font-mono); font-size: 12px; color: var(--et-muted); margin-right: 6px; }

.dev-rang-commentaire td { padding-top: 7px; padding-bottom: 7px; }
.dev-commentaire-txt {
    width: 100%; height: 26px; padding: 0;
    border: 0; background: transparent; font-family: inherit;
    font-size: 13px; font-style: italic; color: var(--et-muted); outline: none;
}

.dev-rang-kit { background: var(--et-tint); border-bottom: 1px solid var(--et-info-bord) !important; }
.dev-kit-code { font-family: var(--et-font-mono); font-size: 13px; font-weight: 700; color: var(--et-form-blue-d); }
.dev-kit-marque {
    padding: 1px 8px; border-radius: var(--et-r-pill);
    background: var(--et-blue); color: var(--et-surface);
    font-size: 12px; font-weight: 700;
}
/* Un composant de kit est EN RETRAIT, avec le filet qui le rattache à sa tête :
   sans lui, une ligne de composant se lit comme un article vendu seul. */
.dev-composant { padding-left: 22px !important; border-left: 2px solid var(--et-info-bord); }

.dev-art-rang { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.dev-art-code { font-family: var(--et-font-mono); font-size: 13px; font-weight: 600; }
.dev-art-lib { font-size: 12px; color: var(--et-muted); }
.dev-art-tarif {
    padding: 1px 7px; border-radius: var(--et-r-pill);
    background: var(--et-tint); color: var(--et-form-blue-d);
    font-size: 12px; font-weight: 600;
}
.dev-art-tarif.est-saisi { background: var(--et-surface-2); color: var(--et-muted); }
.dev-art-alerte {
    display: flex; align-items: center; gap: 5px; margin-top: 2px;
    font-size: 12px; font-weight: 600; color: var(--et-avertissement-ink);
}
.dev-art-alerte.est-danger { color: var(--et-danger-ink); }
.dev-art-catalogue { font-size: 12px; margin-top: 1px; color: var(--et-inerte); }

/* La note de ligne : un champ qui ne se voit qu'au survol et à la saisie. Elle
   est imprimée sous l'article, donc elle doit être là ; elle est rare, donc
   elle ne doit pas peser sur une grille de quarante lignes. */
.dev-note-rang { display: flex; align-items: center; gap: 5px; margin-top: 2px; }
.dev-note-rang > i { font-size: 12px; color: var(--et-inerte); }
.dev-note {
    flex: 1; min-width: 0; height: 22px; padding: 0 4px;
    font-family: inherit; font-size: 12px; font-style: italic; color: var(--et-muted);
    border: 0; border-bottom: 1px dashed transparent;
    background: transparent; outline: none;
}
.dev-note:hover { border-bottom-color: var(--et-form-border); }
.dev-note:focus { border-bottom-color: var(--et-form-blue); color: var(--et-ink); background: var(--et-surface-3); }

/* ELLE SE REPLIE QUAND ELLE EST VIDE — ce que le commentaire ci-dessus décrivait
   sans que rien ne le fasse : le rang était rendu sur CHAQUE ligne d'article,
   vide ou non. Vingt-quatre pixels par ligne, soit une hauteur d'écran entière
   sur un devis de quarante lignes, pour un champ que l'écran lui-même qualifie
   de rare.

   « Vide » se lit par :placeholder-shown — un champ qui montre son invite ne
   porte pas de texte. Une note SAISIE reste donc visible en permanence, comme
   avant ; seules les lignes qui n'en ont pas rendent leur place.

   SOUS @media (hover: hover), ET C'EST LA CONDITION QUI COMPTE. Replier ce qui
   ne se déplie qu'au survol rendrait le champ inatteignable là où il n'y a pas
   de survol. Sur une tablette ou un téléphone, le rang reste donc déplié — la
   règle tactile du dépôt dit qu'une cible ne rétrécit jamais, et un champ qu'on
   ne peut pas viser est un champ qui n'existe plus. Le pointeur fin est exigé
   en plus : un écran tactile qui émule le survol ne passe pas. */
@media (hover: hover) and (pointer: fine) {
    .dev-note-rang:has(.dev-note:placeholder-shown) {
        height: 0; margin-top: 0; overflow: hidden;
        opacity: 0; visibility: hidden;
    }

    /* Le survol de la RANGÉE, et non celui du rang replié : à hauteur nulle, il
       n'y a plus rien à survoler pour le rouvrir. :focus-within garde le champ
       ouvert pendant la saisie, y compris quand on l'atteint au clavier. */
    .dev-grille tbody tr:hover .dev-note-rang,
    .dev-note-rang:focus-within {
        height: auto; margin-top: 2px; opacity: 1; visibility: visible;
    }
}

.dev-saisie {
    width: 100%; height: 30px; padding: 0 8px; text-align: right;
    font-family: var(--et-font-mono); font-size: 13px; color: var(--et-ink);
    background: var(--et-surface);
    border: 1px solid var(--et-hairline); border-radius: 0; outline: none;
}
.dev-saisie:focus { border-color: var(--et-form-blue); }
.dev-saisie:disabled { background: var(--et-surface-2); color: var(--et-muted); }
.dev-saisie-select {
    width: 100%; height: 30px; padding: 0 4px;
    font-family: inherit; font-size: 12px; color: var(--et-ink);
    background: var(--et-surface);
    border: 1px solid var(--et-hairline); border-radius: 0;
}

.dev-livre { font-family: var(--et-font-mono); font-size: 13px; color: var(--et-succes-ink); }
.dev-reste { font-family: var(--et-font-mono); font-size: 13px; color: var(--et-muted); }
.dev-reste.est-du { color: var(--et-avertissement-ink); font-weight: 600; }

.dev-dispo {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 2px 8px; border-radius: var(--et-r-pill);
    font-size: 12px; font-weight: 600;
    background: var(--et-succes-bg); color: var(--et-succes-ink);
}
.dev-dispo::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
.dev-dispo.est-partiel { background: var(--et-avertissement-bg); color: var(--et-avertissement-ink); }
.dev-dispo.est-rupture { background: var(--et-danger-badge-bg); color: var(--et-danger-ink); }
.dev-dispo-stock { font-size: 12px; color: var(--et-inerte); font-family: var(--et-font-mono); margin-top: 2px; }

/* LES JETONS DE TAXE, retirables. Retirer un code n'est pas anodin — la
   ventilation se recalcule sur la base réelle de la ligne — d'où la croix
   qui rougit avant le clic. */
.dev-taxes { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }
.dev-taxe {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 2px 4px 2px 8px; border-radius: var(--et-r-btn);
    background: var(--et-tint); color: var(--et-form-blue-d);
    font-family: var(--et-font-mono); font-size: 12px; font-weight: 600;
}
.dev-taxe button {
    display: inline-flex; align-items: center; justify-content: center;
    width: 14px; height: 14px; padding: 0; border: 0; border-radius: 0;
    background: transparent; color: var(--et-form-blue-l); cursor: pointer; font-size: 12px;
}
.dev-taxe button:hover { background: var(--et-danger); color: var(--et-surface); }
.dev-taxe-ajout {
    width: 26px; height: 22px; padding: 0;
    border: 1px dashed var(--et-inerte); border-radius: var(--et-r-btn);
    background: var(--et-surface); color: var(--et-form-blue-d);
    font-size: 12px; cursor: pointer;
}

.dev-montant {
    font-family: var(--et-font-mono); font-size: 13px; font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.dev-marge { font-size: 12px; font-weight: 600; color: var(--et-succes-ink); }
.dev-marge.est-faible { color: var(--et-avertissement-ink); }
.dev-marge.est-negative { color: var(--et-danger-ink); }

.dev-actions-ligne { display: inline-flex; align-items: center; gap: 1px; }
.dev-ico {
    width: 22px; height: 24px; border: 0; border-radius: 0;
    background: transparent; color: var(--et-inerte); cursor: pointer;
}
.dev-ico:hover:enabled { background: var(--et-tint); color: var(--et-form-blue); }
.dev-ico:disabled { opacity: .35; cursor: not-allowed; }
.dev-ico.est-retrait { width: 26px; height: 26px; }
.dev-ico.est-retrait:hover:enabled { background: var(--et-danger-badge-bg); color: var(--et-danger-ink); }

/* LA RANGÉE DE MOTIF. Elle s'ouvre SOUS la ligne remisée plutôt que dans une
   modale : le motif se saisit en regardant la remise, pas après l'avoir
   quittée des yeux. */
.dev-rang-motif { background: var(--et-avertissement-bg); }
.dev-motif-rang { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.dev-motif-txt { font-size: 12px; color: var(--et-avertissement-ink); white-space: nowrap; }
.dev-motif-champ {
    flex: 1; min-width: 180px; height: 28px; padding: 0 8px;
    font-family: inherit; font-size: 12px; color: var(--et-ink);
    background: var(--et-surface);
    border: 1px solid var(--et-avertissement-bord); border-radius: 0; outline: none;
}
.dev-motif-etat { font-size: 12px; font-weight: 600; color: var(--et-danger-ink); }
.dev-motif-etat.est-ok { color: var(--et-succes-ink); }

/* ===========================================================================
   8. COLONNE LATÉRALE — contrôles, totaux, journal

   L'ORDRE COMPTE : on lit ce qui cloche AVANT de lire le montant. Mettre les
   totaux en tête ferait valider sur le chiffre sans avoir vu l'alerte.
   =========================================================================== */
.dev-controle {
    display: flex; gap: 9px; padding: 7px 0;
    border-bottom: 1px solid var(--et-surface-2);
}
.dev-controle:last-child { border-bottom: 0; }
.dev-controle > i { font-size: 14px; margin-top: 1px; flex: none; color: var(--et-succes-ink); }
.dev-controle.est-alerte > i { color: var(--et-avertissement-ink); }
.dev-controle.est-bloquant > i { color: var(--et-danger-ink); }
.dev-controle-titre { font-size: 13px; font-weight: 600; color: var(--et-ink); }
.dev-controle-detail { font-size: 12px; color: var(--et-muted); line-height: 1.45; }

.dev-total-rang {
    display: flex; justify-content: space-between; gap: 12px;
    padding: 4px 0; font-size: 13px; color: var(--et-muted);
}
.dev-total-rang > span:last-child { font-family: var(--et-font-mono); white-space: nowrap; }
.dev-total-rang.est-remise { color: var(--et-avertissement-ink); }
.dev-total-rang.est-ht {
    padding: 8px 0 4px; margin-top: 4px;
    border-top: 1px solid var(--et-rang);
    font-size: 13px; color: var(--et-ink);
}
.dev-total-rang.est-ht > span:last-child { font-weight: 600; }
/* La base à côté du code : « TVA 18 % base 6 858 333 ». Un montant de taxe
   sans son assiette ne se rapproche d'aucune déclaration. */
.dev-total-base { font-family: var(--et-font-mono); font-size: 12px; color: var(--et-inerte); }
.dev-total-ttc {
    display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
    padding-top: 10px; margin-top: 8px;
    border-top: 2px solid var(--et-table-head);
}
.dev-total-ttc-lbl {
    font-size: 12px; font-weight: 700; text-transform: uppercase;
    letter-spacing: .08em; color: var(--et-ink);
}
.dev-total-ttc-val {
    font-family: var(--et-font-mono); font-size: 24px; font-weight: 600;
    letter-spacing: -.02em; color: var(--et-ink);
}
.dev-total-rang.est-net > span:last-child { color: var(--et-succes-ink); font-weight: 600; }
.dev-total-rang.est-retenue > span:last-child { color: var(--et-avertissement-ink); }
.dev-total-marge { padding-top: 10px; margin-top: 10px; border-top: 1px solid var(--et-rang); }

/* Le journal : qui a fait quoi, quand. Une chronologie et non un tableau —
   la colonne d'un tableau supposerait qu'on compare les lignes entre elles. */
.dev-journal { display: flex; gap: 10px; padding: 6px 0; border-bottom: 1px solid var(--et-surface-2); }
.dev-journal:last-child { border-bottom: 0; }
.dev-journal > i { font-size: 12px; margin-top: 2px; color: var(--et-inerte); flex: none; }
.dev-journal-quoi { font-size: 13px; color: var(--et-ink); }
.dev-journal-quand { font-size: 12px; color: var(--et-inerte); font-family: var(--et-font-mono); }

/* ===========================================================================
   9. VOLET CLIENT — 460 px, à droite, en superposition.

   Il n'est pas une page : on l'ouvre pour vérifier un NIF ou un encours, et on
   le referme. Naviguer vers la fiche client ferait perdre le document en cours.
   =========================================================================== */
.dev-voile {
    position: fixed; inset: 0; z-index: 60;
    background: rgba(20, 27, 38, .38); border: 0;
    animation: mxIn .16s ease both;
}
.dev-volet {
    position: fixed; top: 0; right: 0; bottom: 0; z-index: 61;
    width: 460px; max-width: 96vw;
    display: flex; flex-direction: column;
    background: var(--et-surface); border-left: 1px solid var(--et-hairline);
    box-shadow: var(--et-ombre-volet);
}
.dev-volet-tete {
    display: flex; align-items: center; gap: 10px;
    padding: 12px 16px; border-bottom: 1px solid var(--et-hairline);
    background: var(--et-surface-2);
}
.dev-volet-titre { font-size: 15px; font-weight: 700; color: var(--et-ink); min-width: 0; }
.dev-volet-corps { flex: 1; min-height: 0; overflow: auto; padding: 14px 16px 24px; }
.dev-volet-ind { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px; background: var(--et-hairline); }
.dev-volet-ind > div { background: var(--et-surface-2); padding: 8px 10px; }

/* ===========================================================================
   10. APERÇU DE LA PIÈCE — rendu A4 et filigrane

   LE FILIGRANE EST UNE RÈGLE, PAS UNE DÉCORATION. Un brouillon imprimé et
   signé de bonne foi est le seul défaut que cet écran ne peut pas rattraper :
   il porte donc la mention tant que le document n'est pas figé.
   =========================================================================== */
.dev-apercu {
    position: fixed; top: 0; right: 0; bottom: 0; z-index: 61;
    width: 520px; max-width: 96vw;
    display: flex; flex-direction: column;
    background: var(--et-surface-2); border-left: 1px solid var(--et-hairline);
    box-shadow: var(--et-ombre-volet);
}
.dev-apercu-corps { flex: 1; min-height: 0; overflow: auto; padding: 16px; }

/* La barre d'actions de l'aperçu — agrandir, imprimer, PDF, fermer. Elle est
   poussée à droite du titre par la marge automatique, et non par un style
   inline sur le dernier bouton : un bouton ajouté au milieu déplaçait la
   fermeture, et la fermeture est le bouton qu'on cherche sans regarder. */
.dev-apercu-actions { display: flex; align-items: center; gap: 6px; margin-left: auto; }

/* L'avis du volet : refus d'impression (ambre) ou erreur de l'appelant (rouge).
   Encre au rang -ink sur le fond pâle d'état — --et-avertissement sur
   --et-avertissement-bg rend 2,02:1 et --et-danger sur son fond 4,22:1, tous
   deux sous l'AA d'un texte de 13 px (docs/couleurs-en-dur.md). */
.dev-apercu-avis {
    display: flex; align-items: center; gap: 8px;
    padding: 8px 16px; border-bottom: 1px solid var(--et-hairline);
    background: var(--et-avertissement-bg); color: var(--et-avertissement-ink);
    font-size: var(--et-fs-cell);
}
.dev-apercu-avis > span { flex: 1; min-width: 0; }
.dev-apercu-avis.est-erreur {
    background: var(--et-danger-badge-bg); color: var(--et-danger-ink);
}
/* Le bouton hérite l'encre de l'avis : le gabarit y poserait la sienne (le bleu
   de contenu) et son survol un aplat bleu pâle — une croix bleue sur un fond
   ambre se lit comme un autre objet. Le survol passe donc par l'opacité, qui ne
   suppose aucune couleur de fond. */
.dev-apercu-avis-x { flex: none; color: inherit; padding: 0 6px; }
.dev-apercu-avis-x:hover:enabled { background: transparent; color: inherit; opacity: .7; }

/* --- L'APERÇU AGRANDI : LA FEUILLE, À SA LARGEUR ---------------------------
   520 px, c'est 66 % d'une A4 : la pièce y est lisible ligne à ligne, mais on
   ne voit pas ce qu'on va IMPRIMER — une désignation qui déborde sa colonne, un
   total qui passe à la ligne, un tableau qui se comprime. Avant d'imprimer, il
   faut la feuille entière ; après, on referme et on retourne à la saisie.

   210 mm est une dimension PHYSIQUE et non un palier de largeur : c'est la
   largeur du papier, comme les 80 mm du rouleau thermique de caisse.css. En
   dessous, `max-width: 100%` la ramène à l'écran, et sous 1024 px le volet est
   déjà pleine largeur (section 11).

   ET LE TEXTE PASSE À LA TAILLE QU'IL AURA SUR LE PAPIER — 13 px, celle du
   bloc d'impression, et non les 12 px du volet étroit. Agrandi, l'aperçu doit
   montrer la FEUILLE IMPRIMÉE : deux tailles de texte selon le geste feraient
   d'une vérification de mise en page une vérification d'autre chose. Les deux
   sont dans l'échelle de la révision du 2026-09-02, rien sous 12 px.
   -------------------------------------------------------------------------- */
.dev-apercu.est-large { left: 0; right: 0; width: auto; max-width: none; border-left: 0; }
.dev-apercu.est-large .dev-apercu-corps { padding: 20px 16px 32px; }
.dev-apercu.est-large .dev-piece {
    width: 210mm; max-width: 100%; margin: 0 auto;
    padding: 18mm 16mm; font-size: var(--et-fs-cell);
}
.dev-piece {
    position: relative; overflow: hidden;
    background: var(--et-surface); border: 1px solid var(--et-hairline);
    padding: 24px 26px 30px; font-size: 12px; color: var(--et-ink);
}
.dev-piece-tete { display: flex; align-items: flex-start; gap: 16px; padding-bottom: 14px; border-bottom: 2px solid var(--et-table-head); }
.dev-piece-emetteur { flex: 1; min-width: 0; }
.dev-piece-societe { font-size: 15px; font-weight: 700; }
.dev-piece-titre { font-family: var(--et-font-mono); font-size: 16px; font-weight: 700; text-align: right; }
.dev-piece-blocs { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin: 14px 0; }
.dev-piece-bloc { border: 1px solid var(--et-hairline); padding: 9px 11px; }
.dev-piece-bloc-lbl {
    font-size: 12px; font-weight: 700; text-transform: uppercase;
    letter-spacing: .12em; color: var(--et-muted);
}
.dev-piece-tbl { width: 100%; border-collapse: collapse; font-size: 12px; }
.dev-piece-tbl th {
    background: var(--et-table-head); color: var(--et-sur-ardoise);
    text-align: left; font-size: 12px; font-weight: 600;
    text-transform: uppercase; letter-spacing: .08em; padding: 6px 7px;
}
.dev-piece-tbl td { padding: 5px 7px; border-bottom: 1px solid var(--et-rang); vertical-align: top; }
.dev-piece-tbl .num { text-align: right; font-family: var(--et-font-mono); }
.dev-piece-tbl tr.est-section td {
    background: var(--et-surface-2); font-weight: 700;
    text-transform: uppercase; letter-spacing: .05em; font-size: 12px;
}
.dev-piece-tbl tr.est-commentaire td { font-style: italic; color: var(--et-muted); }
.dev-piece-note { font-style: italic; color: var(--et-muted); font-size: 12px; }
.dev-piece-totaux { margin-left: auto; width: 62%; margin-top: 12px; }
.dev-piece-mentions { margin-top: 16px; padding-top: 10px; border-top: 1px solid var(--et-hairline); font-size: 12px; color: var(--et-muted); }
.dev-piece-signatures { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: 18px; }
.dev-piece-cartouche { border: 1px solid var(--et-hairline); height: 68px; padding: 6px 8px; font-size: 12px; color: var(--et-muted); }

/* Le filigrane : en travers, derrière le texte, et non cliquable. */
.dev-filigrane {
    position: absolute; inset: 0; display: grid; place-items: center;
    pointer-events: none; z-index: 1;
}
.dev-filigrane span {
    transform: rotate(-28deg);
    font-size: 58px; font-weight: 700; letter-spacing: .1em;
    color: var(--et-danger-ink); opacity: .1; white-space: nowrap;
}
.dev-filigrane.est-approbation span { color: var(--et-avertissement-ink); }
.dev-filigrane.est-brouillon span { color: var(--et-muted); }

/* ===========================================================================
   10 bis. CIRCUIT D'APPROBATION — la carte de la colonne droite

   ELLE REMPLACE UN REFUS. Le plafond de remise (VNT-03) ne savait que bloquer
   la validation ; ici, le document reste au vendeur et la décision revient à
   qui a le pouvoir de la prendre. La carte doit donc se lire comme un CHEMIN
   (où en est-on, qui attend, qui a signé), pas comme une alerte de plus.

   LA COULEUR DIT L'ÉTAT, ET RIEN D'AUTRE. Le filet de gauche est le seul aplat
   coloré : ambre tant qu'une décision est attendue, rouge sur un refus, rien
   quand tout est signé. Aucune valeur littérale — le thème sombre suit par les
   jetons.
   =========================================================================== */
.dev-appro { border-left: 3px solid var(--et-hairline); }
.dev-appro.est-attente { border-left-color: var(--et-avertissement-mark); }
.dev-appro.est-refuse { border-left-color: var(--et-danger); }

.dev-appro-motif {
    display: flex; gap: 8px; align-items: flex-start;
    padding: 8px 10px; margin-bottom: 10px;
    background: var(--et-surface-2);
    font-size: 12px; line-height: 1.45; color: var(--et-muted);
}
.dev-appro-motif > i { flex: none; margin-top: 1px; font-size: 13px; }

.dev-appro-vide { font-size: 12px; line-height: 1.5; color: var(--et-muted); }

/* Les étapes : une liste ordonnée, sans sa numérotation — le niveau est écrit,
   et deux numérotations côte à côte se contrediraient dès qu'un palier saute. */
.dev-appro-etapes { list-style: none; margin: 0 0 10px; padding: 0; }
.dev-appro-etape {
    display: flex; gap: 9px; padding: 7px 0;
    border-bottom: 1px solid var(--et-surface-2);
}
.dev-appro-etape:last-child { border-bottom: 0; }
.dev-appro-etape > i { flex: none; margin-top: 2px; font-size: 13px; color: var(--et-inerte); }
.dev-appro-etape.est-fait > i { color: var(--et-succes-ink); }
.dev-appro-etape.est-refuse > i { color: var(--et-danger-ink); }
.dev-appro-etape.est-courant > i { color: var(--et-avertissement-ink); }
.dev-appro-etape.est-a-venir { opacity: .62; }

.dev-appro-etape-corps { min-width: 0; }
.dev-appro-etape-tete { display: flex; flex-wrap: wrap; gap: 8px; align-items: baseline; }
.dev-appro-niveau { font-size: 13px; font-weight: 600; color: var(--et-ink); }
.dev-appro-role { font-size: 12px; color: var(--et-form-blue); }
.dev-appro-etape-detail { font-size: 12px; color: var(--et-muted); line-height: 1.45; }
.dev-appro-commentaire {
    margin-top: 3px; font-size: 12px; font-style: italic;
    color: var(--et-faint); line-height: 1.45;
}

.dev-appro-mot {
    width: 100%; margin-bottom: 8px; padding: 6px 8px;
    font-family: inherit; font-size: 13px; line-height: 1.45;
    color: var(--et-ink); background: var(--et-surface);
    border: 1px solid var(--et-filet-fort); border-radius: 0; resize: vertical;
}
.dev-appro-mot:focus { outline: none; border-color: var(--et-form-blue); }

.dev-appro-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.dev-appro-action { width: 100%; justify-content: center; }
.dev-appro-refus { color: var(--et-danger-ink); }

/* ===========================================================================
   10 ter. LE DOSSIER — pièces jointes, envoi & suivi, fenêtre d'envoi

   DEUX CARTES ET UNE FENÊTRE, ET UNE SEULE IDÉE : ce qui accompagne la pièce et
   ce qu'il en est advenu. Elles suivent le gabarit .dev-bloc comme les autres —
   rien ici ne redéfinit une surface, un filet ou une encre.

   LA COULEUR DIT L'ÉTAT, ET RIEN D'AUTRE, comme au circuit d'approbation : le
   filet de gauche du bloc d'envoi passe au rouge sur un échec, au vert sur un
   envoi abouti, et reste neutre tant que rien n'est parti. Une pièce marquée
   « communicable » se signale par un filet, PAS par une encre colorée — la règle
   du dépôt veut qu'une couleur d'état ne s'écrive jamais en `color:`.

   Aucune valeur littérale : le thème sombre suit par les jetons.
   =========================================================================== */

/* ---- Pièces jointes ---- */
.dev-pj-vide { font-size: 12px; line-height: 1.5; color: var(--et-muted); }

.dev-pj-liste { list-style: none; margin: 0 0 10px; padding: 0; }
.dev-pj-item {
    display: flex; align-items: flex-start; gap: 10px;
    padding: 9px 0; border-bottom: 1px solid var(--et-rang);
    border-left: 2px solid transparent; padding-left: 6px; margin-left: -6px;
}
.dev-pj-item:last-child { border-bottom: 0; }
/* Le filet — un MARK, pas une encre : le vert en texte de 12 px n'atteint pas AA
   sur le rang survolé, et la règle du dépôt le proscrit partout. */
.dev-pj-item.est-communicable { border-left-color: var(--et-succes); }

.dev-pj-icone { flex: none; margin-top: 2px; font-size: 15px; color: var(--et-inerte); }
.dev-pj-corps { min-width: 0; flex: 1; }

.dev-pj-nom {
    display: block; padding: 0; border: 0; background: transparent; font-family: inherit;
    text-align: left; font-size: 13px; font-weight: 600; color: var(--et-form-blue-d);
    cursor: pointer; word-break: break-word;
    text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px;
}
.dev-pj-nom:hover { color: var(--et-form-blue); }
.dev-pj-nom:disabled { color: var(--et-muted); cursor: default; text-decoration: none; }

.dev-pj-detail {
    display: flex; flex-wrap: wrap; gap: 4px 10px; margin-top: 2px;
    font-size: 12px; color: var(--et-muted);
}
.dev-pj-nature { font-weight: 600; color: var(--et-faint); }

.dev-pj-envoi {
    display: flex; align-items: center; gap: 6px; margin-top: 5px;
    font-size: 12px; color: var(--et-muted); cursor: pointer;
}
.dev-pj-envoi input { margin: 0; }

.dev-pj-retirer {
    flex: none; width: 28px; height: 28px; padding: 0;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--et-hairline); background: var(--et-surface);
    color: var(--et-muted); cursor: pointer; font-size: 13px;
}
.dev-pj-retirer:hover { border-color: var(--et-danger); color: var(--et-danger-ink); }

/* La zone de dépôt : la nature D'ABORD, le fichier ensuite — demandée après, elle
   se saute, le fichier étant déjà en place. */
.dev-pj-depot { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 4px; }
.dev-pj-nature-choix {
    flex: 1 1 130px; min-width: 0; height: 30px; padding: 0 8px;
    border: 1px solid var(--et-filet-fort); background: var(--et-surface);
    color: var(--et-ink); font-family: inherit; font-size: 13px;
}
.dev-pj-nature-choix:focus { outline: none; border-color: var(--et-form-blue); }

/* Le <label> EST le bouton : l'InputFile natif est illisible dans une charte, et
   le masquer sous un label est la seule façon de garder le clavier et le
   glisser-déposer du navigateur. */
.dev-pj-bouton {
    display: inline-flex; align-items: center; justify-content: center; gap: 6px;
    flex: 1 1 150px; height: 30px; padding: 0 12px; cursor: pointer;
    border: 1px solid var(--et-filet-fort); background: var(--et-surface);
    color: var(--et-ink); font-size: 13px; font-weight: 600;
}
.dev-pj-bouton:hover { border-color: var(--et-form-blue); color: var(--et-form-blue); }
.dev-pj-bouton.est-occupe { opacity: .55; cursor: default; }
.dev-pj-bouton input[type="file"] {
    position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none;
}
.dev-pj-aide { margin-top: 6px; font-size: 12px; line-height: 1.45; color: var(--et-inerte); }

/* ---- Envoi & suivi ---- */
.dev-env { border-left: 3px solid var(--et-hairline); }
.dev-env.est-envoye { border-left-color: var(--et-succes); }
.dev-env.est-echec { border-left-color: var(--et-danger); }

.dev-env-vide { font-size: 12px; line-height: 1.5; color: var(--et-muted); }

.dev-env-fil { list-style: none; margin: 0 0 10px; padding: 0; }
.dev-env-jalon {
    display: flex; align-items: flex-start; gap: 9px;
    padding: 8px 0; border-bottom: 1px solid var(--et-rang);
}
.dev-env-jalon:last-child { border-bottom: 0; }
.dev-env-jalon > i { flex: none; margin-top: 2px; font-size: 13px; color: var(--et-inerte); }
.dev-env-jalon.est-envoye > i { color: var(--et-succes-ink); }
.dev-env-jalon.est-consulte > i { color: var(--et-form-blue); }
.dev-env-jalon.est-echec > i { color: var(--et-danger-ink); }

.dev-env-jalon-corps { min-width: 0; }
.dev-env-jalon-quoi { font-size: 13px; font-weight: 600; color: var(--et-ink); }
.dev-env-jalon-detail { font-size: 12px; color: var(--et-faint); line-height: 1.45; word-break: break-word; }
.dev-env-jalon-quand { font-size: 12px; color: var(--et-muted); }

/* Ce qui EMPÊCHE d'envoyer, sous la chronologie et non à sa place : un document
   annulé garde ses envois, ils ont eu lieu. Le filet du haut détache la contrainte
   du récit — sans lui, la phrase se lirait comme un dernier jalon. */
.dev-env-empeche {
    margin-top: 10px; padding-top: 9px; border-top: 1px solid var(--et-rang);
    font-size: 12px; line-height: 1.5; color: var(--et-muted);
}
.dev-env-fil + .dev-env-empeche { margin-top: 4px; }

.dev-env-action { width: 100%; justify-content: center; }

/* ---- La fenêtre d'envoi ---- */
.dev-env-fen { display: flex; flex-direction: column; max-height: 88vh; background: var(--et-surface); }

.dev-env-fen-tete {
    display: flex; align-items: flex-start; gap: 12px;
    padding: 14px 18px; border-bottom: 1px solid var(--et-hairline);
}
.dev-env-fen-surtitre {
    font-size: 12px; font-weight: 700; text-transform: uppercase;
    letter-spacing: .12em; color: var(--et-muted);
}
.dev-env-fen-titre { font-size: 18px; font-weight: 700; letter-spacing: -.02em; color: var(--et-ink); }
.dev-env-fen-fermer {
    margin-left: auto; width: 30px; height: 30px; padding: 0; flex: none;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--et-hairline); background: var(--et-surface);
    color: var(--et-muted); cursor: pointer;
}
.dev-env-fen-fermer:hover { border-color: var(--et-filet-fort); color: var(--et-ink); }

.dev-env-fen-corps { padding: 14px 18px; overflow-y: auto; }
.dev-env-fen-pied {
    display: flex; justify-content: flex-end; gap: 8px;
    padding: 12px 18px; border-top: 1px solid var(--et-hairline); background: var(--et-surface-3);
}

.dev-env-champ { margin-bottom: 12px; }
.dev-env-champ > label {
    display: block; margin-bottom: 4px;
    font-size: 12px; font-weight: 700; text-transform: uppercase;
    letter-spacing: .11em; color: var(--et-muted);
}
.dev-env-saisie {
    width: 100%; height: 32px; padding: 0 9px;
    border: 1px solid var(--et-filet-fort); background: var(--et-surface);
    color: var(--et-ink); font-family: inherit; font-size: 13px;
}
.dev-env-saisie:focus { outline: none; border-color: var(--et-form-blue); }
.dev-env-corps { height: auto; padding: 8px 9px; line-height: 1.5; resize: vertical; }

.dev-env-note { margin-top: 4px; font-size: 12px; line-height: 1.45; color: var(--et-muted); }
/* Une note qui signale un manque prend le filet d'alerte, jamais l'encre : à
   11,5 px l'ambre ne passe pas AA, et --et-avertissement-mark est fait pour ça. */
.dev-env-note.est-alerte {
    padding-left: 8px; border-left: 2px solid var(--et-avertissement-mark);
    color: var(--et-avertissement-ink);
}

.dev-env-pieces {
    margin-top: 14px; padding-top: 10px; border-top: 1px solid var(--et-hairline);
    display: flex; flex-direction: column; gap: 2px;
}
.dev-env-piece {
    display: flex; align-items: center; gap: 8px; padding: 6px 0; cursor: pointer;
    font-size: 13px; color: var(--et-ink);
}
.dev-env-piece input { margin: 0; flex: none; }
.dev-env-piece-nom {
    display: inline-flex; align-items: center; gap: 6px; min-width: 0;
    font-weight: 600; word-break: break-word;
}
.dev-env-piece-note { margin-left: auto; flex: none; font-size: 12px; color: var(--et-muted); }

/* ===========================================================================
   11. PALIERS DE LARGEUR

   Géométrie seule, aucune couleur : le thème sombre suit par les jetons.
   L'échelle est celle de docs/conventions-responsive.md — 1100, 1024, 720,
   640, 560 — et rien d'autre n'est inventé ici.
   =========================================================================== */

/* Sous 1100 px, la colonne latérale passe SOUS le document. Elle ne se replie
   pas dans un tiroir : les contrôles avant validation doivent rester lisibles
   sans un geste de plus. */
@media (max-width: 1100px) {
    .dev-grille-fiche { grid-template-columns: minmax(0, 1fr); }
    .dev-laterale { position: static; }
}

@media (max-width: 1024px) {
    .dev-liste { grid-template-columns: minmax(0, 1fr); }
    .dev-ind-grille { grid-template-columns: repeat(2, 1fr); }

    /* CIBLES TACTILES (docs/cibles-tactiles.md) : sous 1024 px, aucune cible de
       cet écran ne descend sous 44 px, et aucune ne rétrécit. */
    .dev-onglet { min-height: 44px; }
    .dev-facette { min-height: 44px; }
    .dev-ico { width: 44px; height: 44px; }
    .dev-ico.est-retrait { width: 44px; height: 44px; }
    .dev-taxe button { width: 24px; height: 24px; }
    .dev-saisie, .dev-saisie-select { height: 44px; }
    .dev-recherche input, .dev-champ-article input { height: 44px; }
    .dev-pagination button { height: 44px; min-width: 44px; }
    .dev-volet, .dev-apercu { width: 100%; }
    .dev-apercu-actions .mx-btn { min-height: 44px; }
    .dev-appro-actions .mx-btn, .dev-appro-action { min-height: 44px; }
    .dev-pj-bouton, .dev-pj-nature-choix { height: 44px; }
    .dev-pj-retirer { width: 44px; height: 44px; }
    .dev-env-action { min-height: 44px; }
    .dev-env-fen-fermer { width: 44px; height: 44px; }
    .dev-env-saisie { height: 44px; }
    .dev-env-piece { min-height: 44px; }
}

@media (max-width: 720px) {
    /* La barre de l'aperçu passe en ICÔNES SEULES. Quatre boutons libellés, un
       titre et une puce de type ne tiennent pas sur 390 px : ils débordaient du
       volet, et c'est la fermeture qui sortait la première. Le `title` de chaque
       bouton porte le sens, et la barre garde le droit de passer à la ligne si la
       puce est longue (« Bons de livraison »). Les cibles restent à 44 px — la
       règle tactile du lot 02 ne se paie pas en largeur d'intitulé. */
    .dev-volet-tete { flex-wrap: wrap; }
    .dev-apercu-lbl { display: none; }
    .dev-apercu-actions .mx-btn { width: 44px; padding: 0; }

    .dev-tete { padding: 12px 14px 0; }
    .dev-corps { padding: 14px 14px 22px; }
    .dev-resume { gap: 12px; }
    .dev-sep-vert { display: none; }
    .dev-encours { flex: 1 1 100%; }
    /* Le popover cesse d'être ancré : sur 720 px, 390 px de large sous un lien
       de gauche sortiraient de l'écran. Il devient une feuille du bas. */
    .dev-popover {
        position: fixed; left: 0; right: 0; bottom: 0; top: auto;
        width: auto; max-width: none; max-height: 74vh;
    }
    /* La fenêtre d'envoi prend la hauteur disponible : sur 720 px, quatre champs
       et une liste de pièces ne tiennent pas dans une boîte centrée. */
    .dev-env-fen { max-height: 96vh; }
    .dev-env-piece-note { margin-left: 0; flex-basis: 100%; }
}

@media (max-width: 560px) {
    .dev-ind-grille { grid-template-columns: minmax(0, 1fr); }
    .dev-tete { padding: 10px 10px 0; }
    .dev-corps { padding: 12px 10px 20px; }
    .dev-champ-article input { width: 100%; }
    .dev-champ-article { flex: 1 1 100%; }
    .dev-suggestions { width: 100%; }
}

/* ===========================================================================
   12. IMPRESSION — le mobilier disparaît, la pièce reste.

   Imprimer l'écran doit donner la PIÈCE, pas la copie d'écran d'un logiciel :
   ni barre d'outils, ni facettes, ni colonne de contrôles. Le filigrane, lui,
   reste — c'est justement à l'impression qu'il sert.

   DEUX CHEMINS, UNE SEULE FEUILLE. Imprimer la fiche sort la pièce telle que
   la saisie la dessine ; imprimer l'APERÇU ouvert sort l'aperçu seul. Les deux
   passent par ici, et le bouton « Imprimer » de l'aperçu ne fait rien de plus
   que Ctrl+P : un bouton qui imprimerait autre chose que le raccourci serait un
   piège, pas une commodité.

   LE BLANC EST CELUI DU PAPIER. Les trois `#fff` de ce bloc sont les seules
   couleurs littérales de cette feuille et n'existent que sous @media print :
   un jeton de surface suivrait le thème, et une pièce imprimée depuis un poste
   en sombre sortirait sur un aplat gris.
   =========================================================================== */
@media print {

    /* --- Le mobilier ------------------------------------------------------ */
    .dev-tete, .dev-filtre, .dev-table-barre, .dev-grille-barre, .dev-selection,
    .dev-laterale, .dev-liens, .dev-suite, .mx-blocage, .dev-actions-ligne,
    .dev-poignee, .dev-menu, .dev-suggestions, .dev-voile,
    .dev-env-fen { display: none !important; }

    /* Les DEUX volets ont un en-tête, et un en-tête est du mobilier : titre,
       puce de type, actions. Le volet client entier disparaît avec — on
       l'ouvre pour vérifier un NIF, jamais pour le donner au client. L'aperçu,
       lui, reste : c'est la pièce. */
    .dev-volet, .dev-volet-tete, .dev-apercu-avis { display: none !important; }

    /* --- L'APERÇU OUVERT IMPRIME LA PIÈCE, ET RIEN QU'ELLE ----------------
       « est-apercu » est posée sur .dev-ecran par DocumentVenteEcran quand
       l'aperçu est ouvert ; l'aperçu, lui, est monté en FRÈRE de l'écran, pas
       dedans. Masquer l'écran ne l'emporte donc pas, et une règle suffit là où
       il aurait fallu masquer chaque meuble un par un — la première carte
       ajoutée sans classe `no-print` serait revenue sur le papier.

       C'est le composant qui le sait, et non un :has() : la même raison qu'à
       lot06-ancrage-gabarit.css, et ici elle pèse plus encore, car un
       navigateur qui ignore :has() imprimerait la saisie AVEC la pièce. */
    .dev-ecran.est-apercu { display: none !important; }

    /* --- La feuille ------------------------------------------------------- */
    .dev-ecran, .dev-piece { background: #fff; }

    /* Le volet cesse d'être un volet : plus de position fixe, plus de cadre,
       plus d'ombre, et son corps rend son défilement au flux du document —
       sans quoi la pièce serait coupée net au bas de la première page. */
    .dev-apercu {
        display: block; position: static;
        width: auto; max-width: none; border: 0; box-shadow: none;
    }
    .dev-apercu-corps { overflow: visible !important; padding: 0 !important; }

    /* Agrandie ou non, la pièce sort à la largeur de la PAGE : la feuille de
       210 mm de l'aperçu écran est ici celle de l'imprimante, et un second
       cadrage à l'intérieur du premier volerait deux marges. */
    .dev-piece,
    .dev-apercu.est-large .dev-piece {
        width: auto; max-width: none; margin: 0;
        border: 0; padding: 0; overflow: visible;
        font-size: var(--et-fs-cell);
    }

    .dev-grille-fiche { grid-template-columns: minmax(0, 1fr); }
    .dev-filigrane span { opacity: .16; }

    /* --- Ce qui ne survit pas au papier sans correction ------------------- */

    /* L'EN-TÊTE DU TABLEAU NE COMPTE PAS SUR SON APLAT. Les navigateurs
       n'impriment pas les fonds par défaut : l'aplat ardoise disparaît, et son
       encre claire (--et-sur-ardoise) laisse une rangée de titres BLANCS SUR
       BLANC — invisible sur la seule feuille où l'on relit les colonnes. On
       rend donc l'encre au texte et la séparation à un filet, qui s'imprime
       toujours. Même correction pour la rangée de section, qui se distinguait
       elle aussi par un fond. */
    .dev-piece-tbl th {
        background: #fff; color: var(--et-ink);
        border-bottom: 2px solid var(--et-table-head);
    }
    .dev-piece-tbl tr.est-section td {
        background: #fff; border-top: 1px solid var(--et-table-head);
    }

    /* Une pièce de quarante lignes tient sur deux feuilles : l'en-tête se
       répète sur chacune, aucune ligne ne se coupe en deux, et le pied — les
       totaux, les mentions, les cartouches de signature — ne se scinde pas.
       Un « Bon pour accord » séparé de son total ne se signe pas. */
    .dev-piece-tbl thead { display: table-header-group; }
    .dev-piece-tbl tr { break-inside: avoid; }
    .dev-piece-totaux, .dev-piece-mentions, .dev-piece-signatures { break-inside: avoid; }
}
