/* Agora v2 — interface de l'utilisateur (SENTINEL-46, vigie SENTINEL-79).
   Identite Sentinel : ardoise + accent pervenche, IBM Plex, theme sombre unique.
   Jetons de la maquette v2 (SENTINEL-86, direction A) : gris remontes pour tenir
   AA partout (mesures dans docs/agora-v2/maquettes-v2/captures/contrastes.json),
   navigation en tete sur toutes les largeurs ; la page d'accueil « la vigie »
   suit l'ordre des questions de l'utilisateur, une section par question. */

/* IBM Plex, servie par l'instance (static/fonts, licence OFL) : aucune police distante.
   Deux graisses livrees : 400 et 700 ; 500 retombe sur 400, 600 sur 700. */
@font-face { font-family: 'IBM Plex Sans'; font-weight: 400; font-style: normal; font-display: swap;
  src: url('/static/fonts/IBMPlexSans-Regular.woff2') format('woff2'); }
@font-face { font-family: 'IBM Plex Sans'; font-weight: 600 700; font-style: normal; font-display: swap;
  src: url('/static/fonts/IBMPlexSans-Bold.woff2') format('woff2'); }
@font-face { font-family: 'IBM Plex Mono'; font-weight: 400; font-style: normal; font-display: swap;
  src: url('/static/fonts/IBMPlexMono-Regular.woff2') format('woff2'); }
@font-face { font-family: 'IBM Plex Mono'; font-weight: 600 700; font-style: normal; font-display: swap;
  src: url('/static/fonts/IBMPlexMono-Bold.woff2') format('woff2'); }

:root {
  --bg: #0e1116;
  --panel: #151a23;
  --panel-2: #1b2130;
  --line: #242c3b;
  --text: #dde3ef;
  /* Gris v2 (SENTINEL-86) : --muted 8.2:1 et --faint 6.2:1 sur panneau — AA partout
     (l'ancien --faint #59627a mesurait 2,5:1, et portait des infos de fraicheur). */
  --muted: #a8b2cc;
  --faint: #8f99b6;
  --tool: #b3bcfb;
  --accent: #7d8cf8;
  --live: #41d98d;
  --warn: #f0b429;
  --bad: #ef6b6b;
  /* Couleur de chaleur des echanges (SENTINEL-79) : chaud = quelques minutes,
     froid = pres de 24 h. Pastilles : objets graphiques, seuil 3:1 (nettement tenu,
     mesures dans le rapport de recette) ; le texte a cote reste AA. */
  --heat-0: #f0b429;
  --heat-1: #f0975c;
  --heat-2: #b3a7e0;
  --heat-3: #9cc0fa;
  --mono: 'IBM Plex Mono', ui-monospace, monospace;
  --sans: 'IBM Plex Sans', system-ui, sans-serif;
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { height: 100%; }
/* L'application tient la fenetre : l'en-tete, puis la vue qui prend tout le
   reste (la vue Reseau en hauteur relative ; les autres vues defilent
   dedans). Aucune hauteur en pixels pour ces zones. */
#app { height: 100dvh; display: flex; flex-direction: column; }
#app > main { flex: 1; min-height: 0; overflow-y: auto; }
body {
  font-family: var(--sans); background: var(--bg); color: var(--text);
  font-size: 15px; line-height: 1.5;
  -webkit-text-size-adjust: 100%;
}
[hidden] { display: none !important; }
/* Barres de defilement dans le theme (SENTINEL-189 : les barres blanches du
   systeme juraient sur le fond sombre). */
:root { color-scheme: dark; }
* { scrollbar-width: thin; scrollbar-color: #2e3748 #0e1116; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #2e3748; border-radius: 6px; border: 2px solid var(--bg); }
::-webkit-scrollbar-thumb:hover { background: #3b4660; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
button:focus-visible, input:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

.wordmark {
  font-family: var(--mono); font-weight: 600; font-size: 15px;
  letter-spacing: 3px; user-select: none;
}
.wordmark .tick { color: var(--accent); }
.mono { font-family: var(--mono); }
.muted { color: var(--muted); }
.faint { color: var(--faint); }

/* ===== Verrouillage ===== */
.lock {
  min-height: 100dvh; display: flex; align-items: center; justify-content: center;
  padding: 24px 16px calc(24px + env(safe-area-inset-bottom));
}
.lock-box { width: 100%; max-width: 320px; display: flex; flex-direction: column; align-items: center; gap: 18px; }
.lock-title { font-family: var(--mono); font-size: 12px; letter-spacing: 2px; text-transform: uppercase; color: var(--muted); }
.lock-login { width: 100%; max-width: 280px; padding: 10px 12px; font: inherit; font-family: var(--mono); text-align: center; color: inherit; background: transparent; border: 1.5px solid var(--faint); border-radius: 8px; }
.lock-login:focus { outline: none; border-color: var(--accent); }
/* SENTINEL-489 : le code en champ texte (16 px : iOS ne zoome pas au focus). */
.lock-code { font-size: 16px; letter-spacing: 1px; }
.lock-msg { min-height: 20px; font-size: 13px; color: var(--muted); text-align: center; }
.lock-msg.err { color: var(--bad); }
.lock-go { width: 100%; max-width: 280px; min-height: 44px; }

/* ===== Barre d'application (navigation en tete, toutes largeurs) ===== */
.top {
  position: sticky; top: 0; z-index: 5;
  display: flex; align-items: center; gap: 16px;
  padding: 10px 20px; padding-top: calc(10px + env(safe-area-inset-top));
  background: var(--panel); border-bottom: 1px solid var(--line);
}
.top .spacer { flex: 1; }
.nav { display: flex; gap: 4px; flex: none; }
.tab {
  background: none; border: 1px solid transparent; border-radius: 6px;
  padding: 8px 13px; font-family: var(--mono); font-size: 12.5px; color: var(--muted); cursor: pointer;
  white-space: nowrap;
}
.tab.on { color: var(--text); border-color: var(--accent); background: rgba(125,140,248,.12); }
.nav .tab { font-size: 13.5px; padding: 8px 16px; }
.badge {
  display: inline-block; min-width: 18px; padding: 0 5px; margin-left: 6px;
  border-radius: 9px; background: var(--warn); color: #0e1116;
  font-family: var(--mono); font-size: 11px; font-weight: 600; line-height: 18px; text-align: center;
  vertical-align: 1px;
}
/* ===== Menu secondaire « ⋯ » (SENTINEL-309/310) : gestes rares regroupés —
   en-tête (Enrôlements, Machines, Verrouiller) et fiche d'un fil (Renommer,
   Fermer, Rouvrir). Même composant visuel aux deux endroits. */
.menu-wrap { position: relative; flex: none; }
.menu-btn {
  display: flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border: 1px solid var(--line); border-radius: 8px;
  font-size: 18px; line-height: 1; color: var(--muted); cursor: pointer;
}
.menu-btn:hover, .menu-btn[aria-expanded="true"] { color: var(--text); border-color: var(--accent); }
.menu-btn.small { width: 30px; height: 30px; font-size: 15px; border-radius: 6px; }
.menu-pop {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 20;
  display: flex; flex-direction: column; gap: 2px; min-width: 190px; padding: 6px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 10px 28px rgba(0,0,0,.4);
}
.menu-item {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  padding: 10px 12px; border-radius: 6px; cursor: pointer;
  font-family: var(--mono); font-size: 12.5px; color: var(--muted);
}
.menu-item:hover, .menu-item:focus-visible { color: var(--text); background: rgba(125,140,248,.12); }
.menu-item.on { color: var(--text); }
.menu-item svg { width: 13px; height: 13px; flex: none; }
.menu-item.danger:hover { color: var(--bad); background: rgba(239,107,107,.1); }
/* SENTINEL-310 : les boutons « Renommer »/« Fermer »/« Rouvrir » du fil
   gardent leur classe .chip (comportement et teinte au survol inchangés) une
   fois dans le menu — seule la forme (pilule -> ligne pleine largeur) change. */
.menu-pop .chip {
  width: 100%; justify-content: flex-start; border: none; border-radius: 6px;
  min-height: auto; padding: 10px 12px; font-size: 12.5px;
}
.menu-pop .chip.fermer:hover { background: rgba(239,107,107,.1); }
.menu-pop .chip.rouvrir:hover { background: rgba(65,217,141,.1); }
.menu-pop .chip.renommer:hover { background: rgba(125,140,248,.1); }

/* ===== Forfaits IA de l'en-tête (SENTINEL-337) : un bloc par fournisseur
   (Claude, GLM) — DEUX jauges étiquetées « 5 h » et « sem. » (SENTINEL-387),
   chacune en barre et chiffre ; l'heure de reprise (remise à zéro), la
   source et l'âge au survol. Réutilise la jauge des sessions
   (participants.js) : haut = rouge dès 85, périmée = hachurée. Plein
   (100 %) : le nom et le chiffre passent en rouge — c'est le signal que
   l'en-tête existe pour. Mesure ancienne (> 30 min) : tout en gris.
   Tendance (SENTINEL-387) : mini-courbe SVG de la fenêtre 5 h sur 2 h et
   delta de la demi-heure — des mesures réelles, rien d'inventé. ===== */
.forfaits { display: flex; align-items: center; gap: 16px; flex: none; }
.forfait {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--mono); font-size: 11.5px; color: var(--muted);
  cursor: default; white-space: nowrap;
}
.forfait .f-nom { font-weight: 600; letter-spacing: .02em; }
.forfait .f-nom-court { display: none; }
.forfait .f-age { color: var(--faint); font-size: 11px; margin-left: 4px; }
.forfait .jauge .jg-barre { width: 46px; height: 5px; }
.forfait.plein .f-nom, .forfait.plein .jg-txt { color: var(--bad); }
.forfait.plein .f-nom { font-weight: 700; }
.forfait.perimee .f-nom { font-weight: 400; color: var(--faint); }
.f-g { display: inline-flex; align-items: center; gap: 4px; }
.f-etiq { color: var(--faint); font-size: 10px; }
.f-tendance { display: inline-flex; align-items: center; gap: 5px;
  color: var(--faint); padding-left: 2px; }
.f-tendance .f-courbe { display: block; }
.f-tendance .f-courbe polyline {
  fill: none; stroke: currentColor; stroke-width: 1.25; }
.f-tendance .f-courbe circle { fill: currentColor; }
.f-delta { font-size: 10.5px; color: var(--faint); }
/* Mobile (règle de l'en-tête, max-width 899px) : une seule ligne, et la
   navigation garde sa place (SENTINEL-309 : elle tenait tout juste à 390 px).
   Les blocs passent en colonne compacte — initiale, jauges, chiffres — ; les
   étiquettes, la tendance et l'âge restent au survol (desktop d'abord,
   SENTINEL-387). */
@media (max-width: 899px) {
  .forfaits { flex-direction: column; align-items: flex-start; gap: 3px; }
  .forfait { gap: 3px; font-size: 10px; line-height: 1.1; }
  .forfait .f-nom-long { display: none; }
  .forfait .f-nom-court { display: inline; }
  .forfait .f-etiq, .forfait .f-tendance { display: none; }
  .forfait .f-age { font-size: 9px; }
  .forfait .f-age-ily, .forfait .f-cause { display: none; }
  .forfait .jauge { gap: 3px; }
  .forfait .jauge .jg-barre { width: 26px; height: 4px; }
}

/* SENTINEL-402 : entre 900 et 1440 px, onglets + forfaits + menu ne tenaient
   plus sur une rangée (les onglets passaient à la ligne, le menu sortait de
   l'écran à 1100). Les onglets ne se replient plus ; la tendance et l'âge
   passent au survol sous 1440 px (SENTINEL-420 : pas l'âge ni la cause d'une
   mesure périmée ou en échec, qui se voient à toutes les largeurs), les étiquettes « 5 h »/« sem. » et les
   jauges se resserrent sous 1280 px. */
@media (min-width: 900px) and (max-width: 1440px) {
  .top { gap: 12px; }
  .forfaits { gap: 12px; }
  .forfait .f-tendance { display: none; }
}
@media (min-width: 900px) and (max-width: 1280px) {
  .top { padding-left: 14px; padding-right: 14px; }
  .nav .tab { padding: 8px 10px; font-size: 13px; }
  .forfait .jauge .jg-barre { width: 30px; }
}
@media (min-width: 900px) and (max-width: 1160px) {
  .forfait .f-etiq { display: none; }
}

/* La vue d'ensemble occupe l'ecran en pleine largeur (SENTINEL-103 puis
   SENTINEL-148, bureau d'abord) ; la page des fils aussi (SENTINEL-104) ; les
   autres ecrans gardent la colonne de lecture d'avant (1156 px = l'ancien
   main 1200 moins ses marges). Le padding vit sur les vues : la vue
   d'ensemble porte ses propres marges (bandeau et grille, SENTINEL-148). */
main { padding: 0; }
.view { display: none; padding: 20px clamp(20px, 2.5vw, 40px) 34px; }
#view-enroll, #view-machines { max-width: 1156px; margin: 0 auto; }
.view.on { display: block; }
#view-reseau.on { display: flex; flex-direction: column; height: 100%; min-height: 0;
  padding: 0 20px 16px; }

.section-title {
  font-family: var(--mono); font-size: 11px; letter-spacing: 2px; text-transform: uppercase;
  color: var(--muted); margin: 18px 2px 8px; display: flex; justify-content: space-between; gap: 8px;
}
.section-title:first-child { margin-top: 2px; }
.section-title .sub { letter-spacing: 0; text-transform: none; color: var(--faint); }
.card {
  background: var(--panel); border: 1px solid var(--line); border-radius: 10px;
  padding: 12px 14px; margin-bottom: 10px;
}
.empty { color: var(--muted); font-size: 13.5px; padding: 18px 4px; text-align: center; }
.error-line { color: var(--bad); font-size: 13px; margin-top: 8px; }
/* SENTINEL-482 : les demandes qui attendent encore, dans le refus de fermeture. */
.error-line .attente-liste { margin: 4px 0 6px; padding-left: 20px; }
.ok-line { color: var(--live); font-size: 13px; margin-top: 8px; }

/* Pastilles d'etat (avec libelle) */
.st { display: inline-flex; align-items: center; gap: 7px; font-family: var(--mono); font-size: 12px; white-space: nowrap; }
.st::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--faint); flex: none; }

.tag {
  display: inline-block; font-family: var(--mono); font-size: 11.5px; padding: 2px 8px;
  border-radius: 10px; background: var(--panel-2); color: var(--muted); white-space: nowrap;
}
.tag.frais { color: var(--live); }
.tag.tiede { color: var(--warn); }
.tag.froid { color: #9cc0fa; }
.tag.archive { color: var(--faint); }
/* SENTINEL-411 : la pastille de portée d'un fil d'équipe. */
.tag.equipe { color: var(--accent); border: 1px solid rgba(125,140,248,.45); background: none; }
.tag.humain { color: #0e1116; background: var(--accent); }
.tag.warn { color: #0e1116; background: var(--warn); }
.tag.op { color: var(--accent); border: 1px solid rgba(125,140,248,.4); background: none; }
/* SENTINEL-383 : le modèle servi d'une session — libellé court (celui que
   le connecteur déclare, sinon le dernier segment de l'identifiant),
   identifiant complet au survol, rien si inconnu. Sans fond : il se pose
   partout (pastille d'un fil, écran Sessions, fiche Réseau). */
.tag.modele { background: none; border: 1px solid var(--line); }
/* SENTINEL-383, recette : sur l'écran Sessions, la cellule « Poste · outil »
   tronque (nowrap + ellipsis) — un badge posé APRÈS le texte passait sous
   la coupure et devenait invisible. Il vit sur sa PROPRE ligne sous le
   texte, hors de portée de la troncature ; la cellule lui laisse son
   white-space à elle (l'héritage nowrap lui interdisait de tenir son
   texte), et un libellé démesuré enveloppe dans le badge au lieu de
   disparaître. La colonne garde un plancher (minmax des grilles
   ci-dessous) assez large pour le plus long libellé du catalogue réel. */
.ss-c-depot .tag.modele { display: block; width: fit-content;
  max-width: 100%; margin: 3px 0 0; white-space: normal; overflow-wrap: anywhere; }

/* ===== Identite d'un agent (SENTINEL-61) : machine › depot › Outil, puis session « code » ===== */
.ident { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.ident-main { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 6px; min-width: 0; }
.ident-machine { font-family: var(--mono); font-size: 12.5px; color: var(--muted); overflow-wrap: anywhere; }
.ident-repo { font-family: var(--mono); font-size: 13.5px; font-weight: 600; color: var(--text); overflow-wrap: anywhere; }
.ident-repo.none { color: var(--faint); font-weight: 400; font-style: italic; }
.ident-tool { font-family: var(--sans); font-size: 13.5px; font-weight: 600; color: var(--tool); overflow-wrap: anywhere; }
.ident-sep { font-family: var(--mono); font-size: 12px; color: var(--faint); }
.ident-meta { display: flex; flex-wrap: wrap; gap: 0 12px; font-family: var(--mono); font-size: 12px; color: var(--muted); }
.fact { white-space: nowrap; }
.k { font-family: var(--mono); font-size: 11px; letter-spacing: .03em; color: var(--faint); }
/* Code de session (SENTINEL-74) : « dalor » ressort, le role reste discret. */
.sess-code { font-family: var(--mono); font-weight: 600; letter-spacing: .04em; }
.sess-role { color: var(--muted); }
.ident.compact { flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: 2px 12px; }
.ident.compact .ident-repo, .ident.compact .ident-tool { font-size: 12.5px; }
.ident.compact .ident-machine { font-size: 12px; }
.machine-label { display: inline-flex; align-items: baseline; gap: 6px; min-width: 0; }
.repo-group { border-top: 1px solid var(--line); padding-top: 6px; margin-top: 4px; }
.machine-head + .repo-group, .idents > .repo-group:first-child { border-top: none; margin-top: 0; }
.repo-head { display: flex; align-items: baseline; gap: 6px; padding: 2px 0 2px; }
.repo-head .count { margin-left: auto; font-family: var(--mono); font-size: 11px; color: var(--faint); }
.agent-row { display: flex; align-items: center; gap: 6px 10px; flex-wrap: wrap; }
.agent-meta { font-size: 12.5px; color: var(--faint); }
.machine-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 6px; }
.machine-name { font-family: var(--mono); font-size: 14px; font-weight: 600; }
.machine-head .count { margin-left: auto; font-family: var(--mono); font-size: 11.5px; color: var(--muted); }

/* ===== La vigie (accueil, SENTINEL-79) ===== */
.page-h { margin: 0 0 16px; }
.page-h h1 { font-size: 23px; font-weight: 600; letter-spacing: -.01em; line-height: 1.25; }
.page-h h1 b { color: var(--live); font-weight: 600; }
.page-h .meta { font-size: 13px; color: var(--muted); margin-top: 4px; }

/* Ferme par un autre que son createur (SENTINEL-92) : bandeau d'avis en
   ambre — un avis, pas une urgence. */
.warn-banner {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 12px;
  border: 1px solid rgba(240,180,41,.4); border-left: 3px solid var(--warn);
  border-radius: 8px; background: var(--panel);
  padding: 10px 14px; margin-bottom: 24px; font-size: 13.5px;
}
.warn-banner .why {
  color: var(--warn); font-family: var(--mono); font-size: 11.5px;
  letter-spacing: .06em; text-transform: uppercase; font-weight: 600;
}

.q { margin-bottom: 32px; }
.q-title { display: flex; align-items: baseline; gap: 12px; margin-bottom: 6px; }
.q-title h2 { font-size: 16.5px; font-weight: 600; }
.q-title .n { font-family: var(--mono); font-size: 11.5px; color: var(--accent); letter-spacing: .1em; }
.q-sub { font-size: 13px; color: var(--muted); margin-bottom: 14px; }

/* §01 presence : une table plate, une ligne par session */
table.presence { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.presence th {
  font-family: var(--mono); font-size: 11px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--faint); font-weight: 400; text-align: left; padding: 0 12px 8px;
  border-bottom: 1px solid var(--line);
}
.presence td { padding: 9px 12px; border-bottom: 1px solid var(--line); vertical-align: baseline; }
.presence tr:last-child td { border-bottom: none; }
.presence th.ta-r, .presence td.ta-r { text-align: right; }
.presence .sess b { font-family: var(--mono); font-weight: 600; font-size: 13.5px; }
.presence .sess .role { color: var(--muted); }
.presence .tool { color: var(--tool); }
.presence .qui { font-family: var(--mono); font-size: 12.5px; color: var(--muted); overflow-wrap: anywhere; }
.presence .vu { font-family: var(--mono); font-size: 11.5px; color: var(--faint); white-space: nowrap; margin-top: 3px; }
.presence .st-td { white-space: nowrap; width: 1%; }
/* Signe de vie d'une session (SENTINEL-61) : vert, ambre (sondage ancien), rouge (relais muet). */
.life { display: inline-flex; align-items: center; gap: 6px; }
.life::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--faint); flex: none; }
.life.ok { color: var(--live); } .life.ok::before { background: var(--live); }
.life.idle { color: var(--warn); } .life.idle::before { background: var(--warn); }
.life.bad { color: var(--bad); } .life.bad::before { background: var(--bad); }

/* §02 conversations : fils vivants + echanges 24 h */
.conv-grid { display: grid; grid-template-columns: minmax(0,7fr) minmax(0,5fr); gap: 26px; align-items: start; }
.conv {
  display: flex; gap: 12px; align-items: flex-start; width: 100%; text-align: left;
  padding: 11px 10px; border-bottom: 1px solid var(--line); border-radius: 8px;
}
/* le bloc du milieu peut retrecir sous son contenu : le sujet et les noms
   passent a la ligne, la colonne d'age ne pousse plus la page (mesure 390 px). */
.conv > div { min-width: 0; }
.conv:hover { background: var(--panel); }
.conv:last-child { border-bottom: none; }
.conv .tags { display: flex; gap: 5px; flex: none; padding-top: 2px; }
.conv .subj { font-size: 14.5px; font-weight: 500; line-height: 1.35; }
.conv .who { font-family: var(--mono); font-size: 11.5px; color: var(--muted); margin-top: 4px; line-height: 1.7; }
.conv .who .nm { white-space: nowrap; }
.conv-side { margin-left: auto; flex: none; text-align: right; display: flex; flex-direction: column; gap: 3px; align-items: flex-end; }
.conv-side .age { font-family: var(--mono); font-size: 12px; color: var(--muted); white-space: nowrap; }
.conv-side .nfo { font-family: var(--mono); font-size: 11px; color: var(--faint); white-space: nowrap; }

.dyads { background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 6px 14px 10px; }
.dyads .section-title { margin: 8px 0 4px; }
.dyad {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px; width: 100%; text-align: left;
  font-family: var(--mono); font-size: 12px; color: var(--muted); padding: 9px 0;
  border-bottom: 1px solid var(--line);
}
.dyad:last-child { border-bottom: none; }
.dyad .nm { color: var(--text); }
.dyad .x { color: var(--accent); }
.dyad .n { color: var(--text); font-weight: 600; }
.dyad .age { margin-left: auto; color: var(--muted); font-size: 11.5px; white-space: nowrap; }
/* Couleur de chaleur : pastille carree (8 px) a gauche de la paire. */
.heat { display: inline-block; width: 8px; height: 8px; border-radius: 2px; flex: none; align-self: center; }
.heat.h0 { background: var(--heat-0); }
.heat.h1 { background: var(--heat-1); }
.heat.h2 { background: var(--heat-2); }
.heat.h3 { background: var(--heat-3); }
/* L'echelle, dans les jetons de couleur */
.heat-scale { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; padding: 8px 0 4px; font-family: var(--mono); font-size: 11px; color: var(--faint); }
.heat-scale .lg { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }

.legend-line { font-size: 12px; color: var(--muted); margin: 2px 2px 0; line-height: 1.5; }
.legend-line summary { cursor: pointer; color: var(--accent); font-family: var(--mono); font-size: 11.5px; }

/* Fraicheur de la page (SENTINEL-61) : l'heure du dernier rafraichissement reussi,
   sa periode, et un signal clair si le dernier a echoue (les donnees affichees
   restent, datees). */
.fresh { font-family: var(--mono); font-size: 11.5px; color: var(--muted); margin: 0 2px 14px; }
.fresh.bad {
  font-family: var(--sans); font-size: 13px; color: var(--bad); padding: 7px 10px; border-radius: 8px;
  border: 1px solid rgba(239,107,107,.5); background: rgba(239,107,107,.08);
}
.fresh.bad strong { font-weight: 600; }

/* ===== Fils ===== */
.filters { display: flex; gap: 6px; flex-wrap: wrap; margin: 0 0 10px; }
.chip {
  font-family: var(--mono); font-size: 12px; color: var(--muted); background: none;
  border: 1px solid var(--line); border-radius: 20px; padding: 0 14px; min-height: 40px;
  display: inline-flex; align-items: center; cursor: pointer; white-space: nowrap;
}
/* SENTINEL-310 : Participants, Documents, Actualiser de la fiche d'un fil —
   visibles mais plus discrets que les pilules pleines (fond et bordure
   atténués, un peu moins de respiration) qu'avait le même rang qu'un geste
   rare. */
.chip.ghost { border-color: transparent; background: none; color: var(--faint); min-height: 34px; padding: 0 10px; }
.chip.ghost:hover { color: var(--muted); border-color: var(--line); }
.chip.on { color: var(--text); border-color: var(--accent); background: rgba(125,140,248,.12); }
/* Ligne d'un fil (SENTINEL-151 ; compacte depuis SENTINEL-471, environ
   45 px au lieu de 100) : losange de fraîcheur, sujet sur une ligne, point
   « non lu », punaise, âge ; le but sur une ligne tronquée ; qui parle, le
   volume et le mandat en petit sur le fil choisi (en infobulle sinon : les
   montrer au survol ferait sauter la liste sous la souris). Un fil clos
   est atténué (70 %), un fil archivé de même (l'état le dit). */
.thread-item {
  display: block; width: 100%; text-align: left; cursor: pointer;
  padding: 6px 10px 6px 9px; border: 0; border-left: 3px solid transparent; border-radius: 6px;
  margin-bottom: 2px; background: none; box-shadow: none;
  transition: background .12s, border-color .12s;
}
.thread-item:hover { background: var(--panel-2); }
.thread-item.sel { border-left-color: var(--accent); background: var(--panel-2); }
.thread-item.clos { opacity: .7; }
/* SENTINEL-411 : un fil d'équipe où aucun de mes agents n'est actif. */
.thread-item.attenue { opacity: .75; }
.thread-item.attenue.clos { opacity: .55; }
.thread-item .tscope, .ov-tl1 .tscope, .ov-fpartage .tscope { flex: none;
  font-family: var(--mono); font-size: 10.5px; color: var(--accent);
  border: 1px solid rgba(125,140,248,.45); border-radius: 8px; padding: 0 5px; }
/* SENTINEL-416 : le fil 1-1 entre liaisons, rangé sous le fil de son annonce. */
.thread-item.sous { margin-left: 14px; }
.thread-item .tscope.cache, .ov-tl1 .tscope.cache, .ov-fpartage .tscope.cache { color: var(--faint); border-color: var(--line); }
.thread-vis { margin: 2px 0 0; font-size: 12.5px; color: var(--faint); }
/* SENTINEL-471 : les sections de la liste (Épinglés, Mes fils, Entre agents,
   Calmes, Clos) — un en-tête qui replie ou déplie, le nombre de fils, et sur
   une section repliée le point « nouveau » si un de ses fils a du non lu. */
.fsec { display: flex; align-items: center; gap: 7px; width: 100%; margin: 12px 0 4px;
  padding: 4px 4px; background: none; border: 0; cursor: pointer; text-align: left;
  font-family: var(--mono); font-size: 11px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--faint); }
.fsecs > .fsec:first-child, #view-pourtoi .fsec:first-of-type { margin-top: 2px; }
.fsec:hover { color: var(--muted); }
.fsec:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; border-radius: 4px; }
.fsec-chev { width: 10px; font-size: 10px; letter-spacing: 0; }
.fsec .ic-marque { color: var(--accent); }
.fsec-n { letter-spacing: .04em; }
.fsec-hint { margin-left: auto; letter-spacing: .04em; text-transform: none; }
.fsec .nouveau { width: 7px; height: 7px; background: var(--accent); }
.pt-fils + .fsec { margin-top: 18px; }
/* La punaise (SENTINEL-471) : au survol sur ordinateur, toujours visible au
   doigt ; pleine et pervenche sur un fil épinglé. */
.tpin { flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; margin: -3px 0; border-radius: 5px; color: var(--faint);
  cursor: pointer; align-self: center; }
.tpin:hover, .tpin:focus-visible { color: var(--text); background: rgba(125,140,248,.14); outline: none; }
.tpin.on { color: var(--accent); }
.tpin.err { color: var(--bad); }
.tpin[aria-expanded="true"] { color: var(--text); background: rgba(125,140,248,.14); }
/* SENTINEL-473 : les marques — la punaise pleine (épinglé), le sablier (en
   attente), les plans (de fond) ; même pervenche, la forme les distingue. */
.mq-menu.occupe { opacity: .6; pointer-events: none; }
.mq-item .gs-label { display: flex; align-items: center; gap: 8px; width: 100%; }
.mq-item .ic-marque { color: var(--accent); flex: none; }
.mq-item.coche .gs-label { color: var(--accent); }
.mq-coche { margin-left: auto; font-size: 12px; }
.mq-item .gs-aide { padding-left: 21px; }
.mq-form { padding: 2px 8px 8px 29px; display: flex; flex-direction: column; gap: 6px; }
.mq-form[hidden] { display: none; }
.mq-note { width: 100%; box-sizing: border-box; background: var(--bg); color: var(--text);
  border: 1px solid var(--line); border-radius: 6px; padding: 6px 8px; font: inherit; font-size: 13px; }
.mq-note:focus { outline: none; border-color: var(--accent); }
.mq-form-act { display: flex; align-items: center; gap: 8px; }
.mq-compte { font-size: 11px; color: var(--faint); }
.tattente, .pt-attente { display: flex; align-items: center; gap: 6px; min-width: 0;
  color: var(--muted); }
.tattente { margin: 1px 0 0 18px; font-size: 12px; line-height: 1.35; }
.pt-attente { margin-top: 4px; font-size: 13px; }
.tattente .note, .pt-attente .note { min-width: 0; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; }
.tattente .depuis, .pt-attente .depuis { flex: none; margin-left: auto; font-family: var(--mono);
  font-size: 11px; color: var(--faint); }
@media (pointer: coarse) {
  .mq-item { min-height: 44px; }
  .mq-note { font-size: 16px; }
}
@media (pointer: fine) {
  .thread-item .tpin:not(.on), .pt-fsub .tpin:not(.on) { visibility: hidden; }
  .thread-item:hover .tpin, .thread-item:focus-within .tpin, .thread-item .tpin:focus-visible,
  .pt-fsub:hover .tpin, .pt-fsub .tpin:focus-visible { visibility: visible; }
}
.filters.scope { margin-top: -4px; }
.filters[hidden] { display: none; }
.thread-item .tl1 { display: flex; align-items: center; gap: 8px; min-height: 20px; }
.thread-item .dz { width: 10px; height: 10px; align-self: center; flex: none; }
.thread-item .tsubj { flex: 1; min-width: 0; font-size: 13.5px; font-weight: 600;
  line-height: 1.3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.thread-item .tage { flex: none; font-family: var(--mono); font-size: 11px; color: var(--faint);
  min-width: 38px; text-align: right; }
.thread-item .nouveau { width: 7px; height: 7px; background: var(--accent); }
.thread-item .tgoal { margin: 1px 0 0 18px; font-size: 12px; color: var(--muted); line-height: 1.35;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.thread-item .tmeta { display: none; flex-wrap: nowrap; gap: 2px 10px; align-items: center;
  font-size: 10.5px; line-height: 1.35; color: var(--faint); margin: 2px 0 0 18px; }
.thread-item.sel .tmeta { display: flex; }
.thread-item .twho { flex: 0 1 auto; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.thread-item .tcount, .thread-item .ttype, .thread-item .mbadge { flex: none; }
.thread-item .mbadge { border: 1px solid var(--accent); border-radius: 4px; padding: 0 5px;
  font-family: var(--mono); font-size: 11px; color: var(--tool); white-space: nowrap; }
/* Changer de fil sans ecran vide : l'ancien s'estompe le temps du chargement. */
#thread-main { transition: opacity .15s; }
#thread-main.chargement { opacity: .45; }
.fact.ecoute { color: var(--live); }
.load-more {
  width: 100%; padding: 12px; background: none; border: 1px dashed var(--line); border-radius: 8px;
  color: var(--accent); font-family: var(--mono); font-size: 12px; cursor: pointer; margin-bottom: 10px;
}

.thread-back {
  display: none; background: none; border: none; color: var(--accent); font-family: var(--mono); font-size: 12.5px;
  cursor: pointer; padding: 2px 0 10px;
}
.thread-head { display: flex; align-items: flex-start; gap: 14px; margin: 0 0 10px; }
.thread-title { font-size: 19px; font-weight: 600; line-height: 1.3; }
.head-tags { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin: 4px 0 0; font-family: var(--mono); font-size: 12px; color: var(--muted); }
/* L'essentiel du fil en une ligne (SENTINEL-104) : le detail (createur, mandat,
   fermeture) vit replie dans « Details du fil ». */
.thread-essence { font-size: 13px; color: var(--muted); margin: 5px 0 0; }
.thread-act { margin-left: auto; display: flex; align-items: center; gap: 10px; flex: none; padding-top: 3px; }
.thread-act .fresh { margin: 0; }
.kv { display: grid; grid-template-columns: max-content 1fr; gap: 5px 14px; font-size: 13px; }
.kv dt { color: var(--muted); font-family: var(--mono); font-size: 12px; padding-top: 1px; }
.kv dd { overflow-wrap: anywhere; }
.kv q { font-style: italic; color: var(--text); }
.people { display: flex; flex-direction: column; gap: 6px; }
/* Details du fil repliables et carte des participants (rail a droite sur
   grand ecran, empiles sinon). */
.thread-facts { padding: 0; }
.thread-facts summary {
  cursor: pointer; list-style: none; padding: 11px 14px; font-family: var(--mono);
  font-size: 12px; letter-spacing: .1em; text-transform: uppercase; color: var(--muted);
}
.thread-facts summary::after { content: " +"; color: var(--faint); }
.thread-facts[open] summary::after { content: " −"; }
.thread-facts[open] summary { border-bottom: 1px solid var(--line); }
.thread-facts .kv { padding: 11px 14px; }
.thread-people .section-title { margin: 2px 0 8px; }

/* ===== Participants condensés (SENTINEL-197) : des pastilles en ligne =====
   Une pastille par tête — dépôt (ou outil), session « code », étiquette
   « créateur » — qui enveloppent ; au-delà de six, « +N » déplie. Le point
   devant chaque pastille est l'état (198 ; SENTINEL-276 : `.lm`, les quatre
   couleurs de partout). */
.thread-people .people { flex-direction: row; flex-wrap: wrap; gap: 5px; }
.ppl {
  display: inline-flex; align-items: center; gap: 6px; min-width: 0; max-width: 100%;
  padding: 3px 9px; border: 1px solid var(--line); border-radius: 999px;
  background: var(--panel-2); font-family: var(--mono); font-size: 12px;
}
.ppl .lm { margin-right: 0; }
.ppl-nom { font-weight: 600; color: var(--text); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; max-width: 16ch; min-width: 2ch; }
/* SENTINEL-241/276 : le role, nom d'usage de la session. */
.ppl-nom.role { font-family: var(--sans); max-width: 30ch; }
.ppl .tag { padding: 1px 6px; font-size: 10.5px; }
.ppl.replie { display: none; }
button.ppl.plus { cursor: pointer; color: var(--muted); background: none;
  border-style: dashed; }
button.ppl.plus:hover { color: var(--text); }
/* L'humain (198, avec 180) : le même anneau que la scène 3D en glyph — rose
   fixe, hors des palettes d'agents et d'états — et le prénom, pas un dépôt. */
.ppl.humain { border-color: rgba(239,143,176,.35); }
.ppl.humain .ppl-nom { font-family: var(--sans); color: var(--accent); }
.ppl-toi { color: var(--faint); }
/* SENTINEL-376 : les gestes d'un participant passent par son menu « ⋯ »
   (gestes-session.js) ; la bande de confirmation vit sous les pastilles. */
.ppl-gerer, .ppl-quitter { margin-left: auto; font-size: 12px; }
/* La croix garde son allure pour les lignes du composant de choix
   (`.cp-x`, SENTINEL-371) ; le mode « retirer… » de la carte n'existe plus. */
.ppl-x { border: 0; background: none; color: var(--muted); cursor: pointer;
  font-size: 14px; line-height: 1; padding: 0 0 0 2px; }
.ppl-x:hover { color: var(--bad); }
.ppl-confirme { margin-top: 10px; font-size: 13px; }
.ppl-confirme[hidden] { display: none; }
.ppl-err { color: var(--bad); font-size: 12.5px; }
/* SENTINEL-276 : le nom seul (role sinon code) — la pastille d'un agent
   passe a la ligne plutot que de couper ; l'adresse est au survol. Une
   session qui ne sera pas reveillee porte un liseré ambre. */
.ppl.agent { flex-wrap: wrap; border-radius: 12px; row-gap: 2px; }
.ppl.agent .ppl-nom { max-width: none; white-space: normal; overflow-wrap: anywhere; }
.ppl.sourd { border-color: rgba(240,180,41,.45); }
/* Le panneau « Ajouter un participant » : sobre comme la confirmation du
   retrait ; l'avertissement de reveil, ambre, avant le bouton. */
/* Les deux gestes du titre, groupes a droite ; le groupe passe a la ligne
   entier sur petit ecran plutot que de deborder. */
.ppl-gestes { margin-left: auto; display: inline-flex; gap: 12px; }
.ppl-gestes .ppl-gerer, .ppl-gestes .ppl-quitter { margin-left: 0; }
.thread-people .section-title { flex-wrap: wrap; row-gap: 4px; }
.ppl-ajout { display: flex; flex-direction: column; gap: 8px; margin-top: 10px;
  padding-top: 10px; border-top: 1px dashed var(--line); font-size: 13px; }
.ppl-ajout[hidden] { display: none; }
.ppl-ajout-sel { width: 100%; font: inherit; font-size: 13px; color: var(--text);
  background: var(--bg); border: 1px solid var(--line); border-radius: 8px;
  padding: 6px 8px; min-height: 34px; }
.ppl-ajout-sel:focus { outline: none; border-color: var(--accent); }
.ppl-ajout-act { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.ppl-histo { display: inline-flex; align-items: center; gap: 6px; color: var(--muted);
  font-size: 12.5px; cursor: pointer; }
.ppl-avert, .cmp-avert > div { color: var(--warn); font-size: 12.5px; line-height: 1.4; }
.cmp-avert { display: flex; flex-direction: column; gap: 2px; margin-top: 8px; }
.cmp-avert:empty { display: none; }

.decision { padding: 8px 0; border-top: 1px solid var(--line); font-size: 13.5px; }
.decision:first-child { border-top: none; padding-top: 0; }
.decision .meta { font-family: var(--mono); font-size: 11.5px; color: var(--muted); margin-top: 3px; display: flex; flex-wrap: wrap; gap: 4px 12px; }

/* But du fil (SENTINEL-181), lecture seule : un paragraphe lisible. Les etapes
   vivaient sous le but — retraites avec leurs regles (SENTINEL-326). */
.thread-goal .goal-text { margin: 0 0 12px; font-size: 13.5px; line-height: 1.45; }
.thread-goal .section-title { margin: 6px 0 8px; }
.thread-goal .section-title:first-child { margin-top: 0; }

/* Réveils programmés du fil (SENTINEL-493) : une ligne par réveil actif,
   « Retirer » à droite (un clic arme, le second retire). */
.thread-reveils[hidden] { display: none; }
.thread-reveils .reveil { padding: 8px 0; border-top: 1px solid var(--line); font-size: 13.5px; }
.thread-reveils .reveil:first-of-type { border-top: none; padding-top: 0; }
.thread-reveils .reveil-tete { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.thread-reveils .reveil-texte { min-width: 0; overflow-wrap: anywhere; line-height: 1.45; }
.thread-reveils .meta { font-family: var(--mono); font-size: 11.5px; color: var(--muted); margin-top: 3px; }
.chip.reveil-retirer { flex: none; min-height: 28px; }
.chip.reveil-retirer:hover, .chip.reveil-retirer.danger { color: var(--bad); border-color: rgba(239,107,107,.45); }

/* Qui parle (SENTINEL-104) : la session d'abord — pastille + code colores,
  derive du code de session (unique, jamais reutilise) — puis l'agent en
  petit. Deux sessions du meme depot se distinguent au premier regard ;
  le liseré a gauche du message porte la meme couleur.
  Palette mesuree : >= 5,9:1 sur panneau-2 et >= 6,9:1 sur fond pour chaque
  teinte (AA texte), hors familles de l'accent, du vert « live », de l'ambre
  et du rouge pour ne pas se confondre avec les etats. */
.msg { margin-bottom: 18px; max-width: 86ch; }
.sess-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: var(--sess); flex: none; align-self: center; }
.sess-name { font-family: var(--mono); font-weight: 600; font-size: 13.5px; letter-spacing: .04em; color: var(--sess); overflow-wrap: anywhere; }
.sess-role2 { font-size: 12.5px; color: var(--muted); }
.msg-who { flex: 1 1 auto; min-width: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 2px 8px; }
.msg-agent { font-family: var(--mono); font-size: 12px; color: var(--faint); overflow-wrap: anywhere; }
/* SENTINEL-189 : l'auteur par son nom lisible (role ou outil, son nom affiché). */
.msg-name { font-weight: 600; font-size: 14px; color: var(--sess, var(--text)); }
.msg .tag.qtag { color: var(--warn); border-color: rgba(240,180,41,.4); }
.msg-head { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 2px 10px; margin-bottom: 5px; }
.msg-time { margin-left: auto; font-family: var(--mono); font-size: 11.5px; color: var(--faint); padding-top: 2px; }
/* SENTINEL-308 : le bouton « supprimer » d'un message, dans .msg-head a cote
   de l'heure — discret : visible au survol du message a la souris, toujours
   visible mais attenue au toucher (pas de survol possible). */
.msg-del-btn {
  position: relative; /* porte le ::after qui elargit la cible tactile */
  flex: none; background: none; border: none; padding: 2px 6px; margin-left: 4px;
  font-family: var(--sans); font-size: 11.5px; color: var(--faint); border-radius: 4px;
  cursor: pointer; opacity: 0; transition: opacity .15s ease, color .15s ease, background-color .15s ease;
}
.msg:hover .msg-del-btn, .msg-del-btn:focus-visible { opacity: 1; }
.msg-del-btn:hover, .msg-del-btn:focus-visible {
  color: var(--bad); background: rgba(239,107,107,.1); outline: none;
}
@media (pointer: coarse) {
  /* Pas de survol possible au doigt : le bouton reste visible, a faible
     opacite ; un ::after invisible elargit la cible sans agrandir le bouton
     ni casser le retour a la ligne de .msg-head (un min-height litteral
     poussait « supprimer » seul sur sa ligne, decale sous l'heure — y
     compris sur les messages de l'utilisateur, .msg.mine en row-reverse). */
  .msg-del-btn { opacity: .6; }
  .msg-del-btn::after { content: ''; position: absolute; inset: -14px; }
}
.msg-del-confirm .msg-del-raison {
  display: block; width: 100%; margin: 8px 0; padding: 7px 10px;
  background: var(--bg); border: 1px solid var(--line); border-radius: 6px;
  color: var(--text); font-family: var(--sans); font-size: 13px;
}
.msg-del-confirm .msg-del-raison:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.msg-del-stat:empty { display: none; }
.msg-body {
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 8px;
  padding: 10px 14px; font-size: 15px; line-height: 1.6; overflow-wrap: anywhere;
}
/* Un message de type demande : un fait, pas un etat a suivre (SENTINEL-147) —
   l'etiquette « demande » dans l'en-tete, grise, et un liseré gris sur le corps. */
.msg.demande .msg-body { border-left: 3px solid var(--warn); }
/* Les messages de l'utilisateur, a droite, teinte d'accent : on se lit en conversation. */
.msg.mine { margin-left: auto; }
.msg.mine .msg-head { flex-direction: row-reverse; }
.msg.mine .msg-who { justify-content: flex-end; }
.msg.mine .msg-time { margin-left: 0; margin-right: auto; }
.msg.mine .msg-name { color: var(--accent); }
.msg.mine .msg-body { background: rgba(125,140,248,.13); border-color: rgba(125,140,248,.35); }
/* SENTINEL-206 : l'accuse de reception des messages de l'utilisateur, discret sous la
   bulle — « en attente », puis « remis », puis « remis · lu » (accent quand
   c'est lu). Mis a jour au suivi 5 s de la page fil. */
.msg-dlv { margin-top: 3px; font-size: 11.5px; line-height: 1.4; color: var(--faint); text-align: right; }
.msg-dlv.remis { color: var(--muted); }
.msg-dlv.lu { color: var(--accent); }
/* SENTINEL-334 : la marque « non déposé » — une ligne sobre sous le message,
   la couleur d'avertissement ; les destinataires au survol. */
.msg-sans-depot { margin-top: 3px; font-size: 11.5px; line-height: 1.4;
  color: var(--warn); text-align: right; }
.msg-reply { font-size: 12.5px; color: var(--faint); margin-bottom: 4px; overflow: hidden;
  white-space: nowrap; text-overflow: ellipsis; }
.msg-reply strong { color: var(--muted); font-weight: 600; }
.msg-reply-x { font-style: italic; }
.msg-body p { margin: 0 0 8px; } .msg-body p:last-child { margin-bottom: 0; }
.msg-body code { font-family: var(--mono); font-size: 13.5px; background: var(--bg); padding: 1px 5px; border-radius: 4px; color: var(--accent); }
.msg-body pre { background: var(--bg); border: 1px solid var(--line); border-radius: 6px; padding: 10px; overflow-x: auto; margin: 8px 0; }
.msg-body pre code { background: none; padding: 0; color: var(--text); font-size: 13px; }
/* Tableaux markdown (SENTINEL-71) : le tableau deroule seul sur mobile, jamais
   la page ; les cellules ne se replient pas en colonnes d'un caractere. */
.msg-body .table-wrap { overflow-x: auto; margin: 8px 0; scrollbar-width: thin; scrollbar-color: var(--accent) transparent; }
/* Math des messages (SENTINEL-212) : ```math en bloc — centré par KaTeX
   (.katex-display), marge verticale portée ici seule, formule large qui
   déroule seule comme les tableaux, jamais la page ; $…$ en ligne, aligné
   sur la ligne et insécable. Les équations suivent la taille du texte
   environnant : KaTeX cale tout en em, rien de fixe ici. */
.math-block { margin: 10px 0; overflow-x: auto; overflow-y: hidden; }
.math-block .katex-display { margin: 0; }
.math-inline { white-space: nowrap; }
/* Diagrammes Mermaid des messages (SENTINEL-212, lot 2) : le conteneur du
   SVG, même famille que pre et .math-block — fond légèrement distinct de la
   bulle, déroulement horizontal seul (un diagramme large garde sa taille
   naturelle, fixée par le code au viewBox, et ne sort jamais de la page).
   Le pre>code de repli — tant que le SVG n'est pas rendu, ou pour toujours
   si la source est invalide — vit dedans sans double encadré. */
.mermaid-block { margin: 10px 0; padding: 12px; background: var(--bg);
  border: 1px solid var(--line); border-radius: 6px;
  overflow-x: auto; overflow-y: hidden; }
.mermaid-block svg { display: block; margin: 0 auto; height: auto; }
.mermaid-block pre { background: none; border: none; padding: 0; margin: 0;
  text-align: left; }
.mermaid-block .mermaid-err { margin-top: 8px; font-size: 13px; color: var(--bad);
  text-align: left; overflow-wrap: anywhere; }
/* SENTINEL-302 : l'affordance de défilement horizontal des blocs larges
   (tableau, Mermaid, formule, code) — sans elle rien ne montre qu'un bloc
   continue hors champ, surtout sur mobile où la scrollbar système est
   invisible. `documents.js` (poserAffordanceDefilement) mesure le
   défilement réel et bascule deux éléments `.defil-fondu` (gauche/droite)
   avec `.show` — à gauche une fois qu'on a défilé, à droite tant qu'il
   reste du contenu, jamais les deux en butée. Posés en enfants du bloc qui
   défile, ils défilent avec son contenu (constaté à l'usage, pseudo-élément
   ou noeud réel pareil) : `documents.js` les pose plutôt dans un
   `.defil-cadre` englobant, qui ne défile pas lui, et les ancre à ses
   bords. Couleur de --accent (#7d8cf8) en triplet : un fondu basé sur --bg
   (quasi noir) serait invisible sur le thème sombre. */
.defil-cadre { position: relative; }
.defil-fondu {
  position: absolute; top: 0; bottom: 0; width: 20px; pointer-events: none; opacity: 0;
}
.defil-fondu.show { opacity: 1; }
.defil-fondu.g { left: 0; background: linear-gradient(to right, rgba(125, 140, 248, .55), transparent); }
.defil-fondu.d { right: 0; background: linear-gradient(to left, rgba(125, 140, 248, .55), transparent); }
/* SENTINEL-398 : le fondu seul se lisait mal — un chevron dans le fondu dit
   qu'il reste à voir de ce côté.
   Le chevron suit la lecture (sticky) : sur un long tableau, il reste à
   l'écran au lieu de rester au milieu du bloc, hors de vue. */
.defil-fondu { width: 28px; display: flex; align-items: flex-start; justify-content: center;
  color: #fff; font-size: 20px; font-weight: 600; line-height: 1; }
.defil-fondu::after { position: sticky; top: 45vh; margin-top: 10px; }
.defil-fondu.g::after { content: '‹'; }
.defil-fondu.d::after { content: '›'; }
.msg-body table { border-collapse: collapse; }
.msg-body th, .msg-body td {
  border: 1px solid var(--line); background: var(--bg); padding: 4px 9px;
  text-align: left; vertical-align: top; white-space: nowrap;
}
.msg-body th { font-family: var(--mono); font-size: 11.5px; font-weight: 600; color: var(--muted); }
.msg-body th.ta-r, .msg-body td.ta-r { text-align: right; }
.msg-body th.ta-c, .msg-body td.ta-c { text-align: center; }
.msg-body strong { color: #fff; font-weight: 600; }
.msg-body a { color: var(--accent); }
/* SENTINEL-305 : image Markdown ![alt](url) d'un message ou d'un document
   (.msg-body porte les deux, documents.js ajoute .doc-body en plus) — jamais
   plus large que la colonne, jamais de debordement horizontal sur mobile. */
.msg-body img.msg-img { display: block; max-width: 100%; height: auto; border-radius: 6px; margin: 8px 0; }
/* Titres et listes markdown des messages (SENTINEL-209) : sobres, IBM Plex,
   thème sombre — h2 et h3 portent la structure des listes d'agents, h1 rare ;
   puces pleines au premier niveau, creuses au second. */
.msg-body h1, .msg-body h2, .msg-body h3 {
  font-weight: 600; line-height: 1.35; color: var(--text);
  margin: 14px 0 6px; overflow-wrap: anywhere;
}
.msg-body h1 { font-size: 17.5px; }
.msg-body h2 { font-size: 16.5px; }
.msg-body h3 { font-size: 15px; color: var(--muted); }
.msg-body h1:first-child, .msg-body h2:first-child, .msg-body h3:first-child { margin-top: 0; }
.msg-body ul, .msg-body ol { margin: 0 0 8px; padding-left: 22px; }
.msg-body ul { list-style: disc; }
.msg-body ul ul { list-style: circle; }
.msg-body li { margin: 2px 0; }
.msg-body li > ul, .msg-body li > ol { margin: 2px 0 4px; }
.msg-body ul:last-child, .msg-body ol:last-child { margin-bottom: 0; }
/* Ligne de séparation `---`, `***`, `___` (SENTINEL-398) : un filet discret. */
.msg-body hr { border: none; border-top: 1px solid var(--line); margin: 14px 0; }
.doc-body hr { margin: 22px 0; }

/* ===== Documents d'un fil (SENTINEL-213) ===== */
/* La section discrète du rail : une ligne par document déposé — titre, auteur,
   date, jamais le contenu — qui mène à la page du document. */
.thread-docs .section-title { margin: 2px 0 8px; }
.doc-row {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px;
  width: 100%; text-align: left; background: none; border: none;
  border-top: 1px solid var(--line); padding: 8px 0; cursor: pointer;
  color: var(--text); font-family: var(--sans);
}
.doc-row:first-of-type { border-top: none; }
.doc-row:hover .doc-t { color: var(--accent); }
.doc-row .doc-t { flex: 1 1 100%; font-size: 13.5px; font-weight: 600;
  line-height: 1.35; overflow-wrap: anywhere; }
.doc-row .doc-m { flex: none; font-family: var(--mono); font-size: 11px; color: var(--faint); }
/* SENTINEL-222 : la pastille « Sur le document « … » » d'une remarque liée —
   au-dessus du corps du message, discrète, vers la page du document (même
   lien que la carte Documents). Un titre long se coupe à l'ellipse, la bulle
   ne déborde jamais. */
.doc-ref {
  display: block; font-size: 12px; line-height: 1.4; color: var(--faint);
  margin-bottom: 4px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.doc-ref strong { font-weight: 600; color: var(--muted); }
.doc-ref:hover, .doc-ref:hover strong { color: var(--accent); }
/* SENTINEL-233 : « pour nexus » — l'agent du fil que le message de l'utilisateur
   désigne, à côté de l'auteur, sobre comme la pastille document ci-dessus ;
   le handle complet reste en infobulle. */
.msg-pour { font-size: 12px; color: var(--faint); white-space: nowrap;
  max-width: 220px; overflow: hidden; text-overflow: ellipsis; }
/* La page d'un document : le corps reprend la carte de lecture des messages
   (msg-body) sans son encadré de bulle — une page, pas un message. Le rendu
   Markdown (titres, listes, tableaux, code, SENTINEL-209) vient des styles
   msg-body, ajustés plus bas pour la page (tableaux, séparateurs).
   SENTINEL-398 (remplace la colonne de 800 px et la grille « breakout » de
   SENTINEL-301) : une seule largeur pour tout. 07/10 : « il faudrait
   qu'on utilise le plus de la largeur possible disponible dans l'écran ».
   Le retour au fil, le titre, le texte, les tableaux, les diagrammes et les
   remarques occupent toute la largeur de la vue, avec ses marges. Avant, le
   texte était centré à 800 px et les blocs larges dans un cadre plus grand
   décalé à gauche : la lecture sautait d'un bord à l'autre. */
/* Le retour au fil reste visible a toutes les largeurs : la page du document
   est pleine largeur, sans liste des fils a cote qui servirait de retour (le
   bouton du fil, lui, est mobile-only — la liste le remplace sur bureau). */
#view-document .thread-back { display: block !important; }
.doc-titre { font-size: 23px; font-weight: 600; line-height: 1.25; letter-spacing: -.01em;
  margin: 6px 0 0; overflow-wrap: anywhere; }
.doc-meta { font-size: 13px; color: var(--muted); margin: 6px 0 10px; }
.doc-actions { margin: 0 0 18px; }
.doc-body {
  background: none; border: none; border-top: 1px solid var(--line);
  border-radius: 0; padding: 16px 0 0; line-height: 1.65;
}
/* Tableaux de la page (SENTINEL-398) : les cellules passent à la ligne pour
   que le tableau tienne dans la colonne tant que c'est possible — un
   plancher sur les colonnes de texte long (`col-long`, posé par tableEl)
   évite les colonnes d'un mot par ligne (le souci que SENTINEL-71 réglait
   par nowrap dans les bulles ; SENTINEL-402 : les bulles passent aussi à la
   ligne, avec un plancher plus bas). Le code en ligne et les mots
   ne se coupent pas au milieu dans une cellule. Ce qui reste trop large est
   réduit à l'échelle par documents.js (ajusterEchelle) ; sous le plancher,
   il défile, avec l'affordance (SENTINEL-302) et une barre visible. Le code
   d'un document passe à la ligne au lieu de défiler. */
.msg-body td { white-space: normal; overflow-wrap: normal; }
.msg-body td.col-long { min-width: 10em; }
.doc-body td.col-long { min-width: 16em; }
.msg-body td code { white-space: nowrap; }
.doc-body pre, .doc-body pre code { white-space: pre-wrap; overflow-wrap: anywhere; }
.doc-body .table-wrap, .doc-body .mermaid-block, .doc-body .math-block, .doc-body pre {
  scrollbar-width: thin; scrollbar-color: var(--accent) transparent; }
.msg-summary { font-size: 13px; color: var(--muted); margin-bottom: 4px; }
/* Reponse a un message : le destinataire porte sa couleur quand le message
   vise est charge dans la page (sinon son numero seul). */
.msg-summary .sess-name { font-size: 12.5px; }
/* Lignes de trace (but, etapes, mandat) : une ligne grise, jamais un message. */
/* SENTINEL-237 : une famille visuelle pour tout ce que dit Agora — etiquette,
   evenement, texte entier (plus de troncature), liseré discret ; jamais un message. */
.msg-sys {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px;
  font-size: 12.5px; color: var(--muted); margin: 8px 0; padding: 4px 0 4px 10px;
  border-left: 2px solid var(--line); line-height: 1.5; max-width: 86ch;
}
.msg-sys-qui { font-family: var(--mono); font-size: 10.5px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--tool); }
.msg-sys-evt { font-family: var(--mono); font-size: 10.5px; padding: 0 6px; border-radius: 999px;
  border: 1px solid var(--line); color: var(--faint); }
.msg-sys-x { flex: 0 1 auto; min-width: 0; overflow-wrap: anywhere; }
.msg-sys-t { font-family: var(--mono); font-size: 11px; color: var(--faint); opacity: .8; }
.msg-sys.evt-fermeture, .msg-sys.evt-fermeture_froid { border-left-color: rgba(239,107,107,.45); }
.msg-sys.evt-reouverture, .msg-sys.evt-ouverture { border-left-color: rgba(65,217,141,.45); }
/* SENTINEL-493 : un réveil programmé — liseré pervenche ; « reçu par K »
   discret, à côté du texte qui dit déjà « livré à N ». */
.msg-sys.evt-reveil { border-left-color: rgba(125,140,248,.5); }
.msg-sys-recu { font-family: var(--mono); font-size: 11px; color: var(--faint); }
.msg-deleted { font-style: italic; color: var(--faint); font-size: 13px; }
.ev { margin-top: 8px; border: 1px solid var(--line); border-left: 3px solid var(--accent); border-radius: 6px; background: var(--bg); overflow: hidden; }
.ev-head { font-family: var(--mono); font-size: 11.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--accent); padding: 6px 10px; border-bottom: 1px solid var(--line); }
.ev pre { margin: 0; padding: 8px 10px; font-family: var(--mono); font-size: 12px; white-space: pre-wrap; overflow-wrap: anywhere; }
.ev .out { color: var(--muted); border-top: 1px dashed var(--line); }
.msg-secret { margin-top: 6px; padding: 5px 10px; border-radius: 6px; font-family: var(--mono); font-size: 11px; color: #ffb4a2; background: rgba(255,90,60,.1); border: 1px solid rgba(255,90,60,.35); }
/* Le champ de remarque sous la lecture (SENTINEL-215, choix A de l'utilisateur) :
   sobre comme la saisie du fil — la remarque part dans le fil, préfixée par
   le document regardé ; confirmation discrète en vert, lien de retour. */
.doc-remarque .cmp-text { background: var(--bg); }
/* SENTINEL-398 : le champ reste accessible pendant la lecture — collé au bas
   de l'écran (sticky dans #app > main) tant que la fin du document n'est pas
   atteinte, à sa place ensuite. Compact pour masquer peu : une ou deux lignes
   de saisie, plus au focus ; repliable en sa seule ligne de titre. Une ombre
   portée vers le haut le détache du texte qui passe dessous. */
.doc-remarque { position: sticky; bottom: 0; z-index: 2; margin: 26px 0 0;
  padding: 8px 14px 10px; box-shadow: 0 -8px 20px rgba(0,0,0,.45); }
.doc-remarque .section-title { margin: 0 0 6px; align-items: center; }
.doc-remarque.replie .section-title { margin: 0; }
.doc-remarque .doc-rem-text { min-height: 44px; height: 44px; }
.doc-remarque:focus-within .doc-rem-text { height: 96px; }
.doc-remarque .cmp-act { margin-top: 6px; }
.doc-remarque .cmp-act .btn { min-height: 34px; }
.doc-rem-plier { background: none; border: none; padding: 2px 0; cursor: pointer;
  font-family: var(--mono); font-size: 11px; letter-spacing: 0; text-transform: none;
  color: var(--accent); }
.doc-rem-plier:hover { text-decoration: underline; text-underline-offset: 2px; }
.doc-rem-plier:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Téléphone : l'aide « Ctrl + Entrée » n'y sert pas, elle cède sa place
   pour que le champ tienne sur peu de hauteur. Les colonnes longues y
   gardent un plancher plus bas : le tableau tient plus souvent par la
   réduction à l'échelle, sans défiler. */
@media (max-width: 640px) {
  .doc-body td.col-long { min-width: 8em; }
  .doc-remarque .cmp-hint { display: none; }
  .doc-remarque { padding: 6px 10px 8px; }
}
.doc-rem-ok { color: var(--live); font-size: 13px; }
.doc-rem-ok a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }

/* ===== Enrolements, machines ===== */
.code-big { font-family: var(--mono); font-size: 24px; font-weight: 600; letter-spacing: 3px; color: var(--accent); }
.row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.row.end { justify-content: flex-end; }
.actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.btn {
  min-height: 42px; padding: 0 16px; border-radius: 8px; cursor: pointer;
  border: 1px solid var(--line); background: var(--panel-2); font-size: 14px;
}
.btn.primary { background: var(--accent); border-color: var(--accent); color: #0e1116; font-weight: 600; }
.btn.danger { color: var(--bad); border-color: rgba(239,107,107,.45); background: none; }
.btn:disabled { opacity: .45; cursor: default; }
.btn.small { min-height: 34px; padding: 0 12px; font-size: 13px; }
.field { display: flex; flex-direction: column; gap: 4px; margin-top: 10px; }
.field label { font-family: var(--mono); font-size: 11px; color: var(--faint); }
.field input {
  min-height: 42px; background: var(--bg); color: var(--text); border: 1px solid var(--line);
  border-radius: 8px; padding: 0 12px; font-size: 15px; font-family: var(--sans);
}
.field input:focus { outline: none; border-color: var(--accent); }

/* ===== Complements (JS) ===== */
button.link {
  background: none; border: none; padding: 0; cursor: pointer; text-align: left;
  color: var(--accent); font: inherit; font-size: 13.5px; font-weight: 500;
}
.hint { font-size: 12.5px; margin-top: 10px; }
.enroll-kv { margin: 10px 0 0; }
.idents { margin-top: 8px; border-top: 1px solid var(--line); padding-top: 6px; }
.idents .agent-row { padding: 3px 0; }
.agent-meta.right { margin-left: auto; }
.confirm { margin-top: 12px; padding-top: 10px; border-top: 1px dashed var(--line); }
.confirm .faint { font-size: 12.5px; margin-top: 4px; }
.messages { margin-top: 4px; }



/* ===== Vue d'ensemble (SENTINEL-103, dispo SENTINEL-148) : un ecran, une periode ===== */

/* Bandeau de periode, 44 px sous la barre de navigation : selecteur segmente,
   compteurs, heure. */
.ov-bar { flex: none; height: 44px; display: flex; align-items: center; gap: 6px 18px;
  font-family: var(--mono); font-size: 12.5px; color: var(--muted); }
.seg { display: flex; border: 1px solid var(--line); border-radius: 6px; overflow: hidden; flex: none; }
.seg button { padding: 5px 11px; border-right: 1px solid var(--line);
  font-family: var(--mono); font-size: 12.5px; color: var(--muted); cursor: pointer; }
.seg button:last-child { border-right: 0; }
.seg button.on { background: rgba(125,140,248,.18); color: var(--text); }
.seg button:focus-visible { outline-offset: -2px; }
.ov-counts { display: flex; flex-wrap: wrap; gap: 4px 16px; min-width: 0;
  font-variant-numeric: tabular-nums; }
.ov-counts .ct { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.ov-counts .ct b { color: var(--text); font-weight: 600; }
.ov-counts .ct.link { cursor: pointer; }
.ov-counts .ct.link:hover { color: var(--text); }
.ov-fill { flex: 1; }
.ov-updated { color: var(--faint); font-size: 11.5px; white-space: nowrap; }
.ov-updated.bad { color: var(--bad); cursor: help; }

/* Corps : la scene a gauche — toute la hauteur tant que la frise de
   SENTINEL-150 n'est pas livree — et la colonne de droite sur les deux
   lignes (Sessions 45 %, Fils le reste). */
.ov-grid { flex: 1; min-height: 0; display: grid; grid-template-columns: 1fr 372px;
  grid-template-rows: 1fr 232px; gap: 12px; position: relative; }
.panel {
  background: var(--panel); border: 1px solid var(--line); border-radius: 10px;
  display: flex; flex-direction: column; min-height: 0; overflow: hidden;
}
.ov-scene { grid-row: 1 / 3; min-width: 0; }
.ov-side { grid-row: 1 / 3; grid-column: 2; display: flex; flex-direction: column;
  gap: 12px; min-height: 0; }
.ov-side #ov-sessions { flex: 0 0 45%; min-height: 0; }
.ov-side #ov-threads-panel { flex: 1; min-height: 0; }
.panel-title {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: 2px; text-transform: uppercase;
  color: var(--muted); padding: 9px 14px 7px; border-bottom: 1px solid var(--line);
  display: flex; align-items: baseline; gap: 10px; flex: none;
}
.panel-title .sub { letter-spacing: 0; text-transform: none; color: var(--faint); font-size: 10.5px; }
.panel-body { flex: 1; overflow-y: auto; padding: 8px 12px; min-height: 0; }
.panel-body::-webkit-scrollbar { width: 8px; }
.panel-body::-webkit-scrollbar-thumb { background: var(--line); border-radius: 4px; }

/* Le graphe : le fond porte le degage du panneau, la scene 3D rend #0e1116 */
.graph-wrap { flex: 1; position: relative; min-height: 0; overflow: hidden;
  background: radial-gradient(ellipse at 50% 42%, rgba(125,140,248,.05), transparent 62%), var(--bg); }
.scene-host { position: absolute; inset: 0; }

/* Infobulle du survol (noeud ou trait) : DOM maison, jamais de HTML d'agent */
.gtip {
  position: absolute; z-index: 6; pointer-events: none; max-width: 330px;
  background: rgba(16,20,28,.97); border: 1px solid var(--line); border-radius: 8px;
  padding: 9px 11px; box-shadow: 0 8px 28px rgba(0,0,0,.45);
  font-size: 12.5px; line-height: 1.5; color: var(--text);
}
.gtip .tt-name { font-family: var(--mono); font-weight: 600; font-size: 13px; }
.gtip .tt-ident { font-family: var(--mono); font-size: 11.5px; color: var(--muted); margin-top: 1px; }
.gtip .tt-state { margin-top: 5px; font-size: 12.5px; }
.gtip .tt-sess { font-family: var(--mono); font-size: 11.5px; color: var(--muted); margin-top: 5px; display: flex; flex-direction: column; gap: 2px; }
.gtip .tt-facts { font-family: var(--mono); font-size: 11.5px; color: var(--faint); margin-top: 6px; padding-top: 6px; border-top: 1px dashed var(--line); }

/* Les noms, au survol seulement (SENTINEL-149) : couche HTML au-dessus du
   canvas, taille fixe en pixels — nets et lisibles a toute distance. La
   couche ne capte pas la souris : le survol et les clics passent au graphe. */
.glabels {
  position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 3;
}
.glabel {
  position: absolute; left: 0; top: 0;
  font-family: var(--mono); font-size: 12.5px; line-height: 1.25;
  color: var(--text); background: rgba(14,17,22,.72);
  padding: 1px 6px; border-radius: 4px; white-space: nowrap;
  will-change: transform; user-select: none;
}
.glabel.off { display: none; }
/* Le sujet d'un fil, au survol comme les noms : meme couche, meme taille
   (12,5 px, SENTINEL-149), style distinct */
.glabel.fil { font-style: italic; color: var(--muted); font-size: 11.5px;
  border: 1px solid var(--line); }
/* SENTINEL-189 : noms toujours visibles — discrets pour les agents, en
   evidence pour l'humain. */
.glabel.agent { font-size: 11.5px; color: var(--muted); background: rgba(14,17,22,.55); }
/* SENTINEL-395 : le nom d'un depot au sommet de son enveloppe — discret, sans fond. */
.glabel.depot { background: none; font-size: 11px; letter-spacing: .04em; opacity: .85; padding: 0 2px; }
/* SENTINEL-417 : l'anneau « Organisation › Équipe » (teinte posée par la scène). */
.glabel.depot.equipe { font-family: var(--mono); font-size: 10.5px; opacity: .95; }
.glabel.humain { font-family: var(--sans); font-weight: 600; font-size: 13px; color: #f6c1d3; }

/* La légende de la scène (SENTINEL-149, refondue par SENTINEL-315) : un
   cartouche de lignes courtes, en bas à gauche, mono 11,5 px — couleur =
   le dépôt (pastilles des dépôts présents) et forme = l'état. Toujours
   visible sur ordinateur ; masquée sous 900 px : l'écran étroit ne lui
   laisse pas de place, et ses formes se lisent au survol, pas à la tape.
   Le bouton « Légende » qui la repliait s'en est allé avec le repli. */
.glegend {
  position: absolute; left: 10px; bottom: 10px; z-index: 5;
  display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
  max-width: calc(100% - 20px);
  font-family: var(--mono); font-size: 11.5px; color: var(--muted);
  background: rgba(21,26,35,.88); border: 1px solid var(--line);
  border-radius: 6px; padding: 4px 9px; pointer-events: none;
}
.glegend .lg-l { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 5px; }
@media (max-width: 899px) { .glegend { display: none; } }
.glegend .lg { font-size: 12px; flex: none; }
.glegend .lg.s { color: #7d8cf8; }   /* ● session (la couleur varie par dépôt) */
.glegend .lg.h { color: #ef8fb0; }   /* ⊙ humain (SENTINEL-180, rose fixe) */
.glegend .lg.f { color: var(--muted); }
.glegend .lg.a { color: #f0b429; }   /* ■ fil actif */
.glegend .lg.p { color: #a07d2e; }   /* ■ fil en pause */
.glegend .lg.e { color: #5a6478; }   /* ■ fil éteint */
/* Les pastilles « couleur = le dépôt » (SENTINEL-315) : cliquables seules
   dans un cartouche sinon traversé par le graphe (pointer-events: none
   ci-dessus) ; un clic passe le dépôt à la teinte suivante du palet. */
.glegend .lg-depots { display: inline-flex; flex-wrap: wrap; gap: 2px 8px; }
.glegend .lg-depot {
  pointer-events: auto; cursor: pointer; display: inline-flex;
  align-items: center; gap: 4px; font: inherit; color: var(--muted);
  background: none; border: 0; padding: 0;
}
.glegend .lg-depot:hover { color: var(--text); text-decoration: underline; }
.glegend .lg-depot.err { color: #e5484d; }
.glegend .lg-dot {
  width: 9px; height: 9px; border-radius: 50%; flex: none;
  background: #66708a; border: 1px solid rgba(255,255,255,.22);
}

/* Commandes du graphe : petits boutons sobres, coin haut droit du panneau */
.graph-tools { position: absolute; top: 10px; right: 10px; z-index: 5; display: flex; gap: 6px; }
.gtool {
  font-family: var(--mono); font-size: 11px; color: var(--muted);
  border: 1px solid var(--line); border-radius: 6px; padding: 4px 10px;
  background: rgba(21,26,35,.88); cursor: pointer; white-space: nowrap;
}
.gtool:hover { color: var(--text); }
.gtool.on { color: var(--text); border-color: var(--accent); background: rgba(125,140,248,.14); }

/* Sans WebGL : la scene ne s'ouvre pas, les panneaux restent */
.no-webgl {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  padding: 24px; text-align: center; color: var(--muted); font-size: 14px; line-height: 1.6;
}
.no-webgl b { color: var(--text); font-family: var(--mono); font-size: 13px; display: block; margin-bottom: 6px; }

/* Marqueur d'ecoute, volontairement simple (SENTINEL-148) : un point plein
   quand la session ecoute, vide sinon — l'anneau anime vient avec
   SENTINEL-152. */
.lm { display: inline-block; width: 10px; height: 10px; border-radius: 50%;
  border: 1.5px solid var(--faint); background: transparent; flex: none; }

/* Pastille de la couleur d'agent (SENTINEL-149) : la teinte vient du slot
   resolu par le serveur (`interface.agent_colors`, par depot) — bleu, orange,
   sarcelle, orchidee, gris ardoise hors table. */
.cl { display: inline-block; width: 8px; height: 8px; border-radius: 50%; flex: none; }

/* Marqueur d'humain (SENTINEL-180) : le meme anneau que la scene 3D, en
   glyph — rose fixe, hors des palettes d'agents et d'etats. */
.hm-glyph { color: #ef8fb0; font-family: var(--mono); font-size: 12.5px;
  line-height: 1; flex: none; }

/* Panneau Sessions : une ligne de 28 px, grille 14px 1fr 70px 30px 44px —
   marqueur, nom court « depot > code » avec pastille d'agent, barre de
   volume, messages, fils. La ligne d'un humain (SENTINEL-180) garde la meme
   grille — marqueur ⊙, « nom · humain » — sur un fond a peine rose. */
.ov-srow { display: grid; grid-template-columns: 14px 1fr 70px 30px 44px;
  align-items: center; gap: 8px; height: 28px; font-size: 13px;
  border-radius: 5px; padding: 0 2px; }
.ov-srow:hover, .ov-srow.hl { background: rgba(125,140,248,.07); }
.ov-srow.humain, .ov-srow.humain:hover, .ov-srow.humain.hl {
  background: rgba(239,143,176,.06); }
.ov-srow.humain.hl { background: rgba(239,143,176,.14); }
.ov-srow .nm { display: flex; align-items: center; gap: 6px; min-width: 0;
  font-family: var(--mono); font-size: 12px; color: var(--text);
  white-space: nowrap; overflow: hidden; }
/* SENTINEL-268 : le nom de la session (role sinon code) passe avant le depot,
   qui cede la place le premier. */
.ov-srow .nm .rp { flex: 0 0 auto; max-width: 65%; min-width: 3ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ov-srow .nm .rp.none { color: var(--faint); font-style: italic; }
.ov-srow .nm .rp.humain-nom { color: #ef8fb0; }
.ov-srow .nm .cd { color: var(--faint); flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vbar { height: 6px; background: var(--panel-2); border-radius: 3px; overflow: hidden; }
.vbar i { display: block; height: 100%; background: var(--accent); border-radius: 3px; }
.ov-srow.humain .vbar i { background: #ef8fb0; }
.ov-srow .n { font-family: var(--mono); font-size: 12px; color: var(--text);
  text-align: right; font-variant-numeric: tabular-nums; }
.ov-srow .f { font-family: var(--mono); font-size: 11px; color: var(--faint);
  text-align: right; white-space: nowrap; }

/* Panneau Fils : deux lignes par fil — losange d'etat, sujet, nombre ; puis
   barre de 90 px et codes des sessions qui ont parle, par volume. Le losange
   suit les seuils de window.thresholds (actif / en pause / eteint), en
   pointille si le fil est clos. */
.ov-trow { display: block; width: 100%; text-align: left; padding: 5px 4px;
  border-top: 1px solid var(--line); cursor: pointer; border-radius: 0 6px 6px 0; }
.ov-trow:first-child { border-top: none; }
.ov-trow:hover, .ov-trow.hl { background: rgba(125,140,248,.07); }
.ov-tl1 { display: flex; align-items: baseline; gap: 8px; font-size: 13px; }
.ov-tsubj { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ov-tn { font-family: var(--mono); font-size: 12px; color: var(--text); flex: none;
  font-variant-numeric: tabular-nums; }
.ov-tl2 { display: grid; grid-template-columns: 90px 1fr; gap: 10px; align-items: center;
  margin: 3px 0 0 20px; }
.ov-tl2 .vbar { width: 90px; }
.ov-twho { font-family: var(--mono); font-size: 11.5px; color: var(--faint);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Losange d'etat d'un fil : actif (plein, chaud), en pause (ocre), eteint
   (gris) ; clos : pointille. Memes couleurs que la chaleur de la scene. */
.dz { display: inline-block; width: 9px; height: 9px; transform: rotate(45deg);
  border: 1.5px solid #5a6478; flex: none; }
.dz.actif { border-color: var(--heat-0); background: rgba(240,180,41,.3); }
.dz.pause { border-color: #a07d2e; }
.dz.clos { border-style: dashed; }

/* Fiche d'un fil (elle remplace le panneau Fils au clic) */
.ov-fiche { display: flex; flex-direction: column; height: 100%; }
.ov-h { font-family: var(--mono); font-size: 10.5px; letter-spacing: 2px;
  text-transform: uppercase; color: var(--faint); margin: 10px 0 4px; }
.ov-fiche .ov-h:first-child { margin-top: 2px; }
.ov-fhead { padding: 9px 14px 10px; border-bottom: 1px solid var(--line); flex: none; }
.ov-back { background: none; border: none; padding: 0; cursor: pointer;
  color: var(--accent); font-family: var(--mono); font-size: 12px; }
.ov-fsub { font-size: 15px; font-weight: 600; line-height: 1.3; margin-top: 4px; }
.ov-fmeta { font-family: var(--mono); font-size: 11.5px; color: var(--muted);
  margin-top: 4px; display: flex; flex-wrap: wrap; gap: 3px 12px; }
.ov-fbody { flex: 1; overflow-y: auto; padding: 8px 14px 12px; min-height: 0; }
.ov-fbody::-webkit-scrollbar { width: 8px; }
.ov-fbody::-webkit-scrollbar-thumb { background: var(--line); border-radius: 4px; }
.ov-fwho { display: flex; align-items: center; gap: 7px; padding: 2px 0;
  font-family: var(--mono); font-size: 12px; color: var(--muted); }
.ov-fwho .n { margin-left: auto; color: var(--text); }
.ov-fwho.humain { color: #ef8fb0; }
/* SENTINEL-417 : l'auteur d'un autre propriétaire, dans un fil partagé. */
.ov-fwho.externe { color: var(--muted); }
.ov-fwho.externe .hm-glyph { color: var(--faint); }
.ov-fpartage { color: var(--accent); }
.ov-fwho.humain .n { color: var(--text); }
.ov-msg { border-top: 1px solid var(--line); padding: 6px 0; margin-top: 6px; }
.ov-msg:first-of-type { border-top: none; }
.ov-msg .mm { font-family: var(--mono); font-size: 11px; color: var(--faint); }
.ov-msg .mt { font-size: 12.5px; color: var(--muted); margin-top: 2px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.ov-open { min-height: 36px; border-radius: 8px; cursor: pointer;
  border: 1px solid var(--accent); background: rgba(125,140,248,.14); color: var(--text);
  font-family: var(--mono); font-size: 12.5px; width: 100%; }
.ov-open:hover { background: rgba(125,140,248,.24); }
/* Le pied de la fiche : « Ouvrir le fil » reste visible, le corps defile. */
.ov-ffoot { flex: none; padding: 10px 14px; border-top: 1px solid var(--line); }

/* Tiroir des sessions : la table de la vigie par-dessus la colonne de droite,
   ouvert depuis les compteurs d'ecoute du bandeau. */
.ov-drawer { position: absolute; top: 0; bottom: 0; right: 0; width: min(600px, 100%);
  background: var(--panel); border: 1px solid var(--line); border-radius: 10px;
  z-index: 8; display: flex; flex-direction: column; min-height: 0;
  box-shadow: -18px 0 40px rgba(0,0,0,.45); }
.ov-drawer .panel-body { flex: 1; overflow: auto; }
.ov-drawer-close { margin-left: auto; background: none; border: none; cursor: pointer;
  color: var(--muted); font-family: var(--mono); font-size: 12px; padding: 0 2px; }
.ov-drawer-close:hover { color: var(--text); }

/* Styles que la bibliotheque 3D injecte en <style> : leurs empreintes sont
   declarees dans la CSP (ui.py) pour une console propre, donc les deux
   s'appliquent — nos copies passent devant par specificite (`#app`),
   l'identite de l'interface gagne. La barre de navigation de la scene est
   coupee (showNavInfo(false)) ; sa regle reste, par completude. */
#app .scene-container { position: relative; }
#app .scene-container canvas:focus { outline: none; }
#app .scene-nav-info {
  position: absolute; bottom: 5px; width: 100%; text-align: center;
  color: var(--faint); opacity: .7; font-size: 10px; font-family: var(--mono);
  pointer-events: none; user-select: none;
}
#app .float-tooltip-kap {
  position: absolute; width: max-content; max-width: max(50%, 150px);
  padding: 3px 5px; border-radius: 3px; font-family: var(--sans); font-size: 12px;
  color: var(--text); background: rgba(16,20,28,.95); border: 1px solid var(--line);
  pointer-events: none;
}
#app .graph-info-msg {
  top: 50%; width: 100%; text-align: center; color: var(--muted); opacity: .7;
  font-size: 22px; position: absolute; font-family: var(--sans);
}
#app .scene-container .clickable { cursor: pointer; }
#app .scene-container .grabbable { cursor: move; cursor: grab; }
#app .scene-container .grabbable:active { cursor: grabbing; }

/* Sous 1280 px : l'ecran sans defilement n'est plus promis (SENTINEL-148 le
   tient a partir de 1280x800) — la vue se replie en colonne sans se casser. */
@media (max-width: 1279px) {
  #view-reseau.on { height: auto; overflow: visible; }
  .ov-grid { display: flex; flex-direction: column; height: auto; flex: none; }
  .ov-scene { flex: none; height: max(340px, 52dvh); }
  .ov-side { flex: none; }
  .ov-side #ov-sessions, .ov-side #ov-threads-panel { flex: none; }
  .ov-side #ov-sessions .panel-body, #ov-threads-panel .panel-body,
  #ov-threads-panel .ov-fbody { max-height: 320px; }
  .ov-bar { height: auto; flex-wrap: wrap; padding: 8px 0; }
  /* Le compteur d'humains (SENTINEL-180) s'insere apres l'ecoute : les deux
     derniers compteurs plient d'abord, l'humain reste visible. */
  .ov-counts .ct:nth-child(n+6) { display: none; }
  .ov-drawer { position: fixed; top: 10px; bottom: 10px; right: 10px; }
}

/* ===== Bureau et mobile ===== */
.threads-layout { display: block; }
.thread-rail { min-width: 0; }
@media (min-width: 900px) {
  /* La liste suit l'ecran (360 a 480 px) au lieu de 400 px fixes ; le fil
     prend le reste — a 1920 px il gagne ~600 px (SENTINEL-104). */
  /* Colonne de liste (SENTINEL-151) : 420 px en 1440, 480 px en 1920
     (240 + 12.5vw passe par les deux), 340 px au plancher des grands écrans. */
  /* SENTINEL-252 : la page des fils tient la hauteur de <main> (le patron de
     la vue Reseau) et chaque colonne defile dans sa propre fenetre — la liste
     a gauche, le fil a droite. L'ancien sticky (top 70px, max-height
     100dvh - 90px) etait cale sur un defilement du body, en-tete compris ;
     le defilement vit dans #app > main, sous l'en-tete : la colonne debordait
     de ~40 px sous la fenetre et le dernier fil restait coupe. */
  #view-threads.on { height: 100%; padding-bottom: 0; }
  .threads-layout { display: grid; grid-template-columns: clamp(300px, calc(160px + 11vw), 400px) minmax(0, 1fr); grid-template-rows: minmax(0, 1fr); gap: 28px; height: 100%; }
  .thread-side { min-height: 0; overflow-y: auto; padding: 0 4px 24px 0; }
  .thread-main { min-height: 0; overflow-y: auto; padding-bottom: 24px; }
  .thread-back { display: none !important; }
  .machines-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(460px, 1fr)); gap: 0 14px; }
}
/* Grand ecran (>= 1450 px) : le detail du fil monte dans un rail colle a
   droite des messages — participants et details restent visibles pendant la
   lecture. Le duo colle a la liste des fils (gouttiere de la grille) ; le
   reliquat de largeur reste a droite du rail, jamais entre les deux colonnes.
   Les messages gardent leur mesure (72ch ~= 85 caracteres). */
@media (min-width: 1450px) {
  /* SENTINEL-252 : les messages et le rail defilent chacun dans sa fenetre,
     bornee a la hauteur de l'ecran. Le rail colle (SENTINEL-220) ne montrait
     son bas — les documents — qu'a la fin de la discussion ; il deroule
     maintenant seul jusqu'au dernier document, la discussion ne bouge pas. */
  .thread-main { display: grid; grid-template-columns: minmax(0, 1fr) minmax(300px, 380px); grid-template-rows: minmax(0, 1fr); gap: 0 30px; overflow: hidden; padding-bottom: 0; }
  .thread-col { grid-column: 1; min-width: 0; min-height: 0; overflow-y: auto; padding-bottom: 24px; }
  .thread-rail { grid-column: 2; grid-row: 1; min-height: 0; overflow-y: auto; padding: 0 4px 24px 0; }
}
/* SENTINEL-252 : le saut vers les documents ne sert que sans rail a droite. */
@media (min-width: 1450px) { .docs-saut { display: none; } }
@media (max-width: 899px) {
  /* SENTINEL-309 : une seule rangée (~56-64 px) — logo, les quatre onglets
     du quotidien (la nav défile horizontalement si l'écran est trop étroit),
     le menu secondaire. Plus de rangée d'administration ni de bouton
     Verrouiller pleine largeur. */
  .top { flex-wrap: nowrap; gap: 6px; padding: 12px 8px; padding-top: calc(12px + env(safe-area-inset-top)); }
  /* SENTINEL-309 (recette) : à 360-390 px, la nav seule porte déjà flex:1 —
     le séparateur ne sert qu'à pousser le menu sur bureau (plusieurs onglets
     d'administration avant), il ne vaut plus la place de ses deux gouttières
     ici. Sans lui, les quatre onglets et « ⋯ » tiennent en entier à 360 px
     (mesuré : nav.scrollWidth <= nav.clientWidth). */
  .top .spacer { display: none; }
  .nav { flex: 1 1 auto; min-width: 0; overflow-x: auto; flex-wrap: nowrap; padding-bottom: 0; gap: 1px; }
  .nav .tab { flex: none; padding: 6px 6px; font-size: 11px; }
  /* Le sigle et le menu cèdent un peu de place aux onglets, jamais au point
     de disparaître (« ne rien masquer »). */
  .top .wordmark { font-size: 13px; letter-spacing: 1.5px; }
  .menu-btn { width: 33px; height: 33px; font-size: 16px; }
  .view { padding: 16px 14px 28px; }
  #view-reseau.on { padding: 0 14px 16px; }
  .ov-scene { height: max(300px, 48dvh); }
  /* SENTINEL-315 (recette) : la barre d'outils du graphe (position absolue,
     ancrée seulement à droite) débordait par la gauche à 390 px — le
     sélecteur « Rendu » n'y montrait plus que son chevron. Bornée aussi à
     gauche et autorisée à passer à la ligne : rien ne sort plus du panneau,
     les boutons qui ne tiennent pas descendent sur une deuxième rangée. */
  .graph-tools { left: 10px; flex-wrap: wrap; justify-content: flex-end; }
  select.gtool { max-width: 122px; }
  .conv-grid { grid-template-columns: 1fr; }
  .threads-layout.detail .thread-side { display: none; }
  .threads-layout:not(.detail) .thread-main { display: none; }
  .thread-back { display: block; }
  .machines-grid { display: grid; grid-template-columns: 1fr; }
  /* La table devient une liste : chaque session tient sur deux lignes */
  .presence thead { display: none; }
  .presence, .presence tbody { display: block; }
  .presence tr { display: block; padding: 10px 2px; border-bottom: 1px solid var(--line); }
  .presence td { display: block; border: none; padding: 0 0 0 16px; }
  .presence td.st-td { padding-left: 0; margin-bottom: 4px; }
  .presence td.st-td .st { font-size: 11.5px; }
  .presence .sess b { font-size: 14px; }
  .presence td.qui { font-size: 12px; }
  .presence td.life { padding: 2px 0 0; font-size: 11.5px; text-align: left; }
  .warn-banner { font-size: 12.5px; }
  /* le fil vivant : sujet et participants d'un cote, l'age et le detail
     descendent en ligne dessous — jamais de page qui derive. */
  .conv { flex-wrap: wrap; }
  .conv-side { margin-left: 0; padding-left: 10px; flex-direction: row; flex-basis: 100%;
               align-items: baseline; gap: 8px; text-align: left; }
  .conv-side .nfo { white-space: normal; }
  .dyad .age { margin-left: 0; flex-basis: 100%; }
}

/* ===== Pour toi (SENTINEL-180, refonte SENTINEL-189) =====
   Pleine largeur. Avec des questions : elles prennent les trois quarts, les
   fils la colonne de droite (collee a l'ecran). Sans question : les fils
   prennent toute la place, en grille. Bureau d'abord (le mobile attend
   SENTINEL-188). */
#view-pourtoi { padding-top: 26px; }
.pt-layout { display: grid; grid-template-columns: minmax(0, 3fr) minmax(320px, 1fr);
  gap: 32px; align-items: start; }
.pt-layout.calme { grid-template-columns: minmax(0, 1fr); }
.pt-layout.calme .pt-side { display: none; }
.pt-side { position: sticky; top: 16px; max-height: calc(100dvh - 110px);
  overflow-y: auto; padding-right: 4px; }
.pt-side .section-title:first-child { margin-top: 10px; }

.pt-hero { display: flex; align-items: baseline; gap: 16px; margin: 0 2px 18px; }
.pt-h1 { font-size: 22px; font-weight: 600; letter-spacing: -.01em; }
.pt-fresh { font-family: var(--mono); font-size: 12px; color: var(--faint); }
.pt-fresh.err { color: var(--bad); }
.pt-calme { color: var(--muted); margin: -8px 2px 22px; font-size: 14.5px; }

/* Un groupe = un fil qui attend l'utilisateur. */
.pt-groupe { padding: 12px 14px 12px; margin-bottom: 16px; border-radius: 12px; }
.pt-thead { display: flex; align-items: baseline; gap: 12px; width: 100%;
  text-align: left; cursor: pointer; }
.pt-tsubj { font-size: 14.5px; font-weight: 600; color: var(--text); min-width: 0; overflow-wrap: anywhere; }
.pt-tn { flex: none; font-family: var(--mono); font-size: 11px; color: #0e1116; background: var(--warn);
  border-radius: 9px; padding: 0 7px; line-height: 18px; }
.pt-open { margin-left: auto; flex: none; font-size: 12.5px; color: var(--faint); }
.pt-thead:hover .pt-open, .pt-thead:hover .pt-tsubj { color: var(--accent); }
.pt-goal { font-size: 13.5px; color: var(--muted); margin-top: 4px; line-height: 1.45; }
.pt-goal .k { font-family: var(--mono); font-size: 10.5px; letter-spacing: 1.5px;
  text-transform: uppercase; color: var(--faint); margin-right: 8px; }
.pt-goal.none { color: var(--faint); font-style: italic; }
.pt-gact { align-items: center; margin-top: 14px; }

/* Une question. */
/* Chaque question dans sa carte : on voit ou l'une finit et l'autre commence. */
.pt-q { background: var(--bg); border: 1px solid var(--line); border-radius: 10px;
  padding: 14px 16px; margin-top: 8px; }
.pt-q.envoi { opacity: .55; pointer-events: none; }
/* Le texte de la question, rendu comme les messages (SENTINEL-217) : le moteur
   209 y produit titres, listes, pre, code en ligne, gras et tableaux — le
   reset global les laissait nus (puces sans retrait, titres sans air), et la
   graisse 600 du conteneur noyait le **gras** : la police ne porte que 400 et
   700, tout rendait Bold. Les styles reprennent msg-body, en compact : la
   carte est plus étroite que le fil, et reste une carte — le tableau déroule
   seul dans .table-wrap, jamais la page. */
.pt-qtext { font-size: 14.5px; line-height: 1.55; color: #f2f5fb; overflow-wrap: anywhere; }
.pt-qtext p { margin: 0 0 8px; } .pt-qtext p:last-child { margin-bottom: 0; }
.pt-qtext a { color: var(--accent); }
.pt-qtext code { font-family: var(--mono); font-size: .85em; color: var(--accent);
  background: var(--panel-2); padding: 1px 5px; border-radius: 4px; }
.pt-qtext pre { background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 6px; padding: 8px 10px; overflow-x: auto; margin: 8px 0; }
.pt-qtext pre:last-child { margin-bottom: 0; }
.pt-qtext pre code { background: none; padding: 0; color: var(--text); font-size: 12.5px; }
.pt-qtext strong { color: #fff; font-weight: 600; }
.pt-qtext h1, .pt-qtext h2, .pt-qtext h3 { font-weight: 600; line-height: 1.35;
  color: var(--text); margin: 10px 0 4px; overflow-wrap: anywhere; }
.pt-qtext h1 { font-size: 16px; }
.pt-qtext h2 { font-size: 15.5px; }
.pt-qtext h3 { font-size: 14.5px; color: var(--muted); }
.pt-qtext h1:first-child, .pt-qtext h2:first-child, .pt-qtext h3:first-child { margin-top: 0; }
.pt-qtext ul, .pt-qtext ol { margin: 0 0 8px; padding-left: 20px; }
.pt-qtext ul { list-style: disc; }
.pt-qtext ul ul { list-style: circle; }
.pt-qtext li { margin: 2px 0; }
.pt-qtext li > ul, .pt-qtext li > ol { margin: 2px 0 4px; }
.pt-qtext ul:last-child, .pt-qtext ol:last-child { margin-bottom: 0; }
.pt-qtext .table-wrap { overflow-x: auto; margin: 8px 0; }
.pt-qtext .table-wrap:last-child { margin-bottom: 0; }
.pt-qtext table { border-collapse: collapse; }
.pt-qtext th, .pt-qtext td { border: 1px solid var(--line); background: var(--panel-2);
  padding: 3px 8px; text-align: left; vertical-align: top; white-space: nowrap; }
.pt-qtext th { font-family: var(--mono); font-size: 11px; font-weight: 600; color: var(--muted); }
.pt-qtext th.ta-r, .pt-qtext td.ta-r { text-align: right; }
.pt-qtext th.ta-c, .pt-qtext td.ta-c { text-align: center; }
.pt-qhead { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; margin-top: 2px; }
.pt-qmeta { font-size: 12.5px; color: var(--faint); font-family: var(--mono); }
.pt-late { color: var(--bad); background: none; border: 1px solid rgba(239,107,107,.45); }
.pt-fill { flex: 1; }
.pt-qopts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.pt-opt { display: flex; align-items: center; gap: 8px; padding: 4px 10px 4px 5px; max-width: 100%;
  border: 1px solid var(--line); border-radius: 10px; background: var(--panel-2);
  cursor: pointer; transition: border-color .12s, background .12s; }
.pt-opt:hover { border-color: rgba(125,140,248,.55); }
.pt-opt input { position: absolute; opacity: 0; pointer-events: none; }
.pt-lettre { flex: none; width: 20px; height: 20px; border-radius: 5px; display: grid;
  place-items: center; font-family: var(--mono); font-size: 13px; font-weight: 600;
  border: 1px solid var(--line); color: var(--muted); background: var(--bg); }
.pt-opt-t { font-size: 13.5px; line-height: 1.35; overflow-wrap: anywhere; }
.pt-opt.reco { border-color: rgba(125,140,248,.45); }
.pt-reco { flex: none; align-self: center; font-family: var(--mono);
  font-size: 10.5px; color: var(--accent); letter-spacing: .04em; }
.pt-opt:has(input:checked) { border-color: var(--accent); background: rgba(125,140,248,.16); }
.pt-opt:has(input:checked) .pt-lettre { background: var(--accent); border-color: var(--accent); color: #0e1116; }
.pt-opt:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.pt-text { display: block; width: 100%; min-height: 38px; margin-top: 8px;
  background: var(--bg); border: 1px solid var(--line); border-radius: 10px;
  color: var(--text); font: inherit; font-size: 14.5px; padding: 10px 12px; resize: vertical; }
.pt-text:focus { outline: none; border-color: var(--accent); }
.pt-qact { display: flex; align-items: center; gap: 10px; margin-top: 8px; }
.pt-qact .btn.primary { min-width: 104px; min-height: 36px; }
.pt-clore { font-size: 12.5px; color: var(--faint); padding: 4px 2px; }
.pt-clore:hover { color: var(--bad); }
.pt-qstat:empty { display: none; }
.pt-parti { color: var(--live); font-size: 13.5px; padding: 8px 12px; margin-top: 8px;
  border: 1px dashed rgba(65,217,141,.35); border-radius: 10px; }

/* Les fils de l'utilisateur : grille sans question, colonne a droite sinon. */
.pt-fils { display: grid; grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); gap: 14px; }
.pt-side .pt-fils { grid-template-columns: 1fr; gap: 10px; }
.pt-fil { margin: 0; padding: 16px 18px; display: flex; flex-direction: column; gap: 8px;
  border-radius: 12px; cursor: pointer; transition: border-color .12s; }
/* Toute la carte ouvre le fil (SENTINEL-226) : liseré discret au survol,
   même famille que les options de réponse ; le champ garde son curseur de
   texte, et le focus clavier porte l'accent des autres contrôles. */
.pt-fil:hover { border-color: rgba(125,140,248,.45); }
.pt-fil:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.pt-fil .pt-text { cursor: text; }
.pt-fsub { display: flex; align-items: baseline; gap: 10px; width: 100%; text-align: left; cursor: pointer; }
.pt-fsubj { font-size: 15.5px; font-weight: 600; line-height: 1.35; min-width: 0; overflow-wrap: anywhere; }
.pt-fsub:hover .pt-fsubj { color: var(--accent); }
.pt-fage { margin-left: auto; flex: none; font-family: var(--mono); font-size: 11.5px; color: var(--faint); }
.pt-x { border-left: 2px solid var(--line); padding: 2px 0 2px 10px; }
.pt-xh { font-family: var(--mono); font-size: 11.5px; color: var(--faint); }
.pt-xt { font-size: 13.5px; color: var(--muted); margin-top: 2px; line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
/* La rangée porte l'ancre du menu des presets (SENTINEL-231). */
.pt-fact { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 4px;
  position: relative; }
.pt-write .actions { margin-top: 8px; }
/* « Pour : » (SENTINEL-233) : à qui le message s'adresse — un select natif
   (l'utilisateur dicte : pas d'arobase à taper), discret, poussé à droite de la
   rangée d'actions ; il peut passer seul à la ligne sur petit écran. */
.pt-pour { display: inline-flex; align-items: center; gap: 6px; margin-left: auto;
  min-height: 34px; cursor: pointer; }
.pt-pour > span { font-family: var(--mono); font-size: 11px; letter-spacing: .03em;
  color: var(--faint); }
.pt-pour-sel { font: inherit; font-size: 12.5px; color: var(--muted);
  background: var(--bg); border: 1px solid var(--line); border-radius: 8px;
  padding: 4px 6px; min-height: 30px; max-width: 150px; }
.pt-pour-sel:focus { outline: none; border-color: var(--accent); }
/* SENTINEL-260 : le même « Pour : » dans le composer du fil et la remarque
   d'un document — la rangée passe à la ligne sur petit écran, le select y a
   un peu plus de place (le nom de session, puis dépôt-outil@poste). */
.cmp-act { flex-wrap: wrap; }
.cmp-act .pt-pour { margin-left: 0; }
.cmp-act .pt-pour-sel { max-width: 240px; }
/* Les presets (SENTINEL-231) : « + » ouvre un menu discret ancre sous la
   rangée d’actions — des titres seuls, le contenu part au clic ; « Gérer… »
   deploie sous la carte le panneau de creation/edition, meme pose sobre que
   la zone d’ecriture. */
.pt-plus { min-width: 36px; padding: 0 10px; font-weight: 600; }
.pt-pmenu { position: absolute; right: 0; top: calc(100% + 6px); z-index: 30;
  min-width: 230px; max-width: min(320px, 100%);
  background: var(--panel); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, .4); padding: 4px; }
.pt-pitem { display: block; width: 100%; text-align: left; background: none;
  border: none; border-radius: 7px; padding: 8px 10px; color: var(--text);
  font: inherit; font-size: 13.5px; line-height: 1.35; cursor: pointer;
  overflow-wrap: anywhere; }
.pt-pitem:hover { background: rgba(125, 140, 248, .14); }
.pt-pitem.pt-gerer { margin-top: 2px; color: var(--muted); font-size: 12.5px;
  border-top: 1px solid var(--line); border-radius: 0 0 7px 7px; }
.pt-pitem.pt-gerer:hover { background: rgba(125, 140, 248, .1); }
.pt-pitem.vide { color: var(--faint); }
.pt-pcharg { padding: 8px 10px; font-size: 12.5px; }
.pt-pmenu .error-line { margin: 2px 8px 6px; }
.pt-gestion { display: flex; flex-direction: column; gap: 8px; margin-top: 4px;
  border-top: 1px dashed var(--line); padding-top: 10px; cursor: default; }
.pt-ghead { display: flex; align-items: center; gap: 8px; }
.pt-gtitre { font-family: var(--mono); font-size: 11px; letter-spacing: .03em;
  text-transform: uppercase; color: var(--muted); }
.pt-gclose { min-height: 30px; padding: 0 10px; font-size: 11px; }
.pt-pliste { display: flex; flex-direction: column; gap: 4px; }
.pt-pliste .confirm { margin-top: 2px; }
.pt-prow { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.pt-prow-t { flex: 1; min-width: 0; font-size: 13.5px; overflow-wrap: anywhere; }
.pt-prow .chip { min-height: 30px; padding: 0 10px; font-size: 11px; }
.pt-champ { display: block; width: 100%; background: var(--bg);
  border: 1px solid var(--line); border-radius: 10px; color: var(--text);
  font: inherit; font-size: 14px; padding: 8px 12px; }
.pt-champ:focus { outline: none; border-color: var(--accent); }
textarea.pt-champ { resize: vertical; min-height: 56px; }
.pt-gact { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.pt-fil.etroit .pt-xt { -webkit-line-clamp: 2; }
.pt-fil [role="status"]:empty { display: none; }

/* La zone de saisie de l'utilisateur en tete d'un fil (SENTINEL-189). */
.composer { margin: 6px 0 22px; padding-bottom: 16px; border-bottom: 1px solid var(--line); }
/* SENTINEL-310 (03/10) : la saisie au-dessus des messages,
   collée en haut de la zone qui défile pendant qu'on lit le fil. */
.thread-col .composer {
  position: sticky; top: 0; z-index: 4; margin: 0 0 14px;
  background: var(--bg); border-bottom: 1px solid var(--line);
  padding: 10px 0 12px;
}
.cmp-text { display: block; width: 100%; min-height: 54px; resize: vertical;
  background: var(--panel); border: 1px solid var(--line); border-radius: 10px;
  color: var(--text); font: inherit; font-size: 14.5px; padding: 10px 12px; }
.cmp-text:focus { outline: none; border-color: var(--accent); }
.cmp-act { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
.cmp-hint { font-size: 12px; color: var(--faint); }
.cmp-stat:empty { display: none; }
/* Pieces jointes (SENTINEL-479) : celles qui attendent l'envoi, sous la zone
   de texte — vignette ou « PDF », nom, taille, retirer. La saisie entiere
   recoit un fichier glisse (`.depot`). */
.composer.depot .cmp-text { border-color: var(--accent); border-style: dashed; }
.cmp-pieces { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.cmp-piece { display: flex; align-items: center; gap: 8px; max-width: 100%;
  padding: 4px 4px 4px 4px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--panel); font-size: 13px; }
.cmp-piece-img { width: 40px; height: 40px; object-fit: cover; border-radius: 5px; }
.cmp-piece-ic, .piece-ic { display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: 5px; background: var(--panel-2);
  color: var(--muted); font: 600 11px var(--mono); }
.cmp-piece-nom { min-width: 0; max-width: 220px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; color: var(--text); }
.cmp-piece-t { color: var(--faint); font-size: 12px; white-space: nowrap; }
.cmp-piece-x { min-width: 32px; min-height: 32px; border: 0; border-radius: 6px; background: none;
  color: var(--faint); font-size: 18px; cursor: pointer; }
.cmp-piece-x:hover { color: var(--bad); background: var(--panel-2); }
/* La piece dans son message porteur : l'image en apercu (un clic l'agrandit),
   le PDF en carte ; la commande de l'agent reste lisible, en retrait. */
.piece { margin: 8px 0 4px; }
.piece-cadre { display: block; padding: 0; border: 1px solid var(--line); border-radius: 8px;
  background: var(--panel); cursor: zoom-in; max-width: 100%; overflow: hidden; }
.piece-img { display: block; max-width: min(100%, 420px); max-height: 320px; height: auto; }
.piece-cadre.grand { cursor: zoom-out; }
.piece-cadre.grand .piece-img { max-width: 100%; max-height: none; }
.piece-pied { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-top: 6px; }
.piece-lib { font-size: 12.5px; color: var(--muted); overflow-wrap: anywhere; }
.piece-pdf { display: flex; align-items: center; gap: 10px; padding: 8px 10px;
  border: 1px solid var(--line); border-radius: 8px; background: var(--panel); max-width: 460px; }
.piece-pdf .piece-pied { margin-top: 0; }
.piece-stat:empty { display: none; }
.msg-piece-cmd { font-size: 12.5px; color: var(--faint); }
/* Secret confie (SENTINEL-498) : le panneau sous la saisie (champ masque,
   note visible) et, dans le fil, le message masque avec l'etat de sa
   livraison. Jamais le secret. */
.cmp-secret { display: flex; flex-direction: column; gap: 8px; margin-top: 8px;
  padding: 10px 12px 12px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--panel); }
.cmp-secret-titre { font-size: 13.5px; color: var(--text); }
.cmp-secret-champ, .cmp-secret-note { width: 100%; min-height: 40px; background: var(--bg);
  border: 1px solid var(--line); border-radius: 8px; color: var(--text); font: inherit;
  font-size: 14.5px; padding: 8px 11px; }
.cmp-secret-champ { font-family: var(--mono); flex: 1; min-width: 0; }
.cmp-secret-champ.masque { -webkit-text-security: disc; }
.cmp-secret-ligne { display: flex; gap: 8px; align-items: stretch; }
.cmp-secret-cle { min-width: 40px; padding: 0 10px; color: var(--faint); }
.cmp-secret-cle.on { border-color: var(--accent); color: var(--accent); }
.ic-secret { vertical-align: -2px; flex: none; }
.cmp-secret-btn, .cmp-secret-titre { display: inline-flex; align-items: center; gap: 5px; }
.cmp-secret-titre { display: flex; }
.cmp-secret-champ:focus, .cmp-secret-note:focus { outline: none; border-color: var(--accent); }
.cmp-secret-aide { font-size: 12.5px; line-height: 1.4; }
.cmp-secret-act { display: flex; flex-wrap: wrap; gap: 8px; }
.cmp-secret-stat:empty { display: none; }
.cmp-secret-btn[aria-expanded="true"] { border-color: var(--accent); color: var(--accent); }
.msg-secret-conf .secret-titre { color: var(--text); }
.secret-etat { margin-top: 4px; font-size: 12.5px; color: var(--warn); }
.secret-etat.efface { color: var(--faint); }
/* Le geste « Fermer le fil » (SENTINEL-194) : un panneau replie sous la tete
   du fil, sobre comme le composer — la conclusion, une ligne, seule formalite.
   Le geste « Renommer » (SENTINEL-218) reprend le meme panneau ; sa puce reste
   neutre (l'accent au survol), la fermeture seule prend le rouge. */
.close-panel { margin: 6px 0 18px; padding: 12px 14px 14px; }
.close-text { display: block; width: 100%; min-height: 42px; margin-top: 8px;
  background: var(--bg); border: 1px solid var(--line); border-radius: 10px;
  color: var(--text); font: inherit; font-size: 14.5px; padding: 9px 12px; }
.close-text:focus { outline: none; border-color: var(--accent); }
.chip.fermer { color: var(--muted); }
.chip.fermer:hover { color: var(--bad); border-color: rgba(239,107,107,.45); }
.chip.renommer, .chip.poser { color: var(--muted); }
.chip.renommer:hover, .chip.poser:hover { color: var(--accent); border-color: rgba(125,140,248,.45); }
/* Le geste « Rouvrir » (SENTINEL-196) : meme puce neutre, le vert du frais
   au survol — rouvrir rend le fil actif a nouveau. */
.chip.rouvrir { color: var(--muted); }
.chip.rouvrir:hover { color: var(--live); border-color: rgba(65,217,141,.45); }
/* Le geste « Se joindre au fil » (SENTINEL-195) : puce neutre, pervenche au
   survol — entrer dans la conversation. Sa cousine discrete de la liste
   (fin de la ligne meta d'une carte) : meme teinte, meme poids que « à
   tous », un liseret au survol pour dire le clic ; « err » fige la puce
   quand le serveur a refuse. */
.chip.joindre { color: var(--muted); }
.chip.joindre:hover { color: var(--accent); border-color: rgba(125,140,248,.45); }
.thread-item .tjoin { flex: none; font-family: var(--mono); font-size: 11px;
  color: var(--accent); cursor: pointer; padding: 1px 7px; margin: -2px -3px;
  border: 1px solid transparent; border-radius: 10px; }
.thread-item .tjoin:hover { border-color: rgba(125,140,248,.45); background: rgba(125,140,248,.1); }
.thread-item .tjoin.err { color: var(--bad); cursor: not-allowed; }
/* Le dialogue du fil 1:1 (SENTINEL-205) : une carte sobre posee sur la
   scene, sous les commandes du coin haut droit — meme famille que les
   panneaux du fil (titre de section, saisie une ligne, actions). */
.one2one {
  position: absolute; top: 46px; right: 10px; z-index: 6; margin: 0;
  width: min(400px, calc(100% - 20px));
  background: rgba(21,26,35,.97); box-shadow: 0 8px 28px rgba(0,0,0,.45);
}
.one2one .close-text { margin-top: 6px; }
.pt-reply { display: flex; align-items: flex-end; gap: 10px; margin-top: 8px; }
.pt-reply .pt-text { margin-top: 0; flex: 1; }
.pt-reply .btn.primary { flex: none; min-width: 104px; min-height: 38px; }
/* Les questions ouvertes d'un fil, en tete de l'ecran Fils (SENTINEL-189). */
.thread-questions { margin: 4px 0 18px; }
.thread-questions .section-title { margin-top: 0; }
.msg-path { font-family: var(--mono); font-size: 12.5px; color: var(--muted); }
/* Machines (SENTINEL-189) : resume, depots actifs, inactifs replies. */
.mresume { display: flex; flex-wrap: wrap; gap: 4px 16px; font-size: 13px; color: var(--muted); margin: 6px 0 4px; }
.mresume b { color: var(--text); font-weight: 600; }
.mresume .on b { color: var(--live); }
.mcalmes, .mjeton { margin-top: 10px; border-top: 1px solid var(--line); padding-top: 8px; }
.mcalmes > summary, .mjeton > summary { cursor: pointer; font-size: 12.5px; color: var(--faint);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mcalmes > summary:hover, .mjeton > summary:hover { color: var(--text); }
.machines-grid { align-items: start; }
/* Enroler une machine depuis l'interface (SENTINEL-189). */
.enr-guide > summary { cursor: pointer; font-weight: 600; font-size: 14.5px; }
.enr-steps { margin: 10px 0 2px 20px; font-size: 14px; color: var(--muted); display: flex; flex-direction: column; gap: 8px; }
/* Installer une machine (SENTINEL-283) : un code a usage unique et deux
   lignes a coller. Les lignes se replient au lieu de defiler : sur le
   telephone, on voit la commande entiere avant de la copier. */
.inst-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.inst-intro { font-size: 13px; }
.inst-titre { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.inst-nom { font-weight: 600; font-size: 14.5px; }
.inst-reste { font-family: var(--mono); font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.inst-code { margin-top: 6px; }
.inst-ligne { margin-top: 12px; }
.inst-os { font-family: var(--mono); font-size: 11px; color: var(--faint); margin-bottom: 4px; }
.inst-cmd { font-family: var(--mono); font-size: 12.5px; background: var(--bg); border: 1px solid var(--line);
  border-radius: 8px; padding: 10px 12px; margin: 0; color: var(--text);
  white-space: pre-wrap; overflow-wrap: anywhere; user-select: all; }
.inst-ligne .actions { margin-top: 6px; align-items: center; }
.inst-actions { border-top: 1px solid var(--line); padding-top: 10px; }
.inst-note { font-size: 12px; margin-top: 6px; }
/* Survol dans la scene (SENTINEL-189) : le voisinage garde ses noms, en
   avant ; le reste s'efface. */
.glabel.loin { opacity: .12; }
.glabel.voisin { color: var(--text); background: rgba(14,17,22,.88); border-color: rgba(139,156,247,.6); }
/* Message arrive pendant la lecture (SENTINEL-189). */
.msg.neuf { animation: neuf 1.6s ease-out; }
@keyframes neuf { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.bandeau-version { position: fixed; right: 18px; bottom: 18px; z-index: 50; display: flex; gap: 12px;
  align-items: center; background: var(--panel-2); border: 1px solid var(--accent); border-radius: 10px;
  padding: 10px 12px 10px 16px; font-size: 13.5px; box-shadow: 0 6px 24px rgba(0,0,0,.4); }
/* Agora redemarre (SENTINEL-478) : discret, en bas, sans masquer la page ni
   capter les clics ; il part seul a la reprise. */
.bandeau-reprise { position: fixed; bottom: 18px; left: 50%; max-width: calc(100vw - 32px); transform: translateX(-50%); z-index: 60;
  pointer-events: none; background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 999px; padding: 5px 14px; font-size: 12.5px; color: var(--muted); white-space: nowrap;
  box-shadow: 0 4px 16px rgba(0,0,0,.35); }
/* Nouveaux messages depuis la derniere lecture (SENTINEL-189). */
.nouveau { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--faint); align-self: center; }
.nouveau.fort { width: auto; height: auto; border-radius: 9px; background: var(--accent); color: #0e1116;
  font-family: var(--mono); font-size: 10.5px; font-weight: 600; padding: 0 7px; line-height: 17px; }

/* Les remarques déjà faites sur un document (et leurs réponses), sous la
   lecture, au-dessus du champ « Remarque » : les messages tels qu'au fil, sans
   la pastille « Sur le document » (on y est). */
.doc-remarques { margin-top: 26px; }
.doc-remarques .section-title { margin: 2px 0 10px; }
.doc-remarques .doc-ref { display: none; }
.doc-rem-vide { font-size: 13px; }
/* Un message trop long (plus de maxlength qui coupait sans prévenir). */
.cmp-trop { font-size: 12.5px; color: var(--bad); margin-top: 6px; }
.cmp-trop:empty { display: none; }

/* -- SENTINEL-207/265 : « occupée » (en plein tour), jauge de contexte, compactage -- */
.jauge { display: inline-flex; align-items: center; gap: 6px; font-family: var(--mono);
  font-size: 12px; color: var(--muted); white-space: nowrap; }
.jauge .jg-barre { position: relative; display: inline-block; width: 72px; height: 6px;
  border-radius: 3px; background: var(--line); overflow: hidden; }
.jauge .jg-plein { position: absolute; left: 0; top: 0; bottom: 0; background: var(--live); }
.jauge.moyen .jg-plein { background: var(--warn); }
.jauge.haut .jg-plein { background: var(--bad); }
.jauge.moyen .jg-txt { color: var(--warn); }
.jauge.haut .jg-txt { color: var(--bad); }
.jauge.inconnue .jg-txt { color: var(--faint); }
.jauge.courte { gap: 4px; font-size: 10.5px; }
.jauge.courte .jg-barre { width: 34px; height: 4px; }
/* SENTINEL-279/327 : mesure périmée — chiffre grisé, barre hachurée ; l'âge (jg-age) s'affiche désormais toujours. */
.jauge.perimee .jg-plein { background: repeating-linear-gradient(135deg, var(--faint) 0 3px, transparent 3px 6px); }
.jauge.perimee .jg-txt { color: var(--faint); }
.jauge .jg-age { color: var(--faint); font-size: .9em; }
.tag.tour { color: var(--accent); }
.pt-compactages { margin: 6px 0 18px; }
.pt-compact { border-left: 3px solid var(--warn); }
.pt-compact-tete { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  flex-wrap: wrap; }
.pt-compact-nom { font-weight: 600; overflow-wrap: anywhere; }
.pt-compact-ligne { margin: 8px 0 6px; }
.pt-compact-gestes { display: flex; align-items: center; gap: 14px; margin-top: 10px; }
.pt-ctx-compacter { font-size: 12.5px; }
.pt-ctx-stat { flex-basis: 100%; }
.pt-ctx-stat:empty { display: none; }

/* SENTINEL-268 : l'etiquette d'une session dans la scene — pastille d'etat
   (meme code que .lm), nom, « pause », pourcentage de contexte. */
.glabel .gl-st { display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  border: 1.5px solid var(--faint); margin-right: 5px; vertical-align: 0; }
.glabel .gl-st.ecoute { background: var(--live); border-color: var(--live); }
.glabel .gl-st.occupee { background: var(--accent); border-color: var(--accent); }
.glabel .gl-st.pause { border-color: var(--warn); }
.glabel .gl-et { margin-left: 5px; color: var(--warn); }
.glabel .gl-jg { margin-left: 6px; padding: 0 4px; border-radius: 3px;
  background: rgba(125,140,248,.16); color: var(--text); }
.glabel .gl-jg.moyen { color: var(--warn); }
.glabel .gl-jg.haut { color: var(--bad); }
.glabel .gl-jg.perimee { color: var(--faint); }   /* SENTINEL-279 */
.gtip .tt-jauge { margin-top: 5px; }
.gtip .tt-warn { margin-top: 5px; font-size: 12px; color: var(--warn); }

/* SENTINEL-254 : lancer une session depuis le fil. */
.lc-brief { resize: vertical; min-height: 64px; }

/* SENTINEL-242/251 : la vue « Postes » (annuaire, outils, sessions, comptes et quotas). */
.comptes-carte { margin-bottom: 14px; }
.compte { padding: 8px 0; border-top: 1px solid var(--line); }
.compte:first-of-type { border-top: none; }
.compte.court { padding: 6px 0; }
.compte-tete { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 8px; }
.compte-nom { font-weight: 600; }
.compte-age { margin-left: auto; font-family: var(--mono); font-size: 11px; color: var(--faint); }
.tag.nonoff { color: var(--warn); border-color: rgba(240,180,41,.4); }
.quotas { display: grid; gap: 4px; margin-top: 6px; }
.quota { display: grid; grid-template-columns: 92px auto 1fr auto; align-items: center; gap: 10px; font-size: 12.5px; }
.quota .q-fen { color: var(--muted); font-family: var(--mono); font-size: 11.5px; }
.quota .jauge .jg-barre { width: 120px; }
.quota .q-remise { color: var(--faint); font-family: var(--mono); font-size: 11px; }
/* SENTINEL-281 : la machine qui a mesure la fenetre (la plus fraiche gagne). */
.quota .q-src { color: var(--faint); font-family: var(--mono); font-size: 11px; text-align: right; white-space: nowrap; }
.quota .q-montant { font-family: var(--mono); }
.warn-line { color: var(--warn); }
.poste-sessions { border-top: 1px solid var(--line); margin-top: 6px; }
.poste-sess { padding: 7px 0; border-top: 1px dashed var(--line); }
.poste-sess:first-child { border-top: none; }
.ps-tete { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.ps-nom { font-family: var(--mono); font-size: 13px; }
.ps-nom.role { color: var(--text); font-family: var(--sans); font-weight: 600; }
.ps-caps summary { cursor: pointer; font-size: 11.5px; color: var(--faint); margin-top: 2px; }
.caps-liste { list-style: none; margin: 4px 0 0; padding: 0; font-size: 12px; display: grid; gap: 2px; }
.caps-liste .cap.oui::before { content: "✓ "; color: var(--live); }
.caps-liste .cap.non::before { content: "× "; color: var(--faint); }
@media (max-width: 640px) {
  .quota { grid-template-columns: 80px auto; row-gap: 2px; }
  .quota .q-remise, .quota .q-src { grid-column: 1 / -1; text-align: left; }
  .quota + .quota { margin-top: 6px; }
  .quota .jauge .jg-barre { width: 90px; }
}
.compte-resume { font-size: 12.5px; color: var(--muted); }
.compte-resume b { color: var(--text); font-weight: 600; }

/* SENTINEL-281 (lot 2) : l'inventaire d'un poste — outils, racines, comptes —
   chacun avec son etat (le choix du propriétaire) et ses gestes « Confirmer » /
   « Exclure ». Une ligne : ce que c'est, l'etat, les gestes ; elle passe a
   la ligne sur telephone (les gestes dessous, a 44 px au doigt). */
.inventaire { border-top: 1px solid var(--line); margin-top: 6px; padding-top: 4px; }
.inv-groupe + .inv-groupe { margin-top: 6px; }
.inv-titre { font-family: var(--mono); font-size: 11px; color: var(--faint); margin: 4px 0 2px; }
.inv-ligne { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; padding: 4px 0;
  font-size: 12.5px; color: var(--muted); border-top: 1px dashed var(--line); }
.inv-groupe .inv-ligne:first-of-type { border-top: none; }
.inv-ligne b { color: var(--text); font-weight: 600; }
.inv-quoi { flex: 1 1 200px; min-width: 0; overflow-wrap: anywhere; }
.inv-chemin { font-size: 12px; color: var(--text); }
.inv-gestes { display: flex; gap: 6px; margin-left: auto; }
.inv-gestes .btn.small { min-height: 28px; padding: 0 10px; font-size: 12px; }
.inv-ligne.a-confirmer { box-shadow: inset 2px 0 0 var(--warn); padding-left: 8px; }
.inv-ligne.exclu .inv-quoi { opacity: .6; }
.inv-msg { flex-basis: 100%; }
.inv-msg:empty { display: none; }
/* Rattacher un compte local a un autre (« meme compte que… »). */
.cpt-ratts { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; }
.cpt-ratt { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; }
.cpt-ratt .btn.small { min-height: 28px; padding: 0 10px; font-size: 12px; }
.cpt-sel { min-height: 30px; max-width: 100%; flex: 0 1 360px; background: var(--bg); color: var(--text);
  border: 1px solid var(--line); border-radius: 8px; padding: 0 8px; font-size: 12.5px; font-family: var(--sans); }
@media (max-width: 640px) {
  .inv-gestes .btn.small { min-width: 104px; }
  .cpt-sel { flex: 1 1 100%; }
}
@media (pointer: coarse) {
  .inv-gestes .btn.small, .cpt-ratt .btn.small, .cpt-sel { min-height: 44px; }
}

/* SENTINEL-258 : relancer les sessions muettes (Sessions depuis SENTINEL-476). Le bouton
   se range a droite du titre ; le panneau liste les fils avant l'envoi. */
.pt-hero { flex-wrap: wrap; }
.pt-muettes-b { margin-left: auto; align-self: center; }
.pt-muettes { margin: -6px 2px 18px; }
.pt-muettes[hidden] { display: none; }
.pt-muettes.confirm { padding-top: 12px; border-top: 1px solid var(--line); }
.pt-mu-titre { margin: 0 0 8px; font-size: 14px; }
.pt-mu-liste { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.pt-mu-fil { border-left: 2px solid var(--line); padding: 2px 0 2px 10px; }
.pt-mu-fil.ok { border-left-color: var(--live); }
.pt-mu-fil.err { border-left-color: var(--bad); }
.pt-mu-tete { display: flex; gap: 10px; align-items: baseline; }
.pt-mu-sujet { color: var(--text); font-weight: 500; text-decoration: none; overflow-wrap: anywhere; }
.pt-mu-sujet:hover { color: var(--accent); }
.pt-mu-etat { margin-left: auto; font-family: var(--mono); font-size: 11.5px; color: var(--muted); white-space: nowrap; }
.pt-mu-fil.ok .pt-mu-etat { color: var(--live); }
.pt-mu-fil.err .pt-mu-etat { color: var(--bad); }
.pt-mu-sess { display: flex; flex-direction: column; gap: 2px; margin-top: 2px; }
.pt-mu-s { font-size: 12.5px; color: var(--muted); overflow-wrap: anywhere; }
.pt-mu-note { font-size: 12px; margin-top: 10px; }
.pt-mu-act { justify-content: flex-end; margin-top: 10px; }

/* SENTINEL-258 (ajout) : « Nouveau fil » dans la vue Fils. */
.nf-row { margin: 0 2px 10px; }
.nf-bouton { width: 100%; }
.nf-form { display: flex; flex-direction: column; gap: 10px; margin: 0 0 12px; }
.nf-form[hidden] { display: none; }
.nf-form.confirm { padding-top: 12px; border-top: 1px solid var(--line); }
.nf-form .section-title { margin: 0; }
.nf-l { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--faint); font-family: var(--mono); }
.nf-in { min-height: 38px; background: var(--bg); color: var(--text); border: 1px solid var(--line);
  border-radius: 8px; padding: 0 10px; font-size: 14px; font-family: var(--sans); }
.nf-in:focus { outline: none; border-color: var(--accent); }
.nf-act { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.nf-hint { flex-basis: 100%; }
/* Fil 79 : le champ du renommage d'une session (participants.js). */
.nf-role { flex: 1 1 120px; font-family: var(--sans); }

/* SENTINEL-371 : choisir des participants — le composant commun de
   « Nouveau fil » et « ajouter… » (choix-participants.js). Une ligne par
   choix : son état (existante / à lancer), son nom, sa machine et son outil,
   la croix ; dessous, le rôle (poste) ou le détail d'une nouvelle session.
   Au téléphone, la tête de ligne passe à la ligne au lieu de déborder. */
.cp { display: flex; flex-direction: column; gap: 8px; font-family: var(--sans); font-size: 13px;
  color: var(--text); }
.cp-lignes { display: flex; flex-direction: column; gap: 8px; }
.cp-lignes:empty { display: none; }
.cp-ligne { position: relative; display: flex; flex-direction: column; gap: 6px; padding: 8px 10px;
  border: 1px solid var(--line); border-radius: 10px; background: var(--panel-2); min-width: 0; }
/* La croix reste en haut à droite, quelle que soit la largeur : la tête
   lui garde sa place au lieu de la faire passer seule à la ligne. */
.cp-tete { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; min-width: 0;
  padding-right: 26px; }
.cp-etat { flex: 0 0 auto; font-family: var(--mono); font-size: 11.5px; color: var(--accent);
  border: 1px solid rgba(125,140,248,.45); border-radius: 999px; padding: 1px 8px; }
.cp-etat.existante { color: var(--muted); border-color: var(--line); }
.cp-nom { font-weight: 600; overflow-wrap: anywhere; min-width: 0; }
.cp-meta { flex: 1 1 auto; font-family: var(--mono); font-size: 12px; color: var(--faint);
  overflow-wrap: anywhere; min-width: 0; }
.cp-x { display: inline-flex; align-items: center; justify-content: center; position: absolute;
  top: 6px; right: 6px; min-width: 24px; min-height: 24px; font-size: 16px; padding: 0; }
.cp-detail { display: flex; flex-direction: column; gap: 6px; padding-left: 10px;
  border-left: 2px solid rgba(125,140,248,.45); }
.cp-role { font-family: var(--sans); }
.cp-erreur[hidden] { display: none; }
.nf-form .cp .ppl-ajout-sel { font-size: 14px; }

/* SENTINEL-270 : sélecteurs en cascade (machine → outil → session ou dépôt)
   et navigateur de dossiers d'une nouvelle session (SENTINEL-371). */
.cs-cascade { display: flex; flex-wrap: wrap; gap: 8px; }
.cs-cascade > select { flex: 1 1 130px; width: auto; min-width: 0; }
.cs-cascade > select.cs-final { flex: 3 1 220px; }
/* SENTINEL-286 : agents non sélectionnables (ni session ni outil lançable). */
.cs-cascade > .cs-indispo { flex: 1 1 100%; color: var(--faint); font-size: 12.5px; line-height: 1.4;
  white-space: pre-line; overflow-wrap: anywhere; }
.cs-cascade > .cs-indispo[hidden] { display: none; }
.cs-cascade option:disabled { color: var(--faint); }
.lc-nav { display: flex; flex-direction: column; gap: 6px; padding: 8px; border: 1px solid var(--line);
  border-radius: 8px; background: var(--bg); }
.lc-nav[hidden] { display: none; }
.lc-nav-tete { display: flex; align-items: center; gap: 8px; min-width: 0; }
.lc-nav-chemin { font-family: var(--mono); font-size: 12px; color: var(--muted); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; flex: 1; min-width: 0; }
.lc-nav-liste { display: flex; flex-direction: column; max-height: 240px; overflow-y: auto; }
.lc-nav-entree { display: flex; align-items: center; gap: 8px; text-align: left; font: inherit;
  font-size: 13px; color: var(--text); background: none; border: 0; border-radius: 6px;
  padding: 7px 8px; min-height: 36px; cursor: pointer; }
.lc-nav-entree:hover, .lc-nav-entree:focus-visible { background: rgba(125,140,248,.12); outline: none; }
.lc-nav-nom { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lc-nav-badge { font-size: 11px; color: var(--muted); border: 1px solid var(--line); border-radius: 999px;
  padding: 0 6px; }
.lc-nav-badge.warn { color: var(--warn); border-color: var(--warn); }
.lc-nav-vide { font-size: 12.5px; color: var(--faint); padding: 6px 8px; }
@media (max-width: 640px) {
  .cs-cascade > select, .cs-cascade > select.cs-final { flex: 1 1 100%; }
}

/* ===== SENTINEL-275 : correctifs d'audit (SENTINEL-273), telephone d'abord ===== */
/* Saut vers les participants (et « ajouter… », « lancer… ») : comme celui des
   documents, inutile quand le rail est a droite. */
@media (min-width: 1450px) { .rail-saut { display: none; } }
/* L'en-tete d'un fil garde au titre ~340 px : les gestes (jusqu'a six)
   passent a la ligne a droite plutot que de l'ecraser. */
.thread-head > :first-child { flex: 1 0 min(340px, 50%); min-width: 0; }
.thread-act { flex: 0 1 auto; flex-wrap: wrap; justify-content: flex-end; }
@media (max-width: 899px) {
  /* « Pour toi » : une colonne — les questions, puis les fils. La grille
     3fr / 320 px laissait ~10 px aux questions (page de 85 000 px). */
  .pt-layout { grid-template-columns: minmax(0, 1fr); gap: 20px; }
  .pt-side { position: static; max-height: none; overflow: visible; padding-right: 0; }
  /* En-tete d'un fil : le titre garde toute la largeur, les gestes passent
     dessous et vont a la ligne (Renommer et Fermer etaient hors ecran). */
  .thread-head { flex-wrap: wrap; gap: 10px; }
  .thread-head > :first-child { flex: 1 1 100%; min-width: 0; }
  .thread-act { flex: 1 1 100%; flex-wrap: wrap; margin-left: 0; gap: 8px; padding-top: 0; }
  /* Machines et Postes : une carte ne depasse jamais l'ecran ; la tete de
     carte (nom, systeme, compteur) va a la ligne au lieu de se chevaucher. */
  .machines-grid { grid-template-columns: minmax(0, 1fr); }
  .mcard { min-width: 0; }
  .machine-head { flex-wrap: wrap; row-gap: 4px; }
  .machine-label { flex-wrap: wrap; }
  .machine-name { overflow-wrap: anywhere; }
}
/* Cibles tactiles : 44 px au doigt (« lancer… / ajouter… / retirer… /
   quitter », lignes depliables, options et cloture des questions, case
   « avec l'historique », retour aux fils). La souris garde la densite du bureau. */
@media (pointer: coarse) {
  .ppl-gerer, .ppl-quitter, .pt-clore { min-height: 44px; display: inline-flex; align-items: center; }
  .cp-x { min-width: 44px; min-height: 44px; top: 0; right: 0; }
  .cp-tete { padding-right: 40px; }
  .thread-back { min-height: 44px; padding-block: 12px; }
  .ppl-gestes { align-items: center; }
  /* list-item garde le triangle ; le padding centre une ligne dans 44 px. */
  details > summary { min-height: 44px; padding-block: 12px; box-sizing: border-box; line-height: 20px; }
  .ppl-histo { min-height: 44px; }
  .ppl-histo input { width: 20px; height: 20px; }
  .pt-opt { min-height: 44px; }
  .ppl-ajout-sel, .pt-pour-sel, .chip, .btn, .btn.small, .pt-qact .btn.primary,
  .pt-reply .btn.primary, .pt-gclose, .pt-prow .chip { min-height: 44px; }
}

/* == SENTINEL-276 : quatre etats d'une session, une couleur chacun, partout ==
   a l'ecoute (vert), occupee (pervenche), en pause (ambre), injoignable
   (gris). `.etat` : point et libelle ; `.lm` : le point seul (listes,
   pastilles de participants, compteurs). Les memes classes que
   `etatSession()` dans js/noyau.js. */
.etat { display: inline-flex; align-items: center; gap: 7px; font-family: var(--mono); font-size: 12px;
  white-space: nowrap; color: var(--faint); }
.etat::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--faint); flex: none; }
.etat.ecoute { color: var(--live); } .etat.ecoute::before { background: var(--live); }
.etat.occupee { color: var(--accent); } .etat.occupee::before { background: var(--accent); }
.etat.pause { color: var(--warn); } .etat.pause::before { background: var(--warn); }
.lm.ecoute { background: var(--live); border-color: var(--live); }
.lm.occupee { background: var(--accent); border-color: var(--accent); }
.lm.pause { background: var(--warn); border-color: var(--warn); }
.lm.injoignable { background: var(--faint); border-color: var(--faint); }
.ppl .lm { width: 8px; height: 8px; }
.glabel .gl-st.injoignable { background: var(--faint); border-color: var(--faint); }
.glabel .gl-st.pause { background: var(--warn); }
.presence td.sess .sess-nom { font-weight: 600; }
.ps-presence { margin-top: 2px; }
.pt-mu-s .etat { margin-left: 6px; font-size: 11px; }

/* == SENTINEL-376 : les gestes d'une session, les memes partout ==============
   Un menu « ⋯ » par session (carte d'un fil, ecran Sessions, fiche Reseau),
   pose en position fixe sur le document ; une seule bande de confirmation
   qui dit l'effet reel par session, puis le resultat. */
.gs-plus { border: 1px solid transparent; background: none; color: var(--muted); cursor: pointer;
  border-radius: 6px; padding: 0 6px; min-width: 26px; min-height: 22px; font-size: 14px;
  line-height: 1; display: inline-flex; align-items: center; justify-content: center; }
.gs-plus:hover, .gs-plus[aria-expanded="true"] { color: var(--text); border-color: var(--line);
  background: rgba(125,140,248,.12); }
.ppl .gs-plus { margin-left: 2px; }
.gs-menu { position: fixed; z-index: 30; background: var(--panel); border: 1px solid var(--line);
  border-radius: 10px; box-shadow: 0 10px 30px rgba(0,0,0,.45); padding: 6px; max-height: 70vh;
  overflow-y: auto; }
.gs-menu-titre { font-family: var(--mono); font-size: 10.5px; letter-spacing: 1.5px;
  text-transform: uppercase; color: var(--faint); padding: 6px 8px 4px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.gs-item { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; width: 100%;
  text-align: left; background: none; border: 0; border-radius: 6px; padding: 7px 8px;
  cursor: pointer; color: var(--text); font: inherit; font-size: 13.5px; }
.gs-item:hover:not([disabled]), .gs-item:focus-visible { background: rgba(125,140,248,.12); outline: none; }
.gs-item.danger .gs-label { color: var(--bad); }
.gs-item[disabled] { cursor: default; }
.gs-item[disabled] .gs-label { color: var(--faint); }
.gs-aide { font-size: 11.5px; color: var(--muted); line-height: 1.35; }
.gs-aide.err { color: var(--bad); padding: 4px 8px; }
.gs-sep { height: 1px; background: var(--line); margin: 4px 6px; }
.gs-bande { margin-top: 10px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--panel-2); display: flex; flex-direction: column; gap: 8px; font-size: 13px; }
.gs-bande.danger { border-color: rgba(239,107,107,.45); }
.gs-bande-titre { line-height: 1.45; color: var(--text); }
.gs-bande-titre > span { color: var(--muted); }
.gs-lignes { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.gs-ligne { display: flex; flex-wrap: wrap; gap: 2px 10px; align-items: baseline; padding: 3px 0;
  border-top: 1px dashed var(--line); }
.gs-ligne:first-child { border-top: none; }
.gs-nom { font-weight: 600; min-width: 12ch; }
.gs-effet { color: var(--muted); flex: 1 1 260px; min-width: 0; }
.gs-effet.processus { color: var(--text); }
.gs-effet.agora_seul { color: var(--warn); }
.gs-effet.non, .gs-effet.refus { color: var(--bad); }
.gs-effet.ok { color: var(--live); }
.gs-bande-act { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.gs-statut { font-size: 12.5px; color: var(--muted); }
.gs-statut.err { color: var(--bad); }
.gs-statut.ok { color: var(--live); }
.gs-champ { width: 100%; font: inherit; font-size: 14px; color: var(--text); background: var(--bg);
  border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; }
.gs-champ:focus { outline: none; border-color: var(--accent); }

/* L'ecran « Sessions » (U2) : une table en grille, une carte par ligne sur
   telephone. SENTINEL-476 : pleine largeur ; colonnes Dépôt · modèle,
   Contexte, Activité, Fils ouverts (la colonne Machine seulement a plusieurs
   machines) ; la ligne grise (machine · outil · origine) toujours sous le nom. */
.ss-carte .section-title { margin-bottom: 6px; align-items: baseline; flex-wrap: wrap; }
.ss-tete-l { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin-bottom: 10px; }
.ss-resume-l { display: flex; flex-wrap: wrap; gap: 4px 16px; font-size: 13.5px; color: var(--muted); }
.ss-resume-l b { color: var(--text); font-weight: 600; }
.ss-resume-l .on b { color: var(--live); }
.ss-filtre { display: flex; flex-wrap: wrap; gap: 6px 12px; align-items: baseline; font-size: 12.5px;
  color: var(--muted); margin-bottom: 8px; }
.ss-barre { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px; margin-bottom: 10px; }
.ss-onglets { display: flex; flex-wrap: wrap; gap: 6px; }
.ss-onglets .chip, .ss-tri .chip { min-height: 34px; gap: 8px; }
.ss-tri { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-left: auto; }
.ss-tri-k { font-size: 12.5px; color: var(--faint); }
.ss-n { color: var(--faint); }
.ss-alerte { color: var(--warn); font-size: 12.5px; margin-bottom: 8px; }
.ss-ligne { display: grid; align-items: start; gap: 4px 12px; padding: 9px 6px;
  grid-template-columns: 22px 12px minmax(200px, 2.2fr) minmax(130px, 1fr) 230px 92px minmax(170px, 1.6fr) 34px;
  border-top: 1px solid var(--line); font-size: 13px; }
.ss-table.avec-machine .ss-ligne:not(.terminee) {
  grid-template-columns: 22px 12px minmax(200px, 2.2fr) 110px minmax(130px, 1fr) 230px 92px minmax(170px, 1.6fr) 34px; }
.ss-table.terminees .ss-ligne {
  grid-template-columns: 22px 12px minmax(200px, 2fr) minmax(150px, 1fr) 140px 100px 110px 34px; }
.ss-ligne > .ss-c-case, .ss-ligne > .ss-c-etat { padding-top: 3px; }
.ss-tete { font-family: var(--mono); font-size: 10.5px; letter-spacing: 1.5px; text-transform: uppercase;
  color: var(--faint); border-top: none; padding-bottom: 6px; }
.ss-groupe { padding: 14px 6px 6px; border-top: 1px solid var(--line); font-family: var(--mono);
  font-size: 10.5px; letter-spacing: 1.5px; text-transform: uppercase; color: var(--faint); }
.ss-ligne.sel { background: rgba(125,140,248,.08); }
.ss-ligne.terminee .ss-nom, .ss-ligne.injoignable .ss-nom { color: var(--muted); }
.ss-case { width: 16px; height: 16px; margin: 0; accent-color: var(--accent); }
.ss-c-nom { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ss-nom { font-weight: 600; overflow-wrap: anywhere; }
.ss-presence { font-size: 12.5px; color: var(--muted); overflow-wrap: anywhere; }
.ss-gris { font-size: 12px; color: var(--faint); overflow-wrap: anywhere; }
.ss-mobile { display: none; }
.ss-raison { font-size: 12px; color: var(--faint); line-height: 1.35; }
.ss-raison.ok { color: var(--accent); }
.ss-c-depot { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.ss-depot, .ss-c-machine, .ss-c-act { font-family: var(--mono); font-size: 12px; color: var(--muted);
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ss-c-ctx { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; min-width: 0; }
.ss-c-ctx .jauge .jg-barre { width: 64px; }
.ss-c-fils { display: flex; flex-direction: column; gap: 2px; min-width: 0; font-size: 12.5px; }
.ss-c-fils .tag { width: fit-content; }
.ss-fil { color: var(--accent); text-decoration: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ss-fil:hover { text-decoration: underline; }
.ss-c-orig { font-size: 12.5px; color: var(--muted); }
.ss-ligne.terminee .ss-c-fils { font-family: var(--mono); font-size: 12px; color: var(--muted); }
.tag.hors { color: var(--muted); border: 1px solid var(--line); background: none; }
.tag.tour { color: var(--accent); border-color: rgba(125,140,248,.5); }
.ss-c-menu { display: flex; justify-content: flex-end; }
.ss-selbar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin-top: 10px;
  padding: 10px 12px; border: 1px solid var(--accent); border-radius: 10px; background: rgba(125,140,248,.06); }
.ss-resume { color: var(--muted); font-size: 12.5px; }
.ss-carte .pt-muettes { margin-bottom: 10px; }
@media (max-width: 640px) {
  .ss-tete { display: none; }
  .ss-ligne, .ss-table.terminees .ss-ligne,
  .ss-table.avec-machine .ss-ligne:not(.terminee) { grid-template-columns: 22px 12px minmax(0, 1fr) 44px; }
  .ss-c-depot, .ss-c-machine, .ss-c-ctx, .ss-c-orig, .ss-c-act, .ss-c-fils { display: none; }
  .ss-mobile { display: flex; flex-direction: column; gap: 3px; margin-top: 2px; }
  .ss-mobile .tag { width: fit-content; max-width: 100%; white-space: normal; }
  .ss-m-ctx { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
  .ss-m-meta { font-family: var(--mono); font-size: 11.5px; color: var(--muted); overflow-wrap: anywhere; }
  .ss-m-fils { font-size: 12.5px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .ss-tri { margin-left: 0; }
  .ss-selbar .pt-fill { display: none; }
  .ss-selbar .ss-resume { flex: 1 1 100%; }
  .gs-bande-act .pt-fill { flex-basis: 100%; height: 0; }
  .gs-bande-act .gs-statut { flex: 1 1 100%; }
}
@media (pointer: coarse) {
  .gs-plus { min-width: 44px; min-height: 44px; }
  .gs-item { min-height: 44px; }
  .ss-case { width: 22px; height: 22px; }
}

/* La fiche d'une session dans la vue Reseau (U3), meme cadre que celle d'un fil. */
.ov-srow.clic { cursor: pointer; }
.ov-ftitre { display: flex; align-items: center; gap: 8px; margin-top: 4px; }
.ov-ftitre .ov-fsub { margin-top: 0; flex: 1; min-width: 0; overflow-wrap: anywhere; }
.ov-kv { display: grid; grid-template-columns: 76px minmax(0, 1fr); gap: 8px; padding: 4px 0;
  font-size: 12.5px; border-top: 1px dashed var(--line); }
.ov-kv:first-child { border-top: none; }
.ov-kv .k { font-family: var(--mono); font-size: 11px; color: var(--faint); padding-top: 1px; }
.ov-kv .v { color: var(--text); overflow-wrap: anywhere; }
.ov-kv.fin.non .v { color: var(--faint); }
.ov-kv.fin.agora_seul .v { color: var(--warn); }
.ov-kv-fils { display: flex; flex-direction: column; gap: 2px; }
.ov-kv-fils .link { font-size: 12.5px; }
/* Cinq onglets (« Sessions » en plus) : sur un telephone etroit, la rangee
   tient encore sans defiler — l'ecart vient du rembourrage lateral. */
@media (max-width: 420px) { .nav .tab { padding-left: 3px; padding-right: 3px; } }

/* SENTINEL-421 : sous 640 px la jauge des forfaits (deux fenêtres, âge de la
   mesure) ne laisse plus de place à cinq onglets sur la rangée du logo : la nav
   passe sur sa propre rangée, pleine largeur, et défile seule si besoin. */
@media (max-width: 640px) {
  .top { flex-wrap: wrap; row-gap: 4px; }
  .forfaits { margin-left: auto; }
  .nav { order: 3; flex: 1 0 100%; scrollbar-width: none; }
  .nav .tab { flex: 1 0 auto; font-size: 12px; }
  /* SENTINEL-409 : sans forfaits mesurés (un nouvel utilisateur), le « ⋯ »
     restait collé au logo et son menu, aligné à droite, sortait de l'écran
     par la gauche ; il se range à droite dans les deux cas. */
  .top > .menu-wrap { margin-left: auto; }
  .forfaits:not([hidden]) + .menu-wrap { margin-left: 0; }
}

/* ===== Personnes (SENTINEL-409) : organisations, équipes, invitations ===== */
#view-personnes { max-width: 760px; margin: 0 auto; }
.pp-titre { font-size: 13.5px; font-weight: 600; margin-bottom: 6px; }
.pp-titre .faint { font-weight: 400; }
.pp-ligne { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 8px 0;
  border-top: 1px solid var(--line); }
.pp-ligne:first-of-type { border-top: none; }
.pp-qui { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px; flex: 1 1 160px; min-width: 0; }
.pp-qui .faint { font-size: 12.5px; }
.pp-plein { flex-basis: 100%; }
.pp-plein:empty { display: none; }
.pp-equipe { padding: 8px 0; border-top: 1px solid var(--line); }
.pp-equipe:first-of-type { border-top: none; }
.pp-membres { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.pp-membre { display: inline-flex; align-items: center; gap: 4px; padding: 2px 4px 2px 8px;
  border: 1px solid var(--line); border-radius: 999px; font-size: 12.5px; }
.pp-x { min-width: 28px; min-height: 28px; border: none; background: none; color: var(--faint);
  cursor: pointer; font-size: 16px; line-height: 1; border-radius: 50%; }
.pp-x:hover { color: var(--bad); }
.pp-ajout { margin-top: 6px; }
.pp-ajout select, .pp-grille select, .field select {
  min-height: 42px; background: var(--bg); color: var(--text); border: 1px solid var(--line);
  border-radius: 8px; padding: 0 10px; font: inherit; font-size: 14px; }
.pp-ajout select { min-height: 34px; font-size: 13px; }
.pp-grille { display: grid; grid-template-columns: 1fr; gap: 0 12px; }
@media (min-width: 640px) { .pp-grille { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.pp-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px; margin-top: 10px;
  padding-top: 10px; border-top: 1px dashed var(--line); }
.pp-champ { flex: 1 1 180px; margin-top: 0; }
.pp-msg { flex-basis: 100%; }
.pp-msg:empty { display: none; }
.pp-code { border-color: var(--accent); }
.pp-code-val { margin: 8px 0 2px; overflow-wrap: anywhere; font-size: 20px; letter-spacing: 2px; }
.pp-passees summary { cursor: pointer; color: var(--muted); font-size: 13px; padding: 8px 0 2px; }
.pp-quitter { margin: 18px 2px 0; }
.pp-plateforme { margin-top: 26px; }
.pp-orgs { margin-bottom: 4px; }
/* L'arrivée d'un invité : l'écran du code, en formulaire. */
.pp-arrivee { max-width: 360px; align-items: stretch; gap: 12px; }
.pp-arrivee .wordmark, .pp-arrivee .lock-title { align-self: center; }
.pp-arrivee .field { margin-top: 0; }
.pp-creation { display: flex; flex-direction: column; gap: 12px; }
.pp-actions { margin-top: 4px; }
.pp-actions .btn { flex: 1 1 auto; }
.pp-bascule, .lock-invitation { align-self: center; font-size: 13px; }

/* ===== Journal des connexions (SENTINEL-490) ===== */
.cx-note { margin: -4px 2px 10px; font-size: 12.5px; }
.cx-heure { min-width: 92px; color: var(--muted); font-size: 12.5px; }
.cx-qui { font-weight: 500; }
.cx-ligne.ko .cx-qui { color: var(--muted); }
.cx-ligne .meta span { overflow-wrap: anywhere; }
.pt-qauteur { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; margin: 0 0 6px; }
.pt-qauteur-nom { font-size: 14.5px; font-weight: 600; color: #fff; overflow-wrap: anywhere; }
.pt-qauteur-depot { font-size: 12.5px; color: var(--muted); font-family: var(--mono); overflow-wrap: anywhere; }
.pt-qadr { font-size: 11.5px; color: var(--faint); font-family: var(--mono); overflow-wrap: anywhere; margin: 2px 0 6px; }
.pt-commande { display: block; overflow-wrap: anywhere; }
@media (max-width: 640px) { .cx-heure { min-width: 0; } }

/* ===== Mise à disposition (SENTINEL-413) : carte d'agent, panneau d'équipe ===== */
.dispo-bloc .dispo-agent { padding: 8px 0; border-top: 1px solid var(--line); }
.dispo-bloc .dispo-agent:first-of-type { border-top: none; }
.dispo-nom { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
.dispo-nom .btn { margin-left: auto; }
.dispo-carte { margin-top: 8px; padding: 8px 10px; border: 1px solid var(--line); border-radius: 8px; }
.dispo-phrase { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; font-size: 13px; }
.dispo-carte .actions { margin-top: 8px; }
.dispo-form, .dispo-retrait { margin-top: 8px; }
.dispo-form .field { margin-top: 8px; }
.dispo-form .field input, .dispo-form .field select { width: 100%; max-width: 360px; }
.dispo-implique { margin: 10px 0 0; padding-left: 18px; font-size: 12.5px; color: var(--muted); }
.dispo-implique li { margin-top: 3px; }
.dispo-stop { display: flex; align-items: center; gap: 8px; margin-top: 8px; font-size: 13px; min-height: 34px; }
.dispo-panneau { margin-top: 8px; }
.dispo-panneau summary { cursor: pointer; color: var(--muted); font-size: 13px; padding: 6px 0; }
.dispo-ligne .pp-qui { flex-basis: 140px; }

/* SENTINEL-415 : l'annonce à toute l'équipe — son état et le geste. */
.msg-annonce { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px;
  margin-top: 6px; padding: 6px 8px; border-left: 2px solid var(--accent);
  background: var(--panel-2); border-radius: 4px; font-size: 13px; }
.msg-annonce.prise { border-left-color: var(--line); }
.msg-annonce-stat { flex-basis: 100%; }
.msg-annonce-stat:empty { display: none; }

/* SENTINEL-476 : « Pour toi » — une ligne d'alerte par session au-delà du
   seuil de contexte (le contexte des sessions vit dans Sessions). */
.pt-alertes { display: grid; gap: 6px; margin: 4px 0 14px; }
.pt-alerte-ctx { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; padding: 8px 12px;
  border: 1px solid rgba(240,104,104,.45); border-radius: 10px; background: rgba(240,104,104,.06); font-size: 13.5px; }
.pt-alerte-txt { flex: 1 1 22ch; min-width: 0; overflow-wrap: anywhere; }
.pt-write .actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }

/* SENTINEL-476 : l'ecran « Machines » (ancien « Postes ») — la machine en
   pleine largeur, une fiche en clair a gauche, l'inventaire (replie quand
   tout est confirme) et la mise a disposition a droite ; les comptes une
   fois, en lignes larges, sous les machines. */
.machines-liste { display: grid; gap: 14px; margin-bottom: 18px; }
.mcard.plein .machine-head { flex-wrap: wrap; }
.mf-sessions { margin-left: auto; font-size: 13.5px; }
.mf-corps { display: grid; gap: 14px 28px; margin-top: 8px; }
.mf-fiche { display: grid; grid-template-columns: minmax(120px, 180px) minmax(0, 1fr); gap: 6px 16px; margin: 0; font-size: 13px; }
.mf-fiche dt { color: var(--muted); }
.mf-fiche dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.mf-caps summary { cursor: pointer; }
.mf-cote { min-width: 0; }
.mf-inv > summary { cursor: pointer; font-size: 13px; color: var(--text); padding: 2px 0 6px; }
.mf-inv:not([open]) + .inventaire { margin-top: 8px; }
.comptes-carte.large .compte { display: grid; gap: 6px 24px; }
@media (min-width: 1100px) {
  .mf-corps { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .comptes-carte.large .compte { grid-template-columns: minmax(220px, 300px) minmax(0, 1fr); }
  .comptes-carte.large .compte > :not(.compte-tete):not(.quotas) { grid-column: 1; }
  .comptes-carte.large .compte-age { margin-left: 0; flex-basis: 100%; }
  .comptes-carte.large .quotas { grid-column: 2; grid-row: 1 / span 3; grid-template-columns: repeat(2, minmax(0, 1fr)); margin-top: 0; }
}
@media (max-width: 640px) {
  .mf-fiche { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .mf-fiche dd { margin-bottom: 6px; }
  .mf-sessions { margin-left: 0; flex-basis: 100%; }
}
