/* ═══════════════════════════════════════════════════════════════
   DigiSync Platform — main.css
   Design tokens + shared components
   Font: Inter (self-hosted via Google Fonts for simplicity)
   ═══════════════════════════════════════════════════════════════ */

@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');

/* ── Design tokens ───────────────────────────────────────────── */
:root {
  /* ── Surfaces : échelle de profondeur ─────────────────────────
     Quatre niveaux, du plus bas au plus haut. Un composant se rattache
     à un NIVEAU, jamais à une couleur littérale — c'est ce qui garantit
     qu'il bascule seul en thème sombre.
       0  --bg        fond de l'application
       1  --card      cartes, panneaux, barre supérieure
       2  --card-sub  en-têtes de carte et de tableau, pied de modale, zébrures
       3  --elev      modales, menus déroulants, infobulles, popovers
     --input-bg est en CREUX (sous le niveau 1) : un champ se lit comme un
     renfoncement dans sa carte, dans les deux thèmes.
     --sb est une surface de marque (bleu nuit), hors échelle. */
  /* Valeurs reprises de digisync.fr : le Tailwind du site est
     personnalisé aux couleurs DigiSync (bg-blue-500 y vaut #1470be,
     c'est-à-dire la marque). Le site alterne sections blanches et
     sections coolGray-50 ; ici la page porte la teinte et les cartes
     restent blanches, convention d'un outil de gestion. */
  --bg:       #f2f4f8;
  --sb:       #0c3f74;
  --card:     #ffffff;
  --card-sub: #f7f8f9;   /* coolGray-50 du site */
  --elev:     #ffffff;
  --input-bg: #ffffff;

  /* Traits et surfaces interactives */
  --border:        #e3e7ed;   /* bordure de composant */
  --border-strong: #d5dae1;   /* coolGray-200 du site — survol, champ appuyé */
  --b2:            #eef0f3;   /* coolGray-100 du site — séparateur interne */
  --hover:         #f4f6f9;   /* survol d'une ligne, d'un item de menu */
  --active:        #e8eff9;   /* état sélectionné / enfoncé */

  /* Texte */
  /* Teinte ardoise du site. coolGray-900 / -800 / -500 sont repris tels
     quels ; --t3 et --t5 sont interpolés, le site n'ayant que quatre
     niveaux. Son plus clair (coolGray-400, 3:1) ne sert chez lui qu'au
     gros texte : ici il ne convient qu'au désactivé, que WCAG exempte. */
  --t1: #2a3342;   /* coolGray-900 — principal */
  --t2: #333f51;   /* coolGray-800 — courant (cellules, corps) */
  --t3: #48597a;   /* secondaire (libellés) */
  --t4: #556987;   /* coolGray-500 — méta (horodatages, aides) */
  /* Passe de #9aa5b8 (2,49:1, sous le seuil et signalé comme limite
     connue) à 4,68:1 sur blanc. Un placeholder porte du sens. */
  --t5: #637591;   /* placeholder */
  --t-dis: #8896ab; /* coolGray-400 — désactivé, exempté */

  /* Brand */
  --blue:   #1470be;   /* = bg-blue-500 du site */
  --bd:     #0c3f74;
  /* Marque BRUTE. Contrairement à --blue, jamais réécrite en thème
     sombre : c'est elle qui remplit les aplats pleins, des deux côtés.
     app.html / login.html / booking.html la réinjectent depuis
     Administration > Général, au même titre que --blue. */
  --brand-raw: #1470be;
  --bl:     #ebf3fe;   /* bg-blue-100 du site */
  --bll:    #d6e6fc;

  --green:  #16a34a;
  --gl:     #e6f6eb;
  --gb:     #bbf7d0;

  --red:    #dc2626;
  --rl:     #fbeaea;
  --rb:     #fecaca;

  --amber:  #b45309;
  --al:     #fff4e6;
  --ab:     #fde68a;

  --purple: #5b4fe0;
  --pl:     #eeebff;
  --pb:     #ddd6fe;

  --teal:   #0d9488;
  --tl:     #e9fbfa;
  --tb:     #99f6e4;

  --indigo: #4338ca;
  --il:     #eef2ff;
  --ib:     #c7d2fe;

  /* Radii / shadows */
  --r:  8px;
  --r2: 6px;
  --r-lg: 12px;
  /* Le site teinte ses ombres d'ardoise plutôt que de gris neutre
     (rgba(85,105,135,.1) et rgba(42,51,66,.06)) : elles se fondent dans
     la charte au lieu de grisailler. */
  --sh-1: 0 1px 2px rgba(85,105,135,.10);
  --sh-2: 0 4px 12px rgba(85,105,135,.12);
  --sh-3: 0 12px 34px rgba(42,51,66,.14);
  --ring: 0 0 0 3px rgba(20,112,190,.22);
  --ov-bg: rgba(15,23,42,.45);   /* voile derrière une modale */
  /* Surface FLOTTANTE : toast et infobulle de graphique. Elle s'inverse
     — encre sombre en thème clair, surface élevée en thème sombre — parce
     qu'une annotation passagère doit trancher sur la page, pas s'y fondre.
     Un toast blanc sur une carte blanche ne se verrait pas. */
  --float-bg: #12233a;
  --float-fg: #eef2f7;
  --float-bd: rgba(255,255,255,.12);
  /* Étoile des favoris : lue sur le bleu nuit de la barre latérale, donc
     identique dans les deux thèmes. */
  --fav: #f5c451;

  /* Motion */
  --t-fast: .12s ease;
  --t-med:  .2s ease;

  /* ── Jetons sémantiques ───────────────────────────────────────
     Noms explicites pour la charte ; ce sont des ALIAS des jetons
     ci-dessus, pas un second système : une seule valeur à changer. */
  /* Accent : deux rôles distincts, longtemps confondus — c'est ce qui rendait
     le bouton primaire illisible en sombre.
       --blue / --accent   TEXTE, icône, lien, bordure, onglet actif. Doit
                           contraster avec les surfaces : clair en sombre.
       --accent-solid      REMPLISSAGE d'un bouton primaire, sous --on-accent.
                           Doit contraster avec du blanc : soutenu en sombre.
     Le survol approfondit le remplissage dans les DEUX thèmes — l'éclaircir
     en sombre ferait retomber le blanc sous le seuil AA (mesuré 3,8:1). */
  --accent-solid:   var(--brand-raw);
  --accent-solid-h: color-mix(in srgb, var(--brand-raw) 78%, #000);
  --on-accent:      #ffffff;

  /* Bouton secondaire / au contour. En thème sombre c'est un voile
     blanc, pas la couleur de carte : posé sur une carte, --card le
     rendrait invisible. Même procédé que digisync.fr. */
  --btn-soft:   #ffffff;
  --btn-soft-h: var(--bl);

  /* Mêmes rôles pour les boutons pleins métier. Valeurs désaturées
     reprises telles quelles de la charte en vigueur (thème clair
     inchangé) ; le thème sombre les redérive en profondeur. */
  /* Vert assombri depuis #2f9e54 : le blanc n'y tenait que 3,4:1. */
  --success-solid:   #217a41;
  --success-solid-h: #1a6234;
  --danger-solid:    #cf3b3b;
  --danger-solid-h:  #a72b2b;
  --warning-solid:   #d8920a;
  --warning-solid-h: #aa7308;
  /* L'ambre vif ne porte pas de blanc (2,6:1). En thème clair il porte
     une encre sombre (6,3:1) ; en sombre le remplissage est rabaissé et
     c'est le blanc qui reprend la main. */
  --on-warning:      #2a1d05;

  --success: var(--green);
  --warning: var(--amber);
  --danger:  var(--red);
  --info:    var(--blue);
  --accent:  var(--blue);

  /* Texte posé SUR la teinte pâle de sa famille (badge, bandeau,
     pastille). L'accent brut n'y suffit pas en thème clair : --green
     sur --gl ne donne que 2,9:1. Variante assombrie ici, accent
     éclairci en thème sombre — un seul nom des deux côtés. */
  --blue-fg:   #1265ab;   /* la marque, juste assez assombrie pour tenir 5,4:1 sur --bl */
  --green-fg:  #136e35;
  --red-fg:    #b91c1c;
  --amber-fg:  #8a5a08;
  --purple-fg: #4a40a3;
  --teal-fg:   #0f766e;
  --indigo-fg: #3730a3;

  /* ── Jetons alias ────────────────────────────────────────────
     Variables utilisées dans le JS/CSS hérités mais jamais définies
     (panel admin, projets, oidc…). On les mappe sur la charte via
     var() : elles restent donc thème-aware automatiquement et n'ont
     pas besoin d'être redéclarées dans .theme-dark. Corrige les fonds
     blancs et bordures invisibles en thème sombre. */
  --bg1:           var(--card);
  --bg2:           var(--card-sub);
  --bg3:           var(--b2);
  --bd2:           var(--border);
  --t6:            var(--border);
  --tc2:           var(--t3);
  --ds-blue-light: var(--bl);
  --orange:        var(--amber);
  --yellow:        var(--amber);
  --sh:            var(--sh-2);

  /* Charte 2026 : ces trois noms pilotent la barre latérale, les onglets
     d'administration et le sous-menu du calendrier. Adossés à la charte,
     ils suivent le thème ET la couleur de marque configurée (--blue est
     réinjecté par app.html) — avant, figés en dur, ils restaient clairs
     en thème sombre et ignoraient la marque. */
  --ds-blue:      var(--blue);
  --ds-blue-dark: var(--bd);
  --ds-violet:    var(--purple);
}

/* ── Thème sombre ───────────────────────────────────────────────
   Le sélecteur reste « .theme-dark » (une seule classe, sans « body ») :
   app.html et login.html réinjectent la couleur de marque via une règle
   « .theme-dark { --blue: … } » de MÊME spécificité déclarée après cette
   feuille. La renforcer en « body.theme-dark » ferait gagner ce bloc et
   la marque configurée cesserait de s'appliquer en sombre.

   Neutres bleu-ardoise (teinte ~218°) plutôt que gris purs : la charte
   est bleu nuit, un gris neutre jurerait avec la barre latérale. Aucun
   noir absolu — le plus sombre est #080d15. */
.theme-dark {
  /* ── Palette reprise de digisync.fr (css/custom/dark.css) ─────
     Le thème sombre de l'application diverge de celui du site public :
     mêmes surfaces, mêmes niveaux de texte, même accent. Les jetons que
     le site n'a pas (modale, champ) sont dérivés dans la même teinte.
     Contrastes mesurés sur --card (#111c33) : t1 16,2:1 · t2 13,7:1 ·
     t3 11,4:1 · t4 6,6:1 · placeholder 6,1:1. Pire cas toutes surfaces
     confondues : 5,46:1. */
  --bg:       #0b1220;   /* --bg du site      */
  --sb:       #0f172a;   /* --surface du site */
  --card:     #111c33;   /* --card du site    */
  --card-sub: #0f172a;   /* en-têtes, zébrures, pied de modale */
  --elev:     #16213a;   /* modales, menus — au-dessus de la carte */
  /* Champ : voile blanc translucide, comme le site. Il se compose donc
     correctement sur n'importe quelle surface — carte, modale ou page —
     au lieu d'un aplat opaque valable sur une seule. */
  --input-bg: rgba(255,255,255,.04);

  /* Traits teintés ardoise, pas blanc pur : le blanc pur sur ce bleu
     nuit tire vers le gris froid et durcit les contours. */
  --border:        rgba(148,163,184,.18);   /* --border du site */
  --border-strong: rgba(148,163,184,.34);
  --b2:            rgba(148,163,184,.11);
  --hover:         rgba(255,255,255,.06);
  --active:        rgba(255,255,255,.10);

  --t1: #f8fafc;   /* --title du site */
  --t2: #e5e7eb;   /* --text du site  */
  --t3: #cbd5e1;
  --t4: #94a3b8;   /* --muted du site */
  --t5: #8b9cb3;   /* placeholder — 5,5:1 sur la pire surface */
  /* Désactivé : volontairement en retrait, et exempté par WCAG. Le
     curseur « not-allowed » porte l'information sans la couleur. */
  --t-dis: #64748b;

  /* --blue reste la teinte ÉCLAIRCIE : texte, icône, lien, bordure.
     Les REMPLISSAGES passent par --brand-raw (cf. --accent-solid dans
     :root), qui n'est pas réécrit ici — c'est ce qui redonne au bouton
     primaire la vivacité du site au lieu d'un bleu délavé. */
  --blue:   #5698d0;
  --bd:     color-mix(in srgb, var(--blue) 72%, #ffffff);
  /* Les remplissages métier ne sont plus rabaissés non plus : les
     valeurs de :root sont déjà calibrées (blanc à 5,4:1 sur le vert,
     4,8:1 sur le rouge) et gardent leur éclat. --on-warning garde donc
     son encre sombre des deux côtés. */

  /* Voile du bouton secondaire : voir --btn-soft dans :root. */
  --btn-soft:   rgba(255,255,255,.06);
  --btn-soft-h: rgba(255,255,255,.10);
  --bl:     color-mix(in srgb, var(--blue) 16%, transparent);
  --bll:    color-mix(in srgb, var(--blue) 30%, transparent);

  --green:  #4ecf8c;
  --gl:     rgba(78,207,140,.13);
  --gb:     rgba(78,207,140,.26);

  --red:    #f47a7a;
  --rl:     rgba(244,122,122,.13);
  --rb:     rgba(244,122,122,.28);

  --amber:  #e8a851;
  --al:     rgba(232,168,81,.14);
  --ab:     rgba(232,168,81,.30);

  --purple: #a99bf5;
  --pl:     rgba(169,155,245,.15);
  --pb:     rgba(169,155,245,.30);

  --teal:   #4fd1c5;
  --tl:     rgba(79,209,197,.13);
  --tb:     rgba(79,209,197,.26);

  --indigo: #9db4fb;
  --il:     rgba(157,180,251,.15);
  --ib:     rgba(157,180,251,.30);

  /* Sur fond sombre l'accent éclairci EST déjà la bonne encre : il
     mesure de 5,9 à 9,1:1 sur --card. Pas de variante distincte. */
  --blue-fg:   var(--blue);
  --green-fg:  var(--green);
  --red-fg:    var(--red);
  --amber-fg:  var(--amber);
  --purple-fg: var(--purple);
  --teal-fg:   var(--teal);
  --indigo-fg: var(--indigo);
  /* --on-warning n'est PAS réécrit ici : le remplissage ambre garde sa
     vivacité dans les deux thèmes, il lui faut donc la même encre sombre.
     Le blanc n'y tiendrait que 2,6:1. */

  /* Ombres : en sombre une ombre portée ne se voit pas — c'est la
     différence de surface qui porte l'élévation. On les garde pour
     détacher modales et menus du fond, sans excès. */
  /* Ombres du site (--shadow : 0 12px 35px rgba(0,0,0,.45)). */
  --sh-1: 0 1px 2px rgba(0,0,0,.35);
  --sh-2: 0 8px 24px rgba(0,0,0,.40);
  --sh-3: 0 12px 35px rgba(0,0,0,.45);
  /* Anneau de focus du site : rgba(59,130,246,.35), ici dérivé de la
     marque pour la suivre. */
  --ring: 0 0 0 3px color-mix(in srgb, var(--blue) 35%, transparent);
  --ov-bg: rgba(3,7,14,.66);
  --float-bg: var(--elev);
  --float-fg: var(--t1);
  --float-bd: var(--border);
}

/* ── Reset ───────────────────────────────────────────────────── */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

html { font-size: 14px; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; }

body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  background: var(--bg);
  color: var(--t1);
  font-feature-settings: 'cv11','ss01','ss03';
}
input, select, textarea, button { font-family: inherit; color: inherit; }
/* opacity:1 — Firefox applique sinon une opacité par défaut au placeholder,
   qui reprendrait 30 % de contraste au passage. */
::placeholder { color: var(--t5); opacity: 1; }

a { color: var(--blue); text-decoration: none; }
a:hover { text-decoration: underline; }

/* Focus-visible ring for keyboard users only */
:focus { outline: none; }
:focus-visible { outline: none; box-shadow: var(--ring); border-radius: 4px; }

/* ── Typography ─────────────────────────────────────────────── */
h1 { font-size: 1.5rem;  font-weight: 600; letter-spacing: -.01em; }
h2 { font-size: 1.15rem; font-weight: 600; letter-spacing: -.005em; }
h3 { font-size: .95rem;  font-weight: 600; }

/* ── Buttons ─────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: 7px 14px; border-radius: var(--r); border: 1px solid transparent;
  cursor: pointer; font-size: 13px; font-weight: 500; line-height: 1.3;
  transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast), transform var(--t-fast), box-shadow var(--t-fast);
  white-space: nowrap; user-select: none;
}
.btn:disabled { opacity: .55; cursor: not-allowed; }
.btn:active:not(:disabled) { transform: translateY(1px); }
.btn:focus-visible { box-shadow: var(--ring); }

.btn-p  { background: var(--accent-solid); color: var(--on-accent); }
.btn-p:hover:not(:disabled)  { background: var(--accent-solid-h); }

.btn-o  { background: var(--card); color: var(--t2); border-color: var(--border); }
.btn-o:hover:not(:disabled)  { border-color: var(--border-strong); color: var(--t1); }

.btn-g  { background: transparent; color: var(--t3); }
.btn-g:hover:not(:disabled)  { background: var(--hover); color: var(--t1); }

/* .btn-gr, .btn-r et .btn-in sont redéfinis en PLEIN dans app.css ;
   seuls .btn-am et .btn-pu restent teintés. */
.btn-gr { background: var(--gl); color: var(--green-fg);  border-color: var(--gb); }
.btn-r  { background: var(--rl); color: var(--red-fg);    border-color: var(--rb); }
.btn-am { background: var(--al); color: var(--amber-fg);  border-color: var(--ab); }
.btn-pu { background: var(--pl); color: var(--purple-fg); border-color: var(--pb); }
.btn-in { background: var(--il); color: var(--indigo-fg); border-color: var(--ib); }

.btn-danger { background: var(--danger-solid); color: var(--on-accent); }
.btn-danger:hover:not(:disabled) { background: var(--danger-solid-h); }

.btn-sm  { padding: 5px 10px; font-size: 12px; border-radius: 6px; }
.btn-xs  { padding: 3px 7px;  font-size: 11px; border-radius: 5px; }
.btn-full { width: 100%; padding: 10px; font-size: 13px; }

/* ── Cards ───────────────────────────────────────────────────── */
.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--r);
  box-shadow: var(--sh-1);
}
.ch {
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: wrap;
}
.cl { font-size: 13px; font-weight: 600; color: var(--t2); }
.cb { padding: 16px; }
/* Groupe de boutons d'action dans un en-tête de carte (.ch) */
.ch-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* ── KPI cards ───────────────────────────────────────────────── */
.kpi { background: var(--card); border: 1px solid var(--border); border-radius: var(--r); padding: 15px 17px; transition: box-shadow var(--t-fast), border-color var(--t-fast); }
.kpi:hover { box-shadow: var(--sh-2); border-color: var(--bll); }
.kpi-h { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.kpi-n { font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: .5px; color: var(--t3); }
.kpi-v { font-size: 24px; font-weight: 600; line-height: 1.1; margin-bottom: 4px; letter-spacing: -.01em; }
.kpi-s { font-size: 11px; color: var(--t4); }

/* ── Grids ───────────────────────────────────────────────────── */
.g2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-bottom: 14px; }
.g3 { display: grid; grid-template-columns: repeat(3,1fr); gap: 12px; margin-bottom: 14px; }
.g4 { display: grid; grid-template-columns: repeat(4,1fr); gap: 12px; margin-bottom: 14px; }
@media (max-width: 900px) { .g4, .g3 { grid-template-columns: repeat(2,1fr); } .g2 { grid-template-columns: 1fr; } }
@media (max-width: 560px) { .g4, .g3 { grid-template-columns: 1fr; } }
/* .g3-30 : grille de filtres/formulaire — empêche les <select> longs de
   déborder de leur colonne et garde les champs en pleine largeur de cellule. */
.g3-30 > label { min-width: 0; }
.g3-30 .fc, .g3-30 .inp { width: 100%; }
/* .g2-stack : passe en colonne unique dès la tablette (cartes avec actions). */
@media (max-width: 1100px) { .g2-stack { grid-template-columns: 1fr; } }

/* ── Tables ─────────────────────────────────────────────────── */
.tw { overflow-x: auto; border-radius: var(--r); }
/* .cell-clip : borne une cellule de texte libre (libellé bancaire, notes…).
   Sans elle, un libellé à rallonge étire la table bien au-delà de l'écran :
   les colonnes suivantes partent hors champ et la barre de défilement
   horizontale se retrouve tout en bas d'une table de 100 lignes, donc
   inatteignable. Le texte complet reste lisible au survol (attribut title). */
.cell-clip {
  max-width: 380px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
.cell-clip[title] { cursor: help; }
table { width: 100%; border-collapse: collapse; }
th {
  font-size: 11px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .5px; color: var(--t3); padding: 10px 14px;
  border-bottom: 1px solid var(--border); background: var(--card-sub);
  text-align: left; white-space: nowrap; position: sticky; top: 0;
}
td {
  padding: 10px 14px; border-bottom: 1px solid var(--b2);
  font-size: 13px; color: var(--t2); vertical-align: middle;
}
tr:last-child td { border-bottom: none; }
tbody tr { transition: background var(--t-fast); }
tbody tr:hover td { background: var(--hover); }
.td-p { font-weight: 500; color: var(--t1); }
.td-m { color: var(--t4); font-size: 12px; }

/* ── Badges ─────────────────────────────────────────────────── */
.b {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 8px; border-radius: 999px;
  font-size: 11px; font-weight: 600; line-height: 1.1;
  border: 1px solid transparent;
}
/* Chaque famille : fond teinté + texte accentué + bordure de la même
   teinte. La bordure porte la moitié de la lisibilité en thème sombre,
   où les fonds teintés sont des voiles très légers. */
.bg  { background: var(--b2); color: var(--t3);        border-color: var(--border); }
.bb  { background: var(--bl); color: var(--blue-fg);   border-color: var(--bll); }
.bgr { background: var(--gl); color: var(--green-fg);  border-color: var(--gb); }
.br  { background: var(--rl); color: var(--red-fg);    border-color: var(--rb); }
.by  { background: var(--al); color: var(--amber-fg);  border-color: var(--ab); }
.bp  { background: var(--pl); color: var(--purple-fg); border-color: var(--pb); }
.bin { background: var(--il); color: var(--indigo-fg); border-color: var(--ib); }
.bt  { background: var(--tl); color: var(--teal-fg);   border-color: var(--tb); }
/* Neutre « en attente » — même rendu que .bg, nom conservé pour le JS. */
.bw  { background: var(--b2); color: var(--t3);      border-color: var(--border); }

/* ── Delta indicators ───────────────────────────────────────── */
.dl { font-size: 11px; font-weight: 500; padding: 2px 6px; border-radius: 4px; }
.dl-u { background: var(--gl); color: var(--green-fg); }
.dl-d { background: var(--rl); color: var(--red-fg); }

/* ── Forms ───────────────────────────────────────────────────── */
.fg { margin-bottom: 13px; }
.fg label { display: block; font-size: 12px; font-weight: 500; color: var(--t3); margin-bottom: 5px; }
.fc {
  width: 100%; padding: 9px 12px;
  border: 1px solid var(--border); border-radius: var(--r);
  font-size: 13px; color: var(--t1); outline: none; background: var(--input-bg);
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.fc:hover { border-color: var(--border-strong); }
.fc:focus { border-color: var(--blue); box-shadow: var(--ring); }
/* Désactivé : reconnaissable au fond ET au curseur, pas seulement à une
   nuance de gris — le texte reste au-dessus du seuil de lisibilité. */
.fc:disabled, .fc[readonly] { background: var(--b2); color: var(--t-dis); cursor: not-allowed; }
textarea.fc { resize: vertical; min-height: 80px; font-family: inherit; }

/* .inp : champ de saisie hors formulaire (recherches, filtres en barre d'outils).
   Dans un <label> de formulaire, c'est « form label > .inp » (app.css) qui pilote
   la largeur ; ici on ne fournit que l'apparence, alignée sur .fc. */
.inp {
  padding: 8px 11px;
  border: 1px solid var(--border); border-radius: var(--r);
  font-size: 13px; font-family: inherit;
  color: var(--t1); background: var(--input-bg); outline: none;
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.inp:hover  { border-color: var(--border-strong); }
.inp:disabled { background: var(--b2); color: var(--t-dis); cursor: not-allowed; }
.inp:focus  { border-color: var(--blue); box-shadow: var(--ring); }
.inp-sm { padding: 6px 9px; font-size: 12px; border-radius: var(--r2); }

.fr { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
@media (max-width:560px) { .fr { grid-template-columns: 1fr; } }

.hint { font-size: 11px; color: var(--t4); margin-top: 4px; }

/* ── Search input ───────────────────────────────────────────── */
.si { position: relative; }
.si input {
  padding: 7px 10px 7px 30px;
  border: 1px solid var(--border); border-radius: var(--r);
  font-size: 13px; background: var(--input-bg); color: var(--t1);
  outline: none; width: 220px;
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.si input:focus { border-color: var(--blue); box-shadow: var(--ring); }
.si-ico { position: absolute; left: 9px; top: 50%; transform: translateY(-50%); color: var(--t4); pointer-events: none; }

select.sl {
  padding: 7px 10px; border: 1px solid var(--border); border-radius: var(--r);
  font-size: 13px; background: var(--input-bg); color: var(--t2); outline: none; cursor: pointer;
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
select.sl:hover { border-color: var(--border-strong); }
select.sl:focus { border-color: var(--blue); box-shadow: var(--ring); }
select.sl:disabled { background: var(--b2); color: var(--t-dis); cursor: not-allowed; }

/* ── Filter bar ─────────────────────────────────────────────── */
.fb { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; flex-wrap: wrap; }

/* ── Tabs ────────────────────────────────────────────────────── */
.stabs { display: flex; border-bottom: 1px solid var(--border); margin-bottom: 16px; overflow-x: auto; }
.stab {
  padding: 9px 16px; font-size: 13px; font-weight: 500; color: var(--t3);
  cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px;
  transition: color var(--t-fast), border-color var(--t-fast);
  background: none; border-left: none; border-right: none; border-top: none;
  white-space: nowrap;
}
.stab:hover { color: var(--t1); }
.stab.on { color: var(--blue); border-bottom-color: var(--blue); }

/* ── Modals ──────────────────────────────────────────────────── */
.ov {
  display: none; position: fixed; inset: 0;
  background: var(--ov-bg); z-index: 400;
  align-items: center; justify-content: center;
  backdrop-filter: blur(3px); padding: 20px;
}
.ov.open { display: flex; }
/* Niveau 3 de l'échelle : une modale doit se détacher de la page ET des
   cartes qu'elle recouvre — en thème sombre l'ombre portée ne suffit pas,
   c'est l'écart de surface qui porte l'élévation. */
.mo {
  background: var(--elev); border-radius: var(--r-lg);
  width: 560px; max-width: 100%;
  border: 1px solid var(--border);
  box-shadow: var(--sh-3);
  overflow: hidden; max-height: 92vh;
  display: flex; flex-direction: column;
  animation: mo-in .18s ease;
}
@keyframes mo-in { from { transform: scale(.98) translateY(8px); opacity:0; } }
.mo-h {
  padding: 14px 20px; border-bottom: 1px solid var(--border);
  display: flex; align-items: center; justify-content: space-between; flex-shrink: 0;
}
.mo-t { font-size: 15px; font-weight: 600; color: var(--t1); }
.mo-x { background: none; border: none; cursor: pointer; color: var(--t3); font-size: 22px; line-height: 1; padding: 2px 6px; border-radius: 4px; }
.mo-x:hover { color: var(--t1); background: var(--hover); }
.mo-b { padding: 20px; overflow-y: auto; flex: 1; }
.mo-f {
  padding: 12px 20px; border-top: 1px solid var(--border);
  display: flex; justify-content: flex-end; gap: 8px;
  background: var(--card-sub); flex-shrink: 0;
}

/* ── Banners / Alerts ────────────────────────────────────────── */
.ban-ro, .ban-info, .ban-warn, .ban-suc, .ban-err {
  border-radius: var(--r); padding: 10px 14px; font-size: 13px;
  margin-bottom: 12px; display: flex; align-items: center; gap: 10px;
  border: 1px solid transparent;
}
.ban-info { background: var(--bl); border-color: var(--bll); color: var(--blue-fg); }
.ban-warn, .ban-ro { background: var(--al); border-color: var(--ab); color: var(--amber-fg); }
.ban-suc  { background: var(--gl); border-color: var(--gb); color: var(--green-fg); }
.ban-err  { background: var(--rl); border-color: var(--rb); color: var(--red-fg); }

.alert { padding: 10px 14px; border-radius: var(--r); font-size: 13px; margin-bottom: 12px; border: 1px solid transparent; }
.alert-error   { background: var(--rl); color: var(--red-fg);   border-color: var(--rb); }
.alert-success { background: var(--gl); color: var(--green-fg); border-color: var(--gb); }

/* ── Toggle switch ──────────────────────────────────────────── */
.tg { position: relative; display: inline-flex; align-items: center; cursor: pointer; }
.tg input { opacity: 0; width: 0; height: 0; position: absolute; }
.tg-tr { width: 34px; height: 18px; background: var(--t5); border-radius: 999px; transition: background var(--t-fast); }
.tg input:checked + .tg-tr { background: var(--blue); }
.tg-th { position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; background: #fff; border-radius: 50%; transition: left var(--t-fast); box-shadow: 0 1px 3px rgba(0,0,0,.25); }
.tg input:checked ~ .tg-th { left: 18px; }
.tg input:focus-visible + .tg-tr { box-shadow: var(--ring); }

/* ── Progress bar ────────────────────────────────────────────── */
.pb { height: 6px; background: var(--b2); border-radius: 999px; overflow: hidden; }
.pb-f { height: 100%; border-radius: 999px; background: var(--blue); transition: width var(--t-med); }

/* ── Avatar ──────────────────────────────────────────────────── */
.av { border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-weight: 600; color: #fff; flex-shrink: 0; letter-spacing: .02em; position: relative; overflow: hidden; }
/* Photo de profil, posée PAR-DESSUS les initiales. Si le fichier manque,
   l'image ne peint rien (alt vide) et les initiales restent visibles : pas de
   trou dans la pastille. `object-fit: cover` remplit le cercle sans déformer —
   la source est déjà carrée, c'est une ceinture de sécurité. */
.av-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: inherit; }

/* ── Info rows ───────────────────────────────────────────────── */
.info-row { display: flex; gap: 12px; margin-bottom: 10px; font-size: 13px; }
.info-l { color: var(--t3); font-size: 12px; min-width: 120px; flex-shrink: 0; }

/* ── Denied ──────────────────────────────────────────────────── */
.denied { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 80px 40px; text-align: center; color: var(--t4); }
.denied h3 { font-size: 15px; font-weight: 600; color: var(--t3); margin-bottom: 6px; }
.denied p  { font-size: 13px; max-width: 340px; }

/* ── Spinner ─────────────────────────────────────────────────── */
.spinner {
  display: inline-block; width: 14px; height: 14px;
  border: 2px solid rgba(255,255,255,.3);
  border-radius: 50%; border-top-color: #fff;
  animation: spin .65s linear infinite;
}
.spinner.dark { border-color: var(--b2); border-top-color: var(--blue); }
@keyframes spin { to { transform: rotate(360deg); } }

/* ── Skeleton loader ─────────────────────────────────────────── */
.skel {
  background: linear-gradient(90deg, var(--b2) 25%, var(--card-sub) 50%, var(--b2) 75%);
  background-size: 200% 100%; animation: skel 1.2s infinite; border-radius: 4px;
}
@keyframes skel { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }

/* ── Scrollbars ──────────────────────────────────────────────── */
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 999px; border: 2px solid transparent; background-clip: padding-box; }
::-webkit-scrollbar-thumb:hover { background-color: var(--t5); }
::-webkit-scrollbar-track { background: transparent; }

/* ── Empty state ─────────────────────────────────────────────── */
.empty { text-align: center; padding: 50px 20px; color: var(--t4); }
.empty svg { opacity: .3; margin-bottom: 12px; }
.empty p { font-size: 13px; }

/* ── Loading overlay ─────────────────────────────────────────── */
.loading-overlay {
  position: absolute; inset: 0; background: color-mix(in srgb, var(--card) 70%, transparent);
  display: flex; align-items: center; justify-content: center; z-index: 10;
  border-radius: var(--r);
}

/* Toast styling lives in app.css (#toast-root). */

/* ── Utility ─────────────────────────────────────────────────── */
.muted { color: var(--t4); }
.mono  { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
.row-g { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.sep   { height: 1px; background: var(--border); margin: 12px 0; }
.pad   { padding: 16px; }
.pad-lg{ padding: 24px; }

/* Marges — échelle courte, utilisée par les pages métier */
.mt4  { margin-top: 4px; }
.mt6  { margin-top: 6px; }
.mt10 { margin-top: 10px; }
.mb6  { margin-bottom: 6px; }
.mb10 { margin-bottom: 10px; }
.mb14 { margin-bottom: 14px; }

/* Alignement (cellules numériques, pieds de formulaires) */
.tar, .tae { text-align: right; }

/* Alignement flex ponctuel — à combiner avec .row-g */
.aic  { align-items: center; }
.jcsb { justify-content: space-between; }

/* Titre secondaire et libellé de liste */
.h2 { font-size: 15px; font-weight: 600; color: var(--t1); }
.lb { font-size: 13px; font-weight: 600; color: var(--t1); }

/* Indicateur de chargement d'une page */
.pgld { padding: 28px 12px; text-align: center; font-size: 13px; color: var(--t4); }

/* Conteneur de page centré */
.page-wrap { max-width: 1200px; margin: 0 auto; }

/* Respect reduced motion */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
}

/* ── Tri & filtre de colonnes (core/table-tools.js) ─────────────
   Les outils s'ajoutent dans le <th> existant : mêmes typo et couleurs que
   l'en-tête, la flèche de tri et l'entonnoir restent discrets tant qu'ils
   sont inactifs. Le panneau de filtre est en position fixe et rattaché au
   <body> : dans le <th> il serait rogné par le `overflow-x` de .tw. */
.tt-h {
  display: flex; align-items: center; gap: 4px;
  min-width: 0;
}
.tt-sort {
  display: inline-flex; align-items: center; gap: 4px;
  background: none; border: 0; padding: 0; margin: 0;
  font: inherit; color: inherit; letter-spacing: inherit; text-transform: inherit;
  cursor: pointer; border-radius: 3px;
  transition: color var(--t-fast);
}
.tt-sort:hover { color: var(--t1); }
.tt-arw {
  font-size: 8px; line-height: 1; color: var(--blue);
  width: 8px; flex-shrink: 0;
}
.tt-th.tt-sorted .tt-sort { color: var(--blue); }

.tt-flt {
  display: inline-flex; align-items: center; justify-content: center;
  width: 17px; height: 17px; flex-shrink: 0;
  background: none; border: 0; padding: 0; margin: 0;
  border-radius: 3px; cursor: pointer;
  color: var(--t5); opacity: .38;
  transition: opacity var(--t-fast), color var(--t-fast), background var(--t-fast);
}
.tt-flt svg { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linejoin: round; }
.tt-th:hover .tt-flt, .tt-flt:focus-visible { opacity: 1; }
.tt-flt:hover { color: var(--t2); background: var(--b2); }
/* Filtre actif : entonnoir plein et toujours visible — c'est le seul indice
   qu'une colonne masque des lignes. */
.tt-flt.tt-on { opacity: 1; color: var(--blue); }
.tt-flt.tt-on svg { fill: currentColor; stroke: currentColor; }

.tt-table tbody tr.tt-hidden { display: none; }
.tt-empty-row td {
  text-align: center; color: var(--t4); font-size: 12px; padding: 18px 14px;
}

/* Panneau de filtre */
.tt-pop {
  position: fixed; z-index: 500;
  width: 232px; max-width: calc(100vw - 16px);
  background: var(--elev); border: 1px solid var(--border);
  border-radius: var(--r); box-shadow: var(--sh-3);
  padding: 8px; font-size: 12px; color: var(--t2);
}
.tt-pop-h {
  font-size: 10px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .5px; color: var(--t4);
  padding: 0 2px 6px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tt-pop-s, .tt-pop-n {
  width: 100%; padding: 6px 8px; font-size: 12px; font-family: inherit;
  color: var(--t1); background: var(--input-bg);
  border: 1px solid var(--border); border-radius: var(--r2); outline: none;
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.tt-pop-s:focus, .tt-pop-n:focus { border-color: var(--blue); box-shadow: var(--ring); }
.tt-pop-r { display: flex; align-items: center; gap: 5px; margin-top: 6px; }
.tt-pop-sep { color: var(--t5); font-size: 11px; flex-shrink: 0; }

.tt-pop-l { max-height: 208px; overflow-y: auto; margin-top: 6px; }
.tt-pop-i {
  display: flex; align-items: center; gap: 6px;
  padding: 3px 4px; border-radius: var(--r2); cursor: pointer;
  transition: background var(--t-fast);
}
.tt-pop-i:hover { background: var(--hover); }
.tt-pop-i input { margin: 0; flex-shrink: 0; accent-color: var(--blue); }
.tt-pop-t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tt-pop-c { font-size: 10px; color: var(--t4); flex-shrink: 0; }
.tt-pop-all {
  border-bottom: 1px solid var(--border);
  margin-bottom: 3px; padding-bottom: 5px; font-weight: 600; color: var(--t3);
}
.tt-pop-note { padding: 8px 4px; color: var(--t4); font-size: 11px; }

.tt-pop-f {
  display: flex; gap: 5px; justify-content: flex-end;
  margin-top: 8px; padding-top: 7px; border-top: 1px solid var(--border);
}
.tt-pop-b {
  padding: 4px 8px; font-size: 11px; font-family: inherit; font-weight: 500;
  border: 1px solid var(--border); border-radius: var(--r2);
  background: var(--elev); color: var(--t2); cursor: pointer;
  transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast);
}
.tt-pop-b:hover { border-color: var(--border-strong); color: var(--t1); }
.tt-pop-b-g { border-color: transparent; color: var(--t4); margin-right: auto; }
.tt-pop-b-g:hover { background: var(--hover); border-color: transparent; }
.tt-pop-b-p { background: var(--accent-solid); border-color: var(--accent-solid); color: var(--on-accent); }
.tt-pop-b-p:hover { background: var(--accent-solid-h); border-color: var(--accent-solid-h); color: var(--on-accent); }
