/* ============================================================================
   EasyCompta — fenêtres modales
   Voile, cadre, tête, grille de champs et pied : les mêmes mesures pour toutes
   les fenêtres du module, qu'elles appartiennent à un écran ou à la coquille.
   Les variables de forme (--et-modal-*, --et-form-*) viennent du thème.

   NÉE DANS EASYCOMPTA, ELLE SERT DÉSORMAIS AUSSI LA TRÉSORERIE (2026-09-07) : les
   cinquante fenêtres d'EasyTreso portaient déjà ce contenu .xp-* dans un cadre
   Bootstrap, et le cadre les a rejointes. Chargée dans App.razor pour tout le
   back-office, non bornée à .appgrid, elle est de fait une feuille de gabarit ; le
   nom du fichier dit d'où elle vient, pas qui la lit. Un troisième module qui
   l'adopte ne la recopie pas : il la lit.

   PALIER 900 px, ET UN SEUL : la feuille reçue le portait deux fois à l'identique
   (recopie de passation). Le second exemplaire est retiré — il ne disait rien de
   plus, et une règle écrite deux fois finit par être modifiée une fois.

   LA RÈGLE TACTILE Y EST DÉJÀ : sous 900 px, champs et bascules passent à 44 px,
   comme l'exige docs/cibles-tactiles.md pour tout ce qui se touche.
   ========================================================================== */

.xp-voile { position: fixed; inset: 0; z-index: 1090; display: flex; align-items: center; justify-content: center; padding: 20px; background: var(--et-voile); }
.xp-modal { display: flex; flex-direction: column; width: 100%; max-width: 560px; max-height: 100%; background: var(--et-surface); border: 1px solid var(--et-filet-fort); border-radius: var(--et-r); overflow: hidden; box-shadow: var(--et-ombre-fenetre); }
.xp-tete { flex: none; display: flex; align-items: center; gap: 11px; min-height: var(--et-modal-tete); padding: 0 var(--et-modal-pad); background: var(--et-form-blue); border-bottom: 3px solid var(--et-form-blue-d); color: var(--et-sur-aplat); font-size: 15px; font-weight: 600; letter-spacing: -.01em; }
.xp-tete > .bi:first-child { display: grid; place-items: center; width: 30px; height: 30px; flex: none; border-radius: 0; background: var(--et-fond-marine); font-size: 15px; }
.xp-fermer { display: grid; place-items: center; width: var(--et-modal-ferme); height: var(--et-modal-ferme); flex: none; background: transparent; border: 0; border-radius: 0; color: var(--et-sur-aplat-doux); cursor: pointer; }
.xp-fermer:hover { background: var(--et-fond-marine); color: var(--et-sur-aplat); }

/* LE TITRE ET LE SOUS-TITRE DE L'EN-TÊTE, ENFIN DANS LE GABARIT.
   Les cinquante-sept appelants de .xp-tete écrivaient ces deux lignes à la main,
   à l'identique — « font-size:14px;font-weight:700;color:#fff » et
   « font-size:12px;color:rgba(255,255,255,.78) », octet pour octet, dans vingt-neuf
   fichiers de cinq domaines. Ce n'était pas cinquante-sept règles : c'était UNE
   règle et cinquante-six occasions de la voir diverger.

   C'est la règle du dépôt appliquée à ce qu'elle vise — « une classe employée par
   deux écrans remonte au gabarit ». Elle valait déjà pour la mise en page de
   .xp-tete ; elle n'avait simplement jamais été appliquée à son ENCRE, parce
   qu'une couleur écrite dans un attribut style ne ressemble pas à une classe.

   Le conteneur des deux lignes reste en ligne (« flex:1;min-width:0 »), lui, et
   c'est délibéré : c'est de la GÉOMÉTRIE, et ce lot ne porte que des couleurs.
   Il se remontera ici quand quelqu'un reprendra les mises en page en ligne. */
.xp-tete-titre { font-size: 14px; font-weight: 700; color: var(--et-sur-aplat); }
.xp-tete-sous { font-size: 12px; color: var(--et-sur-aplat-doux); }
.xp-corps { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 12px var(--et-modal-pad) 14px; }
.xp-grille { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--et-form-gap-l) var(--et-form-gap-c); align-items: start; margin-top: 12px; }
.xp-cellule { display: grid; grid-template-columns: var(--et-form-lab) minmax(0, 1fr); column-gap: 12px; row-gap: 2px; align-items: start; min-width: 0; }
.xp-cellule > *:not(.xp-label) { grid-column: 2; width: 100%; }
.xp-plein { grid-column: 1 / -1; }
.xp-label { grid-column: 1; grid-row: 1; align-self: start; margin: 0; display: flex; align-items: center; justify-content: flex-end; gap: 5px; height: var(--et-h-champ); font-size: var(--et-fs-lab); color: var(--et-muted); text-align: right; line-height: 1.25; }
.xp-champ { box-sizing: border-box; height: var(--et-h-champ); padding: 0 9px; background: var(--et-surface); border: 1px solid var(--et-form-border); border-radius: var(--et-r2); color: var(--et-ink); font-family: inherit; font-size: var(--et-fs-champ); outline: none; }
/* LES LISTES NATIVES ARRONDISSENT LEURS COINS QUEL QUE SOIT border-radius tant qu'on leur
   laisse leur rendu (2026-09-06, relevé sur la fenêtre de ventilation de SAI-01) : on le leur
   retire et on redessine le chevron — deux traits obliques dans l'encre secondaire — comme
   la feuille kilomètre le fait déjà pour ses champs. Angles droits partout, c'est la charte. */
select.xp-champ {
    appearance: none; -webkit-appearance: none;
    padding-right: 26px;
    background-image:
        linear-gradient(45deg, transparent 50%, var(--et-muted) 50%),
        linear-gradient(135deg, var(--et-muted) 50%, transparent 50%);
    background-position: right 13px center, right 8px center;
    background-size: 5px 5px, 5px 5px;
    background-repeat: no-repeat;
}
.xp-champ.mono { font-family: var(--et-font-mono); }
.xp-champ:focus { border-color: var(--et-form-blue); box-shadow: inset 0 0 0 1px var(--et-form-blue); }
.xp-champ:disabled { background: var(--et-neutre-bg); color: var(--et-muted); }
.xp-bascule { display: flex; align-items: center; gap: 8px; height: var(--et-h-champ); margin: 0; font-size: 13px; color: var(--et-ink); cursor: pointer; }
.xp-recap { margin-top: 12px; padding: 10px 12px; background: var(--et-surface-2); border: 1px solid var(--et-hairline); }
.xp-pied { flex: none; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 8px var(--et-modal-pad); background: var(--et-surface-2); border-top: 1px solid var(--et-hairline); }
.xp-notepied { flex: 1 1 200px; min-width: 0; font-size: 12px; line-height: 1.45; color: var(--et-muted); }
/* ============================================================================
   CE QUI MANQUAIT AU GABARIT POUR QU'UNE FENÊTRE N'AIT PLUS BESOIN DE BOOTSTRAP
   (2026-09-06). Dix-huit écrans du module ouvraient encore leur fenêtre en
   Bootstrap — ModalCadre, .modal-header, .form-control, .btn — ou posaient un
   contenu .xp-* dans un cadre Bootstrap avec des boutons Bootstrap au pied.
   Ce n'est pas qu'ils l'aient voulu : le gabarit n'avait ni bouton, ni alerte,
   ni sous-titre de section, ni largeur large, ni conteneur de titre. Les voici,
   une fois, pour que le prochain écran n'ait rien à recopier.
   ========================================================================== */

/* Le conteneur des deux lignes de l'en-tête — il s'écrivait « flex:1;min-width:0 »
   en ligne dans cinquante-sept appelants (voir plus haut). */
.xp-tete-l { flex: 1; min-width: 0; }

/* Largeurs : la fenêtre ordinaire fait 560 px ; une fenêtre à formulaire large
   (deux colonnes de champs) 800 ; une confirmation 440. */
.xp-modal.est-large { max-width: 800px; }
.xp-modal.est-etroite { max-width: 440px; }
/* Le quatrième cran, 680 px, est venu de la Trésorerie (2026-09-07) : ses cinquante
   fenêtres écrivaient DOUZE largeurs différentes de 520 à 820 px, à la main dans chaque
   cadre — pas douze besoins, une valeur recopiée et retouchée. Quatre crans les
   absorbent : 440 / 560 / 680 / 800. Un cadre de 600 à 680 prend celui-ci. */
.xp-modal.est-moyenne { max-width: 680px; }

/* LE CINQUIÈME CRAN, 1040 px, EST D'UNE AUTRE NATURE QUE LES QUATRE PREMIERS, et c'est ce
   qui le justifie plutôt qu'un besoin de place. Les quatre échelonnent des fenêtres de
   FORMULAIRE — une confirmation, une, deux colonnes de champs — dont la largeur suit le
   nombre de colonnes de .xp-grille. Celui-ci est pour une fenêtre qui tient un formulaire
   ET UNE TABLE : les fiches de SAI-03 (2026-09-07) portent les lignes du modèle, puis la
   pièce développée avec ses deux colonnes de montants et son échéance. Une table ne se
   replie pas comme une grille — elle se comprime, et des montants comprimés se relisent mal.

   1040 et non 800 : c'est la largeur à laquelle la grille dense cesse de se replier (quatre
   blocs d'étiquette de 180 px, un bloc large de 260, le rembourrage du gabarit) ET où les
   cinq colonnes de la pièce gardent leur largeur de lecture. Elle prend aussi toute la
   hauteur, seule des cinq : une fenêtre dont le corps change de hauteur en changeant d'onglet
   ou en ajoutant une ligne se redimensionnerait sous la main.

   Premier appelant, et assumé comme tel : le cran existe pour que la prochaine fenêtre de
   même nature ait un cran plutôt qu'une largeur écrite dans son cadre — ce que la Trésorerie
   avait fait douze fois avant le cran de 680. */
.xp-modal.est-tres-large { max-width: 1040px; height: 100%; }

/* Les boutons du pied. Blanc pour annuler et les gestes secondaires ; bleu pour
   l'action forte ; orange pour LE CTA d'une fenêtre de création — le seul cas où
   l'orange sort du bandeau d'écran (modele-erp.css, .mx-btn-cta) ; rouge pâle
   pour une suppression, bordure et non aplat. Éteint, le CTA est DÉLAVÉ et non
   gris : un bouton à demi effacé se lit comme un défaut d'affichage. */
.xp-btn, .xp-btn-fort, .xp-btn-cta, .xp-btn-danger {
    display: inline-flex; align-items: center; gap: 7px;
    height: 32px; padding: 0 12px;
    background: var(--et-surface); border: 1px solid var(--et-filet-fort); border-radius: 0;
    color: var(--et-ink); font: inherit; font-size: 13px; font-weight: 600;
    text-decoration: none; cursor: pointer;
}
.xp-btn:hover { border-color: var(--et-form-blue); color: var(--et-form-blue); }
.xp-btn-fort { background: var(--et-form-blue); border-color: var(--et-form-blue); color: var(--et-sur-aplat); }
.xp-btn-fort:hover { background: var(--et-form-blue-d); border-color: var(--et-form-blue-d); color: var(--et-sur-aplat); }
.xp-btn-cta { background: var(--et-action); border-color: var(--et-action); color: var(--et-sur-aplat); }
.xp-btn-cta:hover { background: var(--et-action-d); border-color: var(--et-action-d); color: var(--et-sur-aplat); }
.xp-btn-danger { border-color: var(--et-danger); color: var(--et-danger-ink); }
.xp-btn-danger:hover { background: var(--et-danger-badge-bg); }
.xp-btn:disabled { background: var(--et-surface); border-color: var(--et-hairline); color: var(--et-inerte); cursor: not-allowed; }
.xp-btn-fort:disabled, .xp-btn-danger:disabled { background: var(--et-inerte); border-color: var(--et-inerte); color: var(--et-sur-aplat); cursor: not-allowed; }
.xp-btn-cta:disabled { background: var(--et-action-off); border-color: var(--et-action-off); color: var(--et-sur-aplat); cursor: not-allowed; }
.xp-btn:focus-visible, .xp-btn-fort:focus-visible, .xp-btn-cta:focus-visible, .xp-btn-danger:focus-visible { outline: 2px solid var(--et-form-blue); outline-offset: 2px; }
/* Dans le pied, l'action forte se cale à droite, après la note. */
.xp-pied > .xp-btn-fort, .xp-pied > .xp-btn-cta, .xp-pied > .xp-btn-danger { margin-left: auto; }
.xp-pied > .xp-notepied ~ .xp-btn-fort, .xp-pied > .xp-notepied ~ .xp-btn-cta, .xp-pied > .xp-notepied ~ .xp-btn-danger,
.xp-pied > .xp-btn ~ .xp-btn-fort, .xp-pied > .xp-btn ~ .xp-btn-cta, .xp-pied > .xp-btn ~ .xp-btn-danger { margin-left: 0; }

/* L'alerte d'une fenêtre : un refus du serveur, une mise en garde avant un geste. Fond
   d'état, encre du rang -ink (docs/couleurs-en-dur.md). */
.xp-alerte { display: flex; align-items: flex-start; gap: 9px; margin: 0 0 12px; padding: 8px 11px; font-size: 13px; line-height: 1.45; }
.xp-alerte.est-grave { background: var(--et-danger-badge-bg); color: var(--et-danger-ink); }
.xp-alerte.est-signal { background: var(--et-avertissement-bg); color: var(--et-avertissement-ink); }
.xp-alerte.est-info { background: var(--et-tint); color: var(--et-ink); }
.xp-alerte > .bi { flex: none; margin-top: 2px; }

/* Une note sous les champs, et un sous-titre de section entre deux groupes. */
.xp-aide { display: flex; align-items: flex-start; gap: 7px; margin: 12px 0 0; font-size: 12px; line-height: 1.5; color: var(--et-muted); }
.xp-aide > .bi { flex: none; color: var(--et-form-blue); margin-top: 2px; }
.xp-section { grid-column: 1 / -1; margin: 6px 0 0; padding-top: 10px; border-top: 1px solid var(--et-hairline); font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--et-muted); }
/* Un texte de confirmation, sans grille : la question, puis ce qu'il faut savoir. */
.xp-question { margin: 0; font-size: 14px; color: var(--et-ink); line-height: 1.5; }
.xp-question + .xp-aide { margin-top: 10px; }
/* Une zone de texte garde la grammaire du champ et prend sa hauteur au contenu. */
textarea.xp-champ { height: auto; min-height: 72px; padding: 7px 9px; resize: vertical; line-height: 1.45; }
.xp-champ.num { text-align: right; font-family: var(--et-font-mono); font-variant-numeric: tabular-nums; }

/* UN CHAMP DE DATE NATIF NE SE COMPRIME PAS COMME UN CHAMP DE TEXTE (2026-09-07).
   Le contrôle du navigateur pose lui-même « jj/mm/aaaa » et son bouton de calendrier :
   à l'échelle de la charte (14 px, fonte mono) il lui faut 146 px, mesurés sous Chromium.
   La demi-rangée de .xp-grille lui en donne 120 — 120 px de piste moins les 120 px de
   libellé et les 12 px de gouttière sur une colonne de 252 — et le navigateur n'avertit
   pas : il AMPUTE, en silence. Sur CPT-02 la borne d'exercice s'affichait « 01/01/202 »,
   millésime coupé, sur l'écran dont c'est justement le sujet.

   Une borne de date se pose donc en rangée entière, et là elle prend sa largeur
   NATURELLE plutôt que les 388 px de la piste : max-content suit le format et la fonte
   du poste, donc il ne coupera pas davantage sous une locale plus longue. La règle est
   ici et non dans une feuille d'écran parce qu'elle corrige le « width: 100% » du
   gabarit lui-même — et parce qu'elle ne vaut QUE pour .xp-plein : dans une demi-rangée
   elle déborderait sur la cellule voisine, ce qui est pire que la coupe. */
.xp-cellule.xp-plein > input[type="date"].xp-champ,
.xp-cellule.xp-plein > input[type="datetime-local"].xp-champ,
.xp-cellule.xp-plein > input[type="month"].xp-champ,
.xp-cellule.xp-plein > input[type="time"].xp-champ { width: max-content; max-width: 100%; }

/* ---- Paliers, sur l'échelle retenue (docs/conventions-responsive.md) ----
   720 et non 900 : 900 n'est pas un palier de l'échelle. Sous 1024 px les cibles
   font 44 px ; sous 720 px la fenêtre prend tout l'écran et la grille une colonne. */
@media (max-width: 1024px) {
  .xp-champ, .xp-bascule { height: 44px; }
  textarea.xp-champ { height: auto; }
  .xp-btn, .xp-btn-fort, .xp-btn-cta, .xp-btn-danger { min-height: 44px; }
  .xp-btn { min-width: 44px; }
  .xp-fermer { width: 44px; height: 44px; }
}
@media (max-width: 720px) {
  .xp-voile { padding: 0; }
  .xp-modal, .xp-modal.est-large, .xp-modal.est-tres-large,
  .xp-modal.est-moyenne, .xp-modal.est-etroite { max-width: 100%; height: 100%; border: 0; }
  .xp-grille { grid-template-columns: minmax(0, 1fr); }
  .xp-cellule, .xp-cellule.xp-plein { grid-template-columns: minmax(0, 1fr); }
  .xp-cellule > *:not(.xp-label) { grid-column: 1; }
  .xp-label { justify-content: flex-start; height: auto; min-height: 0; text-align: left; }
  .xp-pied > .xp-btn, .xp-pied > .xp-btn-fort, .xp-pied > .xp-btn-cta, .xp-pied > .xp-btn-danger { flex: 1 1 100%; justify-content: center; margin-left: 0; }
}


/* ---- Cases à cocher des fenêtres : LA REPRISE EST PARTIE (2026-09-10) ----

   CE QU'IL Y AVAIT ICI, ET POURQUOI ÇA N'A PLUS D'OBJET
     Un sélecteur en huit branches — « finit par -bascule », « contient
     -bascule », « contient -modal », « contient -voile », fois checkbox et
     radio — qui reposait 17 px sur toute case du module. Il défaisait le
     « width: 100% » que app.css pose sur TOUT input : sans lui la case prenait
     la largeur de sa ligne et écrasait son libellé à zéro.
     Depuis le 2026-09-09, app.css pose lui-même les 17 px, juste après son
     « width: 100% » et dans le même fichier — donc plus rien à défaire ici.

   POURQUOI LE RETIRER, ET PAS SEULEMENT PARCE QUE C'EST REDONDANT
     Sa spécificité était (0,2,1), et cette feuille est liée en App.razor:344,
     très tard. Il gagnait donc contre TOUT — y compris contre ce qui devait
     le dépasser :
       · la marche tactile de lot02 (0,1,1) : six écrans restaient à 17 px sous
         1024 px au lieu de 24, dont le modèle de fiche .fx-* et le gabarit ;
       · les 24 px que le POS pose lui-même sur .inv-bascule input (0,1,1) —
         écrasés à 17 px alors que le POS a sa propre densité et n'est pas
         régi par la charte.
     Aucun des deux ne se voyait autrement qu'en mesurant : une règle plus
     spécifique ne produit pas d'erreur, elle gagne. Relevé au banc, avec
     CSS.getMatchedStylesForNode plutôt qu'en relisant la cascade.

   CE QUE ÇA N'ANNULE PAS
     Le motif « -bascule suivi d'une ESPACE » reste la bonne façon de nommer un
     jeton de classe qui n'est pas le dernier, et la leçon des huit bascules de
     VNT-09 tient : « finit par » lit l'attribut entier, donc un ternaire Razor
     qui rend vide suffit à le faire échouer. C'est écrit dans
     docs/conventions-nommage.md ; ce n'est plus écrit en CSS ici. */

/* ============================================================================
   LE BLOC DE FICHE — le gabarit du module, une fois pour toutes.

   POURQUOI IL MONTE ICI. C'est le motif le plus recopié du domaine : « un titre
   de section, deux colonnes d'étiquette/valeur, une note dessous, parfois un
   petit tableau ». Il vivait sous QUINZE préfixes différents (.dr-, .fb-, .x8-,
   .r4-, .f7-, .c1-, .p6-, .m2-, .e3-, .d4-, .p9-, .r2-, .r1-, .m4-, .cpd-),
   dans quinze feuilles d'écran, avec quinze fois les mêmes valeurs — et déjà
   trois variantes involontaires : l'une n'était déclarée que sous .xp-corps et
   disparaissait dès qu'on posait le bloc dans la page, une autre avait perdu
   son repli à une colonne sous 1024 px. Quinze copies d'une même règle ne sont
   pas quinze règles : c'est une règle et quatorze occasions de la voir diverger.

   OÙ ELLE VIT. Dans la feuille des fenêtres, parce que c'est là que le bloc sert
   le plus souvent ; sous le préfixe .eca- du gabarit de module, comme .eca-carte
   et .eca-onglets, parce qu'il sert AUSSI en pleine page — les deux portées sont
   déclarées ensemble, ce qu'aucune des quinze copies ne faisait de façon fiable.

   ANATOMIE : .eca-bloc > .h > span (titre) · .eca-duo (deux colonnes)
              .eca-lab (étiquette) · .eca-val (valeur) · .eca-aide (note)
              .eca-tab (petit tableau : th, td, td.txt, td.num)
   ========================================================================== */

.appgrid .eca-bloc, .xp-corps .eca-bloc { margin-top: 12px; }
.appgrid .eca-bloc:first-child, .xp-corps .eca-bloc:first-child { margin-top: 0; }

.appgrid .eca-bloc .h, .xp-corps .eca-bloc .h { display: flex; align-items: center; gap: 8px; margin-bottom: 7px; }
.appgrid .eca-bloc .h::before, .xp-corps .eca-bloc .h::before { content: ""; flex: none; width: 3px; height: 13px; background: var(--et-form-blue); }
.appgrid .eca-bloc .h span, .xp-corps .eca-bloc .h span { font-family: var(--et-font-mono); font-size: 12px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--et-table-head-encre); }

.appgrid .eca-duo, .xp-corps .eca-duo { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 14px; }
.appgrid .eca-lab, .xp-corps .eca-lab { display: block; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .06em; color: var(--et-muted); margin-bottom: 2px; }
.appgrid .eca-val, .xp-corps .eca-val { font-family: var(--et-font-mono); font-size: 14px; color: var(--et-ink); }
.appgrid .eca-aide, .xp-corps .eca-aide { margin-top: 6px; font-size: 12px; color: var(--et-faint); line-height: 1.5; }

.appgrid .eca-tab, .xp-corps .eca-tab { width: 100%; border-collapse: collapse; font-size: 13px; }
.appgrid .eca-tab th, .xp-corps .eca-tab th { text-align: left; font-size: 12px; text-transform: uppercase; letter-spacing: .06em; color: var(--et-muted); font-weight: 600; padding: 4px 6px; border-bottom: 1px solid var(--et-hairline); }
.appgrid .eca-tab td, .xp-corps .eca-tab td { padding: 5px 6px; border-bottom: 1px solid var(--et-hairline); font-family: var(--et-font-mono); }
.appgrid .eca-tab td.txt, .xp-corps .eca-tab td.txt { font-family: var(--et-font); }
.appgrid .eca-tab td.num, .xp-corps .eca-tab td.num { text-align: right; }

/* Sous 1024 px les deux colonnes se replient : une étiquette et sa valeur ne se
   partagent pas la moitié d'un téléphone. Le repli manquait à deux des copies. */
@media (max-width: 1024px) {
  .appgrid .eca-duo, .xp-corps .eca-duo { grid-template-columns: minmax(0, 1fr); }
}
