/* ==========================================================================
   Polices — servies par l'application, jamais par un CDN
   ==========================================================================
   font-src 'self' dans la CSP interdit tout chargement distant, et un
   cabinet d'avocats n'a pas à signaler à un tiers, page après page, qui
   consulte quoi. Licences et provenance : assets/fonts/LICENCES.md.
   ========================================================================== */
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  /* Fonte variable : un seul fichier couvre 400, 500 et 600. */
  font-weight: 100 700;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-sans-variable.woff2') format('woff2');
}

@font-face {
  font-family: 'Material Symbols Outlined';
  font-style: normal;
  font-weight: 400;
  /* block, pas swap : une icône affichée en toutes lettres pendant le
     chargement (« delete », « menu ») est pire qu'un bref vide. */
  font-display: block;
  src: url('/assets/fonts/material-symbols-outlined.woff2') format('woff2');
}

/* ==========================================================================
   Tokens — voir docs/design-system.md
   ========================================================================== */
:root {
  --gris-0:   #FFFFFF;
  --gris-50:  #F7F8FA;
  --gris-100: #EEF0F3;
  --gris-200: #E2E5EA;
  --gris-300: #CBD0D9;
  --gris-400: #A6ADBA;
  --gris-500: #7C8494;
  --gris-600: #5A6272;
  --gris-700: #3E4452;
  --gris-800: #282C36;
  --gris-900: #14161C;

  --accent-50:  #EEF2F7;
  --accent-100: #D6E0EC;
  --accent-300: #7C97B8;
  --accent-500: #2C4A6E;
  --accent-600: #1F3A5A;
  --accent-700: #16293F;
  --accent-900: #0C1826;

  --succes:      #1E7145;
  --succes-fond: #E6F2EA;
  --alerte:      #9A6400;
  --alerte-fond: #FCF1DC;
  --danger:      #B3261E;
  --danger-fond: #FBE8E7;
  --info:        var(--accent-500);
  --info-fond:   var(--accent-50);

  --fond-app:     var(--gris-50);
  --fond-surface: var(--gris-0);

  --police-defaut: 'IBM Plex Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;

  --texte-xs:   12px; --interligne-xs: 16px;
  --texte-sm:   13px; --interligne-sm: 18px;
  --texte-base: 14px; --interligne-base: 20px;
  --texte-md:   16px; --interligne-md: 24px;
  --texte-lg:   18px; --interligne-lg: 26px;
  --texte-xl:   22px; --interligne-xl: 30px;
  --texte-2xl:  28px; --interligne-2xl: 36px;

  --espace-1: 4px;  --espace-2: 8px;   --espace-3: 12px;
  --espace-4: 16px; --espace-5: 20px;  --espace-6: 24px;
  --espace-8: 32px; --espace-10: 40px; --espace-12: 48px;
  --espace-16: 64px;

  --rayon-sm: 4px;
  --rayon-md: 6px;
  --rayon-lg: 8px;
  --rayon-plein: 999px;
  /* Rayons larges, ajoutes pour les cartes de type widget. Les rayons
     sm/md/lg restent la reference pour les champs, boutons et tableaux :
     un rayon de 24px sur une ligne de tableau dense est illisible. */
  --rayon-xl:  16px;
  --rayon-2xl: 24px;

  --ombre-1: 0 1px 2px rgba(44,34,26,0.06), 0 1px 1px rgba(44,34,26,0.04);
  --ombre-2: 0 4px 12px rgba(44,34,26,0.10), 0 2px 4px rgba(44,34,26,0.06);
  --ombre-interieure: inset 0 1px 2px rgba(44,34,26,0.08);
  /* Ombre large et diffuse, pour les cartes qui doivent flotter plutot
     que se poser. Tres etalee, tres peu opaque : on cherche la lumiere,
     pas le trait. */
  --ombre-flottante: 0 2px 4px rgba(44,34,26,0.03), 0 14px 34px rgba(44,34,26,0.09);
  --liseve-lumiere: inset 0 1px 0 rgba(255,255,255,0.6);

  /* ------------------------------------------------------------------
     Relief — transposé du système « matière et relief » de Geek Factory
     (Portfolio geek factory, src/styles/tokens.css, bloc
     [data-surface="light"]). Une arête blanche en haut, une arête sombre
     en bas : l'objet sort du plan. Inverser les deux le fait rentrer.
     Le relief n'est fait que d'opacités blanches et noires — il ne
     touche donc pas à la palette, qui reste navy et gris.
     ------------------------------------------------------------------ */
  --relief:
    inset 0  1px 0 rgba(255,255,255,1),
    inset 0 -1px 0 rgba(44,34,26,0.06),
    0 1px 2px rgba(44,34,26,0.06),
    0 10px 30px rgba(44,34,26,0.08);
  --relief-sm:
    inset 0  1px 0 rgba(255,255,255,1),
    inset 0 -1px 0 rgba(44,34,26,0.05),
    0 1px 3px rgba(44,34,26,0.07);
  --relief-lg:
    inset 0  1px 0 rgba(255,255,255,1),
    inset 0 -1px 0 rgba(44,34,26,0.07),
    0 2px 4px rgba(44,34,26,0.05),
    0 24px 60px rgba(44,34,26,0.14);

  /* Rentre dans le plan : champs de saisie, état pressé. */
  --creux:
    inset 0 2px 5px rgba(44,34,26,0.10),
    inset 0 -1px 0 rgba(255,255,255,0.9);

  /* Reflet spéculaire. Sur fond clair il doit être franc : c'est lui qui
     porte le volume, l'ombre étant très douce de ce côté. */
  --reflet: linear-gradient(180deg, rgba(255,252,246,0.95), rgba(255,252,246,0.05));
  /* Sur une masse d'accent — navy plein — un blanc à 95 % dévorerait la
     moitié haute du bouton. */
  --reflet-accent: linear-gradient(180deg, rgba(255,255,255,0.22), rgba(255,255,255,0.02));

  /* Texte foncé + ombre blanche dessous : lettres légèrement creusées. */
  --gravure: 0 1px 0 rgba(255,255,255,1);

  /* Une surface plate ne capte pas la lumière : deux points suffisent à
     suggérer une face légèrement bombée. */
  /* Le haut de la matiere tire tres legerement vers le chaud : la
     lumiere qui la frappe vient d'une lampe, pas d'un tube. */
  --matiere: linear-gradient(180deg, #FFFDFA 0%, var(--gris-50) 100%);
}

/* ==========================================================================
   Base
   ========================================================================== */
*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: var(--police-defaut);
  font-size: var(--texte-base);
  line-height: var(--interligne-base);
  color: var(--gris-800);
  /* Une nappe de lumiere chaude tombant du haut, comme une lampe de
     bureau. Le fond reste --fond-app ; la nappe se pose dessus et
     s'epuise avant le milieu de l'ecran. C'est ce qui empeche une
     interface en navy et gris de virer au bleu clinique. */
  /* Trois couches empilees dans le fond lui-meme, sans pseudo-element :
     le grain d'abord, la nappe de lumiere ensuite, la couleur de fond
     dessous. Un body::before en position fixed recouvrait tout le
     contenu — teste, et la page etait blanche. */
  background:
    repeating-linear-gradient(97deg, rgba(44,34,26,0.018) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(7deg,  rgba(44,34,26,0.012) 0 1px, transparent 1px 4px),
    radial-gradient(ellipse 130% 70% at 50% -12%,
      rgba(255, 243, 226, 0.85) 0%,
      rgba(255, 246, 236, 0.30) 38%,
      transparent 68%),
    var(--fond-app);
  background-attachment: fixed, fixed, fixed, scroll;
}
h1, h2, h3, p, ul, form { margin: 0; }
a { color: var(--accent-500); }
.chiffres-tabulaires { font-variant-numeric: tabular-nums; }
.texte-secondaire { color: var(--gris-600); font-size: var(--texte-sm); }

.material-symbols-outlined {
  font-family: 'Material Symbols Outlined', sans-serif;
  font-size: 20px;
  line-height: 1;
  vertical-align: middle;
  /* Sans la ligature, le nom de l'icône s'affiche littéralement. */
  font-feature-settings: 'liga';
  font-weight: normal;
  letter-spacing: normal;
  white-space: nowrap;
  word-wrap: normal;
  direction: ltr;
  -webkit-font-smoothing: antialiased;
}

/* ==========================================================================
   Mise en page
   ========================================================================== */
.mise-en-page { display: flex; min-height: 100vh; }

.nav-bascule {
  display: none;
  position: fixed;
  top: var(--espace-3);
  left: var(--espace-3);
  z-index: 20;
  width: 44px;
  height: 44px;
  align-items: center;
  justify-content: center;
  background: var(--fond-surface);
  border: 1px solid var(--gris-300);
  border-radius: var(--rayon-sm);
  box-shadow: var(--ombre-1);
}

.nav-laterale {
  width: 240px;
  flex-shrink: 0;
  background: var(--fond-surface);
  border-right: 1px solid var(--gris-200);
  display: flex;
  flex-direction: column;
  padding: var(--espace-5) var(--espace-4);
  gap: var(--espace-6);
}
.nav-entete { padding: var(--espace-2) var(--espace-2); }
.nav-logo { font-weight: 600; font-size: var(--texte-md); color: var(--gris-900); }
.nav-liens { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: var(--espace-1); flex: 1; }
.nav-lien {
  display: block;
  padding: var(--espace-2) var(--espace-3);
  border-radius: var(--rayon-sm);
  color: var(--gris-700);
  text-decoration: none;
  font-size: var(--texte-sm);
  font-weight: 500;
}
.nav-lien:hover { background: var(--gris-50); }
.nav-lien-actif { background: var(--accent-50); color: var(--accent-700); }
.nav-deconnexion { margin-top: auto; }

.contenu-principal {
  flex: 1;
  padding: var(--espace-8);
  display: flex;
  flex-direction: column;
  gap: var(--espace-6);
  min-width: 0;
}

/* ==========================================================================
   Boutons
   ========================================================================== */
.bouton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--espace-2);
  height: 40px;
  padding: 0 var(--espace-4);
  border-radius: var(--rayon-sm);
  border: 1px solid transparent;
  font-family: inherit;
  font-size: var(--texte-sm);
  font-weight: 500;
  cursor: pointer;
  text-decoration: none;
  box-shadow: var(--relief-sm);
  /* isolation : le reflet est pose en z-index -1, il doit rester
     au-dessus du fond du bouton mais sous son libelle. */
  position: relative;
  isolation: isolate;
  transition: box-shadow 0.12s ease, transform 0.12s ease, background 0.12s ease;
}

/* Le reflet, a base incurvee. C'est la courbe — pas le degrade — qui
   fait lire une surface bombee : une base droite ne donne qu'un bandeau
   plus clair. */
.bouton::before {
  content: '';
  position: absolute;
  left: 1px;
  right: 1px;
  top: 1px;
  height: 46%;
  z-index: -1;
  border-radius: inherit;
  border-bottom-left-radius: 60% 100%;
  border-bottom-right-radius: 60% 100%;
  background: var(--reflet);
  pointer-events: none;
  transition: opacity 0.12s ease;
}
.bouton-primaire::before { background: var(--reflet-accent); }
.bouton-tertiaire::before { display: none; }

.bouton:hover { box-shadow: var(--relief); transform: translateY(-1px); }

/* L'enfoncement : l'objet descend d'un pixel, son relief s'inverse, et
   il cesse de capter la lumiere du haut. C'est ce trio qui donne la
   sensation tactile — sans le reflet qui s'eteint, le clic sonne faux. */
.bouton:active { box-shadow: var(--creux); transform: translateY(1px); }
.bouton:active::before { opacity: 0; }
.bouton:focus-visible { outline: 2px solid var(--accent-500); outline-offset: 2px; }
.bouton-primaire { background: var(--accent-500); color: var(--gris-0); }
.bouton-primaire:hover { background: var(--accent-600); }
/* Le secondaire est une touche : matiere bombee et texte grave. */
.bouton-secondaire { background: var(--matiere); color: var(--gris-800); border-color: var(--gris-200); text-shadow: var(--gravure); }
.bouton-secondaire:hover { background: var(--gris-50); }
.bouton-tertiaire { background: transparent; color: var(--accent-500); box-shadow: none; }
.bouton-tertiaire:hover { box-shadow: none; transform: none; }
.bouton-tertiaire:active { box-shadow: none; }
.bouton-tertiaire:hover { background: var(--accent-50); }
.bouton-danger { background: var(--danger); color: var(--gris-0); }
.bouton-pleine-largeur { width: 100%; }

.lien-action {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-size: var(--texte-sm);
  color: var(--accent-500);
  cursor: pointer;
  text-decoration: none;
}
.lien-action-danger { color: var(--danger); }
.forme-inline { display: inline; }

/* ==========================================================================
   Champs, select, formulaire
   ========================================================================== */
.formulaire { display: flex; flex-direction: column; gap: var(--espace-4); max-width: 480px; }
.formulaire > div[class^="section-"] { display: flex; flex-direction: column; gap: var(--espace-4); }
.formulaire > div[class^="section-"][hidden] { display: none; }
.champ-groupe { display: flex; flex-direction: column; gap: var(--espace-1); }
.champ-groupe label { font-size: var(--texte-sm); font-weight: 500; color: var(--gris-700); }
.champ-case { flex-direction: row; align-items: center; gap: var(--espace-2); }
.champ-case label { display: flex; align-items: center; gap: var(--espace-2); font-weight: 400; }

.champ, select.champ {
  height: 40px;
  padding: 0 var(--espace-3);
  border: 1px solid var(--gris-300);
  border-radius: var(--rayon-sm);
  font: inherit;
  font-size: var(--texte-base);
  color: var(--gris-800);
  background: var(--fond-surface);
  /* Un champ est un creux : on y depose du texte. */
  box-shadow: var(--creux);
}
.champ:focus, select.champ:focus {
  outline: 2px solid var(--accent-500);
  outline-offset: 1px;
  border-color: var(--accent-500);
}
.champ-erreur { border-color: var(--danger); }
.champ-message-erreur { color: var(--danger); font-size: var(--texte-xs); margin: 0; }

/* Texte d'aide sous un champ : explique une contrainte que l'étiquette
   seule ne porte pas. Nouveau composant, design-system.md §7. */
.champ-aide { font-size: var(--texte-xs); color: var(--gris-600); margin: var(--espace-1) 0 0; }
.champ:disabled { background: var(--gris-100); color: var(--gris-500); box-shadow: none; }

textarea.champ { height: auto; min-height: 88px; padding: var(--espace-2) var(--espace-3); resize: vertical; }

/* Le sélecteur de fichier natif ne se style pas comme un champ texte :
   on lui laisse sa hauteur propre et un padding cohérent. */
.champ-fichier { height: auto; min-height: 40px; padding: var(--espace-2) var(--espace-3); box-shadow: none; }

.champ-radios { display: flex; gap: var(--espace-4); }
.champ-radio { display: flex; align-items: center; gap: var(--espace-2); font-size: var(--texte-base); font-weight: 400; color: var(--gris-800); }

/* wrap : cinq boutons d'action sur une fiche dossier debordaient
   horizontalement sous 420px. */
.formulaire-actions { display: flex; gap: var(--espace-3); margin-top: var(--espace-2); flex-wrap: wrap; }

.formulaire-recherche { display: flex; gap: var(--espace-2); max-width: 480px; }
.formulaire-recherche .champ { flex: 1; }

/* Filtre de période : champs alignés en ligne, bouton en bas de ligne. */
.formulaire-periode { display: flex; gap: var(--espace-3); align-items: flex-end; flex-wrap: wrap; }
.formulaire-periode .champ-groupe { gap: var(--espace-1); }

/* Grille plutot que flex-wrap : en flex, une rangee de trois cartes se
   coupait en 2 + 1 avec un vide a droite. Les colonnes se remplissent
   maintenant a egalite, quel que soit le nombre de cartes. */
.cumuls { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--espace-4); }
.cumuls .carte-stat { max-width: none; }

/* Formulaire de facturation : les tableaux de sélection ont besoin de
   toute la largeur, contrairement aux formulaires de saisie classiques. */
/* Graphiques du tableau de bord : deux colonnes au bureau, empilés en
   dessous de 768px (le canvas est responsive côté Chart.js). */
.grille-graphiques { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: var(--espace-4); }
.carte-graphique {
  background: var(--matiere);
  box-shadow: var(--relief);
  border-radius: var(--rayon-2xl);
  padding: var(--espace-6);
  min-width: 0;
}
/* Chart.js en maintainAspectRatio:false remplit la hauteur de son parent :
   sans conteneur de hauteur fixe, le canvas s'étire hors de sa carte. */
.zone-graphique { position: relative; height: 260px; }
.carte-graphique canvas { max-width: 100%; }

.formulaire-large { max-width: none; }
.champs-en-ligne { display: flex; gap: var(--espace-4); flex-wrap: wrap; }
.champs-en-ligne .champ-groupe { min-width: 180px; }

/* Étiquette réservée aux lecteurs d'écran. */
.visuellement-masque {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ==========================================================================
   Tableau dense
   ========================================================================== */
.tableau-conteneur { overflow-x: auto; }
.tableau-dense { width: 100%; border-collapse: collapse; font-size: var(--texte-sm); background: var(--fond-surface); }
.tableau-dense th {
  text-align: left;
  font-size: var(--texte-xs);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--gris-600);
  padding: var(--espace-2) var(--espace-3);
  border-bottom: 1px solid var(--gris-300);
}
.tableau-dense td {
  padding: var(--espace-2) var(--espace-3);
  border-bottom: 1px solid var(--gris-200);
  height: 40px;
}
.tableau-dense tbody tr:hover { background: var(--gris-50); }
.tableau-actions { display: flex; gap: var(--espace-3); }

/* ==========================================================================
   Badge, alerte, carte-stat, état vide
   ========================================================================== */
.badge {
  display: inline-block;
  padding: var(--espace-1) var(--espace-2);
  border-radius: var(--rayon-sm);
  font-size: var(--texte-xs);
  font-weight: 500;
}
.badge-succes { background: var(--succes-fond); color: var(--succes); }
.badge-alerte { background: var(--alerte-fond); color: var(--alerte); }
.badge-danger { background: var(--danger-fond); color: var(--danger); }
.badge-neutre { background: var(--gris-100); color: var(--gris-600); }

.alerte {
  display: flex;
  align-items: flex-start;
  gap: var(--espace-2);
  padding: var(--espace-3) var(--espace-4);
  border-radius: var(--rayon-sm);
  border-left: 3px solid;
  font-size: var(--texte-sm);
}
.alerte-succes { background: var(--succes-fond); border-color: var(--succes); color: var(--succes); }
.alerte-erreur { background: var(--danger-fond); border-color: var(--danger); color: var(--danger); }
.alerte-info { background: var(--info-fond); border-color: var(--info); color: var(--accent-700); }
.alerte p { margin: 0; }

/* Coins continus : la courbure entre progressivement dans l'angle au
   lieu de demarrer net. C'est une superellipse, pas un arc de cercle.
   Chromium seulement a ce jour — les autres navigateurs ignorent la
   propriete et gardent le border-radius, sans rien casser. */
.carte-stat,
.carte-graphique {
  corner-shape: squircle;
}

.carte-stat {
  /* Le degrade s'epuise dans la surface au lieu de s'arreter net :
     l'accent se lit comme une lumiere, pas comme un aplat. */
  background: linear-gradient(180deg, var(--accent-50) 0%, var(--fond-surface) 62%);
  box-shadow: var(--relief);
  border-radius: var(--rayon-2xl);
  padding: var(--espace-6) var(--espace-5);
  max-width: 280px;
}
.carte-stat-libelle { font-size: var(--texte-sm); color: var(--gris-600); margin: 0 0 var(--espace-1); }
.carte-stat-chiffre { font-size: var(--texte-2xl); font-weight: 600; margin: 0; color: var(--gris-900); }

.etat-vide {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--espace-3);
  padding: var(--espace-12) var(--espace-4);
  color: var(--gris-600);
  text-align: center;
}
.etat-vide-icone { font-size: 48px; color: var(--gris-300); }

.entete-page { display: flex; align-items: center; justify-content: space-between; gap: var(--espace-4); flex-wrap: wrap; }
.titre-page { font-size: var(--texte-xl); font-weight: 600; color: var(--gris-900); }
.titre-section { font-size: var(--texte-md); font-weight: 600; color: var(--gris-900); margin: 0 0 var(--espace-3); }
.titre-auth { font-size: var(--texte-lg); font-weight: 600; margin-bottom: var(--espace-4); }

/* ==========================================================================
   Carte d'information, liste simple (fiche dossier)
   ========================================================================== */
.carte-info {
  background: var(--matiere);
  box-shadow: var(--relief);
  border-radius: var(--rayon-md);
  padding: var(--espace-5);
  display: flex;
  flex-direction: column;
  gap: var(--espace-2);
  max-width: 640px;
}
.carte-info-ligne { display: flex; gap: var(--espace-4); font-size: var(--texte-sm); }
.carte-info-ligne > span:first-child, .carte-info-ligne > a:first-child { flex: 0 0 160px; color: var(--gris-600); }

.liste-simple { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--espace-1); }
.liste-simple li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--espace-3);
  padding: var(--espace-2) var(--espace-3);
  background: var(--fond-surface);
  border: 1px solid var(--gris-200);
  border-radius: var(--rayon-sm);
  font-size: var(--texte-sm);
}
.liste-simple-contenu { display: flex; align-items: center; gap: var(--espace-3); flex-wrap: wrap; }

/* ==========================================================================
   Grille de fiche — design-system.md §7
   ==========================================================================
   Une fiche detaillee empile une carte de synthese puis des sections de
   travail. Sur mobile c'est le bon ordre de lecture. Au bureau, la carte
   plafonne a 640px et laissait pres de 400px inutilises a droite : la
   grille met les sections a cote, et la synthese reste sous les yeux
   pendant qu'on travaille dedans.
   ========================================================================== */
.grille-fiche { display: grid; gap: var(--espace-6); }
.grille-fiche-sections { display: flex; flex-direction: column; gap: var(--espace-6); min-width: 0; }

@media (min-width: 1024px) {
  .grille-fiche { grid-template-columns: minmax(300px, 360px) 1fr; align-items: start; }
  /* La carte occupe sa colonne : le plafond de 640px n'a plus de sens ici. */
  .grille-fiche > .carte-info { max-width: none; position: sticky; top: var(--espace-6); }

  /* Dans une colonne de 360px, libelle et valeur cote a cote se
     serrent et cassent les mots. On les empile, comme le fait deja la
     carte sous 768px : meme composant, meme contrainte de largeur. */
  /* align-items sur le debut : sans lui, un enfant en ligne comme le
     badge de statut s'etire sur toute la largeur de la colonne. */
  .grille-fiche > .carte-info .carte-info-ligne {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--espace-1);
  }
  .grille-fiche > .carte-info .carte-info-ligne > span:first-child,
  .grille-fiche > .carte-info .carte-info-ligne > a:first-child {
    flex: none;
    font-size: var(--texte-xs);
    color: var(--gris-500);
  }
}

/* ==========================================================================
   Chronologie verticale — design-system.md §7
   ========================================================================== */
.chronologie {
  position: relative;
  list-style: none;
  margin: 0;
  padding: 0 0 0 var(--espace-6);
  display: flex;
  flex-direction: column;
  gap: var(--espace-4);
}
.chronologie::before {
  content: '';
  position: absolute;
  left: 5px;
  top: 6px;
  bottom: 6px;
  width: 2px;
  background: var(--gris-300);
}
.chronologie-item { position: relative; }
.chronologie-pastille {
  position: absolute;
  left: calc(-1 * var(--espace-6) + 1px);
  top: 4px;
  width: 10px;
  height: 10px;
  border-radius: var(--rayon-plein);
  background: var(--accent-500);
}
.chronologie-pastille-renvoi { background: var(--alerte); }
.chronologie-pastille-evenement { background: var(--gris-500); }
.chronologie-date { font-size: var(--texte-xs); color: var(--gris-500); margin: 0; }
.chronologie-titre { font-size: var(--texte-sm); font-weight: 500; color: var(--gris-900); margin: var(--espace-1) 0 0; display: flex; align-items: center; gap: var(--espace-2); }
.chronologie-description { font-size: var(--texte-sm); color: var(--gris-600); margin: var(--espace-1) 0 0; }
.chronologie-actions { display: flex; gap: var(--espace-3); margin-top: var(--espace-2); }

/* ==========================================================================
   Calendrier — design-system.md §7 (grille bureau, liste sous 768px)
   ========================================================================== */
/* ==========================================================================
   Onglets — design-system.md §7 (soulignement, pas de pill)
   ========================================================================== */
.onglets { display: flex; gap: var(--espace-4); border-bottom: 1px solid var(--gris-200); }
.onglet {
  padding: var(--espace-2) 0;
  font-size: var(--texte-sm);
  font-weight: 500;
  color: var(--gris-600);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.onglet:hover { color: var(--gris-800); }
.onglet-actif { color: var(--accent-500); border-bottom-color: var(--accent-500); }

.texte-danger { color: var(--danger); font-weight: 500; }

.calendrier-navigation { display: flex; align-items: center; gap: var(--espace-3); }
.calendrier-mois { font-size: var(--texte-md); font-weight: 600; color: var(--gris-900); margin: 0; min-width: 180px; }

.calendrier-legende {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-4);
  font-size: var(--texte-xs);
  color: var(--gris-600);
}
.calendrier-legende li { display: flex; align-items: center; gap: var(--espace-2); }

.calendrier-pastille { width: 8px; height: 8px; border-radius: var(--rayon-plein); flex-shrink: 0; }
.calendrier-pastille-audience      { background: var(--accent-500); }
.calendrier-pastille-delai         { background: var(--alerte); }
.calendrier-pastille-delai_depasse { background: var(--danger); }
.calendrier-pastille-rendez_vous   { background: var(--succes); }
.calendrier-pastille-tache         { background: var(--gris-500); }

.calendrier-tableau { width: 100%; border-collapse: collapse; background: var(--fond-surface); table-layout: fixed; }
.calendrier-tableau th {
  font-size: var(--texte-xs);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--gris-600);
  padding: var(--espace-2);
  border-bottom: 1px solid var(--gris-300);
  text-align: left;
}
.calendrier-case {
  vertical-align: top;
  height: 96px;
  padding: var(--espace-1);
  border: 1px solid var(--gris-200);
}
.calendrier-case-vide { background: var(--gris-50); }
.calendrier-case-aujourdhui { box-shadow: inset 0 0 0 2px var(--accent-500); }
.calendrier-numero { display: block; font-size: var(--texte-xs); color: var(--gris-600); margin-bottom: var(--espace-1); }

.calendrier-evenement {
  display: block;
  font-size: var(--texte-xs);
  line-height: 15px;
  padding: 2px var(--espace-1);
  margin-bottom: 2px;
  border-radius: var(--rayon-sm);
  border-left: 3px solid;
  text-decoration: none;
  color: var(--gris-800);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.calendrier-evenement:hover { background: var(--gris-100); }
.calendrier-evenement-audience      { border-color: var(--accent-500); background: var(--accent-50); }
.calendrier-evenement-delai         { border-color: var(--alerte); background: var(--alerte-fond); }
.calendrier-evenement-delai_depasse { border-color: var(--danger); background: var(--danger-fond); }
.calendrier-evenement-rendez_vous   { border-color: var(--succes); background: var(--succes-fond); }
.calendrier-evenement-tache         { border-color: var(--gris-500); background: var(--gris-100); }

.calendrier-liste { display: none; }
.calendrier-jour + .calendrier-jour { margin-top: var(--espace-4); }
.calendrier-jour-titre { font-size: var(--texte-sm); font-weight: 600; color: var(--gris-900); margin: 0 0 var(--espace-2); }

.champ-cases { display: flex; flex-direction: column; gap: var(--espace-2); }
fieldset.champ-groupe { border: none; margin: 0; padding: 0; }
fieldset.champ-groupe legend { font-size: var(--texte-sm); font-weight: 500; color: var(--gris-700); padding: 0; margin-bottom: var(--espace-1); }

/* ==========================================================================
   Écran de connexion
   ========================================================================== */
.fond-auth { display: flex; align-items: center; justify-content: center; }
.conteneur-auth { width: 100%; max-width: 360px; padding: var(--espace-4); }
.carte-auth {
  background: var(--fond-surface);
  box-shadow: var(--ombre-2);
  border-radius: var(--rayon-md);
  padding: var(--espace-8);
}
.carte-auth .formulaire { max-width: none; }

/* ==========================================================================
   Barre supérieure, recherche globale, cloche — design-system.md §7
   ========================================================================== */
.barre-superieure { display: flex; align-items: center; gap: var(--espace-4); min-width: 0; }
/* min-width:0 sur le formulaire ET sur le champ : sans cela la largeur
   intrinsèque de l'input empêche le rétrécissement et fait déborder la
   barre hors de l'écran à 375 px. */
.barre-recherche { flex: 1; max-width: 440px; min-width: 0; }
.barre-recherche .champ { min-width: 0; }

.cloche {
  position: relative;
  margin-left: auto;
  width: 40px;
  height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--rayon-sm);
  color: var(--gris-600);
  text-decoration: none;
}
/* Le glyphe est la seule étiquette de ce contrôle : tant que la police
   d'icônes n'est pas embarquée (voir docs/journal.md), le navigateur
   affiche le mot « notifications » en clair. On le confine à la cible
   tactile pour qu'il ne pousse jamais la mise en page hors de l'écran. */
.cloche { overflow: hidden; }
.cloche:hover { background: var(--gris-100); color: var(--gris-800); }
.cloche-active { background: var(--accent-50); color: var(--accent-700); }
.cloche-compteur {
  position: absolute;
  top: 2px;
  right: 0;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--rayon-plein);
  background: var(--danger);
  color: var(--gris-0);
  font-size: var(--texte-xs);
  line-height: 18px;
  font-weight: 600;
  text-align: center;
}

/* ==========================================================================
   Résultats de recherche — design-system.md §7
   ========================================================================== */
.bloc-resultats + .bloc-resultats { margin-top: var(--espace-6); }
.compteur-resultats {
  display: inline-block;
  margin-left: var(--espace-2);
  padding: 0 var(--espace-2);
  border-radius: var(--rayon-plein);
  background: var(--gris-100);
  color: var(--gris-600);
  font-size: var(--texte-xs);
  font-weight: 500;
}
.liste-resultats { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--espace-2); }
.resultat {
  display: flex;
  align-items: center;
  gap: var(--espace-3);
  padding: var(--espace-3) var(--espace-4);
  background: var(--fond-surface);
  box-shadow: var(--ombre-1);
  border-radius: var(--rayon-md);
  text-decoration: none;
  color: inherit;
}
.resultat:hover { box-shadow: var(--ombre-2); }
.resultat:active { box-shadow: var(--ombre-interieure); }
.resultat-icone { color: var(--gris-400); flex-shrink: 0; }
.resultat-corps { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.resultat-titre { font-size: var(--texte-base); font-weight: 500; color: var(--gris-900); }
.resultat-detail { font-size: var(--texte-sm); color: var(--gris-600); }

/* ==========================================================================
   Journal d'activité — valeurs avant/après — design-system.md §7
   ========================================================================== */
.detail-journal summary { cursor: pointer; font-size: var(--texte-sm); color: var(--accent-500); }
.differences { margin: var(--espace-2) 0 0; display: flex; flex-direction: column; gap: var(--espace-2); }
.difference { display: flex; flex-direction: column; gap: 2px; }
.difference dt { font-size: var(--texte-xs); color: var(--gris-500); }
.difference dd { margin: 0; display: flex; align-items: center; gap: var(--espace-2); flex-wrap: wrap; font-size: var(--texte-sm); }
.valeur-avant { color: var(--gris-500); text-decoration: line-through; }
.valeur-apres { color: var(--gris-900); font-weight: 500; }
.fleche-difference { font-size: 16px; color: var(--gris-400); }

/* ==========================================================================
   Centre de notifications — design-system.md §7
   ========================================================================== */
.liste-notifications { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--espace-2); }
.notification-bouton {
  width: 100%;
  display: flex;
  align-items: flex-start;
  gap: var(--espace-3);
  padding: var(--espace-3) var(--espace-4);
  background: var(--fond-surface);
  border: none;
  border-left: 3px solid transparent;
  box-shadow: var(--ombre-1);
  border-radius: var(--rayon-md);
  text-align: left;
  cursor: pointer;
  font: inherit;
  color: inherit;
}
.notification-bouton:hover { box-shadow: var(--ombre-2); }
.notification-bouton:active { box-shadow: var(--ombre-interieure); }
.notification-non-lue .notification-bouton { border-left-color: var(--accent-500); background: var(--accent-50); }
.notification-icone { color: var(--gris-400); flex-shrink: 0; }
.notification-non-lue .notification-icone { color: var(--accent-500); }
.notification-corps { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.notification-titre { font-size: var(--texte-base); font-weight: 500; color: var(--gris-900); }
.notification-non-lue .notification-titre { font-weight: 600; }
.notification-message { font-size: var(--texte-sm); color: var(--gris-700); }
.notification-date { font-size: var(--texte-xs); color: var(--gris-500); }
.pastille-non-lue {
  flex-shrink: 0;
  width: 8px;
  height: 8px;
  margin-top: var(--espace-2);
  border-radius: var(--rayon-plein);
  background: var(--accent-500);
}

/* ==========================================================================
   Responsive — 768px (règle 11 : cibles tactiles 44px sous ce seuil)
   ========================================================================== */
@media (max-width: 767px) {
  .nav-bascule { display: flex; }

  .nav-laterale {
    position: fixed;
    inset: 0;
    z-index: 15;
    width: 100%;
    transform: translateX(-100%);
    transition: transform 0.15s ease;
  }
  .nav-laterale.nav-ouverte { transform: translateX(0); }

  .contenu-principal { padding: var(--espace-16) var(--espace-4) var(--espace-6); }

  .bouton, .champ, select.champ { height: 44px; }

  .tableau-dense thead { display: none; }
  .tableau-dense, .tableau-dense tbody, .tableau-dense tr, .tableau-dense td { display: block; width: 100%; }
  .tableau-dense tr {
    background: var(--fond-surface);
    box-shadow: var(--ombre-1);
    border-radius: var(--rayon-md);
    margin-bottom: var(--espace-3);
    padding: var(--espace-2) var(--espace-3);
  }
  .tableau-dense td {
    display: flex;
    justify-content: space-between;
    align-items: center;
    border-bottom: 1px solid var(--gris-100);
    height: auto;
    min-height: 44px;
  }
  .tableau-dense td:last-child { border-bottom: none; }
  .tableau-dense td[data-libelle]::before {
    content: attr(data-libelle);
    font-size: var(--texte-xs);
    color: var(--gris-500);
    font-weight: 500;
  }

  /* La barre supérieure passe sous le bouton de menu fixe : la cloche
     garde sa cible de 44px et le champ occupe la largeur restante. */
  .barre-superieure { flex-wrap: nowrap; }
  .barre-recherche { max-width: none; }
  .barre-recherche .bouton { padding-left: var(--espace-3); padding-right: var(--espace-3); }
  .cloche { width: 44px; height: 44px; }

  .resultat, .notification-bouton { min-height: 44px; }

  /* align-items sur le debut : sans lui, un enfant en ligne comme le
     badge de statut s'etire sur toute la largeur de la carte. */
  .carte-info-ligne { flex-direction: column; align-items: flex-start; gap: var(--espace-1); }
  .carte-info-ligne > span:first-child, .carte-info-ligne > a:first-child { flex: none; font-size: var(--texte-xs); color: var(--gris-500); }

  /* Ces lignes portent des liens et des boutons : cible tactile 44px. */
  .liste-simple li { flex-direction: column; align-items: flex-start; gap: var(--espace-2); min-height: 44px; justify-content: center; }

  /* Une case à cocher fait 13px de haut : c'est son étiquette qui doit
     offrir la cible tactile, pas la case elle-même. */
  .champ-case label { min-height: 44px; }

  /* Une grille 7 colonnes écrasée à 375px est illisible et ne respecte pas
     les cibles tactiles : on bascule sur la liste chronologique. */
  .calendrier-grille { display: none; }
  .calendrier-liste { display: block; }
  .calendrier-mois { min-width: 0; flex: 1; text-align: center; }
}
