/* ==========================================================================
   gdv-app.css - L'Esprit du Vin

   La seule feuille de l'application, posee APRES dist/isl-ui.css et APRES
   le theme. Elle ne contient pas une couleur litterale : tout passe par
   les jetons --isl-*, et c'est ce qui permet a l'ecran de reglage de
   reteindre l'application entiere sans toucher une regle.

   Deux moities, et il faut savoir dans laquelle on ecrit :

      1. LA COQUE (.gdv-*) - barre laterale, barre du haut, palette,
         pied. Elle est neuve : rien de l'ancien habillage n'y survit.

      2. LA REPRISE DU BALISAGE EXISTANT - les quatre-vingt-dix-huit
         modules ecrivent encore <table class="tableau_chps">, .gu-btn,
         .type2... On ne les reecrit pas tous le meme jour ; on redit ce
         que ces balises veulent dire, en jetons. Un ecran repris en
         isl_table() et un ecran encore en <table class="type2"> doivent
         etre indiscernables, sinon la reprise se voit.

   100 % ASCII, comme tout ce qui touche a isl-ui : la moitie de la flotte
   est en latin1.
   ========================================================================== */


/* ==========================================================================
   0. BASE
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

/* Le fond est pose sur <html>, pas seulement sur <body>. Entre deux
   ecrans, le navigateur peint sa toile avant le corps de la page : sans
   cette ligne, chaque navigation passait par un eclair blanc. Et
   color-scheme fait suivre les barres de defilement et les controles
   natifs, qui restaient clairs dans une application sombre. */
html {
   -webkit-text-size-adjust: 100%;
   background: var(--isl-bg);
   color-scheme: light;

   /* Hauteur reelle de la barre du haut. Tout ce qui colle en haut de
      page colle SOUS elle, jamais dessous au sens de l'empilement :
      .gdv-top est collante a top:0 avec z-index 30, donc un en-tete de
      tableau colle a top:0 passait derriere elle et n'etait jamais
      visible. La valeur est remesuree par gdv-app.js - la barre passe a
      deux lignes des que la fenetre est etroite. */
   --gdv-top-h: 62px;
}
:root[data-theme="dark"] { color-scheme: dark; }
@media (prefers-color-scheme: dark) {
   :root:not([data-theme="light"]) { color-scheme: dark; }
}

body.gdv {
   margin: 0;
   padding: 0;
   min-height: 100vh;
   background: var(--isl-bg);
   color: var(--isl-fg);
   font-family: var(--isl-font-ui);
   font-size: var(--isl-fs-base);
   line-height: 1.5;
   -webkit-font-smoothing: antialiased;
}

/* Les chiffres d'un ERP se lisent en colonne. Des chiffres a chasse
   variable font danser les centimes d'une ligne a l'autre. */
body.gdv { font-variant-numeric: tabular-nums; }

/* La couleur des liens de texte. Elle est posee a travers :where() pour que
   le prefixe body.gdv ne compte pas dans la specificite : sans cela, la
   regle vaut (0,1,2) et l'emporte sur .isl-btn (0,1,0) ou .gu-btn, c'est a
   dire sur tout <a> rendu en bouton.

   La variante :visited a ete retiree, et pas seulement parce qu'elle
   repetait la meme couleur. Etant une pseudo-classe, elle comptait DEUX
   classes : elle battait jusqu'a .isl-btn.primary (0,2,0) et repeignait le
   libelle d'un bouton plein dans la teinte de son propre fond. Le bouton
   devenait une pastille vide - mais seulement une fois l'ecran visite, donc
   jamais devant celui qui vient de l'ecrire. */
:where(body.gdv) a { color: var(--isl-accent-text); }
:where(body.gdv) a:hover { color: var(--isl-accent-hover); }

/* Un <a class="isl-btn"> doit etre indiscernable d'un <button class="isl-btn">.
   Sans cette reprise il reste plus specifique de deux regles de lien - celle
   ci-dessus et le .isl-scope a d'isl-ui - et le meme bouton change de couleur
   selon qu'il est ecrit en lien ou en bouton, d'un ecran a l'autre. */
body.gdv a.isl-btn { color: var(--isl-fg); }
body.gdv a.isl-btn:hover { color: var(--isl-accent-text); }
body.gdv a.isl-btn.ghost { color: var(--isl-muted); }
body.gdv a.isl-btn.ghost:hover { color: var(--isl-accent-text); }

/* Filet de securite : un <a> rendu en bouton plein porte son libelle sur un
   aplat d'accent. Quelle que soit la regle de lien qui passera par la un
   jour, ces trois-la gardent le texte que l'aplat exige. */
body.gdv a.isl-btn.primary,
body.gdv a.isl-btn.primary:visited,
body.gdv a.isl-btn.primary:hover,
body.gdv a.isl-btn.danger,
body.gdv a.isl-btn.danger:visited,
body.gdv a.gu-btn-primary,
body.gdv a.gu-btn-primary:visited,
body.gdv a.gu-btn-danger,
body.gdv a.gu-btn-danger:visited,
body.gdv a.gu-new,
body.gdv a.gu-new:visited { color: var(--isl-on-accent); }

body.gdv h1, body.gdv h2, body.gdv h3, body.gdv h4 {
   font-family: var(--isl-font-display);
   letter-spacing: -.02em;
   color: var(--isl-fg);
}

body.gdv img { border: 0; max-width: 100%; }

::selection { background: var(--isl-accent); color: var(--isl-on-accent); }

/* Un seul anneau de focus pour toute l'application. Il doit rester
   visible sur la barre laterale sombre comme sur une carte claire. */
body.gdv :focus-visible {
   outline: 2px solid var(--isl-accent);
   outline-offset: 2px;
   border-radius: var(--isl-r-sm);
}

/* Barres de defilement discretes, dans la teinte du theme. */
body.gdv * { scrollbar-width: thin; scrollbar-color: var(--isl-border-strong) transparent; }
body.gdv ::-webkit-scrollbar { width: 10px; height: 10px; }
body.gdv ::-webkit-scrollbar-track { background: transparent; }
body.gdv ::-webkit-scrollbar-thumb {
   background: var(--isl-border-strong);
   border: 3px solid transparent;
   background-clip: content-box;
   border-radius: var(--isl-r-full);
}
body.gdv ::-webkit-scrollbar-thumb:hover { background-color: var(--isl-subtle); background-clip: content-box; }


/* ==========================================================================
   1. COQUE - ossature
   Une colonne de navigation, une colonne de travail. La navigation ne
   defile pas avec le contenu : sur un poste de comptoir, on y revient
   vingt fois par heure.
   ========================================================================== */

body.gdv .gdv-skip {
   position: absolute; left: -9999px; top: 0; z-index: 200;
   background: var(--isl-accent); color: var(--isl-on-accent);
   padding: 10px 16px; border-radius: 0 0 var(--isl-r) 0; text-decoration: none;
}
body.gdv .gdv-skip:focus { left: 0; }

body.gdv .gdv-app {
   display: flex;
   min-height: 100vh;
   align-items: stretch;
}

/* --- barre laterale ---------------------------------------------------- */

/* La colonne ne se peint PAS avec --isl-fg / --isl-bg : ces deux jetons
   s'echangent en mode sombre, et la colonne devenait blanche a gauche
   d'une application noire. Elle a sa propre famille de jetons, ecrite a
   l'identique dans les deux modes par gdv_theme_coque(). */
body.gdv .gdv-side {
   flex: 0 0 var(--gdv-side-w, 254px);
   width: var(--gdv-side-w, 254px);
   background: var(--gdv-side-bg);
   color: var(--gdv-side-fg);
   display: flex;
   flex-direction: column;
   position: sticky;
   top: 0;
   height: 100vh;
   z-index: 40;
   transition: flex-basis var(--isl-t-slow), width var(--isl-t-slow);
}

/* Repliee, la colonne ne garde que les icones. Le choix est garde sur le
   poste : un caissier qui travaille sur 1280 px la replie une fois pour
   toutes. */
html.is-side-tight body.gdv .gdv-side { --gdv-side-w: 62px; }
html.is-side-tight body.gdv .gdv-nav-lib,
html.is-side-tight body.gdv .gdv-nav-caret,
html.is-side-tight body.gdv .gdv-side-search,
html.is-side-tight body.gdv .gdv-side-foot-txt,
html.is-side-tight body.gdv .gdv-brand-txt { display: none; }
html.is-side-tight body.gdv .gdv-nav-grp .gdv-nav-sub { display: none !important; }
html.is-side-tight body.gdv .gdv-nav-top { justify-content: center; padding-left: 0; padding-right: 0; }
html.is-side-tight body.gdv .gdv-brand { justify-content: center; padding-left: 0; padding-right: 0; }
/* Repliee, la colonne fait 62 px : l'avatar, l'engrenage et la porte ne
   tiennent pas sur une ligne. Ils s'empilent au lieu de deborder. */
html.is-side-tight body.gdv .gdv-side-foot {
   justify-content: center;
   flex-wrap: wrap;
   gap: 4px;
   padding-left: 4px; padding-right: 4px;
}

body.gdv .gdv-brand {
   display: flex; align-items: center; gap: 10px;
   padding: 14px 16px;
   min-height: 62px;
   background: var(--gdv-side-bg-2);
   border-bottom: 1px solid var(--gdv-side-line);
   text-decoration: none;
   color: var(--gdv-side-fg);
   flex: none;
   transition: background var(--isl-t-fast);
}
body.gdv .gdv-brand:hover { color: var(--gdv-side-fg); background: var(--gdv-side-hov); }
body.gdv .gdv-brand-logo {
   width: 34px; height: 34px; flex: none;
   border-radius: var(--isl-r-sm);
   object-fit: contain;
   background: var(--isl-surface);
   padding: 2px;
}
body.gdv .gdv-brand-txt { min-width: 0; }
body.gdv .gdv-brand-nom {
   display: block;
   font-family: var(--isl-font-display);
   font-size: 14.5px; font-weight: 700; letter-spacing: -.02em;
   white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
body.gdv .gdv-brand-soc {
   display: block; font-size: 11px; color: var(--gdv-side-mut);
   white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Le champ de recherche de la colonne n'est pas un champ : c'est le
   declencheur de la palette. Le faire ressembler a un champ et ne pas
   pouvoir y taper serait un mensonge - il porte donc son raccourci. */
body.gdv .gdv-side-search { padding: 12px 12px 6px; flex: none; }
body.gdv .gdv-side-search button {
   width: 100%;
   display: flex; align-items: center; gap: 8px;
   padding: 7px 10px;
   font: inherit; font-size: 12.5px; text-align: left;
   color: var(--gdv-side-mut);
   background: var(--gdv-side-hov);
   border: 1px solid var(--gdv-side-line);
   border-radius: var(--isl-r-sm);
   cursor: pointer;
   transition: color var(--isl-t-fast), background var(--isl-t-fast), border-color var(--isl-t-fast);
}
body.gdv .gdv-side-search button:hover {
   color: var(--gdv-side-fg);
   background: var(--gdv-side-hov-2);
   border-color: var(--gdv-side-hov-2);
}
body.gdv .gdv-side-search svg { width: 14px; height: 14px; flex: none; }
body.gdv .gdv-side-search kbd {
   margin-left: auto; font: inherit; font-size: 10.5px;
   padding: 1px 5px; border-radius: 4px;
   color: var(--gdv-side-fg);
   background: var(--gdv-side-hov-2);
}

body.gdv .gdv-nav {
   flex: 1 1 auto;
   overflow-y: auto;
   overflow-x: hidden;
   padding: 6px 8px 16px;
}

/* Les entrees se distinguent par la COULEUR, pas par l'opacite. Un
   libelle a 66 % d'opacite sur un fond sombre tombe sous le seuil AA :
   c'est lui qu'on ne lisait plus. Au repos --gdv-side-mut donne 8:1, au
   survol --gdv-side-fg donne 18:1, et le fond de survol est un vrai
   aplat au lieu d'un gris a 18 % qui ne se voyait sur aucun des deux
   modes. */
body.gdv .gdv-nav-top {
   width: 100%;
   display: flex; align-items: center; gap: 10px;
   padding: 8px 10px;
   font: inherit; font-size: 13.5px; font-weight: 500;
   color: var(--gdv-side-mut); text-align: left; text-decoration: none;
   background: none; border: none; border-radius: var(--isl-r-sm);
   cursor: pointer;
   transition: color var(--isl-t-fast), background var(--isl-t-fast);
}
body.gdv .gdv-nav-top:hover { background: var(--gdv-side-hov); color: var(--gdv-side-fg); }
body.gdv .gdv-nav-top.is-on {
   font-weight: 600;
   background: var(--gdv-side-hov);
   color: var(--gdv-side-txt-on);
}
body.gdv .gdv-nav-ico { flex: none; display: inline-flex; }
body.gdv .gdv-nav-ico svg { width: 16px; height: 16px; display: block; }
body.gdv .gdv-nav-lib { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
body.gdv .gdv-nav-caret { flex: none; display: inline-flex; transition: transform var(--isl-t); }
body.gdv .gdv-nav-caret svg { width: 14px; height: 14px; display: block; }
body.gdv .gdv-nav-grp.is-open > .gdv-nav-top { color: var(--gdv-side-fg); }
body.gdv .gdv-nav-grp.is-open > .gdv-nav-top .gdv-nav-caret { transform: rotate(180deg); }

/* Le depliage est anime a la main plutot qu'en hauteur automatique :
   une colonne qui saute a chaque clic se lit moins bien qu'une colonne
   qui glisse. */
body.gdv .gdv-nav-sub {
   display: none;
   margin: 2px 0 6px 20px;
   padding-left: 10px;
   border-left: 1px solid var(--gdv-side-line);
}
body.gdv .gdv-nav-grp.is-open > .gdv-nav-sub { display: block; animation: gdv-deplier var(--isl-t-slow) both; }

@keyframes gdv-deplier {
   from { opacity: 0; transform: translateY(-4px); }
   to   { opacity: 1; transform: none; }
}

body.gdv .gdv-nav-item {
   display: block;
   padding: 6px 10px;
   font-size: 12.5px; line-height: 1.35;
   color: var(--gdv-side-mut); text-decoration: none;
   border-radius: var(--isl-r-sm);
   transition: color var(--isl-t-fast), background var(--isl-t-fast);
}
body.gdv .gdv-nav-item:hover { background: var(--gdv-side-hov); color: var(--gdv-side-fg); }
/* L'ecran courant se marque au fond ET au trait : sur un poste de
   comptoir mal regle, l'aplat d'accent seul ne suffit pas toujours. */
body.gdv .gdv-nav-item.is-on {
   font-weight: 600;
   background: var(--gdv-side-on); color: var(--gdv-side-on-fg);
   box-shadow: inset 3px 0 0 var(--gdv-side-fg);
}
body.gdv .gdv-nav-item.is-on:hover { background: var(--gdv-side-on); color: var(--gdv-side-on-fg); }
body.gdv .gdv-nav-item.is-deep { padding-left: 20px; font-size: 12px; }
body.gdv .gdv-nav-sec {
   padding: 10px 10px 3px;
   font-size: 10.5px; font-weight: 700; letter-spacing: .07em;
   text-transform: uppercase; color: var(--gdv-side-sec);
}

body.gdv .gdv-side-foot {
   flex: none;
   display: flex; align-items: center; gap: 8px;
   padding: 10px 12px;
   background: var(--gdv-side-bg-2);
   border-top: 1px solid var(--gdv-side-line);
}
body.gdv .gdv-side-foot-txt { min-width: 0; flex: 1 1 auto; }
body.gdv .gdv-side-foot-nom {
   display: block; font-size: 12.5px; font-weight: 600;
   color: var(--gdv-side-fg);
   white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
body.gdv .gdv-side-foot-rol { display: block; font-size: 11px; color: var(--gdv-side-mut); }
body.gdv .gdv-side-quit,
body.gdv .gdv-side-outil {
   flex: none;
   display: inline-flex; align-items: center; justify-content: center;
   width: 30px; height: 30px;
   color: var(--gdv-side-mut);
   border-radius: var(--isl-r-sm);
   text-decoration: none;
   transition: color var(--isl-t-fast), background var(--isl-t-fast);
}
body.gdv .gdv-side-outil:hover { background: var(--gdv-side-hov); color: var(--gdv-side-fg); }
body.gdv .gdv-side-outil.is-on { background: var(--gdv-side-on); color: var(--gdv-side-on-fg); }
body.gdv .gdv-side-quit:hover { background: var(--isl-danger); color: var(--isl-on-accent); }
body.gdv .gdv-side-quit svg, body.gdv .gdv-side-outil svg { width: 16px; height: 16px; }

body.gdv .gdv-avatar {
   flex: none;
   display: inline-flex; align-items: center; justify-content: center;
   width: 30px; height: 30px;
   border-radius: var(--isl-r-full);
   background: var(--gdv-side-on); color: var(--gdv-side-on-fg);
   font-size: 11.5px; font-weight: 700; letter-spacing: .02em;
}

/* --- colonne de travail ------------------------------------------------ */

body.gdv .gdv-body {
   flex: 1 1 auto;
   min-width: 0;
   display: flex;
   flex-direction: column;
}

body.gdv .gdv-top {
   position: sticky; top: 0; z-index: 30;
   display: flex; align-items: center; gap: var(--isl-s3);
   flex-wrap: wrap;
   min-height: 62px;
   padding: 8px var(--isl-s5);
   background: var(--isl-surface);
   border-bottom: 1px solid var(--isl-border);
}

body.gdv .gdv-burger {
   display: inline-flex; align-items: center; justify-content: center;
   width: 34px; height: 34px; flex: none;
   background: none; border: 1px solid transparent; border-radius: var(--isl-r-sm);
   color: var(--isl-muted); cursor: pointer;
   transition: background var(--isl-t-fast), color var(--isl-t-fast);
}
body.gdv .gdv-burger:hover { background: var(--isl-surface-2); color: var(--isl-fg); }
body.gdv .gdv-burger svg { width: 18px; height: 18px; }

body.gdv .gdv-fil {
   display: flex; align-items: center; gap: 6px;
   min-width: 0; flex-wrap: wrap;
   font-size: 12.5px; color: var(--isl-subtle);
}
body.gdv .gdv-fil svg { width: 12px; height: 12px; opacity: .5; flex: none; }
body.gdv .gdv-fil a { color: inherit; text-decoration: none; }
body.gdv .gdv-fil a:hover { color: var(--isl-accent-text); }
body.gdv .gdv-fil strong { color: var(--isl-fg); font-weight: 600; }

body.gdv .gdv-top-right { margin-left: auto; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

body.gdv .gdv-horloge {
   font-size: 12px; color: var(--isl-subtle);
   font-variant-numeric: tabular-nums;
   white-space: nowrap;
}

/* Le selecteur de societe est un vrai <select> : il porte le name, il
   part au POST, et sans JavaScript il reste utilisable. Il etait aussi le
   seul controle de la barre a ne pas etre a la mesure des autres - 28 px
   de haut a cote d'un bouton de 34 - et son chevron etait dessine avec
   deux degrades, le seul du projet : on ne reconnaissait pas le meme
   logiciel d'un bout de la barre a l'autre.

   C'est donc le <select> lui-meme qui porte le cadre, le fond et toute la
   surface du controle ; l'icone metier et le chevron sont poses par-dessus,
   en absolu, et le remplissage du champ leur reserve leur place.

   Le premier jet faisait l'inverse - habillage sur l'enveloppe, champ nu
   pose au milieu - et c'etait un piege : un pointer-events:none sur le
   chevron ne fait pas tomber le clic sur le champ, il le fait tomber sur le
   <span> qui est dessous. Le controle mesurait 115 px et n'en ouvrait que
   55 ; le chevron, la seule chose qu'on ait envie de cliquer, ne
   repondait pas. Quand un habillage entoure un champ natif, c'est au champ
   de faire toute la boite. */
body.gdv .gdv-soc {
   position: relative;
   display: inline-flex; align-items: center;
   color: var(--isl-muted);
}
body.gdv .gdv-soc:hover { color: var(--isl-accent-text); }

/* Poses sur le champ, jamais devant lui : sans pointer-events:none, le
   chevron redeviendrait un trou dans la surface cliquable. */
body.gdv .gdv-soc-ico,
body.gdv .gdv-soc-caret {
   position: absolute; display: inline-flex; pointer-events: none;
}
body.gdv .gdv-soc-ico { left: 10px; }
body.gdv .gdv-soc-caret { right: 9px; }
body.gdv .gdv-soc-ico svg { width: 14px; height: 14px; opacity: .8; }
body.gdv .gdv-soc-caret svg { width: 13px; height: 13px; opacity: .6; }

/* Trois selecteurs de classe pour battre body.gdv select:hover:not(:disabled)
   et body.gdv select:focus, declares plus bas et donc gagnants a egalite. */
body.gdv .gdv-soc select,
body.gdv .gdv-soc select:hover:not(:disabled),
body.gdv .gdv-soc select:focus {
   font: inherit; font-size: 12.5px; font-weight: 600;
   line-height: 1; letter-spacing: .1px;
   height: 34px; margin: 0; max-width: 170px;
   padding: 0 27px 0 31px;
   color: var(--isl-fg);
   background: var(--isl-surface-2);
   border: 1px solid var(--isl-border);
   border-radius: var(--isl-r-sm);
   box-shadow: none; outline: none;
   cursor: pointer;
   appearance: none; -webkit-appearance: none;
   text-overflow: ellipsis;
   transition: background var(--isl-t-fast), border-color var(--isl-t-fast), box-shadow var(--isl-t-fast);
}
body.gdv .gdv-soc select:hover:not(:disabled) { background: var(--isl-accent-soft); border-color: var(--isl-accent-border); }
body.gdv .gdv-soc select:focus { border-color: var(--isl-accent); box-shadow: 0 0 0 3px var(--isl-ring); }
/* Le menu deroulant natif est peint par le systeme, qui reprend le fond du
   <select>. On le lui redonne en jetons plutot que de compter sur ce que
   le navigateur devine : sur une teinte de marque sombre, plusieurs
   rendaient les options en clair sur clair. */
body.gdv .gdv-soc select option { background: var(--isl-surface); color: var(--isl-fg); }

/* .gdv-icobtn et les regles d'echange lune / soleil ont disparu avec le
   bouton de mode, qui etait leur seul porteur : le reglage vit maintenant
   dans la charte graphique. */

/* --- bandeau d'alertes -------------------------------------------------- */

body.gdv .gdv-alertes {
   display: flex; gap: 8px; flex-wrap: wrap;
   padding: 10px var(--isl-s5);
   background: var(--isl-surface);
   border-bottom: 1px solid var(--isl-border);
}
body.gdv .gdv-alertes:empty { display: none; }

body.gdv .gdv-pill {
   display: inline-flex; align-items: center; gap: 7px;
   padding: 5px 11px 5px 9px;
   font-size: 12px; line-height: 1.3;
   color: var(--isl-muted);
   background: var(--isl-surface-2);
   border: 1px solid var(--isl-border);
   border-radius: var(--isl-r-full);
   text-decoration: none;
   white-space: nowrap;
   transition: transform var(--isl-t-fast), box-shadow var(--isl-t-fast), border-color var(--isl-t-fast);
}
a.gdv-pill:hover { transform: translateY(-1px); box-shadow: var(--isl-sh-1); border-color: var(--isl-border-strong); color: var(--isl-muted); }
body.gdv .gdv-pill svg { width: 14px; height: 14px; flex: none; opacity: .7; }
body.gdv .gdv-pill-lib { color: var(--isl-subtle); }
body.gdv .gdv-pill-val { font-weight: 700; color: var(--isl-fg); }

body.gdv .gdv-pill.warn { background: var(--isl-warning-soft); border-color: transparent; }
body.gdv .gdv-pill.warn svg, body.gdv .gdv-pill.warn .gdv-pill-val { color: var(--isl-warning); opacity: 1; }
body.gdv .gdv-pill.bad { background: var(--isl-danger-soft); border-color: transparent; }
body.gdv .gdv-pill.bad svg, body.gdv .gdv-pill.bad .gdv-pill-val { color: var(--isl-danger); opacity: 1; }
body.gdv .gdv-pill.ok { background: var(--isl-success-soft); border-color: transparent; }
body.gdv .gdv-pill.ok svg, body.gdv .gdv-pill.ok .gdv-pill-val { color: var(--isl-success); opacity: 1; }
body.gdv .gdv-pill.accent { background: var(--isl-accent-soft); border-color: transparent; }
body.gdv .gdv-pill.accent svg, body.gdv .gdv-pill.accent .gdv-pill-val { color: var(--isl-accent-text); opacity: 1; }

/* --- zone de travail ---------------------------------------------------- */

/* Pas d'animation d'entree ici. Chaque changement d'ecran est un
   rechargement complet : faire apparaitre le contenu depuis l'opacite
   zero, c'est precisement fabriquer le clignotement qu'on cherche a
   supprimer. Les animations restent la ou elles accompagnent un geste
   de l'utilisateur - depliage d'un groupe, ouverture de la palette. */
body.gdv .gdv-main {
   flex: 1 1 auto;
   padding: var(--isl-s5) var(--isl-s5) var(--isl-s7);
   min-width: 0;
}
@media (prefers-reduced-motion: reduce) {
   body.gdv .gdv-nav-grp.is-open > .gdv-nav-sub { animation: none; }
   body.gdv *, body.gdv *::before, body.gdv *::after {
      animation-duration: .01ms !important;
      transition-duration: .01ms !important;
   }
}

body.gdv .gdv-foot {
   flex: none;
   display: flex; align-items: center; gap: var(--isl-s4); flex-wrap: wrap;
   padding: var(--isl-s4) var(--isl-s5);
   border-top: 1px solid var(--isl-border);
   font-size: 11.5px; color: var(--isl-subtle);
}
body.gdv .gdv-foot a { color: inherit; text-decoration: none; }
body.gdv .gdv-foot a:hover { color: var(--isl-accent-text); text-decoration: underline; }
body.gdv .gdv-foot .gdv-foot-right { margin-left: auto; display: flex; gap: var(--isl-s4); }

/* Le bandeau d'environnement. Rouge, large, en haut : sur un poste de
   comptoir, confondre le serveur de test et la production coute une
   journee de saisie. */
body.gdv .gdv-env {
   padding: 6px var(--isl-s5);
   background: var(--isl-danger);
   color: var(--isl-on-accent);
   font-size: 12px; font-weight: 700; letter-spacing: .06em;
   text-transform: uppercase; text-align: center;
}

body.gdv .gdv-haut {
   position: fixed; right: 22px; bottom: 22px; z-index: 35;
   display: inline-flex; align-items: center; justify-content: center;
   width: 42px; height: 42px;
   background: var(--isl-accent); color: var(--isl-on-accent);
   border: none; border-radius: var(--isl-r-full);
   box-shadow: var(--isl-sh-2);
   cursor: pointer;
   opacity: 0; pointer-events: none; transform: translateY(8px);
   transition: opacity var(--isl-t), transform var(--isl-t);
}
body.gdv .gdv-haut.is-on { opacity: 1; pointer-events: auto; transform: none; }
body.gdv .gdv-haut svg { width: 18px; height: 18px; transform: rotate(180deg); }


/* ==========================================================================
   2. PALETTE (Ctrl+K)
   Quatre-vingt-dix-huit ecrans derriere trois niveaux de menu : chercher
   un ecran au clavier est plus rapide que de le retrouver a l'oeil.
   ========================================================================== */

body.gdv .gdv-pal-back {
   position: fixed; inset: 0; z-index: 120;
   display: none;
   background: rgba(0, 0, 0, .42);
   backdrop-filter: blur(2px);
   padding: 10vh 16px 16px;
}
body.gdv .gdv-pal-back.is-on { display: block; animation: gdv-fondu var(--isl-t) both; }
@keyframes gdv-fondu { from { opacity: 0; } to { opacity: 1; } }

body.gdv .gdv-pal {
   max-width: 620px; margin: 0 auto;
   background: var(--isl-surface);
   border: 1px solid var(--isl-border);
   border-radius: var(--isl-r-lg);
   box-shadow: var(--isl-sh-3);
   overflow: hidden;
   animation: gdv-monte var(--isl-t-slow) both;
}
@keyframes gdv-monte {
   from { opacity: 0; transform: translateY(-10px) scale(.98); }
   to   { opacity: 1; transform: none; }
}

body.gdv .gdv-pal-head {
   display: flex; align-items: center; gap: 10px;
   padding: 12px 16px;
   border-bottom: 1px solid var(--isl-border);
}
body.gdv .gdv-pal-head svg { width: 17px; height: 17px; color: var(--isl-subtle); flex: none; }
body.gdv .gdv-pal-head input {
   flex: 1 1 auto; min-width: 0;
   font: inherit; font-size: 15px;
   color: var(--isl-fg); background: none; border: none; outline: none;
}
body.gdv .gdv-pal-head input::placeholder { color: var(--isl-subtle); }
body.gdv .gdv-pal-head kbd {
   font: inherit; font-size: 10.5px; color: var(--isl-subtle);
   padding: 2px 6px; border: 1px solid var(--isl-border); border-radius: 4px;
}

body.gdv .gdv-pal-liste { max-height: 52vh; overflow-y: auto; padding: 6px; }

body.gdv .gdv-pal-item {
   display: flex; align-items: center; gap: 10px;
   padding: 9px 11px;
   border-radius: var(--isl-r-sm);
   color: var(--isl-fg); text-decoration: none;
   cursor: pointer;
}
/* Le titre de groupe colle en haut de la boite : sans cette marge de
   defilement, la fleche bas amenerait l'entree suivante EXACTEMENT
   dessous, donc cachee par lui. */
body.gdv .gdv-pal-item { scroll-margin-top: 28px; }
body.gdv .gdv-pal-item svg { width: 15px; height: 15px; color: var(--isl-subtle); flex: none; }
body.gdv .gdv-pal-item .gdv-pal-lib { font-size: 13.5px; font-weight: 500; }
body.gdv .gdv-pal-item .gdv-pal-chemin { margin-left: auto; font-size: 11.5px; color: var(--isl-subtle); }
body.gdv .gdv-pal-item.is-cur,
body.gdv .gdv-pal-item:hover {
   background: var(--isl-accent-soft);
   color: var(--isl-accent-text);
}
body.gdv .gdv-pal-item.is-cur svg, body.gdv .gdv-pal-item:hover svg { color: var(--isl-accent-text); }

body.gdv .gdv-pal-vide { padding: 26px 16px; text-align: center; font-size: 13px; color: var(--isl-subtle); }


/* ==========================================================================
   3. REPRISE DU BALISAGE EXISTANT
   A partir d'ici, on ne decrit plus des composants neufs : on redit en
   jetons ce que les modules ecrivent deja.
   ========================================================================== */

/* --- l'ancienne coque n'existe plus ------------------------------------- */
/* Ces identifiants trainent encore dans quelques modules et dans les
   pages autonomes. Les neutraliser evite qu'un vieux panneau ne
   reapparaisse au milieu du nouvel ecran. */
body.gdv #topPan,
body.gdv #headerPan,
body.gdv #footermainPan,
body.gdv #enbas,
body.gdv #menuPan,
body.gdv .solidblockmenu,
body.gdv .ddsubmenustyle { display: none !important; }


/* --- conteneurs de module ---------------------------------------------- */

.gu-container {
   width: 100%;
   max-width: 1600px;
   min-width: 0;
   margin: 0 auto var(--isl-s5);
   padding: var(--isl-s5);
   background: var(--isl-surface);
   border: 1px solid var(--isl-border);
   border-radius: var(--isl-r-lg);
   box-shadow: var(--isl-sh-1);
   font-family: var(--isl-font-ui);
   color: var(--isl-fg);
}

/* L'en-tete d'ecran. Il n'y en a plus qu'un : isl_entete(). La classe
   .gu-title, qui faisait la meme chose en moins, a disparu avec les vingt
   ecrans qui la portaient, et l'ancien titre centre en gras avec ses trois
   <br> vides avec les vingt-neuf autres.

   Le petit trait d'accent etait la seule marque de la maison dans l'ancien
   habillage. On le garde, pose sur le filet de l'en-tete d'isl-ui. */
body.gdv .isl-pagehead { position: relative; }
body.gdv .isl-pagehead::after {
   content: "";
   position: absolute; left: 0; bottom: -1px;
   width: 46px; height: 2px;
   background: var(--isl-accent);
   border-radius: var(--isl-r-full);
}

.gu-card {
   padding: var(--isl-s4);
   margin-bottom: var(--isl-s4);
   background: var(--isl-surface-2);
   border: 1px solid var(--isl-border);
   border-radius: var(--isl-r);
}
.gu-card:last-child { margin-bottom: 0; }
.gu-card-title {
   margin: 0 0 var(--isl-s3);
   font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
   color: var(--isl-subtle);
   text-align: left;
}

.gu-actions, .gu-form-actions {
   display: flex; gap: 10px; flex-wrap: wrap;
   justify-content: center;
}
.gu-form-actions { margin-top: var(--isl-s4); }


/* --- boutons ------------------------------------------------------------ */
/* Une seule definition de bouton pour toute l'application : .gu-btn, les
   <input type="submit"> des formulaires generes, et .isl-btn d'isl-ui
   doivent se ressembler au pixel, sinon deux ecrans cote a cote n'ont
   pas l'air du meme logiciel. */

/* Les mesures du manifeste, comme .isl-btn : 14 px, 9/17, rayon --isl-r.
   .gu-btn sert surtout sur des <a> - un lien rendu en bouton - et ceux-la
   ne sont pas atteints par la regle des <button>. Sans cet alignement, un
   "Modifier" en lien sortait 5 px plus court que le "Enregistrer" d'a cote. */
.gu-btn {
   display: inline-flex; align-items: center; justify-content: center; gap: 7px;
   padding: 9px 17px;
   font: inherit; font-size: 14px; font-weight: 600;
   line-height: 1.4;
   color: var(--isl-fg);
   background: var(--isl-surface);
   border: 1px solid var(--isl-border-strong);
   border-radius: var(--isl-r);
   text-decoration: none; text-align: center;
   cursor: pointer;
   transition: background var(--isl-t-fast), border-color var(--isl-t-fast),
               color var(--isl-t-fast), box-shadow var(--isl-t-fast), transform var(--isl-t-fast);
}
.gu-btn:hover { background: var(--isl-surface-2); border-color: var(--isl-fg); color: var(--isl-fg); transform: translateY(-1px); }
.gu-btn:active { transform: none; }
.gu-btn:disabled, .gu-btn.is-off { opacity: .45; cursor: not-allowed; transform: none; }

.gu-btn-primary {
   background: var(--isl-accent); border-color: var(--isl-accent); color: var(--isl-on-accent);
}
.gu-btn-primary:hover {
   background: var(--isl-accent-hover); border-color: var(--isl-accent-hover);
   color: var(--isl-on-accent); box-shadow: var(--isl-sh-1);
}
.gu-btn-secondary {
   background: var(--isl-surface-2); border-color: var(--isl-border-strong); color: var(--isl-muted);
}
.gu-btn-secondary:hover { background: var(--isl-surface-3); color: var(--isl-fg); }
.gu-btn-danger {
   background: var(--isl-danger); border-color: var(--isl-danger); color: var(--isl-on-accent);
}
/* Un rouge qu'on eclaircit vire au rose et perd son contraste avec le texte
   blanc. isl-ui fonce le sien au survol (.isl-btn.danger) : on fait pareil,
   sinon deux boutons "Supprimer" cote a cote ne reagissent pas du meme geste.

   Le fond est REPOSE ici, et ce n'est pas une redite de .gu-btn-danger.
   L'etat de survol est un etat a part entiere : .gu-btn:hover y pose
   background: var(--isl-surface-2), et il a la meme specificite (0,2,0)
   que cette regle-ci - donc il l'emporte sur le rouge de .gu-btn-danger,
   qui n'en vaut que (0,1,0). Sans cette ligne, "Supprimer" virait au gris
   clair sous la souris en gardant son texte blanc : le libelle
   disparaissait. Meme chose pour .gu-btn-primary et -secondary, qui
   reposent tous les deux leur fond au survol. */
.gu-btn-danger:hover {
   background: var(--isl-danger);
   filter: brightness(.92); color: var(--isl-on-accent);
   border-color: var(--isl-danger); box-shadow: var(--isl-sh-1);
}

.gu-new {
   display: inline-flex; align-items: center; gap: 6px;
   padding: 9px 17px;
   font-size: 14px; line-height: 1.4; font-weight: 600;
   background: var(--isl-success); color: var(--isl-on-accent) !important;
   border: 1px solid var(--isl-success); border-radius: var(--isl-r);
   text-decoration: none; cursor: pointer;
   transition: filter var(--isl-t-fast), transform var(--isl-t-fast);
}
.gu-new:hover { filter: brightness(.92); transform: translateY(-1px); }

.gu-ico {
   display: inline-flex; align-items: center; justify-content: center;
   width: 30px; height: 30px;
   border: 1px solid var(--isl-border);
   border-radius: var(--isl-r-sm);
   background: var(--isl-surface);
   color: var(--isl-accent-text);
   font-size: 13px; line-height: 1;
   text-decoration: none; cursor: pointer;
   transition: background var(--isl-t-fast), color var(--isl-t-fast),
               border-color var(--isl-t-fast), transform var(--isl-t-fast);
}
/* Le survol d'un bouton d'icone reste doux. Rempli d'accent plein, il entrait
   en collision avec le survol de ligne des listings, qui pose deja
   --isl-accent-soft sous lui : deux bleus l'un sur l'autre, dont un si dense
   qu'il avalait la fleche. Le cadre et le texte d'accent suffisent a dire
   "c'est cliquable", et tiennent sur une ligne survolee comme sur une autre. */
.gu-ico:hover {
   background: var(--isl-accent-soft); border-color: var(--isl-accent-border);
   color: var(--isl-accent-text); transform: translateY(-1px);
}
.gu-ico.is-off, .gu-ico:disabled { opacity: .25; pointer-events: none; }

/* Un bouton d'icone qui detruit porte le rouge, et seulement lui. La
   gestion des menus en a besoin : "monter", "descendre" et "modifier" se
   rattrapent, "supprimer" non. */
body.gdv .gu-ico.is-danger { color: var(--isl-danger); }
body.gdv .gu-ico.is-danger:hover {
   background: var(--isl-danger-soft); border-color: var(--isl-danger);
   color: var(--isl-danger);
}
/* Rendu en <span> dans les lignes de tableau, le bouton d'icone doit garder
   sa boite : la regle generale des <span> ne lui donne rien. */
body.gdv span.gu-ico { display: inline-flex; }
body.gdv .gu-ico svg { width: 15px; height: 15px; }


/* --- champs de saisie, partout ------------------------------------------ */
/* Les modules ecrivent des <input> nus. On les habille au niveau du
   document plutot que dans chaque ecran : c'est la seule facon de reprendre
   quatre-vingt-dix-huit modules sans les rouvrir un par un. */

/* Les mesures sont celles du manifeste, pas les notres : 14 px, 9/11 de
   remplissage, le rayon --isl-r. C'est ce qu'ecrit .isl-input dans
   dist/isl-ui.css, et c'est ce qui donne a tous les controles - champ,
   liste, date, bouton - exactement la meme hauteur, 40 px.

   Avant, cette regle posait 13 px et 7/10 : le champ nu faisait 35,5 px, le
   declencheur de liste 32,3 px et le champ date 34,2 px. Trois hauteurs sur
   la meme ligne de formulaire, d'ou l'impression d'espaces de travers. */
body.gdv input[type="text"],
body.gdv input[type="password"],
body.gdv input[type="search"],
body.gdv input[type="email"],
body.gdv input[type="tel"],
body.gdv input[type="number"],
body.gdv input[type="date"],
body.gdv input[type="time"],
body.gdv input[type="file"],
body.gdv select,
body.gdv textarea {
   font: inherit;
   font-size: 14px;
   line-height: 1.4;
   color: var(--isl-fg);
   background: var(--isl-surface);
   border: 1px solid var(--isl-border-strong);
   border-radius: var(--isl-r);
   padding: 9px 11px;
   max-width: 100%;
   transition: border-color var(--isl-t-fast), box-shadow var(--isl-t-fast), background var(--isl-t-fast);
}
body.gdv input:hover:not(:disabled):not([readonly]),
body.gdv select:hover:not(:disabled),
body.gdv textarea:hover:not(:disabled) { border-color: var(--isl-accent-border); }
body.gdv textarea { line-height: 1.45; min-height: 78px; }
body.gdv select { padding-right: 30px; cursor: pointer; }

/* Dans une ligne de document - une facture, un inventaire, un ticket - le
   champ est une cellule parmi trente. La mesure du formulaire y ferait des
   rangees de cinquante pixels. isl-ui a la meme idee avec .isl-btn.sm : on
   garde la grammaire, on resserre l'echelle. */
body.gdv .type1 td input, body.gdv .type1 td select,
body.gdv .type2 td input, body.gdv .type2 td select,
body.gdv .matable td input, body.gdv .matable td select,
body.gdv .table_theme td input, body.gdv .table_theme td select,
body.gdv .tableau_lst_arts td input, body.gdv .tableau_lst_arts td select,
body.gdv .gu-history-table td input, body.gdv .gu-history-table td select {
   font-size: var(--isl-fs-sm);
   padding: 5px 8px;
   border-radius: var(--isl-r-sm);
}

body.gdv input[type="text"]:focus,
body.gdv input[type="password"]:focus,
body.gdv input[type="search"]:focus,
body.gdv input[type="email"]:focus,
body.gdv input[type="tel"]:focus,
body.gdv input[type="number"]:focus,
body.gdv select:focus,
body.gdv textarea:focus {
   outline: none;
   border-color: var(--isl-accent);
   box-shadow: 0 0 0 3px var(--isl-ring);
}

body.gdv input[readonly],
body.gdv textarea[readonly] {
   background: var(--isl-surface-2);
   color: var(--isl-muted);
   border-style: dashed;
}
body.gdv input:disabled,
body.gdv select:disabled,
body.gdv textarea:disabled { opacity: .55; cursor: not-allowed; }

body.gdv input::placeholder, body.gdv textarea::placeholder { color: var(--isl-subtle); }

/* La largeur d'un champ texte suit sa valeur (js/gdv-app.js pose "Nch" en
   style inline), plafonnee au maxlength. Le reset general met tout le monde
   en border-box : le remplissage (9/11 ici, 5/8 dans une ligne de document)
   mangerait alors les N caracteres au lieu de les entourer, et le texte
   deborderait pour un petit N. content-box rend le "Nch" pose par le script
   exact quel que soit le contexte, sans recalculer un plafond en pixels par
   remplissage. */
body.gdv input[type="text"].gdv-lg-auto {
   box-sizing: content-box;
   min-width: 0;
   max-width: 100%;
}

/* Cases et boutons radio : la taille par defaut d'un navigateur est
   trop petite pour un doigt sur une tablette de comptoir. */
body.gdv input[type="checkbox"],
body.gdv input[type="radio"] {
   width: 16px; height: 16px;
   accent-color: var(--isl-accent);
   vertical-align: -3px;
   cursor: pointer;
}

/* Les boutons de formulaire generes : meme grammaire que .gu-btn.

   line-height et white-space comptent autant que la couleur. Plusieurs
   ecrans - la caisse en tete - fixent la largeur et la hauteur de leurs
   boutons en pixels, valeurs calees sur l'Arial 11 px d'autrefois. Avec
   la nouvelle police, "EN COMPTE" ou "MULTI-REG" sortaient de leur
   cadre. On autorise donc le retour a la ligne et on centre le contenu :
   un bouton trop etroit grandit au lieu de deborder. */
/* LE :not() N'EST PAS DECORATIF.

   Sans lui, cette regle atteint aussi les <button> que rend isl-ui : le
   declencheur d'une liste deroulante (.isl-ctl) est un <button>. Elle vaut
   (0,1,2) et bat .isl-ctl (0,1,0), donc elle lui repeignait sa taille -
   13 px et 8/15 au lieu des 14 px et 9/11 du manifeste. Le declencheur
   sortait 2 px plus court que le champ date d'a cote, sur la meme ligne.

   C'est le meme piege que body.gdv a:visited sur la couleur. La regle
   generale doit dire explicitement ce qu'elle ne vise pas.

   Le :where() autour des :not() n'est pas cosmetique non plus : un :not()
   compte la specificite de son argument. Les trois d'affilee faisaient
   passer la regle a (0,4,2), au-dessus de body.gdv .gdv-side-search button
   (0,2,2) - et le bouton de la palette, dans la colonne, repassait a 14 px
   et se cassait sur deux lignes. :where() remet le tout a zero : la regle
   vaut exactement ce qu'elle valait, elle vise juste moins de monde.

   .gu-btn est exclu pour la meme raison, et c'est le cas le plus visible.
   Un <button class="gu-btn gu-btn-primary"> - le "Enregistrer" des gammes
   et des robes, le "Calculer" de l'inventaire - se faisait reprendre son
   fond par cette regle (0,1,2 contre 0,1,0), mais gardait la couleur de
   texte de .gu-btn-primary:hover (0,2,0 contre 0,1,2) des qu'on le
   survolait : du blanc sur un fond clair, le libelle disparaissait sous
   la souris. Les <input type="submit"> n'etaient pas touches - ils ont
   leur propre regle d'accent plus bas. Les <input type="button"> portaient
   exactement le meme defaut - "Imprimer", "Exporter", "Supprimer" de la
   recherche avancee - ils sont exclus de la meme facon. */
body.gdv input[type="submit"],
body.gdv input[type="button"]:where(:not([class*="gu-btn"])),
body.gdv input[type="reset"]:where(:not([class*="gu-btn"])),
body.gdv button:where(:not([class*="isl-"]):not([class*="gdv-"]):not([class*="ui-"]):not([class*="gu-btn"])) {
   font: inherit;
   font-size: 14px;
   font-weight: 600;
   line-height: 1.4;
   white-space: normal;
   overflow-wrap: break-word;
   padding: 9px 17px;
   color: var(--isl-fg);
   background: var(--isl-surface);
   border: 1px solid var(--isl-border-strong);
   border-radius: var(--isl-r);
   cursor: pointer;
   transition: background var(--isl-t-fast), border-color var(--isl-t-fast),
               color var(--isl-t-fast), transform var(--isl-t-fast);
}
body.gdv input[type="submit"]:hover,
body.gdv input[type="button"]:where(:not([class*="gu-btn"])):hover,
body.gdv input[type="reset"]:where(:not([class*="gu-btn"])):hover,
body.gdv button:where(:not([class*="isl-"]):not([class*="gdv-"]):not([class*="ui-"]):not([class*="gu-btn"])):hover {
   background: var(--isl-surface-2); border-color: var(--isl-fg); transform: translateY(-1px);
}

/* Meme resserrement que les champs dans une ligne de document. */
body.gdv .type1 td input[type="button"], body.gdv .type1 td input[type="submit"],
body.gdv .type2 td input[type="button"], body.gdv .type2 td input[type="submit"],
body.gdv .matable td input[type="button"], body.gdv .matable td input[type="submit"],
body.gdv .table_theme td input[type="button"], body.gdv .table_theme td input[type="submit"],
body.gdv .tableau_lst_arts td input[type="button"], body.gdv .tableau_lst_arts td input[type="submit"] {
   font-size: var(--isl-fs-sm);
   padding: 5px 11px;
   border-radius: var(--isl-r-sm);
}

/* "Enregistrer", "Valider", "Rechercher" font avancer l'ecran : ce sont
   les seuls a porter l'accent. Le reste reste en contour, sinon plus rien
   ne ressort. */
body.gdv input[type="submit"] {
   background: var(--isl-accent); border-color: var(--isl-accent); color: var(--isl-on-accent);
}
body.gdv input[type="submit"]:hover {
   background: var(--isl-accent-hover); border-color: var(--isl-accent-hover); color: var(--isl-on-accent);
}
body.gdv input[type="submit"][value="Supprimer"],
body.gdv input[type="submit"][value="Annuler"],
body.gdv input[name="action"][value="Supprimer"] {
   background: var(--isl-danger); border-color: var(--isl-danger); color: var(--isl-on-accent);
}
body.gdv input[type="submit"][value="Supprimer"]:hover,
body.gdv input[type="submit"][value="Annuler"]:hover,
body.gdv input[name="action"][value="Supprimer"]:hover { filter: brightness(1.08); }

/* La coque et la palette echappent a la regle ci-dessus : leurs boutons
   sont des elements de coque, pas des actions de formulaire. Ceux de la
   colonne et de la barre du haut se defendent tout seuls - leurs regles
   portent maintenant le prefixe body.gdv, sans quoi la regle generale
   ci-dessus, plus specifique, leur repeignait un fond clair au milieu
   d'une colonne sombre. */
body.gdv .isl-btn,
body.gdv .isl-modal button,
body.gdv .isl-seg button,
body.gdv .isl-chip,
body.gdv .isl-tabs button,
body.gdv .isl-ctl,
body.gdv .isl-pagin button {
   font-weight: inherit;
   transform: none;
}
body.gdv .gdv-side button:hover,
body.gdv .gdv-top button:hover,
body.gdv .gdv-pal button:hover,
body.gdv .isl-btn:hover { transform: none; }

/* Le meme piege que la couleur, mais sur l'espacement : la regle generale
   body.gdv button pose padding: 8px 15px, et elle est plus specifique que
   .gdv-burger ou .gdv-haut, qui ne declarent pas de padding du tout. Une
   pastille de 34 px se retrouvait avec 2 px de contenu utile, et son icone
   de 18 px ecrasee a 2 px de large : le bouton "replier la navigation"
   n'affichait plus qu'un point. */
body.gdv .gdv-burger,
body.gdv .gdv-haut,
body.gdv .gdv-side-quit,
body.gdv .gdv-side-outil { padding: 0; }
body.gdv .gdv-burger svg,
body.gdv .gdv-haut svg { flex: none; }


/* --- tableaux ----------------------------------------------------------- */
/* Un ERP se lit dans ses tableaux. Ligne alternee, en-tete colle,
   survol franc : trois regles qui font gagner plus de temps qu'une
   refonte de couleur. */

body.gdv table { border-collapse: collapse; }

body.gdv .tableau_chps,
body.gdv .type1,
body.gdv .type2,
body.gdv .table_theme,
body.gdv .matable,
body.gdv .gu-history-table {
   width: auto;
   background: var(--isl-surface);
   color: var(--isl-fg);
   font-size: var(--isl-fs-data);
   border-collapse: collapse;
   border-radius: var(--isl-r);
}

/* Pas de overflow: hidden ici, et c'est la correction la plus importante de
   la feuille. Il n'etait la que pour rogner les coins arrondis, mais un
   element qui rogne son debordement devient un CONTEXTE DE DEFILEMENT, et un
   enfant en position: sticky se cale alors sur le haut de CETTE boite, pas
   sur celui de la page. L'en-tete de colonnes, cale a var(--gdv-top-h),
   descendait donc de soixante-deux pixels sous le haut de son propre
   tableau - c'est-a-dire par-dessus la premiere ligne - des le chargement,
   sans avoir a defiler, et pour toujours. Tous les listings de
   l'application etaient touches ; on le voyait surtout sur une facture, ou
   la premiere ligne est celle qu'on vient d'ajouter.
   Le meme piege avait deja ete releve deux fois : pour les tableaux en
   carte (plus bas, section 17) et pour le panier de la caisse
   (.gdv-pdv-lignes) - les deux fois contourne localement. Il est traite ici
   a la source, de la meme facon : les rayons sont poses sur les cellules
   d'angle. Meme rendu, rien n'est rogne, et le sticky retrouve la page.
   Les sections sont nommees explicitement : le DOM insere toujours un
   <tbody>, donc un tableau sans <thead> a bien sa premiere ligne dans
   > tbody:first-child > tr:first-child. */
body.gdv :is(.tableau_chps, .type1, .type2, .table_theme, .matable, .gu-history-table) > :is(thead, tbody, tfoot):first-child > tr:first-child > :first-child {
   border-top-left-radius: var(--isl-r);
}
body.gdv :is(.tableau_chps, .type1, .type2, .table_theme, .matable, .gu-history-table) > :is(thead, tbody, tfoot):first-child > tr:first-child > :last-child {
   border-top-right-radius: var(--isl-r);
}
body.gdv :is(.tableau_chps, .type1, .type2, .table_theme, .matable, .gu-history-table) > :is(thead, tbody, tfoot):last-child > tr:last-child > :first-child {
   border-bottom-left-radius: var(--isl-r);
}
body.gdv :is(.tableau_chps, .type1, .type2, .table_theme, .matable, .gu-history-table) > :is(thead, tbody, tfoot):last-child > tr:last-child > :last-child {
   border-bottom-right-radius: var(--isl-r);
}

body.gdv .type1 th,
body.gdv .type2 th,
body.gdv .table_theme th,
body.gdv .matable th,
body.gdv .gu-history-table th,
body.gdv .tableau_chps th {
   height: auto;
   padding: 9px 12px;
   font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
   color: var(--isl-subtle);
   background: var(--isl-surface-2);
   border: 0;
   border-bottom: 1px solid var(--isl-border);
   text-align: left;
   white-space: nowrap;
}

body.gdv .type1 td,
body.gdv .type2 td,
body.gdv .table_theme td,
body.gdv .matable td,
body.gdv .gu-history-table td {
   padding: 8px 12px;
   background: transparent;
   color: var(--isl-fg);
   border: 0;
   border-bottom: 1px solid var(--isl-border);
   vertical-align: middle;
}

body.gdv .type1 tr,
body.gdv .type2 tr,
body.gdv .table_theme tr,
body.gdv .matable tr,
body.gdv .gu-history-table tr { height: auto; background: transparent; }

body.gdv .type1 tbody tr:nth-child(even),
body.gdv .type2 tbody tr:nth-child(even),
body.gdv .table_theme tbody tr:nth-child(even),
body.gdv .matable tbody tr:nth-child(even),
body.gdv .gu-history-table tbody tr:nth-child(even) { background: var(--isl-surface-2); }

body.gdv .type1 tbody tr:hover,
body.gdv .type2 tbody tr:hover,
body.gdv .table_theme tbody tr:hover,
body.gdv .matable tbody tr:hover,
body.gdv .gu-history-table tbody tr:hover { background: var(--isl-accent-soft); }

body.gdv .gu-history-table { width: 100%; }
body.gdv .gu-history-table th { text-align: center; }
body.gdv .gu-history-table tr:last-child td { border-bottom: 0; }
body.gdv .gu-history-table a { color: var(--isl-accent-text); font-weight: 600; }


/* --- l'arbre des familles d'articles (g_groupes.php) -------------------- */
/* Cinq colonnes de largeurs tres inegales : un libelle qui s'etire, un
   compteur, et trois boutons de 30 px. Sans largeurs posees, le navigateur
   les repartissait a parts presque egales et les libelles d'en-tete, centres
   par la regle generale, flottaient loin au-dessus de leur contenu. */

body.gdv .gu-familles th.gu-c-lib,
body.gdv .gu-familles td.gu-c-lib { text-align: left; }

body.gdv .gu-familles th.gu-c-nb,
body.gdv .gu-familles td.gu-c-nb {
   text-align: right; width: 1%; white-space: nowrap;
   font-variant-numeric: tabular-nums;
}

body.gdv .gu-familles th.gu-c-act,
body.gdv .gu-familles td.gu-c-act {
   text-align: center; width: 1%; white-space: nowrap;
   padding-left: 4px; padding-right: 4px;
}

/* La profondeur se lit a l'arbre, pas a un numero de niveau ecrit quelque
   part. Chaque ligne porte le rail de ses ancetres et un coude sous son
   parent ; une famille sans sous-famille suivante ferme son rail.

   Les traits sont des bordures posees en absolu DANS la cellule, qui est
   passee en position: relative. Une cellule de tableau couvre toute la
   hauteur de sa ligne, remplissage compris : le rail d'une ligne rejoint
   donc exactement celui de la suivante, sans trou. Le vieux dessin
   "&nbsp;&nbsp;|__" ne se raccordait pas, changeait de largeur avec la
   police et ne se laissait pas retrecir sur un telephone. */

body.gdv .gu-familles td.gu-c-lib { position: relative; }

body.gdv .gu-familles .gu-br {
   position: absolute; top: 0; bottom: 0; width: 12px;
   pointer-events: none;
}
body.gdv .gu-familles .gu-br-0 { left: 21px; }
body.gdv .gu-familles .gu-br-1 { left: 41px; }
body.gdv .gu-familles .gu-br-2 { left: 61px; }

/* Rail d'ancetre : le trait traverse la ligne de part en part. */
body.gdv .gu-familles .gu-br.is-trait::before,
body.gdv .gu-familles .gu-br.is-coude::before {
   content: ""; position: absolute; left: 0; top: 0; bottom: 0;
   border-left: 1px solid var(--isl-border-strong);
}
/* Coude : le trait descend, puis part vers le libelle a mi-hauteur. */
body.gdv .gu-familles .gu-br.is-coude::after {
   content: ""; position: absolute; left: 0; top: 50%; width: 11px;
   border-top: 1px solid var(--isl-border-strong);
}
/* Derniere de sa fratrie : le rail s'arrete au coude au lieu de continuer
   vers une ligne qui n'existe pas. */
body.gdv .gu-familles .gu-br.is-coude.is-fin::before { bottom: 50%; }

/* Le retrait laisse une case de 20 px par niveau devant le libelle. */
body.gdv .gu-familles tr.gu-fam-p0 td.gu-c-lib { font-weight: 600; }
body.gdv .gu-familles tr.gu-fam-p1 td.gu-c-lib { padding-left: 32px; }
body.gdv .gu-familles tr.gu-fam-p2 td.gu-c-lib { padding-left: 52px; }
body.gdv .gu-familles tr.gu-fam-p3 td.gu-c-lib { padding-left: 72px; }

/* Le total est un pied de tableau : la graisse de l'en-tete, sans la
   majuscule qui en ferait un titre de colonne. */
body.gdv .gu-familles tfoot th {
   background: var(--isl-surface-2);
   border-top: 1px solid var(--isl-border-strong);
   border-bottom: 0;
   color: var(--isl-fg);
   font-size: 12px; text-transform: none; letter-spacing: 0;
}
body.gdv .gu-familles tfoot th.gu-c-nb { font-variant-numeric: tabular-nums; }

/* Sur un telephone la case tombe a 14 px : quatre niveaux tiennent encore
   dans la largeur, et l'arbre suit - rails et coudes se recalent dessus. */
@media (max-width: 760px) {
   body.gdv .gu-familles tr.gu-fam-p1 td.gu-c-lib { padding-left: 26px; }
   body.gdv .gu-familles tr.gu-fam-p2 td.gu-c-lib { padding-left: 40px; }
   body.gdv .gu-familles tr.gu-fam-p3 td.gu-c-lib { padding-left: 54px; }

   body.gdv .gu-familles .gu-br-0 { left: 19px; }
   body.gdv .gu-familles .gu-br-1 { left: 33px; }
   body.gdv .gu-familles .gu-br-2 { left: 47px; }
   body.gdv .gu-familles .gu-br.is-coude::after { width: 7px; }
}

/* La pagination de l'historique vit SOUS le tableau, pas dans une derniere
   ligne de tbody. Un en-tete collant n'est clampe que par son groupe de
   lignes : des que l'historique tenait dans moins d'un ecran, il descendait
   se poser sur les dernieres lignes et sur la pagination. Dehors, il ne
   peut plus l'atteindre. */
body.gdv .gu-histo-pages {
   display: flex;
   align-items: center;
   justify-content: flex-end;
   flex-wrap: wrap;
   gap: var(--isl-s3);
   margin-top: var(--isl-s3);
   font-size: var(--isl-fs-sm);
   color: var(--isl-subtle);
}
body.gdv .gu-histo-pages input[type="button"] {
   font-size: var(--isl-fs-sm);
   padding: 5px 11px;
   border-radius: var(--isl-r-sm);
}

/* Une table imbriquee dans une cellule n'est pas un tableau de donnees :
   elle sert a poser deux champs cote a cote. Elle n'herite donc ni du
   filet, ni du fond, ni de la ligne alternee. */
body.gdv .tableau_chps td table,
body.gdv .type1 td table,
body.gdv .type2 td table,
body.gdv .table_theme td table,
body.gdv .gu-history-table td table { background: transparent; font-size: inherit; }
body.gdv .tableau_chps td table th,
body.gdv .tableau_chps td table td,
body.gdv .type1 td table th, body.gdv .type1 td table td,
body.gdv .type2 td table th, body.gdv .type2 td table td,
body.gdv .table_theme td table th, body.gdv .table_theme td table td,
body.gdv .gu-history-table td table th, body.gdv .gu-history-table td table td {
   background: transparent;
   border: 0;
   padding: 2px 6px;
   text-transform: none; letter-spacing: 0; font-size: inherit;
   color: inherit;
   white-space: normal;
}
body.gdv .tableau_chps td table tbody tr:hover,
body.gdv .type2 td table tbody tr:hover,
body.gdv .table_theme td table tbody tr:hover,
body.gdv .gu-history-table td table tbody tr:hover { background: transparent; }
body.gdv .tableau_chps td table tbody tr:nth-child(even),
body.gdv .type2 td table tbody tr:nth-child(even),
body.gdv .table_theme td table tbody tr:nth-child(even),
body.gdv .gu-history-table td table tbody tr:nth-child(even) { background: transparent; }

/* L'en-tete colle vaut pour tout tableau long. Sans lui, la colonne
   "Montant" n'a plus de nom des la quinzieme ligne. */
body.gdv .type1 thead th,
body.gdv .type2 thead th,
body.gdv .table_theme thead th,
body.gdv .matable thead th,
body.gdv .gu-history-table thead th {
   position: sticky; top: var(--gdv-top-h, 62px); z-index: 2;
   box-shadow: inset 0 -1px 0 var(--isl-border);
}

/* Le filet de separation de colonnes, garde de l'ancien habillage. */
body.gdv .cols_left { border-left: 1px solid var(--isl-border); }


/* --- formulaires generes par tableau_chps() ----------------------------- */
/* Cette table est un formulaire, pas une grille de donnees. Elle se lit
   en paires libelle / champ, donc ni ligne alternee, ni survol. */

body.gdv .tableau_chps {
   margin: 0 auto;
   background: var(--isl-surface);
   border: 1px solid var(--isl-border);
   border-radius: var(--isl-r);
   font-size: var(--isl-fs-sm);
}
body.gdv .tableau_chps tr { background: transparent; }
body.gdv .tableau_chps tbody tr:nth-child(even) { background: transparent; }
body.gdv .tableau_chps tbody tr:hover { background: transparent; }

/* Le rythme vertical du formulaire. Le remplissage etait a 9 px, ce qui
   laissait DIX-HUIT pixels entre le bas d'un controle et le haut du
   suivant : neuf en bas de la premiere rangee, neuf en haut de la seconde.
   La recherche avancee - quarante-sept champs, vingt-quatre rangees - en
   faisait mille six cents de haut, et on en voyait huit a l'ecran.

   Six, c'est douze entre deux controles : exactement le gap des grilles de
   formulaire d'isl-ui (--isl-s3 dans dist/isl-ui.css). On ne resserre donc
   pas en dessous du manifeste, on s'y aligne enfin - et le controle, lui,
   ne bouge pas d'un pixel : il fait toujours ses 40 px. */
body.gdv .tableau_chps th,
body.gdv .tableau_chps td {
   background: transparent;
   border: 0;
   border-bottom: 1px solid var(--isl-border);
   padding: 6px 14px;
   vertical-align: middle;
}
body.gdv .tableau_chps tr:last-child th,
body.gdv .tableau_chps tr:last-child td { border-bottom: 0; }

body.gdv .tableau_chps th {
   text-align: right;
   font-size: var(--isl-fs-sm); font-weight: 500;
   letter-spacing: 0; text-transform: none;
   color: var(--isl-muted);
   white-space: nowrap;
}
body.gdv .tableau_chps th strong { font-weight: 500; }
body.gdv .tableau_chps td { text-align: left; }

body.gdv .tableau_chps td.vide {
   background: transparent;
   border-bottom: 0;
   padding: 3px 0;
}

/* Le titre de section, ecrit en "titre" par tableau_chps(). */
body.gdv .tableau_chps th[colspan]:not(.th_action) {
   text-align: left;
   background: var(--isl-surface-2);
   border-top: 1px solid var(--isl-border);
}
body.gdv .tableau_chps tr:first-child th[colspan]:not(.th_action) { border-top: 0; }
body.gdv .tableau_chps .titre_tab {
   display: inline-block;
   font-family: var(--isl-font-display);
   font-size: 11.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
   color: var(--isl-accent-text);
}

body.gdv .tableau_chps .th_action {
   text-align: center;
   background: var(--isl-surface-2);
   border-bottom: 0;
   border-top: 1px solid var(--isl-border);
   padding: 12px 14px;
}
body.gdv .tableau_chps .th_action input { margin: 0 4px; }

/* L'asterisque de champ obligatoire. */
body.gdv .tableau_chps span.rouge,
body.gdv span.rouge { color: var(--isl-danger); font-weight: 700; }


/* --- couleurs de sens heritees ------------------------------------------ */
/* Les modules ecrivent <font color="#FF0000"> et .text_rouge_gras. On ne
   les supprime pas : on les rebranche sur les jetons semantiques, pour
   qu'un solde debiteur reste rouge en mode sombre aussi. */

body.gdv font[color="#FF0000"],
body.gdv font[color="#ff0000"],
body.gdv font[color="red"],
body.gdv .text_rouge_gras,
body.gdv .solde_rouge,
body.gdv .cl_ckdo_nok { color: var(--isl-danger) !important; }

body.gdv .solde_rouge { text-align: right; font-weight: 700; }
body.gdv .text_rouge_gras, body.gdv .cl_ckdo_nok { font-weight: 700; }

body.gdv font[color="green"], body.gdv .cl_ckdo_ok { color: var(--isl-success) !important; font-weight: 700; }
body.gdv .text_bleu { color: var(--isl-accent-text); font-weight: 700; }

body.gdv .search_art_usual { background: var(--isl-success-soft) !important; }
body.gdv .search_art_title {
   background: var(--isl-surface-2) !important;
   color: var(--isl-subtle) !important;
   font-weight: 700;
}
body.gdv .search_art_det_stock { color: var(--isl-danger); }

body.gdv .popup { background: var(--isl-surface); }

/* Champs numeriques : a droite, en chasse fixe. */
body.gdv .input_num, body.gdv .chp_num { text-align: right; font-variant-numeric: tabular-nums; }
body.gdv .input_qte { text-align: center; }


/* --- font-awesome ------------------------------------------------------- */
/* Le pack reste charge : une quarantaine d'appels y renvoient encore. On
   ne lui impose qu'une couleur et un alignement. */
body.gdv .fa { color: inherit; vertical-align: -1px; }


/* ==========================================================================
   4. REPRISE DES GREFFONS jQuery
   jQuery UI et jscal2 apportent leur propre habillage de 2011. On le
   recouvre : une boite de dialogue grise au milieu d'un ecran reteinte
   annule tout le travail.
   ========================================================================== */

body.gdv .ui-widget,
body.gdv .ui-widget input,
body.gdv .ui-widget select,
body.gdv .ui-widget textarea,
body.gdv .ui-widget button { font-family: var(--isl-font-ui); font-size: var(--isl-fs-sm); }

body.gdv .ui-widget-overlay {
   background: rgba(0, 0, 0, .42) !important;
   opacity: 1 !important;
}
body.gdv .ui-dialog {
   background: var(--isl-surface) !important;
   border: 1px solid var(--isl-border) !important;
   border-radius: var(--isl-r-lg) !important;
   box-shadow: var(--isl-sh-3) !important;
   padding: 0 !important;
   overflow: hidden;
}
body.gdv .ui-dialog .ui-dialog-titlebar {
   background: var(--isl-surface-2) !important;
   border: 0 !important;
   border-bottom: 1px solid var(--isl-border) !important;
   border-radius: 0 !important;
   color: var(--isl-fg) !important;
   padding: 12px 16px !important;
   font-family: var(--isl-font-display); font-weight: 700;
}
body.gdv .ui-dialog .ui-dialog-content {
   background: var(--isl-surface) !important;
   color: var(--isl-fg) !important;
   padding: 18px 20px !important;
}
body.gdv .ui-dialog .ui-dialog-buttonpane {
   background: var(--isl-surface-2) !important;
   border: 0 !important;
   border-top: 1px solid var(--isl-border) !important;
   margin: 0 !important;
   padding: 12px 16px !important;
}
body.gdv .ui-dialog .ui-dialog-buttonpane .ui-button {
   background: var(--isl-surface) !important;
   border: 1px solid var(--isl-border-strong) !important;
   border-radius: var(--isl-r-sm) !important;
   color: var(--isl-fg) !important;
   font-weight: 600;
   padding: 7px 15px !important;
   margin: 0 0 0 8px !important;
}
body.gdv .ui-dialog .ui-dialog-buttonpane .ui-button:first-child {
   background: var(--isl-accent) !important;
   border-color: var(--isl-accent) !important;
   color: var(--isl-on-accent) !important;
}

body.gdv .ui-datepicker {
   background: var(--isl-surface) !important;
   border: 1px solid var(--isl-border) !important;
   border-radius: var(--isl-r) !important;
   box-shadow: var(--isl-sh-2) !important;
   padding: 8px !important;
   z-index: 150 !important;
}
body.gdv .ui-datepicker .ui-datepicker-header {
   background: transparent !important;
   border: 0 !important;
   color: var(--isl-fg) !important;
   font-weight: 700;
}

/* Les fleches de mois etaient des pastilles sombres decoupees dans la sprite
   d'icones de jQuery UI - rondes, grises, et de 2011. Elles sont redessinees
   au filet, dans la couleur du texte : meme boite et meme survol que les
   boutons d'icone du reste du logiciel. */
body.gdv .ui-datepicker .ui-datepicker-prev,
body.gdv .ui-datepicker .ui-datepicker-next {
   top: 6px !important;
   width: 26px !important; height: 26px !important;
   background: none !important;
   border: 1px solid transparent !important;
   border-radius: var(--isl-r-sm) !important;
   cursor: pointer;
}
body.gdv .ui-datepicker .ui-datepicker-prev { left: 6px !important; }
body.gdv .ui-datepicker .ui-datepicker-next { right: 6px !important; }
body.gdv .ui-datepicker .ui-datepicker-prev:hover,
body.gdv .ui-datepicker .ui-datepicker-next:hover {
   background: var(--isl-surface-2) !important;
   border-color: var(--isl-border) !important;
}
/* Le <span> portait l'image ; il porte maintenant deux filets en equerre,
   tournes d'un quart de tour. Le libelle part hors du cadre plutot qu'a
   display:none : un lecteur d'ecran doit continuer de lire "Prev". */
body.gdv .ui-datepicker .ui-datepicker-prev span,
body.gdv .ui-datepicker .ui-datepicker-next span {
   position: absolute !important;
   top: 50% !important; left: 50% !important;
   width: 8px !important; height: 8px !important;
   margin: -4px 0 0 0 !important;
   background: none !important;
   text-indent: -9999px; overflow: hidden;
   border: solid var(--isl-muted);
   border-width: 0 0 1.6px 1.6px;
}
body.gdv .ui-datepicker .ui-datepicker-prev span { transform: rotate(45deg); margin-left: -2px !important; }
body.gdv .ui-datepicker .ui-datepicker-next span { transform: rotate(-135deg); margin-left: -6px !important; }
body.gdv .ui-datepicker .ui-datepicker-prev:hover span,
body.gdv .ui-datepicker .ui-datepicker-next:hover span { border-color: var(--isl-accent-text); }
body.gdv .ui-datepicker td a, body.gdv .ui-datepicker td span {
   background: transparent !important;
   border: 0 !important;
   border-radius: var(--isl-r-sm) !important;
   color: var(--isl-fg) !important;
   text-align: center;
   padding: 5px !important;
}
body.gdv .ui-datepicker td a:hover { background: var(--isl-accent-soft) !important; }
body.gdv .ui-datepicker .ui-state-active,
body.gdv .ui-datepicker .ui-state-highlight {
   background: var(--isl-accent) !important;
   color: var(--isl-on-accent) !important;
}
body.gdv .ui-datepicker th { color: var(--isl-subtle) !important; font-size: 11px; }

/* Une liste de suggestions est posee en absolu sur <body> : sans hauteur
   maximale, huit cents resultats ajoutaient vingt mille pixels a la
   page. C'est ce qui permettait de defiler sous le pied de page, dans le
   vide. Les endpoints plafonnent deja a trente lignes (MAX_SUGGESTIONS),
   la feuille garantit le reste. */
body.gdv .ui-autocomplete, body.gdv .ui-menu {
   background: var(--isl-surface) !important;
   border: 1px solid var(--isl-border) !important;
   border-radius: var(--isl-r) !important;
   box-shadow: var(--isl-sh-2) !important;
   padding: 4px !important;
   z-index: 150 !important;
   max-height: 46vh;
   overflow-y: auto;
   overflow-x: hidden;
   overscroll-behavior: contain;
}
body.gdv .ui-autocomplete { max-width: min(96vw, 900px); }
body.gdv .ui-menu .ui-menu-item-wrapper {
   background: transparent !important;
   border: 0 !important;
   border-radius: var(--isl-r-sm) !important;
   color: var(--isl-fg) !important;
   padding: 6px 9px !important;
}
/* Un libelle d'article long revient a la ligne plutot que d'elargir la
   liste jusqu'a la sortir de l'ecran. */
body.gdv .ui-autocomplete .ui-menu-item-wrapper {
   white-space: normal;
   overflow-wrap: anywhere;
}
/* Le pied pose par gdv-app.js quand la liste est pleine. */
body.gdv .ui-autocomplete .gdv-ac-plus {
   list-style: none;
   margin: 4px -4px -4px;
   padding: 7px 11px;
   font-size: 11.5px; font-weight: 600;
   color: var(--isl-subtle);
   background: var(--isl-surface-2);
   border-top: 1px solid var(--isl-border);
   position: sticky; bottom: -4px;
}
body.gdv .ui-menu .ui-menu-item-wrapper.ui-state-active {
   background: var(--isl-accent-soft) !important;
   color: var(--isl-accent-text) !important;
}
/* Un article indisponible se marque au fond ET au trait : un poste sur
   douze ne distingue pas le rouge du reste. */
body.gdv .ui-menu .ui-menu-item-wrapper.ui-state-disabled {
   background: var(--isl-danger-soft) !important;
   color: var(--isl-danger) !important;
   font-weight: 700;
   text-decoration: line-through;
}

body.gdv .ui-tabs { border: 0 !important; background: transparent !important; padding: 0 !important; }
body.gdv .ui-tabs .ui-tabs-nav {
   background: transparent !important; border: 0 !important;
   border-bottom: 1px solid var(--isl-border) !important;
   border-radius: 0 !important; padding: 0 !important;
}
body.gdv .ui-tabs .ui-tabs-nav li {
   background: transparent !important; border: 0 !important;
   margin: 0 2px -1px 0 !important;
}
body.gdv .ui-tabs .ui-tabs-nav li a {
   color: var(--isl-subtle) !important;
   border-bottom: 2px solid transparent !important;
   padding: 9px 14px !important;
   font-weight: 600;
}
body.gdv .ui-tabs .ui-tabs-nav li.ui-tabs-active a {
   color: var(--isl-accent-text) !important;
   border-bottom-color: var(--isl-accent) !important;
}
body.gdv .ui-tabs .ui-tabs-panel { background: transparent !important; padding: var(--isl-s4) 0 !important; }

/* jscal2, le calendrier des champs "date" de tableau_chps(). */
body.gdv .DynarchCalendar,
.DynarchCalendar {
   background: var(--isl-surface) !important;
   border: 1px solid var(--isl-border) !important;
   border-radius: var(--isl-r) !important;
   box-shadow: var(--isl-sh-2) !important;
   font-family: var(--isl-font-ui) !important;
   color: var(--isl-fg) !important;
}
.DynarchCalendar-title, .DynarchCalendar-topBar, .DynarchCalendar-bottomBar {
   background: transparent !important;
   color: var(--isl-fg) !important;
   border-color: var(--isl-border) !important;
}
.DynarchCalendar-day { color: var(--isl-fg) !important; border-radius: var(--isl-r-sm) !important; }
.DynarchCalendar-day-othermonth { color: var(--isl-subtle) !important; opacity: .5; }
.DynarchCalendar-day-hover, .DynarchCalendar-hover { background: var(--isl-accent-soft) !important; }
.DynarchCalendar-day-today { font-weight: 700; color: var(--isl-accent-text) !important; }
.DynarchCalendar-day-selected {
   background: var(--isl-accent) !important;
   color: var(--isl-on-accent) !important;
}
.DynarchCalendar-dayNames > div { color: var(--isl-subtle) !important; font-size: 11px; }


/* ==========================================================================
   5. IMPRESSION
   L'ecran sert aussi de brouillon d'impression sur plusieurs etats. On
   retire la coque et on rend le fond au papier.
   ========================================================================== */

@media print {
   body.gdv .gdv-side,
   body.gdv .gdv-top,
   body.gdv .gdv-alertes,
   body.gdv .gdv-foot,
   body.gdv .gdv-haut,
   body.gdv .gdv-pal-back,
   body.gdv .gdv-env,
   .hide_imp,
   .a_cacher { display: none !important; }
   body.gdv { background: #fff; color: #000; }
   body.gdv .gdv-app { display: block; }
   body.gdv .gdv-main { padding: 0; animation: none; }
   .gu-container { box-shadow: none; border: 0; padding: 0; max-width: none; }
   body.gdv .type1 thead th, body.gdv .type2 thead th,
   body.gdv .table_theme thead th, body.gdv .gu-history-table thead th { position: static; }
   /* Les listings de tableau_chps collent eux aussi leur premiere ligne.
      Sur le papier, un en-tete collant se repose au milieu de la page. */
   body.gdv .tableau_chps.table_theme > tbody > tr:first-child > th,
   body.gdv .tableau_chps.matable > tbody > tr:first-child > th,
   body.gdv .tableau_chps.gu-history-table > tbody > tr:first-child > th,
   body.gdv .tableau_chps.tableau_lst_arts > tbody > tr:first-child > th { position: static; }
}


/* ==========================================================================
   6. PETITS ECRANS
   Les postes de comptoir sont en 1280 ; les tablettes de cave descendent
   a 800. En dessous, la colonne de navigation devient un tiroir.
   ========================================================================== */

/* --- un formulaire ne depasse jamais son panneau --------------------------
   Ces trois regles ne sont PAS dans un @media, et c'est le coeur de l'affaire.

   Ce qui manque de place a un formulaire, ce n'est pas la fenetre : c'est ce
   qu'il en reste une fois la colonne de navigation servie. Or elle prend 254
   px depliee et 62 repliee, et elle se replie sur un seuil de FENETRE. Une
   fenetre de 1128 px garde donc sa colonne entiere et n'offre que 890 px au
   contenu, quand une fenetre de 1050 - plus petite - en offre 990 avec son
   rail. Tout seuil de fenetre ecrit ici se tromperait de mesure, et se
   tromperait dans les deux sens.

   On ne mesure donc rien. Les deux premieres regles ne se declenchent que
   sous la contrainte : tant qu'il y a la place, la table se pose a sa
   largeur naturelle et les libelles ne reviennent pas a la ligne - un
   max-width qui ne mord pas ne coute rien, un white-space:normal sur une
   colonne dimensionnee au max-content non plus. A 1920 px, pas un pixel ne
   bouge. C'est la meme logique que le max-width de .ui-dialog plus bas : une
   boite plus large que ce qui la contient est un defaut a toutes les
   largeurs, seulement personne ne le rencontre sur un grand ecran.

   La fiche article est celle qui l'a revele - deux colonnes de champs, donc
   deux libelles et deux champs par rangee, plus de huit cents pixels. Sous
   contrainte elle retombe a six cent quinze : les champs tiennent leur
   plafond de 210 px, et les libelles se cassent sur leur plus long mot.
   -------------------------------------------------------------------------- */

/* Le plafond. Sans lui la table se pose a sa largeur naturelle et pousse la
   page - donc la barre du haut et le fil d'Ariane avec elle. */
body.gdv .gdv-chps-empile { max-width: 100%; }

/* Le nowrap des libelles est juste pour un en-tete de listing : une colonne
   ne se casse pas en deux. Il ne l'est pas pour "Fournisseur principal", qui
   se lit tres bien sur deux lignes en face de son champ. La regle ne vise que
   les tableaux que le generateur a reconnus comme des formulaires - c'est ce
   que dit .gdv-chps-empile, posee a toutes les largeurs par gdv-mobile.js. */
body.gdv .gdv-chps-empile > tbody > tr > th { white-space: normal; }

/* Et ce qui ne se resserre pas. Le detail des stocks rend une colonne par
   depot, chacune avec un champ de 80 px : passe cinq depots, aucun plafond ne
   l'y fera tenir. gdv-mobile.js ne l'enrobera jamais - enrobable() refuse
   tout tableau dont un ancetre est un <table>, et celui-ci vit dans une
   cellule du formulaire. Il porte donc son plafond lui-meme. */
body.gdv .gdv-chps-empile > tbody > tr > td > table,
body.gdv .gdv-chps-empile > tbody > tr > td > div > table { max-width: 100%; }


@media (max-width: 1100px) {
   body.gdv .gdv-side { --gdv-side-w: 62px; }
   body.gdv .gdv-side .gdv-nav-lib,
   body.gdv .gdv-side .gdv-nav-caret,
   body.gdv .gdv-side .gdv-side-search,
   body.gdv .gdv-side .gdv-side-foot-txt,
   body.gdv .gdv-side .gdv-brand-txt { display: none; }
   body.gdv .gdv-side .gdv-nav-top { justify-content: center; padding-left: 0; padding-right: 0; }
   body.gdv .gdv-side .gdv-nav-grp .gdv-nav-sub { display: none !important; }
   body.gdv .gdv-side .gdv-brand { justify-content: center; padding-left: 0; padding-right: 0; }
   /* Sur cette largeur, la colonne repliee ne peut plus servir : le
      tiroir prend le relais et la deplie par-dessus le contenu. */
   html.is-drawer body.gdv .gdv-side {
      --gdv-side-w: 254px;
      position: fixed; left: 0; top: 0; bottom: 0;
      box-shadow: var(--isl-sh-3);
   }
   html.is-drawer body.gdv .gdv-side .gdv-nav-lib,
   html.is-drawer body.gdv .gdv-side .gdv-nav-caret,
   html.is-drawer body.gdv .gdv-side .gdv-side-search,
   html.is-drawer body.gdv .gdv-side .gdv-side-foot-txt,
   html.is-drawer body.gdv .gdv-side .gdv-brand-txt { display: block; }
   html.is-drawer body.gdv .gdv-side .gdv-side-search { display: block; }
   html.is-drawer body.gdv .gdv-side .gdv-nav-lib { display: block; }
   html.is-drawer body.gdv .gdv-side .gdv-nav-caret { display: inline-flex; }
   html.is-drawer body.gdv .gdv-side .gdv-nav-top { justify-content: flex-start; padding-left: 10px; padding-right: 10px; }
   html.is-drawer body.gdv .gdv-side .gdv-nav-grp.is-open .gdv-nav-sub { display: block !important; }
   html.is-drawer body.gdv .gdv-side .gdv-brand { justify-content: flex-start; padding-left: 16px; padding-right: 16px; }
   html.is-drawer body.gdv .gdv-voile {
      position: fixed; inset: 0; z-index: 39;
      background: rgba(0, 0, 0, .4);
   }
}

@media (max-width: 760px) {
   body.gdv .gdv-top, body.gdv .gdv-alertes, body.gdv .gdv-main, body.gdv .gdv-foot { padding-left: var(--isl-s4); padding-right: var(--isl-s4); }
   body.gdv .gdv-horloge { display: none; }
   .gu-container { padding: var(--isl-s4); border-radius: var(--isl-r); }
   /* Un tableau large ne doit jamais pousser la page : il defile dans sa
      propre boite. */
   body.gdv .gu-container { overflow-x: auto; }
}


/* ==========================================================================
   7. LARGEURS DE COLONNES HERITEES
   La liste d'articles qui tombe sous un champ de recherche est un
   tableau a colonnes fixes : sans ces largeurs, chaque frappe fait
   danser les colonnes sous le curseur. Reprises telles quelles de
   l'ancienne feuille, en jetons pour ce qui est couleur.
   ========================================================================== */

body.gdv .search_art_code { width: 45px; }
body.gdv .search_art_code_four { width: 70px; }
body.gdv .search_art_lib {
   width: 190px;
   overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
body.gdv .search_art_millesime { width: 45px; text-align: center; }
body.gdv .search_art_format { width: 55px; text-align: center; }
body.gdv .search_art_prix { width: 65px; text-align: right; }
body.gdv .search_art_title_stock { width: 50px; text-align: center; }
body.gdv .search_art_det_stock { width: 50px; text-align: center; }

/* Montants : toujours a droite, toujours en chasse fixe. */
body.gdv .cl_monnaie, body.gdv .cl_det_fact { text-align: right; font-variant-numeric: tabular-nums; }

/* Les boutons de tri des listes de factures. */
body.gdv .bton_tri_facts, body.gdv .bton_action, body.gdv .bton_supp { font-weight: 600; }

/* .a_cacher n'est PAS une classe d'element masque : elle veut dire "a cacher
   a l'impression". Sur "listing", elle porte les quatre boutons de tarif
   (Imprimer / Mail, particuliers et pro) et la colonne de cases "Excl." ;
   les masquer a l'ecran revient a supprimer la fonction. Elle n'est hors
   champ que sur le papier : voir le bloc @media print, et le <style> que
   print_table() ecrit dans sa fenetre. */
body.gdv .z_hide { display: none; }


/* ==========================================================================
   8. LISTES DEROULANTES CHERCHABLES
   Un <select> d'articles porte plusieurs centaines de lignes. Le
   composant d'isl-ui le double d'un declencheur cherchable ; le <select>
   reste en place, garde son name et part au POST, donc aucun code
   serveur n'a a changer.
   ========================================================================== */

/* Dans un formulaire en tableau, le declencheur ne prend pas toute la
   colonne : il se cale sur son contenu, avec un plancher lisible. Ce sont
   les SEULES mesures qu'on lui change - le remplissage, la taille et le
   rayon restent ceux du manifeste, sinon il ne fait plus la meme hauteur
   que le champ texte d'a cote. */
body.gdv .tableau_chps .isl-ctl:where(:not(.gdv-date)),
body.gdv .gu-card .isl-ctl:where(:not(.gdv-date)),
body.gdv .gu-container .isl-ctl:where(:not(.gdv-date)) {
   width: auto;
   min-width: 210px;
   max-width: 100%;
   display: inline-flex;
}
/* Une date n'a pas de largeur variable : elle fait dix caracteres, toujours.
   Le plancher de 210 px des listes lui ajoutait vingt-cinq pixels de vide
   entre le dernier chiffre et l'icone de calendrier. */
body.gdv .tableau_chps .gdv-date,
body.gdv .gu-card .gdv-date,
body.gdv .gu-container .gdv-date { min-width: 0; }

/* Corps des boites de dialogue de l'application ($.alert, $.confirm). */
body.gdv .gdv-dlg-corps {
   font-size: var(--isl-fs-base);
   line-height: 1.5;
   color: var(--isl-fg);
   max-height: 58vh;
   overflow-y: auto;
}


/* ==========================================================================
   9. CHAMPS DE tableau_chps()
   Les classes que pose le generateur de formulaires. Elles decrivent des
   roles - un libelle, une zone de champ, une note sous le champ - pas des
   apparences : le jour ou le generateur change de balisage, c'est ici
   qu'on suit.
   ========================================================================== */

body.gdv .gdv-chp-lib {
   display: inline-block;
   cursor: pointer;
   font-weight: 500;
   color: var(--isl-muted);
}
body.gdv .gdv-chp-lib:hover { color: var(--isl-fg); }

/* Un libelle de zone haute (liste de cases, textarea) se cale en haut du
   champ, pas au milieu de sa hauteur. */
body.gdv .tableau_chps th.gdv-chp-haut { vertical-align: top; padding-top: 10px; }

body.gdv .gdv-chp-zone { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* --- la largeur des champs ----------------------------------------------
   L'attribut size= des modules est une mesure de 2004 : il compte des
   caracteres d'Arial 11 px. A 14 px, un size="50" fait quatre cents pixels
   et un size="100" en fait sept cent soixante-dix. La colonne de droite du
   formulaire sortait deux fois plus large que celle de gauche, et la
   recherche avancee - quarante-sept champs - ne tenait plus dans la page.

   On ne touche pas aux size= des modules : quarante-sept champs valent 5,
   dix-sept valent 8, et ceux-la sont justes. On pose un plafond, et on le
   pose a 210 px, qui est le plancher du declencheur de liste : un champ
   texte long et une liste deroulante font desormais exactement la meme
   colonne. C'est cette egalite-la qu'on lit comme "range", bien plus qu'un
   alignement au pixel. */
body.gdv .tableau_chps input[type="text"],
body.gdv .tableau_chps input[type="password"],
body.gdv .tableau_chps input[type="email"],
body.gdv .tableau_chps input[type="tel"] { max-width: min(210px, 100%); }

/* Le <select> etait le seul champ que ce plafond ne tenait pas, et c'est
   lui qui faisait sauter la page au chargement.

   Un <select> natif se mesure sur sa PLUS LONGUE option. "Producteur /
   Marque", "Appellation", "Fournisseur" en portent des centaines, dont
   certaines de soixante caracteres : la recherche avancee s'ouvrait avec
   une vingtaine de listes de quatre a six cents pixels, donc une grille
   deux fois trop large, les libelles de la colonne de droite repousses
   loin sur le cote. Puis gdv-app.js equipait les listes, isl-ui masquait
   chaque <select> derriere un declencheur de 210 px, et tout revenait en
   place - par a-coups, une reflow par etape du demarrage.

   Ce n'etait donc pas un defaut de mise en page mais un defaut de
   CHRONOLOGIE : la page se peignait juste, mais avec le balisage d'avant
   l'habillage. Retarder la peinture serait pire (le CLAUDE.md le dit pour
   la coque). On donne donc au <select> nu la mesure exacte qu'aura son
   declencheur - 210 px, le meme plafond que les champs texte ci-dessus,
   le meme plancher que .isl-ctl en section 8 - pour que la premiere
   peinture soit deja la bonne.

   Ce qui est vise, c'est la liste DEROULANTE et elle seule. tableau_chps()
   ecrit toujours un size= - il vaut 1 pour une liste deroulante - donc le
   filtre porte sur la valeur, pas sur la presence de l'attribut : size="1"
   ou pas de size du tout. Un size= plus grand est un ascenseur, comme
   .gu-list-select et les listes a choix multiple : ceux-la gardent leur
   mesure.

   Les :not() passent par :where() pour ne rien peser - sans quoi cette
   regle battrait celle des lignes de document, juste en dessous. */
body.gdv .tableau_chps:where(:not(.table_theme):not(.matable):not(.gu-history-table):not(.tableau_lst_arts))
   select:where(:not([multiple]):not(.gu-select):not(.gu-list-select)):where([size="1"], :not([size])) {
   width: 210px;
   max-width: 100%;
}

/* Et dans une ligne de document, une liste reste a sa mesure : la cellule
   d'une facture n'a pas 210 px a donner. Ces regles portent une classe et
   un element de plus (0,2,3 contre 0,2,2), elles reprennent la main. */
body.gdv .type1 td select,
body.gdv .type2 td select,
body.gdv .matable td select,
body.gdv .table_theme td select,
body.gdv .tableau_lst_arts td select,
body.gdv .gu-history-table td select { width: auto; }

/* Une zone de texte n'est pas un champ : elle porte une phrase, pas une
   valeur, et elle garde donc sa propre mesure. Mais un cols="80" - onze des
   dix-huit textarea du logiciel - faisait six cent vingt-cinq pixels a lui
   seul, soit trois fois la colonne d'a cote. */
body.gdv .tableau_chps textarea { max-width: min(52ch, 100%); }

/* Le champ de recherche et le champ date portent deja leur largeur exacte,
   A L'INTERIEUR du cadre du composant : c'est le cadre qui fait la colonne,
   pas l'input. Le plafond ne les vise pas. */
body.gdv .tableau_chps .gdv-cherche input[type="text"],
body.gdv .tableau_chps .gdv-date input[type="text"] { max-width: none; }

/* Le champ de recherche prenait sa largeur de son input - width: 16em, soit
   224 px - et la boite sortait donc a 270 px : sur une rangee de trois
   controles, deux a 210 et un a 270. Dans un formulaire, c'est le CADRE qui
   fait la colonne, pas ce qu'il y a dedans. On remet la largeur a zero et on
   laisse le plancher de 210 px du declencheur decider, comme pour les
   listes. Hors tableau_chps le 16em reste : la regle ne porte pas la. */
body.gdv .tableau_chps .gdv-cherche input[type="text"] { width: 0; }

/* --- le "Libelle long" de la fiche article -------------------------------
   Deux cent cinquante caracteres dans un champ de deux cent dix pixels :
   on en lit trente-quatre. Le champ s'etale donc a la saisie, et revient
   a sa mesure des qu'on le quitte.

   Il s'etale de cent soixante-dix pixels, pas davantage : de quoi lire une
   soixantaine de caracteres, en mordant sur le blanc de la colonne et sur
   le libelle d'a cote, mais JAMAIS sur le champ d'a cote. Un champ qui se
   posait sur la moitie du formulaire donnait une fiche qui se deforme a
   chaque clic - on lisait plus le deplacement que le texte.

   Il s'etale HORS DU FLUX, et c'est tout l'interet. Un tableau se
   dimensionne colonne par colonne, jamais rangee par rangee : un champ
   elargi dans le flux elargirait la colonne pour TOUTES les rangees du
   formulaire, et la fiche sortirait de la page.

   Mais il en sort A DEMEURE, pas seulement au focus. Le sortir du flux au
   moment du clic, c'est vider la cellule de son contenu a cet instant-la :
   la colonne se rabattait alors sur le champ suivant le plus large, et
   TOUT le formulaire se resserrait d'un coup - les deux colonnes se
   rapprochaient sous le curseur. Le champ est donc absolu en permanence,
   et c'est la cellule qui porte la mesure du repos : 210 px, la meme que
   le plafond des champs texte et que le plancher du declencheur de liste,
   juste au-dessus. Elle ne varie plus jamais, focus ou pas, et le
   formulaire ne bouge plus d'un pixel. La hauteur, elle, tient par
   min-height : sans quoi la rangee se refermerait sur une cellule vide.

   La regle vise le formulaire de la fiche, pas le champ lib_art partout :
   celui de la saisie de facture fournisseur est un champ cherchable, avec
   sa loupe posee juste a sa droite, et il n'a rien a gagner a s'etaler
   dessus.

   Sous 760 px le formulaire s'empile et le champ fait deja la largeur de
   l'ecran : il n'a plus rien a etaler. */
@media (min-width: 761px) {
   body.gdv #e_articles #div_lib_art {
      position: relative;
      width: 210px;
      min-height: 40px;
   }
   body.gdv #e_articles #div_lib_art > input[type="text"] {
      position: absolute;
      left: 0;
      top: 0;
      width: 100%;
      max-width: none;
   }
   body.gdv #e_articles #div_lib_art > input[type="text"]:focus {
      z-index: 20;
      width: min(380px, 46vw);
      box-shadow: var(--isl-sh-2);
   }
}

/* --- les champs longs de la fiche client ---------------------------------
   Nom, contact, les quatre lignes d'adresse et l'email de commande web
   echappent au plafond de 210 px. Contrairement au libelle article, ils
   s'elargissent DANS le flux : la colonne grandit avec eux, et aucun champ
   ne peut plus passer sur le libelle de la colonne voisine. Le max-width en
   pourcent laisse le champ se resserrer si la carte manque de place. */
body.gdv #form_clients :is(#div_nom_client, #div_contact1_client, #div_adr1_client, #div_adr2_client, #div_adr3_client, #div_adr4_client, #div_email_cmd_web) > input[type="text"] {
   width: 340px;
   max-width: 100%;
}

body.gdv .gdv-chp-note {
   margin-top: 4px;
   font-size: var(--isl-fs-xs);
   font-style: italic; font-weight: 600;
   color: var(--isl-accent-text);
   text-align: left;
}
body.gdv .gdv-chp-note:empty { margin-top: 0; }

body.gdv .tableau_chps td.gdv-chp-case { text-align: center; }

/* --- champ date ---------------------------------------------------------
   Le composant d'isl-ui (.isl-date sur .isl-ctl), retaille pour la grille de
   saisie. .isl-ctl est prevu pleine largeur dans une grille de formulaire ;
   dans une cellule de tableau_chps, une date etalee sur toute la colonne
   laisse croire qu'on peut y ecrire autre chose qu'un jour.

   Les deux reprises input[type="text"] ne sont pas decoratives : la regle
   generale body.gdv input[type="text"] compte deux classes et l'emporte sur
   le .isl-dateinp d'isl-ui. Sans elles, le champ garde sa propre bordure et
   son propre fond A L'INTERIEUR du cadre du composant - une boite dans une
   boite. */
body.gdv .gdv-date {
   display: inline-flex;
   width: auto; min-width: 0;
   vertical-align: middle;
}
/* Les valeurs sont celles de .isl-dateinp dans dist/isl-ui.css : chasse fixe,
   13,5 px, chiffres tabulaires. On les repete parce que la regle generale
   body.gdv input[type="text"] compte deux classes et gagnerait sinon - le
   champ garderait sa propre bordure et son fond A L'INTERIEUR du cadre du
   composant, une boite dans une boite. */
body.gdv .gdv-date input[type="text"] {
   /* 10ch, pas 8.6em : en chasse fixe, ch vaut exactement la largeur d'un
      caractere, donc dix caracteres font dix ch - la place de jj/mm/aaaa,
      ni plus ni moins. Le em, lui, laissait vingt-cinq pixels de vide. */
   flex: 0 0 auto; width: 10ch;
   border: 0; border-radius: 0; background: none; padding: 0;
   font-family: var(--isl-font-mono); font-size: 13.5px;
   /* La date est en chasse fixe, donc un demi-point plus petite que le reste
      - sinon les chiffres sortent plus larges que le texte voisin. Sa boite
      de ligne est ramenee a celle d'un controle de 14 px, pour que le champ
      fasse exactement la meme hauteur que la liste et le champ texte poses
      sur la meme rangee. */
   line-height: calc(1.4 * 14 / 13.5);
   font-variant-numeric: tabular-nums;
}
body.gdv .gdv-date input[type="text"]:focus { box-shadow: none; outline: none; }
body.gdv .gdv-date .isl-ctl-ico { cursor: pointer; }

/* Verrouille : le meme filet pointille que les autres champs en lecture
   seule de l'application. L'etat se lit sans avoir a cliquer dedans. */
body.gdv .gdv-date.is-lecture {
   background: var(--isl-surface-2);
   border-style: dashed;
   cursor: default;
}
body.gdv .gdv-date input[readonly] {
   background: none; border: 0; padding: 0;
   color: var(--isl-muted);
}

/* DLUO d'une ligne de livraison, corrigee sur place dans la fiche article.
   Un lot a moins de 45 jours de sa limite se signale par la forme et par la
   couleur : le cadre passe a l'accent d'alerte et le chiffre s'epaissit. */
body.gdv .gdv-dluo.is-proche {
   border-color: var(--isl-danger);
   background: var(--isl-danger-soft, var(--isl-surface));
}
body.gdv .gdv-dluo.is-proche input[type="text"] {
   color: var(--isl-danger); font-weight: 700;
}

/* Les quatre champs de date de livraison qui filtrent dimanches et jours
   feries restent sur le datepicker de jQuery UI - isl-ui ne sait pas encore
   desactiver un jour. Ils ont au moins perdu leur declencheur en GIF : c'est
   maintenant un <button>, habille ici avec l'icone du systeme. */
body.gdv button.ui-datepicker-trigger {
   display: inline-flex; align-items: center; justify-content: center;
   width: 32px; height: 32px; padding: 0;
   vertical-align: middle;
   border: 1px solid var(--isl-border-strong);
   border-radius: var(--isl-r-sm);
   background: var(--isl-surface);
   color: var(--isl-subtle);
   cursor: pointer;
}
body.gdv button.ui-datepicker-trigger svg { width: 15px; height: 15px; }
body.gdv button.ui-datepicker-trigger:hover {
   border-color: var(--isl-accent); color: var(--isl-accent-text); transform: none;
}

/* Date + heure : deux controles, un champ cache. Voir gdv_datetime(). */
body.gdv .gdv-datetime { display: inline-flex; align-items: center; gap: 6px; }
body.gdv .gdv-date-h {
   width: 96px; flex: none;
   font-variant-numeric: tabular-nums;
}

/* Grille de cases et de boutons radio. Elle n'est pas un tableau de
   donnees : ni filet, ni ligne alternee, ni survol. */
body.gdv .gdv-chp-grille { width: 100%; background: transparent; }
body.gdv .gdv-chp-grille td {
   background: transparent; border: 0;
   padding: 4px 12px 4px 0;
   vertical-align: middle;
}
body.gdv .gdv-chp-grille tr:hover, body.gdv .gdv-chp-grille tr:nth-child(even) { background: transparent; }

/* La mesure de temps du serveur de developpement. Elle n'existe pas en
   production ; ici, elle doit se voir sans prendre la place d'un contenu. */
body.gdv .gdv-chrono {
   display: inline-flex; align-items: center; gap: 6px;
   margin: var(--isl-s5) 0 0;
   padding: 3px 9px;
   border: 1px dashed var(--isl-border);
   border-radius: var(--isl-r-full);
   font-size: 11px;
   font-variant-numeric: tabular-nums;
   color: var(--isl-subtle);
}
body.gdv .gdv-chrono svg { width: 12px; height: 12px; opacity: .7; }


/* Titre de SECTION, a l'interieur d'un ecran - gdv_section(). Un cran en
   dessous du titre d'ecran : meme famille, plus petit, sans le filet ni la
   marque d'accent, qui n'appartiennent qu'a l'en-tete de page. */
body.gdv .gdv-section {
   display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--isl-s3);
   justify-content: space-between;
   margin: var(--isl-s6) 0 var(--isl-s4);
}
body.gdv .gdv-section h2 {
   margin: 0;
   font-family: var(--isl-font-display);
   font-size: var(--isl-fs-xl); font-weight: 600; letter-spacing: -.02em;
   color: var(--isl-fg);
}
body.gdv .gdv-section-actions { display: flex; gap: 8px; flex-wrap: wrap; }


/* La cellule qui porte l'etat vide d'un tableau sans ligne. Elle ne prend ni
   filet, ni fond alterne, ni survol : ce n'est pas une donnee. */
body.gdv td.gdv-vide {
   background: transparent !important;
   border: 0;
   padding: 0;
}
body.gdv tr:hover td.gdv-vide { background: transparent; }
body.gdv td.gdv-vide .isl-empty { padding: var(--isl-s6) var(--isl-s4); }
body.gdv td.gdv-vide .isl-empty svg { width: 32px; height: 32px; color: var(--isl-border-strong); }


/* --- listes a choix multiples (widget jQuery UI) --------------------------
   Deux filtres de la recherche avancee - Familles, Fournisseur - acceptent
   plusieurs valeurs. Ils passent par le widget "multiselect" de jQuery UI,
   qui n'a pas d'equivalent dans isl-ui et qu'on garde donc tel quel.

   Sans reprise, il arrivait avec l'habillage de jQuery UI de 2011 : degrade
   gris sur le declencheur, bandeau ardoise en tete du panneau, coins carres.
   Au milieu d'une grille ou tous les autres controles sont identiques, ces
   deux-la sautaient aux yeux. On leur donne le cadre de .isl-ctl et le
   panneau de .isl-pop - ni plus, ni moins. */
body.gdv button.ui-multiselect {
   display: inline-flex; align-items: center; gap: 8px;
   /* Les memes mesures que .isl-ctl, et la meme largeur que les listes
      simples posees juste a cote : sans cela, "Familles" et "Fournisseur"
      s'etalaient sur toute la colonne au milieu d'une grille de listes
      calees sur leur contenu. */
   width: auto; min-width: 210px; max-width: 100%;
   padding: 9px 11px;
   font: inherit; font-size: 14px; line-height: 1.4; text-align: left;
   color: var(--isl-fg);
   background: var(--isl-surface);
   border: 1px solid var(--isl-border-strong);
   border-radius: var(--isl-r);
   box-shadow: none;
   cursor: pointer;
   transition: border-color var(--isl-t-fast), box-shadow var(--isl-t-fast);
}
body.gdv button.ui-multiselect:hover { border-color: var(--isl-accent-border); transform: none; }
body.gdv button.ui-multiselect.ui-state-active {
   border-color: var(--isl-accent); box-shadow: 0 0 0 3px var(--isl-ring);
}
body.gdv button.ui-multiselect span:not(.ui-icon) {
   flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Le chevron du widget est une icone-sprite de jQuery UI. On la remplace par
   le meme caret que les autres listes, dessine en bordures. */
/* order: le caret est le PREMIER enfant dans le balisage du widget ; il ne
   tenait a droite que par un float, que la disposition en flex annule.
   Son contenu est remplace par le chevron du systeme dans gdv-app.js - le
   meme que celui des listes simples, sinon deux listes voisines n'ont pas
   la meme fleche. */
body.gdv button.ui-multiselect span.ui-icon {
   float: none; flex: none; order: 2;
   width: 15px; height: 15px;
   background: none; text-indent: 0;
   color: var(--isl-subtle);
   margin-left: auto;
}
body.gdv button.ui-multiselect span.ui-icon svg { width: 15px; height: 15px; display: block; }
body.gdv button.ui-multiselect:hover span.ui-icon { color: var(--isl-accent-text); }

body.gdv .ui-multiselect-menu {
   padding: 5px;
   background: var(--isl-surface);
   border: 1px solid var(--isl-border);
   border-radius: var(--isl-r);
   box-shadow: var(--isl-sh-2);
   font-size: var(--isl-fs-sm);
}
body.gdv .ui-multiselect-header {
   display: flex; align-items: center; gap: 12px;
   margin: 0 0 4px;
   padding: 6px 8px;
   background: var(--isl-surface-2);
   border: 0; border-radius: var(--isl-r-sm);
   color: var(--isl-muted);
   font-size: 12px; font-weight: 600;
}
body.gdv .ui-multiselect-header ul { display: flex; gap: 12px; margin: 0; padding: 0; flex: 1 1 auto; }
body.gdv .ui-multiselect-header li { float: none; padding: 0; list-style: none; }
body.gdv .ui-multiselect-header a { color: var(--isl-accent-text); }
body.gdv .ui-multiselect-checkboxes { padding: 0; margin: 0; }
body.gdv .ui-multiselect-checkboxes label {
   display: flex; align-items: center; gap: 8px;
   padding: 6px 8px;
   border: 0; border-radius: var(--isl-r-sm);
   cursor: pointer;
}
body.gdv .ui-multiselect-checkboxes label:hover,
body.gdv .ui-multiselect-checkboxes label.ui-state-hover,
body.gdv .ui-multiselect-checkboxes label.ui-state-active {
   background: var(--isl-accent-soft); color: var(--isl-accent-text);
}
body.gdv .ui-multiselect-checkboxes label input { top: 0; }


/* --- la barre de touches de la caisse -------------------------------------
   Le bandeau du bas rappelle ce que font F1 a F12. Les touches qui ne
   servent a rien dans l'etat courant - pas de ticket ouvert, pas de ligne -
   etaient barrees par un text-decoration pose en ligne. Barre seul, cela se
   lisait comme un defaut d'affichage plutot que comme une indisponibilite.

   On eteint d'abord, on barre ensuite : c'est la couleur qui porte
   l'information, le trait ne fait que la confirmer. */
body.gdv .gdv-touches {
   width: 100%;
   border-collapse: collapse;
   background: var(--isl-surface-2);
   border-radius: var(--isl-r-sm);
   overflow: hidden;
   font-size: 11.5px;
}
body.gdv .gdv-touches td {
   padding: 5px 10px;
   border: 0;
   border-right: 1px solid var(--isl-border);
   color: var(--isl-fg);
   white-space: nowrap;
}
body.gdv .gdv-touches tr:hover, body.gdv .gdv-touches tr:nth-child(even) { background: transparent; }
body.gdv .gdv-touches td:last-child { border-right: 0; }
body.gdv .gdv-touches u {
   text-decoration: none;
   font-weight: 700;
   color: var(--isl-accent-text);
}
body.gdv .gdv-touche-off {
   color: var(--isl-subtle);
   text-decoration: line-through;
}
body.gdv .gdv-touche-off u { color: var(--isl-subtle); }


/* --- etats poses par le JavaScript des modules ---------------------------
   Une centaine d'appels ecrivaient leur couleur en dur :
   $(x).css("background-color", "#E6E6E6") pour un champ verrouille,
   $(x).css("color", "red") pour une alerte. Un style pose en ligne l'emporte
   sur la feuille et ne suit aucun jeton : en mode sombre, le champ verrouille
   devenait un rectangle gris clair avec du texte clair dessus.

   Ce sont maintenant des classes. Le module dit ce qu'il veut dire - ce champ
   est verrouille, ce chiffre est en alerte - et la feuille decide de quoi ca
   a l'air. */
body.gdv .gdv-verrouille,
body.gdv input.gdv-verrouille,
body.gdv select.gdv-verrouille,
body.gdv textarea.gdv-verrouille {
   background: var(--isl-surface-2);
   color: var(--isl-muted);
   border-style: dashed;
   cursor: default;
}

body.gdv .gdv-txt-bad  { color: var(--isl-danger); }
body.gdv .gdv-txt-ok   { color: var(--isl-success); }
body.gdv .gdv-txt-info { color: var(--isl-accent-text); }
/* Un etat ne se lit jamais a la seule couleur : un utilisateur sur douze ne
   distingue pas le rouge du vert. Quand la classe porte une valeur, elle la
   met aussi en gras. */
body.gdv .gdv-txt-bad, body.gdv .gdv-txt-ok { font-weight: 600; }


/* --- champ "text-search" et sa liste de suggestions ----------------------
   Le champ prend le meme cadre que les autres controles (.isl-ctl) et porte
   la loupe du systeme. La liste s'ouvre dessous, avec l'habillage du panneau
   d'isl-ui : meme rayon, meme ombre, meme filet. */
body.gdv .gdv-cherche {
   width: auto; min-width: 0;
   vertical-align: middle;
}
body.gdv .gdv-cherche input[type="text"] {
   flex: 1 1 auto; min-width: 0; width: 16em;
   border: 0; border-radius: 0; background: none; padding: 0;
   font-size: 14px; line-height: 1.4;
}
body.gdv .gdv-cherche input[type="text"]:focus { box-shadow: none; outline: none; }
body.gdv .gdv-cherche:focus-within {
   border-color: var(--isl-accent); box-shadow: 0 0 0 3px var(--isl-ring);
}

body.gdv .gdv-suggest {
   margin-top: 4px;
   max-height: 320px;
   overflow-y: auto;
   border-radius: var(--isl-r);
}
body.gdv .gdv-suggest.is-on {
   background: var(--isl-surface);
   border: 1px solid var(--isl-border);
   box-shadow: var(--isl-sh-2);
   padding: 4px;
}

/* Les endpoints rendent une suite de <a ...><br>. On en fait des lignes
   franches, avec un etat survol ET un etat clavier : .is-cur est pose par
   les fleches haut/bas, et doit se voir exactement comme le survol. */
body.gdv .gdv-suggest a {
   display: block;
   padding: 7px 10px;
   border-radius: var(--isl-r-sm);
   color: var(--isl-fg);
   text-decoration: none;
   font-size: var(--isl-fs-sm);
   white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
body.gdv .gdv-suggest a:hover,
body.gdv .gdv-suggest a.is-cur {
   background: var(--isl-accent-soft);
   color: var(--isl-accent-text);
}
body.gdv .gdv-suggest br { display: none; }

body.gdv .gdv-suggest table { width: 100%; font-size: var(--isl-fs-data); }
body.gdv .gdv-suggest td { padding: 5px 9px; border-bottom: 1px solid var(--isl-border); }
body.gdv .gdv-suggest tr:hover td { background: var(--isl-accent-soft); cursor: pointer; }

/* Liste de valeurs retirables (type "liste_supp"). */
body.gdv .gdv-liste-supp { list-style: none; margin: 0; padding: 0; display: grid; gap: 5px; }
body.gdv .gdv-liste-supp li {
   display: flex; align-items: center; gap: 10px;
   padding: 5px 6px 5px 11px;
   background: var(--isl-surface-2);
   border-radius: var(--isl-r-sm);
   font-size: var(--isl-fs-sm);
}
body.gdv .gdv-liste-supp li span { flex: 1 1 auto; }
body.gdv .gdv-ico-supp { width: 24px; height: 24px; color: var(--isl-danger); }
body.gdv .gdv-ico-supp:hover { background: var(--isl-danger); border-color: var(--isl-danger); color: var(--isl-on-accent); }

/* "Annuler" quitte un ecran, il ne detruit rien : il ne prend donc pas le
   rouge. C'est "Supprimer" qui le porte, et lui seul. */
body.gdv input[type="submit"][value="Annuler"],
body.gdv input[type="submit"][value="Retour"] {
   background: var(--isl-surface-2);
   border-color: var(--isl-border-strong);
   color: var(--isl-muted);
}
body.gdv input[type="submit"][value="Annuler"]:hover,
body.gdv input[type="submit"][value="Retour"]:hover {
   background: var(--isl-surface-3); color: var(--isl-fg); filter: none;
}


/* ==========================================================================
   10. ECRAN DE CHARTE GRAPHIQUE (modules/z_theme.php)
   Le seul ecran du logiciel qui ait le droit de montrer des couleurs
   litterales : ce sont ses donnees. Elles arrivent en attribut style,
   calculees par le moteur, jamais ecrites dans cette feuille.
   ========================================================================== */

body.gdv .gdv-th {
   display: grid;
   grid-template-columns: minmax(280px, 340px) minmax(0, 1fr);
   gap: var(--isl-s5);
   align-items: start;
}

/* Les reglages restent sous les yeux pendant qu'on fait defiler l'apercu :
   juger une couleur oblige a revenir au curseur dix fois. */
body.gdv .gdv-th-form { position: sticky; top: calc(var(--gdv-top-h, 62px) + var(--isl-s5)); display: grid; gap: var(--isl-s4); }

body.gdv .gdv-th-couleur { display: flex; align-items: center; gap: 10px; }
body.gdv .gdv-th-couleur input[type="color"] {
   width: 54px; height: 42px; flex: none; padding: 3px;
   background: var(--isl-surface);
   border: 1px solid var(--isl-border-strong);
   border-radius: var(--isl-r-sm);
   cursor: pointer;
}
body.gdv .gdv-th-couleur input[type="text"] {
   font-family: var(--isl-font-mono);
   text-transform: uppercase;
   letter-spacing: .04em;
}

body.gdv .gdv-th-aide {
   margin: 10px 0 0;
   font-size: var(--isl-fs-xs);
   line-height: 1.55;
   color: var(--isl-subtle);
}

body.gdv .gdv-th-depart { display: flex; flex-wrap: wrap; gap: 6px; margin-top: var(--isl-s4); }
body.gdv .gdv-th-puce {
   display: inline-flex; align-items: center; gap: 7px;
   padding: 5px 10px 5px 6px;
   font-size: 11.5px; font-weight: 500;
   color: var(--isl-muted);
   background: var(--isl-surface-2);
   border: 1px solid var(--isl-border);
   border-radius: var(--isl-r-full);
   cursor: pointer;
   transition: border-color var(--isl-t-fast), color var(--isl-t-fast), transform var(--isl-t-fast);
}
body.gdv .gdv-th-puce:hover { border-color: var(--isl-border-strong); color: var(--isl-fg); transform: translateY(-1px); }
body.gdv .gdv-th-puce i { width: 16px; height: 16px; border-radius: var(--isl-r-full); flex: none; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .16); }

body.gdv .gdv-th-curseur { display: flex; align-items: center; gap: var(--isl-s3); margin-top: var(--isl-s3); }
body.gdv .gdv-th-curseur input[type="range"] { flex: 1 1 auto; accent-color: var(--isl-accent); cursor: pointer; }
body.gdv .gdv-th-curseur output {
   flex: none; min-width: 54px; text-align: right;
   font-family: var(--isl-font-mono); font-size: var(--isl-fs-sm); font-weight: 600;
   color: var(--isl-accent-text);
}

/* Mode clair / sombre : trois etats exclusifs, donc trois touches cote a
   cote plutot qu'un interrupteur - un interrupteur ne sait dire que deux
   choses, et "Systeme" est la troisieme. Deux classes pour passer devant
   body.gdv button, qui vaut (0,1,1) et imposerait sinon son remplissage. */
body.gdv .gdv-th-mode { display: flex; gap: 6px; flex-wrap: wrap; }
body.gdv .gdv-th-modebt {
   display: inline-flex; align-items: center; gap: 7px;
   flex: 1 1 0; min-width: 104px; justify-content: center;
   padding: 9px 11px;
   font: inherit; font-size: var(--isl-fs-sm); font-weight: 600;
   color: var(--isl-muted);
   background: var(--isl-surface-2);
   border: 1px solid var(--isl-border);
   border-radius: var(--isl-r);
   cursor: pointer;
   transition: background var(--isl-t-fast), color var(--isl-t-fast), border-color var(--isl-t-fast), box-shadow var(--isl-t-fast);
}
body.gdv .gdv-th-modebt svg { width: 15px; height: 15px; flex: none; }
body.gdv .gdv-th-modebt:hover { color: var(--isl-fg); border-color: var(--isl-border-strong); }
body.gdv .gdv-th-modebt:focus-visible { outline: none; border-color: var(--isl-accent); box-shadow: 0 0 0 3px var(--isl-ring); }
body.gdv .gdv-th-modebt.is-on {
   color: var(--isl-accent-text);
   background: var(--isl-accent-soft);
   border-color: var(--isl-accent-border);
}

body.gdv .gdv-th-apercu { display: grid; gap: var(--isl-s5); min-width: 0; }

body.gdv .gdv-th-bloc {
   padding: var(--isl-s5);
   background: var(--isl-surface);
   border: 1px solid var(--isl-border);
   border-radius: var(--isl-r-lg);
}
body.gdv .gdv-th-bloc h3 {
   margin: 0;
   font-family: var(--isl-font-display);
   font-size: var(--isl-fs-xl); font-weight: 700; letter-spacing: -.025em;
}
body.gdv .gdv-th-sous { margin: 5px 0 var(--isl-s4); font-size: var(--isl-fs-sm); color: var(--isl-subtle); max-width: 62ch; }

/* Les rampes. Chaque pas montre sa couleur et son numero : c'est ce
   numero qu'on cite quand on discute d'un jeton. */
body.gdv .gdv-th-rampe { display: flex; gap: 3px; flex-wrap: wrap; margin-bottom: var(--isl-s3); }
body.gdv .gdv-th-pas { flex: 1 1 44px; min-width: 44px; text-align: center; }
body.gdv .gdv-th-pas i {
   display: block; height: 40px;
   border-radius: var(--isl-r-sm);
   box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .1);
}
body.gdv .gdv-th-rampe.gris .gdv-th-pas i { height: 26px; }
body.gdv .gdv-th-pas b {
   display: block; margin-top: 4px;
   font-family: var(--isl-font-mono); font-size: 10px; font-weight: 500;
   color: var(--isl-subtle);
}

body.gdv .gdv-th-ctest {
   display: grid;
   grid-template-columns: repeat(auto-fit, minmax(215px, 1fr));
   gap: 10px;
   margin-bottom: var(--isl-s4);
}
body.gdv .gdv-th-ctile {
   padding: var(--isl-s4);
   border-radius: var(--isl-r);
   box-shadow: inset 0 0 0 1px rgba(127, 127, 127, .22);
   display: flex; flex-direction: column; gap: var(--isl-s4);
   justify-content: space-between;
   min-height: 104px;
}
body.gdv .gdv-th-ctile p { margin: 0; font-size: var(--isl-fs-md); font-weight: 600; line-height: 1.3; }
body.gdv .gdv-th-cpied { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
body.gdv .gdv-th-clib { font-size: 10.5px; opacity: .85; }
body.gdv .gdv-th-cbadge {
   font-family: var(--isl-font-mono); font-size: 10.5px; font-weight: 600;
   padding: 2px 7px; border-radius: var(--isl-r-full);
   background: rgba(127, 127, 127, .26);
   white-space: nowrap;
}
/* L'echec ne se marque pas qu'a la couleur : on ne juge pas un test de
   contraste a une nuance. */
body.gdv .gdv-th-cbadge.fail { box-shadow: inset 0 0 0 1.5px currentColor; font-weight: 700; }

body.gdv .gdv-th-code {
   margin: 0;
   max-height: 300px; overflow: auto;
   padding: var(--isl-s4);
   background: var(--isl-surface-2);
   border: 1px solid var(--isl-border);
   border-radius: var(--isl-r);
   font-family: var(--isl-font-mono); font-size: 11.5px; line-height: 1.6;
   color: var(--isl-muted);
   white-space: pre;
}

@media (max-width: 1000px) {
   body.gdv .gdv-th { grid-template-columns: 1fr; }
   body.gdv .gdv-th-form { position: static; }
}


/* ==========================================================================
   11. ACCUEIL
   Trois blocs : ce qui attend, ce qu'on ouvre tous les jours, la maison.
   ========================================================================== */

body.gdv .gdv-ac-tuiles {
   display: grid;
   grid-template-columns: repeat(auto-fit, minmax(212px, 1fr));
   gap: var(--isl-s3);
   margin-bottom: var(--isl-s5);
}

body.gdv .gdv-ac-tuile {
   position: relative;
   display: flex; flex-direction: column; gap: 2px;
   padding: var(--isl-s4) var(--isl-s4) var(--isl-s4) calc(var(--isl-s4) + 4px);
   background: var(--isl-surface);
   border: 1px solid var(--isl-border);
   border-radius: var(--isl-r);
   text-decoration: none;
   color: inherit;
   overflow: hidden;
   transition: transform var(--isl-t-fast), box-shadow var(--isl-t-fast), border-color var(--isl-t-fast);
}
/* Le filet de gauche porte l'etat. Il double le chiffre : on voit d'un
   coup d'oeil, de l'autre bout du comptoir, s'il y a du rouge. */
body.gdv .gdv-ac-tuile::before {
   content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
   background: var(--isl-border-strong);
}
body.gdv .gdv-ac-tuile.ok::before     { background: var(--isl-success); }
body.gdv .gdv-ac-tuile.warn::before   { background: var(--isl-warning); }
body.gdv .gdv-ac-tuile.bad::before    { background: var(--isl-danger); }
body.gdv .gdv-ac-tuile.accent::before { background: var(--isl-accent); }

a.gdv-ac-tuile:hover {
   transform: translateY(-2px);
   box-shadow: var(--isl-sh-2);
   border-color: var(--isl-border-strong);
   color: inherit;
}

body.gdv .gdv-ac-k {
   font-size: var(--isl-fs-xs); font-weight: 700;
   letter-spacing: .05em; text-transform: uppercase;
   color: var(--isl-subtle);
}
body.gdv .gdv-ac-v {
   font-family: var(--isl-font-display);
   font-size: var(--isl-fs-3xl); font-weight: 700;
   line-height: 1.05; letter-spacing: -.035em;
   color: var(--isl-fg);
}
body.gdv .gdv-ac-tuile.bad .gdv-ac-v  { color: var(--isl-danger); }
body.gdv .gdv-ac-tuile.warn .gdv-ac-v { color: var(--isl-warning); }
body.gdv .gdv-ac-n { font-size: var(--isl-fs-xs); color: var(--isl-subtle); line-height: 1.4; }

body.gdv .gdv-ac-fl {
   position: absolute; right: var(--isl-s4); top: var(--isl-s4);
   color: var(--isl-subtle);
   opacity: 0; transform: translateX(-4px);
   transition: opacity var(--isl-t-fast), transform var(--isl-t-fast);
}
body.gdv .gdv-ac-fl svg { width: 14px; height: 14px; display: block; }
a.gdv-ac-tuile:hover .gdv-ac-fl { opacity: 1; transform: none; }

body.gdv .gdv-ac-carte { margin-bottom: var(--isl-s5); }

body.gdv .gdv-ac-titre {
   margin: 0 0 var(--isl-s3);
   font-size: var(--isl-fs-xs); font-weight: 700;
   letter-spacing: .09em; text-transform: uppercase;
   color: var(--isl-subtle);
   font-family: var(--isl-font-ui);
}

body.gdv .gdv-ac-racc {
   display: grid;
   grid-template-columns: repeat(auto-fit, minmax(232px, 1fr));
   gap: var(--isl-s3);
   margin-bottom: var(--isl-s6);
}
/* Les raccourcis sont huit. En auto-fit, un ecran large en tient cinq, et la
   deuxieme rangee en garde trois, decalees : la grille a l'air inachevee.
   On plafonne a quatre colonnes, elle se remplit alors en deux rangees
   pleines. */
@media (min-width: 1080px) {
   body.gdv .gdv-ac-racc { grid-template-columns: repeat(4, 1fr); }
}
body.gdv .gdv-ac-lien {
   display: flex; align-items: center; gap: var(--isl-s3);
   padding: 13px var(--isl-s4);
   background: var(--isl-surface);
   border: 1px solid var(--isl-border);
   border-radius: var(--isl-r);
   text-decoration: none; color: inherit;
   transition: transform var(--isl-t-fast), box-shadow var(--isl-t-fast),
               border-color var(--isl-t-fast), background var(--isl-t-fast);
}
body.gdv .gdv-ac-lien:hover {
   transform: translateY(-2px);
   box-shadow: var(--isl-sh-2);
   border-color: var(--isl-accent-border);
   color: inherit;
}
body.gdv .gdv-ac-ico {
   flex: none;
   display: inline-flex; align-items: center; justify-content: center;
   width: 36px; height: 36px;
   border-radius: var(--isl-r-sm);
   background: var(--isl-accent-soft);
   color: var(--isl-accent-text);
   transition: background var(--isl-t-fast), color var(--isl-t-fast);
}
body.gdv .gdv-ac-ico svg { width: 18px; height: 18px; }
body.gdv .gdv-ac-lien:hover .gdv-ac-ico { background: var(--isl-accent); color: var(--isl-on-accent); }
body.gdv .gdv-ac-txt { min-width: 0; display: flex; flex-direction: column; }
body.gdv .gdv-ac-txt b { font-size: var(--isl-fs-sm); font-weight: 600; }
body.gdv .gdv-ac-txt i { font-style: normal; font-size: var(--isl-fs-xs); color: var(--isl-subtle); }

body.gdv .gdv-ac-soc-in { display: flex; gap: var(--isl-s5); align-items: flex-start; flex-wrap: wrap; }
body.gdv .gdv-ac-logo {
   width: 96px; height: 96px; flex: none;
   object-fit: contain;
   background: var(--isl-surface-2);
   border-radius: var(--isl-r);
   padding: 8px;
}
body.gdv .gdv-ac-soc-txt { flex: 1 1 260px; min-width: 0; }
body.gdv .gdv-ac-soc-txt h3 {
   margin: 0 0 var(--isl-s3);
   font-size: var(--isl-fs-xl); font-weight: 700; letter-spacing: -.025em;
}
body.gdv .gdv-ac-infos { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }
body.gdv .gdv-ac-infos li {
   display: flex; gap: 10px; align-items: flex-start;
   font-size: var(--isl-fs-sm); color: var(--isl-muted); line-height: 1.5;
}
body.gdv .gdv-ac-infos svg { width: 15px; height: 15px; flex: none; margin-top: 3px; color: var(--isl-subtle); }
body.gdv .gdv-ac-pied { margin: var(--isl-s4) 0 0; font-size: var(--isl-fs-xs); color: var(--isl-subtle); }


/* ==========================================================================
   12. PAGES AUTONOMES
   Les fenetres de reglement et la fiche article en modale s'ouvrent dans
   une popup : pas de coque, pas de menu, et une marge courte - la fenetre
   est deja petite.
   ========================================================================== */

body.gdv-popup {
   padding: var(--isl-s4);
   background: var(--isl-bg);
}
body.gdv-popup .gu-container { margin: 0 auto; }
body.gdv-popup > table { margin: 0 auto; }

/* Les popups de reglement posent leurs tableaux sans classe. Ils
   meritent le meme habillage que les autres : sinon la fenetre de
   reglement est le seul ecran reste en 2008. */
body.gdv-popup table:not(.gdv-chp-grille) {
   background: var(--isl-surface);
   border-radius: var(--isl-r);
   font-size: var(--isl-fs-sm);
}
body.gdv-popup table:not(.gdv-chp-grille) > tbody > tr > th {
   padding: 8px 11px;
   font-size: 11px; font-weight: 700;
   letter-spacing: .05em; text-transform: uppercase;
   color: var(--isl-subtle);
   background: var(--isl-surface-2);
   border: 0; border-bottom: 1px solid var(--isl-border);
   text-align: left;
}
body.gdv-popup table:not(.gdv-chp-grille) > tbody > tr > td {
   padding: 7px 11px;
   border: 0; border-bottom: 1px solid var(--isl-border);
   vertical-align: middle;
}


/* ==========================================================================
   13. CE QUE LES MODULES ECRIVAIENT CHACUN DE LEUR COTE

   Treize modules portaient leur propre copie du systeme "gu-", avec ses
   couleurs en dur. Treize copies, c'est treize endroits ou reteinter
   l'application, et treize occasions de diverger : g_users avait un
   bouton bleu #007bff que personne n'avait decide.

   Tout est rapatrie ici, en jetons. Les blocs <style> des modules ont
   ete retires ; ceux qui restent ne portent plus que de la mise en page.
   ========================================================================== */

/* --- formulaire en grille ----------------------------------------------- */

.gu-form-grid {
   display: grid;
   grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
   gap: var(--isl-s4);
   margin-top: var(--isl-s3);
}
.gu-input-group { display: flex; flex-direction: column; }
/* Un libelle de champ se lit comme un mot, pas comme un en-tete de colonne.
   Celui-ci sortait en capitales de 11 px alors que les libelles rendus par
   tableau_chps() (.gdv-chp-lib) restaient en casse normale : deux ecrans de
   parametres cote a cote n'avaient pas la meme typographie de formulaire.
   Les deux classes disent maintenant la meme chose. */
.gu-label {
   margin-bottom: 5px;
   font-size: var(--isl-fs-sm); font-weight: 500;
   letter-spacing: 0; text-transform: none;
   color: var(--isl-muted);
}
.gu-required { color: var(--isl-danger); margin-left: 2px; }

.gu-subtitle {
   margin: -8px 0 var(--isl-s4);
   font-size: var(--isl-fs-sm);
   color: var(--isl-subtle);
}

/* Les champs .gu-input / .gu-select / .gu-list-select sont des <input>,
   <select> et <select multiple> : l'habillage commun des champs les
   couvre deja. Il ne reste ici que ce qui leur est propre. */
body.gdv .gu-input, body.gdv .gu-select { width: 100%; }
body.gdv .gu-list-select {
   width: 100%;
   min-height: 128px;
   padding: 6px;
}

/* --- messages ------------------------------------------------------------ */

.gu-message {
   padding: 11px var(--isl-s4);
   margin-bottom: var(--isl-s4);
   border-radius: var(--isl-r-sm);
   font-size: var(--isl-fs-sm); font-weight: 500;
   border: 1px solid transparent;
}
.gu-message-error   { background: var(--isl-danger-soft);  color: var(--isl-danger);  border-color: var(--isl-danger); }
.gu-message-success { background: var(--isl-success-soft); color: var(--isl-success); border-color: var(--isl-success); }

/* --- variantes de bouton restantes --------------------------------------- */
/* "Info" etait un bleu sorti de nulle part. Un ecran n'a pas besoin de
   deux couleurs d'action : elle devient l'action d'accent. */
.gu-btn-info {
   background: var(--isl-accent-soft);
   border-color: var(--isl-accent-border);
   color: var(--isl-accent-text);
}
.gu-btn-info:hover {
   background: var(--isl-accent);
   border-color: var(--isl-accent);
   color: var(--isl-on-accent);
}

/* Bouton d'action des listes (envoi de mail, impression...) - et, a la
   caisse, les touches de reglement. Celles-la sont a largeur fixe et
   portent deux lignes de libelle plus leur raccourci : le remplissage du
   formulaire, 17 px de chaque cote, ne laisse pas la place a "ESPECES &euro;".
   On le resserre sur l'horizontale, sans toucher a la hauteur. */
body.gdv .bton_action {
   background: var(--isl-accent);
   border-color: var(--isl-accent);
   color: var(--isl-on-accent);
   font-weight: 600;
   padding-left: 9px; padding-right: 9px;
}
body.gdv .bton_action:hover {
   background: var(--isl-accent-hover);
   border-color: var(--isl-accent-hover);
   color: var(--isl-on-accent);
}

/* --- arbre des acces aux menus (g_acces) --------------------------------- */

.gu-menu-tree {
   border: 1px solid var(--isl-border);
   border-radius: var(--isl-r);
   overflow: hidden;
   background: var(--isl-surface);
}
.gu-menu-row {
   display: flex; align-items: center; justify-content: space-between;
   gap: var(--isl-s3);
   padding: 8px 14px;
   border-bottom: 1px solid var(--isl-border);
   font-size: var(--isl-fs-sm);
   transition: background var(--isl-t-fast);
}
.gu-menu-row:last-child { border-bottom: none; }
.gu-menu-row:hover { background: var(--isl-accent-soft); }
/* Le niveau se lit au retrait ET au fond : un retrait seul disparait des
   qu'une ligne est longue. */
.gu-menu-row.gu-level1 {
   background: var(--isl-surface-2);
   font-weight: 700;
   color: var(--isl-accent-text);
}
.gu-menu-row.gu-level2 { padding-left: 34px; color: var(--isl-fg); }
.gu-menu-row.gu-level3 { padding-left: 58px; color: var(--isl-muted); font-size: var(--isl-fs-xs); }

/* --- historique client --------------------------------------------------- */

.gu-cashback-value {
   text-align: center;
   font-family: var(--isl-font-display);
   font-size: var(--isl-fs-3xl); font-weight: 700; letter-spacing: -.03em;
   color: var(--isl-accent-text);
}
.gu-num-pos { color: var(--isl-success); font-weight: 700; }
.gu-num-neg { color: var(--isl-danger);  font-weight: 700; }
.gu-pagination {
   display: flex; align-items: center; justify-content: center;
   gap: 8px; flex-wrap: wrap;
   margin-top: var(--isl-s4);
   font-size: var(--isl-fs-sm);
   color: var(--isl-subtle);
}


/* ==========================================================================
   14. COULEURS DE SENS PROPRES AUX ECRANS

   Un solde debiteur, un article a creer, une facture annulee : ces
   couleurs portent une information, pas une decoration. Elles etaient
   ecrites en dur dans une dizaine de modules, ou elles ne suivaient ni le
   theme ni le mode sombre. Elles sont ici, et elles le suivent.
   ========================================================================== */

/* Le tampon "ANNULE" pose en travers d'une piece. */
body.gdv .annule {
   color: var(--isl-danger);
   font-size: 36px; font-style: italic; font-weight: 700;
   letter-spacing: .04em;
}

/* Ligne d'article que la facture fournisseur va creer. */
body.gdv tr.lig_art_a_creer td {
   background: var(--isl-warning-soft);
   color: var(--isl-warning);
   font-weight: 600;
}

/* Les onglets de factures ouvertes, en haut des ecrans de saisie. */
body.gdv .fact_encours a,
body.gdv .fact_encours a:link,
body.gdv .fact_encours a:visited { color: var(--isl-muted); text-decoration: none; }
body.gdv .fact_encours a:hover { color: var(--isl-accent-text); }

/* L'encours d'un client : a jour, sous surveillance, depasse. Chacun
   porte un mot a cote dans l'ecran ; la couleur ne fait que doubler. */
body.gdv .cli_solde0 { background: var(--isl-success-soft); color: var(--isl-success); font-size: 13px; }
body.gdv .cli_solde1 { background: var(--isl-warning-soft); color: var(--isl-warning); font-size: 13px; font-weight: 700; }
body.gdv .cli_solde2 { background: var(--isl-danger);       color: var(--isl-on-accent); font-size: 13px; font-weight: 700; }
body.gdv .cli_bloque { text-align: center; color: var(--isl-danger); font-weight: 700; }

/* Alertes de fiche client incomplete ou invalide. */
body.gdv .cli_alerte {
   font-size: .78em;
   padding: 1px 6px;
   border-radius: var(--isl-r-full);
   margin-left: 5px;
   white-space: nowrap;
   cursor: default;
}
body.gdv .cli_alerte_incomplet {
   color: var(--isl-warning);
   background: var(--isl-warning-soft);
   border: 1px solid var(--isl-warning);
}
body.gdv .cli_alerte_invalide {
   color: var(--isl-danger);
   background: var(--isl-danger-soft);
   border: 1px solid var(--isl-danger);
}

/* Erreurs de saisie de stock et anomalies d'article. */
body.gdv .cl_error_stock,
body.gdv .cl_anomalies,
body.gdv .red_color,
body.gdv .bton_reset_mag { color: var(--isl-danger); font-weight: 700; }

/* Lignes d'echeance d'une balance client. */
body.gdv .tr_fact_lst td { background: var(--isl-surface); }
body.gdv .tr_fact_lst_echeance td { background: var(--isl-danger-soft); color: var(--isl-danger); font-weight: 600; }

/* Listing : reference absente du listing en cours. */
body.gdv .not_aff_listing td { background: var(--isl-danger-soft); }

/* Rapport journalier : le detail d'une facture, sous sa ligne. */
body.gdv .cl_det_fact td { background: var(--isl-warning-soft); font-style: italic; }

/* Lignes paires des longues listes de saisie. */
body.gdv .tableau_lst_arts tr:nth-child(odd) { background: var(--isl-surface-2); }

/* ==========================================================================
   POINT DE VENTE

   L'ecran de caisse etait le dernier a n'avoir jamais ete repris. Sa mise en
   page tenait dans un <table border="1"> de trois rangees, imbrique sur trois
   niveaux : une cellule pour le bandeau, une pour le panier, une pour le pave
   de reglement, une pour la legende des touches. Un tableau de mise en page ne
   sait rien faire d'autre que ce qu'on lui a dessine - pas de gouttiere, pas
   de coin arrondi, pas de rangee qui se replie - et chaque cellule y corrigeait
   son propre alignement a la main.

   Ici c'est une grille de deux colonnes : le panier prend la place qui reste,
   le pave garde sa largeur. Le bandeau et la legende traversent les deux.

   Une precision qui n'est pas cosmetique : la caisse tourne sur un poste de
   comptoir, en plein ecran (F11), et l'operateur ne regarde pas ses touches.
   D'ou les deux regles qui gouvernent tout ce bloc - les touches de reglement
   font toutes exactement la meme taille, et rien de ce qui porte un montant
   n'a le droit de bouger d'une frappe a l'autre.
   ========================================================================== */

body.gdv .gdv-pdv {
   display: grid;
   grid-template-columns: minmax(0, 1fr) auto;
   grid-template-areas:
      "bandeau bandeau"
      "panier  pave"
      "pied    pied";
   gap: 14px;
   align-items: start;
}
body.gdv .gdv-pdv-bandeau { grid-area: bandeau; }
body.gdv .gdv-pdv-panier  { grid-area: panier; min-width: 0; }
body.gdv .gdv-pdv-pave    { grid-area: pave; }
body.gdv .gdv-pdv-pied    { grid-area: pied; }

/* Sous 1100 px - une tablette de comptoir posee en portrait - le pave passe
   sous le panier plutot que de l'ecraser a rien. */
@media (max-width: 1100px) {
   body.gdv .gdv-pdv {
      grid-template-columns: minmax(0, 1fr);
      grid-template-areas: "bandeau" "pave" "panier" "pied";
   }
}

/* --- le bandeau ---------------------------------------------------------- */

body.gdv .gdv-pdv-bandeau {
   display: grid;
   grid-template-columns: minmax(220px, auto) minmax(0, 1fr) auto;
   gap: 10px 14px;
   align-items: start;
   padding: 10px 12px;
   background: var(--isl-surface);
   border: 1px solid var(--isl-border);
   border-radius: var(--isl-r);
}
@media (max-width: 900px) {
   body.gdv .gdv-pdv-bandeau { grid-template-columns: minmax(0, 1fr) auto; }
   body.gdv .gdv-pdv-client { grid-column: 1 / -1; }
}

body.gdv .gdv-pdv-client { display: flex; flex-direction: column; gap: 6px; }
body.gdv .gdv-pdv-cli-form,
body.gdv .gdv-pdv-cli-vue { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
body.gdv .gdv-pdv-cli-champ { min-width: 240px; }
body.gdv .gdv-pdv-cli-nom {
   font-size: var(--isl-fs-md);
   font-weight: 700;
   color: var(--isl-fg);
   margin-right: 2px;
}

/* La bande des tickets ouverts. Elle revient a la ligne toute seule : c'est
   la seule zone de l'ecran dont le contenu n'est pas borne, et compter six
   pastilles par rangee a la main - ce que faisait le module - ne tenait que
   tant que la fenetre gardait sa largeur. */
body.gdv .gdv-pdv-tickets {
   display: flex;
   flex-wrap: wrap;
   gap: 8px;
   align-content: flex-start;
   min-width: 0;
}
body.gdv .gdv-pdv-neuf { display: flex; align-items: stretch; }

/* La pastille d'un ticket ouvert : heure, montant, client, l'un sous l'autre.
   Plancher et jamais plafond - le rappel est dans ce CLAUDE.md, il a deja
   coute une fois le nom du client passe sous la bordure. */
body.gdv .fact_en_cours, body.gdv #new_fact {
   min-width: 105px;
   min-height: calc(3 * 1.35em + 14px);
   padding: 6px 10px;
   font-size: 12.5px; line-height: 1.35;
   text-align: center;
   display: inline-flex;
   flex-direction: column;
   justify-content: center;
   gap: 1px;
}
body.gdv .fact_en_cours .gdv-pdv-tk-h,
body.gdv .fact_en_cours .gdv-pdv-tk-mt,
body.gdv .fact_en_cours .gdv-pdv-tk-cli { display: block; }
body.gdv .fact_en_cours .gdv-pdv-tk-mt { font-weight: 700; }
body.gdv .fact_en_cours .gdv-pdv-tk-cli { color: var(--isl-muted); }

/* Le ticket en cours d'edition. Il ne se signalait que par une encre rouge
   sur trois lignes de texte deja petites ; a la caisse, on repere la pastille
   active du coin de l'oeil, pas en la lisant. Elle porte donc le fond de
   l'accent, et l'encre suit. */
body.gdv .fact_en_cours.is-on {
   background: var(--isl-accent);
   border-color: var(--isl-accent);
   color: var(--isl-on-accent);
}
body.gdv .fact_en_cours.is-on .fact_en_cours_select,
body.gdv .fact_en_cours.is-on .gdv-pdv-tk-cli { color: var(--isl-on-accent); }
body.gdv .fact_en_cours_select { font-weight: 700; }

/* --- le panier ----------------------------------------------------------- */

/* Pas de overflow:hidden ici. Il n'etait la que pour arrondir les coins, et
   il coupait la bulle des conditions speciales des que la ligne en edition
   etait la premiere du panier. Les rayons sont poses sur les cellules
   d'angle : meme rendu, rien n'est rogne. */
body.gdv .gdv-pdv-lignes {
   width: 100%;
   border-collapse: collapse;
   background: var(--isl-surface);
   border: 1px solid var(--isl-border);
   border-radius: var(--isl-r);
}
body.gdv .gdv-pdv-lignes tr:first-child th:first-child { border-top-left-radius: var(--isl-r); }
body.gdv .gdv-pdv-lignes tr:first-child th:last-child { border-top-right-radius: var(--isl-r); }
body.gdv .gdv-pdv-lignes th {
   background: var(--isl-surface-2);
   color: var(--isl-fg);
   font-weight: 700;
   font-size: var(--isl-fs-data);
   text-align: center;
   padding: 7px 8px;
   border-bottom: 1px solid var(--isl-border);
}
body.gdv .gdv-pdv-lignes td {
   padding: 4px 8px;
   border-bottom: 1px solid var(--isl-border);
   vertical-align: middle;
}
body.gdv .gdv-pdv-lignes tr:last-child td { border-bottom: 0; }

/* L'alignement des sept colonnes. Il etait ecrit trente-cinq fois, cellule
   par cellule, sur les trois variantes de ligne - affichee, en edition, en
   saisie - et une seule oubliee suffisait a decaler une colonne de chiffres.
   Une colonne s'aligne une fois pour toutes. */
body.gdv .gdv-pdv-lignes td:nth-child(1),
body.gdv .gdv-pdv-lignes td:nth-child(3),
body.gdv .gdv-pdv-lignes td:nth-child(7) { text-align: center; }
body.gdv .gdv-pdv-lignes td:nth-child(4),
body.gdv .gdv-pdv-lignes td:nth-child(5),
body.gdv .gdv-pdv-lignes td:nth-child(6) { text-align: right; font-variant-numeric: tabular-nums; }
body.gdv .gdv-pdv-lignes td.gdv-pdv-lib { text-align: left; font-size: var(--isl-fs-data); }
/* L'en-tete du libelle s'aligne comme sa colonne. Ecrit sur la seule classe,
   il perdait contre le "body.gdv .gdv-pdv-lignes th" qui centre les six
   autres : une classe de plus du cote de la regle generale. */
body.gdv .gdv-pdv-lignes th.gdv-pdv-col-lib { width: 70%; text-align: left; }

body.gdv .gdv-pdv-lig-edit td { background: var(--isl-accent-soft); }
body.gdv .gdv-pdv-sep { background: var(--isl-surface-2); height: 8px; padding: 0; }

/* Une rangee de saisie n'est pas un formulaire : les champs y descendent d'un
   cran, comme le veut le manifeste pour une ligne de document. */
body.gdv .gdv-pdv-lignes input[type="text"],
body.gdv .gdv-pdv-lignes select,
body.gdv .gdv-pdv-lignes button {
   font-size: 13px;
   padding: 5px 8px;
   min-height: 0;
}
body.gdv .gdv-pdv-lignes .input_num { text-align: right; width: 9ch; }
body.gdv .gdv-pdv-lignes .input_qte { text-align: center; width: 5ch; }

/* La cellule Remise ne revient pas a la ligne : la pastille des conditions
   speciales et le pourcentage tiennent cote a cote, et le nombre reste
   aligne a droite avec Prix brut et Total net. */
body.gdv .gdv-pdv-lignes td:nth-child(5) { white-space: nowrap; }

/* --- la rangee de saisie ------------------------------------------------
   CODE et Libelle y etaient fusionnes en un seul colspan="2". Les deux
   champs se posaient donc a cheval sur les deux colonnes, centres par la
   regle d'alignement de la premiere : ni le code-barres sous CODE, ni la
   recherche sous Libelle. Une rangee de saisie doit se lire comme la rangee
   qu'elle va produire, sinon on tape sans savoir ou ca tombe. */
body.gdv .gdv-pdv-lignes .gdv-pdv-codebar { width: 9ch; text-align: center; }
/* La recherche prend toute la colonne du libelle - c'est la seule colonne
   large de l'ecran, et le nom d'un vin y tient rarement en 45 caracteres.
   Le flex est sur un <div> et pas sur la cellule : un display:flex pose sur
   un <td> le sort du modele de tableau et la rangee se disloque. */
body.gdv .gdv-pdv-saisie { display: flex; align-items: center; gap: 6px; }
body.gdv .gdv-pdv-lignes .gdv-pdv-rech { flex: 1 1 auto; min-width: 0; width: 100%; }
body.gdv .gdv-pdv-saisie button { flex: none; }
body.gdv .input_num { text-align: right; }
body.gdv .input_qte { text-align: center; }

/* --- le pave de reglement ------------------------------------------------ */

body.gdv .gdv-pdv-pave {
   display: flex;
   flex-direction: column;
   gap: 12px;
   width: 260px;
   max-width: 100%;
}
@media (max-width: 1100px) { body.gdv .gdv-pdv-pave { width: auto; } }

/* Le total. C'etait deux cellules d'un tableau, une etiquette en x-large a
   droite et un montant en xx-large, separes par deux <br> vides. Le montant
   est le seul chiffre de l'ecran qu'on lit a voix haute : il a droit a sa
   carte, et aux chiffres a chasse fixe pour ne pas frissonner a chaque
   article ajoute. */
body.gdv .gdv-pdv-total {
   background: var(--isl-surface);
   border: 1px solid var(--isl-border);
   border-radius: var(--isl-r);
   padding: 12px 14px;
   text-align: right;
}
body.gdv .gdv-pdv-total-k {
   font-size: 11px; font-weight: 700; letter-spacing: .08em;
   color: var(--isl-muted);
}
body.gdv .gdv-pdv-total-v {
   font-size: 30px; font-weight: 700; line-height: 1.15;
   color: var(--isl-accent-text);
   font-variant-numeric: tabular-nums;
   margin-top: 2px;
}
body.gdv .gdv-pdv-total-dev {
   font-size: 16px; font-style: italic;
   color: var(--isl-muted);
   font-variant-numeric: tabular-nums;
}
body.gdv .gdv-pdv-total-nb {
   margin-top: 8px; padding-top: 8px;
   border-top: 1px solid var(--isl-border);
   font-size: var(--isl-fs-data);
   color: var(--isl-muted);
}

/* Les touches. Deux colonnes egales : c'est ce qui permet de les viser sans
   les regarder. Le deuxieme pave - tickets, tiroir, rapport, annulation - est
   separe du premier et rendu en contour : ces touches-la ne font pas avancer
   l'encaissement, et quatre rangees de bordeaux plein ne se distinguent plus
   les unes des autres. */
body.gdv .gdv-pdv-touches {
   display: grid;
   grid-template-columns: 1fr 1fr;
   gap: 8px;
}
body.gdv .gdv-pdv-touches .bton_action { width: 100%; min-width: 0; }
body.gdv .gdv-pdv-touches-2 { padding-top: 4px; border-top: 1px solid var(--isl-border); }
body.gdv .gdv-pdv-touches-2 .bton_action {
   background: transparent;
   border-color: var(--isl-border);
   color: var(--isl-fg);
}
body.gdv .gdv-pdv-touches-2 .bton_action:hover {
   background: var(--isl-surface-2);
   border-color: var(--isl-muted);
   color: var(--isl-fg);
}

/* Touche de reglement. Deux lignes de libelle plus son raccourci, jamais une
   hauteur figee. L'horizontale est resserree : le remplissage du formulaire,
   17 px de chaque cote, ne laisse pas la place a "ESPECES &euro;". */
body.gdv .bton_action {
   background: var(--isl-accent);
   border-color: var(--isl-accent);
   color: var(--isl-on-accent);
   font-weight: 600;
   min-width: 110px;
   min-height: 44px;
   padding-left: 9px; padding-right: 9px;
   line-height: 1.3;
}
body.gdv .bton_action:hover {
   background: var(--isl-accent-hover);
   border-color: var(--isl-accent-hover);
   color: var(--isl-on-accent);
}
body.gdv .bton_action u { text-decoration: none; opacity: .75; font-size: .9em; }

/* --- les fenetres de reglement ------------------------------------------- */

/* Le moule commun des huit fenetres : une pile de lignes cle/valeur. Le ton
   dit ce que la ligne represente - ce qui est du, ce qui est recu, ce qu'on
   rend - et c'est la feuille qui choisit la couleur, pas le module. */
body.gdv .gdv-reg { display: flex; flex-direction: column; gap: 10px; min-width: 280px; }
body.gdv .gdv-reg-lig {
   display: flex;
   align-items: center;
   justify-content: space-between;
   gap: 14px;
}
body.gdv .gdv-reg-lig .k {
   font-size: var(--isl-fs-data);
   font-weight: 600;
   color: var(--isl-muted);
   white-space: nowrap;
}
body.gdv .gdv-reg-lig .v {
   display: inline-flex; align-items: center; gap: 5px;
   font-size: 20px; font-weight: 700;
   font-variant-numeric: tabular-nums;
   color: var(--isl-fg);
}
body.gdv .gdv-reg-lig-pleine { justify-content: center; text-align: center; }
body.gdv .gdv-reg-lig.du .v     { color: var(--isl-danger); }
body.gdv .gdv-reg-lig.recu .v   { color: var(--isl-success); }
body.gdv .gdv-reg-lig.rendu .v  { color: var(--isl-accent-text); }
body.gdv .gdv-reg-note .v { font-size: var(--isl-fs-data); font-weight: 500; color: var(--isl-muted); }

body.gdv .gdv-reg-champ {
   width: 10ch;
   text-align: right;
   font-size: 18px;
   font-weight: 700;
   font-variant-numeric: tabular-nums;
}
/* Le ton du champ se declare, il ne s'herite pas : la regle generale
   body.gdv input pose une encre, et un color:inherit pose sur la classe ne
   suffit pas a la reprendre a tous les coups. */
body.gdv .gdv-reg-lig.recu .gdv-reg-champ  { color: var(--isl-success); }
body.gdv .gdv-reg-lig.rendu .gdv-reg-champ { color: var(--isl-accent-text); }
body.gdv .gdv-reg-lig.du .gdv-reg-champ    { color: var(--isl-danger); }
body.gdv .gdv-reg-texte { width: 100%; min-width: 260px; }
body.gdv .gdv-reg-centre { text-align: center; }

/* Multi-reglements : mode, montant, devise, puis le TPE quand il y en a un.

   En rang souple et non en grille, parce qu'on ne sait pas d'avance combien
   d'elements la ligne portera : le declencheur du TPE n'apparait que pour les
   modes qui en ont un, et une colonne de grille reservee a un bouton absent
   laisse un trou.

   Le piege propre a isl-ui : le composant de liste masque le <select> et pose
   SON declencheur juste apres. La classe qu'on ecrit dans le module se
   retrouve donc sur un element en display:none, qui ne tient aucune place. La
   largeur se regle sur le frere - d'ou les selecteurs en "+ .isl-ctl". Et le
   declencheur nait en width:100% : sans reprise, la devise (un caractere)
   occupait autant que le mode de reglement. */
body.gdv .gdv-reg-mreg {
   display: grid;
   grid-template-columns: minmax(0, 1fr) auto auto 36px;
   gap: 8px;
   align-items: center;
}
body.gdv .gdv-reg-mreg .gdv-reg-champ { color: var(--isl-success); }
body.gdv .gdv-reg-mreg .gdv-reg-dev + .isl-ctl { width: auto; }
body.gdv .gdv-reg-mreg .bton_tpe_multi_reg { width: 36px; min-width: 0; padding: 9px; }
/* La troisieme ligne est celle de l'appoint. Elle etait ecrite "blue" en
   dur - la couleur ne disait rien, la place dans la pile disait tout. */
body.gdv .gdv-reg-mreg.appoint .gdv-reg-champ { color: var(--isl-accent-text); }
body.gdv .gdv-reg-lib { display: flex; align-items: center; gap: 8px; padding-left: 2px; }
body.gdv .gdv-reg-lib .libelle_reg { width: 14ch; text-align: center; }

/* --- la barre d'actions d'un document ------------------------------------
   Facture, BL, devis : "Annuler", "Reprise", "Transferer", "Dupliquer(+)",
   "Dupliquer(-)". Ils etaient separes par &nbsp;&nbsp;&nbsp;. Une espace
   insecable n'est pas une mesure : elle suit la taille du texte, elle ne se
   replie pas en bout de ligne, et quand un droit masque le bouton d'avant
   elle reste la, en creux, contre le bord de la cellule.

   Les marges par bouton sont parties avec le tableau a deux cellules : une
   marge de 3 px sur chaque bouton, dans une cellule centree, ne garde pas
   deux rangees alignees - elle les decale d'une demi-marge a chaque
   retombee. C'est le gap de la barre qui espace, une seule fois, et les
   deux groupes gardent leur ligne de base.

   Le selecteur d'enfant direct compte : ces deux groupes contiennent des
   tableaux imbriques - les boutons d'impression et de mail - qui ont leur
   propre espacement. */
body.gdv .gdv-doc-barre {
   display: flex;
   flex-wrap: wrap;
   align-items: flex-start;
   justify-content: space-between;
   gap: var(--isl-s3) var(--isl-s5);
   margin-top: var(--isl-s5);
   padding: var(--isl-s4);
   background: var(--isl-surface);
   border: 1px solid var(--isl-border);
   border-radius: var(--isl-r);
   box-shadow: var(--isl-sh-1);
}
body.gdv .gdv-doc-actions {
   display: flex;
   flex-wrap: wrap;
   align-items: center;
   gap: var(--isl-s2);
   min-width: 0;
}
/* Ce qui sort le document - enregistrer, BL, devis, PDF, mail - se range a
   droite, comme partout ailleurs dans l'application. */
body.gdv .gdv-doc-actions-d { justify-content: flex-end; margin-left: auto; }
body.gdv .gdv-doc-actions > input[type="button"],
body.gdv .gdv-doc-actions > input[type="submit"] { margin: 0; }
/* Les tableaux imbriques de la zone d'actions - impression, envoi par mail -
   ne sont pas des listings : ni cadre, ni ombre, ni fond de panneau. */
body.gdv .gdv-doc-actions table {
   border: 0;
   box-shadow: none;
   background: transparent;
   margin: 0;
}
body.gdv .gdv-doc-actions table td { padding: 0 3px; border: 0; }

/* Un groupe vide ne doit pas occuper la moitie de la barre : en saisie, la
   colonne de gauche ne porte qu'un bouton, et parfois aucun. */
body.gdv .gdv-doc-actions:empty { display: none; }

/* L'action qui conclut le document porte l'accent. Les autres sont des
   chemins de traverse ; celle-la est ce qu'on est venu faire. Les trois
   identifiants existent depuis toujours dans le module. */
body.gdv .gdv-doc-barre #bton_enreg:not([disabled]),
body.gdv .gdv-doc-barre #bton_bl:not([disabled]),
body.gdv .gdv-doc-barre #bton_devis:not([disabled]) {
   background: var(--isl-accent);
   border-color: var(--isl-accent);
   color: var(--isl-on-accent);
   font-weight: 600;
}

/* --- le numero de piece --------------------------------------------------
   L'identite du document : ce qu'on lit au telephone, ce qu'on cherche dans
   une pile. Le numero passe en chasse fixe, parce qu'un numero se lit
   chiffre par chiffre et que deux numeros voisins doivent s'aligner. */
body.gdv .gdv-doc-piece {
   display: flex; align-items: baseline; flex-wrap: wrap;
   gap: var(--isl-s2);
   margin-bottom: var(--isl-s3);
}
body.gdv .gdv-doc-piece-lib {
   font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
   color: var(--isl-subtle);
}
body.gdv .gdv-doc-piece-num {
   font-family: var(--isl-font-mono);
   font-size: var(--isl-fs-md);
   font-weight: 700;
   color: var(--isl-fg);
}
body.gdv .gdv-doc-piece-info { color: var(--isl-muted); font-size: var(--isl-fs-sm); }
body.gdv .gdv-doc-piece-compta {
   padding: 2px 8px;
   font-size: var(--isl-fs-xs); font-weight: 600;
   color: var(--isl-accent-text);
   background: var(--isl-accent-soft);
   border: 1px solid var(--isl-accent-border);
   border-radius: var(--isl-r-full);
}

/* --- la navigation d'une piece a l'autre ---------------------------------
   Les deux boutons << et >> de la consultation etaient une rangee de
   tableau a deux cellules, l'une a gauche l'autre a droite : sur un ecran
   large, cent pixels de bouton separes par mille de vide, et rien ne disait
   qu'ils allaient ensemble. Ils se rejoignent au-dessus du document. */
body.gdv .gdv-doc-nav {
   display: flex; align-items: center; gap: var(--isl-s2);
   margin-bottom: var(--isl-s3);
}

/* --- les documents en cours ----------------------------------------------
   La liste des paniers ouverts, en haut de "Creer facture". C'est par la
   qu'on reprend un document commence, donc c'est le premier endroit ou l'on
   clique en arrivant. Elle sortait en tableau de neuf colonnes : sur trois
   documents, trois cellules etirees ; sur vingt, une grille de neuf
   colonnes de quarante pixels ou le nom du client se cassait lettre par
   lettre. Une liste de cartes a largeur minimale se replie d'elle-meme et
   ne depend plus d'un nombre par ligne ecrit dans le module. */
body.gdv .gdv-encours {
   margin: 0 0 var(--isl-s5);
   background: var(--isl-surface);
   border: 1px solid var(--isl-border);
   border-radius: var(--isl-r);
   box-shadow: var(--isl-sh-1);
   /* Ici le rognage est sans danger - c'est un <div>, il ne contient aucun
      element collant - et il sert : il coupe le filet droit de la derniere
      carte de chaque rangee, qui tomberait sinon sur le bord du panneau. */
   overflow: hidden;
}
body.gdv .gdv-encours-tete {
   display: flex; align-items: center; gap: var(--isl-s2);
   padding: 9px var(--isl-s4);
   border-bottom: 1px solid var(--isl-border);
   font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
   color: var(--isl-subtle);
}
body.gdv .gdv-encours-nb {
   display: inline-flex; align-items: center; justify-content: center;
   min-width: 20px; height: 18px; padding: 0 6px;
   font-size: 11px; font-weight: 700; letter-spacing: 0;
   color: var(--isl-accent-text);
   background: var(--isl-accent-soft);
   border: 1px solid var(--isl-accent-border);
   border-radius: var(--isl-r-full);
}
/* auto-fill et non auto-fit : avec auto-fit, deux documents en cours
   s'etirent chacun sur la moitie de l'ecran et une carte de reprise de
   panier prend huit cents pixels. */
body.gdv .gdv-encours-lst {
   display: grid;
   grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}
/* Les filets sont portes par les cartes, pas par un fond vu au travers d'un
   gap : une rangee incomplete laissait sinon une bande grise a la place des
   cases manquantes - trois documents en cours sur quatre colonnes, et un
   quart du panneau sortait en gris plein. */
body.gdv .gdv-encours-doc {
   display: grid;
   grid-template-columns: 1fr auto;
   gap: 2px var(--isl-s3);
   padding: 9px var(--isl-s4);
   background: var(--isl-surface);
   border-right: 1px solid var(--isl-border);
   border-bottom: 1px solid var(--isl-border);
   margin-bottom: -1px;
   text-decoration: none;
   transition: background .12s ease;
}
body.gdv .gdv-encours-doc:hover { background: var(--isl-accent-soft); }
body.gdv .gdv-encours-cli {
   font-weight: 600; color: var(--isl-fg);
   overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
body.gdv .gdv-encours-mt {
   font-variant-numeric: tabular-nums;
   font-weight: 600; color: var(--isl-fg); white-space: nowrap;
}
body.gdv .gdv-encours-bas {
   grid-column: 1 / -1;
   font-size: var(--isl-fs-sm); color: var(--isl-muted);
   overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
body.gdv .gdv-encours-sep { margin: 0 6px; }
/* Le document ouvert. Le repere est un filet a gauche et non un fond plein :
   la carte reste lisible, et on voit d'un coup d'oeil ou l'on est. */
body.gdv .gdv-encours-doc.is-on {
   background: var(--isl-accent-soft);
   box-shadow: inset 3px 0 0 var(--isl-accent);
}
body.gdv .gdv-encours-doc.is-on .gdv-encours-cli,
body.gdv .gdv-encours-doc.is-on .gdv-encours-mt { color: var(--isl-accent-text); }

/* --- la barre "Nouveau document" -----------------------------------------
   Elle ouvre l'ecran, au-dessus de la carte des documents en cours. Le
   <center> qui la porte n'a aucune marge propre, donc le bouton touchait
   presque la carte en dessous : rien ne disait qu'il n'en faisait pas
   partie. Un cran d'espacement l'en detache, comme partout ailleurs entre
   deux blocs de meme rang. */
body.gdv .gdv-doc-neuf { margin-bottom: var(--isl-s5); }

/* --- l'en-tete d'un document ---------------------------------------------
   Qui emet, pour qui, quand. Trois blocs de meme rang, donc trois colonnes
   nommees dans une carte, et non plus deux cellules de tableau de mise en
   page separees par une case vide. Le client passe au milieu : c'est le
   seul des trois qu'on change, et les deux boutons qui le concernent -
   historique, changer client - sont maintenant a cote de son nom.
   minmax(0, 1fr) et non 1fr : une adresse sans espace - un courriel long -
   imposerait sinon sa largeur minimale a la colonne et pousserait les deux
   autres hors de la carte. */
body.gdv .gdv-doc-entete {
   display: grid;
   grid-template-columns: repeat(3, minmax(0, 1fr));
   gap: 1px;
   margin-bottom: var(--isl-s5);
   background: var(--isl-border);
   border: 1px solid var(--isl-border);
   border-radius: var(--isl-r);
   overflow: hidden;
}
body.gdv .gdv-doc-bloc {
   padding: var(--isl-s3) var(--isl-s4);
   background: var(--isl-surface);
}
body.gdv .gdv-doc-bloc-tit {
   margin-bottom: 5px;
   font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
   color: var(--isl-subtle);
}
body.gdv .gdv-doc-bloc-txt { line-height: 1.55; overflow-wrap: break-word; }
body.gdv .gdv-doc-nom { font-size: var(--isl-fs-md); font-weight: 700; }
body.gdv .gdv-doc-nom a { font-weight: 700; }
body.gdv .gdv-doc-annule { margin-top: var(--isl-s3); }
/* Le nom du client et ses deux boutons sur une seule ligne, qui se replie
   si le nom est long. Ils etaient separes par des &nbsp; en serie, donc
   places au petit bonheur selon la longueur du nom. */
body.gdv .gdv-doc-cli-tete {
   display: flex; align-items: center; flex-wrap: wrap;
   gap: var(--isl-s2);
   margin-bottom: 3px;
}
/* Sous 1100 px les trois colonnes n'ont plus la place de vivre cote a cote :
   une adresse de trois lignes dans un tiers de 900 px se casse mot par mot. */
@media (max-width: 1100px) {
   body.gdv .gdv-doc-entete { grid-template-columns: minmax(0, 1fr); }
}

/* --- le libelle d'une ligne de document ----------------------------------
   Chaque nom d'article etait precede de six &nbsp; en dur. Six espaces
   insecables font une trentaine de pixels que la colonne Description ne
   peut ni recuperer ni couper : sur une colonne serree, ils suffisaient a
   pousser "Chateauneuf-du-Pape Domaine du Vieux Telegraphe" sur quatre
   lignes alors qu'il en tenait deux. Un retrait est une affaire de
   feuille - et celui-la peut fondre quand la place manque.
   La colonne prend en meme temps tout l'espace que les autres ne reclament
   pas : elles sont toutes a leur mesure de contenu, donc un width de 100 %
   ici veut dire "le reste", ce qui est exactement ce qu'on veut d'une
   colonne de libelles. */
body.gdv .gdv-doc-lib {
   width: 100%;
   padding-left: var(--isl-s4);
}
@media (max-width: 1100px) {
   body.gdv .gdv-doc-lib { padding-left: var(--isl-s2); }
}

/* --- le commentaire d'un document ---------------------------------------
   Une ligne de saisie pleine largeur, posee juste au-dessus des lignes du
   document. Le champ prend la place qui reste : un commentaire est une
   phrase, et la mesure par defaut d'un input en coupait la moitie. Le
   plafond de 210 px ne l'atteint pas - il ne vise que .tableau_chps. */
body.gdv .gdv-doc-com {
   display: flex; align-items: center; flex-wrap: wrap;
   gap: var(--isl-s2);
   margin-bottom: var(--isl-s3);
}
body.gdv .gdv-doc-com-lib {
   font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
   color: var(--isl-subtle);
   cursor: pointer;
}
body.gdv .gdv-doc-com-chp { flex: 1 1 260px; min-width: 0; }

/* --- l'ancre d'une ligne de document -------------------------------------
   Chaque ajout, chaque modification de ligne recharge l'ecran sur
   "#tag_add" ou "#tag_edit". Le navigateur amene l'ancre a zero, c'est-a-
   dire sous la barre du haut ET sous l'en-tete de colonnes du tableau, qui
   collent l'une a 0 et l'autre a --gdv-top-h : la rangee qu'on vient
   d'ajouter arrivait cachee, et il fallait remonter a la main pour la voir.
   Le retrait est la hauteur de la barre plus celle de l'en-tete de
   colonnes, plus une ligne d'air pour qu'on voie qu'il y a un en-tete
   au-dessus. */
body.gdv .gdv-ancre-doc { scroll-margin-top: calc(var(--gdv-top-h, 62px) + 64px); }

/* --- les colonnes d'un tableau de lignes de document ---------------------
   Le module ecrit ses alignements depuis toujours en align="right" et
   align="center" sur la cellule. Un attribut de presentation vaut moins
   que n'importe quelle regle d'auteur : la regle des listings
   "...table_theme > tbody > tr > td { text-align: left }" les ecrasait tous,
   les uns apres les autres. Un document ou le prix, la remise, la quantite
   et le total sont tous alignes a gauche ne se relit pas - on ne voit plus
   quelle virgule repond a quelle virgule.
   C'est le cas prevu par la charte : un selecteur d'attribut qui rattrape
   le vieux balisage, comme font[color] et [bgcolor] ailleurs. Trois regles
   rendent leur sens aux soixante attributs deja ecrits, sans toucher une
   ligne du module. Le nth-child n'aurait pas marche : la rangee posee
   commence par la cellule du code, la rangee en edition par un colspan de
   deux, donc la meme colonne n'a pas le meme rang selon la ligne.
   Specificite : quatre classes et quatre elements, contre quatre classes
   et trois elements pour la regle des listings. */
body.gdv .tableau_chps.gdv-doc-lignes > tbody > tr > td[align="right"] {
   text-align: right;
   font-variant-numeric: tabular-nums;
}
body.gdv .tableau_chps.gdv-doc-lignes > tbody > tr > td[align="center"] { text-align: center; }
body.gdv .tableau_chps.gdv-doc-lignes > tbody > tr > td[align="left"] { text-align: left; }

/* La cellule Remise porte la pastille et le pourcentage cote a cote. */
body.gdv .gdv-doc-remise { white-space: nowrap; }

/* --- le titre de groupe, dans un document trie par rayon -----------------
   La rangee sortait une cellule unique, sans colspan, dans un tableau qui en
   compte sept ou huit : le titre du rayon se retrouvait serre dans la colonne
   du code article, large de dix pixels, et se cassait lettre par lettre. Le
   colspan est pose dans le module ; il reste a lui donner l'aspect d'un
   intertitre plutot que celui d'une ligne d'article vide.
   Le prefixe long est celui du pied de totaux, et pour la meme raison : la
   regle des cellules de listing vaut (0,4,3) et poserait son filet bas et son
   alignement a gauche par-dessus une classe seule. */
body.gdv .tableau_chps:is(.table_theme, .matable, .gu-history-table, .tableau_lst_arts) > tbody > tr.gdv-doc-groupe > td {
   background: var(--isl-surface-2);
   border-bottom: 1px solid var(--isl-border);
   color: var(--isl-muted);
   font-size: var(--isl-fs-sm);
   letter-spacing: .02em;
   padding-top: 9px;
   padding-bottom: 5px;
}
/* Un intertitre ne se survole pas : il n'y a rien a y cliquer. */
body.gdv .tableau_chps:is(.table_theme, .matable, .gu-history-table, .tableau_lst_arts) > tbody > tr.gdv-doc-groupe:hover {
   background: transparent;
}

/* --- la rangee de saisie d'un document ----------------------------------
   Le champ de recherche prend toute sa colonne. Il portait un size="70"
   qui, dans une colonne a 40 %, debordait ou se faisait couper selon la
   largeur de l'ecran. */
/* Le selecteur est qualifie par [type="text"] a dessein. Le plafond des
   champs de formulaire - "body.gdv .tableau_chps input[type=text]" a
   (0,2,2), plus haut dans la feuille - borne tout champ texte a 210 px, et
   une classe seule a (0,2,0) perd contre lui : le champ de recherche
   d'article restait a 210 px dans une colonne qui en fait quatre cents,
   soit un petit rectangle vide au bord gauche de la rangee de saisie. Or
   une ligne de document n'est pas un formulaire, exactement comme pour les
   <select> juste en dessous de ce plafond-la : la colonne fait la mesure.
   Qualifie de la meme facon, ce selecteur vaut (0,3,2) et reprend la main
   sans elargir un seul autre champ de l'application. */
body.gdv input[type="text"].gdv-doc-rech,
body.gdv .tableau_chps input[type="text"].gdv-doc-rech {
   width: 100%;
   min-width: 0;
   max-width: none;
   box-sizing: border-box;
}
/* La rangee de saisie se distingue des lignes deja posees : c'est la seule
   ou l'on tape. Le survol des listings ne la repeint pas. */
body.gdv .tableau_chps.gdv-doc-lignes > tbody > tr.gdv-doc-saisie > td {
   background: var(--isl-accent-soft);
   border-top: 1px solid var(--isl-accent-border);
}

/* Ce qui faisait "sauter les champs les uns sur les autres".
   Chaque cellule de la rangee en edition porte un champ SUIVI de son unite :
   <input size="6" /> puis "&nbsp;EUR". Le champ fait 81 px dans une colonne
   qui en fait 101, l'unite ne tient pas derriere, et elle passe donc a la
   ligne - sous le champ, decalee, une par colonne. La rangee montait a
   83 px la ou une ligne posee en fait 50, et chaque prix se lisait sur deux
   etages. La derniere cellule, elle, porte les deux boutons Enregistrer et
   Supprimer : dans 57 px, ils s'empilaient et debordaient de la rangee.
   Une cellule de saisie tient sur UNE ligne. Le tableau est en mise en page
   automatique : les colonnes concernees prennent les quelques pixels qui
   leur manquent sur celles qui en ont de reste, et rien ne deborde.
   La premiere cellule est exclue - td + td - parce que c'est la
   description : elle, elle doit se casser sur plusieurs lignes. */
body.gdv .tableau_chps.gdv-doc-lignes > tbody > tr.gdv-doc-saisie > td + td {
   white-space: nowrap;
}
/* Les deux boutons de la cellule d'action gardent un ecart franc. On ne
   passe PAS la cellule en display:flex pour cela : un <td> en flex sort de
   l'algorithme de mise en page du tableau et sa colonne cesse d'etre alignee
   sur celle des lignes posees. Une marge suffit. */
body.gdv .tableau_chps.gdv-doc-lignes > tbody > tr.gdv-doc-saisie > td:last-child > * + * {
   margin-left: var(--isl-s2);
}

/* --- le pied de totaux d'un document ------------------------------------
   Il se lisait comme trois lignes d'articles de plus : meme graisse, meme
   taille, aucune separation d'avec le corps. Un filet au-dessus, les
   libelles en retrait et les montants en chasse fixe les uns sous les
   autres suffisent a en faire un pied.

   Le prefixe n'est pas decoratif. La regle qui habille les cellules d'un
   listing - "body.gdv .tableau_chps.table_theme > tbody > tr > td" - vaut
   (0,4,3) et pose text-align:left, un filet bas et son remplissage. Une
   classe seule, meme prefixee body.gdv, perd contre elle : les libelles
   repartaient a gauche et le filet restait sous chaque ligne de total. Le
   :is() ne compte que pour une classe, donc l'ensemble vaut (0,4,4) : une
   colonne d'elements de plus, ce qui suffit. */
body.gdv .tableau_chps:is(.table_theme, .matable, .gu-history-table, .tableau_lst_arts) > tbody > tr.gdv-doc-tot > td {
   border-bottom: 0;
   background: var(--isl-surface);
}
body.gdv .tableau_chps:is(.table_theme, .matable, .gu-history-table, .tableau_lst_arts) > tbody > tr.gdv-doc-tot-debut > td {
   border-top: 2px solid var(--isl-border-strong);
   padding-top: 10px;
}
body.gdv .tableau_chps:is(.table_theme, .matable, .gu-history-table, .tableau_lst_arts) > tbody > tr.gdv-doc-tot > td.gdv-doc-tot-lib {
   text-align: right;
   color: var(--isl-muted);
   font-weight: 600;
   padding-right: var(--isl-s3);
   white-space: nowrap;
}
body.gdv .tableau_chps:is(.table_theme, .matable, .gu-history-table, .tableau_lst_arts) > tbody > tr.gdv-doc-tot > td.gdv-doc-tot-mt {
   text-align: right;
   font-weight: 700;
   font-variant-numeric: tabular-nums;
   white-space: nowrap;
}
/* Le net a payer est le seul montant sur lequel on s'engage : c'est le seul
   a porter l'accent, et il est d'un cran plus gros. */
body.gdv .tableau_chps:is(.table_theme, .matable, .gu-history-table, .tableau_lst_arts) > tbody > tr.gdv-doc-tot-net > td {
   background: var(--isl-accent-soft);
   border-top: 1px solid var(--isl-accent-border);
   padding-top: 9px;
   padding-bottom: 9px;
}
body.gdv .gdv-doc-tot-net .gdv-doc-tot-lib { color: var(--isl-fg); font-weight: 700; }
body.gdv .gdv-doc-tot-net .gdv-doc-tot-mt { font-size: var(--isl-fs-md); color: var(--isl-accent-text); }
/* Le montant du net est un CHAMP, pas du texte : la taille posee sur la
   cellule ne le traversait pas - un input ne herite pas de font par defaut,
   et la regle des champs d'une ligne de document le remettait a 13 px. Le
   seul chiffre sur lequel la maison s'engage sortait donc plus petit que
   les lignes d'articles au-dessus, dans un cadre gris de champ verrouille.
   Il est ramene a la taille de sa cellule, sans cadre ni fond tant qu'il
   est en lecture seule - un montant calcule n'est pas une saisie - et le
   cadre revient des qu'il est modifiable, c'est-a-dire en devise etrangere.
   Le selecteur porte [type="text"] pour battre la regle des champs de
   ligne de document, qui est elle aussi qualifiee par l'attribut. */
body.gdv .gdv-doc-tot-net input[type="text"].gdv-doc-tot-chp {
   font-size: var(--isl-fs-md);
   font-weight: 700;
   color: var(--isl-accent-text);
   font-variant-numeric: tabular-nums;
}
body.gdv .gdv-doc-tot-net input[type="text"].gdv-doc-tot-chp[readonly] {
   background: transparent;
   border-color: transparent;
   box-shadow: none;
   padding-right: 0;
}
/* Un pied de tableau ne repond pas au survol : il n'y a pas de ligne a
   suivre du doigt, et la teinte d'accent du survol mangeait celle du net
   a payer. */
body.gdv .tableau_chps:is(.table_theme, .matable, .gu-history-table, .tableau_lst_arts) > tbody > tr.gdv-doc-tot:hover {
   background: transparent;
}
/* Le champ du net a payer garde sa largeur, pas celle du texte qu'il
   contient : une facture a quatre chiffres et une facture a six ne doivent
   pas decaler la colonne des montants d'une ligne a l'autre. */
body.gdv .gdv-doc-tot-chp { width: 11ch; text-align: right; font-weight: 700; }

/* --- la pastille des conditions speciales, dans une ligne de document ----
   Caisse et facture posaient le meme bouton, qui portait le libelle complet
   de la condition dans sa valeur - "REMISE CAVISTE (10%)". La colonne
   Remise doublait ou triplait de largeur des qu'une ligne passait en
   edition, et elle changeait encore d'une condition a l'autre : les
   colonnes suivantes ne tombaient plus jamais au meme endroit. C'est une
   pastille carree, de largeur constante quel que soit le libelle, et le
   libelle est dans la bulle d'isl-ui (.isl-tip).
   La pastille porte son apparence en entier, bordure et curseur compris.
   La regle generale des boutons s'exclut elle-meme sur
   :not([class*="gdv-"]) : tout ce qui est nomme en gdv- est cense etre un
   morceau de coque qui se peint seul. Un bouton metier nomme en gdv- sort
   donc du lot sans le vouloir - pas de cadre, pas de fond, et surtout pas
   de cursor:pointer, donc une fleche au survol et rien qui dise que c'est
   cliquable. Le piege est le meme que .gdv-nav-item contre .isl-scope a,
   pris par l'autre bout. */
body.gdv .gdv-doc-cs { vertical-align: middle; margin-right: 6px; }
body.gdv .gdv-doc-cs-bton {
   width: 26px;
   min-width: 26px;
   height: 26px;
   padding: 0;
   display: inline-flex;
   align-items: center;
   justify-content: center;
   line-height: 1;
   font-size: 13px;
   cursor: pointer;
   color: var(--isl-muted);
   background: var(--isl-surface);
   border: 1px solid var(--isl-border-strong);
   border-radius: var(--isl-r-sm);
   transition: background var(--isl-t-fast), border-color var(--isl-t-fast),
               color var(--isl-t-fast);
}
body.gdv .gdv-doc-cs-bton:hover {
   color: var(--isl-danger);
   border-color: var(--isl-danger);
   background: var(--isl-danger-soft);
}
/* L'etat pose : une condition s'applique a cette ligne. Le rouge etait sur
   le texte du bouton ; sur une pastille, il tient le fond - c'est ce qui se
   voit d'un coup d'oeil sur un document de quinze lignes. */
body.gdv .gdv-doc-cs-bton.is-on {
   color: var(--isl-on-accent);
   background: var(--isl-danger);
   border-color: var(--isl-danger);
}
body.gdv .gdv-doc-cs-bton.is-on:hover {
   color: var(--isl-on-accent);
   background: var(--isl-danger);
   border-color: var(--isl-fg);
}
/* Quantite differente de 1 : la condition ne s'applique pas. Masquee, pas
   retiree du flux - un display:none ferait sauter le pourcentage d'un cran
   a chaque frappe dans la quantite. */
body.gdv .gdv-doc-cs.gdv-cs-off { visibility: hidden; }
/* La bulle est posee par isl-ui au-dessus de la pastille : elle doit rester
   devant les lignes voisines et devant l'en-tete colle du tableau. */
body.gdv .gdv-doc-cs > span { z-index: 40; }

/* Conditions speciales : une colonne de boutons de pleine largeur. */
body.gdv .gdv-reg-cs { display: flex; flex-direction: column; gap: 8px; min-width: 260px; }
body.gdv .bton_remise_cs {
   min-height: 2.4em;
   font-weight: 700;
   color: var(--isl-danger);
   width: 100%;
}

/* Raccourcis d'articles : une vraie grille, qui se remplit d'elle-meme. */
body.gdv .gdv-pdv-raccourcis {
   display: grid;
   grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
   gap: 10px;
   max-height: 420px;
   overflow: auto;
   padding: 2px;
}
body.gdv .bton_article_racc {
   width: 100%;
   min-height: 60px;
   padding-left: 8px; padding-right: 8px;
   white-space: normal;
}

/* --- la liste de suggestions d'articles ---------------------------------- */

body.gdv .search_art_tab { width: 100%; border-collapse: collapse; table-layout: fixed; }
body.gdv .search_art_title {
   background: var(--isl-surface-2);
   font-weight: 700;
   color: var(--isl-fg);
}
body.gdv .search_art_dispo { font-weight: 700; }
body.gdv .search_art_code { text-align: right; }
body.gdv .search_art_lib  { color: var(--isl-accent-text); }
body.gdv .search_art_prix { text-align: right; font-variant-numeric: tabular-nums; }
body.gdv .search_art_title_stock { text-align: center; width: 70px; }
body.gdv .search_art_det_stock   { text-align: center; width: 70px; color: var(--isl-danger); }

/* Un article bloque dans la liste de suggestions. */
body.gdv .ui-menu-item-wrapper.ui-state-disabled {
   background: var(--isl-danger-soft);
   color: var(--isl-danger);
   font-weight: 700;
}

/* Fond de caisse : le comptage des especes. */
body.gdv .cl_qte_monnaie { text-align: center; }
body.gdv .span_new_fdc { font-weight: 700; color: var(--isl-accent-text); }


/* ==========================================================================
   15. ATTRIBUTS bgcolor= HERITES

   Un attribut bgcolor= ne peut pas contenir var(--isl-...) : c'est du
   HTML 3.2, il n'accepte qu'une couleur litterale. On ne reecrit donc
   pas les modules qui en posent encore - on les rattrape au selecteur
   d'attribut, ce qui rend exactement le meme service et se retire d'un
   bloc le jour ou ces balises disparaissent.

   Les valeurs ci-dessous sont celles reellement presentes dans le code.
   Chacune porte un sens : une ligne d'en-tete, une cellule mise en
   evidence parce que sa valeur n'est pas nulle.
   ========================================================================== */

/* En-tete de tableau. */
body.gdv [bgcolor="#E6E6E6"],
body.gdv [bgcolor="#CCCCCC"] {
   background-color: var(--isl-surface-2) !important;
   color: var(--isl-fg);
}

/* Cellule mise en evidence : du stock, des ventes sur la periode. */
body.gdv [bgcolor="#66FFFF"],
body.gdv [bgcolor="#CCCCFF"] {
   background-color: var(--isl-accent-soft) !important;
   color: var(--isl-accent-text);
}

/* Cellule de total non nul. */
body.gdv [bgcolor="#99FF66"] {
   background-color: var(--isl-success-soft) !important;
   color: var(--isl-success);
}

/* Les <font color> restants. Le selecteur compare la valeur, pas les
   guillemets : color='red' et color="red" tombent tous deux ici. */
body.gdv font[color="blue"] { color: var(--isl-accent-text); }
body.gdv font[color="#555"] { color: var(--isl-muted); }


/* ==========================================================================
   16. QUAND tableau_chps N'EST PAS UN FORMULAIRE

   La classe .tableau_chps sert deux choses tres differentes : la table
   de saisie rendue par tableau_chps(), et les listings de resultats, qui
   la portent aussi - le plus souvent avec .table_theme ou .matable a
   cote. Sans cette section, un listing de mille factures serait rendu
   comme un formulaire : libelles a droite, pas de ligne alternee, pas de
   survol. C'est la combinaison qui tranche, donc elle passe devant.
   ========================================================================== */

body.gdv .tableau_chps.table_theme,
body.gdv .tableau_chps.matable,
body.gdv .tableau_chps.gu-history-table,
body.gdv .tableau_chps.tableau_lst_arts {
   width: 100%;
   margin: 0;
   font-size: var(--isl-fs-data);
}

body.gdv .tableau_chps.table_theme > tbody > tr > th,
body.gdv .tableau_chps.matable > tbody > tr > th,
body.gdv .tableau_chps.gu-history-table > tbody > tr > th,
body.gdv .tableau_chps.tableau_lst_arts > tbody > tr > th,
body.gdv .tableau_chps.table_theme > thead > tr > th,
body.gdv .tableau_chps.matable > thead > tr > th,
body.gdv .tableau_chps.gu-history-table > thead > tr > th,
body.gdv .tableau_chps.tableau_lst_arts > thead > tr > th {
   text-align: left;
   font-size: 11px; font-weight: 700;
   letter-spacing: .05em; text-transform: uppercase;
   color: var(--isl-subtle);
   background: var(--isl-surface-2);
   padding: 9px 10px;
   border-bottom: 1px solid var(--isl-border);
   border-top: 0;
}

body.gdv .tableau_chps.table_theme > tbody > tr > td,
body.gdv .tableau_chps.matable > tbody > tr > td,
body.gdv .tableau_chps.gu-history-table > tbody > tr > td,
body.gdv .tableau_chps.tableau_lst_arts > tbody > tr > td {
   padding: 7px 10px;
   border-bottom: 1px solid var(--isl-border);
   text-align: left;
}

/* Une ligne sur deux, et un survol franc. Sur un listing de mille
   lignes, c'est ce qui empeche de lire le montant de la ligne d'en
   dessous. */
body.gdv .tableau_chps.table_theme > tbody > tr:nth-child(even),
body.gdv .tableau_chps.matable > tbody > tr:nth-child(even),
body.gdv .tableau_chps.gu-history-table > tbody > tr:nth-child(even),
body.gdv .tableau_chps.tableau_lst_arts > tbody > tr:nth-child(even) {
   background: var(--isl-surface-2);
}
body.gdv .tableau_chps.table_theme > tbody > tr:hover,
body.gdv .tableau_chps.matable > tbody > tr:hover,
body.gdv .tableau_chps.gu-history-table > tbody > tr:hover,
body.gdv .tableau_chps.tableau_lst_arts > tbody > tr:hover {
   background: var(--isl-accent-soft);
}

/* La ligne d'en-tete reste visible quand on descend dans la liste. */
body.gdv .tableau_chps.table_theme > tbody > tr:first-child > th,
body.gdv .tableau_chps.matable > tbody > tr:first-child > th,
body.gdv .tableau_chps.gu-history-table > tbody > tr:first-child > th,
body.gdv .tableau_chps.tableau_lst_arts > tbody > tr:first-child > th {
   position: sticky;
   top: var(--gdv-top-h, 62px);
   z-index: 2;
   box-shadow: inset 0 -1px 0 var(--isl-border);
}


/* ==========================================================================
   17. LES TABLEAUX SONT DES PANNEAUX
   Un listing pose a nu sur le fond de page flotte. Un filet et une ombre
   d'un pixel suffisent a lui donner un bord.
   ========================================================================== */

body.gdv .type1,
body.gdv .type2,
body.gdv .table_theme,
body.gdv .matable,
body.gdv .gu-history-table {
   border: 1px solid var(--isl-border);
   box-shadow: var(--isl-sh-1);
}
/* Sauf a l'interieur d'une carte, qui porte deja son propre bord.
   Et sans bord ni coin arrondi a couper, le rognage n'a plus d'objet -
   il coute meme cher : un tableau qui coupe son debordement devient un
   contexte de defilement, et son en-tete collant se fige alors a
   --gdv-top-h du haut de SA boite, qui ne defile jamais. Il se posait
   ainsi sur les premieres lignes, des le chargement et pour toujours.
   C'est la meme mecanique que pour les tableaux en boite .gdv-scroll-x,
   traitee plus bas. */
body.gdv .gu-card .gu-history-table,
body.gdv .isl-card .gu-history-table,
body.gdv .gu-card .table_theme,
body.gdv .isl-card .table_theme {
   border: 0;
   box-shadow: none;
   overflow: visible;
}


/* ==========================================================================
   LA CARTE DE FILTRES REPLIABLE

   Rendue par gdv_filtres() (lib/isl-app.php). Repliee, elle ne montre plus
   que ce qui est filtre ; la recherche avancee passe de quatorze cents
   pixels a quarante, et les resultats arrivent dans l'ecran.
   ========================================================================== */

body.gdv .gdv-filtres {
   background: var(--isl-surface);
   border: 1px solid var(--isl-border);
   border-radius: var(--isl-r);
   margin-bottom: var(--isl-s4);
   overflow: hidden;
}

body.gdv .gdv-filtres-tete {
   display: flex;
   align-items: center;
   gap: var(--isl-s3);
   flex-wrap: wrap;
   padding: 9px var(--isl-s4);
}
/* Deployee, la tete est un en-tete de carte : elle a un filet sous elle.
   Repliee, elle EST la carte - un filet sous la derniere ligne pendrait
   dans le vide. */
body.gdv .gdv-filtres:not(.is-replie) .gdv-filtres-tete {
   border-bottom: 1px solid var(--isl-border);
   background: var(--isl-surface-2);
}

body.gdv .gdv-filtres-titre {
   font-family: var(--isl-font-display);
   font-size: 11.5px; font-weight: 700;
   letter-spacing: .07em; text-transform: uppercase;
   color: var(--isl-accent-text);
   flex: none;
}

body.gdv .gdv-filtres-lst {
   display: flex; align-items: center;
   gap: 6px; flex-wrap: wrap;
   flex: 1 1 auto; min-width: 0;
}
body.gdv .gdv-filtres-aucun {
   flex: 1 1 auto;
   font-size: var(--isl-fs-sm); font-style: italic;
   color: var(--isl-subtle);
}

/* --- une pastille de filtre ---------------------------------------------
   Deux registres dans la meme pastille : l'intitule du filtre en gris, la
   valeur en encre pleine. C'est la valeur qu'on cherche des yeux, pas le
   nom du champ. */
body.gdv .gdv-chip {
   display: inline-flex; align-items: center; gap: 5px;
   max-width: 100%;
   padding: 3px 3px 3px 9px;
   font-size: var(--isl-fs-sm); line-height: 1.5;
   background: var(--isl-accent-soft);
   border: 1px solid var(--isl-accent-border);
   border-radius: var(--isl-r-full);
}
body.gdv .gdv-chip-k { color: var(--isl-muted); flex: none; }
body.gdv .gdv-chip-k::after { content: ":"; }
body.gdv .gdv-chip-v {
   color: var(--isl-accent-text); font-weight: 600;
   overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
   max-width: 28ch;
}

/* La croix est un bouton d'icone : elle remet son remplissage a zero, sinon
   la regle generale "body.gdv button { padding: 9px 17px }" - plus
   specifique qu'une classe seule - en fait une pastille de quarante pixels
   dans une pastille de vingt-quatre. C'est le piege deja documente pour
   .gdv-burger et .gdv-haut. */
body.gdv .gdv-chip-x {
   display: inline-flex; align-items: center; justify-content: center;
   flex: none;
   width: 18px; height: 18px; padding: 0;
   border: 0; border-radius: var(--isl-r-full);
   background: transparent;
   color: var(--isl-muted);
   cursor: pointer;
}
body.gdv .gdv-chip-x:hover {
   background: var(--isl-accent);
   border-color: transparent;
   color: var(--isl-on-accent);
   transform: none;
}

/* --- la bascule ---------------------------------------------------------- */
body.gdv .gdv-filtres-bascule {
   flex: none;
   padding: 5px 13px;
   font-size: var(--isl-fs-sm); font-weight: 600;
   color: var(--isl-accent-text);
   background: transparent;
   border: 1px solid var(--isl-accent-border);
   border-radius: var(--isl-r);
   cursor: pointer;
}
body.gdv .gdv-filtres-bascule:hover {
   background: var(--isl-accent);
   border-color: var(--isl-accent);
   color: var(--isl-on-accent);
   transform: none;
}

body.gdv .gdv-filtres-corps { padding: var(--isl-s4); }
body.gdv .gdv-filtres.is-replie .gdv-filtres-corps { display: none; }

/* Le formulaire est deja centre par .tableau_chps { margin: 0 auto }. */
body.gdv .gdv-filtres-corps .gu-form-actions { margin-top: var(--isl-s4); }

/* Sur un ecran etroit, les pastilles prennent leur propre ligne : un
   intitule, six pastilles et un bouton sur 400 px, c'est illisible. */
@media (max-width: 640px) {
   body.gdv .gdv-filtres-lst { flex: 1 1 100%; order: 3; }
}

/* A l'impression, un filtre replie est un filtre perdu : la feuille de
   resultats doit dire sur quoi elle porte. */
@media print {
   body.gdv .gdv-filtres.is-replie .gdv-filtres-corps { display: none; }
   body.gdv .gdv-filtres-bascule, body.gdv .gdv-chip-x { display: none; }
}


/* ==========================================================================
   18. CE QUI DIT QUE CA TRAVAILLE

   Une barre de trois pixels en haut de l'ecran, au-dessus de tout, y
   compris de la barre du haut collante. Elle ne prend aucune place dans
   la page : elle est posee en fixe, et elle ne recoit jamais le clic.
   ========================================================================== */

body.gdv .gdv-prog {
   position: fixed;
   top: 0; left: 0; right: 0;
   height: 3px;
   z-index: 400;
   pointer-events: none;
   opacity: 0;
   transition: opacity var(--isl-t) ease;
}
body.gdv .gdv-prog.is-on { opacity: 1; }

body.gdv .gdv-prog-fil {
   display: block;
   height: 100%;
   width: 0;
   background: var(--isl-accent);
   box-shadow: 0 0 8px var(--isl-accent);
   transition: width .24s ease-out;
}
/* Le dernier pas, celui qui va au bord, se joue plus vite : arriver
   lentement a 100 % donnerait l'impression que ca traine encore. */
body.gdv .gdv-prog.is-fin .gdv-prog-fil { transition: width .12s ease-out; }

@media (prefers-reduced-motion: reduce) {
   body.gdv .gdv-prog-fil { transition: none; }
}


/* --- le bouton qui vient d'envoyer -------------------------------------- */

/* Il n'est PAS desactive : un <input type="submit"> desactive ne part pas
   au POST, et la moitie des ecrans lisent $_POST['action'] pour savoir ce
   qu'on leur demande. Il est rendu inerte, ce qui ne change rien a ce que
   le formulaire envoie. */
body.gdv .is-gdv-attente {
   position: relative;
   pointer-events: none;
   opacity: .62;
   cursor: progress;
}
body.gdv .is-gdv-attente::after {
   content: "";
   position: absolute;
   right: 7px; top: 50%;
   width: 11px; height: 11px;
   margin-top: -6px;
   border: 2px solid currentColor;
   border-right-color: transparent;
   border-radius: var(--isl-r-full);
   opacity: .8;
   animation: gdv-tourne .6s linear infinite;
}
@keyframes gdv-tourne { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
   body.gdv .is-gdv-attente::after { animation: none; }
}


/* ==========================================================================
   19. LA BARRE D'OUTILS DES LISTINGS
   Tri au clic sur l'en-tete, filtre instantane, compte de lignes. Voir
   js/gdv-app.js pour ce qu'elle refuse d'equiper et pourquoi.
   ========================================================================== */

body.gdv .gdv-lst-outils {
   display: flex;
   align-items: center;
   gap: var(--isl-s3);
   flex-wrap: wrap;
   margin: 0 0 var(--isl-s3);
}

body.gdv .gdv-lst-cherche {
   position: relative;
   display: inline-flex;
   align-items: center;
   flex: 0 1 260px;
   min-width: 170px;
}

/* Les mesures des controles viennent du manifeste : 14 px, 9/11, rayon
   --isl-r. Un champ de filtre qui ne fait pas la hauteur des autres
   champs de l'ecran se voit tout de suite. */
body.gdv .gdv-lst-q {
   width: 100%;
   font: inherit;
   font-size: var(--isl-fs-base);
   padding: 9px 11px;
   color: var(--isl-fg);
   background: var(--isl-surface);
   border: 1px solid var(--isl-border);
   border-radius: var(--isl-r);
}
body.gdv .gdv-lst-q::placeholder { color: var(--isl-subtle); }
body.gdv .gdv-lst-q:focus {
   outline: none;
   border-color: var(--isl-accent);
   box-shadow: 0 0 0 3px var(--isl-ring);
}

body.gdv .gdv-lst-compte {
   font-size: 12px;
   font-weight: 600;
   color: var(--isl-subtle);
   font-variant-numeric: tabular-nums;
}
body.gdv .gdv-lst-outils.is-filtre .gdv-lst-compte { color: var(--isl-accent-text); }

body.gdv .gdv-lst-rien td { padding: 0; }


/* --- l'en-tete qui trie -------------------------------------------------- */

/* La fleche n'apparait qu'au survol tant que la colonne n'est pas celle
   qui trie : douze chevrons gris en permanence font un bandeau de bruit
   au-dessus des donnees. */
body.gdv .gdv-th-tri {
   cursor: pointer;
   user-select: none;
   white-space: nowrap;
}
body.gdv .gdv-th-tri:hover { color: var(--isl-accent-text); }

body.gdv .gdv-th-fleche {
   display: inline-block;
   width: 0; height: 0;
   margin-left: 5px;
   vertical-align: middle;
   border-left: 4px solid transparent;
   border-right: 4px solid transparent;
   border-bottom: 5px solid currentColor;
   opacity: 0;
   transition: opacity var(--isl-t) ease;
}
body.gdv .gdv-th-tri:hover .gdv-th-fleche { opacity: .45; }
body.gdv .gdv-th-tri.is-tri-asc .gdv-th-fleche,
body.gdv .gdv-th-tri.is-tri-desc .gdv-th-fleche { opacity: 1; }
body.gdv .gdv-th-tri.is-tri-desc .gdv-th-fleche {
   border-bottom: 0;
   border-top: 5px solid currentColor;
}
body.gdv .gdv-th-tri.is-tri-asc,
body.gdv .gdv-th-tri.is-tri-desc { color: var(--isl-accent-text); }

/* Au papier, ni la barre d'outils ni les fleches n'ont de sens. */
@media print {
   body.gdv .gdv-lst-outils,
   body.gdv .gdv-th-fleche,
   body.gdv .gdv-prog { display: none !important; }
}


/* ==========================================================================
   20. LES RECENTS DE LA PALETTE
   Six entrees avant les quatre-vingt-dix-huit. Le meme dessin que la
   liste complete : ce sont les memes entrees, clonees.
   ========================================================================== */

body.gdv .gdv-pal-rec {
   padding: 6px 6px 0;
   border-bottom: 1px solid var(--isl-border);
}

body.gdv .gdv-pal-titre {
   padding: 7px 10px 5px;
   font-size: 10.5px;
   font-weight: 700;
   letter-spacing: .06em;
   text-transform: uppercase;
   color: var(--isl-subtle);
}


/* --- les groupes de la liste complete ------------------------------------ */
/* Chaque sous-menu est range sous son menu : le titre de groupe porte le
   chemin, l'entree ne porte plus que son nom. Le titre COLLE en haut de
   la boite a defilement - c'est le seul moyen de savoir dans quelle
   section on se trouve apres vingt lignes de defilement. Il saigne sur
   les 6 px de marge de la liste (marges negatives), sinon les entrees
   defileraient visiblement de part et d'autre de lui.

   Ce sticky-la est a top: 0 et non a var(--gdv-top-h) : il colle au haut
   de SA boite a defilement, dans une fenetre modale posee par-dessus la
   page, pas sous la barre du haut.

   Le titre de section porte la couleur d'accent, la ou "Recents" et
   "Tous les ecrans" restent gris : ces deux-la nomment un bloc, un titre
   de section nomme une COUPURE. En gris comme le reste, il se noyait dans
   la liste - il faut le distinguer des entrees qu'il coiffe, pas
   seulement les separer d'un filet.

   Le jeton est --isl-accent-text et non --isl-accent : c'est celui dont
   la paire avec --isl-surface est controlee en AA par l'ecran de charte
   ("Texte d'accent sur carte"), dans les deux modes. Le fond reste la
   surface : un bandeau en --isl-accent-soft ici aurait exactement l'air
   de l'entree survolee, juste au-dessous. */
body.gdv .gdv-pal-grp-titre {
   position: sticky;
   top: 0;
   z-index: 1;
   margin: 0 -6px;
   padding: 7px 16px 5px;
   background: var(--isl-surface);
   color: var(--isl-accent-text);
}

/* Un filet entre deux sections. Pas au-dessus de la premiere : elle suit
   deja soit le bord de la boite, soit le titre "Tous les ecrans". */
body.gdv .gdv-pal-grp + .gdv-pal-grp .gdv-pal-grp-titre {
   margin-top: 5px;
   padding-top: 10px;
   border-top: 1px solid var(--isl-border);
}

/* Le ou les niveaux au-dessus du dernier, dans un chemin a deux etages :
   presents pour lever l'ambiguite, effaces pour que l'oeil accroche le
   nom de la section. */
body.gdv .gdv-pal-grp-haut { opacity: .62; }

/* Le chemin repete sur chaque entree n'a plus lieu d'etre : il est
   au-dessus, une fois. Il reste en revanche sur les clones du bloc des
   recents, qui eux sont hors de tout groupe. */
body.gdv .gdv-pal-liste .gdv-pal-chemin { display: none; }


/* --- le pied de la palette ---------------------------------------------- */
/* Les touches ne sont ecrites nulle part ailleurs. On les met la ou l'on
   est deja, et assez discretement pour ne pas concurrencer la liste. */

body.gdv .gdv-pal-pied {
   display: flex;
   gap: var(--isl-s4);
   flex-wrap: wrap;
   padding: 8px 14px;
   border-top: 1px solid var(--isl-border);
   background: var(--isl-surface-2);
   font-size: 11px;
   color: var(--isl-subtle);
   border-radius: 0 0 var(--isl-r-lg) var(--isl-r-lg);
}
body.gdv .gdv-pal-pied span { display: inline-flex; align-items: center; gap: 5px; }
body.gdv .gdv-pal-pied kbd {
   font: inherit; font-size: 10.5px;
   padding: 1px 5px;
   color: var(--isl-muted);
   border: 1px solid var(--isl-border);
   border-radius: 4px;
   background: var(--isl-surface);
}
@media (max-width: 520px) {
   body.gdv .gdv-pal-pied { display: none; }
}


/* ==========================================================================
   21. LE TELEPHONE

   L'application se travaille au comptoir, sur 1280 ou 1920. Mais il
   arrive qu'un telephone soit le seul appareil sous la main - un
   inventaire dans la cave, une facture a retrouver chez un client, un
   reglement a saisir depuis la route. Ce bloc ne redessine rien : il
   fait tenir ce qui existe deja dans 390 pixels, sans qu'un seul pixel
   bouge au-dessus de 760.

   Trois principes, dans cet ordre :

   1. La COQUE se replie. Sous 640 px la colonne de navigation sort
      entierement de l'ecran - un rail de 62 px, c'est 16 % d'un
      telephone donnes a des icones qui ont perdu leur libelle. Le
      burger l'ouvre en tiroir, et la regle du tiroir existe deja a
      1100 px : il n'y a qu'a la laisser descendre.
   2. Les FORMULAIRES s'empilent. tableau_chps() rend un tableau de
      deux a six colonnes ; sur un telephone, chaque libelle passe
      au-dessus de son champ et le champ prend la largeur.
   3. Les LISTINGS defilent dans leur boite, jamais dans la page. Une
      facture a onze colonnes ne rentrera jamais dans 390 px et on ne
      va pas la reinventer : elle defile lateralement, la coque reste
      en place. C'est le compromis assume - un peu de defilement
      horizontal vaut mieux qu'un ecran a moitie reecrit.

   Ce qui n'est PAS ici : les print_*.php et les pdf_*.php. C'est du
   papier, et le papier n'a pas de largeur de fenetre.
   ========================================================================== */


/* --- 21.1 la boite a defilement ------------------------------------------
   Posee par js/gdv-mobile.js autour des tableaux trop larges, a TOUTES les
   largeurs. Elle a longtemps ete reservee au telephone, et c'etait le
   defaut : un navigateur pose sur la moitie d'un ecran fait huit cents
   pixels, le seuil de 760 px passait juste en dessous, et le tableau
   sortait de sa carte sans que rien ne le rattrape. Ce qui borne la boite
   n'est pas une largeur de fenetre mais la mesure du debordement : sur
   1920 px rien ne deborde, donc le bureau ne voit toujours pas cette
   classe. Elle est retiree a chaque remesure, sinon un poste passe en
   fenetre etroite puis rendu plein ecran gardait ses boites. */

body.gdv .gdv-scroll-x {
   max-width: 100%;
   overflow-x: auto;
   -webkit-overflow-scrolling: touch;
   overscroll-behavior-x: contain;
}
/* Le tableau garde sa largeur naturelle DANS la boite : c'est la boite
   qui defile, pas la page. */
body.gdv .gdv-scroll-x > table { max-width: none; }

/* Les popups centrent leur tableau sur le body ; avec la boite au milieu,
   c'est a la boite de le centrer. */
body.gdv-popup > .gdv-scroll-x > table { margin: 0 auto; }

/* L'en-tete collant est rendu a la page des qu'un listing entre en boite.
   overflow-x: auto n'existe pas seul - le navigateur calcule overflow-y a
   "auto" avec lui - donc la boite devient le contexte de defilement, et un
   en-tete en position: sticky s'y fige sur le haut de la boite au lieu du
   haut de la page : une ligne d'en-tete arretee au milieu du tableau, avec
   son ombre. Mieux vaut qu'il redevienne une ligne comme les autres. Cette
   regle ne coute rien au bureau ordinaire : sans debordement, pas de boite,
   et l'en-tete continue de coller a la barre du haut.

   La troisieme ligne de selecteur n'est pas un doublon. Les listings qui
   portent .tableau_chps EN PLUS de leur classe de famille posent leur
   en-tete collant avec quatre classes (section 16 : .gdv .tableau_chps
   .gu-history-table :first-child, soit 0,4,4). Les deux lignes au-dessus
   n'en ont que trois (0,3,5) et PERDAIENT : en boite, ces en-tetes-la
   restaient collants, se figeaient a --gdv-top-h du haut de LEUR boite -
   qui ne defile jamais verticalement, faute de hauteur bornee - et
   descendaient donc de la hauteur de la barre du haut une fois pour
   toutes. Ils se posaient sur la premiere ligne du tableau, masquee des le
   chargement et pour toujours, en laissant un bandeau vide au-dessus.
   Trente-six tableaux, sur vingt-trois ecrans, etaient dans ce cas :
   recherche d'articles, de clients et de factures, les historiques,
   l'inventaire, les mouvements, le rapport journalier, les tableaux de
   bord.
   .gdv-scroll-x est repete pour reprendre la main sans !important - (0,5,5)
   contre (0,4,4) - et la regle ne vise toujours que ce qui est en boite. */
body.gdv .gdv-scroll-x > table > thead > tr > th,
body.gdv .gdv-scroll-x > table > tbody > tr:first-child > th,
body.gdv .gdv-scroll-x.gdv-scroll-x > table.tableau_chps > tbody > tr:first-child > th {
   position: static;
}


@media (max-width: 760px) {

   /* Sur un telephone, une cellule ne revient pas a la ligne. Un tableau
      qui defile deja n'a rien a gagner a se casser en hauteur :
      "Restaurant Le Tamarin" sur trois lignes, c'est une ligne de listing
      haute de soixante pixels, et vingt-deux factures qui font un ecran et
      demi de defilement vertical pour dire ce qui tiendrait en dix lignes.
      On accepte deux cents pixels de plus en largeur - ils sont derriere
      un geste - pour rendre le tableau lisible d'un coup d'oeil.

      La regle ne vaut QUE la, et c'est pour cela qu'elle est descendue
      ici. Depuis que la boite se pose a toutes les largeurs, un nowrap
      permanent la retournerait contre elle-meme : la colonne "Details" de
      l'historique d'article, qui se casse aujourd'hui sur trois lignes
      lisibles, partirait sur une seule de deux mille pixels. Sur un demi-
      ecran on veut que le tableau se resserre d'abord, et qu'il ne defile
      que de ce qui reste.

      Un champ de saisie garde son propre retour a la ligne : white-space
      ne traverse pas la frontiere d'un <textarea>. */
   body.gdv .gdv-scroll-x > table > tbody > tr > td,
   body.gdv .gdv-scroll-x > table > tbody > tr > th,
   body.gdv .gdv-scroll-x > table > thead > tr > th { white-space: nowrap; }

   /* --- 21.2 la barre du haut -------------------------------------------
      Elle porte cinq choses. Sur 390 px elle passerait a trois lignes et
      mangerait le quart de l'ecran - et comme --gdv-top-h la mesure, tout
      ce qui colle en dessous descendrait d'autant. */

   /* Du fil d'Ariane on ne garde que le dernier niveau : le nom de
      l'ecran. Les niveaux au-dessus sont dans le tiroir, a un geste. */
   body.gdv .gdv-fil a,
   body.gdv .gdv-fil span,
   body.gdv .gdv-fil svg { display: none; }
   body.gdv .gdv-fil strong {
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
      max-width: 100%;
   }
   body.gdv .gdv-top { gap: var(--isl-s3); padding: 6px var(--isl-s4); min-height: 52px; }
   body.gdv .gdv-soc select { max-width: 30vw; }

   /* Le bandeau d'alertes : une ligne qui defile, pas un pave de six
      pastilles qui repousse le contenu sous la ligne de flottaison. */
   body.gdv .gdv-alertes {
      flex-wrap: nowrap;
      overflow-x: auto;
      scrollbar-width: none;
      padding: 8px var(--isl-s4);
   }
   body.gdv .gdv-alertes::-webkit-scrollbar { display: none; }
   body.gdv .gdv-pill { flex: none; }

   body.gdv .gdv-foot { flex-direction: column; align-items: flex-start; gap: 6px; }
   body.gdv .gdv-foot .gdv-foot-right { margin-left: 0; }

   /* Le bouton "remonter en haut" se decale du bord : sur un telephone,
      les quinze derniers pixels appartiennent au geste de retour arriere
      du navigateur. */
   body.gdv .gdv-haut { right: 12px; bottom: 14px; }


   /* --- 21.3 les formulaires s'empilent ---------------------------------
      Un formulaire, c'est .tableau_chps SEULE. Combinee a .table_theme,
      .matable, .gu-history-table ou .tableau_lst_arts, c'est un listing,
      et un listing ne s'empile pas : il defile (21.5). Le tri est fait
      une fois pour toutes par js/gdv-app.js, qui pose .gdv-chps-empile -
      une classe vaut mieux qu'une chaine de quatre :not(), dont la
      specificite (0,5,0) ecraserait des regles legitimes. */
   body.gdv .gdv-chps-empile,
   body.gdv .gdv-chps-empile > tbody,
   body.gdv .gdv-chps-empile > tbody > tr,
   body.gdv .gdv-chps-empile > tbody > tr > th,
   body.gdv .gdv-chps-empile > tbody > tr > td {
      display: block;
      width: auto;
      max-width: 100%;
   }
   /* Le libelle colle a son champ, et le champ respire jusqu'au suivant. */
   body.gdv .gdv-chps-empile > tbody > tr > th {
      padding: 10px 0 3px;
      text-align: left;
      background: none;
      border: 0;
   }
   body.gdv .gdv-chps-empile > tbody > tr > td { padding: 0 0 4px; border: 0; }
   /* Les cellules d'espacement ne valent plus une ligne entiere. */
   body.gdv .gdv-chps-empile > tbody > tr > td.vide { padding: 3px 0; }
   /* Un titre de section garde son bandeau : c'est ce qui redonne des
      groupes a un formulaire devenu une seule colonne. Il faut le viser
      par son [colspan] comme le fait la regle de bureau, sinon elle
      l'emporte - (0,3,2) contre (0,2,4) - et le bandeau reste peint
      sous un titre qu'on aurait decale de vingt-quatre pixels : une
      bande vide en haut de chaque groupe. */
   body.gdv .gdv-chps-empile > tbody > tr > th[colspan]:not(.th_action) {
      margin-top: var(--isl-s4);
      padding: 8px 11px;
      background: var(--isl-surface-2);
      border-top: 1px solid var(--isl-border);
      border-bottom: 1px solid var(--isl-border);
      border-radius: var(--isl-r-sm);
   }
   body.gdv .gdv-chps-empile > tbody > tr:first-child > th[colspan]:not(.th_action) { margin-top: 0; }

   /* Empile, un champ prend la largeur. Les mesures du manifeste - 14 px,
      remplissage 9/11, 40 px de haut - ne bougent pas : seule la largeur
      change, et c'est aussi ce qui donne une cible au doigt. */
   body.gdv .gdv-chps-empile input[type="text"],
   body.gdv .gdv-chps-empile input[type="password"],
   body.gdv .gdv-chps-empile input[type="number"],
   body.gdv .gdv-chps-empile input[type="email"],
   body.gdv .gdv-chps-empile input[type="tel"],
   body.gdv .gdv-chps-empile select,
   body.gdv .gdv-chps-empile textarea {
      width: 100%;
      max-width: 100%;
      box-sizing: border-box;
   }
   /* Le declencheur de liste cherchable perd son plancher de 210 px :
      sur 390 px de large, un plancher est un debordement. */
   body.gdv .gdv-chps-empile .isl-ctl {
      width: 100%;
      min-width: 0;
      max-width: 100%;
   }
   /* La date garde ses dix caracteres - elle n'a pas de largeur variable,
      c'est ecrit dans le CLAUDE.md et ca reste vrai sur un telephone. */
   body.gdv .gdv-chps-empile .gdv-date { width: auto; min-width: 0; }
   body.gdv .gdv-chps-empile .gdv-chp-zone { max-width: 100%; }

   /* Les boutons d'un formulaire s'etalent : viser "Enregistrer" a cote
      d'"Annuler" sur 390 px, c'est viser soixante pixels. */
   body.gdv .gu-form-actions > .gu-btn,
   body.gdv .gu-form-actions > .isl-btn,
   body.gdv .gu-form-actions > input[type="submit"],
   body.gdv .gu-form-actions > input[type="button"],
   body.gdv .gu-form-actions > button { flex: 1 1 170px; }


   /* --- 21.4 les conteneurs ---------------------------------------------- */

   /* La marge du panneau se resserre : 24 px de chaque cote sur 390, c'est
      un huitieme de l'ecran donne au vide. */
   .gu-container { padding: var(--isl-s3); }

   body.gdv .isl-pagehead { gap: var(--isl-s3); padding-bottom: var(--isl-s3); margin-bottom: var(--isl-s4); }
   body.gdv .isl-pagehead h1 { font-size: var(--isl-fs-xl); }

   /* La boite de suggestions d'un champ de recherche rend un tableau a
      colonnes fixes - code, libelle, millesime, format, prix : 475 px.
      Elle defile, elle ne deborde pas. */
   body.gdv .gdv-suggest { overflow-x: auto; }
   body.gdv .search_art_lib { width: auto; max-width: 42vw; }


   /* --- 21.5 les listings defilent, la page non -------------------------- */

   /* Les largeurs heritees en pixels - <table width="900"> - datent d'un
      ecran de 1024. Elles ne servent qu'a empecher le tableau de se
      resserrer ; on les rend a "auto" pour qu'il prenne la place de son
      contenu, ni plus ni moins. Les largeurs en POURCENT sont laissees
      tranquilles : width="100%" veut dire "prends la place", et c'est
      exactement ce qu'on veut ici. */
   body.gdv table[width]:not([width$="%"]) { width: auto; max-width: 100%; }

   /* L'en-tete collant est rendu a la page. Dans une boite a defilement il
      ne colle a rien - la boite devient le contexte de defilement et
      l'en-tete se fige sur son propre haut, donc hors de vue. Et sur un
      telephone, la barre du haut prend deja la hauteur qu'il aurait
      occupee. */
   body.gdv .tableau_chps.table_theme > tbody > tr:first-child > th,
   body.gdv .tableau_chps.matable > tbody > tr:first-child > th,
   body.gdv .tableau_chps.gu-history-table > tbody > tr:first-child > th,
   body.gdv .tableau_chps.tableau_lst_arts > tbody > tr:first-child > th,
   body.gdv .type1 thead th,
   body.gdv .type2 thead th,
   body.gdv .table_theme thead th,
   body.gdv .matable thead th,
   body.gdv .gu-history-table thead th {
      position: static;
   }

   /* La barre d'outils d'un listing : le champ de filtrage prend la
      largeur, le compte et le tri passent dessous. */
   body.gdv .gdv-lst-cherche { flex: 1 1 100%; }


   /* --- 21.6 les pages autonomes ------------------------------------------
      Fenetres de reglement, fiche article, l.php, saisie sur tablette.
      Elles s'ouvrent par window.open() avec une taille en dur ; sur un
      telephone le navigateur l'ignore et rend un onglet plein ecran.
      Depuis gdv_head_isl(), elles portent enfin un <meta viewport> -
      sans lui, le telephone les rendait dans une fenetre virtuelle de
      980 px puis reduisait le tout a la loupe. */
   body.gdv-popup { padding: var(--isl-s3); }
   body.gdv-popup .gu-container { padding: var(--isl-s3); }
}


/* --- 21.7 sous 640 : la colonne sort de l'ecran --------------------------- */

@media (max-width: 640px) {
   body.gdv .gdv-side { display: none; }

   html.is-drawer body.gdv .gdv-side {
      display: flex;
      /* Un tiroir qui couvre tout l'ecran ne dit plus qu'il est un
         tiroir : on laisse voir la page dessous. */
      --gdv-side-w: min(280px, 84vw);
   }

   /* La barre du haut est collante a z-index 30, le voile est a 39 : sans
      cette ligne, la barre reste nette au-dessus du voile et le tiroir a
      l'air ouvert par-dessus rien. */
   html.is-drawer body.gdv .gdv-top { z-index: 10; }

   body.gdv .gdv-top, body.gdv .gdv-alertes, body.gdv .gdv-main, body.gdv .gdv-foot {
      padding-left: var(--isl-s3); padding-right: var(--isl-s3);
   }
   body.gdv .gdv-main { padding-top: var(--isl-s4); }

   /* Le selecteur de societe porte des noms longs ; sur cette largeur il
      ne reste de place que pour lui ou pour le fil d'Ariane. Le fil
      gagne : il dit ou l'on est. L'icone metier part avec : le chevron
      suffit a dire que c'est une liste, et elle rendait vingt pixels. */
   body.gdv .gdv-soc select { max-width: 124px; padding: 0 25px 0 10px; }
   body.gdv .gdv-soc-ico { display: none; }
   body.gdv .gdv-soc-caret { right: 8px; }

   /* Pas de clavier a montrer sur un telephone. */
   body.gdv .gdv-side-search kbd { display: none; }
   body.gdv .gdv-pal-head kbd { display: none; }
}


/* --- 21.8 la caisse -------------------------------------------------------
   Le pave de reglement passe deja sous le panier a 1100 px. Reste le
   tableau des lignes de ticket : sept colonnes dont trois de saisie, il
   ne se resserre pas et il est exclu de l'enrobage automatique (il porte
   data-gdv-sans-vide et sa propre attente). Sa boite est donc posee ici,
   en dur. */

@media (max-width: 560px) {
   body.gdv .gdv-pdv-pave { width: auto; }
   body.gdv .gdv-pdv-total-v { font-size: 24px; }
   body.gdv .gdv-pdv-cli-champ { min-width: 0; flex: 1 1 100%; }

   body.gdv .gdv-pdv-panier { overflow-x: auto; }
   body.gdv .gdv-pdv-lignes { min-width: 500px; }

   /* Le bandeau passe sur une colonne. A 900 px il en garde deux - les
      tickets ouverts, puis la touche "+" a droite ; sous 560 cette
      touche prend cent pixels sur les deux cent quatre-vingts qui
      restent, et une pastille de ticket n'a plus la place d'afficher le
      nom du client sur une ligne. La touche passe donc dessous, ou elle
      est aussi plus facile a viser. */
   body.gdv .gdv-pdv-bandeau { grid-template-columns: minmax(0, 1fr); }
   body.gdv .gdv-pdv-neuf { justify-content: stretch; }
   body.gdv .gdv-pdv-neuf .bton_action { width: 100%; }
}


/* --- 21.9 les fenetres de jQuery UI ---------------------------------------
   Dix ecrans ouvrent une .dialog() dont la largeur est ecrite en dur dans
   le module : 520, 550, 580, 730. Sur 390 px, une fenetre de 550 sort de
   l'ecran des deux cotes a la fois.

   Un max-width suffit, et il n'a pas besoin d'!important : une largeur
   posee en ligne par le widget ne l'emporte JAMAIS sur un max-width de
   la feuille, c'est la definition meme de la propriete. Et comme jQuery
   UI mesure l'element APRES l'avoir habille pour decider ou le poser,
   sa strategie "fit" recentre la fenetre sur la largeur bornee.

   La regle n'est pas dans un @media : une fenetre plus large que l'ecran
   est un defaut a toutes les largeurs - c'est simplement sur 1920 px que
   personne ne le rencontre. */

body.gdv .ui-dialog { max-width: calc(100vw - 16px); }
body.gdv .ui-autocomplete { max-width: calc(100vw - 16px); }

@media (max-width: 760px) {
   /* Le contenu d'une fenetre porte souvent un tableau - la liste des
      factures d'un client, les lignes d'un inventaire. Il defile dans la
      fenetre, qui ne bouge pas. */
   body.gdv .ui-dialog .ui-dialog-content { overflow-x: auto; padding: 12px 14px !important; }
   body.gdv .ui-dialog .ui-dialog-titlebar { padding: 10px 14px !important; }
}


/* ==========================================================================
   22. LA FACTURE SUR UN TELEPHONE

   L'ecran "Creer facture" pose sa vraie grille de donnees au fond de deux
   tableaux de MISE EN PAGE herites : <table width="90%"> puis
   <table width="100%">, et seulement ensuite le tableau des lignes. Aucun
   des trois ne peut etre mis en boite par js/gdv-mobile.js, et pour une
   raison qui n'est pas un oubli : ce script enrobe un tableau quand il est
   plus large que SON PARENT, or le parent d'un tableau imbrique est une
   cellule, et une cellule s'elargit avec son contenu. Le debordement n'est
   donc visible nulle part dans la chaine - il ressort tout en haut, sur la
   page, qui partait en defilement horizontal avec la barre du haut et le
   fil d'Ariane.

   Sous 760 px, les deux tableaux de mise en page cessent donc d'etre des
   tableaux : ils n'ont jamais porte que des cellules empilees les unes sous
   les autres. Ce qui reste - le tableau des lignes, lui une vraie grille -
   defile alors dans sa propre boite, et la page ne bouge plus.

   Rien de tout cela n'existe au-dessus de 760 px : un poste de comptoir ou
   une tablette de cave a 800 px voit exactement ce qu'il voyait.
   ========================================================================== */

@media (max-width: 760px) {

   body.gdv .gdv-doc-mep,
   body.gdv .gdv-doc-mep > tbody,
   body.gdv .gdv-doc-mep > tbody > tr,
   body.gdv .gdv-doc-mep > tbody > tr > td {
      display: block;
      width: auto;
      max-width: 100%;
      padding-left: 0;
      padding-right: 0;
   }

   /* Le tableau des lignes reste une grille - sept colonnes dont trois de
      saisie, il n'y a rien a empiler la-dedans - mais il defile dans sa
      boite. display: block sur un <table> en fait un bloc qui peut rogner
      son debordement ; les rangees se remettent d'elles-memes dans une
      table anonyme, donc les colonnes restent alignees. */
   body.gdv .gdv-doc-lignes {
      display: block;
      overflow-x: auto;
      -webkit-overflow-scrolling: touch;
      max-width: 100%;
   }

   /* Dans une boite a defilement, un en-tete collant se fige sur le haut de
      LA BOITE, donc hors de vue. C'est la meme regle que pour les autres
      listings sous 760 px : il est rendu a la page. */
   body.gdv .gdv-doc-lignes > tbody > tr:first-child > th {
      position: static;
   }

   /* Une cellule de document ne revient pas a la ligne dans une boite qui
      defile deja : un nom d'article sur quatre lignes fait un ecran de
      defilement vertical pour dire ce qui tient en deux. */
   body.gdv .gdv-doc-lignes > tbody > tr > td { white-space: nowrap; }
   body.gdv .gdv-doc-lib { white-space: normal; min-width: 22ch; }

   /* L'en-tete du document et les documents en cours passent deja sur une
      colonne (grid-template-columns plus haut) ; il ne reste qu'a rendre au
      commentaire toute la largeur. */
   body.gdv .gdv-doc-com-chp { flex: 1 1 100%; }
}
