/* ===========================================================================
   Finition de l'interface
   ===========================================================================
   Deux règles tenues d'un bout à l'autre :

   1. AUCUNE couleur nouvelle. Tout reprend les variables de css/app.css
      (--navy, --coral, --brand-red, --magenta, --jaune, --jaune-texte,
      --border, --card, --bg, --text, --text-soft). Le vert #2E9E5B est un
      état (« fait »), pas une couleur de charte ; il est repris tel quel,
      jamais élargi. La charte du 29/09/2026 (outils/charte-2026.py) a
      remplacé l'ardoise, l'orange, le rouge et l'ocre par le bleu, le
      corail, le rose et le jaune du nouveau logo.

   2. Aucun mot n'est touché : cette feuille ne fait que présenter.

   Chargée après app.css et etapes-formation.css.
=========================================================================== */

/* ---------------------------------------------------------------------------
   Les icônes
   ---------------------------------------------------------------------------
   Elles remplacent 191 emojis de 58 formes différentes. Toutes proviennent du
   même jeu (public/js/icones.js) : 24 × 24, trait de 2, sans couleur propre.
   Elles prennent celle du texte qui les entoure, donc suivent les deux thèmes.
--------------------------------------------------------------------------- */
.ico {
  flex-shrink: 0;
  vertical-align: -0.16em;
  /* Le trait ne s'épaissit pas quand l'icône est réduite : sans cela, une
     icône de 12 px paraît plus grasse qu'une icône de 17 px. */
  vector-effect: non-scaling-stroke;
}

/* Dans un titre ou un bouton, l'icône est un peu plus discrète que le texte
   qu'elle accompagne : elle situe, elle ne crie pas. */
h3 > .ico:first-child,
h4 > .ico:first-child { opacity: .75; margin-right: 2px; }

.btn .ico { opacity: .9; }

/* Une icône seule dans un bouton carré doit être centrée, pas alignée sur la
   ligne de base d'un texte absent. */
.qbtn .ico, .logout .ico, .avatar .ico { vertical-align: 0; }

/* ---------------------------------------------------------------------------
   Les pastilles d'état
   ---------------------------------------------------------------------------
   Les scores étaient rendus par 🔥 🟡 🟢 🔴 🔵 : cinq pictogrammes dont le
   dessin change selon le système d'exploitation, et qui font doublon avec la
   couleur déjà portée par la classe .score du prototype.

   Un point prend la couleur du texte de son parent : les nuances de .score
   s'appliquent donc sans qu'aucune couleur soit redéfinie ici.
--------------------------------------------------------------------------- */
[class^="pastille"] {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
  margin-right: 5px;
  vertical-align: 0.05em;
}
.score [class^="pastille"] { margin-right: 4px; }

/* Les variantes servent là où il n'y a pas de parent coloré : la légende de
   l'aide. Les valeurs viennent toutes de la charte (cf. .score dans app.css). */
.pastille-hot { color: var(--coral); }
.pastille-warm { color: var(--jaune-texte); }
.pastille-cold { color: var(--navy); }
.pastille-client { color: #2E9E5B; }
.pastille-perdu { color: var(--magenta); }
.pastille-urgente { color: var(--brand-red); }
.pastille-active { color: #2E9E5B; width: 9px; height: 9px; }

/* ---------------------------------------------------------------------------
   Le chevron des rubriques d'aide
--------------------------------------------------------------------------- */
.aide-fleche {
  color: var(--text-soft);
  display: inline-flex;
  transition: transform .18s ease;
}

/* ===========================================================================
   Finition générale
   ===========================================================================
   Ce qui suit ne change ni la structure, ni les couleurs, ni les mots : ce
   sont les détails qui séparent une maquette d'un outil qu'on ouvre tous les
   jours — la profondeur, les états visibles, et le confort de lecture.
=========================================================================== */

/* --- Les chiffres s'alignent -----------------------------------------------
   Sans cela, une colonne de montants ou de pourcentages tremble d'une ligne à
   l'autre, parce que le « 1 » est plus étroit que le « 8 ». */
table td, table th,
.score, .status-tag, .pill, .priorite,
.recapitulatif-pourcent, .jauge-valeur, .nav-badge {
  font-variant-numeric: tabular-nums;
}

/* --- On voit toujours où on est -------------------------------------------
   Le prototype n'avait aucun style de focus : au clavier, on avançait à
   l'aveugle. C'est une exigence d'accessibilité autant qu'un signe de finition.
   :focus-visible n'apparaît qu'au clavier, jamais après un clic de souris. */
:focus-visible {
  outline: 2px solid var(--coral);
  outline-offset: 2px;
  border-radius: 6px;
}
.btn:focus-visible, .qbtn:focus-visible, .nav-item:focus-visible {
  outline-offset: 3px;
}

/* --- Les surfaces respirent ------------------------------------------------
   Une ombre unique et plate donne un aspect « collé ». Deux couches — un
   contact net, une diffusion large — suffisent à poser les cartes sans
   assombrir l'écran. Les valeurs restent dans la teinte de la charte. */
.panel {
  box-shadow: 0 1px 2px rgba(11, 65, 122, .05), 0 8px 24px -12px rgba(11, 65, 122, .14);
  transition: box-shadow .2s ease;
}
[data-theme="dark"] .panel {
  box-shadow: 0 1px 2px rgba(0, 0, 0, .25), 0 10px 28px -14px rgba(0, 0, 0, .5);
}

/* --- Les boutons répondent -------------------------------------------------
   Un enfoncement de 1 px au clic : le geste est confirmé sans animation
   tapageuse. */
.btn {
  transition: filter .15s ease, transform .1s ease, box-shadow .15s ease;
}
.btn:hover { filter: brightness(1.06); }
.btn.ghost:hover { filter: none; background: var(--bg); }
.btn:active { transform: translateY(1px); }

/* --- Les lignes de liste se distinguent au survol --------------------------
   Sur un tableau de quinze lignes, savoir laquelle on vise évite les erreurs
   de clic. Le fond reprend --bg, déjà utilisé partout. */
.list-row { transition: background .14s ease; border-radius: 8px; }
.list-row:hover { background: var(--bg); }
table tbody tr { transition: background .14s ease; }
table tbody tr:hover { background: var(--bg); }

/* --- Les en-têtes de tableau restent lisibles au défilement ----------------- */
table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--card);
}

/* --- Les écrans vides ------------------------------------------------------
   La bulle accueillait un emoji de 22 px ; elle accueille maintenant une
   icône au trait, plus sobre et de la même famille que le reste. */
.placeholder-view .bubble-icon {
  color: var(--text-soft);
  box-shadow: 0 1px 2px rgba(11, 65, 122, .04);
}
.placeholder-view .bubble-icon .ico { opacity: .7; }

/* --- Les champs de saisie --------------------------------------------------
   Une bordure qui s'anime au survol et à la sélection dit où l'on écrit. */
input, select, textarea { transition: border-color .15s ease, box-shadow .15s ease; }
input:hover:not(:disabled), select:hover:not(:disabled) { border-color: var(--text-soft); }
input:focus, select:focus, textarea:focus {
  border-color: var(--coral);
  box-shadow: 0 0 0 3px rgba(245, 96, 88, .14);
  outline: none;
}

/* --- Le classement, sans médailles -----------------------------------------
   Trois emojis de podium se ressemblent à petite taille et ne se distinguent
   pas en noir et blanc. Un rang chiffré se lit tout de suite. */
.leaderboard-rank {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  color: var(--text-soft);
}

/* --- Rien ne bouge pour qui préfère que rien ne bouge ----------------------
   Réglage système respecté : personnes sujettes au mal des transports,
   troubles vestibulaires, ou simple préférence. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* --- Un score sans texte devient un point, pas une pilule vide -------------
   Le prototype mettait un pictogramme dans la pilule colorée. Une pastille
   seule au milieu de ce fond paraissait inachevée : quand il n'y a rien
   d'autre à lire, le point se suffit à lui-même. Là où le score porte un
   libellé (« À relancer »), la pilule est conservée. */
.score:has([class^="pastille"]:only-child) {
  background: none;
  padding: 0;
}
.score:has([class^="pastille"]:only-child) [class^="pastille"] {
  width: 10px;
  height: 10px;
  margin: 0;
}

/* --- Le point de la frise, aligné sur son trait --------------------------- */
.timeline-dot [class^="pastille"] { margin: 0; }

/* --- Le prospect tiède, en jaune franc --------------------------------------
   Demandé après coup, puis aligné sur la charte du 29/09/2026 : le POINT
   prend le jaune du logo (--jaune).

   Le libellé du badge (« Relancé récemment ») garde la forme foncée du jaune
   (--jaune-texte) : un jaune franc sur fond clair descendrait sous le seuil
   de lisibilité. Le point, lui, n'a pas ce problème — il n'a rien à faire
   lire. */
.score.warm [class^="pastille"] { color: var(--jaune); }
.pastille-warm { color: var(--jaune); }

/* --- La flamme du prospect chaud -------------------------------------------
   Comme pour le point seul, un badge qui ne contient qu'une icône se passe de
   son fond coloré : il ne reste rien à lire dessus. */
.score:has(> .ico:only-child) {
  background: none;
  padding: 0;
}
/* Accolée à un libellé, l'icône s'aligne sur la ligne de base du texte ;
   seule dans son badge, elle se centre — il n'y a plus de texte à suivre. */
.score .ico { vertical-align: -0.2em; }
.score:has(> .ico:only-child) .ico { vertical-align: middle; }

/* --- Le suivi prospection d'un dossier, sur deux colonnes -------------------
   À gauche ce qui s'est passé (actions puis relances), à droite ce qu'il reste
   à faire (les tâches). Les trois historiques se suivaient auparavant sur une
   seule colonne : il fallait dérouler tout l'historique des actions avant de
   savoir s'il restait une tâche.

   La bascule se règle sur la largeur du PANNEAU, pas sur celle de la fenêtre :
   le suivi vit dans une colonne de la fiche, et une fenêtre large ne garantit
   donc pas une place large. Une requête de conteneur mesure ce qui compte.
   Sans prise en charge, on reste sur une colonne — lisible partout. */
#fiche-suivi-prospection-list {
  container-type: inline-size;
  container-name: suivi;
}

.suivi-colonnes {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 30px;
  align-items: start;
}

@container suivi (min-width: 600px) {
  .suivi-colonnes {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 26px;
  }
  /* La colonne de droite se démarque par un filet, pas par un fond : un aplat
     de plus alourdirait une zone déjà chargée. */
  .suivi-colonne + .suivi-colonne {
    border-left: 1px solid var(--border);
    border-top: none;
    padding-left: 26px;
    padding-top: 0;
  }
}

/* Empilées, les deux colonnes se séparent par un filet horizontal. */
.suivi-colonne + .suivi-colonne {
  border-top: 1px solid var(--border);
  padding-top: 22px;
}

/* Le titre à gauche, le bouton à droite. Le libellé et son icône sont dans un
   même <span> : sans lui, l'espacement les aurait écartés aux deux bords. */
.suivi-colonne h3 {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 4px;
}
.suivi-colonne h3 > span:first-child { min-width: 0; }
/* L'icône est ici dans le <span>, hors de portée de la règle `h3 > .ico`. */
.suivi-colonne h3 .ico { opacity: .75; margin-right: 6px; }
.suivi-colonne h3 .btn {
  flex-shrink: 0;
  align-self: center;
  padding: 4px 10px;
  font-size: var(--txt-xs);
  white-space: nowrap;
}

/* Ce qui distingue une relance d'une tâche, écrit sous le titre : les deux
   mots se ressemblent trop pour qu'on laisse deviner. */
.suivi-explication {
  font-size: var(--txt-xs);
  color: var(--text-soft);
  margin-bottom: 12px;
  line-height: 1.45;
}

.suivi-vide {
  font-size: var(--txt-sm);
  color: var(--text-soft);
  padding: 4px 0 2px;
}

/* Le compte de ce qui reste, accolé au titre. */
.suivi-compte {
  display: inline-block;
  font-size: var(--txt-xs);
  font-weight: 650;
  color: var(--text-soft);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 1px 8px;
  white-space: nowrap;
  vertical-align: 1px;
}

/* Une tâche posée par les automatismes du suivi de formation. Elle reste
   visible ici — c'est un historique — mais se coche depuis l'autre onglet. */
.suivi-origine {
  display: inline-block;
  font-size: var(--txt-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-soft);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 1px 6px;
  white-space: nowrap;
}

/* --- Une rangée de boutons de modale qui ne coupe plus les mots -------------
   Trois boutons dans la fiche d'une séance (agenda, fiche complète, fermer)
   tenaient à l'étroit : le libellé se cassait en deux lignes au milieu d'un
   mot. Les boutons gardent leur libellé d'un seul tenant et la rangée passe à
   la ligne si la modale est trop étroite. */
.modal-actions { flex-wrap: wrap; }
.modal-actions .btn { white-space: nowrap; }

/* --- Le rectangle du bas de la barre latérale, devenu bouton ---------------
   Il en avait déjà l'apparence sans en avoir le comportement. Il ouvre
   maintenant la page Profil ; la déconnexion reste un bouton à part, pour que
   les deux gestes ne se confondent pas. */
.user-chip-open {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 9px;
  background: none;
  border: 0;
  padding: 2px;
  margin: -2px;
  border-radius: 8px;
  cursor: pointer;
  text-align: left;
  color: inherit;
  font: inherit;
}
/* Pas de couleur nouvelle au survol : le nom est déjà en blanc dans
   css/app.css, le soulignement suffit à dire que c'est cliquable. */
.user-chip-open:hover .who .name { text-decoration: underline; }
.user-chip-open:focus-visible {
  outline: 2px solid var(--coral);
  outline-offset: 2px;
}

/* --- La photo de profil ----------------------------------------------------
   Elle remplit le cercle de l'avatar sans le déformer : `cover` recadre, une
   photo en portrait comme en paysage reste un rond. */
.avatar-photo {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
  display: block;
}

/* --- La page Profil -------------------------------------------------------- */
.profil-identite {
  display: flex;
  align-items: flex-start;
  gap: 16px;
}
.profil-identite-texte { min-width: 0; }

.profil-avatar {
  width: 76px;
  height: 76px;
  font-size: 24px;
  flex-shrink: 0;
  overflow: hidden;
}

.profil-nom {
  font-size: var(--txt-xl);
  font-weight: 700;
  color: var(--text);
  line-height: 1.3;
}
.profil-role {
  font-size: var(--txt-sm);
  color: var(--text-soft);
  margin-bottom: 10px;
}
.profil-boutons { display: flex; flex-wrap: wrap; gap: 8px; }
.profil-boutons .btn { padding: 6px 12px; font-size: var(--txt-sm); }

/* Les panneaux de la page se rangent côte à côte quand la place le permet.
   Empilés en une colonne de 480 px, ils laissaient les deux tiers de l'écran
   vides — ce qui donnait à la page l'air d'un formulaire oublié. */
/* `.active` fait partie du sélecteur : sans lui, la règle l'emporterait sur
   `.view { display: none }` et la page resterait visible sous tous les autres
   écrans. */
/* Des colonnes plutôt qu'une grille (29/09/2026) : dans une grille, chaque
   rangée prend la hauteur de son panneau le plus haut, et « Mon agenda »
   flottait au-dessus d'un grand vide pendant que la version du CRM tombait
   dans une case du milieu. Les colonnes se remplissent de haut en bas, et la
   version, qui les enjambe, ferme la page. */
#view-profil.active {
  display: block;
  column-count: 2;
  column-gap: 16px;
  max-width: 1060px;
}
#view-profil.active > .panel {
  break-inside: avoid;
  margin-bottom: 16px;
}
#view-profil.active > .version-crm { column-span: all; }
@media (max-width: 760px) {
  #view-profil.active { column-count: 1; }
}

/* Un cercle d'avatar qui porte une photo ne doit pas la laisser déborder. */
.avatar:has(.avatar-photo) { overflow: hidden; padding: 0; }

@media (max-width: 560px) {
  .profil-identite { flex-direction: column; }
}

/* --- L'écran Import / Export, en deux colonnes -----------------------------
   Quatre panneaux s'y suivaient sur une colonne de 640 px collée au bord
   gauche : il fallait dérouler tout l'import pour atteindre l'export, et rien
   ne disait que les deux premiers parlent d'entrée et les deux derniers de
   sortie. Sur un écran étroit, les colonnes se suivent — l'ordre de lecture
   reste celui-là. */
.io-grille {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(360px, 1fr));
  gap: 20px;
  align-items: start;
  max-width: 1180px;
}
.io-colonne {
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-width: 0;
}

/* Le titre de colonne : il nomme le groupe sans se faire passer pour un
   panneau de plus. */
.io-titre {
  font-size: var(--txt-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--text-soft);
  margin: 0 0 -4px 2px;
}

/* --- La messagerie ---------------------------------------------------------
   L'écran tenait dans une colonne de 900 px centrée : de larges bandes vides
   à gauche et à droite, pendant que le fil de discussion étouffait dans
   420 px de haut. Il prend la largeur disponible, et le fil la hauteur de la
   fenêtre. */
.messagerie {
  display: grid;
  grid-template-columns: 250px minmax(0, 1fr);
  gap: 16px;
  align-items: stretch;
  /* La hauteur de la fenêtre, et non une hauteur minimale : avec treize
     versions dans le fil « CRM Allokom », le panneau s'allongeait sous
     l'écran au lieu de défiler (29/09/2026). */
  height: calc(100vh - 190px);
  min-height: 420px;
}
.messagerie-liste { overflow-y: auto; max-height: 100%; }
@media (max-width: 820px) {
  .messagerie { grid-template-columns: minmax(0, 1fr); min-height: 0; }
}

.messagerie-liste { padding: 10px; align-self: start; }
.messagerie-fil { display: flex; flex-direction: column; min-width: 0; }

/* Le fil occupe ce qui reste du panneau et défile seul : la zone de saisie
   reste sous les yeux, quelle que soit la longueur de la conversation. */
.messagerie-fil #messages-feed {
  flex: 1;
  min-height: 220px;
  overflow-y: auto;
  margin-bottom: 16px;
  padding-right: 4px;
}
.messagerie-saisie { display: flex; gap: 8px; }

/* --- Une conversation dans la liste ---------------------------------------
   Plus de cadenas devant les conversations privées : dans cette interface il
   veut dire « fermé, vous n'y avez pas accès » — c'est son sens sur les
   mailings pas encore ouverts — alors qu'ici la conversation est justement
   ouverte. Le rôle de la personne, en sous-titre, dit mieux de quoi il
   s'agit. */
.conv-ligne {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px;
  border-radius: 9px;
  cursor: pointer;
  margin-bottom: 2px;
}
.conv-ligne:hover { background: var(--bg); }
.conv-active { background: var(--bg); }

.conv-avatar { width: 30px; height: 30px; font-size: var(--txt-xs); flex-shrink: 0; }
.conv-texte { flex: 1; min-width: 0; }
.conv-nom {
  font-size: var(--txt-md);
  line-height: 1.3;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.conv-active .conv-nom { font-weight: 650; }
.conv-sous {
  font-size: var(--txt-xs);
  color: var(--text-soft);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.conv-compte {
  background: var(--brand-red);
  /* Blanc, et non `--card` : en thème sombre, --card devient une teinte
     ardoise très foncée et le chiffre disparaîtrait sur le rouge. Même règle
     que `.nav-badge` dans css/app.css. */
  color: #fff;
  font-size: var(--txt-xs);
  font-weight: 700;
  border-radius: 10px;
  padding: 1px 7px;
  flex-shrink: 0;
}

/* --- Les encarts d'assistance, repliables ----------------------------------
   « Ressortir davantage et prendre moins de place » : les deux à la fois, ce
   que seul le repliement concilie. L'en-tête reste visible, avec son icône et
   le nombre de points qu'il contient ; le contenu se déroule d'un clic.

   Ce qui ALERTE ne se replie pas — voir public/js/encarts.js. */
.assistant-panel h4 { margin: 0; }

.assistant-bascule {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: var(--txt-sm);
  font-weight: 700;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.assistant-bascule:focus-visible {
  outline: 2px solid var(--coral);
  outline-offset: 3px;
  border-radius: 4px;
}
/* Un encart d'alerte n'a pas de bascule : le curseur ne doit pas promettre
   un clic qui ne fait rien. */
.assistant-panel[data-encart="alerte"] .assistant-bascule { cursor: default; }

/* L'icône de tête, posée dans une pastille : c'est elle qui fait ressortir
   l'encart maintenant qu'il est le plus souvent replié. */
.assistant-bascule > .ico:first-child {
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  padding: 5px;
  border-radius: 8px;
  background: rgba(11, 65, 122, .12);
  opacity: 1;
  box-sizing: border-box;
}

/* Le nombre de points, annoncé sur l'en-tête replié : on sait s'il y a
   quelque chose à lire avant d'ouvrir. */
.assistant-compte {
  margin-left: auto;
  font-size: var(--txt-xs);
  font-weight: 700;
  color: var(--text-soft);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0 7px;
  line-height: 17px;
  min-width: 19px;
  text-align: center;
}
.assistant-compte:empty { display: none; }

.assistant-chevron {
  display: inline-flex;
  flex-shrink: 0;
  color: var(--text-soft);
  transition: transform .18s ease;
}
.assistant-compte + .assistant-chevron { margin-left: 4px; }
.assistant-bascule[aria-expanded="false"] .assistant-chevron { transform: rotate(-90deg); }
/* Un encart d'alerte est toujours déployé : ni chevron, ni compte à
   annoncer — son contenu est sous les yeux. */
.assistant-panel[data-encart="alerte"] .assistant-chevron,
.assistant-panel[data-encart="alerte"] .assistant-compte { display: none; }

.assistant-corps { margin-top: 10px; }
.assistant-replie .assistant-corps { display: none; }
/* Replié, l'encart n'est plus qu'une ligne : il rend la place qu'il occupait. */
.assistant-replie { padding: 10px 14px; margin-bottom: 12px; }

@media (prefers-reduced-motion: reduce) {
  .assistant-chevron { transition: none; }
}

/* ===========================================================================
   Ce qui alerte se fait remarquer
   ===========================================================================
   Trois degrés, un seul vocabulaire, employé dans les relances, les tâches,
   les notifications et les fiches. La couleur ne porte jamais l'information
   seule : chaque degré a son icône et son mot (voir URGENCES dans app.js).
--------------------------------------------------------------------------- */

/* --- L'en-tête d'un groupe d'échéances ------------------------------------ */
.groupe-urgence {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--txt-md);
  margin-bottom: 8px;
  color: var(--text-soft);
}
.groupe-urgence .ico { opacity: 1; }
.groupe-compte {
  font-size: var(--txt-xs);
  font-weight: 700;
  border-radius: 999px;
  padding: 0 8px;
  line-height: 18px;
  background: var(--bg);
  border: 1px solid var(--border);
  color: inherit;
}

.groupe-urgence.urgence-retard { color: var(--magenta); font-weight: 700; }
.groupe-urgence.urgence-retard .groupe-compte {
  background: var(--magenta);
  border-color: var(--magenta);
  color: #fff;   /* voir .conv-compte : --card s'assombrit avec le thème */
}
.groupe-urgence.urgence-aujourdhui { color: var(--coral); font-weight: 700; }
.groupe-urgence.urgence-aujourdhui .groupe-compte {
  background: rgba(245, 96, 88, .16);
  border-color: transparent;
  color: var(--coral);
}

/* Le bloc « En retard » porte un filet sur toute sa hauteur : on le repère en
   parcourant la page, sans lire les titres. */
.bloc-urgence { margin-bottom: 16px; }
.bloc-urgence.urgence-retard > .panel,
.panel.bloc-urgence.urgence-retard { border-left: 3px solid var(--magenta); }
.bloc-urgence.urgence-aujourdhui > .panel,
.panel.bloc-urgence.urgence-aujourdhui { border-left: 3px solid var(--coral); }

/* Le nombre de jours de retard, sous la date : « le 3 septembre » ne dit pas
   qu'on a dix jours de retard. */
.retard-jours {
  font-size: var(--txt-xs);
  font-weight: 700;
  color: var(--magenta);
  margin-top: 3px;
  white-space: nowrap;
}

/* --- Le grelot des notifications ------------------------------------------
   Il ne portait qu'un point de 9 px, muet sur le nombre et sur la gravité :
   aucune raison de l'ouvrir. Il porte maintenant le compte. */
.qbtn .dot {
  top: -6px;
  right: -6px;
  width: auto;
  height: auto;
  min-width: 18px;
  padding: 0 5px;
  border-radius: 999px;
  font-size: var(--txt-xs);
  font-weight: 700;
  line-height: 18px;
  text-align: center;
  color: #fff;
  background: var(--coral);
}
.qbtn .dot.dot-urgent { background: var(--brand-red); }

/* Un retard en cours : le bouton lui-même le signale, discrètement mais sans
   ambiguïté. Pas de clignotement — une alerte permanente qui bat finit par
   être ignorée, et gêne les personnes sensibles au mouvement. */
.qbtn.qbtn-alerte { box-shadow: 0 0 0 2px var(--brand-red); }

/* --- Les lignes du panneau de notifications ------------------------------- */
#notif-dropdown .notif-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.notif-compte {
  font-size: var(--txt-xs);
  font-weight: 700;
  border-radius: 999px;
  padding: 0 8px;
  line-height: 18px;
  color: #fff;
  background: var(--coral);
}
.notif-compte.urgence-retard { background: var(--brand-red); }

/* La liste défile, l'en-tête reste. Le panneau s'allongeait avec ses lignes :
   au-delà d'une dizaine, le surplus passait sous le bas de l'écran et l'on ne
   pouvait ni le voir ni l'atteindre (28/09/2026). Soixante pour cent de la
   fenêtre au plus, pour qu'on voie toujours qu'il y a une page derrière. */
#notif-liste {
  max-height: min(60vh, 480px);
  overflow-y: auto;
  overscroll-behavior: contain;
}
#notif-dropdown .notif-item {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  line-height: 1.45;
}
#notif-dropdown .notif-item .ico { margin-top: 1px; flex-shrink: 0; }
#notif-dropdown .notif-item[data-action] { cursor: pointer; }
#notif-dropdown .notif-item[data-action]:hover { background: var(--bg); }
#notif-dropdown .notif-item.urgence-retard { color: var(--magenta); }
#notif-dropdown .notif-item.urgence-retard b { color: var(--magenta); }
#notif-dropdown .notif-item.urgence-aujourdhui .ico { color: var(--coral); }

/* --- La ligne qui explique un écran --------------------------------------- */
.sous-titre-ecran {
  color: var(--text-soft);
  font-size: var(--txt-sm);
  line-height: 1.55;
  max-width: 82ch;
  margin-bottom: 16px;
}
.sous-titre-ecran b { color: var(--text); }

/* ===========================================================================
   L'échelle typographique, et le rythme vertical
   ===========================================================================
   Six marches, aux écarts nets. Onze tailles voisines cohabitaient auparavant
   dans les fichiers servis — 10.5, 11, 11.5, 12, 12.5, 13, 13.5, 14.5, 15, 19,
   32 px : des écarts d'un demi-pixel que personne ne lit comme une hiérarchie,
   mais qu'on voit comme un défaut d'alignement. outils/typographie.py a rangé
   les tailles écrites en ligne sur ces marches ; celles qui suivent règlent
   les éléments de structure.

   Rien de la charte ne bouge : ni couleur, ni police. Seules changent les
   tailles, les graisses et les espaces.
--------------------------------------------------------------------------- */
:root {
  --txt-xs: 11.5px;    /* mentions, méta, en-têtes de colonne */
  --txt-sm: 12.5px;    /* texte secondaire, sous-titres */
  --txt-md: 13.5px;    /* texte courant, lignes de liste, boutons */
  --txt-lg: 15px;      /* titre de bloc secondaire */
  --txt-xl: 17px;      /* titre de panneau */
  --txt-2xl: 22px;     /* titre de page */

  /* Deux interlignes : serré pour les titres, aéré pour ce qui se lit. */
  --ligne-titre: 1.25;
  --ligne-texte: 1.55;
}

body { font-size: var(--txt-md); line-height: var(--ligne-texte); }

h1, h2, h3, h4 {
  line-height: var(--ligne-titre);
  /* Un titre sur deux lignes se coupe au milieu plutôt qu'en laissant un mot
     seul sur la seconde. Ignoré par les navigateurs qui ne connaissent pas. */
  text-wrap: balance;
}

/* --- Le titre de page ------------------------------------------------------
   19 px en demi-gras : à peine plus gros que le titre d'un panneau qu'il
   surplombe, et donc pas lu comme le sommet de la page. */
#topbar h1 {
  font-size: var(--txt-2xl);
  font-weight: 700;
  letter-spacing: -.01em;
}
#topbar .sub { font-size: var(--txt-sm); line-height: 1.4; }

/* --- Le titre d'un panneau ------------------------------------------------- */
.panel h3 { font-size: var(--txt-xl); }
.modal-box h3 { font-size: var(--txt-xl); }

/* --- Le titre d'un bloc à l'intérieur d'un panneau ------------------------- */
.panel h4,
.assistant-panel h4,
.assistant-bascule { font-size: var(--txt-md); }

/* --- Le texte courant ------------------------------------------------------ */
.list-row { font-size: var(--txt-md); }
.list-row .meta .sub { font-size: var(--txt-sm); line-height: 1.45; }
.sub { line-height: 1.5; }
table { font-size: var(--txt-md); }
thead th { font-size: var(--txt-xs); }
.field label { font-size: var(--txt-sm); }

/* --- Le rythme vertical ----------------------------------------------------
   Les panneaux qui se suivent dans un écran gardaient des marges écrites une
   par une : 16, 18, 22 px selon l'endroit. Une seule valeur, celle de
   l'échelle d'espacement de css/app.css. Les marges écrites en ligne
   l'emportent encore là où elles existent ; celle-ci sert de défaut. */
.view > .panel + .panel,
.view > .panel + .assistant-panel,
.view > .assistant-panel + .panel { margin-top: var(--sp-md); }

/* Un titre de panneau collé à son contenu se lit comme une ligne de plus.
   L'écart sous le titre est légèrement supérieur à l'interligne du texte,
   comme le veut l'usage. */
.panel h3 { margin-bottom: var(--sp-md); }
.panel h3 + .sub { margin-top: calc(-1 * var(--sp-xs)); }

/* --- La barre de gauche ne sort plus de l'écran ----------------------------
   Ses entrées étaient des enfants directs d'une colonne flexible : dès qu'il
   y en a beaucoup — quatorze rubriques pour un administrateur — la colonne
   s'allongeait au-delà de la fenêtre et le pied de barre partait avec, rendant
   le profil et la déconnexion inatteignables.

   Le logo et le pied de barre restent en place ; seules les entrées défilent.
   Faire défiler toute la barre aurait emporté le profil avec le reste. */
#sidebar { height: 100%; overflow: hidden; }

#sidebar-nav {
  flex: 1;
  /* Sans `min-height: 0`, un enfant flexible refuse de descendre sous la
     hauteur de son contenu : la barre de défilement n'apparaîtrait jamais. */
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  /* La place de la barre de défilement est réservée en permanence : sans
     cela, les entrées se décalent de quelques pixels quand elle apparaît. */
  scrollbar-gutter: stable;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, .22) transparent;
}

/* Le même dessin discret pour les navigateurs qui ne lisent pas
   `scrollbar-color`. */
#sidebar-nav::-webkit-scrollbar { width: 6px; }
#sidebar-nav::-webkit-scrollbar-track { background: transparent; }
#sidebar-nav::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, .22);
  border-radius: 3px;
}
#sidebar-nav::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, .34); }

/* --- L'abonnement à l'agenda ----------------------------------------------- */
#agenda-lien {
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: var(--txt-sm);
  /* L'adresse fait plus de soixante caractères : elle doit pouvoir défiler
     dans son champ plutôt que d'élargir le panneau. */
  overflow-x: auto;
  text-overflow: clip;
}
.agenda-boutons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.agenda-boutons .btn { padding: 8px 14px; font-size: var(--txt-sm); }

/* L'avertissement : une adresse qui vaut clé se signale, sans crier. */
.encadre-prudence {
  font-size: var(--txt-sm);
  line-height: 1.55;
  color: var(--text);
  background: rgba(245, 96, 88, .08);
  border-left: 3px solid var(--coral);
  border-radius: 0 9px 9px 0;
  padding: 10px 14px;
  margin-bottom: 14px;
}

.agenda-mode-emploi { font-size: var(--txt-sm); color: var(--text-soft); }
.agenda-mode-emploi summary {
  cursor: pointer;
  font-weight: 650;
  color: var(--navy);
  padding: 4px 0;
}
[data-theme="dark"] .agenda-mode-emploi summary { color: #8fb3de; }
.agenda-mode-emploi summary:focus-visible { outline: 2px solid var(--coral); outline-offset: 3px; }
.agenda-mode-emploi ul { margin: 8px 0 0; padding-left: 20px; line-height: 1.6; }
.agenda-mode-emploi li { margin-bottom: 6px; }
.agenda-mode-emploi li b { color: var(--text); }
.agenda-note { margin-top: 10px; font-size: var(--txt-xs); line-height: 1.5; }

/* ===========================================================================
   Corriger une ligne de suivi
   ===========================================================================
   Les deux boutons apparaissent au survol de la ligne, et restent toujours
   atteignables au clavier : « discret » ne doit pas vouloir dire « caché ».
--------------------------------------------------------------------------- */

.suivi-corriger {
  display: flex;
  gap: 6px;
  margin-top: 6px;
  opacity: 0;
  transition: opacity .15s ease;
}
.timeline-item:hover .suivi-corriger,
.suivi-corriger:focus-within { opacity: 1; }

.suivi-corriger .btn {
  padding: 3px 9px;
  font-size: var(--txt-xs);
}

/* Au doigt, il n'y a pas de survol : les boutons restent visibles. */
@media (hover: none) {
  .suivi-corriger { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .suivi-corriger { transition: none; }
}

/* ===========================================================================
   La fenêtre du mot de passe temporaire
   ===========================================================================
   Elle remplace un message en bas à droite qui s'effaçait au bout de six
   secondes — donc qu'on pouvait ne jamais voir. Celle-ci est au centre, et
   emploie le rouge de la charte, celui des alertes.
--------------------------------------------------------------------------- */

.mdp-urgent-box {
  /* --magenta : la teinte d'alerte de la charte, celle de « Perdu » et du
     rappel déjà présent sur la page Profil. Pas --brand-red, qui sert au
     dégradé du bandeau et au grelot des notifications. */
  border: 2px solid var(--magenta);
  text-align: center;
  max-width: 460px;
}

.mdp-urgent-bandeau {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 54px;
  height: 54px;
  margin: 0 auto 14px;
  border-radius: 50%;
  background: rgba(240, 64, 93, .12);
  color: var(--magenta);
}

.mdp-urgent-titre {
  color: var(--magenta);
  font-weight: 800;
  font-size: var(--txt-2xl);
  line-height: var(--ligne-titre);
  margin-bottom: 10px;
}

.mdp-urgent-texte {
  font-size: var(--txt-md);
  line-height: var(--ligne-texte);
  color: var(--text);
  margin-bottom: 10px;
}

.mdp-urgent-box .modal-actions { justify-content: center; }

/* ===========================================================================
   Le bloc « À venir »
   ===========================================================================
   « Ma journée » ne montrait que le retard et le jour même : une relance posée
   pour la semaine suivante n'apparaissait nulle part sur cet écran. Elle y est
   maintenant, mais repliée — ce qui presse garde le haut de l'encadré.
--------------------------------------------------------------------------- */

.bloc-avenir { margin-top: 12px; border-top: 1px dashed var(--border); padding-top: 10px; }

.avenir-bascule {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 4px 0;
  background: none;
  border: 0;
  cursor: pointer;
  font-family: inherit;
  font-size: var(--txt-sm);
  font-weight: 600;
  color: var(--text-soft);
  text-align: left;
}
.avenir-bascule:hover { color: var(--text); }

.avenir-chevron {
  display: inline-flex;
  flex-shrink: 0;
  transition: transform .18s ease;
}
.avenir-bascule[aria-expanded="false"] .avenir-chevron { transform: rotate(-90deg); }

.avenir-titre { flex: 1; }

.avenir-compte {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0 8px;
  line-height: 18px;
  font-size: var(--txt-xs);
}

.avenir-corps { display: none; margin-top: 4px; }
.bloc-avenir.ouvert .avenir-corps { display: block; }

/* La date d'une relance, à droite de la ligne. */
.relance-quand {
  flex-shrink: 0;
  font-size: var(--txt-xs);
  font-weight: 600;
  color: var(--text-soft);
  white-space: nowrap;
}
.relance-quand.retard { color: var(--magenta); }
.relance-quand.aujourdhui { color: var(--coral); }

@media (prefers-reduced-motion: reduce) {
  .avenir-chevron { transition: none; }
}

/* ===========================================================================
   Les explications d'écran
   ===========================================================================
   Celles des Relances et des Tâches tenaient en un paragraphe dense de cinq
   lignes — celui qu'on saute. Or c'est exactement le texte qui lève la
   confusion entre les deux notions : il doit se lire d'un coup d'œil.

   Une définition en une phrase, puis deux ou trois points. Le dernier renvoie
   toujours vers l'autre écran.
--------------------------------------------------------------------------- */

.definition-ecran {
  font-size: var(--txt-md);
  line-height: var(--ligne-texte);
  color: var(--text);
  margin: 0 0 8px;
}

.points-ecran {
  margin: 0;
  padding-left: 18px;
  list-style: disc;
}
.points-ecran li {
  font-size: var(--txt-sm);
  line-height: var(--ligne-texte);
  color: var(--text-soft);
  margin-bottom: 5px;
}
.points-ecran li:last-child { margin-bottom: 0; }
.points-ecran b { color: var(--text); }

/* ===========================================================================
   L'onglet Dossiers : tri et filtres par colonne
   ===========================================================================
   Une seule colonne se triait, par une flèche posée à la main dans son
   en-tête. Les huit se trient maintenant, et six se filtrent.
--------------------------------------------------------------------------- */

.th-triable {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
.th-triable:hover { color: var(--text); }

.tri-fleche {
  display: inline-flex;
  vertical-align: middle;
  margin-left: 4px;
  color: var(--coral);
}
/* La colonne triée se distingue sans couleur seule : le libellé s'épaissit. */
.th-triable.triee { font-weight: 800; }

.ligne-filtres-colonnes th {
  padding-top: 0;
  padding-bottom: 8px;
  font-weight: 400;
}
.ligne-filtres-colonnes input,
.ligne-filtres-colonnes select {
  width: 100%;
  min-width: 0;
  padding: 5px 8px;
  border-radius: 7px;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--text);
  font-family: inherit;
  font-size: var(--txt-xs);
}
/* « Score » n'a qu'une pastille pour contenu (01/10/2026) : sa liste se
   coupait à deux lettres. */
#fc-score { min-width: 86px; }
.ligne-filtres-colonnes input::placeholder { color: var(--text-soft); }

/* ---------------------------------------------------------------------------
   Un nom de client mène toujours à son dossier
   ===========================================================================
   Le nom n'était cliquable que dans la liste des Dossiers et dans « Mes
   relances commerciales ». Il l'est maintenant dans les tâches, les relances,
   les historiques d'appels, les réclamations, le journal d'activité et les
   écrans du formateur.

   Le souligné pointillé le dit AVANT le clic : le curseur en main, lui, ne se
   voit qu'une fois la souris dessus, et rien ne distinguait jusque-là un nom
   cliquable d'un nom en clair sur la même ligne.

   Aucune teinte nouvelle : --border pour le trait, --coral au survol.
--------------------------------------------------------------------------- */

.nom-client {
  cursor: pointer;
  text-decoration: underline;
  text-decoration-style: dotted;
  text-decoration-color: var(--border);
  text-underline-offset: 3px;
}
.nom-client:hover {
  color: var(--coral);
  text-decoration-color: var(--coral);
}

/* ---------------------------------------------------------------------------
   Le tableau de bord du formateur, et ses écrans en panneaux
   ===========================================================================
   « Les écrans MA JOURNÉE des formateurs ne sont pas beaux. Les sections
   doivent être affichées comme les autres comptes, sous forme de rectangle,
   carré etc. » (17/09/2026)

   Ses écrans empilaient des titres nus sur le fond de page. Ils posent
   maintenant leur contenu dans .panel, comme tous les autres comptes, et
   « Ma journée » s'ouvre sur quatre .kpi-card.

   Les diagrammes sont des barres en CSS — aucune bibliothèque, donc aucun CDN
   à vérifier auprès de l'hébergement, et rien qui demande un script en ligne
   que la politique de sécurité (script-src 'self') refuserait.

   Aucune teinte nouvelle : --coral pour les barres, --border pour la piste.
--------------------------------------------------------------------------- */

/* Quatre chiffres plutôt que cinq : .kpi-grid en pose cinq par défaut, et la
   cinquième colonne resterait vide. */
.kpi-grid-4 { grid-template-columns: repeat(4, 1fr); }

/* Le filtre d'année : même dessin que les listes déroulantes de la barre
   d'outils des statistiques, sans le style en ligne. */
.champ-filtre {
  padding: 8px 12px;
  border-radius: 9px;
  border: 1.5px solid var(--border);
  background: var(--card);
  color: var(--text);
  font-family: inherit;
  font-size: var(--txt-md);
}

/* --- Un diagramme en barres, mois par mois -------------------------------- */
.barre-mois {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 9px;
}
.barre-mois-libelle {
  width: 40px;
  flex-shrink: 0;
  font-size: var(--txt-xs);
  color: var(--text-soft);
}
/* Pour l'avancement des formations, le libellé est un nom de client : il lui
   faut la place d'être lu, et d'être cliqué. */
.barre-mois-libelle-large {
  width: 190px;
  color: var(--text);
  font-size: var(--txt-sm);
}
.barre-mois-piste {
  flex: 1;
  min-width: 0;
  background: var(--border);
  border-radius: 6px;
  height: 16px;
  overflow: hidden;
}
.barre-mois-valeur {
  height: 100%;
  background: var(--coral);
  border-radius: 6px;
}
.barre-mois-texte {
  width: 210px;
  flex-shrink: 0;
  text-align: right;
  font-size: var(--txt-xs);
  line-height: 1.4;
}
.barre-mois-vide { color: var(--text-soft); }

/* Sur un écran étroit, le texte passe sous la barre plutôt que de l'écraser. */
@media (max-width: 1100px) {
  .barre-mois { flex-wrap: wrap; }
  .barre-mois-texte { width: 100%; text-align: left; }
}

/* ---------------------------------------------------------------------------
   L'identité de l'entreprise, et les colonnes de l'import
   ===========================================================================
   « Pour la section d'import, il faut ajouter des champs car il n'y en a pas
   assez et donc on importe pas des dossiers assez complet. » (24/09/2026)

   Le SIRET et l'adresse étaient déjà en base, saisissables à la création, et
   affichés nulle part. Les huit champs d'identité ont maintenant leur bloc en
   bas de la fiche, séparé du reste par un filet plutôt que par un panneau de
   plus : c'est une suite de l'en-tête, pas une autre section.

   Aucune teinte nouvelle : --border pour les filets, --coral pour les liens.
--------------------------------------------------------------------------- */

.fiche-identite {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
.fiche-identite h4 {
  margin: 0 0 8px;
  font-size: var(--txt-sm);
  color: var(--text-soft);
  font-weight: 700;
}
.fiche-identite-liste {
  font-size: var(--txt-md);
  line-height: 2;
  color: var(--text-soft);
}
.fiche-identite-liste b { color: var(--text); }
.fiche-identite-liste a {
  color: var(--coral);
  /* Un lien vers un site externe s'annonce : sans souligné, il ne se
     distingue du texte voisin que par la couleur. */
  text-decoration: underline;
  text-underline-offset: 2px;
  /* Une URL sans espace déborderait de la colonne. */
  overflow-wrap: anywhere;
}
.fiche-identite-titre-edition {
  margin: 16px 0 8px;
  font-size: var(--txt-sm);
  color: var(--text-soft);
  font-weight: 700;
}

/* --- L'aperçu d'import dit ce qu'il a reconnu ----------------------------- */
/* Un en-tête mal orthographié se voit ici, et non une fois les dossiers
   créés : la ligne reste, mais ses colonnes ne sont pas reprises. */
.import-colonnes-lues {
  font-size: var(--txt-xs);
  color: var(--text-soft);
  font-style: italic;
}

/* --- La liste des colonnes reconnues, repliée par défaut ------------------ */
.colonnes-import {
  margin-bottom: 16px;
  border: 1px solid var(--border);
  border-radius: 9px;
  background: var(--bg);
}
.colonnes-import > summary {
  cursor: pointer;
  padding: 10px 14px;
  font-size: var(--txt-sm);
  font-weight: 600;
  list-style-position: inside;
}
.colonnes-import > summary:hover { color: var(--coral); }
.colonnes-import p,
.colonnes-import ol {
  margin: 0 14px 10px;
  font-size: var(--txt-sm);
  color: var(--text-soft);
  line-height: var(--ligne-texte);
}
.colonnes-import ol { padding-left: 20px; }
.colonnes-import b { color: var(--text); }

/* ---------------------------------------------------------------------------
   Joindre un PDF à un message
   ===========================================================================
   « On doit pouvoir s'envoyer des fichiers au format PDF dans les messages. »
   (24/09/2026)

   Trois éléments : le trombone à côté du champ de saisie, la pastille du
   fichier choisi avant l'envoi, et le lien de téléchargement dans la bulle.

   Aucune teinte nouvelle : --border, --bg, --text-soft et --coral, plus le
   blanc des bulles envoyées, qui existe déjà dans app.css.
--------------------------------------------------------------------------- */

.message-trombone {
  width: auto;
  padding: 9px 12px;
  border-radius: 20px;
  flex-shrink: 0;
  /* Le picto seul doit rester centré quelle que soit la hauteur du champ. */
  display: inline-flex;
  align-items: center;
}

/* --- La pastille du fichier choisi, avant l'envoi ------------------------- */
.piece-jointe-choisie {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
  padding: 7px 10px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg);
  font-size: var(--txt-sm);
  color: var(--text);
}
.piece-jointe-choisie span {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.piece-jointe-retirer {
  border: 0;
  background: none;
  cursor: pointer;
  color: var(--text-soft);
  font-size: var(--txt-lg);
  line-height: 1;
  padding: 0 4px;
}
.piece-jointe-retirer:hover { color: var(--magenta); }

/* --- Le lien de téléchargement, dans la bulle ----------------------------- */
/* Une bulle peut ne contenir que le fichier : la marge du haut ne s'applique
   donc que lorsqu'un texte le précède. */
.piece-jointe {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
  padding: 8px 10px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--text);
  text-decoration: none;
  font-size: var(--txt-sm);
}
.piece-jointe:first-child { margin-top: 0; }
.piece-jointe:hover { border-color: var(--coral); color: var(--coral); }
.piece-jointe-nom {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
}
.piece-jointe-taille {
  flex-shrink: 0;
  color: var(--text-soft);
  font-size: var(--txt-xs);
}
/* Dans une bulle envoyée (fond --navy), le cadre clair ne se verrait pas. */
.piece-jointe-moi {
  background: rgba(255, 255, 255, .12);
  border-color: rgba(255, 255, 255, .28);
  color: #fff;
}
.piece-jointe-moi:hover {
  background: rgba(255, 255, 255, .2);
  border-color: rgba(255, 255, 255, .5);
  color: #fff;
}
.piece-jointe-moi .piece-jointe-taille { color: rgba(255, 255, 255, .72); }

/* ---------------------------------------------------------------------------
   Enchaîner les dossiers
   ===========================================================================
   « Ajouter à gauche un bouton "Dossier précédent" et un bouton à droite
   "Dossier suivant", qui nous permettra de fluidifier les traitements de
   dossier lorsqu'on les enchaîne à la suite. » (24/09/2026)

   Les deux boutons encadrent le retour à la liste, et le compteur de position
   dit où l'on en est : « 12 / 47 » vaut mieux que deux flèches aveugles.

   Un bouton désactivé garde sa place plutôt que de disparaître : une barre
   dont les éléments bougent d'un dossier à l'autre se relit à chaque fois.
--------------------------------------------------------------------------- */

.fiche-navigation {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 16px;
  flex-wrap: wrap;
}
/* Le compteur pousse « Dossier suivant » à droite, quelle que soit la largeur
   du bouton de retour. */
.fiche-position {
  margin-left: auto;
  font-size: var(--txt-sm);
  color: var(--text-soft);
  font-variant-numeric: tabular-nums;
}
.fiche-navigation .btn[disabled] {
  opacity: .45;
  cursor: not-allowed;
}
.fiche-navigation .btn[disabled]:hover {
  /* Sans cela, le survol laisse croire que le bouton répond encore. */
  border-color: var(--border);
  color: inherit;
  background: inherit;
}

/* ---------------------------------------------------------------------------
   Corriger un contact
   ===========================================================================
   Le bouton reste discret : on ouvre cet onglet pour lire des coordonnées,
   pas pour les modifier.
--------------------------------------------------------------------------- */

.contact-modifier {
  width: auto;
  padding: 6px 12px;
  font-size: var(--txt-sm);
  flex-shrink: 0;
}

/* ---------------------------------------------------------------------------
   Sélectionner plusieurs dossiers, et agir sur tous à la fois
   ===========================================================================
   « Tout sélectionner » et « supprimer » / « assigner à un autre commercial »
   dans l'écran Dossiers (24/09/2026).

   La barre n'apparaît qu'une fois des dossiers cochés : un bouton
   « Supprimer » toujours à l'écran finirait par être cliqué sans qu'on le
   veuille. Elle emprunte le --magenta de la charte, déjà employé par la
   « Zone sensible » d'une fiche — c'est le même genre de geste.
--------------------------------------------------------------------------- */

.barre-selection {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 14px;
  padding: 10px 14px;
  border: 1.5px solid var(--coral);
  border-radius: 11px;
  background: rgba(245, 96, 88, .08);
}
.barre-selection-compte {
  font-size: var(--txt-sm);
  font-weight: 700;
  color: var(--text);
  /* Le compte pousse les boutons à droite, et sa largeur ne saute pas d'un
     nombre à l'autre. */
  margin-right: auto;
  font-variant-numeric: tabular-nums;
}
.barre-selection .btn,
.barre-selection .champ-filtre {
  width: auto;
  padding: 7px 13px;
  font-size: var(--txt-sm);
}
/* Le geste destructeur ne se distingue pas des autres par sa seule place :
   il porte la couleur d'alerte, comme « Supprimer ce dossier ». */
.barre-selection-supprimer {
  border-color: var(--magenta);
  color: var(--magenta);
}
.barre-selection-supprimer:hover {
  background: rgba(240, 64, 93, .1);
  border-color: var(--magenta);
  color: var(--magenta);
}

/* --- La colonne des cases ------------------------------------------------- */
.colonne-selection {
  width: 34px;
  text-align: center;
  /* La case ne doit pas se comporter comme le reste de la ligne, qui ouvre le
     dossier au clic. */
  cursor: default;
}
.colonne-selection input[type="checkbox"] {
  width: 16px;
  height: 16px;
  cursor: pointer;
  accent-color: var(--coral);
}

/* ---------------------------------------------------------------------------
   Sélectionner plusieurs dossiers, et agir sur tous à la fois
   ===========================================================================
   « Tout sélectionner » et « supprimer » / « assigner à un autre commercial »
   dans l'écran Dossiers (24/09/2026).

   La barre n'apparaît qu'une fois des dossiers cochés : un bouton
   « Supprimer » toujours à l'écran finirait par être cliqué sans qu'on le
   veuille. Elle emprunte le --magenta de la charte, déjà employé par la
   « Zone sensible » d'une fiche — c'est le même genre de geste.
--------------------------------------------------------------------------- */

.barre-selection {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 14px;
  padding: 10px 14px;
  border: 1.5px solid var(--coral);
  border-radius: 11px;
  background: rgba(245, 96, 88, .08);
}
.barre-selection-compte {
  font-size: var(--txt-sm);
  font-weight: 700;
  color: var(--text);
  /* Le compte pousse les boutons à droite, et sa largeur ne saute pas d'un
     nombre à l'autre. */
  margin-right: auto;
  font-variant-numeric: tabular-nums;
}
.barre-selection .btn,
.barre-selection .champ-filtre {
  width: auto;
  padding: 7px 13px;
  font-size: var(--txt-sm);
}
/* Le geste destructeur ne se distingue pas des autres par sa seule place :
   il porte la couleur d'alerte, comme « Supprimer ce dossier ». */
.barre-selection-supprimer {
  border-color: var(--magenta);
  color: var(--magenta);
}
.barre-selection-supprimer:hover {
  background: rgba(240, 64, 93, .1);
  border-color: var(--magenta);
  color: var(--magenta);
}

/* --- La colonne des cases ------------------------------------------------- */
.colonne-selection {
  width: 34px;
  text-align: center;
  /* La case ne doit pas se comporter comme le reste de la ligne, qui ouvre le
     dossier au clic. */
  cursor: default;
}
.colonne-selection input[type="checkbox"] {
  width: 16px;
  height: 16px;
  cursor: pointer;
  accent-color: var(--coral);
}

/* --- Une ligne de stagiaire : prénom, nom, adresse ------------------------ */
/* Trois champs côte à côte dans un flex qui ne revenait jamais à la ligne. Sur
   un écran étroit, l'adresse se retrouvait réduite à une dizaine de
   caractères : impossible de la lire, encore moins de la vérifier avant
   d'envoyer un accès e-learning dessus.

   Même remède que pour .etape-corps .list-row : on autorise le retour à la
   ligne, ici seulement. Les largeurs de base sont choisies pour que les trois
   restent côte à côte sur un écran large, et que l'adresse descende seule —
   donc sur toute la largeur — dès qu'elles ne tiennent plus. */
.ligne-stagiaire {
  flex-wrap: wrap;
  gap: 8px;
}
/* Sans min-width, un champ de saisie refuse de descendre sous sa largeur par
   défaut (une vingtaine de caractères) et fait déborder la ligne. */
.ligne-stagiaire input {
  min-width: 0;
}
.ligne-stagiaire .champ-prenom,
.ligne-stagiaire .champ-nom {
  flex: 1 1 110px;
}
.ligne-stagiaire .champ-email {
  flex: 2 1 210px;
}

/* --- Les deux colonnes de la fiche d'un dossier --------------------------- */
/* La grille restait à deux colonnes quelle que soit la largeur de l'écran. La
   colonne de gauche — en-tête, assistant, détail de la formation — tombait à
   une cinquantaine de pixels sur un écran de téléphone : les champs de saisie
   y devenaient illisibles, l'adresse d'un stagiaire la première.

   En dessous de mille pixels, les deux colonnes se mettent l'une sous
   l'autre : chacune prend alors toute la largeur.

   `!important` est ici le seul moyen : les proportions de cette grille sont
   posées par un attribut `style` sur la balise elle-même, et aucun sélecteur,
   même le plus précis, ne l'emporte sur un style en ligne. La règle est
   limitée à la grille de la fiche et à cette largeur d'écran. */
@media (max-width: 1000px) {
  #view-fiche > .row-2 {
    grid-template-columns: minmax(0, 1fr) !important;
  }
}

/* --- La ligne du membre choisi, dans le comparatif ------------------------ */
/* Le comparatif entre commerciaux ignore volontairement le filtre par membre :
   comparer suppose de voir tout le monde, et son sous-titre le dit. Mais quand
   quelqu'un est choisi en haut de l'écran, sa ligne doit se retrouver sans la
   chercher dans un tableau de dix noms.

   Le filet à gauche porte l'information autant que le fond : une ligne
   légèrement plus claire ne se remarquerait pas sur un écran mal réglé. */
.ligne-membre-choisi > td {
  background: rgba(245, 96, 88, .07);
  font-weight: 600;
}
.ligne-membre-choisi > td:first-child {
  box-shadow: inset 3px 0 0 var(--coral);
}

/* ---------------------------------------------------------------------------
   Le tableau de bord d'un commercial
   ===========================================================================
   « Lorsqu'on clique sur un commercial, j'aimerais vraiment voir un tableau de
   bord plus poussé avec plus de statistiques commerciales, avec des
   graphiques. » (28/09/2026)

   Tout est dessiné en HTML et en CSS. Aucune bibliothèque de graphiques : la
   consigne du projet est de ne dépendre d'aucun CDN extérieur sans avoir
   vérifié sa compatibilité avec l'hébergement, et la politique de sécurité de
   la page (script-src 'self') interdit de toute façon un script tiers.

   Aucune teinte nouvelle : --navy, --coral, --magenta, --border, --text-soft,
   et les deux fonds translucides que css/app.css emploie déjà.
--------------------------------------------------------------------------- */

/* La fenêtre est large : un tableau de bord tient mal dans 440 px. */
.modal-box.modal-large {
  width: 1060px;
  max-width: 94vw;
}

/* --- Un graphique en colonnes --------------------------------------------- */
.graphe-colonnes {
  display: flex;
  align-items: flex-end;
  gap: 6px;
}
.graphe-colonnes .colonne {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}
.colonne-piste {
  width: 100%;
  height: var(--hauteur-graphe, 130px);
  display: flex;
  align-items: flex-end;
  background: rgba(11, 65, 122, .06);
  border-radius: 6px;
  overflow: hidden;
}
.colonne-barre {
  width: 100%;
  min-height: 2px;
  background: var(--navy);
  border-radius: 6px 6px 0 0;
  /* La barre pousse depuis le bas quand le graphique s'affiche : le regard
     suit le mouvement et comprend l'échelle sans la lire. */
  transition: height .4s cubic-bezier(.22, .61, .36, 1);
}
.colonne-barre.coral { background: var(--coral); }
.colonne-nom,
.colonne-valeur {
  font-size: var(--txt-xs);
  color: var(--text-soft);
  line-height: 1.3;
  white-space: nowrap;
}
.colonne-valeur { font-weight: 650; color: var(--text); }
/* Le mois en cours se distingue sans couleur supplémentaire. */
.graphe-colonnes .colonne.courant .colonne-nom {
  color: var(--coral);
  font-weight: 700;
}

/* --- Un graphique en barres horizontales ----------------------------------
   L'étiquette et le chiffre au-dessus, la barre en dessous sur toute la
   largeur. Les trois sur une seule ligne, comme on l'écrit d'abord, ne
   laissaient plus rien à la barre dans une colonne de trois cents pixels :
   elle se réduisait à un trait. C'est aussi la forme que l'encadré
   « Performance par source » emploie déjà dans les statistiques. */
.graphe-barres { display: flex; flex-direction: column; gap: 11px; }
.barre-entete {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 4px;
}
.barre-etiquette {
  font-size: var(--txt-xs);
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.barre-piste {
  /* C'est un <span> : sans display:block, la hauteur ne s'applique pas et la
     barre disparaît purement et simplement. */
  display: block;
  height: 10px;
  background: rgba(11, 65, 122, .06);
  border-radius: 6px;
  overflow: hidden;
  min-width: 0;
}
.barre-remplissage {
  display: block;
  height: 100%;
  background: var(--navy);
  border-radius: 6px;
  transition: width .4s cubic-bezier(.22, .61, .36, 1);
}
.barre-remplissage.coral { background: var(--coral); }
.barre-chiffre {
  flex-shrink: 0;
  font-size: var(--txt-xs);
  color: var(--text-soft);
  font-variant-numeric: tabular-nums;
}

/* --- Les encadrés du tableau de bord -------------------------------------- */
.membre-grille {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 16px;
  align-items: start;
}
.membre-bloc {
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 14px 16px;
}
.membre-bloc h4 {
  margin: 0 0 3px;
  font-size: var(--txt-sm);
  font-weight: 700;
}
.membre-bloc .sous {
  font-size: var(--txt-xs);
  color: var(--text-soft);
  margin: 0 0 12px;
}
.membre-vide {
  font-size: var(--txt-xs);
  color: var(--text-soft);
  font-style: italic;
  padding: 10px 0;
}

/* --- Les adresses mail supplémentaires ------------------------------------
   « On doit pouvoir ajouter plusieurs adresses mails pour une même personne,
   une adresse mail peut être liée à une entreprise, à une personne. »
   (28/09/2026)

   Elles se rangent sous la personne — ou sous l'entreprise — à qui elles
   appartiennent, en retrait, pour qu'on voie d'un coup d'œil ce qui dépend de
   quoi sans que la liste des contacts double de hauteur. */
.adresses-supplementaires {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 6px;
}
.ligne-adresse {
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: wrap;
  font-size: var(--txt-xs);
  color: var(--text-soft);
}
.ligne-adresse .ico { flex-shrink: 0; }
.etiquette-adresse {
  font-size: var(--txt-xs);
  font-weight: 600;
  color: var(--text-soft);
  background: var(--border);
  border-radius: 20px;
  padding: 1px 8px;
}
/* Les deux gestes restent discrets tant qu'on ne survole pas la ligne : ils
   ne doivent pas concurrencer l'adresse elle-même, qui est l'information. */
.bouton-adresse {
  padding: 2px 8px;
  font-size: var(--txt-xs);
  opacity: .55;
  transition: opacity .15s ease;
}
.ligne-adresse:hover .bouton-adresse,
.bouton-adresse:focus-visible { opacity: 1; }
.bouton-adresse-retirer { color: var(--magenta); }
.bouton-ajouter-adresse {
  padding: 2px 8px;
  font-size: var(--txt-xs);
  align-self: flex-start;
}
/* Le bloc de l'entreprise, au-dessus des personnes : c'est le même objet
   qu'un contact, mais il n'appartient à personne. */
.bloc-entreprise .avatar { background: var(--coral); }

/* ===========================================================================
   Ergonomie : micro-interactions, densité, retours, cohérence
   ===========================================================================
   « En terme d'UX il n'y a pas grand-chose de fait. C'est un CRM où on passe
   notre journée dessus. Il faudrait une bonne UX. » (28/09/2026)

   Quatre axes retenus avec la direction, et rien d'autre :

     1. LES MICRO-INTERACTIONS. Un geste doit se sentir. Rien de spectaculaire
        — sur un outil qu'on manipule huit heures par jour, une animation qui
        se remarque au bout de trois fois devient insupportable à la
        trentième. Des durées courtes (80 à 200 ms) et des amplitudes d'un ou
        deux pixels.
     2. LA DENSITÉ ET LA LISIBILITÉ. Les en-têtes de colonne restent sous les
        yeux quand on descend une liste de deux cents dossiers, et les
        chiffres s'alignent verticalement.
     3. LES RETOURS ET LES ERREURS. Un message qui annonce une réussite et un
        message qui annonce un échec ne se ressemblaient pas seulement : ils
        étaient IDENTIQUES. Le bandeau porte maintenant sa couleur, son icône,
        et reste plus longtemps quand il y a un problème à lire.
     4. LA COHÉRENCE VISUELLE. Un seul anneau de focus pour toute
        l'application, une seule façon de réagir au survol, une seule façon de
        s'enfoncer sous le clic.

   Aucune teinte nouvelle : les variables de la charte, et les deux couleurs
   d'état que le prototype employait déjà.

   Tout ce qui bouge ici est neutralisé par le bloc
   `@media (prefers-reduced-motion: reduce)` du haut de ce fichier.
--------------------------------------------------------------------------- */

/* --- 1. Les boutons répondent au doigt ------------------------------------ */
/* `.btn` n'avait ni survol, ni état enfoncé, ni état désactivé : rien ne
   distinguait un bouton d'une étiquette, et un bouton mis en attente pendant
   une requête gardait exactement la même apparence. */
.btn {
  transition: background .15s ease, border-color .15s ease, color .15s ease,
              transform .08s ease, box-shadow .15s ease;
}
.btn:hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(11, 65, 122, .13); }
.btn:active { transform: translateY(1px) scale(.985); box-shadow: none; }
.btn.ghost:hover { background: var(--bg); border-color: var(--navy); }
.btn:disabled,
.btn[disabled] {
  opacity: .5;
  cursor: progress;
  transform: none;
  box-shadow: none;
}

/* --- 2. Un seul anneau de focus, pour toute l'application ----------------- */
/* Il n'y en avait aucun : au clavier, on ne savait pas où l'on était.
   `:focus-visible` ne l'affiche qu'à qui navigue au clavier — la souris ne
   laisse pas de halo derrière elle. */
:focus-visible {
  outline: 2px solid var(--coral);
  outline-offset: 2px;
}
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline-offset: 0;
  border-color: var(--coral);
}
input, select, textarea {
  transition: border-color .15s ease, box-shadow .15s ease;
}

/* --- 3. Ce qui se clique le dit ------------------------------------------- */
.list-row[data-action],
.tab,
.nav-item,
.qualite-tab-btn {
  transition: background .13s ease, color .13s ease, border-color .13s ease;
}
.list-row[data-action] { border-radius: 8px; }
.list-row[data-action]:hover { background: var(--bg); }
.tab:hover { color: var(--text); }

/* --- 4. Les en-têtes de colonne restent sous les yeux --------------------- */
/* Sur une liste de deux cents dossiers, on descend et on ne sait plus quelle
   colonne on lit.

   C'est le `<thead>` ENTIER qui se colle, et non chaque cellule : la liste des
   dossiers en a deux lignes — les intitulés et les filtres — et les coller
   séparément aurait demandé de connaître la hauteur de la première, qui change
   avec la largeur de l'écran dès qu'un intitulé passe sur deux lignes.

   `top` est NÉGATIF de la valeur du rembourrage de #content : le conteneur de
   défilement, c'est lui, et son rembourrage fait partie de la zone qui défile.
   Avec `top: 0`, l'en-tête s'arrêtait vingt-huit pixels trop bas et les lignes
   du tableau défilaient dans la bande laissée libre. */
/* `.panel { overflow: hidden }` ferait du panneau un conteneur de défilement :
   l'en-tête s'y collerait, c'est-à-dire ne bougerait pas. Les panneaux qui
   portent un tableau laissent donc déborder, et rattrapent eux-mêmes
   l'arrondi que le débordement caché leur donnait. */
.panel:has(> table) { overflow: visible; }
.panel:has(> table) > table > thead > tr:first-child > th:first-child {
  border-top-left-radius: var(--radius);
}
.panel:has(> table) > table > thead > tr:first-child > th:last-child {
  border-top-right-radius: var(--radius);
}
/* Le rembourrage passe de la zone de défilement aux écrans eux-mêmes. Il
   faisait partie de ce qui défile : un élément collant s'arrêtait donc
   vingt-huit pixels trop bas, et les lignes du tableau défilaient dans la
   bande ainsi laissée libre, au-dessus de l'en-tête. Déplacé sur les écrans,
   il est exactement le même à l'œil, et le haut de la zone de défilement
   devient le haut de l'écran. */
#content { padding: 0; }
#content > .view { padding: var(--sp-xl); }

thead {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--card);
}
thead th { background: var(--card); }

/* --- 5. Les chiffres s'alignent ------------------------------------------- */
/* Des chiffres à chasse variable ne s'empilent pas : une colonne de montants
   devient illisible dès qu'on la parcourt du regard. */
.kpi-card .value,
.barre-chiffre,
.colonne-valeur,
td .score {
  font-variant-numeric: tabular-nums;
}

/* --- 6. Un message de réussite et un message d'échec ne se ressemblent pas - */
#toast {
  display: flex;
  align-items: center;
  gap: 10px;
  border-left: 4px solid var(--navy);
}
#toast .ico { flex-shrink: 0; }
#toast.succes { border-left-color: #2E9E5B; }
#toast.succes .ico { color: #2E9E5B; }
#toast.erreur { border-left-color: var(--magenta); }
#toast.erreur .ico { color: var(--magenta); }

/* --- 7. Les fenêtres s'ouvrent, elles n'apparaissent pas ------------------ */
/* Une fenêtre qui surgit d'un coup fait perdre le fil : on ne sait pas d'où
   elle vient ni ce qu'elle recouvre. Deux dixièmes de seconde suffisent. */
.modal-overlay.visible { animation: voile-entre .18s ease; }
.modal-overlay.visible .modal-box { animation: fenetre-entre .22s cubic-bezier(.22, .61, .36, 1); }
@keyframes voile-entre { from { opacity: 0; } }
@keyframes fenetre-entre {
  from { opacity: 0; transform: translateY(12px) scale(.985); }
}

/* --- 8. Les grilles à deux colonnes se replient sur un écran étroit ------- */
/* Elles restaient à deux colonnes quelle que soit la largeur : sur un écran
   de portable en fenêtre partagée, chaque colonne tombait sous les trois
   cents pixels et plus rien n'était lisible.

   Les deux `!important` visent des grilles dont les proportions sont posées
   par un attribut `style` — sur la balise pour l'écran Équipe, depuis le
   JavaScript pour Ma journée. Aucun sélecteur, si précis soit-il, ne
   l'emporte sur un style en ligne. */
@media (max-width: 900px) {
  .row-2 { grid-template-columns: minmax(0, 1fr); }
  #equipe-commerciaux,
  #ma-journee-missions-row { grid-template-columns: minmax(0, 1fr) !important; }
  .kpi-grid { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
}

/* --- Le nouveau logo (28/09/2026) : un mot, plus large que haut ------------ */
#logo-wrap img { max-width: 220px; }

/* --- Les bases importées se feuillettent (28/09/2026) --------------------- */
.pagination-bases {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-top: 12px;
  font-size: 12.5px;
  color: var(--text-soft);
}
.pagination-bases .btn { width: auto; padding: 6px 12px; font-size: 12.5px; }
.pagination-bases .btn[disabled] { opacity: .45; cursor: default; }

/* --- Le bleu de la charte, sur fond sombre (29/09/2026) ---------------------
   Le bleu du logo (--navy) sert de texte et de marque un peu partout. Sur
   les fonds du thème sombre — eux-mêmes tirés de ce bleu — il ne se lit
   plus : la forme éclaircie (#8fb3de, déjà admise pour les en-têtes de
   colonne) le remplace là où il fait du texte ou une marque fine. Les fonds
   pleins (boutons, avatars) gardent le bleu, sous du texte blanc. */
[data-theme="dark"] .kpi-card .value.navy,
[data-theme="dark"] .session-card .heure,
[data-theme="dark"] .mode-badge.visio,
[data-theme="dark"] .score.cold,
[data-theme="dark"] .finance.cpf,
[data-theme="dark"] .opp-card .opp-amount,
[data-theme="dark"] .pill.rdv,
[data-theme="dark"] .kcard .amount,
[data-theme="dark"] .tab.active,
[data-theme="dark"] .pastille-cold { color: #8fb3de; }
[data-theme="dark"] .tab.active { border-bottom-color: #8fb3de; }
[data-theme="dark"] .gr,
[data-theme="dark"] .gr-etincelle { --gr-couleur: #8fb3de; }
[data-theme="dark"] .gr.coral,
[data-theme="dark"] .gr-etincelle.coral { --gr-couleur: var(--coral); }
[data-theme="dark"] .gr-etincelle.magenta { --gr-couleur: var(--magenta); }
[data-theme="dark"] .gr-jauge { --gr-couleur: var(--coral); }
[data-theme="dark"] .gr-jauge.atteint { --gr-couleur: #2E9E5B; }

/* --- La version du CRM, et le fil « CRM Allokom » (29/09/2026) -------------
   « Savoir combien de MAJ nous avons faites. » La version se lit en bas des
   pages, discrète ; le fil des nouveautés se lit en cartes, une par version. */
.version-crm {
  margin-top: 18px;
  text-align: center;
  font-size: var(--txt-xs);
  color: var(--text-soft);
  letter-spacing: .04em;
  text-transform: uppercase;
}
.version-crm:empty { display: none; }
.version-crm-page { margin: 28px auto 4px; }
.maj-carte {
  border: 1px solid var(--border);
  border-left: 4px solid var(--coral);
  border-radius: 12px;
  padding: 12px 16px;
  margin-bottom: 12px;
  background: var(--card);
}
.maj-entete { display: flex; align-items: baseline; gap: 10px; margin-bottom: 4px; }
.maj-version {
  font-family: 'Poppins', sans-serif;
  font-weight: 700;
  font-size: var(--txt-lg);
  color: var(--navy);
}
[data-theme="dark"] .maj-version { color: #8fb3de; }
.maj-date { font-size: var(--txt-xs); color: var(--text-soft); }
.maj-titre { font-weight: 600; margin-bottom: 6px; }
.maj-points { margin: 0; padding-left: 18px; font-size: var(--txt-sm); line-height: var(--ligne-texte); }
.maj-points li { margin-bottom: 2px; }

/* --- Le fil « CRM Allokom » : son avatar, sa dernière version --------------- */
.conv-avatar-crm { background: #FFF; padding: 0; overflow: hidden; border: 1px solid var(--border); }
.avatar-crm { object-fit: contain; padding: 3px; box-sizing: border-box; }
.maj-carte.maj-recente { border-left-color: var(--brand-red); }
.maj-nouveau {
  margin-left: auto;
  padding: 2px 9px;
  border-radius: 20px;
  background: var(--brand-red);
  color: #FFF;
  font-size: var(--txt-xs);
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
}

/* --- Le Planning : les rendez-vous commerciaux (30/09/2026) ----------------- */
/* Une relance qui a une heure. Bord corail sur fond de carte : elle se
   distingue des séances, pleines et à la couleur du formateur. */
.planning-rdv-pill {
  background: var(--card);
  color: var(--coral);
  border: 1.5px solid var(--coral);
}

/* ===========================================================================
   Les tâches se corrigent, et les explications se replient (01/10/2026)
   =========================================================================== */
/* Les boutons d'une ligne de la chronologie du dossier : à droite, discrets,
   comme ceux d'une relance. */
.timeline-boutons { display: flex; gap: 6px; align-items: flex-start; flex-shrink: 0; margin-left: auto; }
.timeline-boutons .btn { padding: 4px 9px; font-size: var(--txt-xs); }

/* « Ces textes prennent beaucoup trop de place : un petit (i) déroulant. »
   Un <details> natif : fermé, une ligne avec le rond (i) ; ouvert, la
   définition et ses points. Aucun script. */
.aide-ecran { margin: 0 0 14px; }
.aide-ecran summary {
  display: inline-flex; align-items: center; gap: 8px;
  cursor: pointer; list-style: none; user-select: none;
  font-size: var(--txt-sm); color: var(--text-soft);
  padding: 4px 10px 4px 4px; border-radius: 20px;
  transition: background .14s ease, color .14s ease;
}
.aide-ecran summary::-webkit-details-marker { display: none; }
.aide-ecran summary:hover, .aide-ecran[open] summary { color: var(--text); background: var(--card); }
.aide-ecran-i {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 50%; flex-shrink: 0;
  border: 1.5px solid var(--text-soft); color: var(--text-soft);
  font-family: 'Poppins', 'Century Gothic', sans-serif; font-weight: 700; font-size: var(--txt-xs);
  font-style: italic; line-height: 1;
}
.aide-ecran[open] .aide-ecran-i { border-color: var(--navy); color: var(--navy); }
.aide-ecran-corps {
  margin-top: 8px; padding: 12px 16px;
  background: var(--card); border: 1px solid var(--border); border-radius: 12px;
  max-width: 720px;
}
.aide-ecran-corps .definition-ecran { margin-bottom: 6px; }

/* ===========================================================================
   Nouveau mois, nouveaux objectifs (13/10/2026)
   =========================================================================== */
.objectifs-mois-box { border: 2px solid var(--navy); text-align: center; max-width: 480px; }
.objectifs-mois-bandeau {
  display: flex; align-items: center; justify-content: center;
  width: 54px; height: 54px; margin: 0 auto 14px; border-radius: 50%;
  background: rgba(11, 65, 122, .12); color: var(--navy);
}
.objectifs-mois-titre { color: var(--navy); font-weight: 800; font-size: var(--txt-2xl); line-height: var(--ligne-titre); margin-bottom: 10px; }
.objectifs-mois-texte { font-size: var(--txt-md); line-height: var(--ligne-texte); color: var(--text); margin-bottom: 10px; }
.objectifs-mois-noms { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; margin: 4px 0 6px; }
.objectifs-mois-noms span {
  font-size: var(--txt-sm); font-weight: 600; color: var(--navy);
  background: rgba(11, 65, 122, .08); border-radius: 999px; padding: 4px 10px;
}
.objectifs-mois-box .modal-actions { justify-content: center; }

/* Un message qui arrive : une notification en haut au milieu, comme sur un
   téléphone (13/10/2026), à part des autres bandeaux. */
.notif-message {
  position: fixed; top: 14px; left: 50%; z-index: 90;
  display: flex; align-items: center; gap: 12px;
  width: min(520px, calc(100vw - 32px)); padding: 12px 14px;
  background: var(--card); color: var(--text); border: 1px solid var(--border);
  border-left: 4px solid var(--coral); border-radius: 14px;
  box-shadow: 0 18px 50px rgba(0, 0, 0, .22);
  transform: translate(-50%, -140%); opacity: 0; pointer-events: none;
  transition: transform .32s cubic-bezier(.2, .9, .3, 1.1), opacity .25s ease;
  cursor: pointer;
}
.notif-message.visible { transform: translate(-50%, 0); opacity: 1; pointer-events: auto; }
.notif-message-avatar { flex-shrink: 0; display: flex; }
.notif-message-corps { flex: 1; min-width: 0; }
.notif-message-titre { font-size: var(--txt-md); font-weight: 700; color: var(--navy); }
.notif-message-de { font-weight: 500; color: var(--text-soft); }
.notif-message-extrait {
  font-size: var(--txt-sm); color: var(--text); margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.notif-message-voir {
  flex-shrink: 0; background: var(--coral); color: #FFF; border: 0; border-radius: 999px;
  padding: 7px 14px; font-size: var(--txt-sm); font-weight: 700; cursor: pointer; font-family: inherit;
}
.notif-message-fermer {
  flex-shrink: 0; background: none; border: 0; color: var(--text-soft); cursor: pointer;
  font-size: var(--txt-lg); line-height: 1; padding: 2px 4px; font-family: inherit;
}

/* ===========================================================================
   Emojis et GIF dans la messagerie (13/10/2026)
   =========================================================================== */
.messagerie-saisie { position: relative; }
.message-emoji, .message-gif {
  flex-shrink: 0; padding: 8px 10px; border-radius: 20px; font-family: inherit;
}
.message-gif { font-size: var(--txt-xs); font-weight: 800; letter-spacing: .04em; }
.message-emoji.actif, .message-gif.actif { background: rgba(11, 65, 122, .10); border-color: var(--navy); color: var(--navy); }
.eg-panneau {
  position: absolute; left: 0; right: 0; bottom: calc(100% + 8px); z-index: 20;
  background: var(--card); border: 1px solid var(--border); border-radius: 14px;
  box-shadow: 0 18px 50px rgba(0, 0, 0, .18); padding: 10px 12px; max-height: 320px;
  display: flex; flex-direction: column; gap: 8px;
}
.eg-panneau[hidden] { display: none; }
.eg-entete {
  display: flex; align-items: center; justify-content: space-between;
  font-size: var(--txt-sm); font-weight: 700; color: var(--navy);
}
.eg-fermer { background: none; border: 0; color: var(--text-soft); cursor: pointer; font-size: var(--txt-lg); line-height: 1; padding: 0 4px; font-family: inherit; }
.eg-emojis { overflow-y: auto; }
.eg-famille { font-size: var(--txt-xs); font-weight: 600; color: var(--text-soft); text-transform: uppercase; letter-spacing: .04em; margin: 6px 0 4px; }
.eg-grille-emojis { display: flex; flex-wrap: wrap; gap: 2px; }
.eg-emoji {
  width: 34px; height: 34px; border: 0; background: none; border-radius: 8px;
  font-size: var(--txt-xl); line-height: 1; cursor: pointer; font-family: inherit;
}
.eg-emoji:hover { background: rgba(11, 65, 122, .10); transform: scale(1.15); }
.eg-recherche {
  width: 100%; padding: 8px 12px; border-radius: 10px; border: 1px solid var(--border);
  background: var(--bg); color: var(--text); font-family: inherit; font-size: var(--txt-md);
}
/* Le panneau des GIF (16/10/2026) : « plus haut, moins large », et des
   cases de hauteur fixe — avec des hauteurs laissées au contenu, les GIF se
   chevauchaient. La grille défile, le panneau garde sa hauteur. */
.eg-panneau.eg-gifs { position: fixed; right: auto; width: 460px; max-width: calc(100vw - 24px); max-height: min(70vh, 600px); z-index: 60; }
.eg-grille-gifs {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); grid-auto-rows: 120px; gap: 8px;
  overflow-y: auto; min-height: 60px; flex: 1 1 auto; align-content: start; padding-right: 2px;
}
.eg-gif { display: block; height: 120px; padding: 0; border: 0; background: var(--bg); border-radius: 10px; overflow: hidden; cursor: pointer; }
.eg-gif img { width: 100%; height: 100%; object-fit: cover; display: block; }
.eg-gif:hover { outline: 2px solid var(--coral); }
.eg-vide { font-size: var(--txt-sm); color: var(--text-soft); padding: 10px 4px; grid-column: 1 / -1; align-self: start; }
.eg-source { font-size: var(--txt-xs); color: var(--text-soft); text-align: right; }
.msg-gif { display: block; max-width: 240px; max-height: 240px; border-radius: 10px; margin-top: 6px; }

/* ===========================================================================
   Tâches dans l'ordre, et repliées par client (13/10/2026)
   =========================================================================== */
.tache-bloquee .tache-check { opacity: .35; cursor: not-allowed; border-style: dashed; }
.tache-bloquee .tache-check:hover { transform: none; border-color: var(--border); }
.tache-bloquee-motif { font-size: var(--txt-xs); color: var(--text-soft); font-style: italic; margin-top: 2px; }
.tache-suite { padding: 0 20px 10px 62px; }
.tache-suite-bascule {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--txt-sm); font-weight: 600; color: var(--navy);
  background: none; border: 0; padding: 4px 0; cursor: pointer; font-family: inherit;
}
.tache-suite-bascule .ico { transition: transform .18s ease; }
.tache-suite-bascule.ouverte .ico { transform: rotate(180deg); }
.tache-suite-liste { margin-top: 4px; border-left: 2px solid var(--border); }
.tache-suite-liste[hidden] { display: none; }

/* ===========================================================================
   Messagerie : statut de lecture et suppression (13/10/2026)
   =========================================================================== */
.msg-statut {
  display: flex; align-items: center; justify-content: flex-end; gap: 4px;
  font-size: var(--txt-xs); color: var(--text-soft); margin-top: 3px;
}
.msg-statut.lu { color: var(--navy); }
.msg-supprimer {
  background: none; border: 0; padding: 2px; cursor: pointer; color: var(--text-soft);
  opacity: 0; transition: opacity .15s ease; font-family: inherit; font-size: var(--txt-xs);
}
.msg-ligne:hover .msg-supprimer, .msg-supprimer:focus { opacity: 1; }

/* ===========================================================================
   L'en-tête d'un écran sur une seule ligne (16/10/2026)
   ===========================================================================
   « Dans Relances, un grand espace dédié au petit (i) et aux boutons : bien
   trop grand. » Le (i) à gauche, les boutons à droite, sur une ligne ; le
   (i) déroulé s'étale sous la ligne, sans pousser les boutons.
--------------------------------------------------------------------------- */
.toolbar-aide { align-items: flex-start; gap: 12px; margin-bottom: 10px; }
.toolbar-aide .aide-ecran-ligne { flex: 1; min-width: 0; margin: 0; }
.toolbar-aide .aide-ecran-ligne summary { margin-top: 5px; }
.toolbar-actions { display: flex; gap: 8px; flex-shrink: 0; flex-wrap: wrap; justify-content: flex-end; }

/* ===========================================================================
   Le dégradé des cartes de chiffres (16/10/2026)
   ===========================================================================
   « Ce petit bleu qui s'estompe en blanc vers le bas fait vieillot. » Le
   même dégradé que le volet de l'assistant et les cartes de l'Équipe : en
   diagonale, du bleu au corail, à peine posé sur le fond. Pour les cartes
   de chiffres et les panneaux de « Ma journée » (app.css posait le dégradé
   vertical sur les deux).
--------------------------------------------------------------------------- */
.kpi-card,
.panel-dashed {
  background:
    radial-gradient(circle at 100% 0%, rgba(245,96,88,.055), transparent 45%),
    linear-gradient(135deg, rgba(11,65,122,.085), rgba(11,65,122,.02) 55%, rgba(248,184,65,.045)),
    var(--card);
}
[data-theme="dark"] .kpi-card,
[data-theme="dark"] .panel-dashed {
  background:
    radial-gradient(circle at 100% 0%, rgba(245,96,88,.08), transparent 45%),
    linear-gradient(135deg, rgba(255,255,255,.07), rgba(255,255,255,.02) 55%, rgba(248,184,65,.05)),
    var(--card);
}

/* ===========================================================================
   Petit écran (01/10/2026)
   ===========================================================================
   « Il faut le rendre responsive, sans casser la version desktop. » Tout ce
   qui suit ne s'applique qu'au-dessous de 900 px : au-dessus, pas une règle
   ne change. La barre de gauche devient un tiroir (public/js/mobile.js), la
   barre du haut se replie sur deux lignes, les grilles passent sur une
   colonne et les tableaux défilent de côté dans leur panneau.
--------------------------------------------------------------------------- */
#menu-burger { display: none; }
#menu-voile { display: none; }

@media (max-width: 900px) {
  /* Le tiroir. */
  #sidebar {
    position: fixed; top: 0; left: 0; bottom: 0; z-index: 70;
    width: 264px; min-width: 264px;
    transform: translateX(-100%);
    transition: transform .22s ease;
    box-shadow: none;
  }
  body.menu-ouvert #sidebar { transform: none; box-shadow: 0 0 40px rgba(0,0,0,.35); }
  #menu-voile { position: fixed; inset: 0; z-index: 69; background: rgba(0,0,0,.45); }
  body.menu-ouvert #menu-voile { display: block; }
  #menu-burger {
    display: inline-flex; align-items: center; justify-content: center;
    width: 38px; height: 38px; border-radius: 10px; flex-shrink: 0;
    border: 1px solid rgba(255,255,255,.22); background: rgba(255,255,255,.1); color: #FFF;
    cursor: pointer; padding: 0;
  }
  #menu-burger svg { width: 20px; height: 20px; }

  /* La barre du haut : titre et bouton sur la première ligne, raccourcis
     sur la seconde. */
  #topbar { padding: 12px 16px; flex-wrap: wrap; gap: 10px 12px; }
  #topbar > div:first-of-type { flex: 1; min-width: 0; }
  #topbar h1 { font-size: 17px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  #topbar .sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .quickbar { width: 100%; justify-content: flex-start; flex-wrap: wrap; }
  .search-box { width: auto; flex: 1; min-width: 0; padding: 8px 12px; }
  .search-box .kbd { display: none; }

  /* Le rembourrage est porté par les écrans (voir plus haut), pas par #content. */
  #content > .view { padding: 14px; }
  .toolbar { flex-wrap: wrap; gap: 8px; }
  .toolbar > * { min-width: 0; max-width: 100%; }
  .toolbar > div { flex-wrap: wrap; }
  /* Les lignes d'un encart d'assistance : le texte au-dessus des boutons. */
  .assistant-item { flex-wrap: wrap; row-gap: 8px; }

  /* Les grilles sur une colonne, les tuiles sur deux. */
  .kpi-grid, .kpi-grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .row-2, .io-grille, .suivi-colonnes, #view-fiche > .row-2 { grid-template-columns: minmax(0, 1fr) !important; }
  .panel { padding-left: 14px; padding-right: 14px; }

  /* Un tableau plus large que l'écran défile de côté, dans son panneau. La
     règle `.panel:has(> table) { overflow: visible }` du grand écran sert à
     coller l'en-tête du tableau ; ici, c'est le défilement qui compte. */
  .panel, .panel:has(> table) { overflow-x: auto; }
  .kpi-card { min-width: 0; }

  /* Les fenêtres prennent la largeur, moins une marge. */
  .modal-box { width: 100%; max-width: calc(100vw - 20px); padding: 18px 16px; max-height: 92vh; }
  .modal-actions { flex-wrap: wrap; }

  /* Le planning : sept colonnes tiennent, les pastilles se font courtes. */
  .planning-day { min-height: 54px; padding: 4px 3px; }
  .planning-session-pill { padding: 3px 4px; }
  .planning-pill-ligne2 { display: none; }

  /* La messagerie : la liste des conversations au-dessus du fil. */
  .messagerie { height: auto; min-height: 0; }
  .messagerie-liste { max-height: 220px; }
  .messagerie-saisie { flex-wrap: wrap; }

  /* La connexion. */
  .login-card { width: 100%; max-width: 400px; margin: 0 16px; padding: 26px 20px; }
}

@media (max-width: 560px) {
  .kpi-grid, .kpi-grid-4, .stats-tuiles { grid-template-columns: minmax(0, 1fr); }
  /* Les grilles réglées en ligne dans le HTML (deux ou trois colonnes). */
  .kpi-grid[style*="grid-template-columns"] { grid-template-columns: minmax(0, 1fr) !important; }
  #pipeline-board { height: calc(100vh - 230px); }
  .kanban-col { min-width: 200px; }
  .list-row { flex-wrap: wrap; row-gap: 6px; }
}

/* Petit écran : deux GIF par ligne (16/10/2026) ; la largeur suit la saisie (placerPanneauGifs). */
@media (max-width: 640px) {
  .eg-grille-gifs { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-rows: 110px; }
}
