:root {
  /* Palette chaleureuse (tons neutres affinés + accent ambre/brun). */
  --border: #e4e4e9;
  --text: #17171f;
  --muted: #6c6c7c;
  --bg-page: #f7f7f9;
  --bg-card: #ffffff;
  --bg-card-muted: #fafafb;
  --accent: #b45309;
  --accent-hover: #92400e;
  --accent-soft: #fef3e2;
  --radius: 14px;
  --radius-sm: 9px;
  --shadow-sm: 0 1px 2px rgba(17, 17, 31, 0.04), 0 1px 1px rgba(17, 17, 31, 0.03);
  --shadow-md: 0 10px 28px rgba(17, 17, 31, 0.08);
}

* { box-sizing: border-box; }

body {
  font-family: "Inter", -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
  font-feature-settings: "cv05", "cv11";
  font-size: 15px;
  line-height: 1.55;
  color: var(--text);
  margin: 0;
  background: var(--bg-page);
}

.table, select, input, textarea, button {
  font-family: inherit;
}

.topbar {
  padding: 1.05rem 2rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-card);
  display: flex;
  align-items: center;
  gap: 1.75rem;
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: -0.02em;
  text-decoration: none;
  color: var(--text);
}

.brand-logo {
  height: 34px;
  width: auto;
  display: block;
}

.brand-label {
  padding-top: 0.1rem;
}

.nav {
  display: flex;
  gap: 1.4rem;
}

.nav a {
  color: var(--muted);
  text-decoration: none;
  font-size: 0.88rem;
  font-weight: 500;
  padding: 0.2rem 0;
  border-bottom: 2px solid transparent;
  transition: color 0.15s ease, border-color 0.15s ease;
}

.nav a:hover {
  color: var(--accent);
  border-color: var(--accent-soft);
}

main {
  max-width: 1360px;
  margin: 0 auto;
  padding: 2.25rem 1.75rem;
}

main.wide {
  max-width: 1680px;
}

h1 { font-size: 1.7rem; font-weight: 700; letter-spacing: -0.02em; margin: 0 0 1.5rem; }
h2 { font-size: 1rem; font-weight: 600; letter-spacing: -0.005em; margin: 0 0 1rem; }
h3 { font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); margin: 0 0 0.6rem; }

.muted { color: var(--muted); font-size: 0.9em; }

/* Zone de filtres : regroupée visuellement dans sa propre carte,
   distincte du tableau de résultats qui la suit. */
.filters-card {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-card);
  box-shadow: var(--shadow-sm);
  padding: 1.1rem 1.3rem;
  margin-bottom: 1.25rem;
}
.filters-card .filters {
  margin-bottom: 0;
}

/* Sous-filtre Tous/Dossiers/Formateurs (page Archivés), sous-onglets
   File d'attente/Réglages et filtres de statut (page Mails) -- même
   bouton que .btn-secondary, juste la sélection active mise en évidence.
   Remplace les anciens liens texte simplement soulignés (.sort-active)
   sur ces pages -- une vraie apparence d'onglet/bouton plutôt qu'un lien
   brut, cohérente avec le reste du CRM (fiches dossier/formateur/agenda).
   Sélecteur composé .btn-secondary.btn-filtre-actif (pas .btn-filtre-actif
   seul) : les deux classes sont toujours posées ensemble dans le HTML,
   et la specificité plus élevée garantit que ce fond l'emporte sur celui
   de .btn-secondary quel que soit l'ordre des règles dans la feuille de
   style -- un simple .btn-filtre-actif de même spécificité que
   .btn-secondary se faisait silencieusement écraser par elle plus bas
   dans le fichier (repéré sur la page Mails, fond resté blanc malgré la
   classe active bien posée). */
.btn-secondary.btn-filtre-actif {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.btn-secondary.btn-filtre-actif:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
  color: #fff;
}

/* Barre de sous-onglets (ex: "File d'attente" / "Réglages") -- même
   espacement que .filters, sans carte englobante (contrairement aux
   filtres de statut ci-dessous, elle-même dans .filters-card) pour
   rester visuellement plus proche du titre de page qu'elle complète. */
.sous-onglets {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 1rem;
}

/* Pastille de compteur à l'intérieur d'un bouton de filtre (ex: "En
   attente 4") -- blanc semi-transparent pour rester lisible aussi bien
   sur le fond orange du bouton actif que sur le fond blanc du bouton
   inactif, plutôt qu'une couleur fixe qui ne conviendrait qu'à un seul
   des deux états. */
.filtre-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.4em;
  padding: 0.05em 0.45em;
  border-radius: 999px;
  font-size: 0.78em;
  font-weight: 700;
  background: rgba(0, 0, 0, 0.08);
}
.btn-filtre-actif .filtre-count {
  background: rgba(255, 255, 255, 0.28);
}
.filters-card + .totaux-bar {
  margin-top: -0.4rem;
}

.filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 1.25rem;
}

.statut-dashboard {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1.25rem;
}

.statut-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.4rem 0.85rem;
  border-radius: 999px;
  font-size: 0.82rem;
  font-weight: 600;
  text-decoration: none;
  border: 2px solid transparent;
  transition: border-color 0.15s ease;
}

.statut-chip-active {
  border-color: currentColor;
}

select, input[type="text"], input[type="date"], input[type="number"], input[type="file"],
input[type="email"], input[type="time"] {
  padding: 0.6rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 0.88rem;
  color: var(--text);
  background: var(--bg-card);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

/* Champ de recherche texte dans une barre de filtres (Dossiers,
   Formateurs) -- sans largeur minimale, un input[type="text"] prend sa
   taille par défaut du navigateur (~170px), trop étroite pour afficher
   en entier un placeholder de type "Rechercher un formateur..." (repéré
   tronqué en conditions réelles). flex-grow modéré : s'élargit si la
   barre a de la place, repasse sur sa propre ligne comme les autres
   champs sur un écran étroit (.filters est déjà flex-wrap). */
.filters input[type="text"] {
  min-width: 260px;
  flex: 1 1 260px;
}

/* Menus déroulants : la flèche native est remplacée par un chevron dessiné
   (SVG en data-URI, donc aucun fichier à charger) pour un rendu identique
   sur macOS, Windows et Linux -- la version native est grise, écrasée et
   varie d'un navigateur à l'autre. Le padding droit réserve la place du
   chevron pour qu'un intitulé long ne passe jamais dessous. */
select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 2.1rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%236b7280' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 8l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.7rem center;
  background-size: 1.05rem 1.05rem;
  cursor: pointer;
}
select:hover {
  border-color: var(--accent);
}
select:focus {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%23b45309' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 8l4 4 4-4'/%3E%3C/svg%3E");
}
select:disabled {
  cursor: default;
  opacity: 0.6;
}

select:focus, input:focus, textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

button, .btn-secondary {
  padding: 0.55rem 1.1rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--accent);
  background: var(--accent);
  color: #fff;
  cursor: pointer;
  font-size: 0.88rem;
  font-weight: 600;
  text-decoration: none;
  box-shadow: none;
  transition: background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, transform 0.05s ease;
}

button:hover, .btn-secondary:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: #fff; box-shadow: var(--shadow-sm); }
button:active, .btn-secondary:active { transform: translateY(1px); }

.btn-secondary {
  background: var(--bg-card);
  color: var(--accent);
}

.btn-secondary:hover {
  background: var(--accent-soft);
  border-color: var(--accent-hover);
  color: var(--accent-hover);
}

/* Lien "retour" (ex: fiche dossier -> liste) -- bouton discret plutôt
   qu'un simple lien texte souligné, cohérent avec .btn-secondary mais
   plus compact et sans bordure d'accent par défaut (action secondaire
   de navigation, pas une action de formulaire). */
.btn-back {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.45rem 0.9rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg-card-muted);
  color: var(--text);
  font-size: 0.85rem;
  font-weight: 600;
  text-decoration: none;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.btn-back:hover {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-hover);
}
.btn-back svg {
  width: 1rem;
  height: 1rem;
  display: block;
}

.table-wrap {
  overflow-x: auto;
}

.table {
  width: 100%;
  min-width: 720px;
  /* "separate" + border-spacing:0 plutôt que "collapse" : rendu visuel
     identique ici (seul border-bottom est utilisé sur les cellules, pas
     de bordures verticales à fusionner), mais "collapse" empêche
     position:sticky de fonctionner sur les <th>/<td> dans les navigateurs
     à base Chromium/WebKit -- l'en-tête sticky de la liste des dossiers
     restait figé à sa position statique au lieu de se coller en haut. */
  border-collapse: separate;
  border-spacing: 0;
}

.table th, .table td {
  text-align: left;
  padding: 0.8rem 0.95rem;
  border-bottom: 1px solid var(--border);
  font-size: 0.88rem;
  vertical-align: middle;
}

/* Hauteur de ligne uniforme, indépendante du contenu (nom d'entreprise
   long, intitulé de formation long...) -- combinée à la troncature
   .col-entreprise/.col-formation ci-dessous pour empêcher un retour à
   la ligne qui ferait dépasser cette hauteur. Scopé à .table-rows-fixed
   plutôt qu'à .table globalement : les tableaux plus denses (documents,
   import) gardent leur hauteur naturelle, plus compacte. */
.table-rows-fixed tbody tr {
  height: 56px;
}
/* Toute colonne peut se retrouver trop étroite selon la largeur d'écran
   (ex: "Date formation") -- interdit le retour à la ligne partout dans
   ces tableaux, pas seulement sur les colonnes tronquées ci-dessous,
   pour garantir les 56px quel que soit le contenu. */
.table-rows-fixed td {
  white-space: nowrap;
}
/* Police et padding resserrés sur ces tableaux (Dossiers, Formateurs,
   Formations) uniquement -- pas le reste de l'appli -- pour que les
   nombreuses colonnes numériques (Montant, Prix, Commission, Bénéfice,
   Perçu) prennent moins de place et que le tableau tienne dans la
   largeur de .main (1360px) sans scroll sur un écran standard. */
.table-rows-fixed {
  font-size: 0.8rem;
}
.table-rows-fixed th,
.table-rows-fixed td {
  padding: 0.45rem 0.4rem;
}
.table-rows-fixed .badge {
  padding: 0.2rem 0.5rem;
  font-size: 0.72rem;
}

/* Colonnes à largeur plafonnée avec troncature "..." -- le nom complet
   reste consultable via l'attribut title (posé côté template) plutôt
   que perdu. Sert de largeur par défaut (avant tout redimensionnement
   manuel, cf. table-resize.js) sur la liste des dossiers, et de largeur
   fixe sur les tableaux non redimensionnables qui réutilisent ces
   classes (ex: la mini-table Brouillons de cette même page). */
.col-entreprise {
  max-width: 190px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.col-formation {
  max-width: 210px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.col-formateur-nom {
  max-width: 100px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
/* Dans un tableau redimensionnable, la largeur réelle de la colonne
   (posée en style inline sur le <th>, propagée par table-layout:fixed)
   doit gouverner la troncature -- pas ce max-width fixe, sinon élargir
   la colonne à la souris n'afficherait jamais plus de texte. */
.table-resizable .col-entreprise,
.table-resizable .col-formation,
.table-resizable .col-formateur-nom {
  max-width: none;
}

.table th {
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  background: var(--bg-card);
}

/* .table-wrap a overflow-x:auto -- même en fixant overflow-y à "visible"
   explicitement, la spec CSS Overflow force quand même overflow-y à se
   comporter comme "auto" dès que overflow-x n'est pas "visible" (un axe
   non-visible entraîne l'autre). Ça fait de .table-wrap le conteneur
   défilant de référence pour position:sticky au lieu de la fenêtre --
   comme il ne défile jamais lui-même verticalement (aucune hauteur
   contrainte), le <th> sticky ne s'accrochait donc jamais réellement, il
   suivait le flux normal en restant décalé de `top`. Seule solution
   fiable : ne PAS créer de conteneur défilant du tout ici (overflow
   visible sur les deux axes) -- scope .table-wrap-sticky uniquement, pas
   .table-wrap globalement, pour ne pas toucher le défilement horizontal
   des autres tableaux de l'appli (page Import notamment). Sur cette
   liste, la table reste dans la largeur de la page dans la plupart des
   cas (voir la réduction de police/padding de .table-rows-fixed
   ci-dessus, dimensionnée pour tenir dans .main sans déborder sur un
   écran standard). Sur un très petit écran où ça ne suffirait plus, le
   filet de sécurité ci-dessous reprend un vrai overflow-x:auto -- l'en-
   tête perd alors son effet sticky (sacrifié uniquement en dessous de
   ce seuil), mais la table défile localement au lieu d'emporter toute
   la page (topbar/nav compris) dans un défilement horizontal. */
.table-wrap-sticky {
  overflow: visible;
}

/* En-tête figé pendant le défilement d'une longue liste (ex: dossiers) --
   décalé sous le bloc filtres+totaux sticky (.dossiers-sticky-top), dont
   la hauteur variable selon la largeur d'écran est mesurée en JS et
   posée dans --sticky-filters-height (cf. dossiers-list.js). */
.table-wrap-sticky .table th {
  position: sticky;
  top: var(--sticky-filters-height, 0px);
  z-index: 1;
  box-shadow: 0 1px 0 var(--border);
}

@media (max-width: 900px) {
  .table-wrap-sticky {
    overflow-x: auto;
  }
  /* L'en-tête stickait alors par rapport à .table-wrap-sticky lui-même
     (nouveau conteneur défilant) plutôt qu'à la fenêtre, ce qui le
     faisait flotter au milieu de la page au lieu de rester en haut --
     désactivé proprement plutôt que de laisser cet effet parasite. Ce
     bloc doit rester APRÈS la règle .table-wrap-sticky .table th
     ci-dessus : même sélecteur, même spécificité, seul l'ordre dans la
     feuille de style tranche. */
  .table-wrap-sticky .table th {
    position: static;
  }
}

/* Filtres + totaux figés ensemble en haut de la liste des dossiers
   pendant le défilement, juste au-dessus de l'en-tête du tableau. */
.dossiers-sticky-top {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--bg-page);
  padding: 0.75rem 0;
}

/* CA acquis (dossier avec formateur + prix connus, donc bénéfice
   calculable) vs CA prévisionnel (formateur ou prix pas encore connu,
   bénéfice non calculable) -- cf. app/routes.py, boucle de calcul
   total_ca_acquis/total_ca_previsionnel/total_benefices. Le bénéfice est
   imbriqué visuellement dans la carte "acquis" (flèche "↳") plutôt
   qu'affiché comme un troisième chiffre indépendant, pour montrer qu'il
   en découle et n'est jamais calculé sur le prévisionnel. Couleurs
   alignées sur les badges de statut existants (vert = acquis/soldé,
   ambre = en attente).*/
.stats-grid {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: 0.6rem;
  margin-bottom: 0.4rem;
}

.stat-card {
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  padding: 0.55rem 0.85rem;
  box-shadow: var(--shadow-sm);
}

.stat-card--acquis {
  background: #f0faf3;
  border-left: 4px solid #4ade80;
}

.stat-card--previsionnel {
  background: #fdf6ee;
  border-left: 4px solid #fbd3a1;
  opacity: 0.92;
}

.stat-label {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.65rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 0.1rem;
}

.stat-card--acquis .stat-label { color: #14532d; }
.stat-card--previsionnel .stat-label { color: #9a3412; }

.stat-dot { width: 6px; height: 6px; border-radius: 50%; display: inline-block; }
.stat-card--acquis .stat-dot { background: #4ade80; }
.stat-card--previsionnel .stat-dot { background: #f7bd7a; }

.stat-value {
  font-size: 1.2rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--text);
  line-height: 1.1;
}

.stat-sub { font-size: 0.7rem; color: var(--muted); margin-top: 0.1rem; }

.stat-divider {
  border: none;
  border-top: 1px dashed rgba(20, 83, 45, 0.25);
  margin: 0.4rem 0 0.35rem;
}

.stat-benefice-row { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }
.stat-benefice-label { display: flex; align-items: baseline; gap: 0.35rem; font-size: 0.72rem; font-weight: 700; color: var(--accent-hover); }
.stat-benefice-arrow { color: #14532d; opacity: 0.55; font-weight: 400; }
.stat-benefice-value { font-size: 0.98rem; font-weight: 800; color: var(--accent-hover); font-variant-numeric: tabular-nums; }
.stat-benefice-note { font-size: 0.66rem; color: var(--muted); margin-top: 0.05rem; }

.stat-previsionnel-note {
  display: flex;
  gap: 0.35rem;
  align-items: flex-start;
  font-size: 0.68rem;
  color: #9a3412;
  background: rgba(251, 211, 161, 0.35);
  border-radius: var(--radius-sm);
  padding: 0.3rem 0.5rem;
  margin-top: 0.4rem;
}

.grand-total {
  text-align: right;
  font-size: 0.72rem;
  color: var(--muted);
  padding: 0 0.2rem;
  margin-bottom: 0.6rem;
}
.grand-total strong { color: var(--text); font-variant-numeric: tabular-nums; }

@media (max-width: 640px) {
  .stats-grid { grid-template-columns: 1fr; }
}

/* Commission non applicable (seul le commercial "Yassine" en perçoit une) --
   fond neutre pour distinguer visuellement "sans objet" d'une valeur
   simplement absente. */
.cell-na {
  background: repeating-linear-gradient(135deg, #ded8cd, #ded8cd 5px, #d0c9bc 5px, #d0c9bc 10px) !important;
}

.table select, .table input[type="text"] {
  max-width: 100%;
}

/* Tableaux à colonnes redimensionnables à la souris (page Import) :
   largeurs fixes pour que le glisser-déposer sur l'en-tête tienne, le
   tableau peut dépasser son conteneur (scroll horizontal dans .table-wrap)
   plutôt que d'écraser les colonnes voisines. */
.table-resizable {
  table-layout: fixed;
}

.table-resizable th {
  position: relative;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.table-resizable td {
  overflow: hidden;
  overflow-wrap: break-word;
}

.col-resize-handle {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 10px;
  cursor: col-resize;
  user-select: none;
  touch-action: none;
}

/* Bordure fine toujours visible sur le bord droit de l'en-tête, pour
   repérer la zone de redimensionnement avant même de la survoler. */
.col-resize-handle::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  width: 3px;
  background: var(--muted);
  opacity: 0.4;
}

.col-resize-handle:hover::after,
.col-resize-handle.is-resizing::after {
  background: var(--accent);
  opacity: 1;
}

.col-fichier {
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* Import groupé (page /import, cf. app/scan.py) -- bouton "Importer la
   sélection" à côté de "Tout cocher / tout décocher", au-dessus des
   tableaux plutôt que répété par section (une seule sélection couvre
   toutes les sections, cf. app/static/scan-select.js). */
.scan-actions-groupe {
  display: flex;
  gap: 0.6rem;
  align-items: center;
  margin-top: 0.75rem;
}
.scan-actions-groupe form {
  display: inline;
}
.table-resizable td:first-child,
.table-resizable th:first-child {
  width: 2rem;
  text-align: center;
}

.col-detail {
  overflow-wrap: break-word;
}

.col-formations {
  max-width: 320px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* Zébrage subtil pour la lisibilité des longues listes -- appliqué au
   fond des cellules (les lignes elles-mêmes n'ont pas de fond propre),
   contourné par .row-brouillon et les lignes déjà colorées (badges de
   cellule) grâce à !important sur ces cas particuliers. */
.table tbody tr:nth-child(even) td {
  background: var(--bg-card-muted);
}

.table tbody tr[onclick] { cursor: pointer; }

/* Survol des lignes cliquables : léger changement de fond + transition
   douce. La règle précédente (background: var(--bg-card)) était un
   no-op visuel car --bg-card correspond déjà au fond par défaut des
   lignes -- corrigé ici avec une teinte ambre douce, cohérente avec la
   palette d'accent, et une spécificité qui l'emporte sur le zébrage. */
.table tbody tr[onclick] td {
  transition: background-color 0.15s ease;
}
.table tbody tr[onclick]:hover td {
  background: var(--accent-soft);
}

/* Dossiers brouillon (cf. app/email_sending.py::recalculer_brouillon) --
   ligne entière en gris foncé pour les distinguer visuellement des
   dossiers actifs, section séparée en haut de la liste. */
.row-brouillon,
.row-brouillon td {
  background: #3f3f46 !important;
  color: #e4e4e7;
}
.row-brouillon:hover td { background: #52525b !important; }
.table-brouillons-titre {
  font-weight: 600;
  font-size: 0.85rem;
  color: var(--muted);
  margin: 0 0 0.4rem 0;
}

.sort-link {
  color: inherit;
  text-decoration: none;
  white-space: nowrap;
}
.sort-link:hover { text-decoration: underline; }
.sort-active { color: var(--accent); }

.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.3em;
  padding: 0.28rem 0.7rem;
  border-radius: 7px;
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  white-space: nowrap;
  background: #e5e7eb;
}

/* Badges de statut -- une petite icône texte (pas d'emoji, rendu stable
   dans currentColor) accompagne systématiquement le libellé plutôt
   qu'une simple pastille de couleur. Familles de couleurs plus
   saturées et distinctes : tons chauds ambre/brun pour les étapes
   d'attente (dégradé du plus clair au plus soutenu selon l'avancement),
   vert franc pour terminé/facturé/réglé, rouge vif pour à vérifier. */
.badge-en_attente_opco::before { content: "◷"; }
.badge-en_attente_opco { background: #fde4c8; color: #9a3412; }

.badge-en_attente_formateur::before { content: "◔"; }
.badge-en_attente_formateur { background: #fbd3a1; color: #92400e; }

.badge-en_attente_date_formation::before { content: "◑"; }
.badge-en_attente_date_formation { background: #f7bd7a; color: #7c2d12; }

.badge-en_attente_realisation::before { content: "◕"; }
.badge-en_attente_realisation { background: #f3a35a; color: #7c2d12; }

.badge-a_verifier::before { content: "!"; font-weight: 900; }
.badge-a_verifier { background: #fecaca; color: #b91c1c; }

.badge-termine::before { content: "✓"; }
.badge-termine { background: #bbf7d0; color: #166534; }

.badge-facture::before { content: "€"; }
.badge-facture { background: #86efac; color: #14532d; }

.badge-regle::before { content: "✔"; }
.badge-regle { background: #4ade80; color: #14532d; }

.badge-brouillon::before { content: "✏"; }
.badge-brouillon { background: #475569; color: #f1f5f9; }

.badge-doc-manquant::before { content: "✕"; }
.badge-doc-manquant { background: #fecaca; color: #b91c1c; }

.badge-doc-vierge_envoye::before { content: "→"; }
.badge-doc-vierge_envoye { background: #fde4c8; color: #9a3412; }

.badge-doc-recu_rempli::before { content: "✓"; }
.badge-doc-recu_rempli { background: #bbf7d0; color: #166534; }

.badge-absent::before { content: "✕"; }
.badge-absent { background: #e4e4e9; color: #8c8c9c; }

.grid-2 {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1rem;
  margin-bottom: 1rem;
}

.card-span {
  grid-column: 1 / -1;
}

.field-row {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 0.6rem;
  margin-bottom: 0.6rem;
}

/* Les deux champs "Remarques" (call center / commercial, cf.
   dossier_detail.html) côte à côte à parts égales plutôt que dans la
   grille auto-fill (qui leur donnerait une colonne étroite chacun) --
   et assez hautes pour lire le contenu sans avoir à faire défiler. */
.field-row-remarques {
  grid-template-columns: 1fr 1fr;
}
.field-row-remarques textarea {
  min-height: 9rem;
}

textarea {
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 0.9rem;
  line-height: 1.5;
  font-family: inherit;
  resize: vertical;
}

.card {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.5rem 1.65rem;
  background: var(--bg-card);
  box-shadow: var(--shadow-sm);
  margin-bottom: 1.5rem;
}

/* En-tête de section : bordure colorée à gauche + fond légèrement
   teinté qui s'estompe, pour que chaque carte se lise comme une
   section distincte plutôt qu'un mur de champs uniforme. Ciblé sur le
   premier h2 d'une carte (titre de section), pas les h2 isolés
   ailleurs dans la page. */
.card > h2:first-child {
  border-left: 3px solid var(--accent);
  padding: 0.3rem 0 0.3rem 0.85rem;
  margin: -0.15rem 0 1.2rem -0.1rem;
  background: linear-gradient(90deg, var(--accent-soft), transparent 75%);
  border-radius: 0 8px 8px 0;
}
.card-danger > h2:first-child {
  border-left-color: #ef4444;
  background: linear-gradient(90deg, #fee2e2, transparent 75%);
}

dl { margin: 0; }
dt { color: var(--muted); font-size: 0.78rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em; margin-top: 0.6rem; }
dd { margin: 0; font-size: 0.95rem; }

.statuts-form { display: flex; flex-direction: column; gap: 0.5rem; }
.checkbox { display: flex; align-items: center; gap: 0.4rem; font-size: 0.92rem; }
/* L'attribut natif [hidden] (display:none du user-agent stylesheet, très
   faible spécificité) se fait silencieusement écraser par toute règle de
   classe posant son propre "display" -- repéré en conditions réelles sur
   .field ci-dessous (display:flex), qui rendait un bloc masqué par
   [hidden] quand même visible. Règle générale explicite plutôt qu'un
   correctif ponctuel : protège tout usage futur de [hidden], quelle que
   soit la classe portée par l'élément. */
[hidden] { display: none !important; }

.field { display: flex; flex-direction: column; gap: 0.25rem; margin: 0.4rem 0; position: relative; }
.field label { font-size: 0.8rem; color: var(--muted); white-space: nowrap; }

/* Champ obligatoire (étoile rouge, cf. macros.requis_star) encore vide.
   Le pavé orange précédent (fond + bordure + décalage de padding) était
   trop lourd et déformait l'alignement de la ligne : l'étoile rouge du
   libellé suffit à signaler ce qui reste à remplir. Le sélecteur est
   conservé -- il reste posé/retiré dynamiquement par la page et sert de
   point d'accroche -- mais ne change plus l'apparence du champ. */
.field-manquant {
  background: none;
  border: none;
  padding: 0;
}

.doc-form { display: flex; gap: 0.4rem; align-items: center; flex-wrap: wrap; }

/* Cellule "Fichier" du tableau Documents (fiche dossier) : icône ouvrir /
   sélecteur de fichier / bouton final doivent tomber sur la même position
   horizontale d'une ligne à l'autre, quel que soit le contenu réellement
   présent (pas de fichier, pas de bouton de génération, etc.) -- chaque
   emplacement a donc une largeur fixe et reste dans le flux même vide,
   plutôt que d'être conditionnellement omis. */
.doc-action-cell,
.doc-action-cell form {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.doc-slot-icon {
  flex: 0 0 2rem;
  width: 2rem;
  height: 2rem;
}

.doc-slot-badge {
  flex: 0 0 90px;
  width: 90px;
}

.doc-slot-fichier {
  flex: 0 0 160px;
  width: 160px;
  overflow: hidden;
}

.doc-slot-fichier .file-input-wrap {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.15rem;
  width: 100%;
}

.doc-slot-fichier .file-input-name {
  max-width: 100%;
}

.doc-slot-bouton {
  flex: 0 0 100px;
  width: 100px;
}

.doc-slot-bouton button {
  width: 100%;
  text-align: center;
  white-space: nowrap;
}

.doc-type-block { margin-bottom: 1.5rem; }
.doc-type-block:last-child { margin-bottom: 0; }
.doc-type-block h3 { font-size: 0.95rem; margin-bottom: 0.4rem; }

.doc-compact-table td { vertical-align: middle; }

/* Documents Qualiopi -- table-layout fixed + <colgroup> (dans le
   template) pour un alignement cohérent entre CV / NDA / Kbis / etc.
   malgré des libellés de longueurs différentes -- un <colgroup> explicite
   est nécessaire plutôt que nth-child seul : une ligne "Manquant" a un
   colspan sur ses 2 dernières colonnes, et c'est la seule ligne de sa
   table, ce qui fausse le calcul de largeur en fixed-layout sans lui. */
.doc-compact-table {
  table-layout: fixed;
}
.doc-compact-table td:nth-child(4) { text-align: center; }

/* Documents de dossier (fiche dossier) -- même logique de colgroup fixe
   que .doc-compact-table, pour que Type/Stagiaire/Statut/Date/Fichier
   restent alignés malgré des lignes de contenu très différent (document
   reçu, manquant, ligne de formulaire d'ajout avec colspan). */
.doc-dossier-table {
  table-layout: fixed;
}
.doc-dossier-table td { vertical-align: top; padding-top: 0.6rem; }

/* Colonnes Ajouter/Générer/Supprimer : un formulaire par colonne plutôt
   qu'un seul bloc conditionnel -- Ajouter reste toujours cliquable même
   quand Générer existe aussi sur la même ligne (cf. Étape 6 bis pt.4),
   sans jamais se chevaucher (pt.3) puisque chacun a sa propre cellule. */
.doc-ajouter-form {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
}

/* Bloc "Ajouter un autre document" -- séparé visuellement du tableau des
   documents déjà présents (fond légèrement teinté + bordure + marge),
   plutôt qu'une ligne de formulaire vide intégrée au tableau : une fois
   qu'un fichier est envoyé, il rejoint le tableau principal comme une
   ligne normale (cf. dossier_detail.html), seul ce bloc-ci reste
   toujours vide et disponible pour l'ajout suivant. */
.doc-autre-ajout {
  margin-top: 1.1rem;
  padding: 0.9rem 1rem;
  background: var(--bg-card-muted);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.doc-autre-ajout h3 {
  margin-bottom: 0.2rem;
}
.doc-autre-ajout > p.muted {
  margin-top: 0;
  margin-bottom: 0.7rem;
}

/* "Inclus dans" (cf. Étape 6 ter pt.8, harmonisé ensuite) : à l'état
   "manquant", une simple icône lien à côté du badge ouvre le petit menu
   de sélection (rien de permanent à l'écran tant qu'on ne clique pas).
   Une fois marqué inclus, la ligne prend exactement la même apparence
   qu'un document réellement reçu -- badge "Reçu" vert identique, croix
   de suppression au même emplacement/style (qui dissocie l'inclusion
   plutôt que de supprimer un fichier) -- seule la petite mention en
   dessous du badge indique qu'il s'agit d'une inclusion et pas d'un
   fichier propre à cette ligne. */
.doc-statut-badge-icone {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
}
.doc-inclus-toggle {
  width: 1.6rem;
  height: 1.6rem;
  font-size: 0.85rem;
}

/* Cellule statut du tableau Documents : alignée en haut plutôt qu'au
   centre (défaut .table td) -- avec .doc-inclus-mention ci-dessous, une
   mention longue ("Inclus dans autre document - Feuille d'émargement")
   passant sur plusieurs lignes agrandit la cellule et recentrait alors le
   badge "Reçu"/"Manquant" plus bas, le désalignant des badges des autres
   lignes du tableau dont la mention est courte ou absente. */
.col-statut-doc {
  vertical-align: top;
}

.doc-inclus-mention {
  margin-top: 0.2rem;
  font-size: 0.74rem;
  color: var(--muted);
}
.doc-inclus-mention a {
  color: inherit;
}
.doc-inclus-mention a:hover {
  color: var(--accent);
}

/* Panneau "supprimer (tapez oui)" / "marquer comme incluse" -- replié
   par défaut (attribut [hidden]), affiché en place sous son bouton
   plutôt qu'en modale (cf. app/static/doc-table.js). */
.confirm-panel-inline {
  margin-top: 0.5rem;
  padding: 0.6rem;
  background: var(--bg-card-muted);
  border-radius: var(--radius-sm);
  max-width: 260px;
}
.confirm-panel-inline p {
  margin: 0 0 0.4rem;
  font-size: 0.85rem;
}
.confirm-panel-inline label {
  display: block;
  font-size: 0.78rem;
  color: var(--muted);
  margin-bottom: 0.3rem;
}
.confirm-panel-inline input[type="text"],
.confirm-panel-inline select {
  width: 100%;
  margin-bottom: 0.4rem;
}
.confirm-panel-inline .confirm-oui-submit:disabled {
  opacity: 0.5;
}


/* Bouton icône (ex: "ouvrir" un document) -- même gabarit que les
   boutons texte voisins, fond/bordure au survol plutôt qu'un lien souligné. */
.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: #fff;
  color: var(--muted);
  text-decoration: none;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.btn-icon:hover {
  background: var(--bg-card);
  border-color: var(--accent);
  color: var(--accent);
}
.btn-icon svg { width: 1.05rem; height: 1.05rem; display: block; }

/* Bouton "danger" (croix de suppression d'un document) -- teinté en
   rouge en permanence (pas seulement au survol comme .btn-icon de
   base) pour rester nettement identifiable même à côté d'autres
   boutons de la même ligne (ex. "Générer"), plutôt que de se fondre
   dans le même gris neutre que "ouvrir le document". Marge à gauche
   pour l'écarter visuellement de la colonne précédente. */
.btn-icon-danger {
  border-color: #fecaca;
  background: #fef2f2;
  color: #b91c1c;
  margin-left: 0.5rem;
}
.btn-icon-danger:hover {
  background: #fee2e2;
  border-color: #b91c1c;
  color: #991b1b;
}

/* Sélecteur de fichier stylé -- masque l'input natif (et son "Aucun
   fichier choisi") au profit d'un bouton cohérent avec le reste du CRM ;
   le nom du fichier choisi s'affiche seulement une fois sélectionné. */
.file-input-wrap {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}
.file-input-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.file-input-label {
  cursor: pointer;
  white-space: nowrap;
}
.file-input-name {
  font-size: 0.8rem;
  color: var(--muted);
  max-width: 100px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.btn-inline-danger {
  background: none;
  border: none;
  color: #991b1b;
  padding: 0;
  font-size: 0.82rem;
  text-decoration: underline;
  cursor: pointer;
}

/* Bouton "Publier sur le site" (fiche formation, envoi WordPress) --
   vert plutôt que la couleur d'accent, pour distinguer nettement l'action
   irréversible-en-pratique (mise en ligne publique) du bouton "brouillon"
   juste à côté. */
.btn-publier {
  background: #166534;
  border-color: #166534;
}
.btn-publier:hover {
  background: #14532d;
  border-color: #14532d;
}

/* Section "Stagiaires / Salariés" -- une ligne = un petit formulaire
   autosave (6 champs + croix de suppression), même gabarit de champ
   que .field-row mais avec le bouton croix en largeur fixe à la fin
   plutôt que dans la grille auto-fill (resterait minuscule sinon).
   flex-wrap : passe sur 2 lignes de champs en dessous d'une certaine
   largeur plutôt que de forcer un défilement horizontal (6 champs ne
   tiennent pas tous sur une seule ligne en dessous d'un écran large). */
.salarie-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.6rem;
  margin-bottom: 0.6rem;
}
.salarie-row .field {
  flex: 1 1 160px;
  min-width: 0;
}
/* La croix de suppression doit s'aligner sur le BAS des champs de saisie,
   pas sur le bas de la ligne : .field porte une marge verticale de 0.4rem
   (cf. `.field { margin: 0.4rem 0 }`), et align-items: flex-end aligne les
   boîtes de marge -- sans marge basse équivalente, le bouton descend donc
   de 0.4rem sous le dernier champ (la date de naissance). */
.salarie-supprimer {
  flex: 0 0 auto;
  color: #991b1b;
  margin-bottom: 0.4rem;
}
.salarie-supprimer:hover {
  background: #fef2f2;
  border-color: #991b1b;
  color: #991b1b;
}

.doc-alerte {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  font-size: 0.78rem;
  color: #92400e;
  font-weight: normal;
  margin-top: 0.15rem;
}
.btn-alerte-valider {
  flex: 0 0 auto;
  padding: 0.25rem 0.65rem;
  font-size: 0.75rem;
}

/* Alerte de génération Fiche RDV (cf. dossier_detail.html) : dans la
   colonne étroite "Générer" du tableau Documents -- sans largeur propre,
   le texte se retrouvait à un mot par ligne (6+ lignes). Une largeur
   minimale force le tableau (overflow-x:auto, cf. .table-wrap) à
   allouer plus de place à cette colonne plutôt que de laisser le texte
   s'écraser, et une police légèrement réduite tient le message sur 2
   lignes maximum. */
.doc-alerte-generation {
  display: block;
  min-width: 150px;
  max-width: 170px;
  font-size: 0.68rem;
  line-height: 1.3;
}

.formations-checklist {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 0.35rem;
  max-height: 20rem;
  overflow-y: auto;
  padding: 0.6rem;
  margin-bottom: 0.75rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.formations-checklist .checkbox {
  align-items: flex-start;
}

.formations-checklist-compact .checkbox {
  font-size: 0.78rem;
}

/* Sélecteur de formations en menu déroulant (cf. macros.html::
   formations_select) -- le panneau replié réutilise le même style que
   .formations-checklist, juste dans un .confirm-panel-inline replié
   par défaut plutôt que toujours à l'écran. */
.formations-select {
  margin-bottom: 0.75rem;
}
.formations-panel {
  max-width: none;
}
.formations-checklist-scroll {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  max-height: 16rem;
  overflow-y: auto;
  /* Barre de scroll personnalisée, visible en permanence (pas seulement
     au survol -- contrairement aux barres "overlay" par défaut de macOS/
     certains navigateurs) : plus fiable qu'une ombre en dégradé pour
     signaler qu'il reste des formations à voir plus bas dans la liste.
     Firefox (scrollbar-width/-color) + navigateurs Chromium/WebKit
     (::-webkit-scrollbar) ci-dessous. */
  scrollbar-width: thin;
  scrollbar-color: var(--accent) var(--bg-card-muted);
}
.formations-checklist-scroll::-webkit-scrollbar {
  width: 8px;
}
.formations-checklist-scroll::-webkit-scrollbar-track {
  background: var(--bg-card-muted);
  border-radius: 4px;
}
.formations-checklist-scroll::-webkit-scrollbar-thumb {
  background-color: var(--accent);
  border-radius: 4px;
}
.formations-checklist-scroll::-webkit-scrollbar-thumb:hover {
  background-color: var(--accent-hover);
}
.formations-checklist-scroll .checkbox {
  align-items: flex-start;
  font-size: 0.85rem;
  text-transform: uppercase;
}

.commentaire {
  white-space: pre-wrap;
  font-family: inherit;
  font-size: 0.92rem;
  margin: 0;
}

.flashes { margin-bottom: 1.25rem; }
.flash {
  padding: 0.65rem 1rem;
  border-radius: var(--radius-sm);
  border-left: 3px solid transparent;
  margin-bottom: 0.5rem;
  font-size: 0.9rem;
  font-weight: 500;
  box-shadow: var(--shadow-sm);
}
.flash-success { background: #d1fae5; color: #065f46; border-left-color: #10b981; }
.flash-error { background: #fee2e2; color: #991b1b; border-left-color: #ef4444; }
.flash-warning { background: #fef3c7; color: #92400e; border-left-color: #f59e0b; }

/* Bannière live des champs manquants pour la Fiche RDV (cf.
   dossier_detail.html) -- liste à puces plutôt qu'une phrase, pour que
   chaque élément disparaisse individuellement au fil de la saisie. */
#banniere-champs-manquants-fiche-rdv ul {
  margin: 0.35rem 0 0;
  padding-left: 1.25rem;
}
#banniere-champs-manquants-fiche-rdv li {
  margin-bottom: 0.15rem;
}

.banner-archive {
  background: var(--accent-soft);
  border-color: #fcd34d;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

.card-danger {
  border-color: #fca5a5;
}

.card-danger h2 { color: #991b1b; }

#btn-supprimer-toggle {
  background: #fff;
  color: #991b1b;
  border-color: #fca5a5;
}

.confirm-panel {
  margin-top: 0.75rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--border);
}

.confirm-panel label {
  display: block;
  font-size: 0.85rem;
  color: var(--muted);
  margin-bottom: 0.4rem;
  max-width: 40rem;
}

.confirm-panel input[type="text"] {
  margin-right: 0.5rem;
}

#btn-supprimer-submit:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.hidden { display: none !important; }

.email-corps-readonly {
  white-space: pre-wrap;
  word-break: break-word;
  font-family: inherit;
  background: var(--bg-alt, #f8fafc);
  padding: 0.75rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
}

.requis-star {
  color: #dc2626;
  font-weight: 700;
  margin-left: 0.15rem;
  cursor: help;
}

/* Indicateur d'erreur d'enregistrement automatique (cf.
   app/static/autosave.js) -- l'enregistrement réussi reste silencieux,
   seul un échec de validation s'affiche brièvement à côté du champ.
   Position absolute : ne déplace pas la mise en page, ne bloque jamais
   la saisie. */
.autosave-indicator {
  position: absolute;
  top: 0;
  right: 0;
  font-size: 0.75rem;
  font-weight: 600;
  color: #991b1b;
  background: #fee2e2;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}
.autosave-indicator-visible { opacity: 1; }

/* Sélecteur "Dates de formation" (cf. dates-formation.js) : champs date
   et mots de liaison ("et le", "et") resserrés sur une même ligne --
   flex avec un petit gap plutôt que la grille de .field-row (colonnes de
   160px mini, bien trop large pour un simple mot de liaison). */
.dates-formation-champs {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.35rem;
}
.dates-formation-champs .field {
  margin: 0;
}
.dates-formation-liaison {
  color: var(--muted);
  padding-bottom: 0.55rem;
  white-space: nowrap;
}
.dates-formation-champ-ligne {
  display: flex;
  align-items: center;
  gap: 0.25rem;
}

/* Message d'ordre chronologique invalide (cf. dates-formation.js::
   verifierOrdre) -- même palette rouge que .autosave-indicator, mais fixe
   (pas absolute/auto-masqué) : porte sur la relation entre plusieurs
   champs, pas sur un seul, donc doit rester visible tant que l'ordre
   n'est pas corrigé. */
.dates-formation-erreur {
  margin: 0.35rem 0 0;
  font-size: 0.8rem;
  font-weight: 600;
  color: #991b1b;
  background: #fee2e2;
  padding: 0.25rem 0.6rem;
  border-radius: 6px;
  display: inline-block;
}
.btn-supprimer-date {
  background: none;
  border: none;
  color: #991b1b;
  font-size: 1.1rem;
  line-height: 1;
  width: 1.3rem;
  height: 1.3rem;
  padding: 0;
  cursor: pointer;
  border-radius: 50%;
}
.btn-supprimer-date:hover:not(:disabled) {
  background: #fee2e2;
}
.btn-supprimer-date:disabled {
  color: var(--border);
  cursor: not-allowed;
}
#btn-ajouter-date {
  margin-top: 0.5rem;
}

/* Agenda (intégration Google Agenda en lecture seule, cf. app/agenda.py) */
.agenda-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.75rem;
}
.agenda-nav {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.agenda-legende {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 1rem;
}
.agenda-legende-item {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.82rem;
  color: var(--muted);
}
.agenda-legende-pastille {
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 50%;
  display: inline-block;
  flex: none;
}

.agenda-grille {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: 1.5rem;
}
/* Sans min-width:0 sur les cellules ci-dessous, un titre d'évènement non
   coupé (white-space:nowrap) fait grossir sa colonne au-delà de sa part
   de 1fr (min-width:auto par défaut = taille du contenu) -- la grille
   entière déborde alors du viewport, et l'overflow:hidden ci-dessus se
   contente de couper ce qui dépasse plutôt que de faire respecter la
   largeur des colonnes : concrètement, les colonnes de droite (samedi,
   dimanche) disparaissaient ou étaient tronquées. Avec min-width:0, les
   cellules acceptent de rétrécir sous leur contenu, qui se tronque en
   "..." (déjà géré par .agenda-evenement) au lieu de forcer la grille à
   déborder. */
.agenda-entete-jour {
  background: var(--bg-card);
  padding: 0.5rem;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  text-align: center;
  min-width: 0;
}
.agenda-jour {
  background: var(--bg-card);
  min-height: 112px;
  min-width: 0;
  padding: 0.4rem;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}
.agenda-jour-hors-mois {
  background: var(--bg-card-muted);
}
.agenda-jour-hors-mois .agenda-jour-numero {
  color: var(--border);
}
.agenda-jour-numero {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--muted);
  align-self: flex-start;
}
.agenda-jour-aujourdhui .agenda-jour-numero {
  color: #fff;
  background: var(--accent);
  width: 1.4rem;
  height: 1.4rem;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.75rem;
}
.agenda-evenement {
  display: block;
  font-size: 0.72rem;
  font-weight: 600;
  padding: 0.15rem 0.4rem;
  border-radius: 5px;
  color: #fff;
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: filter 0.1s ease;
}
.agenda-evenement:hover {
  filter: brightness(0.9);
}
@media (max-width: 900px) {
  .agenda-evenement {
    font-size: 0.66rem;
    padding: 0.1rem 0.3rem;
  }
  .agenda-jour-numero {
    font-size: 0.72rem;
  }
}

/* Formulaire d'édition d'un évènement (cf. agenda_evenement_edit.html) :
   Détails (titre/description) à gauche, colonne compacte "Aperçu" à
   droite (dates/heures + couleur) pour une vision d'ensemble du RDV en
   un coup d'œil. */
.agenda-evt-layout {
  display: grid;
  grid-template-columns: 1fr 310px;
  gap: 1.5rem;
  align-items: start;
}
@media (max-width: 800px) {
  .agenda-evt-layout {
    grid-template-columns: 1fr;
  }
}

.agenda-resume-compact .field {
  margin: 0;
}
.agenda-resume-compact .checkbox {
  font-size: 0.85rem;
  margin-bottom: 0.75rem;
}
.agenda-resume-ligne {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}
/* Largeurs minimales mesurées en conditions réelles (width:max-content
   sur les champs réels) : ~156px pour la date, ~75px pour l'heure --
   valeurs les plus compactes possibles qui affichent encore
   "JJ/MM/AAAA"/"HH:MM" en entier, avec une petite marge de sécurité.
   flex-wrap ci-dessus sert de filet si la colonne devient un jour plus
   étroite que ce total plutôt que de laisser le navigateur tronquer
   l'année. */
.agenda-resume-ligne .field {
  flex: 1 1 10rem;
  min-width: 10rem;
}
/* Sélecteur à deux classes -- .agenda-resume-champ-heure seul (une
   classe) avait une spécificité plus faible que .agenda-resume-ligne
   .field ci-dessus et se faisait donc écraser par sa largeur de champ
   date, quel que soit l'ordre dans le fichier : le champ heure prenait
   la même flex-basis que le champ date, doublant l'espace réellement
   nécessaire et forçant un retour à la ligne à des largeurs qui
   auraient dû suffire. */
.agenda-resume-ligne .agenda-resume-champ-heure {
  flex: 1 1 5rem;
  min-width: 5rem;
}
.agenda-resume-compact .agenda-couleur-select {
  max-width: none;
  margin-top: 0.6rem;
}

/* Pastille inline (titre de la fiche évènement + déclencheur/options du
   sélecteur de couleur) -- plus petite que .agenda-legende-pastille, un
   simple repère visuel à côté d'un texte. */
.agenda-couleur-pastille-inline {
  display: inline-block;
  width: 0.85rem;
  height: 0.85rem;
  border-radius: 50%;
  box-shadow: 0 0 0 1px var(--border);
  vertical-align: middle;
  flex: none;
}
.agenda-couleur-pastille-defaut {
  background: var(--bg-card);
  background-image: linear-gradient(45deg, transparent 46%, var(--muted) 46%, var(--muted) 54%, transparent 54%);
}

/* Sélecteur de couleur façon Google Agenda : bouton compact (pastille +
   nom + crayon) ouvrant un popup avec une grille de pastilles cliquables
   (2 rangées de 11 couleurs) et une option "Par défaut" en dessous. */
.agenda-couleur-select {
  position: relative;
  max-width: 20rem;
}
.agenda-couleur-select-trigger {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  width: 100%;
  padding: 0.5rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-card);
  color: var(--text);
  font-size: 0.85rem;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
}
.agenda-couleur-select-trigger:hover {
  border-color: var(--accent);
}
.agenda-couleur-select-trigger:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
#couleur-select-trigger-label {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.agenda-couleur-select-crayon {
  width: 0.95rem;
  height: 0.95rem;
  color: var(--muted);
  flex: none;
}

.agenda-couleur-popup {
  position: absolute;
  z-index: 5;
  top: calc(100% + 0.4rem);
  left: 0;
  width: 15rem;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  padding: 0.75rem;
}
.agenda-couleur-grille {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 0.5rem;
  margin-bottom: 0.65rem;
}
.agenda-couleur-swatch {
  position: relative;
  width: 1.9rem;
  height: 1.9rem;
  border-radius: 50%;
  border: 2px solid transparent;
  box-shadow: 0 0 0 1px var(--border);
  cursor: pointer;
  padding: 0;
  transition: transform 0.1s ease;
}
.agenda-couleur-swatch:hover {
  transform: scale(1.12);
}
.agenda-couleur-swatch-active {
  border-color: var(--bg-card);
  box-shadow: 0 0 0 2px var(--text);
}
.agenda-couleur-swatch-active::after {
  content: "✓";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 0.8rem;
  font-weight: 700;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
}
.agenda-couleur-defaut {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  width: 100%;
  padding: 0.5rem 0.4rem 0;
  border: none;
  border-top: 1px solid var(--border);
  background: none;
  font-size: 0.85rem;
  color: var(--text);
  text-align: left;
  cursor: pointer;
}
.agenda-couleur-defaut:hover {
  color: var(--accent);
}
.agenda-couleur-defaut-check {
  margin-left: auto;
  color: var(--accent);
  font-weight: 700;
  visibility: hidden;
}
.agenda-couleur-defaut-active .agenda-couleur-defaut-check {
  visibility: visible;
}

/* Fiche évènement : la couleur choisie (pastille du titre + bordure des
   en-têtes de carte) sert de repère visuel cohérent sur toute la fiche. */
#agenda-evt-theme .card > h2:first-child {
  border-left-color: var(--agenda-couleur-evt, var(--accent));
}

/* Lieu de l'évènement : affichage seul (pas de champ Google Agenda
   édité côté CRM), donc du texte simple plutôt qu'un input. */
.agenda-lieu-valeur {
  margin: 0;
  padding: 0.5rem 0.7rem;
  background: var(--bg-card-muted);
  border-radius: var(--radius-sm);
}

/* Bouton "Créer la fiche client" / badge une fois la fiche créée --
   même emplacement, l'un remplace l'autre selon l'état de l'évènement. */
.agenda-fiche-client-form {
  margin: 0.6rem 0 1.1rem;
}
.agenda-fiche-client-badge {
  display: inline-block;
  margin: 0.6rem 0 1.1rem;
  padding: 0.5rem 0.8rem;
  background: var(--bg-card-muted);
  border-radius: var(--radius-sm);
  font-weight: 600;
}

/* Sélecteur de vue Jour / Semaine / Mois */
.agenda-vues {
  display: flex;
  gap: 0.2rem;
  background: var(--bg-card-muted);
  padding: 0.2rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
}
.agenda-vue-bouton {
  padding: 0.35rem 0.85rem;
  border-radius: 6px;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--muted);
  text-decoration: none;
  transition: background-color 0.15s ease, color 0.15s ease;
}
.agenda-vue-bouton:hover {
  color: var(--text);
}
.agenda-vue-bouton-active {
  background: var(--bg-card);
  color: var(--accent);
  box-shadow: var(--shadow-sm);
}

.agenda-date-picker {
  width: auto;
  min-width: 11.5rem;
  flex-shrink: 0;
}

/* Grille horaire (vues Semaine et Jour) -- en-têtes de colonnes, bande
   "journée entière" et corps horaire (heures + évènements positionnés
   en pixels) partagent le même grid-template-columns (gouttière des
   heures + une colonne par jour) pour rester alignés verticalement. */
.agenda-horaire-wrap {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-card);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  margin-bottom: 1.5rem;
}
.agenda-horaire-entetes,
.agenda-horaire-journee-entiere {
  display: grid;
  border-bottom: 1px solid var(--border);
}
.agenda-horaire-entetes .agenda-entete-jour {
  padding: 0.65rem 0.4rem;
  background: var(--bg-card);
}
.agenda-entete-jour-aujourdhui {
  color: var(--accent);
}
.agenda-horaire-journee-entiere {
  padding: 0.3rem 0;
}
.agenda-horaire-gouttiere-label {
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  text-align: right;
  padding: 0.2rem 0.6rem 0 0;
}
.agenda-horaire-colonne-journee-entiere {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 0 4px;
  min-height: 1.6rem;
  min-width: 0;
}
.agenda-horaire-colonne-journee-entiere .agenda-evenement {
  position: static;
}

.agenda-horaire-corps-scroll {
  max-height: 70vh;
  overflow-y: auto;
}
.agenda-horaire-corps {
  display: grid;
  position: relative;
}
.agenda-horaire-gouttiere {
  position: relative;
  border-right: 1px solid var(--border);
  min-width: 0;
}
.agenda-horaire-heure-label {
  font-size: 0.68rem;
  color: var(--muted);
  text-align: right;
  padding-right: 0.6rem;
  box-sizing: border-box;
  transform: translateY(-0.6em);
}
.agenda-horaire-colonne {
  position: relative;
  border-right: 1px solid var(--border);
  min-width: 0;
}
.agenda-horaire-colonne:last-child {
  border-right: none;
}
.agenda-horaire-colonne-aujourdhui {
  background: var(--accent-soft);
}
.agenda-horaire-ligne {
  border-bottom: 1px solid var(--border);
  box-sizing: border-box;
}
.agenda-evenement-horaire {
  position: absolute;
  box-sizing: border-box;
  border-radius: 5px;
  padding: 0.2rem 0.4rem;
  color: #fff;
  font-size: 0.7rem;
  line-height: 1.3;
  overflow: hidden;
  text-decoration: none;
  border: 1px solid rgba(255, 255, 255, 0.35);
  transition: filter 0.1s ease;
}
.agenda-evenement-horaire:hover {
  filter: brightness(0.92);
  z-index: 2;
}
.agenda-evenement-horaire-heure {
  display: block;
  font-weight: 700;
  opacity: 0.9;
}
.agenda-evenement-horaire-titre {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Sous-navigation partagée par les 3 pages regroupées sous l'onglet
   "Outils" (Alertes / Archivés / Import), cf. _outils_sousnav.html. */
.outils-sousnav {
  display: flex;
  gap: 1.6rem;
  border-bottom: 1px solid var(--border);
  margin-bottom: 1.5rem;
}

.outils-sousnav a {
  padding: 0.65rem 0;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--muted);
  text-decoration: none;
  border-bottom: 2px solid transparent;
}

.outils-sousnav a.actif {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

.outils-sousnav a:hover {
  color: var(--accent);
}

/* Modale de confirmation générique (cf. app/static/signature-modal.js) --
   première modale (overlay centré) de l'app ; jusqu'ici les
   confirmations utilisaient .confirm-panel-inline (en place, sous le
   bouton), insuffisant ici où l'action a des conséquences (envoi d'un
   email à un tiers) qui justifient une interruption plus marquée. */
.overlay {
  position: fixed;
  inset: 0;
  background: rgba(23, 23, 31, 0.45);
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 50;
  padding: 1rem;
}
.overlay.ouvert { display: flex; }

.modale {
  background: var(--bg-card);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  max-width: 420px;
  width: 100%;
  padding: 1.6rem 1.75rem;
}
.modale h2 { font-size: 1.1rem; margin: 0 0 0.3rem; }
.modale-soustitre { font-size: 0.85rem; color: var(--muted); margin: 0 0 1.1rem; }
.modale-infos {
  margin: 0 0 1.4rem;
  background: var(--bg-card-muted);
  border-radius: var(--radius-sm);
  padding: 0.9rem 1.1rem;
}
.modale-infos dt { color: var(--muted); font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; margin-top: 0.55rem; }
.modale-infos dt:first-child { margin-top: 0; }
.modale-infos dd { margin: 0; font-size: 0.95rem; font-weight: 600; }
.modale-actions { display: flex; justify-content: flex-end; gap: 0.6rem; }

.btn-compact { font-size: 0.82rem; padding: 0.45rem 0.9rem; }

/* Bascule En attente / Signées -- cf. app/templates/signatures.html.
   Liens simples (pas de JS) : chaque état est une vraie URL (?vue=...),
   cohérent avec le reste des filtres de l'app (ex. filters-card). */
.filtre-toggle {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  margin-bottom: 1.25rem;
}
.filtre-toggle a {
  background: var(--bg-card);
  color: var(--muted);
  padding: 0.5rem 1.1rem;
  font-size: 0.85rem;
  font-weight: 600;
  text-decoration: none;
}
.filtre-toggle a.actif { background: var(--accent); color: #fff; }
.filtre-toggle a:not(.actif):hover { background: var(--bg-card-muted); }

.lien-preuves { color: var(--accent); font-size: 0.85rem; font-weight: 600; text-decoration: none; cursor: pointer; }
.lien-preuves:hover { text-decoration: underline; }

.panneau-preuves {
  background: var(--bg-card-muted);
  border-radius: var(--radius-sm);
  padding: 1rem 1.2rem;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.7rem 1.5rem;
}
.panneau-preuves dt { color: var(--muted); font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; margin: 0 0 0.15rem; }
.panneau-preuves dd { margin: 0; font-size: 0.85rem; font-variant-numeric: tabular-nums; word-break: break-all; }
.panneau-preuves dd.ua { font-size: 0.76rem; word-break: break-word; }
.panneau-preuves dd.hash { font-family: "SF Mono", Consolas, monospace; font-size: 0.76rem; }
.panneau-preuves-full { grid-column: 1 / -1; }

/* Page Trésorerie -- réutilise .stat-card/.stat-label/.stat-value/
   .stat-sub déjà en place pour le bloc CA acquis/prévisionnel de la
   liste Dossiers, pour un rendu cohérent entre les deux tableaux de
   bord de l'app. */
.stats-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 0.7rem; }
.stat-card.solde-qonto { background: linear-gradient(135deg, var(--accent-soft), var(--bg-card) 65%); border-left: 3px solid var(--accent); }
.pastille-live { width: 6px; height: 6px; border-radius: 50%; background: #4ade80; display: inline-block; box-shadow: 0 0 0 2px #f0faf3; }
.badge-qonto { background: #eff6ff; color: #1e40af; font-size: 0.68rem; font-weight: 700; padding: 0.15rem 0.45rem; border-radius: 5px; vertical-align: middle; }

/* Sélecteur de mois -- page Trésorerie */
.mois-nav { display: flex; align-items: center; gap: 0.75rem; background: var(--bg-card-muted); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 0.4rem 0.6rem; width: fit-content; margin-bottom: 1.25rem; }
.mois-nav a, .mois-nav span.mois-nav-disabled { color: var(--muted); font-size: 1rem; text-decoration: none; padding: 0.2rem 0.5rem; border-radius: 6px; }
.mois-nav a:hover { background: var(--border); color: var(--text); }
.mois-nav span.mois-nav-disabled { opacity: 0.3; }
.mois-nav .mois-label { font-weight: 700; font-size: 0.92rem; min-width: 110px; text-align: center; }

/* Graphique tendance recettes/dépenses -- barres SVG */
.chart-legende { display: flex; gap: 1.2rem; font-size: 0.78rem; color: var(--muted); margin-bottom: 0.9rem; }
.chart-legende span { display: inline-flex; align-items: center; gap: 0.35rem; }
.puce { width: 9px; height: 9px; border-radius: 2px; display: inline-block; }

/* Dépenses par catégorie / recettes par source */
.cat-liste { display: flex; flex-direction: column; gap: 0.55rem; }
.cat-ligne { display: grid; grid-template-columns: 150px 1fr 90px; align-items: center; gap: 0.6rem; font-size: 0.82rem; }
.cat-nom { color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cat-barre-fond { background: var(--bg-card-muted); border-radius: 5px; height: 8px; overflow: hidden; }
.cat-barre { height: 100%; border-radius: 5px; }
.cat-barre.depense { background: #f7bd7a; }
.cat-barre.recette { background: #4ade80; }
.cat-montant { text-align: right; font-variant-numeric: tabular-nums; font-weight: 600; }

/* Nom + avatar d'associé -- réutilisé par "Dépenses sur la société par
   associé" (Frais Maxime/Robin, cf. .assoc-carte plus bas). */
.cca-nom { font-weight: 700; font-size: 0.9rem; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.5rem; }
.avatar { width: 22px; height: 22px; border-radius: 50%; background: var(--accent); color: #fff; font-size: 0.7rem; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; }

/* TVA */
.tva-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.7rem; }
.tva-item { text-align: center; padding: 0.8rem 0.5rem; border-radius: var(--radius-sm); background: var(--bg-card-muted); }
.tva-item .stat-label { justify-content: center; }
.tva-item.solde-positif .stat-value { color: #14532d; }
.tva-item.solde-negatif .stat-value { color: #9a3412; }

@media (max-width: 900px) {
  .cca-grid, .tva-row { grid-template-columns: 1fr; }
}

/* Bascule Vue synthèse / Vue tableau -- page Trésorerie */
.vue-toggle { display: inline-flex; border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; margin-bottom: 1.25rem; }
.vue-toggle a { padding: 0.5rem 1.1rem; font-size: 0.85rem; font-weight: 600; text-decoration: none; color: var(--muted); background: var(--bg-card); }
.vue-toggle a.actif { background: var(--accent); color: #fff; }
.vue-toggle a:not(.actif):hover { background: var(--bg-card-muted); }

/* Pastille de couleur par catégorie -- marge à droite pour la détacher
   du nom (uniquement là où elle précède du texte en ligne ; .bplan-cat-nom
   gère déjà son propre espacement via flex+gap). */
.pastille { width: 9px; height: 9px; border-radius: 50%; display: inline-block; flex-shrink: 0; }
.cat-nom .pastille { margin-right: 0.45rem; }

/* Gestion des catégories (panneau repliable) */
.gerer-categories { font-size: 0.8rem; color: var(--accent); text-decoration: none; font-weight: 600; }
.categorie-creation { background: var(--bg-card-muted); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 0.8rem 0.9rem; margin-bottom: 1.1rem; }
.categorie-type-choix { display: inline-flex; align-items: center; gap: 0.35rem; font-size: 0.82rem; cursor: pointer; }
.categorie-type-choix input { accent-color: var(--accent); }
.categories-gestion-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; }
.categorie-gestion-ligne { display: flex; align-items: center; justify-content: space-between; padding: 0.35rem 0; border-bottom: 1px solid var(--border); font-size: 0.85rem; }
.categorie-gestion-ligne:last-child { border-bottom: none; }
.categorie-gestion-ligne form { display: inline; }
.categorie-gestion-ligne .cat-nom { cursor: pointer; }
.categorie-gestion-ligne .cat-nom input[type="checkbox"] { margin-right: 0.4rem; vertical-align: middle; }
.categories-supprimees { margin-top: 1.1rem; border-top: 1px dashed var(--border); padding-top: 0.8rem; }
.categorie-supprimee-ligne { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; padding: 0.4rem 0.6rem; background: var(--bg-card-muted); border-radius: var(--radius-sm); font-size: 0.82rem; color: var(--muted); margin-bottom: 0.3rem; }
.categorie-supprimee-hint { font-size: 0.68rem; background: var(--accent-soft); color: var(--accent-hover); padding: 0.15rem 0.55rem; border-radius: 999px; white-space: nowrap; }

/* Dépenses sur la société par associé (Frais Maxime/Robin) */
.assoc-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.assoc-carte { border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 1rem 1.1rem; background: var(--bg-card-muted); }
.assoc-total { font-size: 1.5rem; font-weight: 800; font-variant-numeric: tabular-nums; margin: 0.3rem 0 0.7rem; }
.assoc-mois-liste { display: flex; flex-direction: column; gap: 0.3rem; border-top: 1px dashed var(--border); padding-top: 0.6rem; }
.assoc-mois-ligne { display: flex; justify-content: space-between; font-size: 0.82rem; padding: 0.35rem 0.4rem; border-radius: 6px; cursor: pointer; }
.assoc-mois-ligne:hover { background: var(--bg-card); }
.assoc-mois-ligne .montant { font-weight: 600; font-variant-numeric: tabular-nums; }
.assoc-detail-panel { margin: 0.2rem 0 0.3rem; padding: 0.6rem 0.7rem; background: var(--bg-card); border-radius: var(--radius-sm); font-size: 0.78rem; }
.assoc-detail-panel .ligne { display: flex; justify-content: space-between; padding: 0.25rem 0; border-bottom: 1px solid var(--border); }
.assoc-detail-panel .ligne:last-child { border-bottom: none; }

/* Élargit Libellé/Montant (place disponible à droite du tableau,
   Catégorisation prend le reste) -- en layout auto (par défaut), les 3
   selects + icône de Catégorisation imposent leur largeur intrinsèque et
   ignorent toute largeur déclarée sur les autres colonnes ; passer en
   table-layout:fixed force le respect des largeurs ci-dessous (les
   selects de Catégorisation passent déjà à la ligne via .cat-select-wrap
   flex-wrap, donc une colonne plus étroite pour eux reste utilisable). */
.table-transactions { table-layout: fixed; }
.table-transactions th:nth-child(1), .table-transactions td:nth-child(1) { width: 100px; }
.table-transactions th:nth-child(2), .table-transactions td:nth-child(2) { width: 34%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.table-transactions th:nth-child(3), .table-transactions td:nth-child(3) { width: 150px; }

/* Catégorisation d'une transaction : select + icône commentaire */
.cat-select-wrap { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; }
.cat-select-wrap form { display: flex; gap: 0.4rem; flex-wrap: wrap; align-items: flex-start; }
/* Plusieurs factures possibles sur une même transaction : chips pour les
   dossiers déjà attachés (avec "×" pour retirer) + un select classique
   (fermé, une seule ligne) pour en ajouter un de plus -- pas un
   <select multiple>, dont le rendu en liste ouverte en permanence et le
   comportement de sélection au clic ne correspondent pas à l'usage
   attendu ici (cf. retour explicite). */
.dossier-multi { width: 230px; display: flex; flex-direction: column; gap: 0.3rem; }
.dossier-chips { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.dossier-chips:empty { display: none; }
.dossier-chip { display: inline-flex; align-items: center; gap: 0.3rem; background: var(--accent-soft); color: var(--accent-hover); border-radius: 999px; padding: 0.15rem 0.3rem 0.15rem 0.6rem; font-size: 0.74rem; font-weight: 600; }
.dossier-chip a { color: inherit; text-decoration: none; }
.dossier-chip a:hover { text-decoration: underline; }
.dossier-chip-retirer { background: none; border: none; cursor: pointer; color: inherit; font-size: 0.85rem; line-height: 1; padding: 0.1rem 0.3rem; border-radius: 50%; opacity: 0.7; }
.dossier-chip-retirer:hover { opacity: 1; background: rgba(0, 0, 0, 0.08); }
.select-dossier-ajouter { font-size: 0.78rem; width: 100%; }
.select-dossier-ajouter:disabled { color: var(--muted); }
.commentaire-icone { background: none; border: none; cursor: pointer; font-size: 0.85rem; opacity: 0.45; padding: 0.2rem; }
.commentaire-icone:hover { opacity: 1; }
.commentaire-texte { font-size: 0.76rem; color: var(--accent-hover); background: var(--accent-soft); border-radius: 6px; padding: 0.25rem 0.5rem; margin-top: 0.3rem; display: flex; align-items: center; gap: 0.4rem; }
.commentaire-modifier { cursor: pointer; margin-left: auto; opacity: 0.6; }
.commentaire-modifier:hover { opacity: 1; }

.commentaire-icone.justificatif-present { opacity: 1; position: relative; }
.justificatif-badge { background: var(--accent); color: #fff; font-size: 0.6rem; font-weight: 700; border-radius: 999px; padding: 0.05rem 0.35rem; margin-left: 0.15rem; vertical-align: top; }
.justificatif-ligne { display: flex; align-items: center; gap: 0.5rem; padding: 0.3rem 0; border-bottom: 1px solid var(--border); font-size: 0.82rem; }
.justificatif-ligne:last-of-type { border-bottom: none; }
.justificatif-ligne a { color: var(--accent-hover); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.justificatif-origine { font-size: 0.66rem; background: var(--bg-card-muted); color: var(--muted); padding: 0.1rem 0.4rem; border-radius: 999px; white-space: nowrap; }

/* Filtres de la vue tableau (granularité + période des colonnes) */
.bplan-filtres { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 0.75rem; margin-bottom: 1rem; }
.bplan-filtres-form { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }
.bplan-filtres-form label { display: flex; align-items: center; gap: 0.5rem; font-size: 0.82rem; color: var(--muted); font-weight: 600; }
.bplan-filtres-form select { font-size: 0.82rem; padding: 0.3rem 0.5rem; border-radius: 6px; border: 1px solid var(--border); background: var(--bg-card); color: var(--text); }

/* Barre "Masqué : [chips] · Tout réafficher" -- visible seulement s'il y
   a au moins une catégorie ou une colonne masquée dans la vue actuelle. */
.bplan-masquees { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 1rem; padding: 0.6rem 0.8rem; background: var(--bg-card-muted); border: 1px solid var(--border); border-radius: var(--radius-sm); }
.bplan-masquees-label { color: var(--muted); font-weight: 600; font-size: 0.78rem; }
.bplan-chip-form { display: inline-flex; }
.bplan-chip { background: var(--bg-card); border: 1px solid var(--border); border-radius: 999px; padding: 0.25rem 0.65rem; font-size: 0.76rem; color: var(--text); cursor: pointer; }
.bplan-chip:hover { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-hover); }
.bplan-tout-reafficher { margin-left: auto; background: none; border: none; color: var(--accent); font-weight: 600; font-size: 0.78rem; cursor: pointer; text-decoration: underline; padding: 0; }

/* Vue tableau (business plan) façon Excel -- border-collapse:separate
   (plutôt que collapse) délibérément : collapse + position:sticky sur
   une cellule de tableau est un bug de rendu connu de WebKit/Safari qui
   fait apparaître le texte d'autres cellules par-dessus la colonne
   figée pendant le défilement horizontal (constaté avec les libellés de
   catégorie qui se superposaient à des montants). border-spacing:0
   supprime l'espace que "separate" introduirait sinon entre cellules. */
.bplan { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 0.78rem; }
.bplan th, .bplan td { padding: 0.4rem 0.55rem; border-bottom: 1px solid var(--border); text-align: right; white-space: nowrap; }
.bplan th:first-child, .bplan td:first-child { text-align: left; position: sticky; left: 0; z-index: 2; background: var(--bg-card); min-width: 170px; }
.bplan thead th { text-transform: uppercase; font-size: 0.66rem; color: var(--muted); background: var(--bg-card-muted); }
.bplan tbody tr.total-row td { font-weight: 800; border-top: 2px solid var(--border); background: var(--bg-card-muted); }
.bplan tbody tr.section-row td { font-weight: 700; background: var(--accent-soft); color: var(--accent-hover); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.03em; text-align: left; }
/* Le libellé ("Total dépenses", "Dépenses"/"Recettes") doit rester
   visible pendant le défilement horizontal, comme la colonne Catégorie
   -- même fond que le reste de la ligne pour ne pas casser la couleur
   pleine largeur au moment où il se détache visuellement en scrollant. */
.bplan tbody tr.total-row td:first-child { background: var(--bg-card-muted); }
.bplan tbody tr.section-row td:first-child { background: var(--accent-soft); }
.bplan tbody tr.tresorerie-row td { font-weight: 800; border-top: 2px solid var(--accent); background: var(--bg-card); color: var(--accent-hover); }
.bplan tbody tr.tresorerie-row td:first-child { background: var(--bg-card); }

/* Commentaire par case (vue Mois uniquement) -- point orange en coin,
   infobulle native au survol (attribut title, pas de JS), clic ouvre un
   petit panneau flottant ancré à la case (position:absolute dans un
   parent position:relative) pour ne jamais interférer avec les cases
   voisines. */
.bplan-cell { position: relative; }
.bplan-cell-clickable { display: block; cursor: pointer; border-radius: 4px; padding: 0.1rem 0.2rem; margin: -0.1rem -0.2rem; }
.bplan-cell-clickable:hover { background: var(--accent-soft); }
.bplan-comment-dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); margin-left: 0.3rem; vertical-align: middle; }
.bplan-comment-panel { position: absolute; top: 100%; right: 0; z-index: 5; min-width: 280px; margin-top: 0.2rem; text-align: left; white-space: normal; box-shadow: var(--shadow-md); }
.bplan-comment-panel textarea { resize: vertical; }
.bplan-comment-panel textarea { font-family: inherit; font-size: 0.8rem; padding: 0.4rem; border: 1px solid var(--border); border-radius: 6px; }
.bplan-cat-nom { display: flex; align-items: center; gap: 0.4rem; }

/* Masquage en un clic : bouton "−" discret, révélé au survol de la ligne
   (catégorie) ou de la colonne (en-tête) -- cf. panneau "Masqué" plus
   haut pour réafficher. */
.bplan-masquer-form { display: inline-flex; }
.bplan-cat-nom .bplan-masquer-form { margin-left: auto; }
.bplan thead th:not(:first-child) { position: relative; padding-right: 1.5rem; }
.bplan thead th .bplan-masquer-form { position: absolute; top: 50%; right: 0.2rem; transform: translateY(-50%); }
.bplan-masquer { background: var(--bg-card); border: 1px solid var(--border); border-radius: 50%; width: 18px; height: 18px; line-height: 1; font-size: 0.85rem; color: var(--muted); cursor: pointer; opacity: 0; transition: opacity 0.15s ease, background 0.15s ease; padding: 0; }
.bplan tbody tr:hover .bplan-masquer, .bplan thead th:hover .bplan-masquer { opacity: 1; }
.bplan-masquer:hover { background: var(--accent-soft); color: var(--accent-hover); border-color: var(--accent); }

@media (max-width: 900px) {
  .assoc-grid, .categories-gestion-grid { grid-template-columns: 1fr; }
}
