/* ===========================================================================
   EASYTIME — Shell applicatif (sidebar + topbar + onglets, thème clair/sombre)
   Porté fidèlement depuis la maquette "Layout easyTime".
   =========================================================================== */

.appgrid {
    display: grid;
    grid-template-columns: 256px 1fr;
    grid-template-rows: 56px 1fr;
    height: 100vh; min-height: 640px;
    font-family: var(--et-font);
    /* LES JETONS DE LA COQUILLE POINTENT TOUS SUR LA CHARTE, ET ILS SONT DÉFINIS ICI
       UNE SEULE FOIS — voir le bloc supprimé sous .appgrid[data-theme="dark"] plus bas,
       et celui supprimé de rail-lateral.css.

       Ce fichier portait deux jeux complets de littéraux, un par thème, hérités de la
       maquette « Layout easyTime ». rail-lateral.css en a reporté douze sur la charte le
       2026-08-17 — mais en le disant lui-même : « le bloc sombre d'easytime-shell.css
       reste maître, sa spécificité (0,2,0) l'emporte sur le sélecteur de classe nu employé
       ici (0,1,0) ». LE PORTAGE NE S'APPLIQUAIT DONC QU'EN THÈME CLAIR. Le thème sombre
       tournait encore intégralement sur les littéraux d'avant la charte, sans que rien ne
       le signale — un bloc plus spécifique ne produit pas d'erreur, il gagne.

       Les jetons ci-dessous BASCULENT tous d'eux-mêmes : plus rien à redéfinir en sombre,
       donc plus de bloc à tenir aligné, donc plus de guerre de spécificité. */
    --app-bg: var(--et-surface-2); --side-bg: var(--et-surface);
    --side-border: var(--et-hairline); --muted: var(--et-muted);
    --item-text: var(--et-ink); --item-icon: var(--et-muted);
    /* ENCRE ET NON APLAT, d'où --et-form-blue-encre : --et-form-blue est
       délibérément hors du bloc sombre (il habille 144 aplats qu'un éclaircissement
       repeindrait), donc il ne bascule pas, et c'est précisément pour cela que le bloc
       sombre écrivait #5cb0ec ici — TROIS FOIS. La charte a un mot pour ce cas : « en
       sombre #8FB4F0, le thème n'invente pas un huitième bleu ». #5cb0ec était ce
       huitième bleu. */
    --item-active-text: var(--et-form-blue-encre); --item-active-icon: var(--et-form-blue-encre);
    --item-active-bg: var(--et-tint);
    --row-hover: var(--et-surface-3);
    --crumb-link: var(--et-form-blue-encre); --crumb-current: var(--et-ink);
    --tabbar-bg: var(--et-surface-2); --tab-border: var(--et-hairline);
    --tab-bg: var(--et-surface-3); --tab-text: var(--et-muted);
    --tab-active-bg: var(--et-surface); --tab-active-text: var(--et-ink);
    --ph-bg: var(--et-surface); --ph-border: var(--et-hairline);
    --ph-icon-bg: var(--et-tint);
    /* --crumb-muted, --ph-title et --ph-text ne sont PAS repris : ils étaient définis
       dans les deux blocs et lus NULLE PART. Six déclarations mortes. */
    --item-py:5px; --tab-py:9px;
}
/* PAS DE BLOC .appgrid[data-theme="dark"] ICI, ET C'EST L'OBJET DU LOT. Il en portait
   un, vingt-quatre déclarations qui repeignaient à la main ce que les jetons ci-dessus
   font déjà — et qui, par sa spécificité, annulaient en sombre le portage à la charte
   fait en clair. Deux de ses lignes étaient déjà la valeur exacte du jeton
   (--crumb-current et --tab-active-text écrivaient #e5edf5, qui EST --et-ink en sombre) :
   la duplication se voyait à l'œil nu dans le fichier. */
.appgrid[data-compact="true"] { --item-py:5px; --tab-py:6px; }
.appgrid[data-collapsed="true"] { grid-template-columns: 64px 1fr; }

/* --- Barre supérieure --- */
.et-topbar {
    grid-column: 1 / -1; display: flex; align-items: center; gap: 12px;
                                                                                                                                                                                                                                                                                                                            
    --et-topbar-px: 16px;
    padding: 0 var(--et-topbar-px);
                                                                                                                                                                                                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
    background: var(--et-blue);
    color: var(--et-sur-marine); z-index: 10; border-bottom: 3px solid var(--et-action);
}
.et-brand { display: flex; align-items: center; gap: 10px; flex-shrink: 0; text-decoration: none; }
.et-brand .ico { display: inline-flex; align-items: center; justify-content: center; width: 38px; height: 38px; background: var(--et-plaque-logo); flex-shrink: 0; }
.et-brand .ico img { width: 27px; height: 27px; display: block; }
.et-brand .txt { font-size: 20px; font-weight: 700; letter-spacing: -.01em; color: var(--et-sur-marine); white-space: nowrap; }
.et-brand .txt span { color: var(--et-action); }
.et-ctrl {
    display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px;
    background: transparent; border: none; color: var(--et-sur-marine-doux); cursor: pointer; transition: background .15s;
}
.et-ctrl:hover { background: var(--et-fond-marine-survol); color: var(--et-sur-marine); }
.et-search { position: relative; width: 220px; flex-shrink: 0; }
.et-search .lp { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: var(--et-sur-marine-doux); display: inline-flex; pointer-events: none; }
.et-search input {
    width: 100%; padding: 7px 10px 7px 32px; font-size: 13px; font-family: inherit; color: var(--et-sur-marine);
    background: var(--et-fond-marine); border: 1px solid var(--et-filet-marine); border-radius: 0; outline: none;
}
.et-search input::placeholder { color: var(--et-sur-marine-faible); }
/* Le filet de FOCUS est une encre, pas un fond : il doit se lire d'un coup d'oeil,
   la ou le filet au repos ne doit que delimiter. C'est la seule fois ou les deux
   familles se croisent, et c'est delibere. */
.et-search input:focus { background: var(--et-fond-marine-survol); border-color: var(--et-sur-marine-faible); }
.et-user { display: flex; align-items: center; gap: 9px; padding-left: 12px; border-left: 1px solid var(--et-filet-marine); flex-shrink: 0; cursor: pointer; position: relative; }
.et-user .av { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: 50%; background: var(--et-fond-marine); font-size: 12px; font-weight: 600; }
.et-user .n1 { font-size: 13px; font-weight: 600; }
.et-user .n2 { font-size: 12px; color: var(--et-sur-marine-faible); }

/* --- Barre latérale --- */
.et-side { grid-row: 2; grid-column: 1; background: var(--side-bg); border-right: 1px solid var(--side-border); overflow-y: auto; overflow-x: hidden; padding-bottom: 16px; }
.et-side::-webkit-scrollbar { width: 8px; }
.et-side::-webkit-scrollbar-thumb { background: var(--et-form-border); }
.et-grouphdr {
    width: 100%; display: flex; align-items: center; gap: 6px; padding: 14px 14px 6px;
    font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--muted);
    background: transparent; border: none; cursor: pointer;
}
.et-grouphdr .chev { display: inline-flex; transition: transform .15s; }
.et-grouphdr.closed .chev { transform: rotate(-90deg); }
.et-navrow { display: flex; align-items: center; border-left: 3px solid transparent; transition: background .12s; }
.et-navrow:hover { background: var(--row-hover); }
.et-navrow:hover .et-star { opacity: 1; }
.et-navrow.active { background: var(--item-active-bg); border-left-color: var(--et-form-blue); }
.et-navmain {
    flex: 1; min-width: 0; display: flex; align-items: center; gap: 11px; justify-content: flex-start;
    padding: var(--item-py) 6px var(--item-py) 13px; font-size: 13px; font-weight: 500; font-family: inherit;
    color: var(--item-text); background: transparent; border: none; cursor: pointer; text-decoration: none;
}
.et-navrow.active .et-navmain { color: var(--item-active-text); font-weight: 600; }
.et-navmain .ic { display: inline-flex; flex-shrink: 0; color: var(--item-icon); }
.et-navrow.active .et-navmain .ic { color: var(--item-active-icon); }
.et-navmain .lb { flex: 1; min-width: 0; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.et-star { display: inline-flex; align-items: center; justify-content: center; width: 34px; flex-shrink: 0; align-self: stretch; background: transparent; border: none; cursor: pointer; opacity: 0; transition: opacity .12s; }
.et-star.on { opacity: 1; }
/* Compteur vivant d'une entrée de menu (paramètre Badges de ShellModule) : demandes
   d'équipe en attente, tickets ouverts. Rouge parce qu'il appelle une action, pas
   parce qu'il informe — c'est le seul endroit du menu qui doit accrocher l'œil. */
.et-nav-badge {
    flex-shrink: 0; min-width: 18px; padding: 1px 5px; border-radius: 999px;
    background: var(--et-danger); color: var(--et-sur-aplat); font-size: 12px; font-weight: 700;
    line-height: 1.5; text-align: center; font-variant-numeric: tabular-nums;
}
.appgrid[data-collapsed="true"] .et-nav-badge { display: none; }

/* Sidebar réduite */
.appgrid[data-collapsed="true"] .et-grouphdr { justify-content: center; padding: 14px 0 6px; }
.appgrid[data-collapsed="true"] .et-grouphdr span:first-child,
.appgrid[data-collapsed="true"] .et-grouphdr .chev { display: none; }
.appgrid[data-collapsed="true"] .et-navmain { justify-content: center; gap: 0; padding: 10px 0; }
.appgrid[data-collapsed="true"] .et-navmain .lb,
.appgrid[data-collapsed="true"] .et-star { display: none; }

/* --- Zone de contenu --- */
.et-content { grid-row: 2; grid-column: 2; display: flex; flex-direction: column; min-width: 0; background: var(--app-bg); }
.et-tabs { display: flex; align-items: stretch; gap: 3px; padding: 6px 12px 0; background: var(--tabbar-bg); border-bottom: 1px solid var(--tab-border); overflow-x: auto; flex-shrink: 0; }
.et-tab { display: inline-flex; align-items: center; gap: 8px; padding: var(--tab-py) 12px; font-size: 13px; color: var(--tab-text); background: var(--tab-bg); border: 1px solid var(--tab-border); border-bottom: none; cursor: pointer; white-space: nowrap; }
.et-tab.active { background: var(--tab-active-bg); color: var(--tab-active-text); font-weight: 600; }
.et-tab .cl { display: inline-flex; border: none; background: transparent; color: inherit; cursor: pointer; opacity: 0; padding: 0; }
.et-tab:hover .cl, .et-tab.active .cl { opacity: .7; }
.et-tab .cl:hover { opacity: 1; }
.et-scroll { flex: 1; min-height: 0; overflow: auto; padding: 20px 22px 28px; }

/* --- Bandeau de délégation (USR-07) ---
   PERMANENT, PAS UNE NOTIFICATION : la passation demande qu'il reste affiché pendant toute
   la période de la délégation, pas jusqu'au premier clic sur une croix. Il n'y a donc pas de
   bouton pour le fermer.

   HORS DE .et-scroll, ET C'EST DÉLIBÉRÉ : posé dans .et-content, au-dessus du conteneur qui
   défile, il reste visible en permanence pendant qu'on parcourt l'écran — c'est le sens même
   d'un bandeau qui doit rappeler en continu « vous n'agissez pas sur vos droits propres ».

   COULEUR D'INFORMATION (--et-info), PAS DE DANGER NI D'ACTION : une délégation en cours est
   un fonctionnement normal du produit, pas un incident ni l'occasion d'un geste. Le orange de
   .mx-btn-cta reste réservé au bouton d'engagement de chaque écran — un bandeau qui l'imiterait
   se ferait prendre pour LE bouton de la page. */
.et-bandeau-delegation {
    display: flex; align-items: center; gap: 10px; flex-shrink: 0;
    padding: 9px 22px; font-size: 13px; font-weight: 500;
    /* --et-info, PAS --et-form-blue : ce dernier n'a pas de variante sombre (audit
       2026-08-12) et tombe à ~2,6:1 sur un fond sombre. --et-info, lui, est redéfini
       pour data-theme="dark" -- le seul des deux à convenir dans une coquille qui peut
       basculer de thème. */
    color: var(--et-info); background: var(--et-info-bg);
    border-bottom: 1px solid var(--et-hairline);
}
.et-bandeau-delegation i { font-size: 15px; }

/* --- Bandeau « intervention de support en cours » (PLT-05) ---
   AMBRE, PAS --et-info comme la délégation : le public et le message diffèrent. La délégation
   dit « vous portez un rôle emprunté » (bénin, dirigé vers l'acteur lui-même) ; celui-ci dit
   « un tiers a un accès temporaire chez vous » (à noter, dirigé vers TOUS les comptes de la
   société). --et-avertissement-ink et non --et-avertissement : ce dernier ne vaut que 2,9:1
   sur --et-avertissement-bg (audit 2026-08-12, easytech-theme.css) — même paire de jetons que
   .dlg-avert (USR-07). */
.et-bandeau-prise-controle {
    display: flex; align-items: center; gap: 10px; flex-shrink: 0;
    padding: 9px 22px; font-size: 13px; font-weight: 500;
    color: var(--et-avertissement-ink); background: var(--et-avertissement-bg);
    border-bottom: 1px solid var(--et-avertissement-bord);
}
.et-bandeau-prise-controle i { font-size: 15px; }

/* --- Bannière période : RETIRÉE -------------------------------------------
   Elle habillait le sélecteur global de la barre du haut, supprimé depuis
   (EasyTimeLayout : « le sélecteur de période a été retiré »). Le bloc, lui,
   était resté : mort, et HOMONYME de la pilule de période que rail-lateral.css
   définit sous le MÊME nom .et-periode. rail-lateral.css se chargeant après,
   il gagnait sur le sélecteur de bloc — mais les six règles descendantes
   (.ico/.lbl/.val/.rng/.st/.btn) restaient, elles, sans propriétaire, prêtes à
   habiller n'importe quel enfant qu'on aurait ajouté à la pilule. Un nom pour
   deux dessins est précisément ce que docs/conventions-nommage.md interdit.

   Le bandeau de page qui l'avait remplacée (css/easytime-periode.css, .bpr-*)
   est parti à son tour : la période se choisit de nouveau dans la barre du
   haut, mais depuis un composant POSÉ PAR EasyTimeLayout et non rendu par la
   coquille pour les neuf modules — c'est ce qui répond à l'objection d'alors.
   Voir Components/Shared/SelecteurPeriodePointage.razor, habillé par la famille
   .et-choix-* de rail-lateral.css. */

/* Menu utilisateur */
.et-usermenu { position: absolute; right: 0; top: calc(100% + 6px); z-index: 40; min-width: 220px; background: var(--ph-bg); border: 1px solid var(--ph-border); box-shadow: var(--et-ombre-flottant); padding: 6px 0; color: var(--crumb-current); }
.et-usermenu a, .et-usermenu button { display: flex; align-items: center; gap: 8px; width: 100%; padding: 9px 16px; font-size: 14px; color: var(--crumb-current); background: transparent; border: none; text-align: left; cursor: pointer; text-decoration: none; }
.et-usermenu a:hover, .et-usermenu button:hover { background: var(--row-hover); }

/* --- Barre de modules (topbar) --- */
.et-modules { display: flex; align-items: center; gap: 2px; flex: 1; min-width: 0; overflow-x: auto; }
.et-modules::-webkit-scrollbar { height: 0; }
.et-mod {
    padding: 7px 12px; font-size: 14px; font-weight: 500; color: var(--et-sur-marine-doux);
    text-decoration: none; white-space: nowrap; border-radius: 0; transition: background .12s;
}
.et-mod:hover { background: var(--et-fond-marine-doux); color: var(--et-sur-marine); }
.et-mod.active { background: var(--et-fond-marine); color: var(--et-sur-marine); font-weight: 600; }

/* ===========================================================================
   MAÎTRE-DÉTAIL (écrans d'édition type "Édition zones") — palette claire
   =========================================================================== */
.md-card { background: var(--et-surface); border: 1px solid var(--et-form-border); border-radius: var(--et-r); overflow: hidden; box-shadow: var(--et-ombre-carte); font-family: var(--et-font); }
.md-head { display: flex; align-items: center; gap: 11px; padding: 14px 22px; background: var(--et-surface-2); }
.md-head .ico { display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px; border-radius: 0; background: var(--et-navy-soft); color: var(--et-navy-ink); flex-shrink: 0; }
.md-head h2 { margin: 0; font-size: 18px; font-weight: 600; color: var(--et-ink); }
.md-head p { margin: 2px 0 0; font-size: 13px; color: var(--et-muted); }
.md-strip { height: 3px; background: var(--et-action); }

.md-body { display: grid; grid-template-columns: 300px 1fr; min-height: 460px; }
.md-left { border-right: 1px solid var(--et-hairline); display: flex; flex-direction: column; min-height: 0; }
.md-left-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 12px 16px; border-bottom: 1px solid var(--et-hairline); }
.md-left-head .lbl { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--et-muted); }
.md-add { display: inline-flex; align-items: center; gap: 5px; padding: 5px 10px; font-size: 13px; font-weight: 600; color: var(--et-sur-aplat); background: var(--et-action); border: none; border-radius: var(--et-r3); cursor: pointer; }
.md-add:hover { background: var(--et-action-d); color: var(--et-sur-aplat); }
.md-list { flex: 1; overflow-y: auto; }
.md-row { display: flex; align-items: center; gap: 10px; padding: 10px 16px; cursor: pointer; border-left: 3px solid transparent; transition: background .12s; }
.md-row:hover { background: var(--et-rang); }
.md-row.sel { border-left-color: var(--et-form-blue); background: var(--et-tint); }
.md-row .code { flex: 0 0 auto; display: inline-block; min-width: 26px; text-align: center; padding: 2px 8px; font-weight: 600; font-size: 12px; color: var(--et-form-blue-encre); background: var(--et-tint); }
.md-row .nom { font-size: 14px; font-weight: 600; color: var(--et-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.md-row .res { font-size: 12px; color: var(--et-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.md-right { display: flex; flex-direction: column; min-width: 0; }
.md-form { flex: 1; overflow: auto; padding: 20px 24px; display: flex; flex-direction: column; gap: 14px; }
.md-field { display: flex; align-items: center; gap: 14px; }
.md-field > label { flex: 0 0 130px; font-size: 13px; font-weight: 600; color: var(--et-muted); }
.md-field > label.r { text-align: right; flex-basis: 120px; }
.md-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 14px 22px; border-top: 1px solid var(--et-hairline); }
.md-del { display: inline-flex; align-items: center; gap: 7px; padding: 9px 18px; font-size: 14px; font-weight: 600; color: var(--et-danger-ink); background: var(--et-surface); border: 1.5px solid var(--et-danger-bord); cursor: pointer; }
.md-del:hover { background: var(--et-danger-badge-bg); border-color: var(--et-danger); color: var(--et-danger-ink); }
.md-save { display: inline-flex; align-items: center; gap: 7px; padding: 9px 20px; font-size: 14px; font-weight: 600; color: var(--et-sur-aplat); background: var(--et-form-blue); border: none; cursor: pointer; }
/* --et-form-blue-plein et non --et-form-blue-d : c'est un APLAT sous du blanc,
   et l'encre bleue s'éclaircit en thème sombre (easytech-theme.css). */
.md-save:hover { background: var(--et-form-blue-plein); color: var(--et-sur-aplat); }
.md-save:disabled { opacity: .6; cursor: default; }

/* --- Thème sombre : fonds/bordures codés en dur ci-dessus (#fff/#e3e6ec/#f7f9fc),
   hors de portée des jetons --et-* (déjà basculés par easytech-theme.css). Même
   portée (.appgrid[data-theme="dark"]) et même chantier — Phase A de l'audit du
   2026-08-12 (docs/PORTAGE_APPLAYOUT_SHELLMODULE.md pour le mécanisme data-theme). --- */
.appgrid[data-theme="dark"] .md-card { background: var(--et-surface); border-color: var(--et-form-border); }
.appgrid[data-theme="dark"] .md-left { border-right-color: var(--et-hairline); }
.appgrid[data-theme="dark"] .md-left-head,
.appgrid[data-theme="dark"] .md-foot { border-color: var(--et-hairline); }
.appgrid[data-theme="dark"] .md-row:hover { background: var(--et-surface-2); }
/* .md-row.sel, .md-row .code et .md-del:hover ne sont plus repris ici : leurs
   trois regles claires nomment --et-tint et --et-danger-badge-bg, qui basculent
   seuls. Les valeurs ecrites etaient des derives a l'oeil des memes jetons
   (rgba(31,111,178,.24) sur la surface nuit donne #142E4B, --et-tint vaut
   #1D2A45) et elles portaient le bleu d'AVANT la revision du 2026-09-02. */
.appgrid[data-theme="dark"] .md-del { background: transparent; }
.appgrid[data-theme="dark"] .md-field > label { color: var(--et-form-label); }
.appgrid[data-theme="dark"] .lic-sep { border-bottom-color: var(--et-form-border); }

/* Sélecteur de période (popup) : RETIRÉ avec la modale du sélecteur global,
   comme la bannière ci-dessus. Aucune vue ne portait plus .et-periode-opt. */

/* Cartes KPI (Effectifs / rapports) */
.kpi { background:var(--et-surface); border:1px solid var(--et-hairline); border-left:4px solid var(--et-form-blue); padding:12px 16px; }
.kpi .kpi-lbl { font-size:12px; font-weight:700; text-transform:uppercase; letter-spacing:.03em; color:var(--et-muted); }
.kpi .kpi-val { font-size:24px; font-weight:700; color:var(--et-ink); line-height:1.1; margin-top:2px; }
.kpi.kpi-green { border-left-color:var(--et-ok); } .kpi.kpi-green .kpi-val { color:var(--et-ok); }
.kpi.kpi-red { border-left-color:var(--et-danger); } .kpi.kpi-red .kpi-val { color:var(--et-danger-ink); }
.kpi.kpi-amber { border-left-color:var(--et-amber); } .kpi.kpi-amber .kpi-val { color:var(--et-amber-ink); }
/* La regle « [data-bs-theme="dark"] .kpi, .dark-mode .kpi » est retiree : elle
   reposait --et-surface sur lui-meme et un filet #1f2b3d voisin de --et-hairline
   sombre (#26324a), que la regle claire ci-dessus nomme deja. .dark-mode, lui,
   n'existe nulle part dans le depot. */

/* Fiche licence */
.lic-row { display:flex; align-items:center; gap:14px; padding:9px 0; border-bottom:1px solid var(--et-hairline); }
.lic-row .lbl { flex:0 0 190px; font-size:13px; font-weight:600; color:var(--et-muted); }
.lic-row .val { font-size:14px; color:var(--et-ink); }
.lic-sep { margin:18px 0 10px; font-size:12px; font-weight:700; text-transform:uppercase; letter-spacing:.03em; color:var(--et-form-blue-encre); border-bottom:2px solid var(--et-tint); padding-bottom:4px; }

/* ===== Lignes de liste compactes (hauteur minimale) =====
   Le rembourrage vertical passe par --et-cellule-y (easytech-theme.css) : c'est
   la MÊME valeur que sert « .tbl tbody td » plus bas. Les deux familles de
   tableaux du back-office se règlent donc d'un seul endroit. */
.table > :not(caption) > * > * { padding-top: var(--et-cellule-y); padding-bottom: var(--et-cellule-y); }
.table td, .table th { line-height: 1.15; vertical-align: middle; }
/* TROISIÈME PRÉTENDANT SUR LE MÊME th, ET IL PERDAIT DÉJÀ. Cette ligne (0,1,2)
   battait le sélecteur générique du dessus (0,1,1) mais était elle-même battue
   par « .table > thead > tr > th » (0,1,3) du thème : ses .3rem n'ont donc jamais
   rien réglé. Elle reste ici pointée sur le jeton plutôt que supprimée — sa
   spécificité intermédiaire protège le jeton si quelqu'un réintroduit un jour un
   raccourci « padding » dans une feuille d'écran. */
.table thead th { padding-top: var(--et-cellule-tete-y); padding-bottom: var(--et-cellule-tete-y); }
.table .btn-sm { padding: .12rem .4rem; line-height: 1.1; }
.table .badge { padding: .28em .5em; font-weight: 600; }
.table .form-select-sm, .table .form-control-sm { padding-top: .1rem; padding-bottom: .1rem; }

/* ===== Mise en page de la fiche employé : DÉPLACÉE dans css/fiche.css ==========
   .fe-gen, .fe-grid4, .fe-tabbody et leurs descendants habillaient une FICHE, pas
   la coquille. Ils vivaient ici pendant que les 143 autres règles .fe-* vivaient
   dans fiche.css : la famille était coupée en deux, et aucune des deux feuilles
   n'en était la source. Même motif que .plg-* (extrait le 2026-09-03) — cette
   feuille est la coquille : barre, rail, gabarit de liste.

   .modal-employe partait avec, et n'a PAS été déplacée : zéro occurrence dans tout
   le dépôt. Une largeur de modale qu'aucune modale ne porte.

   La règle d'impression qui groupe .fe-photo-box avec .md-card et .kpi RESTE ici :
   la scinder pour suivre une seule de ses trois familles coûterait plus qu'elle ne
   rapporte. ============================================================== */

/* ===== Bouton primaire bleu Easytech ===== */
/* Nom historique conservé (52 ecrans l'utilisent) : c'est le bouton d'appel a
   l'action, il porte donc l'orange de la charte et non plus le bleu. */
.btn-easytech-blue { background:var(--et-action); color:var(--et-sur-aplat); border:1px solid var(--et-action); border-radius:var(--et-r2); font-weight:600; }
.btn-easytech-blue:hover, .btn-easytech-blue:focus { background:var(--et-action-d); color:var(--et-sur-aplat); border-color:var(--et-action-d); }

/* ================= Portail salarié =================
   Jetons --et-* plutôt que du blanc/gris codés en dur (voir --et-surface/
   --et-surface-2/--et-hairline, posés Phase A du chantier "étendre le thème
   sombre au contenu", audit du 2026-08-12) : ThemeToggleActive="true" sur
   PortailLayout, donc ce gabarit bascule sous .appgrid[data-theme="dark"]
   comme les quatorze modules du back-office — un fond/filet en dur ici y
   resterait blanc/clair sur fond sombre. */
.portail-page { }
.portail-h1 { font-size:22px; font-weight:800; color:var(--et-ink); letter-spacing:-.01em; position:relative; padding-bottom:8px; }
.portail-h1::after { content:""; position:absolute; left:0; bottom:0; width:46px; height:3px; background:var(--et-action); border-radius:0; }
.portail-h2 { font-size:15px; font-weight:700; color:var(--et-form-blue-encre); margin-bottom:10px; text-transform:uppercase; letter-spacing:.03em; }
.portail-block { background:var(--et-surface); border:1px solid var(--et-hairline); border-radius:0; padding:18px 20px; margin-top:16px; box-shadow:var(--et-ombre-carte); }
.portail-cards { display:grid; grid-template-columns:repeat(auto-fit,minmax(240px,1fr)); gap:14px; margin-top:14px; }
.portail-tile { display:flex; gap:14px; align-items:center; background:var(--et-surface); border:1px solid var(--et-hairline); border-radius:0; padding:16px 18px; text-decoration:none; color:inherit; transition:transform .12s,box-shadow .15s,border-color .15s; position:relative; overflow:hidden; }
.portail-tile::before { content:""; position:absolute; left:0; top:0; bottom:0; width:3px; background:var(--et-action); transform:scaleY(0); transform-origin:top; transition:transform .15s; }
.portail-tile:hover { box-shadow:var(--et-ombre-survol); transform:translateY(-2px); border-color:var(--et-form-blue); }
.portail-tile:hover::before { transform:scaleY(1); }
.portail-tile .t-ico { width:48px; height:48px; border-radius:0; display:flex; align-items:center; justify-content:center; font-size:1.35rem; flex-shrink:0; background:var(--et-amber-voile); color:var(--et-amber-ink); }
.portail-tile .t-title { font-weight:700; color:var(--et-ink); }
.portail-tile .t-sub { font-size:13px; color:var(--et-muted); }

/* LE SEUL TABLEAU DU PORTAIL QUI NE TIENT PAS dans la colonne de contenu :
   « Demandes de mon équipe », huit colonnes dont un motif en texte libre et deux
   boutons d'action. Sans largeur plancher, Bootstrap le comprime jusqu'à
   l'illisible sur téléphone au lieu de le faire défiler ; avec elle il défile
   dans le .table-responsive que DataGrid pose déjà, et sa colonne « Salarié »
   reste ancrée (tbl-ancree + data-ancre, lot03-tables-larges.css).

   Motif repris de Budget/EngagementsBudget.razor, pas inventé ici. Les autres
   tableaux du portail plafonnent à six colonnes et tiennent sans plancher :
   leur en donner un les ferait défiler pour rien. */
.portail-tbl-large { min-width: 1000px; }

/* écrans auth portail */
/* Le degrade est desormais un JETON ENTIER (--et-degrade-accueil, dans
   easytech-theme.css). Le lot precedent le laissait ici en exclusion argumentee,
   au motif que son troisieme arret n'est pas un cran de la famille marine — la
   famille ne fait que DESCENDRE. C'est toujours vrai ; ce qui a change, c'est
   qu'un degrade de marque a sa place dans le theme, comme les trois marines
   au-dessus de lui, et non dans la feuille qui l'emploie. */
.portail-auth { min-height:100vh; display:flex; align-items:center; justify-content:center; padding:24px; background:var(--et-degrade-accueil); }
.portail-card { width:100%; max-width:420px; background:var(--et-surface); border:none; border-top:4px solid var(--et-action); border-radius:0; padding:26px; box-shadow:var(--et-ombre-fenetre); }
.portail-card-head { display:flex; gap:12px; align-items:flex-start; margin-bottom:18px; }
.portail-card-head > i { font-size:1.6rem; color:var(--et-form-blue-encre); }
.portail-card-head h1 { font-size:19px; font-weight:700; margin:0; color:var(--et-ink); }
.portail-card-head p { margin:2px 0 0; font-size:13px; color:var(--et-muted); }

/* séparateur menu portail (avant section manager) */

/* cloche notifications portail */
/* lignes notifications */
.notif-row { display:flex; align-items:center; gap:12px; padding:12px 16px; border-bottom:1px solid var(--et-hairline); cursor:pointer; }
.notif-row:last-child { border-bottom:none; }
.notif-row:hover { background:var(--et-surface-2); }
.notif-row.non-lue { background:var(--et-tint); }
.notif-dot { width:9px; height:9px; border-radius:50%; background:var(--et-form-blue); flex-shrink:0; }
.notif-dot.lu { background:var(--et-inerte); }

/* --- Pictogramme de module (composant PictoModule) ---------------------------
   Tuile de la charte portant l'icône métier du catalogue (ModuleInfo.Icone).
   Ici plutôt que dans un <style> du composant : celui-ci serait réémis à chaque
   instance (quinze copies rien que pour la grille du lanceur d'applications). */
.picto-module {
    display: inline-flex; align-items: center; justify-content: center;
    position: relative; overflow: hidden; flex-shrink: 0;
    border-radius: 22%;
    /* Le degrade de la marque, nomme dans le theme (--et-degrade-marque) :
       c'est l'icone du produit, et son arret haut est un marine PLUS CLAIR que
       --et-blue, que la famille ne nomme pas. Elle ne le nommera pas non plus :
       le degrade entier porte un seul nom, comme --et-ombre-flottant. */
    background: var(--et-degrade-marque);
    color: var(--et-sur-marine); line-height: 1;
}
/* Bootstrap Icons pose vertical-align:-.125em sur .bi::before — un calage pensé pour
   l'icône au fil du texte, qui décale le glyphe dès qu'on le centre dans un conteneur. */
.picto-module i { display: block; line-height: 1; }
.picto-module i::before { display: block; vertical-align: 0; line-height: 1; }
/* Liseré ambre des anciens pictos : la signature de la charte. En absolu, il ne
   participe pas au centrage du glyphe. */
.picto-module::after {
    content: ''; position: absolute; left: 26%; right: 26%; bottom: 10%;
    height: 6%; min-height: 2px; border-radius: 99px; background: var(--et-action);
}

/* ===========================================================================
   THÈME SOMBRE — Phase C : utilitaires Bootstrap à couleur FIGÉE
   Audit du 2026-08-12, corrigé par mesure au getComputedStyle sur banc d'essai
   (une .appgrid[data-theme=dark] réelle, mêmes feuilles, même cascade).

   CE QUE LA MESURE A CORRIGÉ PAR RAPPORT À L'AUDIT — trois surprises :

   1. .text-secondary N'EST PAS adaptatif. Il lit --bs-secondary-rgb, que
      [data-bs-theme=dark] ne redéfinit pas : mesuré #6c757d dans les DEUX
      thèmes. Seul .text-muted l'est (--bs-secondary-color, mesuré
      rgba(222,226,230,.75) en sombre). Donc parmi les compagnons de .bg-light —
      text-dark (116), text-secondary (51), text-muted (35) — un seul était
      cassé avant ce lot ; les deux autres étaient lisibles sur fond clair et
      SERAIENT cassés par l'assombrissement du fond si on les laissait tels quels.

   2. .table-light EST DÉJÀ SANS EFFET dans cette application. easytech-theme.css
      peint tous les en-têtes avec --et-table-head (.table thead th, spécificité
      (0,1,2), au-dessus du mécanisme --bs-table-bg de Bootstrap en (0,1,1)) :
      mesuré rgb(31,111,178) en sombre comme en clair. Les 144 occurrences de
      ClasseEnTete="table-light" sont des classes mortes — rien à corriger ici,
      et surtout aucune règle à écrire qui ne servirait jamais.

   3. Le texte NU héritait du noir. body { color: var(--bs-body-color) } est posé
      par Bootstrap au-dessus de notre portée : data-bs-theme sur .appgrid
      redéfinit bien la variable, mais plus rien ne réapplique `color` en
      dessous. Mesuré rgb(33,37,41) sur fond #111a2b — 1,1:1. C'était la vraie
      cause, préexistante, et c'est elle qui rendait dangereux d'assombrir
      .bg-light : ces pavés clairs étaient des îlots de lisibilité dans une zone
      déjà cassée. On la corrige d'abord (règle ci-dessous), le reste en découle.

   POURQUOI PAS --bs-light-rgb / --bs-dark-rgb DIRECTEMENT (piste écartée) :
   .text-dark est aussi porté par .bg-warning et .bg-info, dont le fond reste
   saturé quel que soit le thème. Basculer --bs-dark-rgb éclaircirait ce texte
   sur du jaune #ffc107 — on casserait 35 badges pour en corriger d'autres. On
   ne bascule .text-dark/.text-secondary que lorsqu'ils accompagnent .bg-light,
   SUR LE MÊME ÉLÉMENT. Même raison pour .bg-white, laissé intact (bloc print).

   PORTÉE @media screen : DÉLIBÉRÉE, c'est le garde d'impression. Quatre usages
   tombent dans une zone imprimable (Paie/Bulletin.razor:91, Stock/EtatStocks
   .razor:119, Support/FicheTicket.razor:72 et :76) ; le papier est toujours
   blanc. Hors écran ces règles n'existent pas, Bootstrap reprend ses valeurs
   claires d'origine, et un bulletin de paie ne s'imprime pas sur aplat nuit.
   =========================================================================== */
@media screen {
    /* Racine du problème (surprise 3). Une déclaration, et tout le texte nu du
       contenu suit le thème : les pages n'ont plus à colorer chaque paragraphe.
       var(--bs-body-color) plutôt que var(--et-ink) : .appgrid porte aussi
       data-bs-theme, la variable y vaut déjà la bonne valeur par thème — et le
       bloc @media print plus bas la repasse au noir, donc l'impression suit
       sans règle supplémentaire. */
    .appgrid[data-theme="dark"] { color: var(--bs-body-color); }

    .appgrid[data-theme="dark"] .bg-light,
    .appgrid[data-theme="dark"] .text-bg-light { background-color: var(--et-neutre-bg) !important; }

    /* .text-muted est volontairement absent : il s'éclaircit seul (surprise 1),
       corriger le fond suffit. */
    .appgrid[data-theme="dark"] .bg-light.text-dark,
    .appgrid[data-theme="dark"] .text-bg-light { color: var(--et-ink) !important; }
    /* --et-muted et non --et-ink : on garde le registre « secondaire ». */
    .appgrid[data-theme="dark"] .bg-light.text-secondary { color: var(--et-muted) !important; }
}

/* --- Garde d'impression -----------------------------------------------------
   Indépendamment du bloc ci-dessus : data-bs-theme="dark" éclaircit aussi
   --bs-body-color, et nos jetons --et-ink/--et-surface passent en clair sur
   fond nuit. Imprimer depuis le thème sombre donnait donc du texte pâle sur du
   papier blanc — régression PRÉEXISTANTE à ce lot, mais du même ressort.
   On rétablit ici les valeurs claires pour le rendu papier uniquement — par
   héritage depuis 2026-09-04, voir le commentaire dans le bloc. --- */
@media print {
    /* La coquille elle-même ne s'imprime pas. app.css avait cette règle pour la barre
       AdminLTE (.app-header/.app-sidebar/.app-footer) ; les quatorze modules montés sur
       ShellModule ne l'ont jamais eue, et le portage d'AdminLayout aurait fait perdre à
       l'administration la sienne. On la pose ici, une fois, pour tout le monde.

       Les trois dernières déclarations comptent autant que les display:none : .appgrid
       est une grille en height:100vh dont .et-scroll est un conteneur overflow:auto —
       à l'impression, le contenu serait coupé net au bas de la première page. On rend
       la hauteur et le débordement au flux du document. */
    .appgrid > .et-topbar,
    .appgrid > .et-side,
    .appgrid > .et-bande { display: none !important; }
    .appgrid { display: block !important; height: auto !important; min-height: 0 !important; }
    .appgrid > .et-content { display: block !important; background: var(--et-surface) !important; }
    .appgrid .et-scroll { overflow: visible !important; height: auto !important; padding: 0 !important; }

    .appgrid[data-theme="dark"] {
        color-scheme: light;
        /* LES VALEURS CLAIRES NE SONT PLUS RECOPIÉES, ELLES SONT RENDUES À
           L'HÉRITAGE. Une propriété personnalisée est héritée : « inherit » la
           fait retomber sur la valeur calculée du PARENT, qui est hors de
           .appgrid — c'est-à-dire sur le bloc clair de :root d'easytech-theme.css.
           Vaut aussi pour les --bs-* : data-bs-theme="dark" est posé sur .appgrid
           ELLE-MÊME (ShellModule.razor, LanceurLayout), jamais au-dessus, donc
           le parent porte les valeurs claires de Bootstrap.

           CE QUE LA RECOPIE COÛTAIT : elle ne suivait aucune bascule. Les huit
           jetons écrits ici avaient dérivé de la charte — --et-ink valait #1b2430
           contre #0F172A depuis la révision du 2026-09-02, --et-surface-2 valait
           #ffffff contre #F5F6F7, --et-form-label #374151 contre #6A6D70,
           --et-muted #4b5563 contre #6A6D70. Imprimer depuis le thème sombre ne
           donnait donc pas LE document clair, mais UN document clair.
           L'ensemble des jetons rendus est inchangé : seul le mécanisme l'est. */
        --bs-body-color:      inherit;
        --bs-body-color-rgb:  inherit;
        --bs-body-bg:         inherit;
        --bs-emphasis-color:  inherit;
        --bs-secondary-color: inherit;
        --bs-tertiary-bg:     inherit;
        --bs-border-color:    inherit;

        --et-ink:         inherit;
        --et-muted:       inherit;
        --et-hairline:    inherit;
        --et-surface:     inherit;
        --et-surface-2:   inherit;
        --et-form-text:   inherit;
        --et-form-label:  inherit;
        --et-form-border: inherit;
    }
    /* --et-surface vaut le blanc du papier par la règle ci-dessus. */
    .appgrid[data-theme="dark"] .md-card,
    .appgrid[data-theme="dark"] .kpi,
    .appgrid[data-theme="dark"] .fe-photo-box { background: var(--et-surface); }
}

/* --- Panneau de notifications (composant PanneauNotifications) ----------------
   Ici plutôt que dans un <style> du composant : celui-ci serait réémis à chaque
   instance, même raison que .picto-module plus haut. Tout est sur les jetons
   --et-* / --ph-* : la version d'origine, en dur dans EasyTimeLayout, codait
   #fff / #eef0f4 / #1f2937 / #f6faff et restait blanche en thème sombre. */
.notif-pastille {
    position: absolute; top: -2px; right: -2px;
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 15px; height: 15px; padding: 0 3px; border-radius: 999px;
    background: var(--et-danger); color: var(--et-sur-aplat); font-size: 12px; font-weight: 700; line-height: 1;
    font-variant-numeric: tabular-nums;
}
/* .et-usermenu porte déjà fond, bordure et ombre ; on ne règle ici que la taille
   et le défilement, propres au panneau. */
.notif-panneau { right: 0; left: auto; min-width: 320px; max-width: 360px; max-height: 430px; overflow: auto; padding: 0; }
/* Au-dessus du fond (z-index 1999) mais sous rien d'autre : le panneau est
   position:absolute dans un parent non stacké, il lui faut son propre contexte. */
.notif-panneau { z-index: 2000; }
.notif-fond { position: fixed; inset: 0; z-index: 1999; background: transparent; }
.notif-entete {
    display: flex; align-items: center; justify-content: space-between;
    padding: 10px 12px; border-bottom: 1px solid var(--et-hairline);
    position: sticky; top: 0; background: var(--ph-bg); z-index: 1;
}
/* --crumb-link et non --et-form-blue : le bleu de MARQUE ne bascule pas par thème
   (il habille des bandeaux à texte blanc), et posé sur le fond nuit du panneau il
   tombait à 3,29:1 — mesuré. --crumb-link est le même bleu en clair et s'éclaircit
   en sombre. Même raison pour le bouton « tout marquer comme lu » ci-dessous. */
.notif-entete strong { font-size: 13px; color: var(--crumb-link); }
.notif-entete span { font-size: 12px; color: var(--et-muted); }
.notif-vide { padding: 18px 12px; text-align: center; color: var(--et-muted); font-size: 13px; }
.notif-ligne { padding: 9px 12px; border-bottom: 1px solid var(--et-hairline); }
.notif-ligne.non-lue { background: var(--et-info-bg); }
.notif-titre { font-size: 13px; font-weight: 600; color: var(--et-ink); }
.notif-detail { font-size: 12px; color: var(--et-form-label); }
.notif-meta { font-size: 12px; color: var(--et-muted); margin-top: 2px; }
.notif-tout-lire {
    width: 100%; padding: 9px; border: 0; border-top: 1px solid var(--et-hairline);
    background: var(--ph-bg); color: var(--crumb-link); font-size: 12px; cursor: pointer;
    position: sticky; bottom: 0;
}
.notif-tout-lire:hover { background: var(--row-hover); }

/* --- Vignettes d'indicateur cliquables (tableau de bord) ---------------------
   Rien n'était cliquable dans le contenu du tableau de bord (mesuré : zéro lien,
   zéro bouton). Les vignettes mènent désormais à l'écran d'action ; encore
   faut-il que ça se VOIE, sinon le lien n'existe que pour qui essaie au hasard. */
.kpi-lien { transition: border-color .12s, box-shadow .12s, transform .12s; }
.kpi-lien:hover {
    border-color: var(--et-form-blue) !important;
    box-shadow: var(--et-ombre-survol);
    transform: translateY(-1px);
}
.kpi-lien:focus-visible { outline: 2px solid var(--et-form-blue); outline-offset: 2px; }

/* ===========================================================================
   TABLEAU UNIFIÉ (composant Tableau<T>) — habillage « Registre »
   Chantier d'uniformisation, relevé du 2026-08-12 : 578 tableaux sur 327 écrans,
   15 variantes de ClasseTable dont 72 % sont la même chaîne à l'ordre des mots
   près, et zéro tableau triable par clic d'en-tête.

   Registre plutôt que le bandeau bleu actuel : le bleu de MARQUE ne bascule pas
   par thème (il habille des bandeaux à texte blanc), si bien qu'un en-tête plein
   reste aussi saturé la nuit qu'en plein jour — c'est le défaut mesuré sur
   .table thead th, jamais assombri hors du module Compta. Ici l'en-tête n'est
   qu'un double filet marine : rien à réconcilier entre les deux thèmes, et rien
   à imprimer non plus.

   DEUX PHRASES CI-DESSUS SONT PÉRIMÉES, gardées pour l'historique du chantier —
   l'arbitrage courant est celui daté du 2026-08-15 sur --tbl-tete-fond, plus bas.
   L'en-tête est redevenu un APLAT PLEIN, et le grief fait au bandeau de marque ne
   tient plus contre lui : l'anthracite #4E5464 est retenu précisément parce qu'il
   vaut dans les deux thèmes. Et « hors du module Compta » n'a plus d'objet — la
   dérogation de Compta a été levée le même jour (compta-ux.css), les deux familles
   de tableaux et tous les modules partagent désormais la même teinte de tête.
   =========================================================================== */
.tbl-cadre {
    /* --tbl-tete a ete RETIRE le 2026-09-04. Il servait le MOBILIER (etat de vue
       actif, survol de bordure) et non la tete de table ; il valait l'ardoise en
       clair et un bleu pale #a9bde0 en sombre, seule valeur du bloc sombre qui ne
       fut jamais un derive d'un jeton. Ses deux consommateurs voulaient d'ailleurs
       le contraire l'un de l'autre en sombre : l'etat de vue actif est un APLAT
       (il prend --et-table-head, invariant par theme, comme les trois familles de
       tableaux depuis le 2026-08-15) et le survol de bordure du selecteur de
       periode est un ACCENT (il prend --tbl-accent, comme la fleche voisine
       .cbp-fleche:hover qui le nommait deja). */
    /* 2026-08-17 : les filets de la passation. Le zebrage disparait — il vaut
       desormais BLANC, c'est-a-dire rien. La passation ne zebre pas : « fond blanc,
       #EBF3FB si selectionnee, survol #EDEDED ». Le jeton est conserve a blanc
       plutot que supprime, pour que les etats Analyse et Croise qui l'annulent
       explicitement continuent de le nommer sans casser. */
    /* UN SEUL GRIS TENAIT DEUX ROLES. La passation ne nomme #EDEDED que pour le
       SURVOL ; le filet l'avait recopie. La charte, elle, a deux noms : --et-rang
       (« separateurs de rangee, survol de rangee ») et --et-hairline (« filets »).
       Le filet prend donc --et-hairline — que sa valeur sombre confirme, l'ancien
       #222e44 etant un derive a quatre unites pres de #26324a. Consequence a
       regarder : en clair le filet des rangees passe de #EDEDED a #E5E5E5, huit
       unites plus soutenu, et s'aligne sur tous les autres filets du produit. */
    --tbl-filet:  var(--et-hairline);
    --tbl-survol: var(--et-rang);
    --tbl-zebre:  var(--et-surface);
    /* #AD4A08 et non l'orange de charte #F26C16 : sur le gris de la tete, celui-ci
       ne donne que 2,80:1 — sous le seuil AA pour du 11px. Mesure prise en recette,
       contre mon propre argument (« l'accent ressortira mieux sur le gris »). Cette
       teinte donne 5,16:1 en restant franchement orange. En sombre, --tbl-accent
       vaut #F49A47 et atteint deja 7,46:1 : rien a corriger de ce cote. */
    /* 2026-08-17, passation « Design 7 » : l'accent du tableau redevient BLEU.
       Le raisonnement de contraste ci-dessus reste vrai — c'est bien pour cela que
       l'orange avait dû être assombri jusqu'a #AD4A08, teinte que plus personne ne
       lisait comme l'orange de la marque. La passation supprime la question : la
       fleche de tri s'affiche en #0A6ED1, et l'orange quitte le tableau, ou il ne
       designait de toute facon aucun bouton d'engagement.
       Mesure : #0A6ED1 sur le chrome #F5F6F7 vaut 4,45:1 ; la fleche fait 9 px mais
       elle est REDONDANTE (la colonne triee porte aussi un fond plus fonce), donc
       hors du seuil exige pour une information portee par elle seule. */
    /* #0A6ED1 EST --et-form-blue-encre : le bleu employe comme ENCRE, que la
       revision de valeurs du 2026-09-02 a laisse ou il etait. La fleche de tri est
       de l'encre, le jeton est donc exact — et il apporte sa valeur sombre. */
    --tbl-accent: var(--et-form-blue-encre);
    --tbl-chrome: var(--et-surface-2);
    /* TETE DE TABLEAU — gris ardoise, retenu apres comparaison de cinq teintes en
       situation sous la barre marine (page de conception, section 08).
       Meme valeur dans les DEUX themes : le texte blanc y tient a 10,31 et la tete se
       detache du corps blanc (10,31) comme du corps nuit (1,69). Rien a reconcilier
       entre les themes, ce qui etait tout le reproche fait a l'ancien bandeau de marque.
       A savoir : c'est la teinte la plus proche du marine EN CLARTE (1,32). Elle s'en
       distingue par la TEINTE — gris neutre contre bleu sature — pas par le poids. */
    /* ARBITRE LE 2026-08-13 : bleu clair, confirme apres essai a l'ecran.
       MAQUETTE 7 : l'en-tete passe du gris ardoise au BLEU CLAIR #E8EFFA, encre
       #4B5563. Le raisonnement de l'ardoise (ci-dessus) tenait ; il repondait a une
       autre question — se detacher du marine du layout par la teinte. La maquette
       tranche autrement : l'en-tete cesse d'etre un aplat sombre et devient un liseré
       clair, ce qui rapproche le tableau du reste des surfaces de l'ecran.
       Mesure refaite : #4B5563 sur #E8EFFA donne 6,54:1, au-dessus du seuil AA de 4,5
       exige par du 10,5 px. En revanche l'ardoise avait un avantage que celle-ci perd :
       elle valait dans les DEUX themes. Le bleu clair, lui, exige sa declinaison sombre,
       posee plus bas. */
    /* ARBITRE LE 2026-08-15 : GRIS ANTHRACITE #4E5464, encre blanche. Essai mene la
       veille sur la seule liste du personnel, puis generalise a tous les tableaux.
       L'en-tete redevient un aplat SOMBRE — le liseré clair de la maquette 7 est
       abandonne — mais en gris neutre, pas au bleu de marque : c'est la reponse a la
       question que l'ardoise posait deja (se detacher du marine du layout par la
       TEINTE et non par le poids), avec une valeur plus soutenue.
       Ce que la bascule REGAGNE : la valeur unique pour les deux themes, seul avantage
       que le bleu clair avait perdu. Blanc sur #4E5464 = 7,54:1 (seuil AA de 4,5 pour
       du 11px largement tenu), et la tete se detache du corps blanc comme du corps
       nuit. La declinaison sombre plus bas ne fait donc plus que reprendre la meme
       valeur, elle n'a plus rien a reconcilier.
       C'est aussi la teinte qui ALIGNE LES TROIS FAMILLES de tableaux. Elle n'est plus
       recopiee ici : --et-table-head (easytech-theme.css) en est la source unique, et
       les .table Bootstrap comme les grilles de planning (.plg-th) y pointent aussi.
       Une prochaine bascule de charte se fait donc la-bas, pas ici. */
    --tbl-tete-fond: var(--et-table-head);
    /* 2026-08-17 : l'encre de l'en-tete n'est plus le blanc pur mais #C3D0E4, le
       gris bleute que la passation reserve aux libelles poses sur fond ardoise.
       6,26:1 sur #354A5F — au-dessus du seuil AA — et l'en-tete cesse de crier plus
       fort que les donnees qu'il coiffe, ce qui etait le reproche fait a l'aplat
       sombre a chacune des trois bascules precedentes. */
    --tbl-tete-encre: var(--et-sur-ardoise);
    /* Colonne triee : un panneau PLUS FONCE, pas une couleur de texte. Aucun ambre ne
       depasse 2,41 sur ce bleu, et la seule teinte qui atteint 4,5 (#FFE9CF) est si
       proche du blanc qu'elle ne se lit plus comme un accent. Le fond, lui, porte le
       signal sans toucher a la lisibilite : blanc dessus 8,98, et il se detache de la
       tete. C'est aussi plus sur pour un daltonien — une difference de VALEUR, doublee
       de la fleche de tri. */
    /* Colonne triee : un cran PLUS SOUTENU que l'en-tete, pas une couleur de texte —
       une difference de valeur reste lisible pour un daltonien, et elle est doublee
       par la fleche de tri. Sur l'anthracite le cran se prend vers le BAS (#3E4453,
       blanc a 9,90:1) : vers le haut il aurait fallu delaver la tete. */
    --tbl-tete-actif: var(--et-table-head-fonce);
    background: var(--et-surface);
}
/* CE BLOC NE REDECLARE PLUS QUE LA TETE. Les six autres valeurs etaient une
   palette sombre parallele : --tbl-chrome #16202f EST --et-surface-2 sombre au
   chiffre pres, --tbl-filet #222e44 un derive de --et-hairline (#26324a), et les
   jetons nommes en clair basculent seuls. Deux d'entre elles n'etaient pas que
   des doublons, elles etaient EN RETARD :

   -- --tbl-accent valait #F49A47, l'AMBRE. La passation du 2026-08-17 a fait
      passer l'accent du tableau au bleu (« l'orange quitte le tableau ») et le
      commentaire du bloc clair le dit ; la bascule n'avait ete portee que sur le
      bloc clair. En thème sombre, la fleche de tri, les cernes de focus et le
      liseré de l'element actif de tous les tableaux du back-office etaient donc
      restes orange pendant tout ce temps.

   -- --tbl-zebre valait #0f1828, plus sombre que la surface. Le zebrage a ete
      SUPPRIME le meme jour (« il vaut desormais BLANC, c'est-a-dire rien ») —
      en clair seulement. Les tableaux du theme sombre zebraient encore.
      Corollaire : .tbl-cal-case.est-weekend s'appuyait sur ce meme jeton et
      avait donc perdu son marquage en clair depuis. Il prend desormais
      --et-surface-2, qui le rend dans les deux themes. */
.appgrid[data-theme="dark"] .tbl-cadre {
    /* L'en-tete clair exigeait une declinaison sombre : un #E8EFFA sur fond nuit aurait
       ete une barre lumineuse en travers de l'ecran, et on gardait le RAPPORT (en-tete
       un cran plus clair que le corps) sans garder la valeur.
       L'ANTHRACITE N'EN A PLUS BESOIN — on repete ici les memes valeurs qu'en clair.
       Elles sont redeclarees plutot que supprimees parce que ce bloc redefinit d'autres
       jetons : les retirer ferait retomber la tete sur celles du bloc clair par
       heritage, ce qui donne le meme resultat aujourd'hui mais le rend accidentel.
       Ecrites, elles disent que la valeur unique est un CHOIX et se verifient au meme
       endroit que les autres. Contraste blanc/#4E5464 sur fond nuit : la tete reste
       plus claire que le corps (#0f1828), le rapport est conserve. */
    --tbl-tete-fond: var(--et-table-head);
    --tbl-tete-encre: var(--et-sur-ardoise-plein);
    --tbl-tete-actif: var(--et-table-head-fonce);
}

/* --- Barre d'outils --- */
/* Le MOBILIER (barre, pied, selecteur) porte un fond distinct des DONNEES.
   Sans lui, en-tete de carte + barre d'outils + pied formaient un seul aplat blanc
   de pres de 300 px au-dessus du tableau : mesure prise sur la maquette, defaut
   present a l'identique ici. La table garde le fond de surface, le reste recule. */
/* « Rangee padding 10px 14px, fond #F5F6F7, bordure 1px solid #E5E5E5, row-gap 8px. »
   Le row-gap n'est pas un detail : la barre s'enroule sur deux lignes des que l'ecran
   retrecit, et sans lui les deux rangees se touchaient. */
.tbl-barre { display: flex; align-items: center; gap: 8px; row-gap: 8px; flex-wrap: wrap; padding: 10px 14px; border-bottom: 1px solid var(--et-hairline); background: var(--tbl-chrome); }
.tbl-barre .btn { border-radius: 0; }

/* Sélecteur d'états : icônes seules, l'état actif en plein */
/* 2026-08-17, gabarit de liste : le selecteur revient DANS LE FLUX, deuxieme element de
   la rangee — « groupe de boutons 32 x 32 px accoles dans une bordure 1px solid #D9D9D9 ».

   Il etait ancre en absolu au coin superieur droit de la carte, pour ne pas se retrouver
   centre verticalement quand la barre s'enroule sur deux lignes. Le row-gap pose sur
   .tbl-barre regle ce defaut sans sortir du flux, et l'ancrage coutait une reserve de
   padding (--tbl-reserve, 78 px) a tenir a la main : les boutons devaient s'enrouler AVANT
   d'atteindre un element qui ne poussait personne. Un chiffre de plus a maintenir pour un
   probleme que la gouttiere resout.
   .tbl-cadre garde son position: relative — le panneau d'apercu s'y ancre. */
.tbl-cadre { position: relative; }
.tbl-etats {
    display: inline-flex; flex: none; overflow: hidden;
    border: 1px solid var(--et-form-border);
}

/* TALON DROIT de la barre : « margin-left: auto puis, a droite, Exporter et le bouton
   d'engagement orange ». La gouttiere automatique est posee sur le talon et non sur son
   premier enfant : sans elle, un ecran qui n'exporte pas verrait son bouton d'engagement
   revenir coller a la recherche. */
.tbl-barre-fin { margin-left: auto; display: flex; align-items: center; gap: 8px; }

/* LA PLACE DU BOUTON D'ENGAGEMENT, QUAND IL N'Y EN A PAS. Un ecran dont les objets ne se
   saisissent pas — les constats d'absence naissent de la generation des heures — laisserait
   ce talon vide, et on chercherait le bouton absent. La phrase l'occupe et dit pourquoi.
   C'est une note : elle explique, elle n'agit pas. */
.tbl-barre-aide {
    max-width: 380px;
    font-size: 12px;
    line-height: 1.45;
    color: var(--et-faint);
    text-align: right;
}
@media (max-width: 1100px) { .tbl-barre-aide { display: none; } }

/* LA METHODE, SOUS LA TABLE. La note de .tbl-barre-aide explique un bouton absent ; celle-ci
   explique un CHIFFRE — d'ou son emplacement, sous les lignes qu'elle qualifie, et non dans
   la barre d'outils. Un tableau qui affiche une valeur indicative sans dire d'ou elle vient
   la fait prendre pour la valeur payee ; c'est le seul endroit ou la dire soit lu.
   ICI ET NON DANS UNE FEUILLE D'ECRAN, bien qu'un seul ecran s'en serve aujourd'hui : c'est
   la FAMILLE qui commande le fichier, comme pour .tbl-barre-aide juste au-dessus. Un
   .tbl-* pose dans ecran-feries.css obligerait le deuxieme ecran a charger la feuille du
   premier — la dependance que la decoupe d'App.razor existe pour empecher. */
.tbl-methode {
    padding: 10px 18px 14px;
    border-top: 1px solid var(--et-hairline);
    font-size: 12px;
    line-height: 1.5;
    color: var(--et-faint);
}
.tbl-etat-opt {
    display: inline-flex; align-items: center; justify-content: center;
    width: 32px; height: 32px; border: 0; border-right: 1px solid var(--et-form-border);
    background: transparent; color: var(--et-muted); cursor: pointer; font-size: 14px;
    transition: background .12s, color .12s;
}
.tbl-etat-opt:last-child { border-right: 0; }
.tbl-etat-opt:hover { background: var(--tbl-survol); color: var(--et-ink); }
/* --et-table-head vaut la meme ardoise dans les deux themes : la declinaison
   sombre (#2c4373, encre --et-ink) n'a plus lieu d'etre. */
.tbl-etat-opt.actif { background: var(--et-table-head); color: var(--et-sur-ardoise-plein); }
.tbl-etat-opt:focus-visible { outline: 2px solid var(--tbl-accent); outline-offset: -2px; }

/* Menu de colonnes — dérivé des colonnes .Optionnelle(), plus de dictionnaire à tenir */
.tbl-menu { position: relative; }
.tbl-fond { position: fixed; inset: 0; z-index: 1999; background: transparent; }
/* 2026-08-17 : aux jetons de la charte. Il tirait son fond et son filet de --ph-bg /
   --ph-border, jetons de la COQUILLE prevus pour les panneaux d'attente : deux gris
   voisins de ceux de la charte, mais qui ne suivaient aucune de ses bascules. Et
   au-dela du fond, ils n'existent que sous .appgrid — un menu rendu hors de la coquille
   retombait sur du transparent.
   L'ombre suit la passation, et sa valeur EST devenue le jeton --et-ombre-menu
   (2026-09-05) : une liste de cases a cocher n'a pas a se detacher comme une modale,
   elle est posee sur le tableau et non devant lui. C'est ce rang-la que le jeton
   nomme, et c'est cette regle-ci qui l'a fixe — deux autres feuilles ecrivaient la
   meme valeur sans le savoir. */
.tbl-menu-liste {
    position: absolute; top: calc(100% + 5px); left: 0; z-index: 2000; min-width: 240px;
    background: var(--et-surface); border: 1px solid var(--et-hairline);
    box-shadow: var(--et-ombre-menu); padding: 6px 0;
    animation: cbp-ouvre .12s ease-out;
}
.tbl-menu-item { display: flex; align-items: center; gap: 9px; padding: 6px 14px; font-size: 13px; color: var(--et-ink); cursor: pointer; }
.tbl-menu-item:hover { background: var(--et-tint); }
/* Case carree et bleue, comme celles du tableau et du panneau de filtres. C'etait la
   case native du navigateur, donc bleu systeme sur un ecran, gris sur un autre. */
/* Taille retiree le 2026-09-10 : la case prend les 17 px du gabarit (app.css),
   et 24 px sous 1024 px (lot02). Voir docs/cibles-tactiles.md. */
.tbl-menu-item input { border-radius: 0; cursor: pointer; }
.tbl-menu-act {
    display: flex; align-items: baseline; gap: 10px; width: 100%; padding: 8px 14px;
    border: 0; background: transparent; color: var(--et-ink); font-family: inherit;
    font-size: 13px; text-align: left; cursor: pointer;
}
.tbl-menu-act:hover { background: var(--et-tint); }
.tbl-menu-act i { width: 15px; flex: none; color: var(--et-muted); }
.tbl-menu-act span { font-weight: 600; }
.tbl-menu-act em { margin-left: auto; font-style: normal; font-size: 12px; color: var(--et-faint); }

/* --- Menu d'export : portee annoncee et vignettes d'extension ---------------
   « Il annonce sa portee en tete » : la ligne de portee n'est ni un titre ni un
   element cliquable, d'ou le fond alterne et le gris de libelle — elle se lit avant
   les trois formats, sans se confondre avec eux. */
.tbl-menu-export { width: 250px; }
.tbl-menu-portee {
    padding: 8px 14px 9px; margin-bottom: 4px;
    background: var(--et-surface-3); border-bottom: 1px solid var(--et-hairline);
    font-size: 12px; color: var(--et-muted);
}
/* La vignette d'extension : elle porte le FORMAT, la seule chose qui distingue les
   trois lignes. En mono et en capitales, dans la paire semantique du format — vert
   pour le CSV (texte brut, sans perte), bleu pour le classeur, rouge pour le PDF,
   qui est le seul des trois qu'on ne peut pas rouvrir pour corriger. */
.tbl-ext {
    flex: none; width: 38px; padding: 3px 0; text-align: center;
    font-family: var(--et-font-mono); font-size: 12px; font-weight: 500; letter-spacing: .08em;
}
.tbl-ext-csv  { background: var(--et-succes-bg); color: var(--et-succes-ink); }
.tbl-ext-xlsx { background: var(--et-tint);      color: var(--et-form-blue-encre); }
.tbl-ext-pdf  { background: var(--et-danger-badge-bg); color: var(--et-danger-ink); }
/* Les trois lignes s'alignent sur la vignette, pas sur la ligne de base du texte :
   une pastille de 20 px et un libelle de 13 px n'ont pas la meme. */
.tbl-menu-export .tbl-menu-act { align-items: center; }

/* Filet de separation et action de pied, dans un menu a cocher. */
.tbl-menu-sep { display: block; height: 1px; margin: 6px 0; background: var(--et-hairline); }
.tbl-menu-tout {
    display: flex; align-items: center; gap: 8px; width: 100%; padding: 7px 14px;
    border: 0; background: transparent; color: var(--et-form-blue-encre);
    font-family: inherit; font-size: 13px; font-weight: 600; text-align: left; cursor: pointer;
}
.tbl-menu-tout:hover:enabled { background: var(--et-tint); color: var(--et-form-blue-d); }
/* Inerte quand tout est deja affiche : le bouton reste VISIBLE plutot que de
   disparaitre. Un bouton qui s'efface fait douter de l'avoir vu, et son absence ne dit
   pas la meme chose que sa version grisee — « il n'y a rien a reafficher ». */
.tbl-menu-tout:disabled { color: var(--et-inerte); cursor: not-allowed; }

/* --- La table --- */
.tbl-defile { overflow-x: auto; background: var(--et-surface); }
.tbl { width: 100%; border-collapse: collapse; font-size: 13px; line-height: 1.3; color: var(--et-ink); }
/* La tete porte le fond du mobilier — arbitrage rendu apres recette du pilote.
   Registre pur laissait la zone de donnees en bloc blanc uni : douze colonnes sans
   rien pour tenir la ligne, et un zebrage a #fbfcfe (1,5 % du blanc) qui ne fait pas
   repere. La tete cesse d'etre une bande de texte flottante, la separation tete/corps
   ne repose plus sur un seul filet, et l'accent orange de la colonne triee ressort
   mieux sur le gris que sur le blanc.
   C'est un pas assume vers la proposition « Ligne claire » : la tete calme de B, le
   double filet marine et l'accent de C. */
/* Tete en GRIS FONCE. Le gris clair ne separait pas assez la tete du corps sur une
   liste dense ; le gris fonce l'ancre sans revenir au bandeau bleu de marque, dont
   tout le probleme etait de ne pas basculer par theme.
   Le lisere ambre reprend la signature de la charte — meme 3px que la barre du haut
   de la coquille, meme role : marquer une limite haute.
   Contrastes mesures : clair, blanc sur #374151 = 10,31:1 et ambre = 4,69:1 ;
   sombre, #e5edf5 sur #243146 = 11,08:1 et ambre = 5,96:1. */
/* 2026-08-17 : l'en-tete passe en IBM PLEX MONO, 10,5 px capitales, chasse .14em,
   avec un filet inferieur #2C3E50. La mono n'est pas un ornement : elle donne aux
   libelles de colonne la meme largeur de glyphe qu'aux valeurs qu'ils coiffent
   (matricules, dates, heures, montants, tous en mono dans la passation), si bien
   qu'une colonne de chiffres ne se retrouve plus plus large ou plus etroite que son
   titre. Le filet inferieur separe la tete du corps sans reposer sur le seul saut
   de teinte — il porte quand la tete defile sous une ligne selectionnee. */
.tbl thead th {
    color: var(--tbl-tete-encre); font-family: var(--et-font-mono); font-size: 12px;
    font-weight: 500; letter-spacing: .14em;
    /* Le vertical vient du jeton partage --et-cellule-tete-y : les deux familles
       d'en-tete tiennent desormais leur hauteur du meme endroit, comme les corps
       de rangee la tiennent de --et-cellule-y. */
    text-transform: uppercase; text-align: left;
    padding: var(--et-cellule-tete-y) 10px;
    border-bottom: 1px solid var(--et-table-head-fonce); white-space: nowrap;
    background: var(--tbl-tete-fond);
}
.tbl thead th.tbl-triable { cursor: pointer; user-select: none; }
.tbl thead th.tbl-triable:hover { background: var(--tbl-tete-actif); }
/* Colonne triee : panneau plus fonce, texte blanc conserve. */
.tbl thead th.tbl-actif { background: var(--tbl-tete-actif); }
.tbl-fleche { font-size: 12px; margin-left: 4px; color: var(--tbl-accent); }
.tbl tbody tr:nth-child(even) td { background: var(--tbl-zebre); }
/* DENSITE. La hauteur de ligne mesuree avant correction etait de 79 px — trois fois
   le necessaire. Le padding n'y etait pour presque rien : la cause etait la colonne
   d'actions, dont les trois boutons de 32 px totalisaient EXACTEMENT la largeur de la
   cellule, si bien que le troisieme passait a la ligne et doublait la hauteur.
   La regle qui reduit ces boutons a 26 px (easytech-theme.css) cible « .table » ; ce
   composant utilise « .tbl », elle ne s'appliquait donc jamais. D'ou les deux blocs
   ci-dessous : d'abord empecher le retour a la ligne, ensuite seulement resserrer. */
/* 2026-08-20 : hauteur FIGEE, une seule valeur pour tous les modules. Le reglage
   11 px / 7 px du 2026-08-17 est retire : il rendait une ligne de « .tbl » a 39,9 px
   la ou le « .table » Bootstrap habille — le catalogue, pris pour reference — en
   servait une de 22,9 px. Deux composants, deux densites, aucune regle de charte
   pour arbitrer : c'est ce que --et-cellule-y (easytech-theme.css) tranche.
   L'interligne descend de 1,3 a 1,15, valeur que « .table td » applique deja depuis
   le bloc « Lignes de liste compactes » : sans elle, le seul rembourrage ne suffit
   pas a rejoindre la reference. Mesure sous Chromium apres coup : 22,3 px la ligne
   de texte, 31,4 px la ligne d'actions, contre 22,9 et 31,4 au catalogue. */
.tbl tbody td { padding: var(--et-cellule-y) 10px; line-height: 1.15; border-bottom: 1px solid var(--tbl-filet); }
.tbl tbody tr { height: 1px; }   /* laisse la ligne se reduire a son contenu */
/* Colonne d'actions : jamais de retour a la ligne, et des boutons a la taille du texte. */
.tbl .tbl-mid { white-space: nowrap; }
.tbl .btn-sm, .tbl .btn.btn-sm {
    width: 24px; height: 24px; padding: 0; border-radius: 0; border-width: 1px;
    display: inline-flex; align-items: center; justify-content: center; font-size: 12px;
    line-height: 1; vertical-align: middle;
}
.tbl .btn-sm + .btn-sm, .tbl .btn-sm.ms-1 { margin-left: 3px !important; }

/* LA RANGÉE DE COMMANDES DE FIN DE LIGNE (.tbl-actions).

   ELLE ÉTAIT ÉCRITE DANS TROIS ÉCRANS ET DÉFINIE DANS AUCUNE FEUILLE — même
   relevé que .mx-btn-mini (modele-erp.css §1), le 2026-09-08 : Abonnes,
   Sauvegardes et Tenants portent un `<td class="tbl-actions">` que la cascade
   ne trouvait nulle part. Les boutons y tombaient donc au fil du texte, avec
   l'espace d'un mot entre deux et un retour à la ligne dès la cellule étroite.

   À NE PAS CONFONDRE AVEC .tbl-mid, juste au-dessus : celui-là est posé par
   ColonneTableau.Alignement sur la CELLULE d'une colonne de type Action — il
   dit « centrée, sans retour à la ligne ». Celle-ci est le CONTENEUR des
   boutons à l'intérieur de la cellule, et c'est lui qui porte l'écart entre
   deux commandes. Les deux se cumulent, et un écran peut n'avoir que l'un :
   une colonne Action dont le rendu ne tient qu'un bouton n'a rien à espacer.

   3 px, comme `.tbl .btn-sm + .btn-sm` juste au-dessus : deux commandes de fin
   de ligne se lisent comme un groupe, pas comme deux boutons indépendants — la
   règle du lot 02 sur l'écart de 10 px vise les commandes INDÉPENDANTES d'une
   barre, ce que ces icônes ne sont pas.

   `justify-content: flex-end` : la colonne est en bout de ligne, ses boutons se
   rangent donc contre le bord droit et non au centre de la place qui reste —
   sans quoi deux lignes aux nombres d'actions différents décalent leurs
   boutons l'une par rapport à l'autre, et l'œil perd la colonne. */
.tbl .tbl-actions {
    display: inline-flex; align-items: center; justify-content: flex-end;
    gap: 3px; white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   LE RANG BOUTON DE CETTE RANGEE (.tbl-action), ET SON EMPLACEMENT RESERVE.

   DEUX SOLUTIONS AU MEME DEFAUT SONT ARRIVEES LE MEME JOUR, 2026-09-08 : le
   conteneur ci-dessus (.tbl-actions, six ecrans d'administration en
   .mx-btn-mini) et une rangee a emplacements fixes ecrite pour quatre listes
   metier en .btn.btn-sm. Un role, un nom : le conteneur retenu est celui-ci,
   arrive le premier dans main. Ce qui suit est ce que la seconde apportait EN
   PLUS, verse dans la meme famille.

   POURQUOI UN RANG BOUTON. La regle `.tbl .btn-sm` plus haut donne au bouton de
   ligne une boite de 24 x 24 px SANS REMBOURRAGE : elle est dimensionnee pour un
   GLYPHE. Un ecran qui y ecrit un mot le fait deborder sur le bouton voisin --
   la liste des utilisateurs rendait « SortieDesactiver » en un seul mot, et
   elargir la colonne n'y pouvait rien. .tbl-action habille ce glyphe : encre de
   lien, aplat au survol, et le rang ENCRE pour les etats (une icone est de
   l'encre posee sur le fond de ligne, qui bouge au survol ; --et-danger y
   perdrait le AA que --et-danger-ink tient sur les trois fonds).

   POURQUOI UN EMPLACEMENT VIDE. `justify-content: flex-end` aligne le BORD
   DROIT de la rangee, ce qui suffit quand toutes les lignes portent les memes
   commandes. Des que le nombre varie -- un compte verrouille, une periode par
   defaut, un role du modele -- la troisieme icone d'une ligne se retrouve sous
   la deuxieme d'une autre, et il faut relire chaque rangee. .tbl-action-vide est
   la boite d'un bouton, vide : elle ne se voit pas, elle tient la colonne. Un
   ecran en rend un la ou le geste ne s'applique pas.

   LARGEUR A DECLARER SUR LA COLONNE : n x 24 px + (n-1) x 3 px d'ecart + 20 px
   de rembourrage de cellule -- soit 152 px a cinq gestes, 125 a quatre, 98 a
   trois. CES TROIS NOMBRES SONT MESURES sous Chromium avec les feuilles reelles,
   non calcules de tete : une version anterieure de ce bloc en annoncait trois
   autres, huit pixels de trop partout, faute d'avoir pose l'addition. Ils
   dependent du `gap` du conteneur ci-dessus : le porter de 3 a 5 px les
   deplacerait tous les trois. */

/* L'ecart est porte par le `gap` du conteneur, qui vaut aussi entre un bouton et
   un emplacement vide ; deux mecanismes superposes donneraient deux valeurs
   selon que le voisin est present ou non. VISE `.btn.btn-sm` ET RIEN D'AUTRE :
   les six ecrans d'administration ci-dessus sont en .mx-btn-mini, que cette
   regle ne touche pas -- leur espacement ne bouge pas d'un pixel. */
.tbl .tbl-actions > .btn.btn-sm + .btn.btn-sm { margin-left: 0 !important; }

.tbl-action { flex: none; color: var(--et-form-blue); text-decoration: none; }
.tbl-action:hover:not(:disabled) { background: var(--et-tint); color: var(--et-form-blue-d); }
.tbl-action:focus-visible { outline: 2px solid var(--et-form-blue); outline-offset: 1px; }

/* Un geste indisponible reste VISIBLE et garde : son `title` nomme la raison.
   L'effacer ferait chercher le bouton. */
.tbl-action:disabled, .tbl-action.disabled { color: var(--et-inerte); }

.tbl-action.est-danger { color: var(--et-danger-ink); }
.tbl-action.est-danger:hover:not(:disabled) { background: var(--et-danger-badge-bg); color: var(--et-danger-ink); }
.tbl-action.est-attention { color: var(--et-avertissement-ink); }
.tbl-action.est-attention:hover:not(:disabled) { background: var(--et-avertissement-bg); color: var(--et-avertissement-ink); }

.tbl-action-vide { flex: none; width: 24px; height: 24px; }

/* CIBLES TACTILES (docs/cibles-tactiles.md) -- sous 1024 px aucune cible du
   gabarit de liste ne descend sous 44 px. `.tbl td .btn` est deja porte a 44 px
   par lot02-cibles-tactiles.css ; l'emplacement vide, qui n'est PAS un `.btn`,
   doit suivre le meme pas ou la colonne se desaligne la ou elle sert le plus.
   Le palier est RECOPIE de lot02 (`max-width: 1024px`, donc inclus) et non
   deduit a 1023 : un ecart d'une unite ne se voit sur aucune capture, seulement
   a 1024 px pile. */
@media (max-width: 1024px) {
    .tbl-action-vide { width: 44px; height: 44px; }
}
.tbl .badge { padding: 1px 7px; font-size: 12px; line-height: 1.45; }
.tbl tbody tr:hover td { background: var(--tbl-survol); }
.tbl tfoot td { padding: 9px 14px; font-weight: 800; border-top: 2px solid var(--tbl-tete-fond); background: var(--tbl-chrome); }
/* Alignements déduits du TYPE de colonne : l'écran ne les écrit plus (text-end
   apparaissait à la main dans 295 fichiers). */
.tbl .tbl-num { text-align: right; font-variant-numeric: tabular-nums; }
/* Chasse fixe sur les dates et les nombres — « matricules, dates et durees en IBM Plex
   Mono 12,5 px ». La classe est posee par ColonneTableau.Alignement, deduite du TYPE de
   colonne : aucun ecran ne l'ecrit, et une colonne de dates ajoutee un jour l'obtient
   sans que personne y pense. */
.tbl .tbl-mono { font-family: var(--et-font-mono); font-size: 13px; }
/* La mono NE RAPETISSE PAS en compacte : la densité ne touche qu'au padding
   vertical des cellules. Deux corps de police pour la même colonne rendaient deux
   captures d'un même écran non comparables. */
/* Le tiret « non renseigne ». Inerte, mais LISIBLE : il doit se distinguer d'une cellule
   vide sans se lire comme une valeur. */
.tbl .tbl-vide { color: var(--et-inerte); }
.tbl .tbl-mid { text-align: center; }
/* Ligne signalée par l'écran (ClasseLigne) : liseré plutôt qu'aplat, pour ne pas
   entrer en conflit avec le zébrage. */
/* Etat CRITIQUE de Fiori (#FEF7F1 / #E9730C) et non plus un ambre a soi : une ligne
   signalee par l'ecran porte desormais la meme paire que la pastille « critique »
   qu'elle contient souvent, au lieu d'une troisieme teinte voisine. */
.tbl tbody tr.tbl-alerte td { background: var(--et-avertissement-bg); }
.tbl tbody tr.tbl-alerte td:first-child { box-shadow: inset 3px 0 0 var(--et-avertissement); }
/* Une valeur inerte est GRISE, pas effacee : elle reste lisible, elle cesse d'attirer. */
.tbl tbody tr.tbl-terne td { color: var(--et-inerte); }
/* INERTE va plus loin que TERNE : la ligne n'est pas seulement secondaire, elle n'est pas une
   decision — c'en est la consequence (une exclusion de rotation est posee PAR une autre
   affectation). Fond retire du blanc en plus du texte attenue, pour qu'on ne la lise pas
   comme une ligne saisie a la main qu'on pourrait supprimer sans consequence. */
.tbl tbody tr.tbl-inerte td { background: var(--et-surface-3); color: var(--et-faint); }
/* Le pendant sur une CELLULE — « sans fin », « — », un compte a zero — est
   .text-inerte, defini avec le bloc Cycles de modele-erp.css. Une seule fois. */
.tbl-etat td { text-align: center; padding: 40px 14px !important; color: var(--et-muted); background: none !important; }

/* DENSITÉ RÉGLABLE — RETIRÉE le 2026-08-20.
   .tbl-dense n'existe plus. La classe ne portait qu'une chose : le rembourrage
   vertical des cellules de corps. La hauteur une fois figée par --et-cellule-y,
   elle n'avait plus rien à changer — et un bouton de densité sans effet vaut moins
   qu'un bouton absent. Il a donc été retiré de la barre d'outils de Tableau.razor
   en même temps que cette règle. */

/* --- Pied : plage lue, choix du nombre de lignes, saut aux extrémités --- */
.tbl-pied { display: flex; align-items: center; gap: 12px; row-gap: 10px; flex-wrap: wrap; padding: 12px 18px; border-top: 1px solid var(--et-hairline); background: var(--tbl-chrome); font-size: 13px; color: var(--et-muted); }
/* La plage lue est un DECOMPTE : mono, comme tous les nombres de la passation. */
/* La plage pousse tout le mobilier du pied a droite. Marge sur ELLE et non sur son
   voisin : le pied compte cinq groupes, et celui qui ouvre la partie droite change
   selon ce que l'ecran offre — une marge posee sur l'un d'eux se retrouve au milieu
   des que cet element manque. */
/* La plage est une PHRASE, pas un relevé de nombres : elle reste en Open Sans. La
   mono lui donnait une allure de compteur et l'alignait de travers avec le reste du
   pied, qui est en texte courant.
   Le rapport qui la suit, lui, EST un relevé — deux nombres qu'on lit en colonne
   d'un écran à l'autre — et il garde la mono. */
.tbl-plage { margin-right: auto; display: inline-flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.tbl-plage-ratio { font-family: var(--et-font-mono); font-size: 12px; color: var(--et-faint); font-variant-numeric: tabular-nums; }

/* Intitule de reglage au pied — « DENSITE », « LIGNES ». Mono capitales, comme tous
   les surtitres de la charte, et volontairement plus petit que ce qu'il coiffe : il
   nomme le groupe, il n'est pas l'un de ses boutons. */
.tbl-pied-lbl {
    font-family: var(--et-font-mono); font-size: 12px; font-weight: 500;
    text-transform: uppercase; letter-spacing: .12em; color: var(--et-muted);
    white-space: nowrap;
}
/* « LIGNES » d'un ton plus clair que « DENSITÉ », et ce n'est pas une variation
   décorative : le premier commande une PROPRIÉTÉ D'AFFICHAGE, le second une
   QUANTITÉ DE DONNÉES. Deux natures, deux poids — l'œil qui cherche à changer la
   taille de page ne s'arrête pas d'abord sur la densité. */
.tbl-pied-lbl.est-secondaire { color: var(--et-faint); }

/* Groupe de boutons accoles — densite, lignes par page. Une seule bordure autour du
   groupe, les separations par border-right : c'est ce qui les fait lire comme UN
   controle a plusieurs positions, et non comme trois boutons voisins.
   Actif en ardoise pleine, comme le selecteur de vue : meme grammaire, meme signal. */
/* La marge droite détache le groupe de l'intitulé du groupe SUIVANT : sans elle,
   « Compacte » et « LIGNES » se touchent, et l'intitulé se lit comme un troisième
   segment du premier contrôle. */
.tbl-groupe { display: inline-flex; flex: none; border: 1px solid var(--et-form-border); overflow: hidden; margin-right: 6px; }
.tbl-groupe > button {
    height: 34px; min-width: 34px; padding: 0 9px;
    border: 0; border-right: 1px solid var(--et-form-border);
    background: var(--et-surface); color: var(--et-ink);
    font-family: inherit; font-size: 13px; line-height: 1; cursor: pointer;
    white-space: nowrap;
}
.tbl-groupe > button:last-child { border-right: 0; }
.tbl-groupe > button:hover { background: var(--et-rang); }
/* LE STYLE SUIT UNE CLASSE, PAS L'ATTRIBUT ARIA. Il suivait [aria-pressed="true"],
   et ne s'appliquait donc JAMAIS : Blazor traite une valeur d'attribut de type bool
   comme un attribut booleen HTML — il ecrit « aria-pressed » sans valeur quand c'est
   vrai, et n'ecrit rien quand c'est faux. Le selecteur cherchait la chaine « true »,
   qui n'etait jamais rendue.

   Le defaut se voyait deux fois : le bouton actif restait blanc, et l'ARIA etait
   invalide — aria-pressed n'accepte que « true », « false » ou « mixed », jamais une
   valeur vide. Une aide technique annoncait donc un groupe dont aucun bouton n'est
   enfonce.

   Regle qui en decoule : ne jamais faire porter un STYLE par un attribut ARIA rendu
   depuis un bool. L'ARIA decrit, la classe habille. */
.tbl-groupe > button.est-actif {
    background: var(--et-table-head); color: var(--et-sur-ardoise-plein); font-weight: 600;
}
/* L'actif ne réagit pas au survol : il ne se sélectionne pas deux fois, et un
   changement de fond sous le curseur laisserait croire qu'il va se passer quelque
   chose. */
.tbl-groupe > button.est-actif:hover { background: var(--et-table-head); }
/* Le groupe des lignes par page porte des NOMBRES à deux ou trois chiffres, pas des
   mots : un peu plus large, un peu moins de padding, et les quatre boutons font la
   même largeur au lieu de suivre leur contenu. */
.tbl-groupe.est-lignes > button { min-width: 36px; padding: 0 8px; }
.tbl-groupe > button:focus-visible { outline: 2px solid var(--et-form-blue); outline-offset: -2px; }
/* Ellipse de pagination : ce n'est pas un bouton, elle ne doit pas en avoir l'air. */
.tbl-pg-ell { padding: 0 2px; color: var(--et-inerte); font-family: var(--et-font-mono); user-select: none; }
/* .tbl-taille : RETIRE le 2026-08-17. Les lignes par page etaient une liste deroulante
   poussee a droite ; le gabarit en fait un groupe de boutons accoles (.tbl-groupe), et
   la gouttiere automatique est passee sur .tbl-plage. */
/* 7 px, comme les autres contrôles du pied : les boutons de pagination sont
   DÉTACHÉS, contrairement aux segmentés — ce ne sont pas les valeurs d'un même
   réglage mais trois gestes distincts. La gouttière le dit. */
.tbl-nav { display: inline-flex; align-items: center; gap: 7px; flex-wrap: wrap; row-gap: 7px; }
/* « La page courante porte bordure #0A6ED1, fond #EBF3FB, texte #0854A0. JAMAIS
   D'ORANGE SUR UN NUMERO DE PAGE. Un bouton de pagination inerte est en #B3B6B9
   avec cursor: not-allowed. »
   Le not-allowed plutot que le default : il dit qu'on a atteint une borne, la ou le
   curseur par defaut laisse croire que le clic n'a pas ete pris. */
.tbl-pg {
    display: inline-flex; align-items: center; justify-content: center; min-width: 34px; height: 34px;
    border: 1px solid var(--et-form-border); background: var(--et-surface); color: var(--et-ink);
    cursor: pointer; font-size: 13px; line-height: 1; font-family: var(--et-font-mono);
}
/* Survol DISCRET : la bordure se fonce, rien d'autre. Le fond bleu qu'il portait
   était celui de la page COURANTE : survoler « 3 » depuis la page 1 donnait deux
   boutons d'apparence courante en même temps. */
.tbl-pg:hover:not(:disabled) { border-color: var(--et-form-border); }
.tbl-pg.est-courante {
    border-color: var(--et-form-blue); background: var(--et-tint);
    color: var(--et-form-blue-d); font-weight: 600;
}
.tbl-pg:disabled { color: var(--et-inerte); border-color: var(--et-hairline); background: var(--et-surface); cursor: not-allowed; }
/* « Précédent » et « Suivant » portent un mot, pas un chiffre : police courante,
   nowrap (Open Sans est large), et pas de largeur minimale carrée. */
.tbl-pg-lbl { padding: 0 11px; font-family: var(--et-font); font-size: 13px; font-weight: 400; white-space: nowrap; }
.tbl-saut { width: 58px; height: 34px; padding: 0 6px; text-align: center; border: 1px solid var(--et-form-border); background: var(--et-surface); color: var(--et-ink); font-family: var(--et-font-mono); font-variant-numeric: tabular-nums; }
.tbl-sur { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Impression : la coquille disparaît déjà (bloc @media print plus haut) ; ici on
   retire le mobilier propre au tableau, qui n'a aucun sens sur papier. */
@media print {
    .tbl-barre, .tbl-pied { display: none !important; }
    .tbl-defile { overflow: visible !important; }

    /* L'EN-TÊTE D'ÉCRAN DE MODULE EST DU MOBILIER, ET IL PARTAIT AU PAPIER.
       Relevé à la recette d'impression du 2026-09-11, sur l'application qui tourne :
       neuf écrans sur quinze imprimaient des liens. Un fil d'Ariane
       (« Consolidation », « EasyPayroll », « File des tickets ») dit d'où l'on vient —
       sur une feuille, il ne mène nulle part ; les actions d'en-tête portaient
       « Recalculer » et, sur le coût complet, le bouton « Imprimer » lui-même.

       La règle est ici et non dans chaque écran parce que .ecran-fil et .et-bandeau-actions
       appartiennent à EcranModule, que 152 écrans montent : une règle par écran serait
       152 copies, et la 153e serait oubliée. Les pastilles de référence (CUT-02,
       « Consultation / état », « Important ») partent avec les actions, dans le même
       conteneur : ce sont des repères de conception, pas des données de la pièce.

       Le titre et la description, eux, RESTENT — une feuille sans titre ne se classe pas. */
    .ecran-fil,
    .et-bandeau-actions,
    .liste-entete > .ms-auto { display: none !important; }
}
/* Recherche générique du tableau */
.tbl-recherche { position: relative; display: inline-flex; align-items: center; flex: 1 1 220px; max-width: 300px; }
.tbl-recherche > .bi-search { position: absolute; left: 10px; color: var(--et-muted); font-size: 13px; pointer-events: none; }
.tbl-recherche input { width: 100%; height: 31px; padding: 0 26px 0 30px; font-size: 13px; font-family: inherit;
                       color: var(--et-ink); background: var(--et-surface); border: 1px solid var(--et-form-border); outline: none; }
.tbl-recherche input:focus { border-color: var(--et-form-blue); box-shadow: none; }
.tbl-vider { position: absolute; right: 6px; border: 0; background: none; color: var(--et-muted); font-size: 18px; line-height: 1; cursor: pointer; padding: 0 4px; }
.tbl-vider:hover { color: var(--et-ink); }
.tbl-filtre-actif { color: var(--et-faint); margin-left: 10px; font-family: var(--et-font); }

/* --- Sélecteur de période en liste déroulante (composant ComboPeriode) --------
   Il remplace depuis le 2026-08-17 le panneau en ligne .per-* (SelecteurBornes),
   dont le bloc a été retiré plus bas. Deux hôtes aujourd'hui : la colonne de filtre
   de 268 px du planning et celle du relevé d'heures.

   Aligné sur le mobilier du tableau unifié : 31 px de haut, 13 px, angles vifs et
   filet --tbl-filet — il se pose donc aussi bien dans une .tbl-barre, à côté de
   .tbl-recherche et des boutons, que dans une colonne latérale.

   Les couleurs passent toutes par les jetons : le thème sombre suit sans règle
   dédiée, sauf le panneau flottant dont l'ombre doit s'appuyer plus fort. */
/* L'ENSEMBLE — intitulé, flèche, combo, flèche.
   Le cadre s'enroule (wrap) parce que son premier hôte est la colonne de filtre de
   268 px : l'intitulé y prend une ligne à lui seul (flex-basis 100 %), et la rangée
   de commande garde les 268 px pour elle. Posé dans une barre large, le même cadre
   met tout sur une ligne sans règle supplémentaire — c'est le wrap qui décide, pas
   une media query par hôte. */
.cbp-cadre { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.cbp-lbl {
    flex: 1 0 100%;
    font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
    color: var(--et-muted);
}
/* La combo prend la place qui reste entre les deux flèches, et peut rétrécir :
   min-width:0 est ce qui autorise .cbp-plage à s'ellipser au lieu de pousser la
   flèche droite hors du cadre. */
.cbp { position: relative; display: inline-block; flex: 1 1 auto; min-width: 0; }

/* LES FLÈCHES — même hauteur et même filet que la combo, carrées.
   Elles ne portent pas l'accent : ce sont deux gestes de répétition, et les teinter
   les mettrait au même rang que le choix de période, qui est le geste porteur. */
.cbp-fleche {
    flex: none;
    display: inline-flex; align-items: center; justify-content: center;
    width: 31px; height: 31px;
    border: 1px solid var(--et-form-border); background: var(--et-surface);
    color: var(--et-ink); font-size: 13px; line-height: 1; cursor: pointer;
    transition: border-color .12s, color .12s;
}
.cbp-fleche:hover { border-color: var(--tbl-accent); color: var(--tbl-accent); }
.cbp-fleche:focus-visible { outline: 2px solid var(--tbl-accent); outline-offset: -2px; }

.cbp-btn {
    display: inline-flex; align-items: center; gap: 8px;
    height: 31px; padding: 0 10px; width: 100%; max-width: 100%;
    border: 1px solid var(--et-form-border); background: var(--et-surface);
    color: var(--et-ink); font-size: 13px; font-family: inherit; line-height: 1;
    cursor: pointer; transition: border-color .12s, box-shadow .12s;
}
.cbp-btn:hover { border-color: var(--tbl-accent); }
.cbp.ouvert .cbp-btn { border-color: var(--tbl-accent); box-shadow: 0 0 0 3px var(--et-focus); }
.cbp-btn:focus-visible { outline: 2px solid var(--tbl-accent); outline-offset: -2px; }

.cbp-ico { color: var(--tbl-accent); font-size: 14px; }
.cbp-lib { font-weight: 600; white-space: nowrap; }
/* Les bornes s'effacent en premier quand la barre se resserre : le libellé, lui,
   doit rester lisible jusqu'au bout. */
.cbp-plage {
    /* flex + min-width:0 : sans eux, text-overflow:ellipsis ne se déclenche jamais dans
       un conteneur flex — l'élément refuse de descendre sous sa largeur de contenu et
       c'est le voisin qui déborde à sa place. */
    flex: 1 1 auto; min-width: 0;
    color: var(--et-muted); font-size: 12px; font-variant-numeric: tabular-nums;
    padding-left: 8px; border-left: 1px solid var(--tbl-filet);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* auto plutôt que 2 px : le chevron reste collé au bord droit quel que soit ce que le
   libellé et les bornes occupent — c'est le repère qui dit « ceci s'ouvre », et il ne
   doit pas se déplacer d'une période à l'autre. */
.cbp-chev { margin-left: auto; padding-left: 2px; color: var(--et-muted); font-size: 12px; transition: transform .15s; }
.cbp.ouvert .cbp-chev { transform: rotate(180deg); }

.cbp-voile { position: fixed; inset: 0; z-index: 1040; background: transparent; }

.cbp-panneau {
    position: absolute; z-index: 1041; top: calc(100% + 4px); left: 0;
    min-width: 268px; padding: 4px;
    background: var(--et-surface); border: 1px solid var(--tbl-filet);
    box-shadow: var(--et-ombre-flottant);
    animation: cbp-ouvre .12s ease-out;
}
@keyframes cbp-ouvre { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

.cbp-item {
    display: flex; align-items: center; gap: 9px; width: 100%;
    padding: 7px 9px; border: 0; border-left: 2px solid transparent; background: transparent;
    color: var(--et-ink); font-size: 13px; font-family: inherit; text-align: left; cursor: pointer;
}
.cbp-item:hover { background: var(--tbl-survol); }
.cbp-item.actif { background: var(--et-surface-2); border-left-color: var(--tbl-accent); font-weight: 600; }
.cbp-item:focus-visible { outline: 2px solid var(--tbl-accent); outline-offset: -2px; }
.cbp-item-ico { width: 16px; text-align: center; color: var(--et-muted); font-size: 13px; }
.cbp-item.actif .cbp-item-ico { color: var(--tbl-accent); }
.cbp-item-lib { white-space: nowrap; }
/* L'indice pousse à droite et ne concurrence jamais le libellé : c'est un repère,
   pas une donnée — d'où le gris, le corps réduit et les chiffres tabulaires. */
.cbp-item-ind {
    margin-left: auto; padding-left: 12px;
    color: var(--et-muted); font-size: 12px; font-weight: 400;
    font-variant-numeric: tabular-nums; white-space: nowrap;
}

.cbp-sep { height: 1px; margin: 4px 2px; background: var(--tbl-filet); }

.cbp-perso { display: grid; gap: 8px; padding: 4px 9px 8px; }
.cbp-perso-champs { display: flex; align-items: center; gap: 6px; }
.cbp-perso-fleche { color: var(--et-muted); font-size: 12px; }
.cbp-date {
    flex: 1 1 0; min-width: 0; height: 29px; padding: 0 6px;
    border: 1px solid var(--et-form-border); background: var(--et-surface); color: var(--et-ink);
    font-size: 13px; font-family: inherit; font-variant-numeric: tabular-nums;
}
.cbp-date:focus { outline: none; border-color: var(--tbl-accent); }
.appgrid[data-theme="dark"] .cbp-date::-webkit-calendar-picker-indicator { filter: invert(1) opacity(.7); }
.cbp-perso-erreur { color: var(--et-danger-ink); font-size: 12px; }
/* BLEU, ET NON ORANGE — écart assumé sur le bloc d'origine, qui datait d'avant la
   bascule de charte du 2026-08-17. L'orange y est réservé à L'UNIQUE bouton
   d'engagement de l'écran ; « Appliquer » valide une saisie de dates à l'intérieur
   d'un menu, et le planning a déjà son bouton orange (Publier). Deux oranges sur le
   même écran ne désignent plus rien. */
.cbp-appliquer {
    height: 29px; border: 1px solid var(--et-form-blue); background: var(--et-form-blue);
    color: var(--et-sur-aplat); font-size: 13px; font-weight: 600; font-family: inherit; cursor: pointer;
}
/* Aplat sous du blanc, comme .md-save : le jeton PLEIN, pas l'encre. */
.cbp-appliquer:hover:not(:disabled) { background: var(--et-form-blue-plein); border-color: var(--et-form-blue-plein); }
.cbp-appliquer:disabled { opacity: .5; cursor: default; }

@media (max-width: 620px) {
    .cbp-plage { display: none; }
    .cbp-panneau { min-width: 240px; }
}

/* --- État VIGNETTES ------------------------------------------------------------
   Réponse au trou responsive relevé sur le dépôt : aucun écran ne bascule en cartes,
   un tableau de douze colonnes défile latéralement sur téléphone. La carte relit la
   même déclaration de colonnes — rien n'est redéclaré ici. */
.tbl-vignettes { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 12px; padding: 14px; }
.tbl-vig { border: 1px solid var(--tbl-filet); border-top: 2px solid var(--tbl-tete-fond); background: var(--et-surface); padding: 12px 14px 13px; }
.tbl-vig.tbl-alerte { border-top-color: var(--et-amber); background: var(--et-avertissement-bg); }
.tbl-vig.tbl-terne { opacity: .68; }
.tbl-vig-haut { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 8px; min-height: 22px; }
.tbl-vig-id { font-family: ui-monospace, 'Cascadia Mono', Menlo, monospace; font-size: 12px; color: var(--et-muted); letter-spacing: .04em; }
.tbl-vig h4 { margin: 0 0 9px; font-size: 14px; font-weight: 650; line-height: 1.35; color: var(--et-ink); }
.tbl-vig-chiffre { font-size: 20px; font-weight: 700; line-height: 1.1; font-variant-numeric: tabular-nums; color: var(--et-ink); margin-bottom: 10px; }
.tbl-vig-chiffre span { font-size: 12px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--et-muted); margin-left: 5px; vertical-align: .22em; }
.tbl-vig-champs { margin: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; border-top: 1px solid var(--tbl-filet); padding-top: 9px; }
.tbl-vig-champs div { min-width: 0; }
.tbl-vig-champs dt { font-size: 12px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--et-muted); margin: 0 0 2px; }
.tbl-vig-champs dd { margin: 0; font-size: 13px; color: var(--et-ink); overflow: hidden; text-overflow: ellipsis; }
.tbl-vig-actions { margin-top: 10px; padding-top: 9px; border-top: 1px solid var(--tbl-filet); text-align: right; }

/* --- Vignette À IMAGE (Tableau.VignetteMedia) ---------------------------------
   La carte perd son padding haut : l'image touche les bords, sinon elle flotte
   dans un liseré blanc qui la fait passer pour une illustration alors qu'elle est
   la donnée. Ce qui suit garde le retrait commun. */
.tbl-vig.tbl-vig-media { padding-top: 0; }
.tbl-vig-img { margin: 0 -14px 10px; height: 128px; background: var(--tbl-chrome); border-bottom: 1px solid var(--tbl-filet); position: relative; overflow: hidden; }
.tbl-vig-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tbl-bloc-etat { grid-column: 1 / -1; padding: 40px 14px; text-align: center; color: var(--et-muted); }

/* --- État ANALYSE --------------------------------------------------------------
   Le corps cesse d'être une projection ligne-à-ligne : ligne de groupe, lignes,
   sous-total. C'est ce que 18 écrans écrivent à la main avec des colspan, chaque
   fois différemment — et c'est ce qui les fait rentrer dans le modèle au lieu d'en
   sortir. Le zébrage cède la place : deux rythmes se contrarieraient. */
.tbl tbody tr.tbl-grp td { background: var(--tbl-chrome); font-size: 13px; padding: 7px 14px; cursor: pointer; border-bottom: 1px solid var(--tbl-filet); }
.tbl tbody tr.tbl-grp:hover td { background: var(--tbl-survol); }
.tbl-chev { display: inline-block; width: 14px; color: var(--et-muted); font-size: 12px; }
.tbl-grp-n { color: var(--et-muted); font-weight: 400; margin-left: 9px; font-size: 12px; }
.tbl-grp-total { float: right; margin-left: 18px; font-variant-numeric: tabular-nums; color: var(--et-muted); font-size: 12px; }
.tbl tbody tr.tbl-sstotal td { font-weight: 700; background: none; border-top: 1px solid var(--tbl-filet); border-bottom: 2px solid var(--tbl-filet); }
.tbl-cadre .tbl tbody tr.tbl-grp:nth-child(even) td,
.tbl-cadre .tbl tbody tr.tbl-sstotal:nth-child(even) td { background: var(--tbl-chrome); }

/* --- Sélecteur de colonnes, discret dans l'en-tête -----------------------------
   Il vivait en bouton « Colonnes » dans la barre d'outils, parmi des commandes qui
   agissent sur les DONNÉES (chercher, exporter) alors qu'il agit sur le TABLEAU.
   Posé au bout de la dernière colonne, il est là où l'on regarde quand on se
   demande « où est passée telle colonne ». Discret au repos, net au survol. */
.tbl-colmenu { position: relative; float: right; margin: -4px -4px 0 0; }
/* 28 x 28, la mesure de la passation pour le bouton de queue. 20 px etait sous le
   plancher de cible tactile et rendait l'icone illisible a 12 px. */
.tbl-colbtn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 28px; height: 28px; border: 0; background: transparent; cursor: pointer;
    color: var(--tbl-tete-encre); opacity: .7; font-size: 13px; line-height: 1;
    transition: opacity .12s, background .12s;
}
.tbl-colbtn:hover { opacity: 1; background: var(--et-fond-ardoise); }
/* L'anneau de focus est CLAIR et non ambre : il se pose sur l'ardoise de l'en-tete,
   ou l'ambre de l'ancienne charte ne ressortait deja pas, et ou le bleu SAP qui l'a
   remplacee partout ailleurs ne vaut que 1,9:1. Le gris bleute de l'en-tete, lui,
   tient 6,26:1 — c'est la teinte des libelles voisins. */
.tbl-colbtn:focus-visible { opacity: 1; outline: 2px solid var(--et-sur-ardoise); outline-offset: 1px; }
/* La liste herite de .tbl-menu-liste ; on la reancre a droite sous l'icone, et on lui
   rend une casse ET UNE POLICE normales. La police n'etait pas rendue : depuis que
   l'en-tete de table est en IBM Plex Mono, le menu en heritait — une liste de libelles
   de colonnes en chasse fixe, deux fois plus large que necessaire. */
.tbl-colliste {
    display: block; right: 0; left: auto; top: calc(100% + 4px);
    font-family: var(--et-font);
    text-transform: none; letter-spacing: normal; font-weight: 400;
    color: var(--et-ink); white-space: nowrap;
}
.tbl-colliste .tbl-menu-item { text-transform: none; letter-spacing: normal; }
/* Champ obligatoire non renseigné : ambre et en italique, pour que le manque se
   distingue d'une valeur. Pas de rouge — ce n'est pas une erreur, c'est une fiche
   à compléter ; le rouge est réservé à ce qui bloque. */
/* Selecteur volontairement long : « .tbl tbody tr.tbl-terne td » (0,2,3) grise les
   lignes des salaries sortis et battait « .tbl td.tbl-manquant » (0,2,1). L'italique
   passait, la couleur non — le manque se voyait donc a peine sur ces lignes. On monte
   a (0,2,4) pour reprendre la main.
   L'ambre l'emporte meme sur une ligne ternie : un champ obligatoire vide reste un
   manque a combler, que la fiche soit active ou non. */
/* LE PANNEAU D'APERÇU ÉMETTAIT DÉJÀ CETTE CLASSE SANS QU'ELLE HABILLE RIEN.
   TableauApercu.razor pose « class="@(c.EstManquant(Item) ? "tbl-manquant" : "")" »
   sur ses <dd> depuis le premier jour, mais aucun sélecteur ne visait ce dl-là : le
   manque était ambre en cellule, ambre en vignette, et INVISIBLE dans le panneau —
   c'est-à-dire à l'endroit même où l'on ouvre une ligne pour savoir ce qui lui manque.
   Le panneau appartient à la famille du Tableau : la règle est donc ici, avec les
   deux autres, et non dans la feuille d'un écran qui l'aurait découvert. */
.tbl tbody tr td.tbl-manquant,
.tbl-vig-champs dd.tbl-manquant,
.tbl-apercu-champs dd.tbl-manquant {
    /* --et-avertissement-ink, et NON --et-amber-ink : ce dernier vaut #C9772E, qui ne
       donne que 3,41:1 sur blanc — sous le seuil pour du texte courant ; il est pensé
       pour des pastilles à fond teinté, pas pour du texte sur fond clair.
       L'ancienne version écrivait #9A5B12 EN DUR pour cette raison, et elle avait
       raison au moment où elle l'a écrit : aucun jeton ne convenait. La révision de
       valeurs du 2026-09-02 en a créé un — 6,85:1, soit MIEUX que le littéral qu'il
       remplace (5,41:1). La justification avait survécu au manque qui la motivait. */
    color: var(--et-avertissement-ink); font-style: italic; font-size: .94em;
}

/* --- Répartition des effectifs -----------------------------------------------
   Deux modèles de graphique, choisis par l'écran selon le nombre de parts :
   anneau jusqu'à cinq, barres classées au-delà (voir EtatSalaries.razor).

   La palette est un DÉGRADÉ, pas une palette catégorielle : elle ne fait que
   redire le classement. En thème sombre le dégradé est retourné — un bleu marine
   sur fond sombre ne se voit pas — de sorte que la part dominante reste dans les
   deux cas la plus contrastée du lot. */
/* Deux colonnes dès qu'il y a la place, trois au large, et pas plus : à quatre ou
   cinq colonnes, six cartes se rangent en 5+1 ou 4+2 — une dernière rangée orpheline.
   Le plafond de 1440 px garde le 3×2, qui se lit d'un bloc.
   Le pas de 300 px est mesuré, pas choisi au jugé : la zone utile fait 651 px sur une
   fenêtre de 1000 px, et deux colonnes de 340 en réclamaient 694 — il manquait 43 px,
   et la grille retombait sur une seule colonne. */
.rep-grille { display: grid; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
              gap: 14px; padding: 16px; max-width: 1440px; }

/* La répartition est devenue un CRAN du tableau de bord (passation Pilotage §3.1) :
   elle n'a plus d'en-tête d'écran à elle, donc ses exports et sa base se posent
   dans le corps du cran. */
.rep-actions { display: flex; justify-content: flex-end; gap: 8px; padding: 0 16px; }
/* LA BASE, SOUS LES AXES. Les quatre autres crans ne comptent que les services
   pointés du périmètre retenu ; celui-ci compte tout le monde. Deux nombres
   différents sur un même écran doivent dire lequel ils comptent. */
.rep-base {
    margin: 0; padding: 0 16px 16px; max-width: 1440px;
    font-size: 13px; color: var(--et-muted);
}

.rep-carte {
    --rep-c1: var(--et-blue); --rep-c2: #2C4488; --rep-c3: #3C5FB0;
    --rep-c4: #5C82C9; --rep-c5: #8AA8DC; --rep-c6: #B6C8EA;
    /* --rep-manque-encre pointe le jeton : sa valeur claire et sa valeur sombre
       étaient tenues ici à la main, et la sombre (#f0a860) était DÉJÀ celle du
       jeton — la redéfinition sombre plus bas ne faisait que la recopier. */
    --rep-manque: var(--et-amber); --rep-manque-encre: var(--et-avertissement-ink);
    border: 1px solid var(--et-form-border); background: var(--et-surface); display: flex; flex-direction: column;
    /* La carte s'interroge elle-même sur sa largeur : c'est elle qui décide de la
       disposition de son anneau, pas la taille de la fenêtre. Elle se comporte donc
       pareil qu'on soit à deux colonnes sur un portable ou à trois sur un grand écran. */
    container-type: inline-size;
}

/* Carte étroite — l'anneau passe au-dessus et rend toute la largeur à la légende.
   Côte à côte à cette largeur, il ne resterait que 57 px de libellé : « SERVICE
   COMMERCIAL » et « SERVICE TECHNIQUE » se couperaient au même endroit et
   deviendraient indiscernables l'un de l'autre. */
@container (max-width: 400px) {
    .rep-anneau-zone { flex-direction: column; align-items: stretch; gap: 10px; }
    .rep-anneau { width: 104px; height: 104px; align-self: center; }
    .rep-legende { width: 100%; }
}
.appgrid[data-theme="dark"] .rep-carte {
    --rep-c1: #9FBEF2; --rep-c2: #7BA2E4; --rep-c3: #5C82C9;
    --rep-c4: #46679F; --rep-c5: #35507D; --rep-c6: #2A3E60;
}

.rep-tete { display: flex; align-items: center; gap: 9px; padding: 10px 13px; border-bottom: 1px solid var(--et-hairline); }
.rep-ico { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; flex: none;
           background: var(--et-info-bg); color: var(--et-form-blue-encre); font-size: 13px; }
.rep-tete h3 { margin: 0; font-size: 14px; font-weight: 700; color: var(--et-ink); }
.rep-couv { margin-left: auto; font-size: 12px; color: var(--et-muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.rep-note { padding: 7px 13px; font-size: 12px; color: var(--rep-manque-encre);
            background: var(--et-avertissement-bg); border-bottom: 1px solid var(--et-hairline); }

/* ----- Anneau ----- */
.rep-anneau-zone { display: flex; align-items: center; gap: 14px; padding: 12px 13px; }
.rep-anneau { width: 118px; height: 118px; flex: none; transform: rotate(-90deg); }
.rep-anneau circle { transition: stroke-dasharray .35s ease; }
@media (prefers-reduced-motion: reduce) { .rep-anneau circle { transition: none; } }
/* Le SVG entier est tourné pour partir à midi ; le texte du centre est remis d'aplomb. */
.rep-anneau text { transform: rotate(90deg); transform-origin: 21px 21px; }
.rep-anneau-n { font-size: 7px; font-weight: 700; fill: var(--et-ink); }
.rep-anneau-l { font-size: 2.9px; fill: var(--et-muted); }
/* Quand c'est le manque qui domine, le centre le dit en ambre — même code couleur
   que la part correspondante de l'anneau et que « À renseigner » des tableaux. */
.rep-anneau-n.rep-anneau-manque { fill: var(--rep-manque-encre); }
.rep-anneau-l.rep-anneau-manque { fill: var(--rep-manque-encre); font-style: italic; }
.rep-legende { list-style: none; margin: 0; padding: 0; flex: 1; min-width: 0; }
.rep-legende li { display: grid; grid-template-columns: 9px minmax(0, 1fr) auto auto; align-items: center;
                  gap: 8px; padding: 2px 0; font-size: 13px; }
.rep-puce { width: 9px; height: 9px; flex: none; align-self: start; margin-top: 4px; }
/* En légende, un libellé trop long REVIENT À LA LIGNE au lieu d'être coupé.
   « Horaire Ordinaire Hebdo Fixe » dépassait de 13 px et perdait sa fin ; deux
   catégories d'horaires qui ne diffèrent que par leur dernier mot deviendraient
   identiques à l'écran. Une ligne de plus coûte moins cher qu'une ambiguïté. */
.rep-legende .rep-lbl { white-space: normal; overflow: visible; overflow-wrap: anywhere; line-height: 1.25; }

/* ----- Barres classées -----
   Hauteur bornée : un axe à trente catégories ferait une carte de deux écrans de
   haut et casserait la grille. On fait défiler la carte plutôt que de tronquer la
   liste — une catégorie masquée en silence se lirait comme une catégorie absente. */
.rep-barres { list-style: none; margin: 0; padding: 8px 0; max-height: 330px; overflow-y: auto; }
.rep-ligne { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center;
             gap: 10px; padding: 4px 13px 6px; font-size: 13px; }
.rep-ligne .rep-jauge { grid-column: 1 / -1; }
/* Survol d'une rangée dans les VUES du tableau (répartition, chronologie, calendrier,
   listes de sélection) : #EDEDED, le survol de rangée de la charte — et non le bleuté
   --row-hover de la coquille, qui sert la barre latérale et le menu utilisateur. Deux
   gris voisins mais distincts, ce qui se voyait sur les écrans qui montrent les deux. */
.rep-ligne:hover { background: var(--et-rang); }
.rep-jauge { height: 7px; margin-top: 2px; background: var(--et-neutre-bg); overflow: hidden; }
.rep-jauge > span { display: block; height: 100%; }

/* ----- Commun aux deux modèles ----- */
.rep-lbl { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--et-ink); }
.rep-n { font-weight: 700; font-variant-numeric: tabular-nums; min-width: 24px; text-align: right; color: var(--et-ink); }
.rep-pc { font-size: 12px; color: var(--et-muted); font-variant-numeric: tabular-nums; min-width: 46px; text-align: right; }
/* Le reste non renseigné : ambre et italique, dans l'anneau comme dans les barres —
   il se compte, mais il ne se confond pas avec une catégorie réelle. */
.rep-manquant .rep-lbl { color: var(--rep-manque-encre); font-style: italic; }
.rep-ligne.rep-manquant .rep-jauge > span {
    background: repeating-linear-gradient(45deg, var(--et-amber), var(--et-amber) 4px, var(--et-amber-clair) 4px, var(--et-amber-clair) 8px) !important; }
/* Le reste, sous le graphique et hors de son axe : bandeau ambre, en pied de carte,
   séparé par un filet — il se lit comme un avertissement, pas comme une barre. */
.rep-reste { display: flex; align-items: center; gap: 8px; margin-top: auto;
             padding: 8px 13px; font-size: 12px; font-style: italic;
             color: var(--rep-manque-encre); background: var(--et-avertissement-bg);
             border-top: 1px solid var(--et-hairline); }
.rep-reste .rep-lbl { flex: 1; color: inherit; }
.rep-reste .rep-pc { color: inherit; font-style: normal; font-weight: 700; }

.rep-vide { padding: 18px 13px; text-align: center; color: var(--et-muted); font-size: 13px; }

/* --- Filtre latéral ----------------------------------------------------------
   Transcription de la maquette « Filtre Salariés latéral » (export 7).
   Valeurs relevées sur la maquette : bordures #D8E0EC / #DDE4EE, en-tête #E8EFFA,
   filets de groupe #4C7FBF, compteurs en orange de marque, champs à coins droits
   et boutons à 10 px — la même règle de charte que partout ailleurs. */
.flt {
    display: flex; flex-direction: column; height: 100%;
    border: 1px solid var(--et-hairline);
    background: var(--et-surface); overflow: hidden;
    font-family: var(--et-font);
}
/* 2026-08-17, passation « Design 7 » : l'en-tête redevient un BANDEAU ARDOISE à titre
   mono capitales — la même tête que celle des tableaux, et le même intitulé que les
   groupes de champs d'une fiche.

   L'argument qui l'avait fait passer au gabarit de carte tenait à l'époque : le panneau
   était alors le seul élément du back-office à s'annoncer autrement que ses voisins.
   Il ne tient plus, et il s'est retourné : depuis la bascule de charte, l'ardoise et la
   mono capitales SONT la façon dont toute structure s'annonce — tête de table, intitulé
   de groupe, libellé de faits saillants. C'est la carte à titre en casse normale qui
   ferait exception aujourd'hui.
   Contraste : #C3D0E4 vaudrait 6,26:1, mais le titre du panneau est ici en BLANC (9,00:1)
   comme dans la maquette — il n'a pas, contrairement à une tête de table, dix colonnes de
   libellés à ne pas écraser. */
.flt-tete {
    display: flex; align-items: center; gap: 9px; padding: 12px 14px;
    background: var(--et-table-head); color: var(--et-sur-ardoise-plein);
    border-bottom: 1px solid var(--et-table-head-fonce);
}
.flt-tete .ico {
    display: inline-flex; align-items: center; justify-content: center;
    flex-shrink: 0; background: transparent; color: var(--et-sur-ardoise-plein); font-size: 13px;
}
.flt-titre {
    font-family: var(--et-font-mono); font-size: 12px; font-weight: 700;
    text-transform: uppercase; letter-spacing: .16em;
}
/* Le compteur de critères : il doit se voir depuis la liste, c'est lui qui dit qu'un
   filtre RETIENT des lignes.
   2026-08-17 : BLEU #0A6ED1 et carré. L'orange assombri #C15308 était un contournement
   de contraste — blanc sur l'orange de marque ne vaut que 3,03:1 — et la passation
   supprime la question en interdisant l'orange sur une pastille. Blanc sur #0A6ED1 vaut
   4,73:1 : le seuil est tenu sans avoir à inventer une teinte que personne ne lit comme
   la couleur de la marque.
   L'ACQUIS D'ACCESSIBILITÉ QUI SURVIT n'est donc pas la valeur mais l'exigence : un
   compteur de 10,5 px doit rester au-dessus de 4,5:1, quelle que soit la charte. */
.flt-compte {
    margin-left: auto; padding: 1px 6px; min-width: 18px; border-radius: 0;
    background: var(--et-form-blue); color: var(--et-sur-aplat); text-align: center;
    font-family: var(--et-font-mono); font-size: 12px; font-weight: 500;
    font-variant-numeric: tabular-nums;
}

.flt-vues { padding: 11px 14px 12px; background: var(--et-surface-3);
            border-bottom: 1px solid var(--et-rang); }
.flt-vues-tete { display: flex; align-items: center; gap: 8px; margin-bottom: 7px; }
/* Surtitre de section : la même formule que partout dans les écrans de paramétrage
   (h6 text-uppercase text-muted small). 3,03:1 avec le gris discret sur du 10 px
   capitalisé était le pire cas de l'écran — #6B7480 vaut 4,74:1. */
/* Mono, 10 px, chasse .14em — le registre des surtitres de la charte. Le #6B7480
   reste : #89919A ne vaut que 3,03:1 sur ce fond, et un intitulé de section se lit. */
.flt-surtitre { font-family: var(--et-font-mono); font-size: 12px; font-weight: 700;
                text-transform: uppercase; letter-spacing: .14em; color: var(--et-faint); }
/* Bouton d'icône : un .btn du kit, ramené au carré. */
.flt-icone { margin-left: auto; flex: none; width: 31px; padding: 0; line-height: 1; }
.flt-vue-saisie { display: flex; gap: 6px; margin-bottom: 7px; }
.flt-vue-saisie .form-control { flex: 1; }
.flt-vue-choix { display: flex; gap: 6px; }
.flt-select-cadre { flex: 1; min-width: 0; }

/* EN-TÊTE DU PANNEAU — ce qui BORNE la requête, avant ce qui la filtre.
   Séparé du reste par un filet, et non fondu dans les facettes : un contrôle posé là ne
   compte pas dans le badge de critères et relance la requête au lieu de réduire la liste.
   Le filet dit cette différence de nature ; sans lui la période passerait pour une facette
   de plus, et son « effacer les critères » manquerait à l'appel. */
.flt-entete { padding: 12px 14px; border-bottom: 1px solid var(--et-rang); }
.flt-entete .flt-surtitre { display: block; margin-bottom: 7px; }

.flt-recherche { position: relative; padding: 13px 14px; }
.flt-loupe { position: absolute; left: 25px; top: 50%; transform: translateY(-50%);
             color: var(--et-muted); font-size: 12px; pointer-events: none; z-index: 4; }
.flt-champ-recherche { height: 42px; padding-left: 32px; padding-right: 32px; font-size: 14px; }
.flt-vider {
    position: absolute; right: 20px; top: 50%; transform: translateY(-50%);
    width: 22px; height: 22px; display: grid; place-items: center; z-index: 4;
    border: none; border-radius: 50%; background: transparent; color: var(--et-muted); cursor: pointer;
}
.flt-vider:hover { background: var(--et-surface-2); }

/* Choix exclusif (« Statut »). Même gouttière et même hauteur de champ que la bascule
   qu'il remplace, pour que le panneau garde son rythme vertical quel que soit celui des
   deux contrôles qu'un écran déclare. */
.flt-choix { margin: 0 14px 12px; display: flex; flex-direction: column; gap: 5px; }
.flt-choix .flt-select-cadre { flex: none; }

.flt-bascule {
    display: flex; align-items: center; gap: 9px; width: calc(100% - 28px); margin: 0 14px 12px;
    padding: 8px 11px; cursor: pointer; border-radius: var(--et-r3);
    border: 1px solid var(--et-form-border); background: var(--et-surface);
    font-family: inherit; font-size: 13px; color: var(--et-ink); text-align: left;
}
.flt-bascule:hover { border-color: var(--et-form-blue); }
.flt-bascule.est-active { border-color: var(--et-form-blue); background: var(--et-info-bg); font-weight: 600; }
.flt-bascule-lbl { flex: 1; }

/* La case elle-même est .mx-case (modele-erp.css) : les lignes d'option sont des
   <button>, et un <input type="checkbox"> dans un bouton n'est pas du HTML valide —
   il faut donc la dessiner. Ne reste ici que l'écart, et il est argumenté : 15 px
   et non les 17 px de la passation, parce que celle-ci est dessinée dans une ligne
   d'option de 12,5 px et non dans une colonne de tableau. La variante radio est
   .mx-case-radio, elle aussi dans le gabarit. */
.flt-case { --mx-case-t: 15px; }

.flt-groupes { flex: 1; overflow-y: auto; min-height: 0; }
/* HUIT RÈGLES SOMBRES ONT ÉTÉ SUPPRIMÉES ICI ET PLUS BAS, ET C'EST L'OBJET DU LOT.
   Chacune repeignait à la main ce que son jeton clair fait DÉJÀ en basculant :
   --et-surface-2, --et-info-bg, --et-tint, --et-form-blue-d, --et-form-blue-encre,
   --et-muted. Écart mesuré entre la valeur du jeton et le littéral qu'il remplace :
   4 à 13 sur 255 par canal — invisible.

   Elles avaient une raison d'être le jour où elles ont été écrites : leur côté clair
   n'était pas encore un jeton qui bascule, ou pas un jeton du tout (voir les jetons
   FANTÔMES résolus dans ce même lot — var(--flt-tete-fond, #E8EFFA) et consorts, où
   le repli gagnait toujours parce que la variable n'existait nulle part). La bascule
   faite, la surcharge sombre est devenue une seconde source de vérité qui ne se
   signale pas : elle ne casse rien, elle fige. */
.flt-groupe { border-top: 1px solid var(--et-rang); }
.flt-groupe-tete {
    display: flex; align-items: center; gap: 10px; width: 100%; padding: 11px 14px;
    border: none; background: transparent; cursor: pointer; font-family: inherit; text-align: left;
}
.flt-groupe-tete:hover { background: var(--et-surface-2); }
.flt-filet { flex: none; width: 3px; height: 15px; border-radius: 0; }
/* Même formule que l'en-tête de groupe d'une fiche (.mx-groupe-lbl) : le panneau et le
   formulaire annoncent leurs sections de la même façon. */
.flt-groupe-lbl { flex: 1; font-family: var(--et-font-mono); font-size: 12px; font-weight: 700;
                  text-transform: uppercase; letter-spacing: .16em; color: var(--et-table-head-encre); }
.flt-groupe-fleche { flex: none; font-size: 12px; color: var(--et-muted); transition: transform .15s ease; }
.flt-groupe-fleche.est-ouvert { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) { .flt-groupe-fleche { transition: none; } }

.flt-options { padding: 0 10px 10px; display: flex; flex-direction: column; gap: 1px; }
.flt-indication { padding: 0 4px 8px; font-size: 12px; color: var(--et-muted); }
.flt-option {
    display: flex; align-items: center; gap: 9px; width: 100%; padding: 7px 8px;
    border: none; border-radius: var(--et-r3); background: transparent; cursor: pointer;
    font-family: inherit; font-size: 13px; color: var(--et-ink); text-align: left;
}
.flt-option:hover:not(:disabled) { background: var(--et-info-bg); }
.flt-option.est-choisie { font-weight: 600; }
/* Une option à zéro reste VISIBLE mais inerte : la retirer ferait croire que la
   valeur a disparu du référentiel, alors qu'elle est seulement exclue par les
   autres critères. */
.flt-option.est-inerte { opacity: .42; cursor: default; }
.flt-option-lbl { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Idem : 3,11:1 avec le gris discret. C'est le compte sur lequel on décide de cocher
   ou non — le lire est tout l'intérêt de l'option. #6B7480 vaut 4,74:1. */
.flt-option-n { flex: none; font-size: 12px; color: var(--et-faint); font-variant-numeric: tabular-nums; }
.flt-option.est-manquante .flt-option-lbl { color: var(--et-avertissement-ink); font-style: italic; }

/* COMPLÉMENT — le contrôle de filtrage que l'écran pose en bas des facettes (le seuil
   d'encours de TRS-03). Il est dans .flt-groupes et porte .flt-groupe : il hérite donc du
   filet qui sépare les groupes, et se lit comme un critère de plus — ce qu'il est, à la
   différence de .flt-entete, qui borne la requête et se pose au-dessus de tout. Rien ici
   que la géométrie : le contrôle lui-même vient de l'écran. */
.flt-complement { padding: 12px 14px; }
.flt-complement .flt-surtitre { display: block; margin-bottom: 7px; }
.flt-complement .flt-indication { padding: 7px 0 0; }

.flt-pied { padding: 11px 14px; background: var(--et-surface-2); border-top: 1px solid var(--et-hairline); }
.flt-effacer { display: inline-flex; align-items: center; justify-content: center; gap: 7px; width: 100%; }

/* Mise en page de l'écran : panneau + liste, le panneau se repliant par le bouton
   de la barre d'outils. Sous 1100 px il passe au-dessus de la liste — côte à côte,
   il ne resterait pas 300 px utiles au tableau. */
.ecran-filtre { display: grid; grid-template-columns: 268px minmax(0, 1fr); gap: 16px; align-items: start; }
.ecran-filtre.est-replie { grid-template-columns: minmax(0, 1fr); }
.ecran-filtre.est-replie > .ecran-filtre-panneau { display: none; }
@media (max-width: 1100px) {
    .ecran-filtre { grid-template-columns: minmax(0, 1fr); }
    .flt-groupes { max-height: 320px; }
}

/* --- En-tête d'écran (hors carte) — maquette « Liste du personnel latéral » ----
   Le fil d'Ariane et le titre vivent sur le fond de page, la carte ne porte plus que
   la liste. C'est ce qui libère la colonne de gauche pour le panneau de filtres :
   un en-tête interne aurait coupé la grille en deux. */
/* 2026-08-17, passation « Design 7 » : l'en-tête d'écran devient une BANDE BLANCHE
   posée sur le fond de page, fermée par un filet de 3 px bleu. C'est la trame
   commune aux deux gabarits — liste et fiche — et le filet est ce qui la sépare du
   corps sans qu'il faille l'encadrer.
   Il n'est pas plein-cadre (les écrans vivent dans des coquilles au padding
   différent, et une marge négative calculée pour l'une déborderait dans l'autre) :
   la bande s'arrête aux gouttières de son conteneur. C'est le seul écart de trame
   assumé par rapport aux maquettes ; il ne se voit qu'aux deux extrémités du filet. */
.ecran-tete {
    margin-bottom: 16px; padding: 12px 16px;
    background: var(--et-surface); border-bottom: 3px solid var(--et-form-strip);
}
.appgrid[data-theme="dark"] .ecran-tete { background: var(--et-surface); }
.ecran-fil { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--et-muted); }
/* --et-ink-2 N'EXISTAIT PAS : le repli #37414F gagnait toujours, et ce lien portait
   donc une couleur en dur déguisée en jeton — le neuvième et dernier de la famille
   relevée au lot des voiles sombres. Il occupait un rang que la charte n'a pas,
   entre --et-muted (#6A6D70) et --et-ink (#0F172A), ce qui avait fait différer
   l'arbitrage. La hiérarchie réelle du fil le tranche : le COURANT porte --et-ink,
   les séparateurs un gris très clair, et les ancêtres se distinguent des deux par
   --et-muted PLUS la graisse 500 et le soulignement au survol. Trois rangs
   subsistent ; aucun n'est perdu, et la surcharge sombre disparaît avec le littéral. */
.ecran-fil a { color: var(--et-muted); font-weight: 500; text-decoration: none; }
.ecran-fil a:hover { color: var(--et-form-blue-d); text-decoration: underline; }
.ecran-fil .sep { color: var(--et-inerte); }
.ecran-fil .courant { color: var(--et-ink); }

.ecran-tete-bas { display: flex; align-items: flex-end; gap: 16px; margin-top: 10px; flex-wrap: wrap; }
.ecran-tete-txt { flex: 1; min-width: 0; }
.ecran-tete-txt h1 { margin: 0; font-size: 23px; font-weight: 700; letter-spacing: -.02em; color: var(--et-ink); }
/* #4B5563 et non le gris discret de la maquette : mesuré à 2,76:1 sur le fond de
   page, très en dessous du seuil AA de 4,5. Ce résumé porte le nombre de lignes
   affichées et le total — l'information la plus consultée de l'écran après la liste
   elle-même. La teinte reste celle de la maquette, prise un cran plus bas : 6,72:1. */
.ecran-resume { margin-top: 3px; font-size: 13px; color: var(--et-muted); }
.ecran-cta {
    flex: none; display: inline-flex; align-items: center; justify-content: center;
                                                                                                                                                                                                                                                                                                                                                                                                                          
    height: 32px; padding: 0 14px; border: none; border-radius: var(--et-r-btn);
    background: var(--et-action); color: var(--et-sur-aplat); font-size: 14px; font-weight: 600;
    font-family: inherit; cursor: pointer; white-space: nowrap;
}
.ecran-cta:disabled { background: var(--et-action-off); cursor: not-allowed; }
.ecran-cta:hover { background: var(--et-action-d); color: var(--et-sur-aplat); }

/* Bouton de repli du panneau de filtres, dans la barre du tableau. La pastille
   orange ne compte pas les critères mais signale qu'un filtre RETIENT des lignes :
   c'est l'écart entre ce qu'on voit et ce qui existe qui mérite l'alerte, pas le
   nombre de cases cochées. */
.tbl-btn-filtre {
    position: relative; flex: none; width: 42px; height: 42px;
    display: inline-grid; place-items: center;
    border: 1px solid var(--et-form-border); border-radius: 0;
    background: var(--et-surface); color: var(--et-muted);
    font-size: 13px; cursor: pointer;
}
.tbl-btn-filtre:hover { border-color: var(--et-form-blue); color: var(--et-form-blue-encre); }
.tbl-btn-filtre.est-actif { border-color: var(--et-form-blue); color: var(--et-form-blue-d); background: var(--et-tint); }
/* La surcharge sombre écrite à la main ici est PARTIE : elle rattrapait à la
   pièce ce que --et-tint et --et-form-blue-d ne savaient pas faire, avec deux
   couleurs en dur — les seules de cette règle. Les jetons portent désormais leur
   valeur sombre, et la règle claire ci-dessus rend juste dans les deux thèmes. */
.tbl-btn-filtre-pt {
    position: absolute; top: -3px; right: -3px; width: 8px; height: 8px;
    border-radius: 50%; background: var(--et-form-blue);
    box-shadow: 0 0 0 2px var(--et-surface);
}

/* --- Sélection de lignes et actions groupées ---------------------------------
   Bandeau au-dessus du tableau, qui n'existe que tant que quelque chose est coché.
   2026-08-17 : il passe de l'ambre a la TEINTE D'INFORMATION #EBF3FB, filet #D9D9D9.
   Ce n'est pas une preference d'habillage. L'ambre disait « attention » la ou il n'y
   a rien d'anormal — cocher trois lignes est un geste ordinaire — et il entrait en
   concurrence avec le bouton d'engagement, seul orange autorise par la passation.
   La teinte bleue dit « ceci est retenu », exactement comme la ligne selectionnee
   qu'elle coiffe : bandeau et lignes portent desormais la meme couleur, ce qui rend
   le lien entre les deux lisible sans le chercher. */
.tbl-selection {
    display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
    padding: 11px 18px; background: var(--et-tint); border-bottom: 1px solid var(--et-filet-fort);
}
/* Le fond n'est plus repris : --et-tint bascule seul, et rgba(10,110,209,.16)
   sur la surface nuit n'en etait qu'un derive. Le filet, lui, reste : --et-filet-fort
   n'a pas de valeur sombre, il resterait clair en travers du bandeau. */
.appgrid[data-theme="dark"] .tbl-selection { border-bottom-color: var(--et-hairline); }
.tbl-selection-n { font-size: 13px; font-weight: 600; color: var(--et-form-blue-d); }
.tbl-selection-actions { display: flex; gap: 8px; flex-wrap: wrap; }
/* Les boutons d'action groupée sont fournis par l'écran : on ne les style pas au
   cas par cas, on habille ce qui atterrit dans le bandeau. */
/* « Ses boutons sont blancs a bordure #A6C8E8, texte #0854A0 » — et non des boutons
   d'engagement : une action de masse s'applique a ce qui est deja coche, elle ne
   demande pas l'elan que l'orange reclame. */
/* Un <a> y atterrit au meme titre qu'un <button> : une action de masse peut mener
   quelque part (un mailto de relance, une edition, une route qui porte la selection).
   Le selecteur ne nommait que le bouton, si bien qu'un lien tombait dans le bandeau
   en lien brut — souligne, bleu, sans hauteur — au milieu de boutons. Meme regle,
   deux elements ; aucune valeur nouvelle. */
.tbl-selection-actions > button,
.tbl-selection-actions > a {
    display: inline-flex; align-items: center; gap: 6px;
    height: 32px; padding: 0 12px; border: 1px solid var(--et-info-bord); border-radius: 0;
    background: var(--et-surface); color: var(--et-form-blue-d); font-size: 13px; font-weight: 600;
    font-family: inherit; cursor: pointer; white-space: nowrap; text-decoration: none;
}
.tbl-selection-actions > button:hover,
.tbl-selection-actions > a:hover { background: var(--et-tint); text-decoration: none; }
/* Le bouton reste FANTOME sur le bandeau (fond transparent au lieu de la
   surface) ; sa bordure et son encre, elles, suivent leurs jetons — --et-info-bord
   a une valeur sombre, et l'encre --et-form-blue-d y vaut #9AC4EE : mesure sur le
   bandeau sombre, 7,83:1 contre 7,11:1 pour le couple que cette regle ecrivait. */
.appgrid[data-theme="dark"] .tbl-selection-actions > button,
.appgrid[data-theme="dark"] .tbl-selection-actions > a { background: transparent; }
.tbl-selection-annuler {
    margin-left: auto; height: 32px; padding: 0 11px; border: none; border-radius: 0;
    background: transparent; color: var(--et-muted); font-size: 13px; font-weight: 600;
    font-family: inherit; cursor: pointer;
}
/* Le survol prend LA SURFACE, comme les boutons d'action du meme bandeau : en
   clair il eclaircit (blanc sur la teinte), en sombre il creuse (la surface nuit
   est plus sombre que la teinte). Dans les deux cas il se detache du bandeau, ce
   que les deux voiles blancs faisaient chacun a sa maniere. */
.tbl-selection-annuler:hover { background: var(--et-surface); color: var(--et-ink); }

.tbl-case-col { width: 40px; padding-left: 14px !important; padding-right: 6px !important; }
/* Case carrée comme les champs, mais l'accent reste celui du navigateur : redessiner
   une case en CSS lui coûterait son comportement natif au clavier et son état
   indéterminé, pour un gain purement décoratif dans une colonne de 40 px. */
/* 17 px et bleu : « case a cochee 17x17, angles droits, cochee fond #0A6ED1 ». Une
   case orange etait le contre-exemple le plus visible de la regle « l'orange ne se
   pose jamais sur une case a cocher ». */
/* Taille retiree le 2026-09-10 : app.css pose les 17 px sur toute case native, et
   lot02 les 24 px sous 1024. Ce qui reste ici est propre a la case de LIGNE. */
.tbl-case { border-radius: 0; cursor: pointer; }
.tbl thead .tbl-case-col { cursor: default; }
.tbl tbody tr.tbl-ligne-cochee td { background: var(--et-tint); }

/* Avatar à initiales dans la cellule d'identité — maquette 7. Les initiales sont
   dérivées du nom : rien à stocker, rien à tenir à jour. La teinte l'est aussi, par
   un condensé du texte, pour qu'une même personne garde sa couleur d'un écran à
   l'autre sans qu'on l'enregistre nulle part. */
.tbl-identite { display: flex; align-items: center; gap: 10px; min-width: 0; }
.tbl-avatar {
    /* Carre et non rond (2026-08-17) : la passation ne connait qu'un seul arrondi
       hors bouton, la pilule des pastilles d'etat. La vignette photo de la fiche est
       carree elle aussi — les deux representations d'une meme personne se
       correspondent. */
    flex: none; width: 24px; height: 24px; border-radius: 0;
    display: grid; place-items: center;
    font-size: 12px; font-weight: 600; line-height: 1;
}
.tbl-identite-nom { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }

/* Liste des zones dans la mise à jour de masse : des cases plutôt qu'un <select multiple>,
   qui demande de tenir Ctrl enfoncé et ne montre pas ce qui est coché sans défiler. */
.mm-zones {
    margin-top: 10px; max-height: 168px; overflow-y: auto;
    border: 1px solid var(--et-form-border); background: var(--et-surface);
    display: flex; flex-direction: column;
}
.mm-zone { display: flex; align-items: center; gap: 9px; padding: 7px 11px; margin: 0;
           font-size: 13px; color: var(--et-ink); cursor: pointer; }
.mm-zone:hover { background: var(--et-rang); }
.mm-zone input { width: 17px; height: 17px; border-radius: 0; accent-color: var(--et-form-blue); flex: none; }
.mm-zone span { flex: 1; }
/* --et-font-mono et non --fx-mono : .mm-zone est défini dans la feuille de la
   COQUILLE, et --fx-mono n'existe que sous « .fx-page, .fx-modale ». Le rendu est
   juste aujourd'hui — la zone vit dans la modale de mise à jour en masse, qui est
   une .fx-modale — mais il tient à cet hasard de placement. Même correction que
   .cbm-* dans le lot de fiche.css. */
.mm-zone em { font-style: normal; font-size: 12px; color: var(--et-muted); font-family: var(--et-font-mono); }
/* --- Tableau unifié : états Kanban et Chronologie ----------------------------
   Ils partagent la carte des Vignettes en plus resserré : mêmes marqueurs de
   colonne, même vocabulaire visuel, deux mises en page différentes. */

/* ----- KANBAN : des voies qui défilent horizontalement ----- */
.tbl-kanban {
    display: flex; gap: 12px; padding: 14px;
    overflow-x: auto; align-items: flex-start;
}
.tbl-voie {
    flex: 0 0 264px; display: flex; flex-direction: column;
    background: var(--tbl-chrome); border: 1px solid var(--et-form-border);
    max-height: 620px;
}
.tbl-voie-tete {
    display: flex; align-items: center; gap: 8px; padding: 9px 11px;
    border-bottom: 1px solid var(--et-form-border); background: var(--et-surface);
}
.tbl-voie-lbl { font-size: 13px; font-weight: 700; color: var(--et-ink);
                overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Encre pleine et non le gris atténué : mesuré à 4,49:1 en thème sombre, soit juste
   sous le seuil AA de 4,5 pour du 11,5 px. C'est un effectif, une donnée — pas une
   mention secondaire. */
.tbl-voie-n {
    margin-left: auto; flex: none; min-width: 22px; padding: 1px 7px;
    background: var(--et-neutre-bg); color: var(--et-ink);
    font-size: 12px; font-weight: 700; text-align: center; font-variant-numeric: tabular-nums;
}
/* La voie du reste : ambre, comme « À renseigner » partout ailleurs. */
.tbl-voie-manquante .tbl-voie-tete { background: var(--et-avertissement-bg); }
.tbl-voie-manquante .tbl-voie-lbl { color: var(--et-avertissement-ink); font-style: italic; }

/* Une voie chargée défile DANS sa colonne plutôt que d'étirer la page : sans
   cela, une voie à cent cartes imposerait sa hauteur aux six autres. */
.tbl-voie-corps { padding: 9px; display: flex; flex-direction: column; gap: 8px; overflow-y: auto; }

.tbl-carte {
    background: var(--et-surface); border: 1px solid var(--et-form-border);
    border-left: 3px solid var(--et-form-blue); padding: 9px 10px;
}
.tbl-carte-haut { display: flex; align-items: flex-start; gap: 7px; }
.tbl-carte-haut h5 {
    margin: 0; flex: 1; min-width: 0; font-size: 13px; font-weight: 600; color: var(--et-ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tbl-carte-champs { margin: 7px 0 0; display: flex; flex-direction: column; gap: 3px; }
.tbl-carte-champs > div { display: flex; gap: 7px; font-size: 12px; }
.tbl-carte-champs dt { flex: none; color: var(--et-muted); font-weight: 400; }
.tbl-carte-champs dd { margin: 0; margin-left: auto; text-align: right; color: var(--et-ink);
                       overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tbl-carte-bas { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
.tbl-carte-bas:empty { display: none; }
.tbl-carte-chiffre { font-size: 13px; font-weight: 700; color: var(--et-ink); font-variant-numeric: tabular-nums; }
.tbl-carte-chiffre > span { font-size: 12px; font-weight: 400; color: var(--et-muted); }
.tbl-carte-actions { margin-left: auto; display: flex; gap: 4px; }

/* ----- CHRONOLOGIE : une frise verticale ----- */
.tbl-frise { padding: 14px 16px 18px; }
.tbl-tranche + .tbl-tranche { margin-top: 14px; }
.tbl-tranche-tete {
    display: flex; align-items: center; gap: 9px; padding: 5px 0 6px;
    border-bottom: 1px solid var(--et-hairline);
}
.tbl-tranche-lbl { font-size: 12px; font-weight: 700; text-transform: uppercase;
                   letter-spacing: .04em; color: var(--et-form-blue-encre); }
.tbl-tranche-n { margin-left: auto; font-size: 12px; color: var(--et-muted); font-variant-numeric: tabular-nums; }

.tbl-evts { list-style: none; margin: 0; padding: 0; }
/* Le rail : un filet continu derrière les pastilles, tiré par la bordure gauche du
   corps plutôt que par un pseudo-élément à positionner. */
.tbl-evt {
    display: grid; grid-template-columns: 52px 13px minmax(0, 1fr) auto;
    align-items: start; gap: 10px; padding: 6px 0;
}
.tbl-evt:hover { background: var(--et-rang); }
.tbl-evt-heure {
    font-size: 12px; color: var(--et-muted); text-align: right;
    font-variant-numeric: tabular-nums; padding-top: 2px;
}
.tbl-evt-pt { position: relative; align-self: stretch; }
.tbl-evt-pt::before {
    content: ""; position: absolute; left: 5px; top: -6px; bottom: -6px;
    width: 1px; background: var(--et-hairline);
}
.tbl-evt:first-child .tbl-evt-pt::before { top: 8px; }
.tbl-evt:last-child .tbl-evt-pt::before { bottom: auto; height: 8px; }
.tbl-evt-pt::after {
    content: ""; position: absolute; left: 2px; top: 6px;
    width: 7px; height: 7px; border-radius: 50%;
    background: var(--et-info); box-shadow: 0 0 0 2px var(--et-surface);
}
.tbl-evt-titre { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--et-ink); }
.tbl-evt-titre > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tbl-evt-champs { display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: 2px; font-size: 12px; color: var(--et-muted); }
.tbl-evt-champs b { font-weight: 400; color: var(--et-muted); opacity: .75; }
.tbl-evt-actions { display: flex; gap: 4px; }

/* La tranche des lignes sans date : ambre, et son rail s'efface — il n'y a pas de
   temps à suivre, seulement un tas à traiter. */
.tbl-tranche-sans .tbl-tranche-lbl { color: var(--et-avertissement-ink); }
.tbl-tranche-sans .tbl-evt-pt::before { display: none; }
.tbl-tranche-sans .tbl-evt-pt::after { background: var(--et-amber); }

/* ----- RÉPARTITION : indicateurs, puis la forme de l'ensemble en barres -----
   Les quatre teintes de bloc se succèdent par index (.t0 à .t3) plutôt que d'être
   choisies par l'écran : la couleur ne PORTE ici aucune information — elle sépare
   deux répartitions voisines, rien de plus. La laisser au paramétrage aurait fait
   croire le contraire, et deux écrans auraient fini par donner deux sens au bleu. */
.tbl-repartition { padding: 14px 16px 18px; display: flex; flex-direction: column; gap: 14px; }
.tbl-rep-indics {
    display: grid; gap: 12px;
    grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
}
.tbl-rep-indic {
    display: flex; flex-direction: column; gap: 3px;
    padding: 12px 14px; background: var(--tbl-chrome); border: 1px solid var(--tbl-filet);
}
.tbl-rep-indic-lbl {
    font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .1em;
    color: var(--et-muted);
}
.tbl-rep-indic-val {
    font-size: 21px; font-weight: 600; line-height: 1.15; color: var(--et-ink);
    font-variant-numeric: tabular-nums;
}
.tbl-rep-indic-det { font-size: 12px; color: var(--et-muted); }

.tbl-rep-blocs { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); align-items: start; }
.tbl-rep-bloc { border: 1px solid var(--tbl-filet); background: var(--et-surface); }
.tbl-rep-bloc-tete {
    padding: 9px 14px; background: var(--tbl-tete-fond); color: var(--tbl-tete-encre);
    border-bottom: 1px solid var(--tbl-filet);
    font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .1em;
}
.tbl-rep-bloc.t0 { --tbl-jauge: var(--et-cat-1); }
.tbl-rep-bloc.t1 { --tbl-jauge: var(--et-cat-2); }
.tbl-rep-bloc.t2 { --tbl-jauge: var(--et-cat-3); }
.tbl-rep-bloc.t3 { --tbl-jauge: var(--et-cat-4); }

.tbl-rep-barres { padding: 12px 14px 14px; display: flex; flex-direction: column; gap: 10px; }
.tbl-rep-barre-lgd { display: flex; align-items: baseline; gap: 8px; }
.tbl-rep-barre-lbl { flex: 1; min-width: 0; font-size: 13px; color: var(--et-ink);
                     overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tbl-rep-barre-val { font-size: 12px; color: var(--et-ink); font-variant-numeric: tabular-nums; }
.tbl-rep-barre-part { font-size: 12px; color: var(--et-muted); font-variant-numeric: tabular-nums; min-width: 34px; text-align: right; }
.tbl-rep-barre-piste { margin-top: 4px; height: 7px; background: var(--tbl-chrome); }
.tbl-rep-barre-jauge { height: 100%; background: var(--tbl-jauge, var(--et-form-blue)); }
/* La barre « Autres » est un CUMUL et non une valeur : hachurée, elle ne se confond
   pas avec une part réelle qu'on pourrait aller filtrer. */
.tbl-rep-barre.est-reste .tbl-rep-barre-lbl { color: var(--et-muted); font-style: italic; }
.tbl-rep-barre.est-reste .tbl-rep-barre-jauge { opacity: .45; }

/* ----- TABLEAU CROISÉ ----- */
.tbl-croise { display: flex; flex-direction: column; }
.tbl-croise-tete {
    display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap;
    padding: 10px 16px; border-bottom: 1px solid var(--tbl-filet); background: var(--tbl-chrome);
}
.tbl-croise-axe { display: flex; flex-direction: column; gap: 3px; }
.tbl-croise-axe > span {
    font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .1em;
    color: var(--et-muted);
}
.tbl-croise-axe select { min-width: 150px; border-radius: 0; }
.tbl-croise-x { padding-bottom: 6px; color: var(--et-muted); font-size: 14px; }
.tbl-croise-mention { margin-left: auto; padding-bottom: 6px; font-size: 12px; color: var(--et-muted); }

/* Densité : la concentration de l'effectif se lit à l'aplat, le chiffre restant
   lisible par-dessus. Le canal est une VARIABLE de couleur et non un rgba écrit dans
   le composant — sans quoi le bleu clair du thème jour resterait posé sur le fond
   nuit, où il ne se voit plus. */
.tbl-cadre { --tbl-densite: 76, 127, 191; }
.appgrid[data-theme="dark"] .tbl-cadre { --tbl-densite: 123, 162, 228; }
/* --d est posé en ligne par la cellule (il DÉPEND de la donnée) ; à défaut il vaut 0,
   ce qui rend le fond transparent — une cellule vide n'a donc rien à déclarer.

   Les sélecteurs sont VOLONTAIREMENT lourds : la zébrure du tableau (.tbl tbody
   tr:nth-child(even) td) poserait sinon son fond par-dessus la densité et l'effacerait
   une ligne sur deux. Compter sur l'ordre du fichier aurait suffi aujourd'hui et cassé
   au premier déplacement de bloc. */
.tbl-cadre .tbl.tbl-croise-table tbody tr td { background: rgba(var(--tbl-densite), var(--d, 0)); }
.tbl-croise-table th.tbl-croise-coin,
.tbl-croise-table .tbl-croise-entete {
    text-align: left; font-weight: 600; color: var(--et-ink);
    border-right: 1px solid var(--tbl-filet); white-space: nowrap;
}
.tbl-cadre .tbl.tbl-croise-table tbody tr td.tbl-croise-marge { background: var(--tbl-chrome); font-weight: 600; }
.tbl-croise-table .tbl-croise-vide { color: var(--et-muted); opacity: .55; }
.tbl-cadre .tbl.tbl-croise-table tfoot td,
.tbl-cadre .tbl.tbl-croise-table tfoot th {
    background: var(--tbl-chrome); border-top: 2px solid var(--tbl-filet); font-weight: 600;
}
.tbl-croise-reste {
    padding: 8px 16px; border-top: 1px solid var(--tbl-filet);
    font-size: 12px; color: var(--et-avertissement-ink); background: var(--tbl-chrome);
}

/* ----- CALENDRIER ----- */
.tbl-calendrier { padding: 0 0 2px; }
.tbl-cal-tete {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    padding: 10px 16px; border-bottom: 1px solid var(--tbl-filet); background: var(--tbl-chrome);
}
.tbl-cal-mois { font-size: 14px; font-weight: 600; color: var(--et-ink); min-width: 130px; text-align: center; }
.tbl-cal-mention { margin-left: auto; font-size: 12px; color: var(--et-muted); }
.tbl-cal-jours {
    display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
    background: var(--tbl-tete-fond); border-bottom: 1px solid var(--tbl-filet);
}
.tbl-cal-jours > span {
    padding: 5px 8px; font-size: 12px; font-weight: 700; text-transform: uppercase;
    letter-spacing: .12em; color: var(--tbl-tete-encre);
}
.tbl-cal-grille { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
.tbl-cal-case {
    min-height: 96px; padding: 6px 7px 8px; background: var(--et-surface);
    border-right: 1px solid var(--tbl-filet); border-bottom: 1px solid var(--tbl-filet);
    display: flex; flex-direction: column; gap: 5px; min-width: 0;
}
.tbl-cal-case:nth-child(7n) { border-right: 0; }
.tbl-cal-case.est-weekend { background: var(--et-surface-2); }
/* Les jours des mois voisins restent VISIBLES et pâles : les effacer casserait la
   grille de six semaines, et un 1er tombant un dimanche perdrait son voisinage. */
.tbl-cal-case.est-hors { opacity: .42; }
.tbl-cal-case.est-aujourdhui { box-shadow: inset 0 0 0 2px var(--tbl-accent); }
.tbl-cal-case-tete { display: flex; align-items: center; gap: 6px; }
.tbl-cal-quantieme { font-size: 13px; font-weight: 600; color: var(--et-ink); font-variant-numeric: tabular-nums; }
.tbl-cal-n {
    margin-left: auto; min-width: 18px; padding: 0 5px; border-radius: 999px;
    background: var(--tbl-tete-fond); color: var(--tbl-tete-encre);
    font-size: 12px; font-weight: 600; text-align: center; font-variant-numeric: tabular-nums;
}
.tbl-cal-case-corps { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.tbl-cal-jeton {
    display: flex; align-items: center; gap: 5px; width: 100%; padding: 2px 6px;
    border: 0; border-left: 3px solid var(--et-form-blue); background: var(--tbl-chrome);
    color: var(--et-ink); font-family: inherit; font-size: 12px; text-align: left; cursor: pointer;
    min-width: 0;
}
.tbl-cal-jeton.est-groupe { cursor: default; }
.tbl-cal-jeton:hover { background: var(--et-rang); }
.tbl-cal-jeton.est-groupe:hover { background: var(--tbl-chrome); }
.tbl-cal-jeton-lbl { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tbl-cal-jeton-n { flex: none; color: var(--et-muted); font-variant-numeric: tabular-nums; }
.tbl-cal-reste { font-size: 12px; color: var(--et-muted); padding-left: 3px; }
.tbl-cal-pied {
    padding: 8px 16px; border-top: 1px solid var(--tbl-filet); background: var(--tbl-chrome);
    font-size: 12px; color: var(--et-avertissement-ink);
}

/* ----- PANNEAU D'APERÇU -----
   En absolu SUR LA CARTE (.tbl-cadre est déjà position:relative) et non sur la
   fenêtre : le filtre latéral de l'écran reste visible et utilisable pendant la
   consultation. C'est la différence de fond avec une modale, et la raison d'être
   du panneau. */
.tbl-apercu-cadre { position: absolute; inset: 0; z-index: 30; display: flex; justify-content: flex-end; }
.tbl-apercu-fond { position: absolute; inset: 0; background: var(--et-voile); }
.tbl-apercu {
    position: relative; width: 380px; max-width: 100%; height: 100%;
    display: flex; flex-direction: column; overflow: hidden;
    background: var(--et-surface); border-left: 3px solid var(--tbl-accent);
    box-shadow: var(--et-ombre-volet);
}
/* --tbl-chrome et non --tbl-tete-fond, decouple le 2026-08-15 avec le passage de la
   tete a l'anthracite. Ce bandeau prenait le FOND de la tete mais pas son encre : son
   titre est en --et-ink, son bouton de fermeture en --et-muted, et l'etat est un badge
   clair. Tant que la tete etait un liseré bleu pale, l'emprunt passait ; sur un aplat
   sombre il aurait pose de l'encre sombre sur de l'anthracite — et il aurait fallu
   repeindre quatre elements pour retrouver ce que --tbl-chrome donne seul.
   Le bandeau est du MOBILIER (comme .tbl-barre et le pied), pas une tete de colonnes :
   c'est le jeton du mobilier qui lui revient, et il suit les deux themes. */
.tbl-apercu-tete {
    display: flex; align-items: center; gap: 10px; padding: 11px 14px;
    background: var(--tbl-chrome); border-bottom: 1px solid var(--tbl-filet);
}
.tbl-apercu-ident { flex: 1; min-width: 0; }
.tbl-apercu-titre {
    font-size: 14px; font-weight: 600; color: var(--et-ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* --et-muted et non --tbl-tete-encre : meme decouplage que le bandeau ci-dessus. Ce
   jeton vaut desormais BLANC (encre de la tete anthracite) ; la cle serait devenue
   invisible sur le mobilier clair. Le registre voulu ici est « secondaire », pas
   « encre d'en-tete » — la valeur d'origine (#4B5563) ne s'en distinguait pas. */
.tbl-apercu-cle { margin-top: 1px; font-size: 12px; color: var(--et-muted); font-variant-numeric: tabular-nums; }
.tbl-apercu-etat { flex: none; }
.tbl-apercu-fermer {
    flex: none; width: 28px; height: 28px; display: grid; place-items: center;
    border: 0; background: transparent; color: var(--et-muted); cursor: pointer; font-size: 13px;
}
.tbl-apercu-fermer:hover { color: var(--et-ink); }
.tbl-apercu-corps { flex: 1; min-height: 0; overflow-y: auto; padding: 14px; }
.tbl-apercu-champs { margin: 0; display: flex; flex-direction: column; gap: 8px; }
.tbl-apercu-champs > div { display: flex; align-items: baseline; gap: 10px; }
.tbl-apercu-champs dt {
    flex: none; width: 104px; font-size: 12px; font-weight: 600; text-transform: uppercase;
    letter-spacing: .1em; color: var(--et-muted);
}
.tbl-apercu-champs dd { margin: 0; flex: 1; min-width: 0; font-size: 13px; color: var(--et-ink); }
/* Intertitre et alerte du corps fourni par l'écran. Ils sont ici et non dans l'écran
   pour que deux panneaux d'aperçu de deux modules se ressemblent : le panneau est un
   gabarit commun, pas une page blanche. */
.tbl-apercu-section {
    display: flex; align-items: baseline; gap: 8px; margin: 16px 0 9px;
    padding-bottom: 5px; border-bottom: 2px solid var(--tbl-filet);
}
.tbl-apercu-section:first-child { margin-top: 0; }
.tbl-apercu-section::before {
    content: ""; flex: none; width: 3px; height: 12px; background: var(--et-info);
}
.tbl-apercu-section > span {
    font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .12em;
    color: var(--crumb-link);
}
.tbl-apercu-alerte {
    display: flex; align-items: flex-start; gap: 9px; padding: 9px 11px;
    font-size: 13px; line-height: 1.45;
}
.tbl-apercu-alerte i { flex: none; margin-top: 1px; }
/* Les deux encarts étaient DOUZE littéraux : fond, bordure et encre, en clair et en
   sombre, pour ce que les familles d'état nomment déjà. L'encre grave était même
   #9F1B12 — la valeur de --et-danger-ink au caractère près, recopiée à la main.
   Mesuré avant substitution, aucun contraste ne se perd :
     grave clair 7,35 → 6,95:1   attention clair 5,18 → 6,46:1
     grave sombre 6,68 → 8,22:1  attention sombre 7,89 → 7,61:1
   Les deux règles sombres disparaissent : les six jetons basculent d'eux-mêmes. */
.tbl-apercu-alerte.est-grave { background: var(--et-danger-badge-bg); border: 1px solid var(--et-danger-bord); color: var(--et-danger-ink); }
.tbl-apercu-alerte.est-attention { background: var(--et-avertissement-bg); border: 1px solid var(--et-avertissement-bord); color: var(--et-avertissement-ink); }
.tbl-apercu-alerte.est-neutre { background: var(--tbl-chrome); border: 1px solid var(--tbl-filet); color: var(--et-muted); }

/* LA MÉTHODE DE CALCUL, écrite sous les chiffres qu'elle produit.
   Un panneau d'aperçu n'affiche pas que des valeurs saisies : il en affiche
   de dérivées, et « 38h30 » sur un cycle de 4 jours est incompréhensible sans
   la formule qui l'a produit. Elle est ici plutôt que dans une infobulle —
   une infobulle se découvre par hasard, or la formule est justement ce qui
   manque à celui qui ne comprend pas le chiffre. */
.tbl-apercu-methode {
    margin-top: 9px; font-size: 12px; line-height: 1.5; color: var(--et-faint);
}

.tbl-apercu-pied {
    display: flex; align-items: center; gap: 8px; padding: 10px 14px;
    background: var(--tbl-chrome); border-top: 1px solid var(--tbl-filet);
}
.tbl-apercu-file { display: flex; align-items: center; gap: 4px; }
.tbl-apercu-pos { font-size: 12px; color: var(--et-muted); font-variant-numeric: tabular-nums; min-width: 56px; text-align: center; }
.tbl-apercu-actions { margin-left: auto; display: flex; align-items: center; gap: 6px; }

/* La ligne qu'on peut ouvrir le dit au survol ; celle qui EST ouverte reste repérable
   sous le panneau, pour qu'on sache d'où l'on parle en le refermant. */
.tbl-ligne-cliquable { cursor: pointer; }
.tbl-ligne-apercue > td { background: var(--tbl-tete-actif) !important; }
/* La ligne est atteignable au clavier : il faut donc qu'on VOIE où l'on est. Le liseré
   est doublé d'un fond, l'outline sur un <tr> restant diversement rendu d'un moteur à
   l'autre — un repère qui disparaît selon le navigateur ne vaut pas mieux que rien. */
.tbl-ligne-cliquable:focus-visible { outline: 2px solid var(--tbl-accent); outline-offset: -2px; }
.tbl-ligne-cliquable:focus-visible > td { background: var(--tbl-survol); }
/* Le volet reçoit le focus à l'ouverture pour qu'Échap le referme ; il n'est pas une
   commande et n'a donc pas à se cerner. Ses boutons, eux, gardent le leur. */
.tbl-apercu:focus { outline: none; }

/* ----- MOYENS DE POINTAGE (pastilles) -----
   Une pastille par moyen enrôlé. Le code court suffit à l'écran — le libellé complet
   est en infobulle — parce que la question posée en balayant la liste est « y a-t-il
   quelque chose ? » avant d'être « quoi ? ». Vide : la ligne le dit en toutes lettres. */
.tbl-moyens { display: inline-flex; align-items: center; gap: 3px; flex-wrap: wrap; }
/* LA PALETTE EST DECLAREE, PLUS ECRITE DANS DIX REGLES. Chaque moyen pose son
   couple fond/encre en jetons, la regle de base les consomme — meme forme que
   « .tbl-rep-bloc.t0 { --tbl-jauge: var(--et-cat-1) } » plus haut.

   ELLE RESTE PROPRE A LA FEUILLE, et c'est mesure. La charte nomme des teintes
   d'IDENTITE pleines (--et-cat-1..8) ; elle n'a pas de couple fond pale / encre
   par categorie, et le deriver par dilution ne passe pas : --et-cat-5 sur sa
   propre teinte a 12 % donne 3,20:1 en clair, et les huit teintes sombres sur
   leur teinte a 18 % s'etagent de 3,21 a 4,23:1 — toutes sous le seuil AA de
   4,5 exige par une pastille de 12 px. Les dix couples ci-dessous tiennent
   4,70 a 6,20:1 en clair et 6,82 a 7,89:1 en sombre. Les remplacer par la
   famille d'identite serait une regression d'accessibilite ; le manque est du
   cote de la charte, qui n'a pas de rang « pastille categorielle ».

   L'ORDRE EST CELUI DU CATALOGUE, pas celui d'une palette : empreinte, visage,
   paume, badge, code. Un sixieme moyen prend le rang suivant, il ne recycle pas. */
.tbl-moyen {
    padding: 1px 6px; border-radius: 999px; font-size: 12px; font-weight: 600;
    letter-spacing: .04em; font-variant-numeric: tabular-nums;
    /* Le repli sert le moyen inconnu : une pastille neutre plutot qu'un texte nu. */
    background: var(--moyen-fond, var(--et-neutre-bg));
    color: var(--moyen-encre, var(--et-ink));
}
.tbl-moyen.est-empreinte { --moyen-fond: #E7F5EC; --moyen-encre: #1E7B45; }
.tbl-moyen.est-visage    { --moyen-fond: #EDE7F6; --moyen-encre: #5E4A86; }
.tbl-moyen.est-paume     { --moyen-fond: #E4F2F4; --moyen-encre: #21707A; }
.tbl-moyen.est-badge     { --moyen-fond: #E8EFFA; --moyen-encre: #2C5C9E; }
.tbl-moyen.est-code      { --moyen-fond: #FBF0D9; --moyen-encre: #8A5B0B; }
.tbl-moyen-aucun { font-size: 12px; color: var(--et-danger-ink); }
.appgrid[data-theme="dark"] .tbl-moyen.est-empreinte { --moyen-fond: #14301f; --moyen-encre: #6fd398; }
.appgrid[data-theme="dark"] .tbl-moyen.est-visage    { --moyen-fond: #221c33; --moyen-encre: #b39ce0; }
.appgrid[data-theme="dark"] .tbl-moyen.est-paume     { --moyen-fond: #102b2e; --moyen-encre: #63c3ce; }
.appgrid[data-theme="dark"] .tbl-moyen.est-badge     { --moyen-fond: #16243a; --moyen-encre: #8fb4ea; }
.appgrid[data-theme="dark"] .tbl-moyen.est-code      { --moyen-fond: #2e2412; --moyen-encre: #e0b45f; }

/* Le sélecteur de bornes en panneau (.per-*) et son composant SelecteurBornes ont été
   retirés le 2026-08-17 : la période se choisit désormais dans ComboPeriode (.cbp-*,
   plus haut). Les deux dessins coexistaient pour un seul geste ; celui-ci rendait à la
   colonne de filtre les sept boutons et les deux champs qu'il y tenait en permanence. */



/* ===========================================================================
   RELEVÉ D'HEURES — liste de navigation entre salariés (ReleveHeures.razor)

   CE QUI RESTE ICI, ET CE QUI N'Y EST PLUS
   La colonne de gauche de l'écran est faite des composants de la maison :
   ComboPeriode pour la période (.cbp-*), FiltreLateral pour les critères et la
   recherche (.flt-*). Ce bloc ne porte plus que le TROISIÈME panneau — la liste des
   salariés retenus, celle sur laquelle on navigue. Un champ de recherche et un
   sélecteur de mois y avaient vécu : ils faisaient à moitié, et pour un seul écran,
   ce que les deux composants partagés font partout.

   La liste, elle, n'a pas d'équivalent partagé : FiltreLateral publie un sous-ensemble,
   il n'affiche pas ses lignes et ne désigne personne. D'où ces quelques classes, et
   pas l'emprunt de .flt-* — deux composants aux gestes différents que rien ne doit
   lier.
   =========================================================================== */

.rlv-compte {
    flex: none; min-width: 24px; padding: 1px 7px; text-align: center;
    background: var(--et-navy-soft); color: var(--et-form-blue-encre);
    font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums;
}


/* 46vh : la liste est le TROISIÈME panneau de la colonne (bornes, filtre, puis
   elle). Plus haute, elle repousserait le relevé hors de l'écran sur mobile, où
   les trois se superposent avant lui. */
.rlv-liste {
    max-height: 46vh; overflow-y: auto;
    padding: 0 8px 10px; display: flex; flex-direction: column; gap: 2px;
}

.rlv-item {
    display: flex; align-items: center; gap: 8px; width: 100%;
    padding: 6px 9px; text-align: left; cursor: pointer;
    border: 1px solid transparent; background: none;
    font-family: inherit; font-size: 13px; color: var(--et-ink);
}
.rlv-item:hover { background: var(--et-surface-2); }
/* Filet ET graisse, pas seulement un fond : le salarié qu'on lit doit se
   retrouver d'un coup d'œil après avoir descendu la liste. */
.rlv-item.est-actif {
    background: var(--et-info-bg); border-color: var(--et-form-blue); font-weight: 600;
}
.rlv-item:focus-visible { outline: 2px solid var(--et-form-blue); outline-offset: -2px; }

.rlv-item-nom { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rlv-item-parti { flex: none; font-size: 12px; color: var(--et-muted); }
.rlv-item-mat {
    flex: none; font-family: var(--et-font-mono);
    font-size: 12px; color: var(--et-muted);
}
.rlv-item.est-actif .rlv-item-mat { color: var(--et-form-blue-encre); }

.rlv-vide { padding: 18px 12px; text-align: center; color: var(--et-muted); font-size: 13px; }

/* --- La table du relevé : treize colonnes dans les trois quarts de la largeur --
   Le padding par défaut du tableau maison (16 px de chaque côté en en-tête)
   coûte à lui seul plus de 300 px sur treize colonnes. Depuis que le panneau de
   navigation prend un quart de l'écran, il ne restait plus rien pour la colonne
   « Nature » : « Absence non justifiée » se pliait sur trois lignes et la ligne
   du jour devenait plus haute que les autres. On resserre, ici seulement. --- */
.rlv-table > thead > tr > th { padding: 9px 8px; }
.rlv-table > tbody > tr > td,
.rlv-table > tfoot > tr > td { padding: 5px 8px; }
/* La colonne des libellés ne descend pas sous cette largeur : c'est elle qui
   porte la nature du jour ET le libellé des ruptures. */
.rlv-table .rlv-nature { min-width: 158px; }

/* --- Pastille de nature des files de pilotage (PilotageFile.razor) -----------
   La couleur vient du modèle (jeton --et-*), posée en style inline sur la
   pastille ; ici on ne fixe que la forme. Le fond est un voile de la couleur du
   texte via color-mix : une pastille par nature aurait sinon demandé autant de
   règles que de natures, et une nature ajoutée dans le modèle serait sortie
   sans fond. */
.badge-file {
    display: inline-block; padding: 2px 8px;
    border: 1px solid currentColor; border-radius: 999px;
    background: color-mix(in srgb, currentColor 10%, transparent);
    font-size: 12px; font-weight: 600; line-height: 1.5; white-space: nowrap;
}

/* --- LOGO DE LA SOCIÉTÉ CLIENTE, À L'ÉCRAN (LogoSociete.razor) ----------------
   La FORME seulement, commune aux deux surfaces qui l'accueillent — la barre du
   haut des quinze modules et le rail de l'écran de vente. Chacune ajoute sa
   propre dimension via .shell-logo / .rail-logo, dans SA feuille : c'est la
   règle de la charte (ce qui sert deux écrans monte, ce qui sert un écran reste
   chez lui), et la taille d'un logo dans une barre de 44 px n'a rien à voir avec
   celle d'un logo dans un rail de 210 px.

   HAUTEUR BORNÉE, LARGEUR LIBRE. Un logo est fourni tel quel par le client :
   carré chez l'un, bandeau de 6:1 chez l'autre. Borner la hauteur et laisser la
   largeur suivre est la seule contrainte qui ne déforme aucun des deux ;
   object-fit:contain garantit le reste si une feuille future impose les deux.

   LA PLAQUE : voir --et-plaque-logo. Sans elle, un PNG transparent à encre
   foncée — le cas le plus fréquent — est invisible sur le marine de la barre. */
.logo-societe {
    display: block;
    flex-shrink: 0;
    width: auto;
    height: auto;
    object-fit: contain;
    background: var(--et-plaque-logo);
    padding: 2px 4px;
    border-radius: var(--et-r-btn);
}
