/* TIME-UP · design system, charte officielle du 20/08/2026 (variante B, choix CEO du 25/08)
   Navy #002A4B, turquoise #389C9A (interface, « le bon bleu » du designer le 11/09/2026, ex-#1F9D8F) et #6BC9C8 (logo seul), blanc.
   Le navy porte les actions : le turquoise du brandbook
   plafonne a 1,9:1 sur blanc, il ne peut pas etre un bouton. Il sert d'aplat, de filet
   et d'etat actif, et s'assombrit en #0E7C7B quand il doit porter du texte. DM Sans partout (self-hébergée), JetBrains Mono
   réservée à l'horloge et aux empreintes. Échelle d'espacement 8/12/16/24/32/48.
   Zéro ressource externe. Les anciens noms de variables restent définis et remappés :
   les 25 pages basculent par les tokens, sans toucher au balisage. */

@import url('/assets/css/fonts.css');

:root {
  /* Neutres : valeurs RELEVÉES dans le projet Lovable du designer le 31/08/2026
     (oklch converties en hex au canvas, dans son navigateur). Copier-coller = ces valeurs. */
  --bg: #F8FAFB;
  --surface: #FFFFFF;
  --text: #002A4B;
  --text-2: #5A6B7C;
  --border: #D9E2EA;
  --border-2: #EFF4F8;

  /* LA primaire : le navy de la marque. Seule couleur de la charte qui porte du
     texte blanc (14,7:1). CTA, actifs, liens importants. Rien d'autre. */
  --primary: #002A4B;
  --primary-h: #01426F;
  --primary-txt: #FFFFFF;
  --primary-pale: #DEF6F4;

  /* Le turquoise d'INTERFACE, repris du travail du designer (choix CEO du 25/08).
     3,34:1 sur blanc : assez pour un filet, une bague de focus ou un aplat (seuil 3:1
     des elements non textuels), pas pour du texte de 14 px. Sa version assombrie,
     meme teinte, porte les liens a 4,7:1. Le turquoise du brandbook #6BC9C8 reste
     celui du logo, plus bas. */
  --accent-turq: #389C9A;   /* 11/09/2026 : son --brand = oklch(63.5% .091 193) = #389c9a, remplace #1F9D8F et #6bc9c8 partout sauf le logo */
  --accent-turq-txt: #178273;

  /* Sémantiques : réservées aux états. Vert et rouge = valeurs du designer (4,5:1 et 5,0:1,
     elles portent du texte). Son ambre d'anneau #DBA000 ne tient que 2,6:1 : il dessine les
     ANNEAUX (--ring-warn), jamais un chiffre ; le texte ambre garde #B45309. */
  --ok: #047857;      --ok-bg: #F0FDF4;      --ok-bd: #BBF7D0;
  --warn: #B45309;    --warn-bg: #FFFBEB;    --warn-bd: #FDE68A;
  --danger: #B91C1C;  --danger-bg: #FEF2F2;  --danger-bd: #FECACA;
  --ring-warn: #DBA000;

  /* Marque officielle. --brand-gold survit sous son ancien nom (des pages l'appellent)
     mais pointe desormais sur le turquoise : l'or n'existe plus dans la charte. */
  --brand-navy: #002A4B;
  --brand-turq: #6BC9C8;
  --brand-gold: var(--accent-turq);

  /* Échelles */
  --sp-1: 8px; --sp-2: 12px; --sp-3: 16px; --sp-4: 24px; --sp-5: 32px; --sp-6: 48px;
  --fs-xs: 12px; --fs-sm: 13px; --fs-md: 14px; --fs-body: 15px; --fs-h3: 15px;
  --fs-h2: 18px; --fs-h1: 24px; --fs-kpi: 32px;
  /* Geometrie du designer : cartes 16,6 px, controles 12,6 px, boutons et liens de menu en
     PILULE (le rayon depasse la demi-hauteur). Mesures relevees le 31/08. */
  --r-badge: 999px; --r-ctrl: 12.6px; --r-card: 16.6px; --r-pill: 999px;
  --shadow-card: 0 1px 2px rgba(2, 32, 55, .04), 0 4px 16px rgba(2, 32, 55, .05);
  --shadow-pop: 0 8px 24px rgba(0, 42, 75, .12);
  --shadow-modal: 0 16px 48px rgba(0, 42, 75, .16);
  /* La courbe signature du designer : cubic-bezier(.22,1,.36,1) sur 200 ms, partout. */
  /* remplace par le lot A :   --ease: cubic-bezier(.22, 1, .36, 1); */
  /* remplace par le lot A :   --tr: border-color .2s var(--ease), background .2s var(--ease), color .2s var(--ease), box-shadow .2s var(--ease), opacity .2s var(--ease), transform .2s var(--ease); */
  /* La police du logo (une graisse), et les deux familles du designer : Outfit pour les
     titres, Plus Jakarta Sans pour tout le texte courant. */
  --font-marque: 'Gilroy', 'Plus Jakarta Sans', system-ui, sans-serif;
  --font-titres: 'Outfit', 'Plus Jakarta Sans', system-ui, sans-serif;

/* ============================================================================
   LOT A : socle de jetons repris du CODE SOURCE du designer (31/08/2026)
   ----------------------------------------------------------------------------
   Source : ZIP Lovable du projet TimeUp Admin Hub, fichier src/styles.css.
   Les couleurs sont ses valeurs oklch converties en hexadecimal par un
   convertisseur valide sur 3 points de controle (#002A4B, #1F9D8F, #FFFFFF).
   A INSERER dans :root de app.css, AVANT le bloc « Anciens noms ».
   ============================================================================ */

  /* ---- A1. COURBES : trois roles distincts, comptes dans son code ----------
     Nous appliquions cubic-bezier(.22,1,.36,1) partout. C'est sa courbe
     MINORITAIRE : 16 usages contre 81 pour (.16,1,.3,1). Correction. */
  --ease: cubic-bezier(.16, 1, .3, 1);         /* 81 usages : transitions et entrees */
  --ease-doux: cubic-bezier(.22, 1, .36, 1);   /* 16 usages : menu mobile, restored-pop, hey-wave */
  --ease-pulse: cubic-bezier(.4, 0, .6, 1);    /* 3 usages : boucles infinies (badge, live, halo) */

  /* ---- A1 bis. DUREES : sa dominante est 300 ms (102 usages), pas 200 ms --- */
  --dur: 300ms;          /* standard */
  --dur-court: 200ms;    /* 27 usages : micro-retours */
  --dur-tactile: 150ms;  /* retour au doigt (lot C) */

  /* Transition generale, recomposee sur les valeurs ci-dessus. */
  --tr: border-color var(--dur) var(--ease), background var(--dur) var(--ease),
        color var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
        opacity var(--dur) var(--ease), transform var(--dur) var(--ease);

  /* ---- A2. OMBRES NOMMEES -------------------------------------------------
     --shadow-raised est SON ombre de survol signature, identique sur les
     boutons et les cartes. Elle n'existait pas chez nous. */
  --shadow-raised: 0 14px 44px -12px rgba(0, 42, 75, .16);
  --shadow-float:  0 10px 40px -10px rgba(0, 42, 75, .10);
  --shadow-plate:  0 1px 2px 0 rgba(0, 42, 75, .05);   /* son --shadow-card au repos */

  /* ---- A3. ECHELLE DE RAYONS COMPLETE -------------------------------------
     Derivee de son --radius: .85rem = 13,6 px. Nous n'avions que 12,6 et 16,6. */
  --r-sm: 10.6px;   /* radius - 3 */
  --r-md: 12.6px;   /* radius - 1  (= notre --r-ctrl) */
  --r-lg: 13.6px;   /* radius */
  --r-xl: 16.6px;   /* radius + 3  (= notre --r-card) */
  --r-2xl: 19.6px;  /* radius + 6 */

  /* ---- A4. JETONS SEMANTIQUES MANQUANTS -----------------------------------
     Il decline chaque couleur en trois temps : la couleur, sa version douce
     (-soft, pour les aplats de fond) et la couleur du texte pose dessus. */
  --surface-muted: #F2F6F9;   /* fond de section, entre --bg et --surface */
  --border-strong: #C2CED9;   /* bordure appuyee (survol de carte) */

  --primary-soft: #E0EDF8;
  --brand-soft:   #DEF6F4;
  --success-soft: #E0F8EC;
  --warning-soft: #FFF3D2;
  --danger-soft:  #FFEEEC;

  --info: #0D3A63;
  --info-soft: #E7F2FC;

  /* Absence et conge : orange fonce. Son commentaire dit pourquoi :
     « negatif modere, distinct du rouge alerte ». Nous n'avions pas cet etat. */
  --away: #AC3A0E;
  --away-soft: #FFE9DF;
  --away-txt: #FFFFFF;

  /* ---- A4 bis. REMAPPAGES : aucun ancien nom n'est supprime ---------------
     Nos fonds d'etat avaient des valeurs differentes des siennes
     (--ok-bg etait #F0FDF4, le sien est #E0F8EC). On aligne le RENDU en
     gardant les NOMS, donc sans toucher une seule page.
     ⚠️ Ces 3 lignes changent la teinte des aplats verts, ambres et rouges.
     Les retirer si le CEO prefere conserver nos fonds actuels. */
  --ok-bg: var(--success-soft);
  --warn-bg: var(--warning-soft);
  --danger-bg: var(--danger-soft);

  /* ------- Anciens noms : remappés, jamais supprimés (les pages en dépendent) ------- */
  --fond: var(--bg);
  --carte: var(--surface);
  --bord: var(--border);
  --bord-2: var(--border-2);
  --encre: var(--text);
  --gris: var(--text-2);
  --gris-2: #7D97A8;
  --accent: var(--primary);
  --accent-h: var(--primary-h);
  --ardoise: var(--brand-navy);
  --ardoise-2: #013A5F;
  --ardoise-3: rgba(255, 255, 255, .07);
  --navy-deep: #001322;
  --navy-light: #0B5578;
  --or: var(--accent-turq);
  --or-2: #8AD8D7;
  --or-pale: #DEF6F4;
  --or-patine: var(--accent-turq-txt);
  --vert: var(--ok);
  --vert-vif: var(--ok);
  --ambre: var(--warn);
  --rouge: var(--danger);
  --radius: var(--r-ctrl);
  --radius-lg: var(--r-card);
  --ombre: var(--shadow-card);
  --ombre-lg: var(--shadow-modal);
  --ombre-hover: var(--shadow-card);

  /* Graphiques : Chart.js ne comprend pas les variables CSS, le JS les LIT (CT.theme).
     Elles vivent donc ici, pas en dur dans les pages, et suivent le mode sombre. */
  --chart-aire: rgba(56, 156, 154, .16);
  --chart-grille: rgba(0, 42, 75, .08);
  --chart-neutre: #C3D3DB;
  --chart-conge: rgba(0, 42, 75, .38);
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
body {
  font-family: 'Plus Jakarta Sans', 'DM Sans', system-ui, -apple-system, "Segoe UI", sans-serif;
  background: var(--bg);
  color: var(--text);
  font-size: var(--fs-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
/* Une seule famille : la hiérarchie vient de la taille et de la graisse. */
h1, h2, h3, h4 {
  font-family: var(--font-titres); font-weight: 700; letter-spacing: -.01em; color: var(--text);
  font-synthesis: none;   /* jamais de faux gras : la graisse absente n'est pas fabriquee */
}
a { color: var(--accent-turq-txt); }
a:hover { color: #0B6362; }
/* Une case native fait 13 px : sous le minimum de 24 px de WCAG 2.2, et penible
   au doigt. On la redimensionne sans changer un seul balisage. */
input[type="checkbox"], input[type="radio"] {
  accent-color: var(--primary); width: 18px; height: 18px; margin: 3px;
  vertical-align: -4px; cursor: pointer;
}
.mono { font-family: 'JetBrains Mono', ui-monospace, "Cascadia Mono", monospace; font-variant-numeric: tabular-nums; }
.num { font-variant-numeric: tabular-nums; }
.tt td.num, .tt th.num { text-align: right; }

/* Focus clavier : visible partout, même dessin (brief accessibilité). */
:focus-visible { outline: 2px solid var(--accent-turq); outline-offset: 2px; border-radius: 2px; }

/* ---------- Utilitaires (échelle 8/12/16/24/32/48) ---------- */
.row { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.stack { display: flex; flex-direction: column; gap: var(--sp-2); }
.gap-1 { gap: var(--sp-1); } .gap-3 { gap: var(--sp-3); } .gap-4 { gap: var(--sp-4); }
.mt { margin-top: var(--sp-4); }
.muted { color: var(--text-2); }
.text-sm { font-size: var(--fs-sm); }
.text-xs { font-size: var(--fs-xs); }

/* ---------- Shell : sidebar claire + contenu ---------- */
.shell { display: flex; min-height: 100vh; }
.side {
  width: 260px; flex-shrink: 0;
  background: #0B1F36; border-right: 1px solid rgba(255, 255, 255, .06);
  display: flex; flex-direction: column; position: sticky; top: 0; height: 100vh;
}
.side-mark { display: flex; align-items: center; gap: 10px; padding: 20px 18px 16px; }
.side-mark .sq {
  width: 30px; height: 30px; background: none;
  display: flex; align-items: center; justify-content: center;
}
.side-mark .sq svg { width: 100%; height: 100%; display: block; }
.side-mark b {
  color: #FFFFFF; font-size: 19px; font-weight: 700; letter-spacing: -.01em;
  font-family: var(--font-marque); font-synthesis: none;
}
/* La barre du mot-symbole est turquoise, comme dans le logo officiel. */
.side-mark b i { color: var(--brand-turq); font-style: normal; padding: 0 3px; font-weight: 400; }
.side nav { padding: var(--sp-1) 0; flex: 1; overflow-y: auto; }
.side nav a {
  display: flex; align-items: center; gap: 10px; margin: 2px var(--sp-2);
  padding: 9px 13px; font-size: 13.5px; font-weight: 500; color: rgba(132, 149, 160, .95);
  text-decoration: none; border-radius: var(--r-pill); transition: var(--tr);
}
.side nav a .bi { font-size: 16px; width: 20px; text-align: center; flex-shrink: 0; }
.side nav a:hover { background: rgba(255, 255, 255, .06); color: #C8D3DA; }
/* L'actif du designer : bouton PLEIN turquoise en pilule, texte blanc. */
.side nav a.on {
  background: var(--accent-turq); color: #FFFFFF; font-weight: 600;
}
.side nav a.on:hover { background: var(--accent-turq); }
/* Badge chiffre du menu (Alertes 8, Conges 2) : pilule turquoise pleine a droite. */
.side nav a .mbadge {
  margin-left: auto; min-width: 22px; height: 22px; padding: 0 7px; border-radius: 999px;
  background: var(--accent-turq); color: #FFF; font-size: 11.5px; font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center; font-variant-numeric: tabular-nums;
}
.side nav a.on .mbadge { background: rgba(255, 255, 255, .22); }
.side nav a.soon { opacity: .35; pointer-events: none; }
/* Section du designer : petit trait a gauche, libelle majuscules, chevron de repli a droite. */
.side-sec {
  margin: var(--sp-3) 20px 4px 20px; padding: 0; font-size: 11px; text-transform: uppercase;
  letter-spacing: 1.2px; color: #7FA2B6; font-weight: 600;   /* 5,4:1 sur le navy */
  display: flex; align-items: center; gap: 9px; cursor: pointer; user-select: none;
  background: none; border: 0; width: calc(100% - 40px); font-family: inherit; text-align: left;
}
.side-sec::before { content: ""; width: 18px; height: 2px; border-radius: 1px; background: rgba(158, 199, 195, .55); flex-shrink: 0; }
.side-sec::after { content: "\F282"; font-family: 'bootstrap-icons'; font-size: 11px; margin-left: auto; transition: transform .2s ease; text-transform: none; letter-spacing: 0; }
.side-sec[aria-expanded="false"]::after { transform: rotate(-90deg); }
/* Le repli anime la hauteur du groupe (meme duree que le designer : 200 ms). */
.side-grp { overflow: hidden; transition: max-height .22s ease, opacity .2s ease; max-height: 500px; }
.side-grp.plie { max-height: 0; opacity: 0; }
.side::-webkit-scrollbar, .side nav::-webkit-scrollbar { width: 4px; }
.side nav::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, .16); border-radius: 2px; }
.side-foot { padding: var(--sp-3) 20px; font-size: var(--fs-xs); color: #6E8A9C; line-height: 1.5; border-top: 1px solid rgba(255, 255, 255, .10); }

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

/* ---------- Page header : Titre / description / actions à droite ---------- */
.top {
  background: rgba(248, 250, 251, .85); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--border);
  min-height: 72px; padding: var(--sp-2) var(--sp-4); display: flex; justify-content: space-between;
  align-items: center; gap: var(--sp-3); position: sticky; top: 0; z-index: 20;
}
.top-title { min-width: 0; }
.top-title h1 { font-size: 16px; font-weight: 600; letter-spacing: -.005em; }
.top-title .sub { font-size: 12.5px; color: var(--text-2); margin-top: 1px; font-weight: 400; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 210px; }
.top-actions { display: flex; align-items: center; gap: var(--sp-2); flex-shrink: 0; }
.top-user { display: flex; align-items: center; gap: 11px; font-size: var(--fs-sm); color: var(--text-2); }
.top-user .who { text-align: right; line-height: 1.35; }
.top-user b { display: block; font-size: var(--fs-sm); font-weight: 600; color: var(--text); }
/* Cible le SOUS-TITRE seul : la regle large teignait aussi les initiales de l'avatar,
   qui tombaient a 2,4:1 sur leur pastille. */
.top-user .who span { color: var(--text-2); font-size: var(--fs-xs); }
.avatar-user, .avatar {
  width: 32px; height: 32px; border-radius: 50%; flex-shrink: 0;
  background: var(--primary-pale); border: 0; color: var(--accent-turq-txt);
  display: inline-flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 12px;
}
.body { padding: var(--sp-5); flex: 1; }

/* ---------- Cartes ---------- */
.card {
  background: var(--surface); border: 1px solid rgba(217, 226, 234, .55); border-radius: var(--r-card);
  box-shadow: var(--shadow-card);
  overflow-x: auto; overflow-y: hidden;
}
.card > h4 {
  font-size: 15px; font-weight: 700; color: var(--text);
  font-family: var(--font-titres); font-synthesis: none;
  padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--border-2);
  display: flex; justify-content: space-between; align-items: center; gap: var(--sp-2); flex-wrap: wrap; row-gap: 8px;
}
.card .card-body { padding: var(--sp-4); }

/* ---------- KPI : alignée à gauche, label discret, valeur, variation ---------- */
.kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: var(--sp-3); }
.kpi {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-card);
  box-shadow: var(--shadow-card);
  padding: 20px var(--sp-4); text-align: left;
}
.kpi .t {
  font-size: var(--fs-sm); color: var(--text-2); font-weight: 500;
  letter-spacing: 0; margin: 0 0 6px; text-transform: none;
}
.kpi .n {
  font-size: var(--fs-kpi); font-weight: 700; line-height: 1.1; color: var(--text);
  letter-spacing: -.02em; font-variant-numeric: tabular-nums;
  font-family: var(--font-marque); font-synthesis: none;
}
.kpi .n small { font-size: 15px; color: var(--text-2); font-weight: 500; }
.kpi .delta { font-size: var(--fs-xs); margin-top: 6px; font-weight: 500; color: var(--text-2); }
.kpi .delta.up { color: var(--ok); }
.kpi .delta.down { color: var(--danger); }
/* Les états ne colorent qu'un point discret devant le label, jamais la carte. */
.kpi.ok .t::before, .kpi.warn .t::before, .kpi.bad .t::before {
  content: ""; display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  margin-right: 7px; vertical-align: 1px;
}
.kpi.ok .t::before { background: var(--ok); }
.kpi.warn .t::before { background: var(--warn); }
.kpi.bad .t::before { background: var(--danger); }

.live { font-size: var(--fs-xs); color: var(--ok); font-weight: 600; }
.live i { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--ok); margin-right: 5px; }

/* ---------- Tableaux ---------- */
table.tt { width: 100%; border-collapse: collapse; }
.tt th {
  font-size: var(--fs-sm); text-align: left; text-transform: none; letter-spacing: 0;
  color: var(--text-2); font-weight: 500; padding: 10px var(--sp-4);
  border-bottom: 1px solid var(--border); white-space: nowrap;
  position: sticky; top: 0; background: var(--surface); z-index: 2;
}
.tt td { font-size: var(--fs-md); padding: 13px var(--sp-4); border-bottom: 1px solid var(--border-2); vertical-align: middle; }
.tt tr:last-child td { border-bottom: 0; }
.tt tr:hover td { background: var(--bg); }

/* Un contenu qui ne doit jamais se couper en deux lignes : horaire, horodatage, durée. */
.nowrap, .tt td.nowrap { white-space: nowrap; }
/* Une adresse e-mail se coupe sur ses tirets et fait doubler la hauteur des lignes :
   on la borne et on la tronque, l'adresse entière reste dans l'infobulle. */
.tt .mail {
  display: inline-block; max-width: 24ch; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; vertical-align: bottom;
}
/* Tables logées dans une colonne latérale : même dessin, moins de respiration. */
.tt-c th { padding: 9px var(--sp-2); }
.tt-c td { padding: 10px var(--sp-2); font-size: var(--fs-sm); }
.tt-c .mail { max-width: 19ch; }
/* Grille du planning : sept colonnes de jours. Le padding de table standard mangeait
   la largeur utile et coupait « 08:00 – 16:30 » en deux lignes. */
.tt-plan th, .tt-plan td { padding: 10px 12px; }
.tt-plan td b, .tt-plan td > span, .tt-plan td .st { white-space: nowrap; }

/* ---------- Badges d'état : subtils, une information ---------- */
.st {
  display: inline-block; font-size: var(--fs-xs); font-weight: 600; letter-spacing: .01em;
  padding: 3px 10px; border-radius: var(--r-badge); white-space: nowrap; border: 1px solid transparent;
}
.st-p { background: var(--ok-bg); color: #15803D; border-color: var(--ok-bd); }
.st-b { background: var(--warn-bg); color: #B45309; border-color: var(--warn-bd); }
.st-a { background: var(--danger-bg); color: #B91C1C; border-color: var(--danger-bd); }
.st-c { background: var(--border-2); color: #475569; border-color: var(--border); }

/* ---------- Boutons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  border: 1px solid var(--primary); cursor: pointer; text-decoration: none; color: var(--primary-txt);
  font-family: inherit; font-synthesis: none;
  font-size: var(--fs-md); font-weight: 600; letter-spacing: 0;
  min-height: 40px; padding: 0 18px; border-radius: var(--r-pill); transition: var(--tr);
  background: var(--primary);
}
.btn:hover { background: var(--primary-h); border-color: var(--primary-h); }
.btn:focus-visible { outline: 2px solid var(--accent-turq); outline-offset: 2px; }
/* min-width : un bouton qui ne porte qu'une icone tombait a 31 px de large. */
.btn-sm { min-height: 34px; min-width: 34px; padding: 0 var(--sp-2); font-size: var(--fs-sm); }
.btn-lg { min-height: 48px; padding: 0 var(--sp-4); font-size: var(--fs-body); }
/* Secondaire : surface blanche, bord discret. */
.btn-ghost { background: var(--surface); color: var(--text); border: 1px solid var(--border); }
.btn-ghost:hover { background: var(--bg); border-color: #D6DAE3; color: var(--text); }
/* Sombre d'appoint (marque) : rare. */
.btn-or { background: var(--brand-navy); border-color: var(--brand-navy); color: #fff; }
.btn-or:hover { background: var(--ardoise-2); border-color: var(--ardoise-2); color: #fff; }
.btn-danger { background: var(--danger); border-color: var(--danger); }
.btn-danger:hover { background: #B91C1C; border-color: #B91C1C; }
.btn-success { background: var(--ok); border-color: var(--ok); }
.btn-success:hover { background: #15803D; border-color: #15803D; }
.btn:disabled { opacity: .45; cursor: not-allowed; }

/* ---------- Formulaires ---------- */
label.fl { display: block; font-size: var(--fs-sm); font-weight: 500; color: var(--text); margin: var(--sp-3) 0 6px; }
label.fl.req::after { content: " *"; color: var(--danger); }
.fi {
  width: 100%; height: 40px; padding: 0 var(--sp-2); border: 1px solid var(--border); border-radius: var(--r-ctrl);
  font-family: inherit; font-size: var(--fs-md); background: var(--surface); color: var(--text); transition: var(--tr);
}
textarea.fi { height: auto; padding: 10px var(--sp-2); }
.fi:focus { outline: none; border-color: var(--accent-turq); box-shadow: 0 0 0 3px rgba(56, 156, 154, .22); }
.fi.err { border-color: var(--danger); }
select.fi {
  appearance: none; -webkit-appearance: none; padding-right: 34px;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath fill='%2364748B' d='M1.4.6 6 5.2 10.6.6 12 2 6 8 0 2z'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center; background-size: 11px;
}
.fhint { font-size: var(--fs-xs); color: var(--text-2); margin-top: 5px; line-height: 1.5; }
.ferr { font-size: var(--fs-sm); color: var(--danger); margin-top: 6px; min-height: 17px; font-weight: 500; }

/* ---------- Sélecteur de date maison (le natif affiche mm/dd/yyyy en en-US) ---------- */
.dp { position: relative; display: block; width: 100%; }
.dp > .fi { width: 100%; padding-right: 38px; }
.dp > .fi.err { border-color: var(--danger); }
.dp-b {
  position: absolute; right: 1px; top: 1px; bottom: 1px; width: 36px;
  display: flex; align-items: center; justify-content: center;
  border: 0; background: none; cursor: pointer; color: var(--text-2);
  border-radius: 0 var(--r-ctrl) var(--r-ctrl) 0; transition: var(--tr);
}
.dp-b:hover { color: var(--primary); background: var(--primary-pale); }
.dp-b:disabled { opacity: .4; cursor: not-allowed; }
.toolbar .dp, .row > .dp { width: auto; }
.toolbar .dp > .fi, .row > .dp > .fi { min-width: 150px; }

.dp-pop {
  position: fixed; z-index: 90; width: 268px; padding: var(--sp-2);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-card);
  box-shadow: var(--shadow-pop);
  opacity: 0; transform: translateY(-4px); transition: opacity .16s ease, transform .16s ease;
}
.dp-pop.ouvert { opacity: 1; transform: none; }
.dp-nav { display: flex; align-items: center; gap: 4px; margin-bottom: 6px; }
.dp-f, .dp-tt {
  border: 0; background: none; cursor: pointer; font-family: inherit; color: var(--text);
  border-radius: 6px; transition: var(--tr);
}
.dp-f { width: 30px; height: 30px; color: var(--text-2); font-size: 14px; }
.dp-f:hover { background: var(--border-2); color: var(--text); }
/* En français, un nom de mois ne prend pas de capitale : « août 2026 », pas « Août 2026 ». */
.dp-tt { flex: 1; height: 30px; font-size: var(--fs-md); font-weight: 600; }
.dp-tt:hover:not(:disabled) { background: var(--border-2); }
.dp-tt:disabled { cursor: default; }
.dp-h { display: grid; grid-template-columns: repeat(7, 1fr); margin-bottom: 2px; }
.dp-h span { text-align: center; font-size: 11px; color: var(--gris-2); font-weight: 600; padding: 4px 0; }
.dp-j { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; }
.dp-m { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; padding: 4px 0; }
.dp-c {
  border: 1px solid transparent; background: none; cursor: pointer; font-family: inherit;
  font-size: var(--fs-sm); color: var(--text); height: 32px; border-radius: 7px;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
  font-variant-numeric: tabular-nums;
}
.dp-m .dp-c { height: 34px; }
.dp-c:hover:not(:disabled) { background: var(--border-2); }
.dp-c.off { color: var(--gris-2); }
.dp-c.auj { font-weight: 700; color: var(--primary); }
.dp-c.sel, .dp-c.sel:hover { background: var(--primary); color: var(--primary-txt); font-weight: 600; }
.dp-c:disabled { opacity: .3; cursor: not-allowed; }
.dp-foot { display: flex; gap: var(--sp-2); margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--border-2); }
.dp-lien {
  border: 0; background: none; cursor: pointer; font-family: inherit; font-size: var(--fs-sm);
  color: var(--primary); font-weight: 500; padding: 4px 6px; border-radius: 6px; transition: var(--tr);
}
.dp-lien:hover { background: var(--primary-pale); }

/* ---------- Barre de filtres ---------- */
.toolbar { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.toolbar .fi { width: auto; min-width: 150px; }

/* ---------- Menu « ⋯ » de ligne ---------- */
.menu-pop {
  position: absolute; z-index: 80; min-width: 200px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-ctrl);
  box-shadow: var(--shadow-pop); padding: 6px;
}
.menu-pop button {
  display: flex; align-items: center; gap: 9px; width: 100%; text-align: left;
  border: 0; background: none; cursor: pointer; font-family: inherit;
  font-size: var(--fs-md); color: var(--text); padding: 9px 10px; border-radius: 6px;
}
.menu-pop button:hover { background: var(--bg); }
.menu-pop button.danger { color: var(--danger); }
.menu-pop button.danger:hover { background: var(--danger-bg); }
.menu-pop .sep { height: 1px; background: var(--border-2); margin: 5px 4px; }

/* ---------- Modale ---------- */
dialog.tu-modal {
  border: 0; border-radius: 12px; padding: 0; max-width: 480px; width: calc(100vw - 32px);
  box-shadow: var(--shadow-modal); color: var(--text);
  /* Le reset « * { margin: 0 } » écrasait le margin:auto natif de <dialog>, qui porte le
     centrage : les modales s ouvraient collées en haut à gauche (mesuré le 18/08 : left 0, top 0). */
  margin: auto;
}
dialog.tu-modal::backdrop { background: rgba(15, 23, 42, .40); }
.tu-modal .m-head { padding: var(--sp-4) var(--sp-4) 0; }
.tu-modal .m-head h3 { font-size: var(--fs-h2); font-weight: 700; }
.tu-modal .m-head p { font-size: var(--fs-md); color: var(--text-2); margin-top: 6px; line-height: 1.55; }
.tu-modal .m-body { padding: var(--sp-2) var(--sp-4) var(--sp-2); }
.tu-modal .m-foot {
  display: flex; justify-content: flex-end; gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4) var(--sp-4);
}

/* ---------- Connexion ---------- */
.login-wrap {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  padding: var(--sp-5) var(--sp-3); background: var(--bg);
}
.login-card {
  background: var(--surface); width: 100%; max-width: 400px; padding: var(--sp-5);
  border-radius: 12px; border: 1px solid var(--border); box-shadow: var(--shadow-card);
}
.login-mark { display: flex; align-items: center; gap: 11px; margin-bottom: var(--sp-4); }
.login-mark .sq {
  width: 42px; height: 42px; background: none;
  display: flex; align-items: center; justify-content: center;
}
.login-mark .sq svg { width: 100%; height: 100%; display: block; }
.login-mark .nm {
  font-size: 27px; font-weight: 700; letter-spacing: -.015em; color: var(--brand-navy);
  font-family: var(--font-marque); font-synthesis: none;
}
.login-mark .nm i { color: var(--brand-turq); font-style: normal; padding: 0 4px; font-weight: 400; }
.login-foot {
  margin-top: var(--sp-4); padding-top: var(--sp-3); border-top: 1px solid var(--border-2);
  font-size: var(--fs-xs); color: var(--text-2); line-height: 1.55;
}

/* ---------- Grilles ---------- */
.grid-2 { display: grid; grid-template-columns: 2.1fr 1fr; gap: var(--sp-4); }
.grid-eq { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-4); }
.grid-side { display: grid; grid-template-columns: 2.9fr 1fr; gap: var(--sp-4); }
.grid-2 > *, .grid-eq > *, .grid-side > * { min-width: 0; }

/* ---------- Toasts : file discrète, accessible ---------- */
.toast-stack {
  position: fixed; bottom: 22px; right: 22px; z-index: 100;
  display: flex; flex-direction: column; gap: 8px; align-items: flex-end;
}
.toast {
  background: var(--text); color: #fff; padding: 11px 16px; border-radius: var(--r-ctrl);
  font-size: var(--fs-md); font-weight: 500; box-shadow: var(--shadow-pop);
  display: flex; align-items: center; gap: 9px;
  opacity: 0; transform: translateY(8px); transition: opacity .2s, transform .2s;
  max-width: min(420px, calc(100vw - 44px));
}
.toast.show { opacity: 1; transform: none; }
.toast .bi { flex-shrink: 0; }
.toast.ok .bi { color: #4ADE80; }
.toast.err .bi { color: #FCA5A5; }
.toast .toast-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.toast .toast-txt small { font-weight: 400; font-size: var(--fs-sm); opacity: .82; line-height: 1.35; }

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* ============================================================================
   MICRO-INTERACTIONS (etape 10 du brief, 150-250 ms)
   Une seule regle : le mouvement REPOND a un geste. Rien ne bouge tout seul, rien
   ne se rejoue en boucle, et la regle `prefers-reduced-motion` ci-dessus coupe l'ensemble.
   ========================================================================== */
/* L'appui s'enfonce d'un pixel : le seul retour tactile qu'un ecran sait donner. */
.btn { transition: var(--tr), transform .12s ease; }
.btn:active:not(:disabled) { transform: translateY(1px); }
.btn-ghost:active:not(:disabled) { background: var(--border-2); }
/* Les surfaces qui repondent au survol le disent en douceur. */
.kpi { transition: border-color .2s ease, box-shadow .2s ease; }
.card, .tt tr, .menu-pop button, .dp-b, .st { transition: var(--tr); }
/* La ligne cliquable d'un tableau : le fond arrive, il ne claque pas. */
.tt tr.clic { transition: background .16s ease; }
/* La bague de focus grandit au lieu d'apparaitre. */
.fi { transition: var(--tr), box-shadow .15s ease; }
/* L'etat actif de la barre laterale : le filet turquoise se pose avec le fond. */
.side nav a { transition: background .18s ease, color .18s ease, box-shadow .18s ease; }

/* Une modale arrive de 8 px, en 160 ms : assez pour qu'on la voie s'ouvrir,
   trop court pour qu'on l'attende. Le voile suit au meme rythme. */
@keyframes tu-modal-in { from { opacity: 0; transform: translateY(8px) scale(.985); } to { opacity: 1; transform: none; } }
@keyframes tu-fade-in { from { opacity: 0; } to { opacity: 1; } }
dialog.tu-modal[open] { animation: tu-modal-in .3s cubic-bezier(.16, 1, .3, 1) cubic-bezier(.2, .7, .3, 1); }
dialog.tu-modal[open]::backdrop { animation: tu-fade-in .16s ease; }
/* Le menu d'actions descend de 4 px depuis son declencheur. */
@keyframes tu-menu-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.menu-pop { animation: tu-menu-in .13s ease; }

/* ---------- Squelettes ---------- */
@keyframes skel { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }
.skel, .tt tr.skl td::before {
  background: linear-gradient(90deg, var(--border-2) 25%, #F7F8FA 37%, var(--border-2) 63%);
  background-size: 400% 100%; animation: skel 1.4s ease infinite;
  border-radius: 4px;
}
.skel { display: block; height: 13px; margin: 10px 0; }
.tt tr.skl td { padding: 15px var(--sp-4); border-bottom: 1px solid var(--border-2); }
.tt tr.skl td::before { content: ""; display: block; height: 13px; }
.tt tr.skl:nth-child(1) td::before { width: 82%; }
.tt tr.skl:nth-child(2) td::before { width: 64%; }
.tt tr.skl:nth-child(3) td::before { width: 73%; }

/* ---------- États vides ---------- */
.vide { padding: var(--sp-5) var(--sp-4); text-align: center; color: var(--text-2); }
.vide > .bi { font-size: 30px; color: #CBD5E1; display: block; margin-bottom: 10px; }
.vide b { display: block; color: var(--text); font-size: var(--fs-body); margin-bottom: 5px; font-weight: 600; }
.vide p { font-size: var(--fs-sm); max-width: 46ch; margin: 0 auto var(--sp-3); line-height: 1.55; }

/* ---------- Bandeaux d'assistance ---------- */
.imp-bar {
  background: var(--warn-bg); color: #92400E; border-bottom: 1px solid var(--warn-bd);
  padding: 10px var(--sp-5); font-size: var(--fs-sm); display: flex; align-items: center; gap: var(--sp-3);
}
.imp-bar b { font-weight: 700; }
.imp-bar .btn, .viewas-bar .btn {
  background: var(--surface); border-color: var(--warn-bd); color: #92400E;
  min-height: 30px; padding: 0 var(--sp-2); font-size: var(--fs-xs);
}
.imp-bar .btn:hover, .viewas-bar .btn:hover { background: var(--warn-bg); }
.viewas-bar {
  background: var(--primary-pale); color: var(--primary-h); border-bottom: 1px solid #C7D2FE;
  padding: 10px var(--sp-5); font-size: var(--fs-sm); display: flex; align-items: center; gap: var(--sp-3);
}
.viewas-bar .btn { border-color: #C7D2FE; color: var(--primary-h); }

/* ---------- Navigation mobile ---------- */
.navmob {
  display: none; position: fixed; bottom: 0; left: 0; right: 0; z-index: 60;
  background: var(--surface); border-top: 1px solid var(--border);
  padding: 6px 4px calc(6px + env(safe-area-inset-bottom));
}
.navmob a {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 7px 2px; text-decoration: none; color: var(--text-2);
  font-size: 11.5px; font-weight: 500; letter-spacing: .01em;
  min-height: 48px; justify-content: center; border-radius: var(--r-ctrl);
}
.navmob a .bi { font-size: 19px; }
.navmob a.on { color: var(--primary); font-weight: 600; }

/* ---------- Paliers responsive ---------- */
/* Tablette : sidebar compacte, icônes seules. */
@media (max-width: 1100px) {
  .grid-eq, .grid-2, .grid-side { grid-template-columns: 1fr; }
  .side { width: 64px; }
  .side-mark b, .side nav a > span.lbl, .side-sec, .side-foot { display: none; }
  .side nav a { justify-content: center; padding: 11px 0; }
  .side nav a .bi { width: auto; }
}
/* Mobile : bottom nav. */
@media (max-width: 860px) {
  .side { display: none; }
  .navmob { display: flex; }
  .body { padding: var(--sp-3) var(--sp-3) 92px; }
  .top { padding: var(--sp-2) var(--sp-3); }
  .top-title h1 { font-size: 20px; }
  .top-user .who { display: none; }
  /* Cibles tactiles : 44 px au doigt, mesures sur un telephone reel (390 px).
     Le bureau garde ses 40 px, ou l'on vise a la souris. */
  .btn { min-height: 44px; }
  .btn-sm { min-height: 44px; min-width: 44px; }
  .fi { height: 44px; }
  textarea.fi { height: auto; }
  .dp-b { width: 44px; }
  .lnk { min-height: 44px; padding: 0 var(--sp-1); }
  /* Un lien d'action dans une carte n'est qu'une ligne de texte de 16 px de haut :
     on lui donne une zone de touche sans changer son dessin. */
  .card a:not(.btn):not(.side-mark) { display: inline-block; padding: 13px 0; }
  .toast-stack { bottom: calc(78px + env(safe-area-inset-bottom)); }
}

/* ============================================================================
   TABLES INTERACTIVES (lot 2 du brief design, 18/08) : recherche, tri, pagination,
   ligne cliquable + menu, cartes sur téléphone. Un seul composant : CT.table (app.js).
   Tout passe par les tokens : le mode sombre suit sans une règle de plus.
   ========================================================================== */
/* Barre d'outils de la table : recherche à gauche, compteur à droite. */
.tbar {
  display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap;
  padding: var(--sp-2) var(--sp-4); border-bottom: 1px solid var(--border-2);
}
.rech { position: relative; flex: 1 1 240px; max-width: 360px; }
.rech .bi {
  position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
  color: var(--text-2); font-size: 14px; pointer-events: none;
}
.rech .fi, .toolbar .rech .fi { padding-left: 36px; width: 100%; min-width: 0; }
.rech .fi::-webkit-search-cancel-button { cursor: pointer; }
.tbar .cnt, .toolbar .cnt { color: var(--text-2); font-size: var(--fs-sm); white-space: nowrap; }
.tbar .cnt { margin-left: auto; }
/* Dans une barre de filtres existante (Pointages), la recherche se range à droite. */
.toolbar .rech { margin-left: auto; max-width: 300px; }
/* Sans espace pour une barre : la table défile sous le header collant, jamais dessous. */
.tbar, .toolbar, table.tt { scroll-margin-top: 96px; }

/* En-têtes triables : la flèche ne se montre qu'au survol, ou sur la colonne active. */
.tt th.tri { cursor: pointer; user-select: none; }
.tt th.tri:hover { color: var(--text); }
.tt th.tri .bi { font-size: 12px; margin-left: 4px; vertical-align: -1px; opacity: 0; transition: opacity .15s; }
.tt th.tri:hover .bi { opacity: .5; }
.tt th.tri.on { color: var(--text); font-weight: 600; }
.tt th.tri.on .bi { opacity: 1; color: var(--primary); }
.tt th.tri:focus-visible { outline-offset: -2px; }

/* Ligne cliquable : toute la ligne est la cible, le chevron le dit ; un seul menu « ⋯ ». */
.tt tr.lk { cursor: pointer; }
.tt tr.lk:hover td { background: var(--primary-pale); }
.tt tr.lk:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
.tt tr.sel td { background: var(--primary-pale); }
.tt tr.sel td:first-child { box-shadow: inset 3px 0 0 var(--primary); }
.tt td.act { width: 1%; white-space: nowrap; text-align: right; }
.tt td.act .chev { color: var(--text-2); font-size: 15px; opacity: .6; margin-left: 6px; vertical-align: middle; }
.tt td.act .btn-sm { min-height: 32px; padding: 0 8px; }
/* Ligne de détail dépliée sous une ligne cliquable (Écarts du planning). */
.tt tr.det td { background: var(--bg); padding-top: 8px; padding-bottom: 10px; }
.tt tr.det .sous { display: flex; flex-wrap: wrap; gap: 6px 18px; font-size: var(--fs-sm); }
.tt tr.det .sous > span { white-space: nowrap; }

/* Pied de table : compteur de tranche et pages. */
.tfoot {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); flex-wrap: wrap;
  padding: var(--sp-2) var(--sp-4); border-top: 1px solid var(--border-2);
  font-size: var(--fs-sm); color: var(--text-2);
}
.pg { display: flex; align-items: center; gap: 2px; }
.pg button {
  min-width: 34px; height: 34px; padding: 0 8px; border: 1px solid transparent; background: transparent;
  border-radius: var(--r-ctrl); color: var(--text-2); font: inherit; font-size: var(--fs-sm);
  cursor: pointer; transition: var(--tr);
}
.pg button:hover:not(:disabled) { background: var(--bg); color: var(--text); }
.pg button.on { background: var(--primary-pale); color: var(--primary); font-weight: 600; }
.pg button:disabled { opacity: .35; cursor: default; }
.pg .pts { padding: 0 4px; }

/* Avatar d'initiales dans une table (Collaborateurs). */
.tt .who { display: flex; align-items: center; }
.tt .who > div { min-width: 0; }
.tt .av {
  display: inline-flex; width: 32px; height: 32px; border-radius: 50%; flex: none;
  background: var(--primary-pale); color: var(--primary); font-size: 12px; font-weight: 700;
  align-items: center; justify-content: center; margin-right: 10px;
}

/* Bouton Déconnexion : le libellé au bureau, l'icône seule sur téléphone.
   (le span du libellé échappe à la règle « .top-user span » qui grise les sous-titres) */
.btn-logout .bi { display: none; }
.top-user .btn-logout .lbl { color: inherit; font-size: inherit; }

@media (max-width: 860px) {
  /* Header sur téléphone : titre et bloc utilisateur sur la première ligne, action
     primaire pleine largeur dessous, sous-titre tu : plus rien ne déborde à 390 px. */
  .top { flex-wrap: wrap; row-gap: var(--sp-1); }
  .top-title { order: 1; flex: 1 1 auto; min-width: 0; }
  .top-title .sub { display: none; }
  .top-actions { display: contents; }
  .top-user { order: 2; margin-left: auto; }
  .top-actions > .btn { order: 3; flex: 1 1 auto; }
  .btn-logout .lbl { display: none; }
  .btn-logout .bi { display: inline; font-size: 15px; }
  .btn-logout { padding: 0; width: 40px; }

  /* Cartes : le MÊME HTML de ligne, dessiné en carte (flex). Le gabarit de ligne pose
     td.tit (titre pleine largeur), td.sur (ligne discrète au-dessus), td.bloc-m (les
     pastilles en bas), td.vide-m (cellule sans valeur, tue), data-th (libellé en ligne). */
  .tt.tt-cartes thead { display: none; }
  .tt.tt-cartes, .tt.tt-cartes tbody { display: block; }
  .tt.tt-cartes tr {
    display: flex; flex-wrap: wrap; align-items: center; row-gap: 4px; position: relative;
    box-sizing: border-box; width: 100%; padding: 12px var(--sp-3); border-bottom: 1px solid var(--border-2);
  }
  .tt.tt-cartes tr:last-child { border-bottom: 0; }
  .tt.tt-cartes tr:hover td, .tt.tt-cartes tr.sel td { background: transparent; box-shadow: none; }
  .tt.tt-cartes tr.sel { box-shadow: inset 3px 0 0 var(--primary); }
  .tt.tt-cartes td { display: block; padding: 0; border: 0; font-size: var(--fs-sm); text-align: left; order: 3; }
  .tt.tt-cartes td.sur { order: 0; flex-basis: 100%; color: var(--text-2); font-size: var(--fs-xs); }
  .tt.tt-cartes td.tit { order: 1; flex-basis: 100%; font-size: var(--fs-md); padding-bottom: 4px; padding-right: 44px; }
  .tt.tt-cartes td.tit .mail { max-width: 100%; display: block; }
  .tt.tt-cartes td[data-th]:not([data-th=""])::before { content: attr(data-th) " "; color: var(--text-2); }
  .tt.tt-cartes td[data-th]:not([data-th=""]) ~ td[data-th]:not([data-th=""]):not(.bloc-m)::before { content: "\00b7\00a0" attr(data-th) " "; }
  .tt.tt-cartes tr::before { content: ""; order: 5; flex-basis: 100%; height: 2px; }
  .tt.tt-cartes td.bloc-m, .tt.tt-cartes td.bloc-m ~ td { order: 6; margin-right: 6px; }
  .tt.tt-cartes td.act { position: absolute; right: var(--sp-2); top: 10px; padding: 0; width: auto; margin: 0; }
  .tt.tt-cartes td.act .chev { display: none; }
  .tt.tt-cartes td.vide-m { display: none; }
  .tt.tt-cartes tr.det { padding-top: 0; }
  .tt.tt-cartes tr.det td { order: 1; flex-basis: 100%; }
  .tt.tt-cartes tr.skl td, .tt.tt-cartes td[colspan] { flex-basis: 100%; }
  .tbar .cnt { margin-left: 0; width: 100%; }
  .toolbar .rech { margin-left: 0; max-width: none; flex-basis: 100%; }
}

/* ============================================================================
   MODE SOMBRE « Navy de marque » (choix CEO du 18/08, redérivé sur la charte du 25/08)
   Le fond descend du navy officiel (#002A4B) : application, kiosque, écran QR et
   mails parlent la même langue. Bascule MANUELLE seule : rien ne change tant que
   l'utilisateur n'a pas cliqué (pas de prefers-color-scheme), le choix vaut pour
   son appareil. Tout passe par les tokens : aucune page n'a été retouchée pour ça.
   ========================================================================== */
:root[data-theme="dark"] {
  /* Fait suivre les controles NATIFS (cases a cocher, ascenseurs, listes deroulantes
     du systeme) : sans cela, une case non cochee reste un carre blanc sur fond navy. */
  color-scheme: dark;

  --bg: #041724;
  /* La surface est franchement plus claire que le fond : une carte doit se voir,
     pas se deviner (le premier essai à #131A3A donnait 1,13 de rapport). */
  --surface: #0D2739;
  --text: #E6F0F5;
  --text-2: #94AFBE;
  --border: #1F415A;
  --border-2: #163044;

  /* Sur fond sombre les roles s'inversent : c'est le turquoise qui porte l'action,
     et son texte redevient le navy de la marque (7,6:1). */
  --primary: #389C9A;
  --primary-h: #4FB0AE;
  --primary-txt: #002A4B;
  --primary-pale: #0F3646;
  --accent-turq-txt: #7FD6D5;

  --ok: #52E08A;      --ok-bg: #102C20;      --ok-bd: #245C3F;
  --warn: #F7C85A;    --warn-bg: #2D2209;    --warn-bd: #5B4617;
  --danger: #FB8686;  --danger-bg: #31171B;  --danger-bd: #63282E;

  --gris-2: #7B96A6;
  --ardoise-2: #013A5F;
  --or-pale: #0F3646;

  /* Une ombre noire ne se voit pas sur du noir : c'est le liseré qui porte le relief. */
  --shadow-card: 0 0 0 1px rgba(255, 255, 255, .03);
  --shadow-pop: 0 12px 32px rgba(0, 0, 0, .60);
  --shadow-modal: 0 22px 64px rgba(0, 0, 0, .70);

  --chart-aire: rgba(56, 156, 154, .18);
  --chart-grille: rgba(255, 255, 255, .10);
  --chart-neutre: #2E5468;
  --chart-conge: rgba(56, 156, 154, .45);
}
/* Surfaces de navigation : le navy de la marque, assumé. */
:root[data-theme="dark"] .side,
:root[data-theme="dark"] .navmob { background: #001B2E; }
/* Textes de badges : ces couleurs étaient en dur, pensées pour un fond clair. */
:root[data-theme="dark"] .st-p { color: var(--ok); }
:root[data-theme="dark"] .st-b { color: var(--warn); }
:root[data-theme="dark"] .st-a { color: var(--danger); }
:root[data-theme="dark"] .st-c { color: var(--text-2); }
:root[data-theme="dark"] .vide > .bi { color: #3B6076; }
:root[data-theme="dark"] dialog.tu-modal::backdrop { background: rgba(0, 0, 0, .62); }
/* Le chevron des listes déroulantes est une image : il faut sa version claire. */
:root[data-theme="dark"] select.fi {
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath fill='%2394AFBE' d='M1.4.6 6 5.2 10.6.6 12 2 6 8 0 2z'/%3E%3C/svg%3E");
}
/* Squelettes de chargement : le miroitement clair devient un miroitement sombre. */
:root[data-theme="dark"] .skel,
:root[data-theme="dark"] .tt tr.skl td::before { background-image: linear-gradient(90deg, #12354A 25%, #1B475F 37%, #12354A 63%); }
/* En sombre, la barre laterale est deja navy : c'est le mot-symbole qui doit rester blanc. */
:root[data-theme="dark"] .login-mark .nm { color: var(--text); }
/* Le bouton d'apparence, dans le bloc utilisateur. */
.btn-apparence { padding: 0; width: 40px; }
.btn-apparence .bi { font-size: 15px; }

/* ============================================================================
   CIBLES TACTILES, DERNIER MOT (etape 10 du brief)
   Ce bloc ferme la feuille EXPRES : les sections precedentes fixent des hauteurs de
   32 px pour les actions de ligne et la pagination, et a specificite egale c'est la
   derniere regle qui gagne. Mesure sur telephone reel (390 px), seuil 44 px.
   ========================================================================== */
@media (max-width: 860px) {
  .tt td.act .btn-sm { min-height: 44px; min-width: 44px; }
  .tfoot button { min-width: 44px; min-height: 44px; }
  .dp-b { top: 0; bottom: 0; }
}

/* ===== Outils d'en-tete : recherche globale + cloche (25/08, fonctions du designer) ===== */
.top-tools { position: relative; display: flex; align-items: center; gap: 4px; }
.top-tools .btn { position: relative; }
.notif-dot {
  position: absolute; top: 3px; right: 3px; min-width: 15px; height: 15px; padding: 0 4px;
  background: var(--danger); color: #fff; border-radius: 9px;
  font-size: 10px; font-weight: 700; line-height: 15px; text-align: center;
  font-variant-numeric: tabular-nums; pointer-events: none;
}
.ph {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 60;
  width: 384px; max-width: calc(100vw - 24px);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-card);
  box-shadow: 0 12px 32px rgba(2, 16, 29, .16); overflow: hidden;
}
.ph-tete { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); padding: 11px 14px; border-bottom: 1px solid var(--border); }
.ph-tete b { font-size: var(--fs-md); }
.ph-tete .lnk { color: var(--lien, var(--primary)); background: none; border: 0; padding: 0; cursor: pointer; font: inherit; font-size: var(--fs-xs); text-decoration: underline; text-underline-offset: 2px; }
.ph-corps { max-height: 380px; overflow-y: auto; }
.ph-item {
  display: flex; gap: 10px; align-items: flex-start; width: 100%; text-align: left;
  padding: 10px 14px; border: 0; border-bottom: 1px solid var(--border); background: none;
  cursor: pointer; color: var(--text); font: inherit; text-decoration: none;
}
.ph-item:last-child { border-bottom: 0; }
.ph-item:hover, .ph-item:focus-visible { background: var(--bg); }
.ph-item i { color: var(--text-2); font-size: 15px; margin-top: 1px; }
.ph-item .pi-c { min-width: 0; flex: 1; }
.ph-item .pi-t { font-weight: 600; font-size: var(--fs-sm); line-height: 1.4; }
.ph-item.lu .pi-t { font-weight: 500; color: var(--text-2); }
.ph-item .pi-b { font-size: var(--fs-xs); color: var(--text-2); line-height: 1.45; margin-top: 1px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.ph-item .pi-d { font-size: var(--fs-xs); color: var(--text-2); white-space: nowrap; margin-top: 1px; }
.ph-vide { padding: 26px 14px; text-align: center; color: var(--text-2); font-size: var(--fs-sm); }
.ph-vide i { display: block; font-size: 22px; margin-bottom: 6px; }
.ph-sec { padding: 8px 14px 3px; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .09em; color: var(--text-2); font-weight: 700; }
.ph-rech { padding: 10px 12px; border-bottom: 1px solid var(--border); }
.ph-rech input { width: 100%; }
@media (max-width: 640px) {
  .ph { position: fixed; top: 66px; left: 12px; right: 12px; width: auto; }
}


/* ==========================================================================
   Copier-coller du design Lovable (31/08/2026, ordre CEO) : les ANIMATIONS du
   designer (valeurs relevees dans son projet) et les composants propres a son
   rendu : anneaux KPI, panneau navy, point vert « en continu », chips,
   groupes replies de la barre, horloge, bloc utilisateur en bas.
   ========================================================================== */

/* --- Keyframes du designer (releves le 31/08) --- */
@keyframes kpi-rise { 0% { opacity: 0; transform: translateY(10px) scale(.985); } 100% { opacity: 1; transform: translateY(0) scale(1); } }
@keyframes reveal-in { 0% { opacity: 0; transform: translateY(8px); } 100% { opacity: 1; transform: translateY(0); } }
@keyframes live-pulse { 0% { box-shadow: 0 0 0 0 rgba(4, 120, 87, .6); } 70% { box-shadow: 0 0 0 5px rgba(4, 120, 87, 0); } 100% { box-shadow: 0 0 0 0 rgba(4, 120, 87, 0); } }
@keyframes badge-pulse { 0% { box-shadow: 0 0 0 0 rgba(56, 156, 154, .55); } 70% { box-shadow: 0 0 0 6px rgba(56, 156, 154, 0); } 100% { box-shadow: 0 0 0 0 rgba(56, 156, 154, 0); } }
@keyframes hey-wave { 0% { transform: rotate(0); } 15% { transform: rotate(-22deg); } 30% { transform: rotate(18deg); } 45% { transform: rotate(-14deg); } 60% { transform: rotate(10deg); } 75% { transform: rotate(-5deg); } 100% { transform: rotate(0); } }
@keyframes empty-halo { 0%, 100% { opacity: .55; transform: scale(1); } 50% { opacity: .85; transform: scale(1.06); } }

/* Entrees de cartes : .anim-rise sur les KPI (echelonnes de 55 ms par --i),
   .anim-reveal sur les grandes cartes. fill both = pas de flash avant l'entree. */
/* backwards et NON both : avec both, l animation terminee continue d imposer son transform
   final (une animation prime sur les declarations normales) et le survol de la tuile ne
   pouvait plus bouger. backwards garde l etat initial pendant le delai (aucun flash) et
   rend la main a la fin. Defaut trouve le 03/09 en mesurant le MOUVEMENT du survol. */
.anim-rise { animation: kpi-rise .55s var(--ease) backwards; animation-delay: calc(var(--i, 0) * 55ms); }
.anim-reveal { animation: reveal-in .5s var(--ease) backwards; }
@media (prefers-reduced-motion: reduce) {
  .anim-rise, .anim-reveal { animation: none; }
  .live i, .hey { animation: none; }
}

/* Le point vert « Mise a jour en continu » du designer : pulse 2 s infini. */
.live i { animation: live-pulse 2s infinite; background: var(--ok); }

/* La main du « Bonjour » : un salut a l'arrivee (origine au poignet). */
.hey { display: inline-block; animation: hey-wave 1.6s var(--ease) 1 .3s; transform-origin: 70% 70%; }

/* --- Anneau KPI du designer : SVG r=25, trait 3, fond --border --- */
.kpi { display: flex; align-items: center; gap: 13px; padding: 15px 16px 15px 14px; position: relative; }
.ring { width: 56px; height: 56px; flex-shrink: 0; position: relative; }
.ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.ring .fond { fill: none; stroke: var(--border); stroke-width: 3; }
.ring .val { fill: none; stroke-width: 3; stroke-linecap: round; transition: stroke-dashoffset .8s var(--ease); }
.ring b {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 14px; font-weight: 700; letter-spacing: -.02em; font-variant-numeric: tabular-nums;
}
.kpi .kt { min-width: 0; }
.kpi .kt .t {
  font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .09em;
  color: var(--text); margin: 0; display: block;
}
.kpi .kt .delta, .kpi .kt .st2 { font-size: 12px; color: var(--text-2); font-weight: 500; margin-top: 2px; }
.kpi .info { position: absolute; top: 10px; right: 12px; color: var(--text-2); opacity: .55; font-size: 13px; }
/* Pastille (i) REELLE sur les tuiles (02/09) : en haut a droite, masquee sur telephone comme chez lui. */
.kpi .info-hint { position: absolute; top: 10px; right: 10px; }
@media (max-width: 640px) { .kpi .info-hint { display: none; } }

/* --- Libelle de section au-dessus des cartes (« ANALYSE DE LA PERIODE ») --- */
.sec-label {
  margin: var(--sp-4) 0 var(--sp-2); font-size: 11.5px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .12em; color: var(--text-2);
}

/* --- Panneau NAVY du tableau de bord (« Alertes ») --- */
.pan-navy {
  background: #0B1F36; color: #E6EDF2; border-radius: var(--r-card);
  border: 1px solid rgba(255, 255, 255, .05); overflow: hidden;
}
.pan-navy .pn-t { display: flex; align-items: center; gap: 9px; padding: 15px 16px 11px; font-family: var(--font-titres); font-weight: 700; font-size: 15px; color: #FFF; }
.pan-navy .pn-lien { color: #9EC7C3; font-size: 12.5px; text-decoration: none; font-weight: 600; white-space: nowrap; margin-left: auto; }
.pan-navy .pn-lien:hover { color: #FFF; }
.pan-navy .pn-item { padding: 11px 16px; border-top: 1px solid rgba(255, 255, 255, .07); font-size: 13px; }
.pan-navy .pn-item .qui { color: #FFF; font-weight: 600; }
.pan-navy .pn-item .meta { color: #8495A0; font-size: 12px; }
.pan-navy .badge-haute {
  float: right; background: rgba(185, 28, 28, .28); color: #FCA5A5; font-size: 10.5px;
  font-weight: 700; letter-spacing: .08em; padding: 2px 8px; border-radius: 999px; text-transform: uppercase;
}
.pan-navy .pn-pied { padding: 10px 16px; border-top: 1px solid rgba(255, 255, 255, .07); font-size: 12.5px; color: #9EC7C3; display: flex; justify-content: space-between; align-items: center; cursor: pointer; }
.pan-navy .pn-pied:hover { color: #FFF; }
.btn-turq { background: var(--accent-turq); border-color: var(--accent-turq); color: #FFF; }
.btn-turq:hover { background: #178E81; border-color: #178E81; color: #FFF; }
.pt-rouge { width: 8px; height: 8px; border-radius: 50%; background: #EF4444; display: inline-block; flex-shrink: 0; }

/* --- Chips de filtre (periodes : actif turquoise plein, comme le designer) --- */
.chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 13px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--surface); color: var(--text-2);
  font-size: 12.5px; font-weight: 600; cursor: pointer; transition: var(--tr); font-family: inherit;
}
.chip:hover { border-color: var(--accent-turq); color: var(--text); }
.chip.on { background: var(--accent-turq); border-color: var(--accent-turq); color: #FFF; }

/* --- Header du designer : recherche pilule centrale + horloge --- */
.top-rech {
  flex: 1; max-width: 390px; min-width: 130px; height: 40px; border-radius: 999px;
  border: 1px solid rgba(217, 226, 234, .6); background: var(--surface);
  display: flex; align-items: center; gap: 9px; padding: 0 15px; cursor: text;
  color: var(--text-2); font-size: var(--fs-md); transition: var(--tr); font-family: inherit;
}
.top-rech:hover { border-color: var(--accent-turq); }
.top-rech .bi { font-size: 14px; flex-shrink: 0; }
.top-rech span { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.top-horloge {
  height: 36px; padding: 0 13px; border-radius: var(--r-ctrl); border: 1px solid var(--border);
  background: var(--bg); display: inline-flex; align-items: center;
  font-size: 14px; font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: .02em;
}
/* La cloche du designer : un POINT vert quand il y a du nouveau (le chiffre vit dans le panneau). */
.notif-dot { background: var(--ok); min-width: 9px; height: 9px; padding: 0; border-radius: 50%; font-size: 0; top: 5px; right: 6px; }

/* --- Bloc utilisateur en BAS de la barre (designer) --- */
.side-user {
  margin-top: auto; padding: 10px 12px 12px; border-top: 1px solid rgba(255, 255, 255, .08);
  display: flex; align-items: center; gap: 10px; cursor: pointer; background: none;
  border-left: 0; border-right: 0; border-bottom: 0;
  width: 100%; font-family: inherit; text-align: left; transition: var(--tr); border-radius: 0;
}
.side-user:hover { background: rgba(255, 255, 255, .05); }
.side-user .avatar { background: var(--accent-turq); color: #FFF; width: 34px; height: 34px; font-size: 12.5px; }
.side-user .qui { min-width: 0; flex: 1; line-height: 1.3; }
.side-user .qui b { display: block; color: #FFF; font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.side-user .qui span { color: #8495A0; font-size: 11.5px; }
.side-user .bi { color: #8495A0; font-size: 13px; }

/* Duree en chrono vivant dans les tables (tabular pour ne pas trembler). */
.chrono { font-variant-numeric: tabular-nums; font-weight: 700; }

/* Le panneau de recherche ancre sous la pilule centrale prend sa largeur. */
.top-rech-wrap { position: relative; flex: 1; max-width: 390px; min-width: 0; }
.top-rech-wrap .top-rech { width: 100%; }
.top-rech-wrap .ph { left: 0; right: 0; width: auto; }
/* Menu du bloc utilisateur (bas de barre) : les deux vrais boutons vivent ici. */
.side-user-menu { padding: 8px 10px; border-top: 1px solid rgba(255, 255, 255, .08); display: flex; flex-direction: column; gap: 2px; }
.side-user-menu .btn { justify-content: flex-start; color: #C8D3DA; border-color: transparent; width: 100%; }
.side-user-menu .btn:hover { background: rgba(255, 255, 255, .07); color: #FFF; border-color: transparent; }
@media (max-width: 860px) {
  .top-horloge { display: none; }
  .top-rech-wrap { max-width: 44px; }
  .top-rech span { display: none; }
  .top-rech { justify-content: center; padding: 0; width: 40px; }
  .top-rech-wrap .ph { position: fixed; top: 66px; left: 12px; right: 12px; }
}

/* Grille du tableau de bord du designer : heros large + colonne droite 360 px. */
.grid-heros { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: var(--sp-4); align-items: start; }
@media (max-width: 1100px) { .grid-heros { grid-template-columns: 1fr; } }
.kpis-anneaux { display: grid; grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); gap: var(--sp-3); }
.kpis-anneaux .kpi { background: var(--surface); border: 1px solid rgba(217, 226, 234, .55); border-radius: var(--r-card); box-shadow: var(--shadow-card); }

/* Finitions du 31/08 : hidden prime sur display:flex ; la main a besoin d'une fonte
   emoji ; les anciens points de lisere n'existent pas chez le designer. */
.side-user-menu[hidden] { display: none; }
.hey { font-family: 'Segoe UI Emoji', 'Noto Color Emoji', 'Apple Color Emoji', sans-serif; }
.kpis-anneaux .kpi.ok .t::before, .kpis-anneaux .kpi.warn .t::before, .kpis-anneaux .kpi.bad .t::before { display: none; }

/* Tuiles : sous-libelle et variation chacun sur SA ligne ; hidden prime toujours. */
.kpi .kt .st2, .kpi .kt .delta { display: block; }
.pan-navy .pn-pied[hidden] { display: none; }

/* --- Composant « carte personne » du designer (Presences, panneau A controler…) --- */
.pcol .pcol-t {
  display: flex; align-items: center; gap: 8px; padding: 13px 16px 9px;
  font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .09em; color: var(--text);
}
.pcol .pcol-t .bi { font-size: 14px; }
.pcol .pcol-t .cnt { margin-left: auto; color: var(--text-2); font-weight: 700; letter-spacing: 0; }
.pcol .pliste { padding: 2px 10px 10px; display: flex; flex-direction: column; gap: 8px; }
.pcarte {
  background: rgba(239, 243, 247, .25); border: 1px solid rgba(217, 226, 234, .6);
  border-radius: 19.6px; padding: 10px 13px;
}
.pcarte .ph1 { display: flex; align-items: center; gap: 10px; }
.pcarte .ph1 .avatar { width: 36px; height: 36px; font-size: 12.5px; }
.pcarte .qui { min-width: 0; flex: 1; line-height: 1.3; }
.pcarte .qui b { display: block; font-size: 13.5px; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pcarte .qui span { font-size: 12px; color: var(--text-2); }
.pcarte .chrono { font-size: 13.5px; color: var(--text); flex-shrink: 0; }
.pcarte .tiret { color: var(--text-2); font-weight: 700; flex-shrink: 0; }
.pcarte .psite { font-size: 11.5px; color: var(--text-2); margin: 7px 2px 0; }
.pcarte .prouge { font-size: 10.5px; color: var(--danger); margin: 4px 2px 0; font-weight: 500; }
.pplus {
  border: 0; background: none; cursor: pointer; font-family: inherit;
  padding: 8px; font-size: 12.5px; color: var(--text-2); font-weight: 600; border-radius: var(--r-ctrl);
}
.pplus:hover { color: var(--text); background: var(--bg); }
/* Badges doux du designer (« A verifier » ambre pale, « Cloturee d office » orange pale). */
.badge-doux {
  display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: 10.5px;
  font-weight: 700; letter-spacing: .04em; background: #FDF3D8; color: #8A5A00;
}
.badge-doux.orange { background: #FBE9DC; color: #9A4A12; }
.badge-doux.rougepale { background: var(--danger-bg); color: var(--danger); }

/* --- Retours CEO 31/08 : graisses et composants exacts du designer --- */
/* Bouton doux (« Vue complete », « Exporter ») : 12 px, graisse 500, bord fin. */
.btn-doux {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 500; letter-spacing: 0; color: var(--text);
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--r-ctrl);
  min-height: 30px; padding: 3px 12px; cursor: pointer; text-decoration: none;
  font-family: inherit; transition: var(--tr);
}
.btn-doux:hover { background: var(--surface); border-color: var(--accent-turq); color: var(--text); }
/* Panneau navy : lien de tete discret et items compacts (pas de boutons dans le panneau). */
.pan-navy .pn-lien { color: #8495A0; font-size: 12px; font-weight: 500; }
.pan-navy .pn-item-c {
  display: flex; align-items: center; gap: 8px; padding: 8px 16px;
  border-top: 1px solid rgba(255, 255, 255, .06); font-size: 12.5px; color: #E6EDF2;
  text-decoration: none; transition: var(--tr);
}
.pan-navy .pn-item-c:hover { background: rgba(255, 255, 255, .05); }
.pan-navy .pn-item-c .lib { min-width: 0; flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Badge de niveau du designer : 9,5 px w600, teinte sur fond de la meme teinte a 16 %. */
.badge-niv { font-size: 9.5px; font-weight: 600; padding: 2px 8px; border-radius: 999px; text-transform: none; flex-shrink: 0; }
.badge-niv.h { color: #F87171; background: rgba(185, 28, 28, .16); }
.badge-niv.m { color: #FACC15; background: rgba(219, 160, 0, .16); }
.badge-niv.b { color: #9DB2BF; background: rgba(148, 163, 175, .16); }
/* Top heures sup du designer : nom + valeur, BARRE FINE turquoise en dessous. */
.ths-ligne { padding: 7px 0; }
.ths-ligne .l1 { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; font-size: 13px; }
.ths-ligne .l1 .nom { font-weight: 500; color: var(--text); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ths-ligne .l1 .val { font-weight: 700; font-variant-numeric: tabular-nums; }
.ths-ligne .piste { height: 5px; background: var(--border-2); border-radius: 3px; margin-top: 5px; overflow: hidden; }
.ths-ligne .piste i { display: block; height: 100%; background: var(--accent-turq); border-radius: 3px; }
/* Delta AMBRE fixe du designer (Total heures supplementaires). */
.delta.ambre { color: var(--warn); }
/* Sous-grille des 2 graphes de la section Analyse (cote a cote comme chez le designer). */
.grid-analyse { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-3); }
@media (max-width: 900px) { .grid-analyse { grid-template-columns: 1fr; } }

/* Table du temps reel resserree : la carte gauche fait ~620 px sur un ecran 1280,
   la colonne Statut doit rester visible sans scroll. */
.tt-serre th, .tt-serre td { padding-left: 8px; padding-right: 8px; }
.tt-serre td { font-size: 12.5px; }
.tt-serre .avatar { width: 26px; height: 26px; font-size: 10px; }

/* --- Erreurs PAR CHAMP (brief design) : bordure danger + message sous le champ fautif. --- */
.fi-err, .fi-err:focus { border-color: var(--danger); box-shadow: 0 0 0 3px rgba(185, 28, 28, .10); }
.ferr-champ { font-size: 12px; font-weight: 500; color: var(--danger); margin: 5px 0 0; animation: reveal-in .18s var(--ease) both; }
.dp + .ferr-champ { margin-top: 2px; }

/* ════════════════════════════════════════════════════════════════════════
   LOT C : zones tactiles (mobile et tablette)
   ------------------------------------------------------------------------
   Repris de son socle `@media (pointer: coarse)` (src/styles.css du ZIP
   Lovable). Nous n'avions AUCUNE regle tactile : toutes nos media queries
   sont basees sur la LARGEUR, ce qui confond « petit ecran » et « ecran
   tactile ». Une tablette de pointage de 1280 px est tactile sans etre
   petite : c'est exactement notre cas d'usage principal.

   Echappatoire, comme chez lui : poser `data-dense` sur un conteneur exclut
   tous ses descendants de l'agrandissement, et `data-touch-compact` exclut
   un element precis.

   A INSERER a la fin de app.css.
   ════════════════════════════════════════════════════════════════════════ */

@media (pointer: coarse) {

  /* 11/09/2026 : ces regles etaient ecrites avec :where() (specificite nulle) et perdaient contre
     .btn-sm, .fi, .lv-sel… : les 44 px et les 16 px ne s appliquaient JAMAIS. Passees en :is(). */
  /* ---- 1. Toute action textuelle fait 44 px de haut au minimum ----------
     Exclus : les controles a coche (traites en 2), les elements a icone
     seule (traites en 3, chez nous l'icone est un <i class="bi">, chez lui
     un <svg>), et les zones explicitement denses. */
  :is(button, a[href], select, [role="button"],
         input:not([type="checkbox"]):not([type="radio"]):not([type="file"])):not([role="switch"]):not([role="checkbox"]):not([role="radio"]):not([role="option"]):not(:has(> svg:only-child)):not(:has(> i:only-child)):not([data-dense] *):not([data-touch-compact]):not(.sr-only) {
    min-height: 44px;
  }

  /* ---- 2. Cases, radios et interrupteurs : zone de tap 44 px ------------
     ⚠️ ECART ASSUME AVEC SON CODE, et il est justifie.
     Sa regle agrandit la zone par un pseudo-element sur le controle
     (`::after { inset: -14px }`). Elle NE FONCTIONNE PAS chez nous :
     nos controles sont de vrais <input>, et un navigateur ne PEINT pas les
     pseudo-elements d'un element remplace. Verifie par la mesure :
     `elementFromPoint` a 10 px du bord de la case ne renvoyait pas la case
     (0 zone active sur 2 controles). Chez lui ses cases sont des
     <button role="checkbox">, ou le pseudo-element fonctionne.

     Chez nous la zone naturelle est le LABEL parent, qui active deja la case
     au clic et fait deja 416 px de large. On lui donne 44 px de haut.
     ⭐ Cette adaptation est plus SURE que la sienne : deux labels de 44 px se
     touchent sans jamais se recouvrir, alors qu'un `inset: -14px` cree des
     zones qui se chevauchent (mesure : 1 chevauchement sur le seul ecran
     Parametres) et rend le tap ambigu entre deux controles voisins. */
  label:has(> input[type="checkbox"]),
  label:has(> input[type="radio"]),
  label.fl-check {
    min-height: 44px;
    display: flex;
    align-items: center;
    gap: 8px;
  }

  /* Controles a coche qui ne sont PAS dans un label (composants ARIA) :
     la regle du designer s'applique, elle fonctionne sur un non-input. */
  :is([role="checkbox"], [role="radio"], [role="switch"]):not(.sr-only) {
    position: relative;
  }
  :is([role="checkbox"], [role="radio"], [role="switch"]):not(.sr-only)::after {
    content: "";
    position: absolute;
    inset: -14px;
  }

  /* ---- 3. Boutons a icone seule : zone de tap elargie, visuel intact ---- */
  :is(button, a[href], [role="button"]):has(> i:only-child):not([data-dense] *),
  :is(button, a[href], [role="button"]):has(> svg:only-child):not([data-dense] *) {
    position: relative;
  }
  :is(button, a[href], [role="button"]):has(> i:only-child):not([data-dense] *)::after,
  :is(button, a[href], [role="button"]):has(> svg:only-child):not([data-dense] *)::after {
    content: "";
    position: absolute;
    inset: min(-8px, calc(50% - 22px));   /* zone de 44 px au moins, 48 px pour une icone de 32 px : une icone de 16 px n avait que 32 px */
  }

  /* ---- 4. Retour tactile : le controle s'enfonce sous le doigt ----------
     Pour les controles qui n'ont pas deja un etat actif propre. */
  :is(button, a[href], [role="button"]):not([data-dense] *) {
    transition: transform var(--dur-tactile) var(--ease);
  }
  :is(button, a[href], [role="button"]):not([data-dense] *):active {
    transform: scale(.97);
  }

  /* ---- 5. Lisibilite : pas de texte sous 12 px --------------------------
     ⚠️ Ecart assume avec lui : nos pastilles ont une geometrie FIXE
     (.notif-dot 15x15, .mbadge 22x22, .badge-haute en pilule). Les remonter
     a 12 px les deformerait, elles sont donc exclues. Lui n'a pas ce cas :
     ses badges sont dimensionnes par le contenu. */
  .side-sec, .dp-h span, .pcarte .psite, .side-user .qui span {
    font-size: 12px;
    line-height: 1.15rem;
  }

  /* ---- 6. Mouvement reduit : le retour tactile disparait aussi ---------- */
  @media (prefers-reduced-motion: reduce) {
    :is(button, a[href], [role="button"]):active {
      transform: none;
    }
  }
}

/* ---- 7. Champs de saisie a 16 px : empeche le zoom automatique d'iOS ----
   Sous 16 px, Safari iOS zoome sur le champ des qu'on le touche et ne
   dezoome jamais : l'ecran reste decale pour le reste de la session. */
@media (pointer: coarse) and (max-width: 1024px) {
  :is(input, select, textarea, .fi):not(.mfa-code) {    font-size: 16px !important;   /* anti-zoom iOS : la regle doit battre les tailles posees par les ecrans */
  }
}

/* ════════════════════════════════════════════════════════════════════════
   LOT B : etats interactifs (survol, appui, focus clavier, desactive)
   ------------------------------------------------------------------------
   Compte dans SON code source : 365 survols dans 62 fichiers, 175 focus
   clavier dans 30 fichiers, 96 etats actifs, 47 desactives. Chez nous :
   34 survols, 5 focus, 2 actifs, 8 desactives. C'est l'ecart que le
   designer voyait en premier.

   Ses deux gestes dominants, qui vont toujours ensemble :
     44 x `hover:-translate-y-px`  (l'element se souleve d'1 px)
     38 x `hover:shadow-raised`    (l'ombre signature, posee au lot A)
     42 x `active:translate-y-0`   (il retombe a l'appui : effet d'enfoncement)

   A INSERER a la fin de app.css, apres le lot C.
   ════════════════════════════════════════════════════════════════════════ */

/* ---- 1. La transition du mouvement, sur SA courbe -----------------------
   ⚠️ Remplace `.btn { transition: var(--tr), transform .12s ease; }` :
   la duree et la courbe etaient improvisees, elles suivent maintenant les
   jetons du lot A. Chez lui : transform, box-shadow et background sur la
   meme duree et la meme courbe. */
.btn, .btn-doux, .chip, .ph-item, .pcarte, .top-rech, .pplus, .side-user {
  transition: var(--tr), transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

/* ---- 2. Le geste de survol signature -----------------------------------
   L'element se souleve d'1 px et prend l'ombre. Les couleurs de survol
   restent celles de nos regles existantes : on n'ajoute QUE le mouvement
   et l'ombre, qui manquaient. */
.btn:hover:not(:disabled),
.btn-doux:hover:not(:disabled),
.chip:hover,
.ph-item:hover,
.top-rech:hover,
.pplus:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-raised);
}

/* Une CARTE se souleve de 2 px et sa bordure s'affirme (mesure faite sur
   ses cartes de collaborateur, ecran Presences). */
.pcarte:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-raised);
  border-color: var(--border-strong);
}

/* ---- 3. L'appui : l'element RETOMBE ------------------------------------
   ⚠️ Remplace `.btn:active:not(:disabled) { transform: translateY(1px); }`.
   Nous enfoncions de 1 px depuis la position neutre. Lui revient a 0 depuis
   la position soulevee : le deplacement est le meme, mais l'element ne passe
   jamais SOUS sa ligne de base. Il accelere aussi a l'appui (`duration-75`),
   ce qui rend le clic plus repondant. */
.btn:active:not(:disabled),
.btn-doux:active:not(:disabled),
.chip:active,
.ph-item:active,
.pcarte:active,
.top-rech:active,
.pplus:active {
  transform: translateY(0);
  transition-duration: 75ms;
}

/* ---- 4. Le focus clavier, partout --------------------------------------
   Il en a 175, nous en avions 5. Tout ce qui s'actionne doit se voir au
   clavier. Sa regle : contour de 2 px, decale de 2 px, couleur de marque.
   `.btn:focus-visible` la portait deja : on l'etend au reste. */
.btn-doux:focus-visible,
.chip:focus-visible,
.ph-item:focus-visible,
.pcarte:focus-visible,
.top-rech:focus-visible,
.pplus:focus-visible,
.menu-pop button:focus-visible,
.pan-navy .pn-lien:focus-visible,
.pan-navy .pn-pied:focus-visible,
.side-user-menu .btn:focus-visible,
.dp-lien:focus-visible,
.dp-c:focus-visible,
.dp-b:focus-visible {
  outline: 2px solid var(--accent-turq);
  outline-offset: 2px;
}

/* Sur le fond navy de la barre laterale, le turquoise d'interface se voit
   mal : on prend le turquoise de marque, plus clair (son `ring-offset-nav`
   repond au meme probleme). */
.side nav a:focus-visible,
.side-user:focus-visible,
.side-sec:focus-visible {
  outline: 2px solid var(--accent-turq);
  outline-offset: 2px;
}

/* ---- 5. L'etat desactive, uniforme -------------------------------------
   Chez lui : opacite .5, curseur interdit, et parfois `pointer-events:none`.
   ⚠️ ECART VOLONTAIRE : nous ne posons PAS `pointer-events: none` sur un
   bouton natif. Les deux se contredisent : sans evenements de pointeur, le
   curseur `not-allowed` ne s'affiche jamais, et l'utilisateur ne comprend
   pas pourquoi rien ne se passe. Un `<button disabled>` est deja inerte.
   On reserve donc `pointer-events: none` aux FAUX boutons (`aria-disabled`),
   qui eux resteraient cliquables. */
.btn:disabled,
button:disabled,
select:disabled,
input:disabled,
textarea:disabled {
  opacity: .5;
  cursor: not-allowed;
}
[aria-disabled="true"] {
  opacity: .5;
  cursor: not-allowed;
  pointer-events: none;
}

/* Un element desactive ne se souleve pas et ne s'enfonce pas. */
.btn:disabled:hover,
.btn:disabled:active,
button:disabled:hover,
button:disabled:active {
  transform: none;
  box-shadow: none;
}

/* ---- 6. Mouvement reduit -----------------------------------------------
   Le souleve disparait, l'ombre et le focus restent : l'information est
   conservee, seul le mouvement est retire. */
@media (prefers-reduced-motion: reduce) {
  .btn:hover, .btn-doux:hover, .chip:hover, .ph-item:hover,
  .pcarte:hover, .top-rech:hover, .pplus:hover,
  .btn:active, .btn-doux:active, .chip:active, .ph-item:active,
  .pcarte:active, .top-rech:active, .pplus:active {
    transform: none;
  }
}

/* ════════════════════════════════════════════════════════════════════════
   LOT E : les 3 animations du designer qui manquaient
   ------------------------------------------------------------------------
   Il en a 9 en propre, nous en avions transpose 6. Voici les 3 dernieres,
   reprises de son src/styles.css avec leurs durees et leurs courbes exactes.

   ⚠️ Il ecrit ses melanges en `color-mix(in oklab, X 7%, transparent)`.
   Nous les ecrivons en rgba equivalent : `color-mix` demande Chrome 111 ou
   Safari 16.2, et nos tablettes de pointage ne sont pas toutes recentes.
   Rendu identique, compatibilite plus large.
   ════════════════════════════════════════════════════════════════════════ */

/* ---- 1. SQUELETTE : balayage diagonal doux ------------------------------
   Le sien passe en diagonale (100deg) sur 1,7 s en ease-in-out, avec une
   bande large (200 % de fond). Le notre balayait a plat (90deg) sur 1,4 s
   avec une bande de 400 %, ce qui donnait un eclair plus dur et plus rapide.
   ⚠️ Remplace le rendu de `.skel` et `.tt tr.skl td::before` : meme
   structure, meme geometrie, seul le mouvement change. */
@keyframes skeleton-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

.skel,
.tt tr.skl td::before,
.skeleton-premium {
  background: linear-gradient(
    100deg,
    rgba(90, 107, 124, .07) 30%,
    rgba(90, 107, 124, .13) 50%,
    rgba(90, 107, 124, .07) 70%
  );
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.7s ease-in-out infinite;
}

/* Sur un fond sombre (barre laterale, panneau navy), le balayage clair est
   invisible : il prend la teinte du texte attenue de la barre, plus dense. */
.skeleton-premium-dark,
.side .skel,
.pan-navy .skel {
  background: linear-gradient(
    100deg,
    rgba(132, 149, 160, .14) 30%,
    rgba(132, 149, 160, .22) 50%,
    rgba(132, 149, 160, .14) 70%
  );
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.7s ease-in-out infinite;
}

/* ---- 2. MATCH-FLASH : le resultat trouve se signale ---------------------
   Chez lui : la recherche dans un document saute sur l'occurrence, qui
   pulse une fois. Chez nous l'usage est la RECHERCHE GLOBALE (Ctrl+K) :
   on arrive sur la page cible avec le terme pre-rempli, et la ligne
   trouvee se signale au lieu de laisser l'oeil la chercher.
   `scroll-margin-block` vient de lui : au defilement, l'element se pose au
   tiers de l'ecran et non colle au bord. */
@keyframes match-flash {
  0%   { box-shadow: 0 0 0 0 rgba(56, 156, 154, .55); transform: scale(1.04); }
  60%  { box-shadow: 0 0 0 5px rgba(56, 156, 154, 0); }
  100% { box-shadow: 0 0 0 0 rgba(56, 156, 154, 0); transform: scale(1); }
}

.match-active {
  animation: match-flash 620ms var(--ease);
  scroll-margin-block: 40%;
}
/* Sur une ligne de tableau, `transform: scale` deforme la grille : on garde
   la pulsation lumineuse et on retire l'echelle. */
tr.match-active {
  animation-name: match-flash;
  transform: none;
}

/* ---- 3. RESTORED-POP : un element qui (re)apparait ---------------------
   ⚠️ Pose en socle, SANS usage a ce jour : nous n'avons ni corbeille ni
   restauration, contrairement a lui. La classe attend son cas d'emploi,
   elle ne sera vivante que le jour ou un element reapparait apres une
   action. Ne pas la brancher artificiellement pour « l'utiliser ». */
@keyframes restored-pop {
  0%   { opacity: 0; transform: translateY(-3px) scale(.92); }
  55%  { opacity: 1; transform: translateY(0) scale(1.06); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

.restored-badge {
  animation: restored-pop .42s var(--ease-doux) both;
}

/* ---- 4. Mouvement reduit : il neutralise animation par animation -------- */
@media (prefers-reduced-motion: reduce) {
  .skel,
  .tt tr.skl td::before,
  .skeleton-premium,
  .skeleton-premium-dark,
  .match-active,
  .restored-badge {
    animation: none;
  }
}

/* ════════════════════════════════════════════════════════════════════════
   AVATARS : photo ou dessin dans la pastille existante
   ------------------------------------------------------------------------
   Les pastilles (.avatar, .tt .av) gardent EXACTEMENT leur geometrie : meme
   taille, meme rondeur, meme place dans la ligne. Seul leur contenu change.
   Quand la personne a une photo ou un avatar, on retire le fond pale et les
   initiales, et l image ou le dessin remplit la pastille.
   ════════════════════════════════════════════════════════════════════════ */

.avatar.av-visuel,
.avatar-user.av-visuel,
.tt .av.av-visuel {
  background: none;
  padding: 0;
  overflow: hidden;
}

/* La photo remplit la pastille sans se deformer : un portrait cadre en hauteur
   est recadre au centre plutot qu ecrase. */
.avatar .av-img,
.avatar-user .av-img,
.tt .av .av-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border-radius: 50%;
}

/* Le dessin de la galerie occupe toute la pastille, quelle que soit sa taille. */
.avatar > svg,
.avatar-user > svg,
.tt .av > svg {
  width: 100%;
  height: 100%;
  display: block;
  border-radius: 50%;
}

/* ---- Fenetre de choix ---------------------------------------------------- */
.av-choix { display: flex; flex-direction: column; gap: var(--sp-3); }

.av-apercu {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3); border: 1px solid var(--border); border-radius: var(--r-xl);
  background: var(--surface-muted);
}
.av-apercu .avatar { width: 64px; height: 64px; font-size: 22px; }
.av-apercu .qui b { display: block; font-family: var(--font-titres); font-size: 15px; }
.av-apercu .qui span { color: var(--text-2); font-size: 12.5px; }

.av-galerie {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(58px, 1fr));
  gap: 10px;
}
.av-galerie button {
  border: 2px solid transparent; background: none; padding: 2px; cursor: pointer;
  border-radius: 50%; line-height: 0;
  transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.av-galerie button:hover { transform: translateY(-2px); }
.av-galerie button:focus-visible { outline: 2px solid var(--accent-turq); outline-offset: 2px; }
.av-galerie button[aria-pressed="true"] { border-color: var(--accent-turq); }
.av-galerie svg { width: 100%; height: auto; border-radius: 50%; }

.av-actions { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.av-aide { color: var(--text-2); font-size: 12.5px; margin: 0; }

/* Invitation discrete a la premiere connexion : une carte, pas un mur. */
.av-invite {
  display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap;
  padding: 12px var(--sp-3); margin-bottom: var(--sp-3);
  border: 1px solid var(--border); border-radius: var(--r-xl);
  background: var(--surface);
  animation: reveal-in .5s var(--ease) both;
}
.av-invite .av-invite-txt { flex: 1; min-width: 200px; font-size: 13.5px; }
.av-invite .av-invite-txt b { font-family: var(--font-titres); }
.av-invite .av-invite-txt span { display: block; color: var(--text-2); font-size: 12.5px; }

@media (prefers-reduced-motion: reduce) {
  .av-invite { animation: none; }
  .av-galerie button:hover { transform: none; }
}

/* ════════════════════════════════════════════════════════════════════════
   LOT F : debordement horizontal des grilles
   ------------------------------------------------------------------------
   Un enfant de grille ou de flex prend par defaut la largeur INTRINSEQUE de
   son contenu (min-width: auto) : un tableau, un mot long ou une suite de
   chiffres suffit alors a pousser la page au-dela de l ecran. Le designer a
   la meme regle chez lui (`main .grid > * { min-width: 0 }`), nous ne
   l avions pas.
   Mesure qui a motive ce lot : a 1024 px, la largeur d une TABLETTE EN
   PAYSAGE, l ecran Feuilles d heures debordait de 30 px.
   ════════════════════════════════════════════════════════════════════════ */
.grid-eq > *, .grid-2 > *, .grid-side > *, .grid-heros > *,
.kpis > *, .kpis-anneaux > *, .fiche-2col > *, .fiche-anneaux > *,
.pcols > *, .body > .card {
  min-width: 0;
}

/* ════════════════════════════════════════════════════════════════════════
   LOT H : conformite du composant le plus repete du produit
   ------------------------------------------------------------------------
   Trouve en comparant SES ECRANS aux notres, apres que le CEO a signale le
   planning. Le probleme depasse le planning : c est LA CARTE elle-meme,
   presente sur tous les ecrans, qui n etait conforme sur aucun point.

   Son motif de bloc, repete partout dans son code :
       rounded-3xl (24 px) + border-border/60 + bg-card + shadow-float
   Le notre : 16,6 px de rayon et une ombre maison a deux couches.

   Mesure : il utilise ses deux ombres nommees 96 fois (shadow-float 46,
   shadow-raised 50). Nous les avions posees au lot A mais ne nous en
   servions QU AU SURVOL (lot B), jamais au repos.
   ════════════════════════════════════════════════════════════════════════ */

/* Il distingue deux elevations, nous n en avions qu une :
     - les GRANDS BLOCS (listes, panneaux, planning) : 24 px, ombre float ;
     - les PETITES CARTES (tuiles, vignettes) : 16,6 px, ombre discrete.
   On introduit le rayon des grands blocs sans toucher a --r-card, qui reste
   celui des tuiles. */
:root {
  --r-bloc: 24px;
}

.card {
  border-radius: var(--r-bloc);
  box-shadow: var(--shadow-float);
}

/* ---- Chiffres en chasse fixe -------------------------------------------
   Il pose `tabular-nums` 159 fois. Sans cela, les colonnes de chiffres
   DANSENT des qu une valeur change : un chrono qui tourne, un compteur
   temps reel, une heure qui s actualise font bouger toute la colonne.
   Mesure avant correction : sur le planning, 22 valeurs numeriques sur 52
   etaient en chasse fixe ; sur le tableau de bord, 13 sur 26.
   La regle est sans risque : `tabular-nums` n agit QUE sur les chiffres,
   jamais sur le texte. */
.tt td, .tt th,
.kpi, .kpi-val,
.pcarte, .ph1, .lrow,
.punch-clock, .chrono, [class*="chrono"] {
  font-variant-numeric: tabular-nums;
}

/* ════════════════════════════════════════════════════════════════════════
   VISIONNEUSE DE DOCUMENTS
   ------------------------------------------------------------------------
   Coque reprise de son DocumentViewer.tsx, valeur par valeur :
     conteneur      rounded-xl (16,6 px) + border-border/60 + shadow-float
     zone de lecture max-h 62vh + overflow-auto + bg-muted/40 + p-4
     barre d outils rounded-xl + border/60 + bg-muted/30 + px-2 py-1.5 + gap-1.5
     separateur     h-4 w-px bg-border/70
     etat vide      max-w-md + rounded-xl + px-5 py-8 + centre
     vue large      max-w-3xl + h-70vh

   ⚠️ ECART ASSUME ET EXPLIQUE : sa visionneuse affiche du TEXTE de
   demonstration decoupe en pages, ce qui lui permet la recherche plein texte,
   les miniatures de pages et le surlignage des occurrences. Nos documents
   sont de VRAIS fichiers (PDF, images) : rendre un PDF page par page
   demanderait une bibliotheque de rendu, et la regle produit interdit toute
   ressource externe cote navigateur. On affiche donc le document avec le
   lecteur NATIF du navigateur, sans aucune dependance. Le zoom, la coque et
   les etats sont conformes ; la recherche dans le texte ne l est pas, et ne
   peut pas l etre sans lever cette regle.
   ════════════════════════════════════════════════════════════════════════ */

/* La regle du socle « dialog.tu-modal » (0,1,1) l emportait sur « .dv-modal » (0,1,0) : la
   visionneuse restait a 480 px et la page se rendait a 272 px de large. Meme specificite que
   la fiche de Collaborateurs, et c est le CORPS qui defile, pas la fenetre. */
dialog.tu-modal.dv-modal { width: min(1180px, 96vw); max-width: min(1180px, 96vw); max-height: calc(100vh - 40px); display: flex; flex-direction: column; }
.dv-modal .m-head, .dv-modal .m-foot { flex: 0 0 auto; }
.dv-modal .m-body { flex: 1 1 auto; min-height: 0; overflow: hidden; display: flex; flex-direction: column; }
.dv-modal .dv-cadre { display: flex; flex-direction: column; min-height: 0; flex: 1 1 auto; }
.dv-corps > .dv-zone { flex: 1 1 auto; min-width: 0; overflow: auto; max-height: min(66vh, 720px); padding: 16px; }
.dv-modal .dv-barre { flex-wrap: wrap; }
/* ---------- Kit de filtres commun (11/09/2026) : badge, jetons, barres, période ----------
   Ne dans Congés (lv-*) puis Documents (dc-*), il servait a Pointages sans etre charge : les
   jetons y etaient nus et les barres invisibles. Il vit ici, une fois, pour tous les ecrans. */
.dc-badge { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 8px 16px; border-bottom: 1px solid var(--border-2); font-size: 11.5px; }
.dc-badge:empty { display: none; }
.dc-badge .dc-tete { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; color: var(--text-2); }
.dc-badge .dc-tete.actif { color: var(--primary); }
.dc-jeton { display: inline-flex; align-items: center; gap: 6px; padding: 2px 8px; border-radius: 999px; border: 1px solid var(--border); background: transparent; color: var(--text-2); font: inherit; font-size: 11px; font-weight: 600; cursor: pointer; transition: all .3s var(--ease); }
.dc-jeton .bi { font-size: 10px; opacity: .6; }
.dc-jeton:hover { border-color: rgba(56, 156, 154, .5); color: var(--primary); }
.dc-jeton.on { border-color: rgba(56, 156, 154, .6); background: rgba(56, 156, 154, .12); color: var(--primary); }
.dc-vider { border: 0; background: transparent; color: var(--primary); font: inherit; font-size: 11px; font-weight: 600; cursor: pointer; text-decoration: underline; padding: 2px 4px; }
.dc-barre { height: 5px; margin-top: 4px; border-radius: 999px; background: rgba(217, 226, 234, .7); overflow: hidden; }
.dc-barre i { display: block; height: 100%; border-radius: 999px; background: var(--accent-turq); transition: width .7s var(--ease); }
.dc-barre i.faible { background: var(--warn, #DBA000); }
.dc-per { display: inline-flex; align-items: center; gap: 6px; flex-wrap: nowrap; white-space: nowrap; font-size: 11px; color: var(--text-2); }
.dc-per .fi { width: 140px; }
/* ---------- Visionneuse PDF (10/09/2026, ses messages 220 a 233) : miniatures, recherche, calques ----------
   Le texte de la page est un CALQUE transparent au-dessus du canvas (PDF.js TextLayer) : c est lui
   qui porte les <mark> de surlignage, donc la selection et la recherche restent celles du vrai texte. */
.dv-corps { display: flex; gap: 10px; min-height: 0; }
.dv-minis { flex: 0 0 116px; max-height: min(64vh, 700px); overflow-y: auto; display: flex; flex-direction: column; gap: 8px; padding: 6px; border-radius: 12px; background: rgba(239, 243, 247, .6); }
.dv-minis[hidden] { display: none; }
.dv-mini { position: relative; border: 2px solid transparent; border-radius: 8px; padding: 3px; background: #FFF; cursor: pointer; transition: border-color .3s var(--ease), transform .3s var(--ease); }
.dv-mini:hover { transform: translateY(-1px); border-color: rgba(56, 156, 154, .5); }
.dv-mini.on { border-color: var(--accent-turq); box-shadow: 0 0 0 1px rgba(56, 156, 154, .35); }
.dv-mini canvas { display: block; width: 100%; height: auto; border-radius: 4px; }
.dv-mini-n { position: absolute; left: 6px; bottom: 6px; padding: 0 6px; border-radius: 999px; background: rgba(0, 42, 75, .85); color: #FFF; font-size: 10px; font-weight: 600; }
.dv-mini-badge { position: absolute; right: 6px; top: 6px; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px; background: var(--accent-turq); color: var(--primary); font-size: 10px; font-weight: 700; line-height: 18px; text-align: center; }
.dv-rech { display: flex; align-items: center; gap: 6px; margin: 0 0 8px; padding: 4px 8px; border: 1px solid var(--border-2); border-radius: 10px; background: rgba(239, 243, 247, .5); }
.dv-rech .bi-search { color: var(--text-2); font-size: 12px; }
.dv-rech input { flex: 1; min-width: 160px; height: 28px; border: 1px solid transparent; border-radius: 8px; background: transparent; padding: 0 6px; font: inherit; font-size: 12px; outline: 0; transition: border-color .3s var(--ease); }
.dv-rech input:focus { border-color: rgba(56, 156, 154, .5); background: #FFF; }
.dv-compte { font-size: 11px; color: var(--text-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
.dv-b { width: 32px; padding: 0; justify-content: center; }
.dv-zone { position: relative; }
.dv-page { position: relative; margin: 0 auto; background: #FFF; box-shadow: 0 1px 3px rgba(2, 20, 35, .12), 0 8px 24px rgba(2, 20, 35, .08); }
.dv-page-img { display: flex; justify-content: center; background: transparent; box-shadow: none; }
.dv-page-img img { transition: transform .3s var(--ease); transform-origin: center center; }
.dv-page canvas { display: block; }
.dv-attente { display: flex; align-items: center; justify-content: center; gap: 10px; padding: 40px; color: var(--text-2); font-size: 13px; }
.dv-attente[hidden] { display: none; }
.dv-attente { flex-wrap: wrap; }
.dv-progres { flex: 1 1 100%; height: 6px; margin-top: 10px; border-radius: 999px; background: rgba(217, 226, 234, .7); overflow: hidden; }
.dv-progres i { display: block; height: 100%; border-radius: 999px; background: var(--accent-turq); transition: width .3s var(--ease); }
.dv-pct { font-variant-numeric: tabular-nums; font-size: 11px; color: var(--text-2); }
/* Calque de texte de PDF.js 6, repris de son pdf_viewer.css et APLATI (aucune regle CSS imbriquee).
   PDF.js ne pose plus de styles en ligne : il ecrit --font-height et --scale-x sur chaque span, et
   --scale-factor sur le calque ; c est CETTE feuille qui en fait une taille et une echelle. Sans
   elle, tous les spans restaient a la taille par defaut et le surlignage tombait a cote du mot. */
.textLayer { color-scheme: only light; position: absolute; text-align: initial; inset: 0; overflow: clip; opacity: 1; line-height: 1; letter-spacing: normal; word-spacing: normal; text-size-adjust: none; forced-color-adjust: none; transform-origin: 0 0; caret-color: CanvasText; z-index: 1;
  --user-unit: 1; --total-scale-factor: calc(var(--scale-factor) * var(--user-unit)); --scale-round-x: 1px; --scale-round-y: 1px;
  --min-font-size: 1; --text-scale-factor: calc(var(--total-scale-factor) * var(--min-font-size)); --min-font-size-inv: calc(1 / var(--min-font-size)); }
.textLayer :is(span, br) { color: transparent; position: absolute; white-space: pre; cursor: text; transform-origin: 0% 0%; user-select: text; }
.textLayer > :not(.markedContent), .textLayer .markedContent span:not(.markedContent) { z-index: 1; --font-height: 0; font-size: calc(var(--text-scale-factor) * var(--font-height)); --scale-x: 1; --rotate: 0deg; transform: rotate(var(--rotate)) scaleX(var(--scale-x)) scale(var(--min-font-size-inv)); }
.textLayer .markedContent { display: contents; }
.textLayer span[role="img"] { user-select: none; cursor: default; }
.textLayer ::selection { background: rgba(0, 42, 75, .25); color: transparent; }
.textLayer .endOfContent { display: block; position: absolute; inset: 100% 0 0; z-index: 0; cursor: default; user-select: none; }
.textLayer.selecting .endOfContent { top: 0; }
.textLayer mark { color: transparent; background: rgba(56, 156, 154, .42); border-radius: 2px; }
/* L occurrence active reste LISIBLE : un aplat opaque cachait le mot sous le calque (vu a la capture). */
.textLayer mark.on { background: rgba(56, 156, 154, .55); box-shadow: 0 0 0 2px rgba(56, 156, 154, .7); }
@keyframes dv-flash { 0% { box-shadow: 0 0 0 6px rgba(56, 156, 154, .6); } 100% { box-shadow: 0 0 0 2px rgba(56, 156, 154, .55); } }
.textLayer mark.flash { animation: dv-flash .6s var(--ease) 1; }
@media (prefers-reduced-motion: reduce) { .textLayer mark.flash { animation: none; } .dv-page-img img { transition: none; } }

.dv-cadre {
  border: 1px solid rgba(217, 226, 234, .6);
  border-radius: var(--r-card);
  background: var(--surface);
  box-shadow: var(--shadow-float);
  overflow: hidden;
}

/* Barre d outils : ses contrôles sont des pilules de 32 px en 12 px. */
.dv-barre {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  padding: 6px 8px;
  border-bottom: 1px solid rgba(217, 226, 234, .6);
  background: var(--surface-muted);
}
.dv-barre .btn { height: 32px; border-radius: 999px; font-size: 12px; }
.dv-sep { width: 1px; height: 16px; margin: 0 2px; background: rgba(217, 226, 234, .7); flex: none; }
.dv-titre {
  min-width: 0; flex: 1;
  font-family: var(--font-titres); font-size: 13px; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.dv-zoom {
  font-size: 12px; color: var(--text-2); min-width: 46px; text-align: center;
  font-variant-numeric: tabular-nums;
}

/* Zone de lecture : sa hauteur (62vh) et son fond attenue. */
.dv-zone {
  max-height: 62vh; overflow: auto; scroll-behavior: smooth;
  background: var(--surface-muted);
  padding: 16px;
  display: flex; align-items: flex-start; justify-content: center;
}
.dv-zone img {
  display: block; max-width: 100%; height: auto;
  border: 1px solid rgba(217, 226, 234, .5);
  border-radius: var(--r-md);
  background: var(--surface);
  transform-origin: top center;
  transition: transform var(--dur) var(--ease);
}
/* Un PDF occupe toute la zone : le lecteur natif gere lui-meme ses pages. */
.dv-zone iframe {
  width: 100%; height: 70vh; max-width: 860px;
  border: 1px solid rgba(217, 226, 234, .6);
  border-radius: var(--r-card);
  background: var(--surface);
}

/* Format non affichable : sa carte d etat vide, centree. */
.dv-vide {
  margin: 0 auto; max-width: 420px;
  border: 1px solid rgba(217, 226, 234, .6);
  border-radius: var(--r-card);
  background: var(--surface);
  padding: 32px 20px; text-align: center;
}
.dv-vide .bi { font-size: 30px; color: var(--text-2); display: block; margin-bottom: 10px; }
.dv-vide b { display: block; font-family: var(--font-titres); font-size: 14.5px; margin-bottom: 4px; }
.dv-vide p { color: var(--text-2); font-size: 12.5px; margin: 0 0 14px; }

/* Le pied reprend ses metadonnees : petit, gris, separe par un filet. */
.dv-pied {
  border-top: 1px solid rgba(217, 226, 234, .6);
  padding: 10px 14px;
  font-size: 11.5px; color: var(--text-2);
  display: flex; flex-wrap: wrap; gap: 4px 14px; align-items: center;
}

@media (prefers-reduced-motion: reduce) {
  .dv-zone { scroll-behavior: auto; }
  .dv-zone img { transition: none; }
}

/* Bascule de periode de la courbe des couts : son groupe segmente en pilule
   (inline-flex items-center rounded-full border p-0.5). */
.ct-bascule {
  display: inline-flex; align-items: center; gap: 2px;
  padding: 2px; border: 1px solid var(--border); border-radius: 999px;
  background: var(--surface-muted);
}
.ct-bascule .chip { border: 0; height: 26px; font-size: 11.5px; }
.ct-bascule .chip.on { background: var(--primary); color: #FFF; }
.ct-tendance .card-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }

/* ════════════════════════════════════════════════════════════════════════
   LOT G-2 : pastille d information par bloc
   ------------------------------------------------------------------------
   Reprise de son InfoHint.tsx, valeur par valeur :
     bouton    16 px rond, gris a 60 %, icone 14 px
     zone tap  invisible de 16 px autour (after:-inset-4), comme au lot C
     survol    scale(1.1) + couleur de marque, transition 300 ms sur SA courbe
     focus     contour 2 px decale, couleur de marque
     bulle     fond NAVY (bg-sidebar), texte 11,5 px, rayon 13,6 px,
               largeur max 272 px, shadow-raised, decalage 8 px, delai 120 ms
   ════════════════════════════════════════════════════════════════════════ */

.info-hint {
  position: relative;
  display: inline-grid; place-items: center;
  width: 16px; height: 16px; flex: none;
  padding: 0; border: 0; background: none; cursor: help;
  color: rgba(90, 107, 124, .6);
  border-radius: 50%;
  transition: color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
/* La zone de tap deborde de 16 px sans changer le visuel : sur une tablette,
   une cible de 16 px est intouchable au doigt. */
.info-hint::after { content: ""; position: absolute; inset: -16px; }
.info-hint .bi { font-size: 13.5px; line-height: 1; }
.info-hint:hover { transform: scale(1.1); color: var(--accent-turq); }
.info-hint:focus-visible { outline: 2px solid var(--accent-turq); outline-offset: 2px; }

/* La bulle : une seule dans la page, deplacee au survol. Fond NAVY comme chez
   lui, pas blanc : elle se detache du contenu au lieu de s y fondre. */
.info-bulle {
  position: fixed; z-index: 9999;
  max-width: 272px;
  padding: 8px 12px;
  border: 1px solid var(--sidebar-border, #23374C);
  border-radius: var(--r-lg);
  background: #0B1F36;
  color: #C8D3DA;
  font-size: 11.5px; line-height: 1.6;
  box-shadow: var(--shadow-raised);
  opacity: 0; transform: translateY(4px);
  transition: opacity .2s var(--ease), transform .2s var(--ease);
  pointer-events: none;
}
.info-bulle.on { opacity: 1; transform: translateY(0); }

@media (prefers-reduced-motion: reduce) {
  .info-hint, .info-bulle { transition: none; }
  .info-hint:hover { transform: none; }
}

/* Lot G-4 : la carte de collaborateur devient un lien vers sa fiche.
   Elle garde EXACTEMENT son apparence : seul le curseur et le survol changent
   (le soulevement du lot B s applique deja a .pcarte). */
a.pcarte-lien { display: block; text-decoration: none; color: inherit; cursor: pointer; }
a.pcarte-lien:focus-visible { outline: 2px solid var(--accent-turq); outline-offset: 2px; }

/* ════════════════════════════════════════════════════════════════════════
   LOT G-3 : choix du style de menu (barre latérale claire ou navy)
   ------------------------------------------------------------------------
   Il propose DEUX variantes de navigation verticale et leur consacre 35 jetons
   (`nav` 21 + `sidebar` 14). Notre barre est navy ; voici sa variante claire,
   avec SES valeurs (oklch converties par le convertisseur validé du lot A).

   Le choix est INDÉPENDANT du mode sombre : on peut vouloir une barre claire
   en thème clair, et le thème sombre garde sa barre sombre quoi qu'il arrive.
   Mémorisé par appareil, comme l'apparence.
   ════════════════════════════════════════════════════════════════════════ */

:root[data-menu="clair"] {
  --nav: #FFFFFF;
  --nav-foreground: #002A4B;
  --nav-muted: #647383;
  --nav-active: var(--accent-turq);
  --nav-active-foreground: #FFFFFF;
  --nav-hover: #EFF4F9;
  --nav-border: #E0E7EE;
}

/* La barre reprend les jetons ci-dessus. Rien d'autre ne bouge : mêmes
   dimensions, mêmes espacements, même géométrie. Seules les couleurs changent. */
:root[data-menu="clair"] .side {
  background: var(--nav);
  border-right: 1px solid var(--nav-border);
  color: var(--nav-foreground);
}
:root[data-menu="clair"] .side nav a { color: var(--nav-foreground); }
:root[data-menu="clair"] .side nav a:hover { background: var(--nav-hover); }
:root[data-menu="clair"] .side nav a.on {
  background: var(--nav-active);
  color: var(--nav-active-foreground);
}
:root[data-menu="clair"] .side-sec { color: var(--nav-muted); }
:root[data-menu="clair"] .side-user { color: var(--nav-foreground); }
:root[data-menu="clair"] .side-user:hover { background: var(--nav-hover); }
:root[data-menu="clair"] .side-user .qui span { color: var(--nav-muted); }
:root[data-menu="clair"] .side-foot { color: var(--nav-muted); }
:root[data-menu="clair"] .side-user-menu {
  background: var(--nav);
  border: 1px solid var(--nav-border);
}
:root[data-menu="clair"] .side-user-menu .btn { color: var(--nav-foreground); }
:root[data-menu="clair"] .side-user-menu .btn:hover { background: var(--nav-hover); }

/* Sur fond clair, l'anneau de focus turquoise du lot B redevient lisible :
   on repasse au turquoise d'interface, plus contrasté que celui du brandbook. */
:root[data-menu="clair"] .side nav a:focus-visible,
:root[data-menu="clair"] .side-user:focus-visible,
:root[data-menu="clair"] .side-sec:focus-visible {
  outline-color: var(--accent-turq);
}

/* Le squelette sombre de la barre n'a plus lieu d'être sur fond clair. */
:root[data-menu="clair"] .side .skel {
  background: linear-gradient(100deg,
    rgba(90, 107, 124, .07) 30%, rgba(90, 107, 124, .13) 50%, rgba(90, 107, 124, .07) 70%);
  background-size: 200% 100%;
}

/* ⚠️ En thème sombre, la barre reste sombre quel que soit le choix : une barre
   blanche dans une interface sombre serait un phare en pleine nuit. */
:root[data-theme="dark"][data-menu="clair"] .side {
  background: #001B2E;
  border-right-color: var(--border);
  color: var(--text);
}
/* ════════════════════════════════════════════════════════════════════════
   LOT G-1 v2 (02/09) : blocs du tableau de bord déplaçables, DÉPOSE COMPLÈTE
   ------------------------------------------------------------------------
   Repris de son SortableStack + DragOverlay. ⚠️ Il utilise @dnd-kit ; la règle
   produit interdit toute dépendance front, donc événements POINTEUR natifs
   (souris et doigt), clavier conservé. Le rendu est le sien, valeur par valeur :
     poignée      ronde 28 px, bordure, fond carte, ombre légère, en haut à
                  DROITE du bloc (sa demande L574), révélée au survol du bloc
     fantôme      à la place du bloc saisi : cadre pointillé couleur de marque à
                  45 %, fond de marque à 4 %, 64 px, « Déplacement de « X »… »,
                  surmonté du filet d'insertion à lueur et de sa pastille à halo
     copie        le bloc cloné suit le curseur : scale 1.02, opacité .95,
                  shadow-raised, anneau de marque à 50 %
     voisins      glissent en 200 ms (FLIP) pour faire place
     dépose       la copie rejoint sa place en 220 ms cubic-bezier(.18,.9,.32,1)
   ════════════════════════════════════════════════════════════════════════ */

.pile-triable { position: relative; }
.pile-bloc { position: relative; }

.bloc-poignee {
  position: absolute; top: -8px; right: 8px; z-index: 5;
  display: inline-grid; place-items: center;
  width: 28px; height: 28px; padding: 0;
  border: 1px solid rgba(217, 226, 234, .6);
  background: var(--surface); border-radius: 50%;
  color: var(--text-2);
  box-shadow: 0 1px 2px rgba(0, 42, 75, .06);
  cursor: grab; opacity: 0;
  touch-action: none;
  transition: opacity var(--dur) var(--ease), color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.pile-bloc:hover .bloc-poignee,
.bloc-poignee:focus-visible { opacity: 1; }
.bloc-poignee:hover { color: var(--text); }
.bloc-poignee:focus-visible { outline: 2px solid rgba(56, 156, 154, .6); outline-offset: 2px; }
.bloc-poignee:active, .pile-en-cours .bloc-poignee { cursor: grabbing; }
.bloc-poignee .bi { font-size: 15px; }

/* Le bloc en vol sort du flux : le fantôme occupe sa place. À la dépose, il
   revient invisible le temps que la copie flottante le rejoigne. */
.bloc-en-vol { display: none; }
.bloc-invisible { visibility: hidden; }

.pile-fantome {
  position: relative;
  display: flex; align-items: center; gap: 12px;
  min-height: 64px; padding: 12px 16px;
  margin-top: var(--sp-4);
  border: 2px dashed rgba(56, 156, 154, .45);
  border-radius: var(--r-card);
  background: rgba(56, 156, 154, .04);
  color: rgba(56, 156, 154, .7);
  font-size: 13.5px; font-weight: 500;
}
.pile-fantome:first-child { margin-top: 0; }
.pile-fantome .bi { font-size: 16px; color: rgba(56, 156, 154, .6); flex: none; }
/* Le filet d'insertion et sa pastille, posés juste au-dessus du fantôme. */
.pile-fantome::before {
  content: ""; position: absolute; left: 0; right: 18px; top: -12px; height: 3px;
  border-radius: 999px; background: var(--accent-turq);
  box-shadow: 0 0 8px rgba(56, 156, 154, .55);
}
.pile-fantome::after {
  content: ""; position: absolute; right: 0; top: -15.5px; width: 10px; height: 10px;
  border-radius: 50%; background: var(--accent-turq);
  box-shadow: 0 0 0 5px rgba(56, 156, 154, .18);
}

.pile-flottant {
  position: fixed; z-index: 1000; pointer-events: none;
  opacity: .95;
  border-radius: var(--r-card);
  transform: scale(1.02);
  will-change: transform;
}
.pile-flottant > * { margin-top: 0 !important; box-shadow: 0 0 0 2px rgba(56, 156, 154, .5), var(--shadow-raised) !important; }
.pile-en-cours { user-select: none; -webkit-user-select: none; cursor: grabbing; }

@media (prefers-reduced-motion: reduce) {
  .bloc-poignee, .pile-bloc, .pile-flottant { transition: none !important; }
}

/* Sur écran tactile la poignée reste visible : il n'y a pas de survol pour la
   révéler, et une commande qu'on ne voit jamais n'existe pas. */
@media (pointer: coarse) {
  .bloc-poignee { opacity: 1; }
}

/* ════════════════════════════════════════════════════════════════════════
   SOUS-TITRES DE BLOC (02/09, son Panel : title + description sous le titre)
   ------------------------------------------------------------------------
   « Cumul du mois en cours », « Éléments nécessitant une décision »… : la
   phrase qui dit ce que le bloc mesure vit SOUS le titre, en 11 px gris,
   tronquée sur une ligne. Le (i) reste collé au titre.
   ════════════════════════════════════════════════════════════════════════ */
.card > h4 .h4-t, .pan-navy .pn-t .h4-t { display: flex; flex-direction: column; min-width: 0; flex: 1 1 12rem; gap: 1px; }
.h4-l { display: flex; align-items: center; gap: 6px; min-width: 0; }
.h4-l > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.h4-sous {
  display: block; font-family: 'Plus Jakarta Sans', system-ui, sans-serif;
  font-size: 11px; font-weight: 500; line-height: 1.4; color: var(--text-2);
  letter-spacing: 0; text-transform: none;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.h4-sous .live { font-size: 11px; font-weight: 500; color: var(--text-2); }
.h4-sous .live i { margin-right: 8px; }
.pan-navy .pn-sous { color: #8495A0; }
.pan-navy .info-hint { color: rgba(200, 211, 218, .55); }
.pan-navy .info-hint:hover { color: #FFF; }
.card > h4 .btn-doux, .card > h4 .fi-inline { align-self: center; }

/* ════════════════════════════════════════════════════════════════════════
   MENU DU COMPTE (02/09, son SidebarAccount) : popover 240 px au-dessus du
   bloc utilisateur, fond carte : en-tête nom + e-mail, rôle et phrase de
   permissions, actions, Déconnexion en rouge. S'ouvre au survol ou au clic.
   ════════════════════════════════════════════════════════════════════════ */
.side-user-wrap { margin-top: auto; position: relative; }
.side-user-wrap .side-user { margin-top: 0; }
.side-user .bi-chevron-down { transition: transform .2s var(--ease); }
.side-user[aria-expanded="true"] .bi-chevron-down { transform: rotate(180deg); }
.side-user-menu, :root[data-menu="clair"] .side-user-menu {
  position: absolute; left: 12px; right: 12px; bottom: calc(100% + 8px); z-index: 60;
  min-width: 236px; padding: 0; gap: 0;
  border: 1px solid var(--border); border-radius: var(--r-lg);
  background: var(--surface); color: var(--text);
  box-shadow: var(--shadow-raised);
  animation: tu-menu-in .18s var(--ease);
}
.side-user-menu[hidden] { display: none; }
.sum-tete { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-bottom: 1px solid var(--border-2); }
.sum-tete .sum-av { width: 36px; height: 36px; font-size: 12px; background: var(--primary); color: #FFF; flex: none; }
.sum-tete .qui { min-width: 0; line-height: 1.3; }
.sum-tete .qui b { display: block; font-size: 13.5px; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sum-tete .qui span { display: block; font-size: 12px; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sum-role { padding: 10px 12px; border-bottom: 1px solid var(--border-2); }
.sum-lbl { display: block; font-size: 10.5px; font-weight: 500; text-transform: uppercase; letter-spacing: .06em; color: var(--text-2); margin-bottom: 6px; }
.sum-role b { display: block; font-size: 12.5px; font-weight: 600; color: var(--text); padding: 6px 8px; border: 1px solid var(--border); border-radius: var(--r-ctrl); background: var(--bg); }
.sum-desc { display: block; margin-top: 6px; font-size: 11px; line-height: 1.45; color: var(--text-2); }
.sum-actions { padding: 4px; }
.sum-pied { padding: 4px; border-top: 1px solid var(--border-2); }
.sum-item, :root[data-menu="clair"] .side-user-menu .sum-item {
  display: flex; align-items: center; gap: 8px; width: 100%; padding: 7px 8px;
  border: 0; background: none; border-radius: var(--r-sm);
  font: inherit; font-size: 13.5px; color: var(--text); text-align: left; text-decoration: none;
  cursor: pointer; transition: background-color .15s var(--ease), color .15s var(--ease);
}
.sum-item:hover, :root[data-menu="clair"] .side-user-menu .sum-item:hover { background: rgba(0, 42, 75, .06); color: var(--text); }
.sum-item:focus-visible { outline: 2px solid var(--accent-turq); outline-offset: -2px; }
.sum-item .bi { font-size: 15px; color: var(--text-2); width: 16px; text-align: center; flex: none; }
.sum-logout, .sum-logout .bi, :root[data-menu="clair"] .side-user-menu .sum-logout { color: var(--danger); }
.sum-logout:hover, :root[data-menu="clair"] .side-user-menu .sum-logout:hover { background: rgba(185, 28, 28, .08); color: var(--danger); }
:root[data-theme="dark"] .sum-item:hover { background: rgba(255, 255, 255, .07); }
:root[data-theme="dark"] .sum-logout:hover { background: rgba(248, 113, 113, .12); }
@media (prefers-reduced-motion: reduce) { .side-user-menu { animation: none; } .side-user .bi-chevron-down { transition: none; } }

/* ════════════════════════════════════════════════════════════════════════
   CASCADE DE CHARGEMENT (lot 1d, 02/09, ses Skeletons + skeleton-shimmer)
   ------------------------------------------------------------------------
   .sq        un os de squelette : reflet diagonal 1,7 s (7 % → 13 % → 7 % du
              gris de texte, 100°), rayon 6 px ; .sq-sombre sur le navy
   .bloc-sq   le squelette d'un bloc, au gabarit du contenu réel
   .sq-cache  le bloc cache son contenu réel tant que le squelette est là
   .revele    fondu + levée 0,5 s cubic-bezier(.16,1,.3,1) à l'arrivée
   ════════════════════════════════════════════════════════════════════════ */
@keyframes sq-reflet { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
.sq {
  display: block; border-radius: 6px; flex: none;
  background-image: linear-gradient(100deg, rgba(90, 107, 124, .07) 30%, rgba(90, 107, 124, .13) 50%, rgba(90, 107, 124, .07) 70%);
  background-size: 200% 100%;
  animation: sq-reflet 1.7s ease-in-out infinite;
}
.sq.sq-sombre { background-image: linear-gradient(100deg, rgba(132, 149, 160, .14) 30%, rgba(132, 149, 160, .22) 50%, rgba(132, 149, 160, .14) 70%); }
:root[data-theme="dark"] .sq { background-image: linear-gradient(100deg, rgba(200, 211, 218, .07) 30%, rgba(200, 211, 218, .13) 50%, rgba(200, 211, 218, .07) 70%); }
.sq-rond, .sq-pilule { border-radius: 999px; }
.sq-cache > :not(.bloc-sq) { display: none !important; }
.sq-cache { overflow: hidden; }
.bloc-sq { display: block; }
.sq-tete { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 16px 20px 8px; }
.pan-navy .sq-tete { border-bottom: 1px solid rgba(255, 255, 255, .07); padding-bottom: 12px; }
.sq-corps { padding: 8px 20px 20px; }
.sq-corps-sombre { padding: 0; }
.sq-ligne { display: flex; align-items: center; gap: 12px; padding: 10px 0; }
.sq-corps-sombre .sq-ligne { padding: 10px 16px; border-bottom: 1px solid rgba(255, 255, 255, .07); }
.sq-corps-sombre .sq-ligne-h { border-bottom: 0; border-top: 1px solid rgba(255, 255, 255, .07); gap: 8px; }
.sq-col { flex: 1; min-width: 0; }
.sq-filtres { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 10px 16px; border-top: 1px solid var(--border-2); border-bottom: 1px solid var(--border-2); }
.sq-graphe { display: flex; align-items: flex-end; gap: 6px; height: 220px; padding: 16px 16px 20px; }
.sq-barre { flex: 1; border-radius: 3px 3px 0 0; }
.sq-grille2 { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 16px; margin-top: 12px; }
.sq-grille2 .sq-ligne { padding: 2px 0; gap: 8px; }
.sq-kpi { display: flex; align-items: center; gap: 13px; padding: 15px 16px 15px 14px; }
/* La barre du haut : son squelette la recouvre 120 ms, sans toucher au vrai contenu. */
.top { position: relative; }
.top.sq-cache > :not(.bloc-sq) { display: flex !important; visibility: hidden; }
.bloc-sq-top { position: absolute; inset: 0; display: flex; align-items: center; padding: 0 var(--sp-5); background: var(--bg); }
.sq-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; width: 100%; }
.sq-top-d { display: flex; align-items: center; gap: 8px; }
@media (max-width: 860px) { .sq-top-d .sq-pilule, .sq-top-d .sq:nth-child(2), .sq-top-d .sq:last-child { display: none; } }
/* backwards, jamais both : sinon l animation terminee fige le transform de l element
   revele et tout survol (tuile a -3 px) devient impossible. */
.revele { animation: reveal-in .5s cubic-bezier(.16, 1, .3, 1) backwards; }
@media (prefers-reduced-motion: reduce) { .sq { animation: none; } .revele { animation: none; } }

/* ════════════════════════════════════════════════════════════════════════
   LOT 2 (03/09) : tuiles KPI cliquables, Répartition de l'effectif, Actions rapides
   ════════════════════════════════════════════════════════════════════════ */
/* La tuile est un lien : levée + ombre au survol, halo de marque (son kpi-glow). */
a.kpi { color: inherit; text-decoration: none; cursor: pointer; }
.kpi { transition: transform .3s cubic-bezier(.16, 1, .3, 1), box-shadow .3s cubic-bezier(.16, 1, .3, 1), border-color .2s ease; }
a.kpi:hover { transform: translateY(-1px); box-shadow: var(--shadow-raised); }
a.kpi::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; opacity: 0;
  background: radial-gradient(120% 90% at 20% 0%, rgba(56, 156, 154, .10), transparent 60%);
  transition: opacity .3s cubic-bezier(.16, 1, .3, 1);
}
a.kpi:hover::after { opacity: 1; }
a.kpi:active { transform: translateY(0); }
a.kpi:focus-visible { outline: 2px solid var(--accent-turq); outline-offset: 2px; }
.kpi .kt .st2:empty { display: none; }
/* Répartition de l'effectif : barre segmentée 10 px + légende sur 2 colonnes. */
.rep-barre { display: flex; height: 10px; border-radius: 999px; overflow: hidden; background: var(--border-2); }
.rep-barre span { display: block; height: 100%; }
.rep-barre[hidden] { display: none; }
.rep-legende { list-style: none; margin: 12px 0 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 6px 16px; }
.rep-legende li { display: flex; align-items: center; gap: 8px; font-size: 12px; min-width: 0; }
.rep-pt { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.rep-lib { color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rep-n { margin-left: auto; font-weight: 600; font-variant-numeric: tabular-nums; }
/* Actions rapides : ses boutons « outline, sm, h-auto, texte à gauche, 2 colonnes ». */
.quick-grid { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.quick-btn {
  display: flex; align-items: center; gap: 8px; width: 100%; padding: 8px 10px;
  border: 1px solid var(--border); border-radius: var(--r-ctrl); background: var(--surface);
  color: var(--text); font-size: 12px; font-weight: 500; line-height: 1.3; text-align: left; text-decoration: none;
  transition: transform .3s cubic-bezier(.16, 1, .3, 1), box-shadow .3s cubic-bezier(.16, 1, .3, 1), border-color .2s ease, background-color .2s ease;
}
.quick-btn .bi { font-size: 16px; flex: none; color: var(--text-2); }
.quick-btn:hover { transform: translateY(-1px); box-shadow: var(--shadow-raised); border-color: var(--accent-turq); }
.quick-btn:active { transform: translateY(0); }
.quick-btn:focus-visible { outline: 2px solid var(--accent-turq); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { a.kpi, .quick-btn { transition: none; } a.kpi:hover, .quick-btn:hover { transform: none; } }
/* Sa grille de tuiles : 2 colonnes, 3 dès 768 px, 5 dès 1280 px (jamais 4 + 1 orpheline). */
.kpis-anneaux { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (min-width: 768px) { .kpis-anneaux { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1280px) { .kpis-anneaux { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
.kpi .kt .t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ════════════════════════════════════════════════════════════════════════
   LOT 3 (03/09) : Alertes en accordéon avec action, Congés, Total HS, états vides
   ════════════════════════════════════════════════════════════════════════ */
/* Ligne d'alerte (son AlertRow) : pastille, titre + employé, raison, badge, heure, bouton. */
.pan-navy .pn-al { display: flex; align-items: center; gap: 10px; padding: 10px 16px; border-top: 1px solid rgba(255, 255, 255, .07); transition: background-color .3s cubic-bezier(.16, 1, .3, 1); }
.pan-navy .pn-al:hover { background: rgba(255, 255, 255, .05); }
.pn-pt { width: 8px; height: 8px; border-radius: 50%; flex: none; align-self: flex-start; margin-top: 5px; }
.pn-corps { min-width: 0; flex: 1; }
.pn-l1 { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.pn-titre { font-size: 13px; font-weight: 600; color: #FFF; line-height: 1.25; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pn-emp { font-size: 11px; color: #8495A0; flex: none; }
.pn-raison { margin-top: 2px; font-size: 11px; line-height: 1.5; color: rgba(132, 149, 160, .85); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pn-droite { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; flex: none; }
.pn-bas { display: flex; align-items: center; gap: 6px; }
.pn-heure { font-size: 10.5px; color: rgba(132, 149, 160, .7); font-variant-numeric: tabular-nums; }
.pn-act {
  height: 24px; padding: 0 8px; border: 0; border-radius: 6px;
  background: var(--accent-turq); color: #FFF; font: inherit; font-size: 11px; font-weight: 500; cursor: pointer;
  transition: transform .3s cubic-bezier(.16, 1, .3, 1), box-shadow .3s cubic-bezier(.16, 1, .3, 1), background-color .3s cubic-bezier(.16, 1, .3, 1);
}
.pn-act:hover { transform: translateY(-1px); background: #1B8C80; box-shadow: var(--shadow-raised); }
.pn-act:active { transform: translateY(0); }
.pn-act:focus-visible { outline: 2px solid #FFF; outline-offset: 2px; }
/* L'accordéon : bouton « Voir N autres alertes » + zone à hauteur animée (grid-template-rows). */
.pn-acc[hidden] { display: none; }
.pn-plus { display: flex; align-items: center; gap: 8px; width: 100%; padding: 10px 16px; border: 0; border-top: 1px solid rgba(255, 255, 255, .07); background: none; color: #8495A0; font: inherit; font-size: 12px; font-weight: 500; text-align: left; cursor: pointer; transition: background-color .3s cubic-bezier(.16, 1, .3, 1); }
.pn-plus:hover { background: rgba(255, 255, 255, .05); }
.pn-plus:focus-visible { outline: 2px solid var(--accent-turq); outline-offset: -2px; }
.pn-plus .bi { font-size: 13px; transition: transform .3s cubic-bezier(.16, 1, .3, 1); }
.pn-plus[aria-expanded="true"] .bi { transform: rotate(180deg); }
.pn-reste { margin-left: auto; font-size: 11px; color: rgba(132, 149, 160, .7); font-variant-numeric: tabular-nums; }
.pn-acc-zone { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .3s cubic-bezier(.16, 1, .3, 1); }
.pn-acc.on .pn-acc-zone { grid-template-rows: 1fr; }
.pn-acc-int { overflow: hidden; }
.pn-acc-int .pn-al:first-child { border-top: 1px solid rgba(255, 255, 255, .07); }
/* États vides : variante navy et variante compacte (petits blocs, comme son EmptyState compact). */
.vide-navy { color: #8495A0; } .vide-navy b { color: #FFF; } .vide-navy > .bi { color: #3B6076; }
.vide-compact { padding: 18px 16px; } .vide-compact > .bi { font-size: 24px; margin-bottom: 8px; }
.vide-compact p { margin-bottom: 0; }
/* Congés : une demande par ligne, séparées d'un filet. */
.cg-ligne { padding: 12px 16px; border-bottom: 1px solid var(--border-2); }
.cg-ligne:last-child { border-bottom: 0; }
/* Total heures supplémentaires : anneau, valeur, variation, repère. */
.ths-total { display: flex; align-items: center; gap: 16px; padding: 4px 0; }
.ths-total[hidden] { display: none; }
.ths-total .val { display: block; font-size: 14px; font-weight: 600; color: var(--text); }
.ths-total .delta { font-size: 12px; font-weight: 500; margin-top: 1px; }
.ths-total .delta.ambre { color: #B45309; }
.ths-total .delta.vert { color: var(--ok); }
.ths-total .repere { font-size: 11px; color: var(--text-2); margin-top: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Finitions des tuiles KPI : son libellé à 10 px, et de la place pour la pastille (i). */
.kpi .kt .t { font-size: 10px; letter-spacing: .08em; }
.kpi .kt { padding-right: 14px; }
.vide-graphe { height: 238px; display: flex; flex-direction: column; justify-content: center; }
.vide-graphe[hidden] { display: none; }

/* ════════════════════════════════════════════════════════════════════════
   LOT 4 (03/09) : la COQUE. Rail réductible 260 → 68 px, pinceau « style du
   menu » en haut du menu avec son popover, sections fermées par défaut hors
   Vue d'ensemble et Mon espace, bulle à droite des icônes en rail.
   ════════════════════════════════════════════════════════════════════════ */
/* Le haut du menu : logo à gauche, pinceau + bouton réduire à droite (ses ThemePicker + CollapseToggle). */
.side { transition: width .3s cubic-bezier(.22, 1, .36, 1); will-change: width; }
.side-mark { position: relative; }
.side-outils { margin-left: auto; display: flex; align-items: center; gap: 2px; }
.btn-rond, .btn-rail {
  display: inline-grid; place-items: center; padding: 0; border: 0; background: none; cursor: pointer;
  color: #8495A0; font-size: 15px; border-radius: 8px;
  transition: background-color .2s ease, color .2s ease, transform .2s ease, border-color .2s ease;
}
.btn-rond { width: 32px; height: 32px; border: 1px solid rgba(255, 255, 255, .12); border-radius: 50%; }
.btn-rail { width: 30px; height: 30px; font-size: 18px; }
.btn-rond:hover, .btn-rail:hover { background: rgba(255, 255, 255, .07); color: #FFF; }
.btn-rond:hover { border-color: rgba(255, 255, 255, .3); }
.btn-rond[aria-expanded="true"] { background: rgba(255, 255, 255, .07); color: #FFF; border-color: rgba(255, 255, 255, .3); }
.btn-rond:active, .btn-rail:active { transform: scale(.9); }
.btn-rond:focus-visible, .btn-rail:focus-visible { outline: 2px solid rgba(56, 156, 154, .7); outline-offset: 2px; }
:root[data-menu="clair"] .btn-rond, :root[data-menu="clair"] .btn-rail { color: var(--nav-muted); }
:root[data-menu="clair"] .btn-rond { border-color: var(--nav-border); }
:root[data-menu="clair"] .btn-rond:hover, :root[data-menu="clair"] .btn-rail:hover, :root[data-menu="clair"] .btn-rond[aria-expanded="true"] { background: var(--nav-hover); color: var(--nav-foreground); }
/* Popover « Style du menu » (son ThemePicker) : à droite du pinceau, 2 options avec pastille et coche. */
.menu-style {
  position: absolute; left: calc(100% + 8px); top: 14px; z-index: 70; width: 208px; padding: 6px;
  border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--surface); color: var(--text);
  box-shadow: var(--shadow-raised); animation: tu-menu-in .18s var(--ease);
}
.menu-style[hidden] { display: none; }
.menu-style p { margin: 0; padding: 4px 8px 6px; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .12em; color: var(--text-2); }
.menu-style button {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px; border: 0; border-radius: var(--r-ctrl);
  background: none; color: var(--text); font: inherit; font-size: 13.5px; text-align: left; cursor: pointer;
  transition: background-color .15s ease;
}
.menu-style button:hover, .menu-style button[aria-checked="true"] { background: rgba(0, 42, 75, .06); }
.menu-style button[aria-checked="true"] { font-weight: 600; }
.menu-style button:focus-visible { outline: 2px solid var(--accent-turq); outline-offset: -2px; }
.menu-style .pastille { width: 20px; height: 20px; border-radius: 50%; flex: none; }
.menu-style .pastille.navy { background: #0B1F36; }
.menu-style .pastille.blanc { background: #FFF; border: 1px solid var(--border); }
.menu-style .bi-check { margin-left: auto; color: var(--accent-turq); font-size: 16px; visibility: hidden; }
.menu-style button[aria-checked="true"] .bi-check { visibility: visible; }
:root[data-theme="dark"] .menu-style button:hover, :root[data-theme="dark"] .menu-style button[aria-checked="true"] { background: rgba(255, 255, 255, .07); }
/* Le RAIL : 68 px, icônes seules, trait de section centré, badge en point, pinceau caché (sa demande L604). */
:root[data-side="reduit"] .side { width: 68px; }
:root[data-side="reduit"] .side-mark { flex-direction: column; gap: 8px; padding: 16px 0 10px; }
:root[data-side="reduit"] .side-mark b, :root[data-side="reduit"] .side nav a > span.lbl, :root[data-side="reduit"] .side-foot,
:root[data-side="reduit"] .side-user .qui, :root[data-side="reduit"] .side-user .bi-chevron-down, :root[data-side="reduit"] #btnStyleMenu, :root[data-side="reduit"] .menu-style { display: none; }
:root[data-side="reduit"] .side-outils { margin-left: 0; }
:root[data-side="reduit"] .side nav a { justify-content: center; padding: 10px 0; margin: 3px 10px; position: relative; }
:root[data-side="reduit"] .side nav a .bi { width: auto; font-size: 18px; }
:root[data-side="reduit"] .side nav a .mbadge {
  position: absolute; top: 2px; right: 6px; margin: 0; min-width: 18px; height: 18px; padding: 0 4px; font-size: 10px;
}
:root[data-side="reduit"] .side-sec { margin: 12px auto 6px; width: 20px; height: 2px; padding: 0; font-size: 0; color: transparent; }
:root[data-side="reduit"] .side-sec::before { width: 20px; }
:root[data-side="reduit"] .side-sec::after { display: none; }
:root[data-side="reduit"] .side-grp.plie { max-height: 500px; opacity: 1; }   /* en rail les icônes restent visibles, pas d'accordéon (comme chez lui) */
:root[data-side="reduit"] .side-user { justify-content: center; padding: 10px 0 12px; }
:root[data-side="reduit"] .side-user-wrap .side-user-menu { left: calc(100% + 8px); right: auto; bottom: 8px; width: 240px; }
/* Bulle à droite d'une icône du rail (son Tooltip side=right) : navy, 12 px, apparaît en 150 ms. */
.rail-bulle {
  position: fixed; z-index: 9999; padding: 6px 10px; border-radius: var(--r-md);
  background: #0B1F36; color: #FFF; font-size: 12px; font-weight: 500; white-space: nowrap;
  border: 1px solid rgba(255, 255, 255, .08); box-shadow: var(--shadow-raised);
  opacity: 0; transform: translateX(-4px); transition: opacity .2s var(--ease), transform .2s var(--ease); pointer-events: none;
}
.rail-bulle.on { opacity: 1; transform: translateX(0); }
/* En dessous de 1100 px le rail est imposé par l'écran : le bouton n'a plus de sens. */
@media (max-width: 1100px) { .btn-rail, #btnStyleMenu, .menu-style { display: none !important; } .side-outils { margin-left: 0; } }
@media (prefers-reduced-motion: reduce) { .side { transition: none; } .rail-bulle { transition: none; } .menu-style { animation: none; } }
/* La barre est sticky, donc un contexte d'empilement : sans z-index, ses popovers qui débordent
   à droite (style du menu, menu du compte en rail) passent SOUS le contenu principal. */
.side { z-index: 40; }

/* ════════════════════════════════════════════════════════════════════════
   LOT 5 (03/09) : le tableau « Qui est présent » du designer, filtres et liste
   ════════════════════════════════════════════════════════════════════════ */
.lv-filtres { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 10px 16px; border-top: 1px solid var(--border-2); border-bottom: 1px solid var(--border-2); }
.lv-rech { position: relative; flex: 1 1 200px; max-width: 256px; min-width: 0; }
.lv-rech .bi { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: var(--text-2); font-size: 14px; pointer-events: none; }
.lv-rech input { width: 100%; height: 36px; padding: 0 12px 0 32px; border: 1px solid var(--border); border-radius: var(--r-ctrl); background: var(--bg); color: var(--text); font: inherit; font-size: 13px; }
.lv-rech input:focus { outline: 2px solid var(--accent-turq); outline-offset: -1px; }
.lv-sel { width: 150px; height: 36px; padding: 0 28px 0 10px; font-size: 13px; }
.lv-sel[hidden] { display: none; }
@media (max-width: 640px) { .lv-rech { max-width: none; flex-basis: 100%; } .lv-sel { width: calc(50% - 4px); } }
.lv-qui { min-width: 0; display: flex; flex-direction: column; line-height: 1.25; }
.lv-qui b { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lv-equipe { font-size: 12px; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lv-anom { margin-top: 2px; font-size: 11px; color: var(--text-2); max-width: 224px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lv-plus { padding: 8px 16px; border-top: 1px solid var(--border-2); text-align: center; }
.lv-plus[hidden] { display: none; }
/* Texte pour les lecteurs d'écran seulement (son sr-only) : présent dans l'arbre, jamais à l'écran. */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }

/* Anneaux KPI (03/09, son KpiRing) : l'arc se trace avec une durée proportionnelle au ratio
   (--ring-dur, 700 à 1 500 ms) et sa courbe (.16,1,.3,1) ; le chiffre arrive en fondu + zoom .9 → 1. */
.ring .val { transition: stroke-dashoffset var(--ring-dur, .8s) cubic-bezier(.16, 1, .3, 1), opacity var(--ring-dur, .8s) cubic-bezier(.16, 1, .3, 1); }
.ring b { transition: transform .7s cubic-bezier(.16, 1, .3, 1), opacity .7s cubic-bezier(.16, 1, .3, 1); }
.ring b.attente { opacity: 0; transform: scale(.9); }
.ring b.ch-l { font-size: 12px; }
.ring b.ch-xl { font-size: 10px; }
@media (prefers-reduced-motion: reduce) { .ring .val, .ring b { transition: none; } .ring b.attente { opacity: 1; transform: none; } }

/* ════════════════════════════════════════════════════════════════════════
   PRÉSENCES (03/09, son PresenceDirectory) : 6 tuiles en 2 × 3, un panneau unique,
   groupes par statut à 4 cartes visibles, popover « +N autres », fiche rapide.
   ════════════════════════════════════════════════════════════════════════ */
.kpis-presences { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
@media (min-width: 420px) { .kpis-presences { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; } }
/* Squelette du répertoire */
.sq-rep { display: grid; gap: 12px; padding: 16px; grid-template-columns: 1fr; }
@media (min-width: 640px) { .sq-rep { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .sq-rep { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1536px) { .sq-rep { grid-template-columns: repeat(6, 1fr); } }
.sq-grp { border: 1px solid rgba(217, 226, 234, .6); border-radius: 16px; background: rgba(239, 243, 247, .25); padding: 10px; }
.sq-carte { border: 1px solid rgba(217, 226, 234, .6); border-radius: 12px; background: var(--surface); padding: 10px; margin-bottom: 8px; }
/* Les groupes par statut, DANS le panneau */
.prep { display: grid; gap: 12px; padding: 16px; grid-template-columns: 1fr; align-items: start; }
@media (min-width: 640px) { .prep { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .prep { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1536px) { .prep { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
.prep[hidden] { display: none; }
.pgrp { position: relative; display: flex; flex-direction: column; min-width: 0; border: 1px solid rgba(217, 226, 234, .6); border-radius: 16px; background: rgba(239, 243, 247, .25); padding: 10px; }
.pgrp[hidden] { display: none; }
.pgrp-t { display: flex; align-items: center; gap: 8px; margin: 0 2px 8px; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .14em; color: var(--text-2); }
.pgrp-t .bi { font-size: 14px; flex: none; }
.pgrp-t .lib { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pgrp-t .cnt { margin-left: auto; padding: 2px 6px; border-radius: 999px; background: var(--surface); color: var(--text); font-size: 10px; font-weight: 600; letter-spacing: 0; font-variant-numeric: tabular-nums; box-shadow: var(--shadow-float); }
.pgrp .pliste { padding: 0; display: flex; flex-direction: column; gap: 8px; }
.pgrp .pcarte, .ppop .pcarte { background: var(--surface); border: 1px solid rgba(217, 226, 234, .7); border-radius: 12px; padding: 10px; box-shadow: var(--shadow-float); width: 100%; text-align: left; font: inherit; color: inherit; cursor: pointer; display: block; }
.pgrp .pcarte .qui b, .ppop .pcarte .qui b { font-size: 12.5px; letter-spacing: -.01em; }
.pgrp .pcarte .qui span, .ppop .pcarte .qui span { font-size: 11px; }
.pgrp .pcarte .chrono, .ppop .pcarte .chrono { font-size: 11.5px; font-weight: 600; }
.pgrp .pcarte .psite, .ppop .pcarte .psite { font-size: 10.5px; margin: 6px 2px 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pgrp .pcarte .prouge, .ppop .pcarte .prouge { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pgrp .pcarte:active, .ppop .pcarte:active { transform: scale(.99); }
.pgrp .pcarte:focus-visible, .ppop .pcarte:focus-visible { outline: 2px solid var(--accent-turq); outline-offset: 2px; }
.pgrp .personne { padding: 16px 8px; text-align: center; font-size: 11px; color: var(--text-2); border: 1px dashed rgba(217, 226, 234, .6); border-radius: 12px; }
.pgrp .pplus { margin-top: 8px; width: 100%; padding: 6px 8px; border: 1px dashed rgba(217, 226, 234, .7); border-radius: 12px; background: none; font-size: 11.5px; font-weight: 600; color: var(--text-2); transition: color .2s ease, border-color .2s ease; }
.pgrp .pplus:hover, .pgrp .pplus[aria-expanded="true"] { color: var(--accent-turq); border-color: var(--accent-turq); background: none; }
/* Popover « +N autres » : sous le bouton, 288 px, en-tête, recherche au-delà de 6, liste défilante. */
.ppop { position: absolute; left: 0; top: 100%; margin-top: 6px; width: 288px; max-width: calc(100vw - 32px); z-index: 70; overflow: hidden; border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--surface); box-shadow: var(--shadow-raised); animation: tu-menu-in .18s var(--ease); }
.ppop[hidden] { display: none; }
.ppop-t { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border-bottom: 1px solid rgba(217, 226, 234, .7); background: rgba(239, 243, 247, .3); font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .14em; color: var(--text-2); }
.ppop-t .bi { font-size: 14px; }
.ppop-t .cnt { margin-left: auto; padding: 2px 6px; border-radius: 999px; background: var(--surface); color: var(--text); font-size: 10px; font-weight: 600; letter-spacing: 0; box-shadow: var(--shadow-float); }
.ppop-rech { position: relative; padding: 8px; border-bottom: 1px solid rgba(217, 226, 234, .7); }
.ppop-rech .bi { position: absolute; left: 16px; top: 50%; transform: translateY(-50%); font-size: 12px; color: var(--text-2); pointer-events: none; }
.ppop-rech input { width: 100%; height: 32px; padding: 0 8px 0 28px; border: 1px solid var(--border); border-radius: 8px; background: var(--bg); color: var(--text); font: inherit; font-size: 12px; }
.ppop-rech input:focus { outline: 2px solid var(--accent-turq); outline-offset: -1px; }
.ppop .pliste { max-height: 288px; overflow-y: auto; overscroll-behavior: contain; padding: 8px; display: flex; flex-direction: column; gap: 8px; scrollbar-width: thin; }
.ppop .vide { padding: 24px 16px; }
.ppop .vide > .bi { font-size: 20px; margin-bottom: 4px; }
/* Fiche rapide (son EmployeeDialog) */
.fr-tete { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.fr-tete .avatar { width: 36px; height: 36px; font-size: 12.5px; }
.fr-tete b { display: block; font-size: 15px; font-weight: 600; }
.fr-tete span { display: block; font-size: 12px; color: var(--text-2); }
.fr-cases { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 0; }
.fr-cases > div { border: 1px solid rgba(217, 226, 234, .7); border-radius: 12px; background: rgba(239, 243, 247, .3); padding: 10px; min-width: 0; }
.fr-cases dt { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .14em; color: var(--text-2); }
.fr-cases dd { margin: 2px 0 0; font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fr-resume { margin-top: 10px; border: 1px solid rgba(217, 226, 234, .7); border-radius: 12px; padding: 10px; }
.fr-resume .lbl { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .14em; color: var(--text-2); }
.fr-barre { display: flex; height: 8px; margin-top: 8px; border-radius: 999px; overflow: hidden; background: var(--border-2); }
.fr-barre span { display: block; height: 100%; transition: width .5s var(--ease); }
.fr-leg { list-style: none; margin: 8px 0 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.fr-leg li { display: flex; align-items: center; gap: 6px; font-size: 11.5px; min-width: 0; }
.fr-leg .pt { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.fr-leg .lib { color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fr-leg .val { margin-left: auto; font-weight: 600; font-variant-numeric: tabular-nums; }
.fr-resume .aucun { margin: 6px 0 0; font-size: 12px; color: var(--text-2); }
.fr-actions { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }

/* ════════════════════════════════════════════════════════════════════════
   ALERTES (03/09, son AlertsCenter + AuditLog) : centre en liste avec filtres, alerte
   traitée barrée + « Rouvrir », fiche d'alerte, absences et journal en listes.
   ════════════════════════════════════════════════════════════════════════ */
.grid-alertes { display: grid; gap: var(--sp-4); grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); align-items: start; }
@media (max-width: 1279px) { .grid-alertes { grid-template-columns: 1fr; } }
/* Ligne d'alerte (son AlertRow) */
.al-ligne { display: flex; align-items: center; gap: 10px; padding: 10px 16px; border-top: 1px solid rgba(217, 226, 234, .6); transition: background-color .3s cubic-bezier(.16, 1, .3, 1), opacity .3s cubic-bezier(.16, 1, .3, 1); }
.al-ligne:hover { background: rgba(239, 243, 247, .5); }
.al-ligne.traitee { opacity: .7; }
.al-pt { width: 8px; height: 8px; border-radius: 50%; flex: none; align-self: flex-start; margin-top: 5px; }
.al-corps { min-width: 0; flex: 1; border: 0; background: none; padding: 0; text-align: left; font: inherit; color: inherit; cursor: pointer; border-radius: 6px; }
.al-corps:focus-visible { outline: 2px solid var(--accent-turq); outline-offset: 2px; }
.al-l1 { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.al-titre { font-size: 13px; font-weight: 600; letter-spacing: -.01em; line-height: 1.25; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.traitee .al-titre { text-decoration: line-through; text-decoration-color: rgba(90, 107, 124, .5); }
.al-emp { font-size: 11px; color: var(--text-2); flex: none; }
.al-raison { margin-top: 2px; font-size: 11px; line-height: 1.5; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.al-droite { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; flex: none; }
.al-bas { display: flex; align-items: center; gap: 6px; }
.al-heure { font-size: 10.5px; color: rgba(90, 107, 124, .8); font-variant-numeric: tabular-nums; }
/* Badge de priorité (son PriorityBadge : couleur + fond à 16 %) */
.pbadge { display: inline-flex; align-items: center; gap: 4px; padding: 1px 6px; border-radius: 999px; font-size: 9.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .05em; flex: none; line-height: 1.5; }
.pbadge.h { color: var(--danger); background: rgba(185, 28, 28, .16); }
.pbadge.m { color: #B45309; background: rgba(219, 160, 0, .16); }
.pbadge.b { color: var(--accent-turq); background: rgba(56, 156, 154, .16); }
.pbadge.ok { color: var(--ok); background: rgba(4, 120, 87, .15); }
.pbadge .bi { font-size: 10px; }
/* Bouton d'action : plein (Traiter) ou contour (Rouvrir) */
.al-act { height: 24px; padding: 0 8px; border: 1px solid transparent; border-radius: 6px; background: var(--accent-turq); color: #FFF; font: inherit; font-size: 11px; font-weight: 500; cursor: pointer; display: inline-flex; align-items: center; gap: 4px; transition: transform .3s cubic-bezier(.16, 1, .3, 1), box-shadow .3s cubic-bezier(.16, 1, .3, 1), background-color .3s cubic-bezier(.16, 1, .3, 1); }
.al-act:hover { transform: translateY(-1px); box-shadow: var(--shadow-raised); background: #1B8C80; }
.al-act:active { transform: translateY(0); }
.al-act.contour { background: var(--surface); color: var(--text); border-color: var(--border); }
.al-act.contour:hover { background: var(--bg); }
.al-act:focus-visible { outline: 2px solid var(--accent-turq); outline-offset: 2px; }
.al-act .bi { font-size: 11px; }
/* Absences (son AbsencesPanel) */
.abs-ligne { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; padding: 10px 16px; border-top: 1px solid rgba(217, 226, 234, .6); transition: background-color .3s cubic-bezier(.16, 1, .3, 1); }
.abs-ligne:hover { background: rgba(239, 243, 247, .5); }
.abs-nom { min-width: 0; flex: 1; font-size: 12.5px; font-weight: 600; letter-spacing: -.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.abs-per { font-size: 11.5px; color: var(--text-2); }
.abs-motif { padding: 2px 8px; border-radius: 999px; background: rgba(239, 243, 247, .95); font-size: 11px; font-weight: 500; }
.abs-par { font-size: 10.5px; color: rgba(90, 107, 124, .8); }
/* Journal d'audit et notifications (son AuditLogPanel) : liste défilante de 420 px */
.aud-liste { max-height: 420px; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; }
.aud-ligne { display: flex; align-items: center; gap: 12px; padding: 10px 16px; border-top: 1px solid rgba(217, 226, 234, .6); transition: background-color .3s cubic-bezier(.16, 1, .3, 1); }
.aud-ligne:hover { background: rgba(239, 243, 247, .5); }
.aud-ligne.lue { opacity: .6; }
.aud-corps { min-width: 0; flex: 1; }
.aud-action { font-size: 12.5px; font-weight: 600; letter-spacing: -.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.aud-detail { font-size: 11px; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.aud-droite { flex: none; text-align: right; }
.aud-heure { font-size: 10.5px; color: var(--text-2); font-variant-numeric: tabular-nums; }
.aud-par { font-size: 10.5px; font-weight: 600; color: rgba(90, 107, 124, .8); }
/* Fiche d'alerte */
.fa-tete { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }

/* ════════════════════════════════════════════════════════════════════════
   CONFORMITÉ FINE (03/09, après audit adversarial de l'écran Alertes) : quatre
   composants PARTAGÉS s'écartaient de son design system sur tous les écrans.
   Chaque valeur vient de son code, citée en commentaire.
   ════════════════════════════════════════════════════════════════════════ */

/* 1. ÉTAT VIDE = son EmptyState (Panel.tsx l.110-137 + styles.css l.534-553).
   Le médaillon de 48 px à dégradé radial et son anneau pointillé animé existaient
   en keyframes chez nous depuis le 31/08 mais AUCUNE règle ne les appliquait :
   nos états vides étaient une icône nue. Posé sur `.vide > .bi` (enfant DIRECT : sinon
   l icone d un bouton place dans l etat vide devenait un medaillon), donc sans toucher
   au balisage des dizaines d'écrans qui l'utilisent déjà. */
.vide { animation: reveal-in .5s cubic-bezier(.16, 1, .3, 1) both; }
.vide > .bi {
  display: grid; place-items: center; position: relative;
  width: 48px; height: 48px; margin: 0 auto 10px;
  border-radius: 50%; font-size: 20px; color: var(--text-2);
  background: radial-gradient(circle at 50% 40%, rgba(56, 156, 154, .16), rgba(56, 156, 154, .04) 70%);
  box-shadow: inset 0 0 0 1px rgba(56, 156, 154, .14);
}
.vide > .bi::after {
  content: ""; position: absolute; inset: -4px; border-radius: 50%;
  border: 1px dashed rgba(56, 156, 154, .35);
  animation: empty-halo 3.6s ease-in-out infinite;
}
.vide b { font-size: 13px; letter-spacing: -.01em; }
.vide p { font-size: 11.5px; max-width: 26ch; line-height: 1.6; }
.vide-navy > .bi { color: #8495A0; background: radial-gradient(circle at 50% 40%, rgba(110, 201, 200, .16), rgba(110, 201, 200, .04) 70%); box-shadow: inset 0 0 0 1px rgba(110, 201, 200, .16); }
.vide-navy > .bi::after { border-color: rgba(110, 201, 200, .3); }
.vide-compact > .bi { width: 40px; height: 40px; font-size: 18px; margin-bottom: 8px; }
@media (prefers-reduced-motion: reduce) {
  .vide { animation: none; }
  .vide > .bi::after { animation: none; }
}

/* 2. PANNEAU : l'ombre monte au survol du bloc (son Panel.tsx l.33 :
   shadow-float au repos, hover:shadow-raised, transition-shadow 300 ms). */
.card { transition: box-shadow .3s cubic-bezier(.16, 1, .3, 1), border-color .2s ease; }
.card:hover { box-shadow: var(--shadow-raised); }
@media (prefers-reduced-motion: reduce) { .card { transition: none; } }

/* 3. TUILE KPI : ses valeurs exactes (styles.css l.335-353, .kpi-card) :
   transitions 450 ms sur transform / ombre / bordure, survol -3 px avec bordure
   appuyée, et RETOMBÉE à l'appui (-1 px en 120 ms). Nous étions à -1 px / 300 ms
   sans changement de bordure et sans retombée. */
.kpi, a.kpi { transition: transform .45s cubic-bezier(.16, 1, .3, 1), box-shadow .45s cubic-bezier(.16, 1, .3, 1), border-color .45s cubic-bezier(.16, 1, .3, 1); }
a.kpi:hover { transform: translateY(-3px); border-color: var(--border-strong); box-shadow: var(--shadow-raised); }
a.kpi:active { transform: translateY(-1px); transition-duration: .12s; }
@media (prefers-reduced-motion: reduce) { .kpi, a.kpi { transition: none; } a.kpi:hover, a.kpi:active { transform: none; } }

/* 4. ALERTES, corrections de valeurs relevées par l'audit :
   - rayon des boutons et du corps cliquable : son rounded-md vaut 12,6 px dans
     son thème (styles.css l.18 + l.90), notre jeton --r-ctrl valait déjà 12,6 px
     et n'avait pas été utilisé ;
   - survol de « Traiter » : son hover:bg-brand/90 ÉCLAIRCIT le bouton sur fond
     clair (#1F9D8F à 90 % sur blanc = #35A79A), nous l'assombrissions ;
   - courbe de survol des lignes du journal et des absences : Tailwind par défaut
     (.4,0,.2,1), sa courbe signature n'est posée que sur la ligne d'alerte ;
   - liste défilante du journal : scrollbar-color (AuditLog.tsx l.22). */
.al-act, .al-corps { border-radius: var(--r-ctrl); }
.al-act:hover { background: #35A79A; }
.al-act.contour:hover { background: var(--bg); }
.abs-ligne, .aud-ligne { transition: background-color .3s cubic-bezier(.4, 0, .2, 1); }
.aud-liste { scrollbar-color: var(--border) transparent; }
/* Cases de la fiche : son rounded-xl = 16,6 px (styles.css l.17 + l.90). */
.fr-cases > div { border-radius: var(--r-card); }
/* Pied de modale aligné à gauche, comme son DialogFooter sm:justify-start. */
.m-foot.pied-gauche { justify-content: flex-start; }
.m-foot.pied-gauche [data-m="valider"] { order: 1; }
.m-foot.pied-gauche .pied-actions { order: 2; }
.m-foot.pied-gauche [data-m="annuler"] { order: 3; margin-left: auto; }
.pied-actions { display: inline-flex; gap: 8px; align-items: center; }

/* ==========================================================================
   PLANNING (04/09/2026) : sa WeekGrid, sa fiche de creneau, ses listes alignees.
   Charte : navy en texte, turquoise en bordure / fond (jamais en texte sur blanc).
   ========================================================================== */
.pl-nav { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.pl-outils { gap: 8px; }
.pl-modele { display: flex; align-items: center; gap: 8px; min-width: 0; }
.pl-lib { display: none; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .08em; color: var(--text-2); white-space: nowrap; }
@media (min-width: 640px) { .pl-lib { display: inline; } }
.pl-modele .lv-sel { width: 190px; }
.pl-reset {
  display: inline-flex; align-items: center; gap: 4px; height: 32px; padding: 0 12px; border-radius: 999px;
  border: 1px solid rgba(56, 156, 154, .35); background: rgba(56, 156, 154, .1); color: var(--primary);
  font: inherit; font-size: 11.5px; font-weight: 600; cursor: pointer; transition: background-color .3s var(--ease);
}
.pl-reset:hover { background: rgba(56, 156, 154, .18); }
.pl-reset[hidden] { display: none; }
.pl-densite { margin-left: auto; display: inline-flex; gap: 2px; padding: 2px; border-radius: 999px; border: 1px solid var(--border-2); background: rgba(239, 243, 247, .5); }
.pl-dens {
  display: grid; place-items: center; width: 28px; height: 28px; border-radius: 999px; border: 0; background: transparent;
  color: var(--text-2); font-size: 14px; cursor: pointer; transition: all .3s var(--ease);
}
.pl-dens:hover { color: var(--text); }
.pl-dens.on { background: var(--primary); color: #FFF; box-shadow: var(--shadow-card); }
.pl-dens:active { transform: scale(.96); }
/* La fenetre de grille : 52 vh, en-tete, colonne Salarie, colonne Total et pied FIGES. */
.pl-wrap { overflow: auto; max-height: 52vh; overscroll-behavior: contain; scrollbar-width: thin; scrollbar-color: var(--border) transparent; }
.pl-wrap[hidden] { display: none; }
.tt-plan { border-collapse: separate; border-spacing: 0; min-width: 720px; }
.tt-plan th { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; z-index: 4; }
.tt-plan th .muted { text-transform: none; letter-spacing: 0; font-size: 10px; }
.tt-plan th:first-child, .tt-plan td:first-child { position: sticky; left: 0; z-index: 3; background: var(--surface); box-shadow: 1px 0 0 0 var(--border); min-width: 132px; }
.tt-plan th:last-child, .tt-plan td:last-child { position: sticky; right: 0; z-index: 3; background: var(--surface); box-shadow: -1px 0 0 0 var(--border); min-width: 76px; text-align: right; }
.tt-plan th:first-child, .tt-plan th:last-child { z-index: 6; }
.tt-plan tbody td { border-bottom: 1px solid var(--border-2); vertical-align: middle; min-width: 108px; }
.tt-plan tbody tr:hover td { background: rgba(239, 243, 247, .5); }
.tt-plan tfoot td { position: sticky; bottom: 0; z-index: 4; background: var(--surface); border-top: 1px solid var(--border); font-size: 11.5px; font-weight: 600; font-variant-numeric: tabular-nums; }
.tt-plan tfoot td:first-child, .tt-plan tfoot td:last-child { z-index: 6; }
.tt-plan tfoot .pl-n { font-size: 10.5px; text-transform: uppercase; letter-spacing: .08em; }
/* Densite : sa vue dense par defaut (padding serre, la pause disparait), sa vue confortable. */
.tt-plan th, .tt-plan td { padding: 8px 10px; }
.tt-plan.dense th, .tt-plan.dense td { padding: 4px 8px; }
.tt-plan.dense .pl-pause, .tt-plan.dense .pl-poste { display: none; }   /* sa vue dense : l horaire seul, le reste dans l infobulle */
.pl-nom { display: block; font-size: 12.5px; letter-spacing: -.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pl-sous { display: block; font-size: 10.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Une case pleine : tuile-bouton qui reagit au survol et s enfonce a l appui (sa ShiftCell). */
.pl-cell {
  display: block; width: 100%; text-align: left; border: 1px solid rgba(56, 156, 154, .2); border-left: 3px solid var(--poste, rgba(56, 156, 154, .2)); background: rgba(56, 156, 154, .07);
  border-radius: 8px; padding: 4px 8px; font: inherit; color: inherit; cursor: pointer; line-height: 1.3;
  transition: border-color .3s var(--ease), background-color .3s var(--ease), transform .3s var(--ease);
}
.pl-cell:hover { border-color: rgba(56, 156, 154, .45); border-left-color: var(--poste, rgba(56, 156, 154, .45)); background: rgba(56, 156, 154, .12); }
/* Un creneau pose sur un conge ou une indisponibilite declaree : signale, jamais bloque, et il reagit au survol. */
.pl-cell.pl-conge { --poste: var(--danger); background: var(--danger-bg); }
.pl-cell.pl-conge:hover { background: rgba(185, 28, 28, .14); }
.pl-cell.pl-indispo { --poste: var(--warn); background: var(--warn-bg); }
.pl-cell.pl-indispo:hover { background: rgba(219, 160, 0, .18); }
.tt-plan tbody td { transition: background-color .3s var(--ease); }
.pl-cell:active { transform: scale(.98); }
.pl-cell .pl-h { display: block; font-size: 11.5px; font-variant-numeric: tabular-nums; letter-spacing: -.01em; white-space: nowrap; }
.pl-cell .pl-poste, .pl-cell .pl-pause { display: block; font-size: 10.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pl-cell .pl-pause { font-weight: 400; }
.pl-cell .pl-sw { display: inline-block; margin-top: 2px; font-size: 10px; }
.tt-plan:not(.dense) .pl-cell { padding: 6px 8px; }
/* Une case vide : bouton pointille « Ajouter un creneau <modele> ». */
.pl-vide {
  display: flex; align-items: center; justify-content: center; height: 28px; width: 100%; border: 1px dashed var(--border); border-radius: 8px;
  background: transparent; color: rgba(90, 107, 124, .5); font: inherit; font-size: 13px; line-height: 1; cursor: pointer;
  transition: border-color .3s var(--ease), color .3s var(--ease), background-color .3s var(--ease);
}
.pl-vide:hover { border-color: rgba(56, 156, 154, .6); color: var(--primary); background: rgba(56, 156, 154, .06); }
.pl-vide.pl-conge, .pl-vide.pl-indispo { font-size: 11px; }
.pl-vide.pl-indispo { background: var(--warn-bg); border-style: solid; border-color: transparent; }
.pl-cell:focus-visible, .pl-vide:focus-visible, .pl-dens:focus-visible, .pl-reset:focus-visible, .pf-act:focus-visible { outline: 2px solid var(--accent-turq); outline-offset: 2px; }
/* Squelette en damier (gabarit « grille »). */
.sq-corps-damier { display: flex; flex-direction: column; gap: 8px; padding: 12px 16px 16px; }
.sq-damier { display: grid; grid-template-columns: 168px repeat(7, minmax(0, 1fr)) 76px; gap: 8px; }
@media (max-width: 860px) { .sq-damier { grid-template-columns: 96px repeat(7, minmax(0, 1fr)) 48px; gap: 4px; } }
/* Les deux listes : 1 fr / 1,3 fr (sa disposition), bandeau « Aligne sur la grille », pilule de compte. */
.grid-planning { display: grid; grid-template-columns: 1fr; gap: var(--sp-4); }
@media (min-width: 1280px) { .grid-planning { grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr); } }
.grid-planning > * { min-width: 0; }
.pl-chip { display: flex; align-items: center; gap: 6px; padding: 6px 16px; background: rgba(56, 156, 154, .08); border-bottom: 1px solid var(--border-2); font-size: 10.5px; font-weight: 600; color: var(--primary); }
.pl-chip[hidden] { display: none; }
.pl-chip span { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pl-chip b { color: var(--text-2); font-variant-numeric: tabular-nums; }
.pl-pilule { display: inline-flex; align-items: center; border-radius: 999px; background: rgba(239, 243, 247, .9); padding: 4px 10px; font-size: 10.5px; font-weight: 600; color: var(--text-2); white-space: nowrap; }
.pl-pilule[hidden] { display: none; }
.al-corps.statique { cursor: default; }
.pl-sw-actions { display: inline-flex; gap: 4px; flex: none; }
#swListe { transition: min-height .2s var(--ease); }
#swPied[hidden] { display: none; }
#swPied .pg b { font-size: 11px; font-variant-numeric: tabular-nums; padding: 0 4px; }
#secEcarts .tbar { display: none; }   /* le compteur du socle : la pilule de l en-tete le porte deja */
/* Sa fiche de creneau (ShiftDialog). */
.pf-modal { width: min(94vw, 520px); }
.pf-modal .m-foot { flex-wrap: wrap; gap: 8px; }
.pf-modal .m-foot .btn { white-space: nowrap; }
.pf-modal .m-head.pf-head { display: flex; align-items: center; gap: 12px; }
.pf-head .pf-id h3 { margin: 0; font-size: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pf-head .pf-id p { margin: 2px 0 0; font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pf-head .pf-av { order: -1; }
.pf-av { width: 40px; height: 40px; border-radius: 50%; flex: none; display: inline-flex; align-items: center; justify-content: center; font-size: 13px; font-weight: 700; color: #FFF; background: var(--primary); overflow: hidden; }   /* initiales en blanc : le fond vient de CT.avatarCouleur (palette foncee) */
.pf-av .av-img, .pf-av svg { width: 100%; height: 100%; object-fit: cover; }
.pf-id { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.pf-id b { font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pf-id .muted { font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pf-statut { display: inline-flex; align-items: center; gap: 6px; flex: none; border: 1px solid var(--border); background: rgba(239, 243, 247, .6); border-radius: 999px; padding: 4px 10px; font-size: 11px; font-weight: 600; }
.pf-statut i { display: inline-block; width: 6px; height: 6px; border-radius: 50%; }
.pf-bandeau { display: flex; align-items: center; gap: 8px; border: 1px solid rgba(56, 156, 154, .3); background: rgba(56, 156, 154, .08); border-radius: 12px; padding: 8px 12px; margin-bottom: 10px; font-size: 13px; font-variant-numeric: tabular-nums; }
.pf-bandeau .bi { color: var(--primary); }
.pf-actions { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin-top: 10px; }
.pf-act {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 36px; border-radius: 10px; border: 1px solid var(--border);
  background: var(--surface); font: inherit; font-size: 12.5px; font-weight: 600; color: var(--text); cursor: pointer; transition: all .3s var(--ease);
}
.pf-act:hover { border-color: rgba(56, 156, 154, .5); background: rgba(239, 243, 247, .6); }
.pf-act:active { transform: scale(.98); }
.pf-act[aria-pressed="true"] { background: var(--primary); border-color: var(--primary); color: #FFF; box-shadow: var(--shadow-card); }
.pf-sec { margin-top: 10px; border: 1px solid var(--border); border-radius: 12px; padding: 10px; }
.pf-sec[hidden] { display: none; }
.pf-lib { margin: 0 0 8px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .14em; color: var(--text-2); }
.pf-form .fl { font-size: 11.5px; }
.pf-ecarts { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 6px 12px; font-size: 11.5px; }
.pf-ecarts li { display: flex; align-items: center; gap: 6px; }
.pf-ecarts li span { color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pf-ecarts li b { margin-left: auto; font-variant-numeric: tabular-nums; }
.pf-retirer { color: var(--danger); }
.pf-retirer:hover { background: rgba(185, 28, 28, .08); color: var(--danger); }
.menu-pop .menu-titre { display: flex; flex-direction: column; gap: 2px; padding: 8px 12px 6px; max-width: 260px; }
.menu-pop .menu-titre b { font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .08em; color: var(--text-2); }
.menu-pop .menu-titre span { font-size: 11px; line-height: 1.4; color: var(--text-2); }
@media (max-width: 640px) {
  .pl-densite { margin-left: 0; }
  .pf-actions { gap: 6px; }
  .pf-act { font-size: 11.5px; padding: 0 4px; }
}
.tu-modal::backdrop { backdrop-filter: blur(3px); }

/* ==========================================================================
   MON PLANNING (05/09/2026) : son MyWeek (7 cartes jour), ses panneaux Creneaux disponibles /
   Mes indisponibilites, sa tuile « Prochain creneau » sans anneau (msg 180-181).
   Charte : navy en texte, turquoise en bordure / fond (jamais en texte sur blanc).
   ========================================================================== */
/* Tuile sans anneau : medaillon d icone + valeur en grand, le reste comme les autres tuiles. */
.kpi.bare .kpi-bare { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; flex-shrink: 0; min-width: 56px; }
.kpi.bare .kpi-bare > i { display: grid; place-items: center; width: 40px; height: 40px; border-radius: 12px; background: rgba(56, 156, 154, .14); color: var(--primary); font-size: 18px; transform: scale(.9); opacity: 0; transition: transform .7s var(--ease), opacity .7s var(--ease); }
.kpi.bare.revele .kpi-bare > i, .kpi.bare .kpi-bare > i.joue { transform: none; opacity: 1; }
.kpi.bare .kpi-bare b { font-family: var(--font-marque); font-size: 17px; font-weight: 700; letter-spacing: -.02em; line-height: 1.1; color: var(--text); font-variant-numeric: tabular-nums; white-space: nowrap; }
@media (max-width: 640px) { .kpi.bare .kpi-bare { align-items: center; } }
/* Sa grille de 7 cartes : 2 colonnes, 4 des 640 px, 7 des 1280 px. */
.mp-jours, .sq-jours { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; padding: 8px 16px 12px; }
.sq-jours { padding-bottom: 16px; }
@media (min-width: 640px) { .mp-jours, .sq-jours { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 1280px) { .mp-jours, .sq-jours { grid-template-columns: repeat(7, minmax(0, 1fr)); } }
.mp-jours[hidden] { display: none; }
.mp-filtre { width: 168px; }
.mp-jour {
  display: flex; flex-direction: column; min-height: 124px; padding: 12px; min-width: 0;
  border: 1px solid rgba(217, 226, 234, .6); border-radius: 16px; background: var(--surface);
  transition: transform .5s var(--ease), box-shadow .5s var(--ease), border-color .5s var(--ease), background-color .5s var(--ease), opacity .5s var(--ease);
}
.mp-jour:hover { transform: translateY(-2px); box-shadow: var(--shadow-card); }
.mp-jour.auj { border-color: rgba(56, 156, 154, .45); background: rgba(56, 156, 154, .07); }
.mp-jour.passe { opacity: .7; }
.mp-jour.indispo { border-color: rgba(90, 107, 124, .5); background: rgba(90, 107, 124, .06); }
.mp-jour.restauree { border-color: rgba(4, 120, 87, .55); background: rgba(4, 120, 87, .08); }
.mp-jours.dense .mp-jour { min-height: 104px; padding: 10px; }
.mp-jours.dense .mp-pause { display: none; }
.mp-jour header { display: flex; align-items: baseline; justify-content: space-between; gap: 4px; }
.mp-jl { font-size: 12px; font-weight: 600; letter-spacing: -.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mp-auj { flex: none; border-radius: 999px; background: var(--primary); color: #FFF; padding: 2px 6px; font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; }
.mp-jd { font-size: 10.5px; color: var(--text-2); }
.mp-h { margin: 10px 0 0; font-size: 14px; font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
.mp-pause { margin: 2px 0 0; display: flex; align-items: center; gap: 4px; font-size: 10.5px; color: var(--text-2); }
.mp-bas { margin-top: auto; display: flex; align-items: center; justify-content: space-between; gap: 4px; padding-top: 8px; }
.mp-duree { font-size: 11.5px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--away, #5A6B7C); }
.mp-passe { font-size: 10.5px; color: var(--text-2); }
.mp-repos { margin-top: auto; display: flex; flex-direction: column; align-items: flex-start; gap: 4px; padding-top: 12px; color: var(--text-2); }
.mp-repos .bi { font-size: 16px; }
.mp-repos span { font-size: 11.5px; font-weight: 500; }
/* Ses pastilles-boutons (indisponible, proposer) : zone de toucher elargie a 44 px sans changer le visuel. */
.mp-badge, .mp-prop {
  position: relative; display: inline-flex; align-items: center; gap: 4px; width: fit-content; max-width: 100%;
  border-radius: 999px; padding: 2px 8px; font: inherit; font-size: 10.5px; font-weight: 600; line-height: 1.5; cursor: pointer;
  border: 1px solid transparent; background: transparent; white-space: nowrap; transition: all .3s var(--ease);
}
.mp-badge::after, .mp-prop::after { content: ""; position: absolute; inset: -12px -6px; }
.mp-badge { margin-top: 6px; font-size: 10px; }
.mp-badge.mp-indispo { background: rgba(90, 107, 124, .12); color: var(--away, #5A6B7C); }
.mp-badge.mp-indispo:hover { background: rgba(90, 107, 124, .2); text-decoration: underline; }
.mp-badge.mp-rest { background: rgba(4, 120, 87, .15); color: var(--ok); cursor: default; animation: mp-pop .4s var(--ease); }
.mp-prop { border-color: var(--border); color: var(--text-2); }
.mp-prop:hover { border-color: rgba(56, 156, 154, .5); color: var(--primary); }
.mp-prop.on { background: var(--primary); border-color: var(--primary); color: #FFF; }
.mp-badge:active, .mp-prop:active, .mp-btn:active, .mp-ico:active { transform: scale(.97); }
.mp-badge:focus-visible, .mp-prop:focus-visible, .mp-btn:focus-visible, .mp-ico:focus-visible { outline: 2px solid var(--accent-turq); outline-offset: 2px; }
.mp-pied { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 16px; margin: 0 16px; padding: 10px 0 14px; border-top: 1px solid rgba(217, 226, 234, .6); font-size: 11.5px; color: var(--text-2); }
.mp-pied b { color: var(--text); font-variant-numeric: tabular-nums; }
.mp-pied .mp-pied-d { margin-left: auto; }
/* Ses deux panneaux : le premier plus large (1.3 fr / 1 fr). */
.mp-grid { display: grid; grid-template-columns: 1fr; gap: var(--sp-4); }
@media (min-width: 1280px) { .mp-grid { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); } }
.mp-grid > * { min-width: 0; }
.mp-liste { display: flex; flex-direction: column; gap: 8px; padding: 8px 16px 16px; }
.mp-item {
  display: flex; align-items: center; gap: 12px; padding: 10px 12px; min-width: 0;
  border: 1px solid rgba(217, 226, 234, .6); border-radius: 16px;
  transition: background-color .3s var(--ease), border-color .5s var(--ease);
}
.mp-item:hover { background: rgba(239, 243, 247, .4); }
.mp-item.mienne { border-color: rgba(56, 156, 154, .4); background: rgba(56, 156, 154, .06); }
.mp-item.restauree { border-color: rgba(4, 120, 87, .55); background: rgba(4, 120, 87, .1); }
.mp-med { display: grid; place-items: center; width: 36px; height: 36px; border-radius: 999px; flex: none; background: rgba(56, 156, 154, .12); color: var(--primary); font-size: 15px; }
.mp-item.mienne .mp-med { background: var(--primary); color: #FFF; }
.mp-med.gris { background: rgba(239, 243, 247, .9); color: var(--text-2); }
.mp-txt { min-width: 0; flex: 1; }
.mp-txt b { display: block; font-size: 12.5px; letter-spacing: -.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
.mp-txt span { display: block; font-size: 11px; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mp-btn {
  display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 12px; flex: none; border-radius: 999px;
  border: 1px solid var(--border); background: transparent; color: var(--text); font: inherit; font-size: 11.5px; font-weight: 600;
  cursor: pointer; white-space: nowrap; transition: all .3s var(--ease);
}
.mp-btn:hover { border-color: rgba(56, 156, 154, .5); color: var(--primary); }
.mp-btn.on { background: var(--primary); border-color: var(--primary); color: #FFF; }
.mp-btn.turq { border-color: rgba(56, 156, 154, .5); background: rgba(56, 156, 154, .1); color: var(--primary); }
.mp-btn.turq:hover { background: rgba(56, 156, 154, .2); }
.mp-etat { flex: none; border-radius: 999px; padding: 2px 8px; font-size: 10.5px; font-weight: 600; white-space: nowrap; }
.mp-etat.vue { color: var(--ok); background: rgba(4, 120, 87, .1); }
.mp-etat.att { color: #B45309; background: rgba(219, 160, 0, .12); }
.mp-etat.rest { color: var(--ok); background: rgba(4, 120, 87, .15); animation: mp-pop .4s var(--ease); }
.mp-acts { display: flex; gap: 2px; flex: none; opacity: .7; transition: opacity .3s var(--ease); }
.mp-item:hover .mp-acts, .mp-item:focus-within .mp-acts { opacity: 1; }
.mp-ico { display: grid; place-items: center; width: 28px; height: 28px; border-radius: 999px; border: 0; background: transparent; color: var(--text-2); font-size: 13px; cursor: pointer; position: relative; transition: all .3s var(--ease); }
.mp-ico::after { content: ""; position: absolute; inset: -8px; }
.mp-ico:hover { background: rgba(56, 156, 154, .12); color: var(--primary); }
.mp-ico.danger:hover { background: rgba(185, 28, 28, .1); color: var(--danger); }
.mp-annuler { display: flex; align-items: center; gap: 12px; margin: 0 16px 16px; padding: 10px 12px; border-radius: 16px; border: 1px solid rgba(217, 226, 234, .6); background: rgba(239, 243, 247, .5); }
.mp-annuler[hidden] { display: none; }
.mp-annuler .mp-med { width: 32px; height: 32px; font-size: 14px; }
.mp-annuler p { margin: 0; min-width: 0; flex: 1; font-size: 12px; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mp-annuler p span { display: block; font-size: 11px; overflow: hidden; text-overflow: ellipsis; }
/* Son dialogue « Proposer mon creneau » : 3 champs sur une ligne, resume de la duree cedee. */
.mp-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.mp-3 .fl { margin-top: 0; }
.mp-resume { display: flex; align-items: center; gap: 10px; margin-top: 12px; padding: 8px 12px; border-radius: 16px; border: 1px solid rgba(217, 226, 234, .6); background: rgba(239, 243, 247, .5); font-size: 11.5px; color: var(--text-2); }
.mp-resume .bi { color: var(--primary); flex: none; }
.mp-resume b { color: var(--text); font-variant-numeric: tabular-nums; }
.mp-resume .mp-res-p { margin-left: auto; display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
.mp-compte { display: block; text-align: right; font-size: 10.5px; color: var(--text-2); margin-top: 4px; }
.mp-modal { width: min(94vw, 460px); }
@keyframes mp-pop { 0% { transform: scale(.8); opacity: 0; } 60% { transform: scale(1.06); } 100% { transform: none; opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .mp-badge.mp-rest, .mp-etat.rest { animation: none; } .mp-jour:hover { transform: none; } }

/* ==========================================================================
   CROIX DE FERMETURE (09/09/2026, message 194 du designer, GO CEO) : pastille ronde
   discrete en haut a droite de CHAQUE fenetre, la croix pivote d un quart de tour au survol.
   Le bouton « Fermer » du pied reste : la croix s ajoute, elle ne remplace rien.
   ========================================================================== */
.tu-croix {
  position: absolute; top: 14px; right: 14px; z-index: 2;
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: 999px; cursor: pointer; padding: 0;
  color: var(--text-2); background: rgba(239, 243, 247, .55);
  border: 1px solid rgba(217, 226, 234, .7);
  transition: background-color .24s var(--ease), color .24s var(--ease),
              transform .24s var(--ease), box-shadow .24s var(--ease);
}
.tu-croix .bi { font-size: 13px; line-height: 1; transition: transform .3s var(--ease); }
.tu-croix:hover { color: var(--text); background: rgba(239, 243, 247, .95); transform: scale(1.06); box-shadow: 0 6px 18px -8px rgba(0, 42, 75, .45); }
.tu-croix:hover .bi { transform: rotate(90deg); }
.tu-croix:active { transform: scale(.94); }
.tu-croix:focus-visible { outline: 2px solid var(--accent-turq); outline-offset: 2px; }
/* Le titre ne passe jamais SOUS la croix. */
.tu-modal .m-head { padding-right: 56px; }
@media (prefers-reduced-motion: reduce) {
  .tu-croix, .tu-croix .bi { transition: none; }
  .tu-croix:hover { transform: none; }
  .tu-croix:hover .bi { transform: none; }
}

/* ---- Fenêtre haute à corps défilant (11/09/2026, kit partagé : fiche collaborateur, règle d heures sup,
   exports, récapitulatifs). Le pied et la tête restent visibles, seul le corps défile. ---- */
dialog.tu-modal.xf-dlg { width: min(1100px, 96vw); max-width: min(1100px, 96vw); max-height: calc(100vh - 48px); display: flex; flex-direction: column; }
.xf-dlg .m-head, .xf-dlg .m-foot { flex: 0 0 auto; }
.xf-dlg .m-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; }

/* ---------- Parametres (11/09/2026) : badge « modifications non enregistrees » dans la barre,
   aides et erreurs sous les champs, repris du designer (SettingsCenter.tsx, Topbar.tsx). ---------- */
.top-nonenr { display: inline-flex; align-items: center; gap: 8px; height: 36px; padding: 0 12px; border-radius: 999px; border: 1px solid var(--warn-bd); background: var(--warn-bg); color: #92400E; font-size: 12px; font-weight: 500; text-decoration: none; white-space: nowrap; box-shadow: var(--shadow-card); transition: border-color .15s, box-shadow .15s, transform .1s; }
.top-nonenr:hover { border-color: #F59E0B; box-shadow: var(--shadow-pop); color: #92400E; }
.top-nonenr:active { transform: scale(.98); }
.top-nonenr[hidden] { display: none; }
.top-nonenr .pt { position: relative; display: inline-flex; width: 8px; height: 8px; }
.top-nonenr .pt::before { content: ""; position: absolute; inset: 0; border-radius: 50%; background: #F59E0B; opacity: .7; animation: nonenr-ping 1.2s cubic-bezier(0, 0, .2, 1) infinite; }
.top-nonenr .pt::after { content: ""; position: relative; display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: #F59E0B; }
@keyframes nonenr-ping { 75%, 100% { transform: scale(2.2); opacity: 0; } }
@media (max-width: 767px) { .top-nonenr .lbl { display: none; } .top-nonenr { padding: 0 10px; } }
.f-aide { font-size: 11.5px; line-height: 1.45; color: var(--text-2); margin: 5px 0 0; }
.f-aide[hidden] { display: none; }
.ferr-champ::before { content: "\f333"; font-family: "bootstrap-icons"; font-size: 12px; margin-right: 5px; vertical-align: -1px; }
.f-obl { color: var(--danger); }
.f-resume { display: flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 500; color: var(--danger); margin-top: 8px; }
.f-resume[hidden] { display: none; }
.f-role-aide { background: var(--bg); border-radius: 12px; padding: 8px 12px; font-size: 11.5px; line-height: 1.5; color: var(--text-2); margin-top: 10px; }
.bandeau-lecture { display: flex; align-items: flex-start; gap: 10px; border: 1px solid var(--border); background: var(--bg); border-radius: var(--r-card); padding: 12px 14px; font-size: 12.5px; line-height: 1.55; color: var(--text-2); margin-bottom: var(--sp-3); }
.bandeau-lecture .bi { margin-top: 2px; flex-shrink: 0; }
.bandeau-lecture strong { color: var(--text); font-weight: 600; }

/* ---------- Groupe « Aide » (Que faire si…, Support) : retire du rail ferme (son message 375),
   present menu ouvert. ---------- */
:root[data-side="reduit"] .side-sec[data-grp="sg-aide"], :root[data-side="reduit"] #sg-aide { display: none; }

/* ════════════════════════════════════════════════════════════════════════
   TIROIR DE NAVIGATION MOBILE (designer, ses messages 377 a 388, pose le 11/09/2026)
   Sous 860 px la barre laterale devient un tiroir hors ecran qui GLISSE (300 ms, sa courbe)
   derriere un hamburger ; voile navy 40 % floute en fondu ; X dans l en-tete du menu ;
   swipe vers la gauche pour fermer (app.js) ; reduced motion coupe tout (regle globale).
   La barre du bas (5 entrees par role) reste : le tiroir donne la navigation complete.
   ════════════════════════════════════════════════════════════════════════ */
.btn-burger, .top-mark, .btn-fermer-menu, .voile { display: none; }
@media (max-width: 860px) {
  /* En-tete : hamburger, marque, titre (tronque), puis recherche et cloche. Avant, la pilule de
     recherche et la cloche heritaient de l ordre 0 et passaient AVANT le titre (chevauchement). */
  .btn-burger { display: inline-grid; place-items: center; width: 44px; height: 44px; border: 0; background: none; border-radius: 10px; color: var(--text); font-size: 24px; cursor: pointer; order: 0; flex-shrink: 0; margin-left: -10px; transition: background .15s, transform .1s; }
  .btn-burger:hover { background: var(--bg); }
  .btn-burger:active { transform: scale(.9); }
  .btn-burger:focus-visible { outline: 2px solid var(--accent-turq); outline-offset: 2px; }
  .top-mark { display: inline-flex; order: 0; flex-shrink: 0; margin-right: 2px; }
  .top-mark .mq { width: 28px; height: 28px; display: block; }
  .top-mark .mq svg { width: 100%; height: 100%; display: block; }
  .top-title { order: 1; flex: 1 1 0; min-width: 0; }
  .top-title h1 { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .top-rech-wrap, .top-tools, .top-user { order: 2; }
  .top-rech { min-width: 0; width: 40px; }   /* la pilule de recherche gardait son min-width de 130 px : 10 px de debordement */
  .top-actions > .btn { order: 3; flex: 1 1 100%; }   /* l action principale de la page sur sa propre ligne, pleine largeur (regle du 31/08 enfin tenue) */
  /* Le tiroir : toujours complet sur telephone (libelles, sections), quel que soit le rail du bureau. */
  .side { display: flex; position: fixed; top: 0; left: 0; bottom: 0; height: 100dvh; width: 260px; z-index: 70; transform: translate3d(-100%, 0, 0); transition: transform .3s var(--ease-doux); will-change: transform; overflow: hidden; }
  :root[data-side="reduit"] .side { width: 260px; }
  .side-mark b, .side nav a > span.lbl { display: inline; }
  .side-sec { display: block; }
  .side-foot { display: block; }
  .side nav a { justify-content: flex-start; padding: 9px 13px; }
  .side nav a .bi { width: 20px; }
  :root[data-menu-mobile="ouvert"] .side { transform: none; box-shadow: 0 24px 60px rgba(0, 0, 0, .35); }
  .side.glisse, .voile.glisse { transition: none; }
  .voile { display: block; position: fixed; inset: 0; z-index: 65; border: 0; padding: 0; margin: 0; background: rgba(0, 42, 75, .4); backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px); opacity: 0; pointer-events: none; transition: opacity .3s var(--ease-doux); cursor: pointer; }
  :root[data-menu-mobile="ouvert"] .voile { opacity: 1; pointer-events: auto; }
  :root[data-menu-mobile="ouvert"] body { overflow: hidden; }
  .btn-fermer-menu { display: inline-grid; width: 32px; height: 32px; font-size: 15px; }
  .btn-rail, .rail-bulle { display: none; }
}
/* Telephone (designer : ses selecteurs Site et Periode sont caches sous 640 px, la page prend sa valeur par defaut). */
@media (max-width: 640px) { .top-actions > select { display: none !important; } }

/* =====================================================================================
   Retour du designer du 13/09/2026 : « espacement, homogénéité des espaces, paddings top et
   bottom, espace entre les blocs, l'intensité des bordures des blocs ». Valeurs de sa maquette
   (AppSidebar.tsx, Panel.tsx, KpiRow.tsx, styles.css), posées en fin de feuille pour primer.
   ===================================================================================== */
/* Menu : conteneur px-3 (12 px) ; titre de groupe px-2.5 py-2, trait 20 px, clair quand le groupe
   est ouvert ; liste pt/pb 6 px, 4 px entre les entrées ; entrée rounded-2xl px-3.5 py-[9px], gap 12,
   texte normal (semi-gras seulement sur l'actif), survol #122D48. */
.side-sec { margin: 0 12px; padding: 8px 10px; width: calc(100% - 24px); gap: 10px; letter-spacing: .09em; border-radius: 10px; transition: background-color .15s ease, color .2s ease; }
.side-sec::before { width: 20px; background: rgba(56, 156, 154, .4); transition: background-color .2s ease; }
.side-sec[aria-expanded="true"]::before { background: var(--accent-turq); }
:root:not([data-menu="clair"]) .side-sec:hover { background: rgba(18, 45, 72, .4); }
:root:not([data-menu="clair"]) .side-sec[aria-expanded="true"] { color: #E6EEF3; }
.side-grp { padding: 6px 0; }
.side-grp.plie { padding: 0; }
.side nav a { margin: 0 12px 4px; padding: 9px 14px; gap: 12px; font-weight: 400; border-radius: 19.6px; }
.side nav a.on { font-weight: 600; }
:root:not([data-menu="clair"]) .side nav a:not(.on):hover { background: #122D48; }
/* Cartes (son Panel) : bordure à 60 %, en-tête 16 px en haut / 8 px en bas SANS filet, 20 px sur
   les côtés, corps 8 / 20 / 20 ; 16 px sur téléphone. La barre de filtres collée au titre ne garde
   que son filet du bas, comme la sienne. */
.card { border-color: rgba(220, 227, 234, .6); }
.card > h4 { padding: 16px 20px 8px; border-bottom: 0; }
.card .card-body { padding: 8px 20px 20px; }
.card > h4 + .lv-filtres { border-top: 0; }
/* Tuiles d'indicateurs (son KpiRow) : bordure à 50 %, ombre flottante, p-4. */
.kpis-anneaux .kpi { border-color: rgba(220, 227, 234, .5); box-shadow: var(--shadow-float); padding: 16px; }
@media (max-width: 640px) {
  .card > h4 { padding: 16px 16px 8px; }
  .card .card-body { padding: 8px 16px 16px; }
}
