/* Sociogramme — interface claire, fiches façon arbre généalogique. */

/* `hidden` doit cacher. Toujours.
 *
 * **Le défaut qu'on répare (13.B).** Le navigateur pose `display: none` sur un
 * élément `hidden`, mais c'est une règle d'agent utilisateur : **la moindre
 * règle d'auteur qui donne un `display` la bat**. Cinq éléments de cette
 * application recevaient un `display: flex` par leur classe et restaient donc
 * visibles alors que le script les avait cachés — mesuré le 14/08/2026 sur un
 * compte d'intendant :
 *
 * - `#groupe-essai` — « Créer un compte » et « Se connecter » proposés à
 *   quelqu'un de déjà connecté. C'est ce qui a été signalé.
 * - `#bandeau-procuration` — « vous écrivez chez les autres », affiché alors
 *   qu'on écrivait chez soi. Le plus grave : ce bandeau ment sur où l'on écrit.
 * - `#bandeau-essai` — l'invitation à créer un compte, sur un compte existant.
 * - `#lien-document` — « 📜 Document » sans document où aller.
 * - `#scene-message` — un message de scène vide.
 *
 * Une règle, et la classe entière de défauts disparaît. Le `!important` est ici
 * à sa place : il n'y a pas de cas où l'on veuille afficher un `hidden`. */
[hidden] { display: none !important; }

:root {
  --fond: #eaeef3;
  --fond-2: #ffffff;
  --fond-3: #f3f6f9;
  --plan: #f7f9fb;
  --plan-grille: #e3e8ee;
  --bord: #dde3ea;
  --bord-clair: #c9d1db;
  --texte: #1f2937;
  --texte-doux: #56606d;
  --texte-faible: #8b95a1;
  --accent: #2f9e8f;
  --accent-fonce: #24796d;
  --accent-doux: #dff2ee;
  --carte-fond: #ffffff;
  /* Une seule couche, et non deux.
   *
   * L'ombre d'une carte était empilée : un liseré net à 2 px de flou, plus un
   * halo à 10. Or elle est posée sur le bandeau **et** sur le corps de chaque
   * fiche, plus la photo, plus la poignée — mesuré le 15/08/2026 sur Westeros,
   * **665 couches d'ombre floue** dans un monde de 21 mégapixels, à re-tramer
   * à chaque cran de zoom. Une couche unique, un peu plus large et un peu plus
   * douce, rend le même relief pour la moitié du travail.
   *
   * On a d'abord voulu poser une seule ombre sur `.carte` au lieu de deux à
   * l'intérieur. C'est faux : `.carte` réserve 34 px transparents pour le
   * portrait, et l'ombre aurait cerné cette bande vide. */
  --carte-ombre: 0 2px 7px rgba(23, 33, 46, .13);
  --carte-ombre-forte: 0 6px 18px rgba(23, 33, 46, .22);
  --ombre-panneau: 0 8px 26px rgba(23, 33, 46, .10);
  --rayon: 9px;
  --police: "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --police-titre: "Iowan Old Style", "Palatino Linotype", Georgia, serif;
}

body.sombre {
  --fond: #10141a;
  --fond-2: #171c23;
  --fond-3: #1e242d;
  --plan: #0f1319;
  --plan-grille: #1b212a;
  --bord: #2a313b;
  --bord-clair: #39424f;
  --texte: #e7e2d6;
  --texte-doux: #a2abb7;
  --texte-faible: #767f8b;
  --accent: #3fbfa9;
  --accent-fonce: #2f9e8f;
  --accent-doux: #17342f;
  --carte-fond: #1c222b;
  --carte-ombre: 0 2px 9px rgba(0, 0, 0, .55);
  --carte-ombre-forte: 0 8px 22px rgba(0, 0, 0, .62);
  --ombre-panneau: 0 8px 26px rgba(0, 0, 0, .45);
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
  background: var(--fond);
  color: var(--texte);
  font-family: var(--police);
  font-size: 14px;
  overflow: hidden;
}

button, input, select, textarea { font: inherit; color: inherit; }

.application { display: flex; flex-direction: column; height: 100vh; }
.corps { flex: 1; display: flex; min-height: 0; position: relative; }

/* ------------------------------------------------------------- barre haut */

.barre-haut {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 9px 16px;
  background: var(--fond-2);
  border-bottom: 1px solid var(--bord);
  z-index: 20;
}

.marque { display: flex; align-items: center; gap: 10px; min-width: 190px; }
.marque-icone { font-size: 20px; color: var(--accent); }
.marque-titre { font-family: var(--police-titre); font-size: 16px; letter-spacing: .03em; }
.marque-univers { font-size: 11px; color: var(--texte-faible); }

.fil-ariane {
  display: flex; align-items: center; gap: 9px;
  margin: 0 auto;
  font-family: var(--police-titre);
  font-size: 15px;
}
.fil-vue { color: var(--texte-doux); }
.fil-separateur { color: var(--texte-faible); }
.fil-focus { color: var(--texte); font-weight: 600; }

.barre-controles { display: flex; align-items: center; gap: 9px; margin-left: auto; }

/* Enregistrement : le bouton force l'écriture, l'état dit où on en est. */
.groupe-enregistrement { display: flex; align-items: center; gap: 6px; }
.badge-attente {
  display: inline-block; margin-left: 6px; min-width: 16px; padding: 0 4px;
  border-radius: 8px; background: var(--accent); color: #fff;
  font-size: 10px; line-height: 15px; text-align: center;
}
.etat-ecriture { font-size: 10.5px; color: var(--texte-faible); white-space: nowrap; }
.etat-ecriture.attente { color: #b8842a; }
.etat-ecriture.erreur { color: #c0392b; }

.champ { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--texte-faible); }
.champ select,
.champ-recherche input {
  background: var(--fond-3);
  border: 1px solid var(--bord);
  border-radius: 8px;
  padding: 6px 9px;
  color: var(--texte);
  outline: none;
}
.champ select:focus, .champ-recherche input:focus { border-color: var(--accent); }

.bouton {
  background: var(--fond-3);
  border: 1px solid var(--bord);
  border-radius: 8px;
  padding: 6px 12px;
  cursor: pointer;
  color: var(--texte-doux);
  transition: background .15s, border-color .15s, color .15s;
}
.bouton:hover { background: var(--fond); border-color: var(--bord-clair); color: var(--texte); }
/* Un lien déguisé en bouton (le document de campagne) : même boîte, pas de
   soulignement, et la ligne de texte alignée sur celle des vrais boutons. */
a.bouton { text-decoration: none; display: inline-flex; align-items: center; line-height: 1.3; }
.bouton-primaire { border-color: var(--accent); color: var(--accent-fonce); background: var(--accent-doux); }
.bouton-primaire:hover { background: var(--accent-doux); border-color: var(--accent-fonce); }
.bouton-icone { padding: 5px 10px; }
.bouton-plat { background: transparent; border-color: transparent; }
.bouton-plat:hover { background: var(--fond-3); border-color: var(--bord); }
.bouton .ico { opacity: .75; margin-right: 4px; }
/* Les libellés de ⚙, 🛡 et ⏻ n'existent qu'au téléphone (13.B) : dans la barre
   du haut, l'infobulle suffit et la place manque.
 *
 * La règle porte sur **les boutons eux-mêmes**, pas sur l'ancêtre qui les
 * contient. Écrite en `.groupe-compte .lib`, elle cessait de s'appliquer dès
 * que `telephone.js` les déménageait — et la contrepartie est vraie aussi :
 * ces trois nœuds voyagent, ce qui les décrit doit voyager avec eux. */
#lien-admin .lib,
#lien-donnees .lib,
#btn-deconnexion .lib { display: none; }
.bouton:disabled { opacity: .45; cursor: default; }
/* Le seul bouton de la barre basse qui *écrit* : il se distingue des commandes
   de cadrage, qui ne font que regarder. */


.bouton-creer { color: var(--accent-fonce); font-weight: 600; }
.bouton-creer:hover { background: var(--accent-doux); border-color: var(--accent); }
.bouton-creer .ico { opacity: 1; }

/* ------------------------------------------------------------------ rail */

.rail {
  width: 246px; flex: 0 0 246px;
  background: var(--fond-2);
  border-right: 1px solid var(--bord);
  overflow-y: auto;
  padding: 14px 12px 30px;
  transition: margin-left .25s ease;
}
.rail.replie { margin-left: -246px; }

.rail-bloc { margin-bottom: 20px; }
.rail-bloc h2 {
  font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--texte-faible); margin: 0 0 8px; padding-bottom: 5px;
  border-bottom: 1px solid var(--bord);
}
/* Un titre de bloc qui porte son propre bouton : le trait passe sous les deux. */
.rail-bloc-entete {
  display: flex; align-items: center; gap: 6px;
  margin: 0 0 8px; padding-bottom: 5px; border-bottom: 1px solid var(--bord);
}
.rail-bloc-entete h2 { flex: 1; margin: 0; padding: 0; border-bottom: 0; }
.btn-entete { padding: 1px 7px; font-size: 13px; line-height: 1.2; }
/* Les axes de filtre, en pastilles : de quoi rappeler un filtre sur mesure
   sans repasser par la liste déroulante du haut. */
.axes-filtre { display: flex; flex-wrap: wrap; gap: 4px; margin: 0 0 8px; }
.axe-puce {
  font: inherit; font-size: 10.5px; line-height: 1.5;
  padding: 2px 8px; border-radius: 11px; cursor: pointer;
  border: 1px solid var(--bord); background: var(--fond-3); color: var(--texte-faible);
}
.axe-puce:hover { border-color: var(--accent); color: var(--texte); }
.axe-puce.actif {
  background: var(--accent-doux); border-color: var(--accent); color: var(--texte);
  font-weight: 600;
}
.axe-puce.sur-mesure::before { content: '⚙ '; opacity: .7; }
.rail-aide { font-size: 10.5px; color: var(--texte-faible); margin: -2px 0 7px; }

.liste-vues { list-style: none; margin: 0; padding: 0; }
.liste-vues li {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: 8px; cursor: pointer; font-size: 13px;
}
.liste-vues li:hover { background: var(--fond-3); }
.liste-vues li.actif { background: var(--accent); color: #fff; }
.liste-vues li.actif .vue-icone { color: #fff; }
.vue-icone { font-size: 15px; color: var(--accent); width: 18px; text-align: center; }

.legende { list-style: none; margin: 0; padding: 0; }
.legende li {
  display: flex; align-items: center; gap: 8px;
  padding: 4px 6px; border-radius: 6px; cursor: pointer;
  font-size: 12px; user-select: none;
}
.legende li:hover { background: var(--fond-3); }
.legende li.eteint { opacity: .35; }
.legende li .nombre { margin-left: auto; color: var(--texte-faible); font-size: 10.5px; font-variant-numeric: tabular-nums; }
.legende-trait { width: 20px; height: 0; border-top-width: 3px; border-top-style: solid; border-radius: 2px; flex: 0 0 20px; }
.legende-pastille { width: 11px; height: 11px; border-radius: 3px; flex: 0 0 11px; }
.legende li .fleche { color: var(--texte-faible); font-size: 10px; }

.options { display: flex; flex-direction: column; gap: 7px; }
.option { display: flex; align-items: center; gap: 8px; font-size: 12px; cursor: pointer; }
.option input { accent-color: var(--accent); }

.stats { font-size: 11.5px; color: var(--texte-doux); line-height: 1.65; }
.stats b { color: var(--texte); font-variant-numeric: tabular-nums; }

/* ----------------------------------------------------------------- scène */

.scene {
  flex: 1; position: relative; min-width: 0;
  background: var(--plan);
  background-image:
    radial-gradient(var(--plan-grille) 1px, transparent 1px);
  background-size: 26px 26px;
}

/* `touch-action: none` : le doigt déplace le plan, il ne fait pas défiler la
   page. Contrepartie assumée — le menu long-press du navigateur disparaît, et
   c'est `surMenuContextuel` qui le remplace (voir js/dom.js). */
.plan {
  position: absolute; inset: 0; overflow: hidden; cursor: grab;
  touch-action: none; -webkit-tap-highlight-color: transparent;
}
.plan:active { cursor: grabbing; }
/* `will-change` dit au navigateur que ce nœud-là va bouger sans arrêt : il lui
   réserve sa propre couche, et le panoramique n'est plus qu'un déplacement de
   couche — sans re-tramer les 21 mégapixels du monde. Le zoom, lui, change
   l'échelle et reste un vrai retraçage : c'est pourquoi le niveau de détail
   ci-dessous compte plus que cette ligne. */
.monde {
  position: absolute; left: 0; top: 0; transform-origin: 0 0;
  will-change: transform;
}
.liens { position: absolute; left: 0; top: 0; overflow: visible; pointer-events: none; }
.cartes { position: absolute; left: 0; top: 0; }

.scene-vide {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  color: var(--texte-faible); font-size: 13px; pointer-events: none; z-index: 4;
}

.barre-basse {
  position: absolute; left: 50%; bottom: 16px; transform: translateX(-50%);
  display: flex; align-items: center; gap: 5px;
  background: var(--fond-2);
  border: 1px solid var(--bord);
  border-radius: 12px;
  padding: 5px 8px;
  box-shadow: var(--ombre-panneau);
  z-index: 6;
}
.separateur-vertical { width: 1px; height: 20px; background: var(--bord); margin: 0 3px; }
#zoom-curseur { width: 116px; accent-color: var(--accent); }

.infobulle {
  position: absolute; z-index: 15; pointer-events: none;
  background: var(--fond-2);
  border: 1px solid var(--bord-clair);
  border-radius: 8px; padding: 8px 11px;
  box-shadow: var(--ombre-panneau);
  max-width: 280px; font-size: 12px; line-height: 1.45;
}
.astuce-scene {
  position: absolute; left: 50%; top: 14px; transform: translateX(-50%);
  z-index: 7; pointer-events: none;
  background: var(--accent-doux); color: var(--accent-fonce);
  border: 1px solid var(--accent); border-radius: 20px;
  padding: 6px 14px; font-size: 12px; line-height: 1.3;
  box-shadow: var(--ombre-panneau); max-width: 82%; text-align: center;
}

.infobulle .ib-titre { font-weight: 600; font-size: 12.5px; }
.infobulle .ib-sous { color: var(--texte-faible); }
.infobulle .ib-ligne { margin-top: 3px; color: var(--texte-doux); }

/* ---------------------------------------------------------------- cartes */

.cartes.sans-transition .carte { transition: none !important; }

.carte {
  position: absolute;
  display: flex; flex-direction: column;   /* le corps remplit la hauteur commune */
  /* Le portrait est en `absolute` : cette réserve est la seule chose qui
     l'empêche de recouvrir le nom. Aucune règle ne doit repasser sur le
     `padding` d'une carte — pas même par un état porté en classe nue. */
  padding-top: 34px;                 /* espace du portrait */
  cursor: pointer;
  /* Un appui long sur une fiche ouvre notre menu : ni sélection de texte, ni
     bulle « copier », ni loupe iOS ne doivent venir s'y superposer. */
  user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;
  transition: left .55s cubic-bezier(.4, 0, .2, 1),
              top .55s cubic-bezier(.4, 0, .2, 1),
              opacity .25s ease, filter .2s ease;
}
.carte.masquee { display: none; }
.carte.hors-recherche { opacity: .28; }
.carte.hors-filtre { opacity: .22; filter: saturate(.35); }
.carte.hors-filtre:hover { opacity: .6; }

.carte-photo {
  position: absolute; top: 0; left: 50%; transform: translateX(-50%);
  width: 46px; height: 46px; border-radius: 50%;
  background: var(--couleur-carte);
  border: 3px solid var(--carte-fond);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .12), var(--carte-ombre);
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-weight: 600; font-size: 16px; letter-spacing: .03em;
  z-index: 2;
}
/* Un mort a le portrait terni. Par un voile, et non par `filter` : un filtre
   force le navigateur à ouvrir une surface de rendu à part pour l'élément, et
   il y en avait **quarante-sept** dans Westeros. Le voile est une couleur
   posée par-dessus — le compositeur ne fait rien de plus.
   Un vrai portrait, lui, garde son filtre : un voile plat ne désature pas une
   photographie, il la salit. Ils sont rares, et le coût suit. */
.carte.morte .carte-photo:not(.avec-photo) {
  background-image: linear-gradient(rgba(120, 124, 130, .38), rgba(120, 124, 130, .38));
}
.carte.morte .carte-photo.avec-photo { filter: saturate(.55) brightness(.92); }
.carte.morte .carte-photo::after {
  content: '†';
  position: absolute; right: -3px; bottom: -3px;
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--carte-fond); color: var(--texte-doux);
  font-size: 11px; display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--bord);
}

.carte-entete {
  background: var(--couleur-carte);
  color: #fff;
  text-align: center;
  padding: 11px 8px 4px;
  border-radius: 6px 6px 0 0;
  font-size: 11.5px; font-weight: 600; line-height: 1.2;
  box-shadow: var(--carte-ombre);
}
/* Un satellite garde la taille commune : seul son bandeau est plus discret. */
.carte.satellite .carte-entete { opacity: .88; }
.carte.gabarit { visibility: hidden; pointer-events: none; left: 0; top: 0; }
/* Votre fiche : liseré et étoile. C'est le point de repère du plan — celui à
   partir duquel on lit les autres — et la seule carte qui ait quelqu'un
   derrière elle. La taille, elle, ne bouge pas : se désigner ne doit pas faire
   sauter la mise en page. */
.carte.moi { --couleur-moi: #c9a227; }
.carte.moi .carte-corps { border-width: 0 2px 2px; border-color: var(--couleur-moi); }
.carte.moi .carte-entete {
  position: relative;
  box-shadow: var(--carte-ombre), inset 0 0 0 2px var(--couleur-moi);
}
.carte.moi .carte-photo { border-color: var(--couleur-moi); }
.carte-moi {
  position: absolute; top: 32px; left: 4px; z-index: 3;
  width: 17px; height: 17px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--carte-fond); color: var(--couleur-moi);
  border: 1px solid var(--couleur-moi);
  font-size: 10px; line-height: 1;
  box-shadow: var(--carte-ombre);
}
/* De loin, les corps de fiche s'effacent : l'étoile, elle, reste lisible —
   c'est à cette échelle qu'on cherche où l'on se trouve. */
.plan.loin .carte-moi { opacity: 1; }
/* Deux lignes de nom au maximum : au-delà, le gabarit ne bornerait plus rien. */
.carte-nom {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}

.carte-corps {
  flex: 1;
  background: var(--carte-fond);
  border: 1px solid var(--bord);
  border-top: 0;
  border-radius: 0 0 6px 6px;
  padding: 4px 8px 6px;
  box-shadow: var(--carte-ombre);
  transition: opacity .2s ease;
}

.carte-titre {
  font-size: 9.5px; color: var(--texte-faible); text-align: center;
  font-style: italic; margin-bottom: 3px; line-height: 1.25;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.carte-ligne { display: flex; align-items: baseline; gap: 4px; font-size: 10px; line-height: 1.4; }
.carte-ligne .ic { color: var(--texte-faible); width: 7px; flex: 0 0 7px; font-size: 8.5px; }
.carte-ligne .lib { color: var(--texte-doux); }
.carte-ligne .val { margin-left: auto; color: var(--texte); font-variant-numeric: tabular-nums; }
.carte-lieu {
  font-size: 9px; color: var(--texte-faible); line-height: 1.3;
  margin: 0 0 1px 11px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.carte-separateur { height: 1px; background: var(--bord); margin: 4px 0 3px; }
/* Les notes, sous le personnage : trois lignes au plus, le reste se lit dans
   la fiche. C'est ce qu'on relit en pleine partie. */
.carte-notes {
  font-size: 10.5px; line-height: 1.4; color: var(--texte-faible);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3;
  overflow: hidden;
}
.carte-relation {
  display: grid; grid-template-columns: 8px 1fr; gap: 0 4px;
  font-size: 9.5px; line-height: 1.35; margin-bottom: 2px;
}
.carte-relation .pastille {
  width: 6px; height: 6px; border-radius: 2px; align-self: center;
}
.carte-relation .rel-type { color: var(--texte-faible); }
.carte-relation .rel-nom {
  grid-column: 2; color: var(--texte); font-weight: 500; font-size: 10px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.carte:hover .carte-corps,
.carte:hover .carte-entete { box-shadow: var(--carte-ombre-forte); }
.carte.focus .carte-corps { border-color: var(--accent); }
.carte.focus .carte-entete { box-shadow: 0 0 0 2px var(--accent), var(--carte-ombre-forte); }
.carte.focus .carte-corps { box-shadow: 0 0 0 2px var(--accent), var(--carte-ombre-forte); }
.carte.focus .carte-photo { border-color: var(--accent); }

/* poignée de liaison : apparaît au survol, se glisse vers une autre fiche */
.carte-poignee {
  position: absolute; left: 50%; bottom: -11px; transform: translateX(-50%);
  width: 20px; height: 20px; border-radius: 50%; padding: 0;
  border: 1px solid var(--bord-clair); background: var(--carte-fond);
  color: var(--texte-doux); font-size: 14px; line-height: 1; font-weight: 600;
  display: flex; align-items: center; justify-content: center;
  cursor: crosshair; opacity: 0; z-index: 3;
  /* Pas d'ombre : ce bouton est transparent au repos, et il y en avait une par
     fiche — soixante-sept halos flous dessinés sous un bouton qu'on ne voit
     pas. Affiché, c'est un rond de 20 px : son bord suffit à le détacher. */
  transition: opacity .15s ease, background .15s ease, color .15s ease;
}
.carte:hover .carte-poignee,
.carte.focus .carte-poignee,
.carte.source-liaison .carte-poignee { opacity: 1; }
.carte-poignee:hover { background: var(--accent); border-color: var(--accent); color: #fff; }
.plan.loin .carte-poignee { display: none; }

.carte.source-liaison .carte-photo { border-color: var(--accent); }
.carte.cible-liaison .carte-entete,
.carte.cible-liaison .carte-corps {
  box-shadow: 0 0 0 2px var(--accent), var(--carte-ombre-forte);
}

/* fiche armée par Maj + clic, en attente de sa destination */
.carte.en-attente .carte-entete,
.carte.en-attente .carte-corps {
  box-shadow: 0 0 0 2px var(--accent), var(--carte-ombre-forte);
}
.carte.en-attente .carte-photo {
  border-color: var(--accent);
  animation: pulsation 1.4s ease-in-out infinite;
}
@keyframes pulsation {
  0%, 100% { box-shadow: 0 0 0 0 rgba(47, 158, 143, .55), var(--carte-ombre); }
  50%      { box-shadow: 0 0 0 7px rgba(47, 158, 143, 0), var(--carte-ombre); }
}

/* déplacement manuel (Ctrl + glisser) */
.plan.en-deport { cursor: grabbing; }
.carte.en-deport { z-index: 5; }
.carte.en-deport .carte-entete,
.carte.en-deport .carte-corps { box-shadow: var(--carte-ombre-forte); }
.carte.en-deport .carte-photo { transform: translateX(-50%) scale(1.06); }

/* niveau de détail : au loin, seuls les bandeaux restent lisibles */
/* Niveau de détail : de loin, on ne dessine plus ce qu'on ne peut pas lire.
 *
 * `opacity: .18` pâlissait le corps de la fiche **et le peignait quand même**,
 * en ouvrant au passage une couche de composition par carte. Or ces corps
 * portent 41 % des nœuds du plan (629 sur 1545, mesuré sur Westeros), et ce
 * sont ceux qui portent du texte — le plus cher à tramer.
 *
 * On cache les **enfants**, pas la boîte : `display: none` sur le corps ferait
 * rétrécir la carte, alors que les traits de liaison sont tracés d'après les
 * boîtes calculées en JavaScript, qui ne bougeraient pas. Les liens
 * finiraient dans le vide. La boîte reste donc, vide et pâle ; ce qu'elle
 * contenait s'en va. */
.plan.loin .carte-corps { background: var(--carte-fond); opacity: .55; }
.plan.loin .carte-corps > * { display: none; }

/* ----------------------------------------------------------------- liens */

.lien-famille { fill: none; stroke-width: 1.7px; stroke-linejoin: round; stroke-linecap: round; }
.lien-union { fill: none; stroke-width: 2.2px; stroke-linecap: round; }
.lien-fratrie { fill: none; stroke-width: 1.6px; stroke-dasharray: 6 4; stroke-linejoin: round; }
.lien-social {
  fill: none; stroke-width: 1.5px; opacity: .55;
  transition: opacity .2s, stroke-width .15s;
}
.lien-social.survol { opacity: 1; stroke-width: 2.4px; }
.lien-social.attenue { opacity: .1; }

/* Filtre de type actif : ce qui reste doit sauter aux yeux. */
/* Révolu : le trait s'efface sans disparaître. On doit pouvoir lire « ils
   ont été alliés » sans confondre avec « ils le sont ». */
.lien-social.revolu { opacity: .38; stroke-width: 1.4px; }
.lien-social.revolu.survol { opacity: .8; }
.option-revolus { margin: 8px 0 2px; }

/* Pastille d'un lien : l'emoji posé sur le trait, sur une rondelle de fond qui
   coupe le trait pour rester lisible.
   `pointer-events: none` n'est pas cosmétique — la pastille est dessinée
   au-dessus du trait, et sans ça elle percerait un trou dans sa zone de survol. */
.lien-pastille {
  font-size: 12.5px;
  pointer-events: none;
  user-select: none;
}
.lien-pastille-fond {
  fill: var(--fond);
  pointer-events: none;
}
.lien-pastille.attenue, .lien-pastille-fond.attenue { opacity: .15; }
.lien-pastille.revolu { opacity: .5; }

/* Saisie de la pastille : un petit champ libre suivi des raccourcis. */
.ligne-emoji { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }
.champ-emoji {
  width: 44px; flex: 0 0 44px; text-align: center;
  font-size: 15px; padding: 4px 2px;
}
.bouton-emoji {
  font-size: 14px; line-height: 1; padding: 4px 5px; min-width: 0;
}
.bouton-emoji.actif { border-color: var(--accent); background: var(--accent-doux); }

.plan.filtre-liens .lien-social { opacity: 1; stroke-width: 3.2px; }
.plan.filtre-liens .lien-social.survol { stroke-width: 4.2px; }
.plan.filtre-liens .lien-social.attenue { opacity: .35; }
.plan.filtre-liens .lien-famille { stroke-width: 3px; }
.plan.filtre-liens .lien-union { stroke-width: 3.4px; }
.plan.filtre-liens .lien-fratrie { stroke-width: 2.8px; }

/* Prises de clic : invisibles, épaisses, empilées au-dessus du dessin.
   Un connecteur de 1,7 px est intraçable à la souris ; celles-ci font 13 px. */
.lien-prise {
  fill: none; stroke: transparent; stroke-width: 13px;
  stroke-linejoin: round; stroke-linecap: round;
  pointer-events: stroke; cursor: pointer;
}

/* Élastique de création de lien */
.couche-guide { opacity: 0; }
.couche-guide.visible { opacity: 1; }
.guide-trait {
  fill: none; stroke: var(--accent); stroke-width: 2.2px;
  stroke-dasharray: 7 5; stroke-linecap: round;
}
.guide-point { fill: var(--accent); }
.plan.en-liaison, .plan.en-liaison .carte { cursor: crosshair; }

/* --------------------------------------------------------------- panneau */

.panneau {
  width: 330px; flex: 0 0 330px;
  background: var(--fond-2);
  border-left: 1px solid var(--bord);
  display: flex; flex-direction: column;
  min-height: 0;
}

.pn-onglets { display: flex; border-bottom: 1px solid var(--bord); flex: 0 0 auto; }
.onglet {
  flex: 1; background: transparent; border: 0; border-bottom: 2px solid transparent;
  padding: 10px 8px; cursor: pointer; color: var(--texte-faible); font-size: 12.5px;
}
.onglet:hover:not(:disabled) { color: var(--texte); }
.onglet.actif { color: var(--accent-fonce); border-bottom-color: var(--accent); font-weight: 600; }
.onglet:disabled { opacity: .4; cursor: default; }

.pn-vue { flex: 1; overflow-y: auto; min-height: 0; }

/* liste des personnes */
.liste-entete {
  position: sticky; top: 0; z-index: 3;
  background: var(--fond-2); border-bottom: 1px solid var(--bord);
  padding: 10px 12px; display: flex; flex-direction: column; gap: 8px;
}
.champ-recherche { position: relative; display: flex; align-items: center; }
.champ-recherche .loupe {
  position: absolute; left: 9px; color: var(--texte-faible); font-size: 14px; pointer-events: none;
}
.champ-recherche input { width: 100%; padding-left: 26px; }
.champ-groupe { justify-content: space-between; }
.champ-groupe select { flex: 1; margin-left: 8px; }

.liste-personnes { padding: 6px; }
.groupe-titre {
  font-size: 10px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--texte-faible); padding: 10px 8px 5px; display: flex; align-items: center; gap: 7px;
}
.groupe-titre .barre-couleur { width: 10px; height: 10px; border-radius: 3px; }
.groupe-titre .nombre { margin-left: auto; }
/* Champ à suggestions (le lieu) : la liste se pose par-dessus la fiche. */
.champ-suggere { position: relative; }
.champ-suggere input { width: 100%; }
.suggestions {
  position: absolute; left: 0; right: 0; top: calc(100% + 2px); z-index: 30;
  list-style: none; margin: 0; padding: 4px;
  max-height: 210px; overflow-y: auto;
  background: var(--fond-2); border: 1px solid var(--bord-clair);
  border-radius: 8px; box-shadow: var(--ombre-panneau);
}
.suggestions li {
  padding: 5px 7px; border-radius: 6px; cursor: pointer;
  display: flex; flex-direction: column; gap: 1px;
}
.suggestions li:hover, .suggestions li.survol { background: var(--accent-doux); }
.sug-valeur { font-size: 12px; }
.sug-detail { font-size: 10px; color: var(--texte-faible); }

.item-personne {
  display: flex; align-items: center; gap: 9px;
  padding: 5px 8px; border-radius: 8px; cursor: pointer;
}
.item-personne:hover { background: var(--fond-3); }
.item-personne.actif { background: var(--accent-doux); }
.item-avatar {
  width: 27px; height: 27px; border-radius: 50%; flex: 0 0 27px;
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 10px; font-weight: 600;
}
.item-corps { min-width: 0; flex: 1; }
.item-nom { font-size: 12.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.item-meta { font-size: 10.5px; color: var(--texte-faible); }
.item-personne.mort .item-avatar { filter: saturate(.5) brightness(.95); }

/* fiche */
.pn-entete {
  position: sticky; top: 0; z-index: 5;
  background: var(--fond-2); border-bottom: 1px solid var(--bord); padding: 13px 14px;
}
.pn-entete-haut { display: flex; align-items: flex-start; gap: 11px; }
.pn-avatar {
  width: 44px; height: 44px; border-radius: 50%; flex: 0 0 44px;
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; color: #fff; font-size: 15px;
}
.pn-nom { font-family: var(--police-titre); font-size: 18px; line-height: 1.2; }
.pn-surnom { color: var(--texte-faible); font-size: 11.5px; font-style: italic; }
.pn-fermer { margin-left: auto; }
.pn-badges { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 9px; }
.badge {
  font-size: 10px; padding: 3px 8px; border-radius: 20px;
  border: 1px solid var(--bord); color: var(--texte-doux); background: var(--fond-3);
}
.badge-vivant { color: #1d7a5f; border-color: #a9dcc9; background: #e6f6f0; }
.badge-mort { color: #9a4b4b; border-color: #e3c2c2; background: #f9eded; }
body.sombre .badge-vivant { color: #7fd6b2; border-color: #2b5a49; background: #16302a; }
body.sombre .badge-mort { color: #d99b9b; border-color: #5b3636; background: #2c1c1c; }
.badge-cercle { color: #fff; font-weight: 600; border: 0; }
/* Vous, dans la fiche. Même or que l'étoile du plan, pour qu'on relie les
   deux sans effort. Il se lit, il ne se clique pas : on se désigne d'un clic
   droit sur le plan, là où l'on voit qui est autour. */
.badge-moi { font-weight: 600; color: #8a6d0b; border-color: #d9be62; background: #fbf3d9; }
body.sombre .badge-moi { color: #e6c964; border-color: #6a5720; background: #302a15; }

/* La parenté déduite. Elle n'est pas un choix de l'utilisateur mais une
   conséquence de l'arbre : discrète, en italique, pour qu'on la distingue
   d'une étiquette qu'on aurait posée soi-même. */
.badge-parente { font-style: italic; color: var(--texte-doux); }

/* Détails d'un lien : repliés tant qu'ils sont vides. */
.fl-details { margin-top: 4px; }
.fl-details > summary {
  cursor: pointer; font-size: 11px; color: var(--texte-faible);
  padding: 3px 0; user-select: none;
}
.fl-details > summary:hover { color: var(--texte); }
.fl-details .champ-edit { margin-top: 6px; }

.pn-actions { display: flex; gap: 7px; margin-top: 10px; }

.pn-section { padding: 13px 14px; border-bottom: 1px solid var(--bord); }
.pn-section > h3 {
  font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--texte-faible); margin: 0 0 10px;
}

.grille-champs { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }
.grille-champs .pleine { grid-column: 1 / -1; }
.champ-edit { display: flex; flex-direction: column; gap: 3px; }
.champ-edit > label { font-size: 10px; color: var(--texte-faible); text-transform: uppercase; letter-spacing: .07em; }
.champ-edit input, .champ-edit select, .champ-edit textarea {
  background: var(--fond-3); border: 1px solid var(--bord); border-radius: 7px;
  padding: 6px 8px; outline: none; width: 100%; font-size: 12px;
}
.champ-edit textarea { resize: vertical; min-height: 86px; line-height: 1.5; }
.champ-edit input:focus, .champ-edit select:focus, .champ-edit textarea:focus { border-color: var(--accent); }

.echelle-aide { font-size: 10px; color: var(--texte-faible); margin: -4px 0 7px; }

.groupe-liens { margin-bottom: 12px; }
.groupe-liens > h4 {
  font-size: 10px; color: var(--texte-faible); margin: 0 0 5px;
  text-transform: uppercase; letter-spacing: .1em;
}
.lien { display: flex; align-items: center; gap: 8px; padding: 6px 7px; border-radius: 7px; cursor: pointer; }
.lien:hover { background: var(--fond-3); }
.lien-trait { width: 13px; height: 0; border-top-width: 3px; border-top-style: solid; flex: 0 0 13px; }
.lien-corps { min-width: 0; flex: 1; }
.lien-nom { font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lien-type { font-size: 10px; color: var(--texte-faible); }
.lien-notes { font-size: 10px; color: var(--texte-faible); font-style: italic; }
.puce-secret { font-size: 9px; color: #a9762a; border: 1px solid #e0c79a; border-radius: 4px; padding: 0 4px; }
.puce-deduit { font-size: 9px; color: var(--texte-faible); border: 1px solid var(--bord); border-radius: 4px; padding: 0 4px; }

.pn-pied {
  position: sticky; bottom: 0;
  background: var(--fond-2); border-top: 1px solid var(--bord);
  padding: 10px 14px; display: flex; align-items: center; gap: 9px;
}
.pn-pied-aide { font-size: 10px; color: var(--texte-faible); margin-left: auto; text-align: right; }
.etat-sauvegarde { font-size: 11px; color: var(--texte-faible); }
.etat-sauvegarde.modifie { color: #b8842a; }
.etat-sauvegarde.ok { color: var(--accent-fonce); }
.etat-sauvegarde.erreur { color: #c0392b; }

.vide { color: var(--texte-faible); font-size: 12px; font-style: italic; }

/* ------------------------------------------------- menus & éditeurs flottants */

.menu-contextuel {
  position: fixed; z-index: 60; min-width: 210px; max-width: 280px; padding: 5px;
  background: var(--fond-2); border: 1px solid var(--bord-clair);
  border-radius: 10px; box-shadow: var(--ombre-panneau); font-size: 12.5px;
}
.menu-titre {
  display: flex; align-items: center; gap: 7px; padding: 6px 9px 8px;
  font-weight: 600; border-bottom: 1px solid var(--bord); margin-bottom: 4px;
}
.menu-titre-texte { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.menu-pastille { width: 9px; height: 9px; border-radius: 3px; flex: 0 0 9px; }
.menu-texte { padding: 1px 9px 8px; color: var(--texte-doux); line-height: 1.45; }
.menu-item {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 7px 9px; border: 0; border-radius: 6px; background: transparent;
  text-align: left; cursor: pointer; color: var(--texte);
}
.menu-item:hover { background: var(--fond-3); }
.menu-item:disabled { opacity: .45; cursor: default; background: transparent; }
.menu-icone { width: 15px; flex: 0 0 15px; text-align: center; opacity: .8; }
.menu-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.menu-detail { color: var(--texte-faible); font-size: 11px; }
.menu-item.danger { color: #c0392b; }
.menu-item.danger:hover { background: #fdecea; }
body.sombre .menu-item.danger { color: #e8776b; }
body.sombre .menu-item.danger:hover { background: #3a1f1c; }
.menu-separateur { height: 1px; background: var(--bord); margin: 4px 2px; }

.flottant {
  position: fixed; z-index: 60; width: 322px;
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--fond-2); border: 1px solid var(--bord-clair);
  border-radius: 12px; box-shadow: var(--ombre-panneau);
}
.fl-entete {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 10px 9px 9px 12px; border-bottom: 1px solid var(--bord);
}
.fl-titre { flex: 1; font-size: 12.5px; line-height: 1.45; }
.fl-nom { font-weight: 600; }
.fl-fleche { color: var(--texte-faible); }
.fl-fermer { flex: 0 0 auto; }
.fl-corps {
  padding: 11px 12px; display: flex; flex-direction: column; gap: 10px;
  max-height: 62vh; overflow: auto;
}
.fl-corps .champ-edit textarea { min-height: 50px; }
.fl-pied {
  display: flex; align-items: center; gap: 7px;
  padding: 9px 12px; border-top: 1px solid var(--bord); background: var(--fond-3);
}
.fl-etat { flex: 1; font-size: 11px; color: var(--texte-faible); text-align: right; }
.fl-etat.erreur { color: #c0392b; }
.fl-aide { margin: 0; font-size: 11px; color: var(--texte-faible); line-height: 1.45; }

/* ------------------------------------------------ raccourcis (lot 16.D) */

.flottant.flottant-raccourcis { width: 342px; }
.rc-groupe { display: flex; flex-direction: column; gap: 4px; }
.rc-titre {
  font-size: 10px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--texte-faible); margin-bottom: 2px;
}
/* Les touches d'abord, à largeur fixe : l'œil descend une colonne de touches
   et s'arrête sur la bonne, au lieu de relire chaque phrase. */
.rc-ligne { display: flex; align-items: baseline; gap: 9px; font-size: 11.5px; }
.rc-touches { flex: 0 0 106px; display: flex; flex-wrap: wrap; gap: 3px; }
.rc-quoi { flex: 1; color: var(--texte-doux); line-height: 1.4; }
.rc-touches kbd {
  font: inherit; font-size: 10.5px; line-height: 1.5;
  padding: 1px 5px; border-radius: 5px;
  background: var(--fond-3); border: 1px solid var(--bord);
  border-bottom-width: 2px; color: var(--texte);
  white-space: nowrap;
}

/* --------------------------------------------------- langue (lot 16.G) */

.flottant.flottant-langue { width: 188px; }
.flottant-langue .fl-corps { padding: 5px; gap: 2px; }
.lg-choix {
  display: flex; align-items: center; gap: 9px;
  padding: 8px 10px; border: 0; border-radius: 8px;
  background: transparent; color: var(--texte);
  font: inherit; font-size: 12.5px; text-align: left; cursor: pointer;
}
.lg-choix:hover { background: var(--fond-3); }
.lg-drapeau { font-size: 15px; line-height: 1; }
.lg-nom { flex: 1; }
.lg-coche { color: var(--accent); width: 12px; }
.lg-choix.actif .lg-nom { font-weight: 600; }

/* ------------------------------ offrir et recevoir une note (lot 16.E) */

.flottant.flottant-envoi { width: 340px; }
.of-adresses { resize: vertical; min-height: 54px; line-height: 1.5; }

/* La boîte de réception peut porter plusieurs propositions : elle est plus
   large que les autres panneaux, et son corps défile. */
.flottant.flottant-offres { width: 396px; }
.flottant-offres .fl-corps { max-height: 58vh; gap: 12px; }
.of-carte {
  border: 1px solid var(--bord); border-radius: 9px;
  padding: 10px 11px; background: var(--fond-3);
  display: flex; flex-direction: column; gap: 5px;
}
.of-de { font-size: 11.5px; }
.of-origine { color: var(--texte-faible); }
.of-titre { font-size: 12.5px; font-weight: 600; }
.of-meta { font-size: 10.5px; color: var(--texte-faible); }
/* L'aperçu est du Markdown brut, volontairement : ce qui compte ici est de
   reconnaître la note, pas de la lire en beauté avant de l'avoir acceptée. */
.of-apercu {
  margin: 2px 0 0; font-size: 11px; line-height: 1.5; color: var(--texte-doux);
  white-space: pre-wrap; overflow-wrap: anywhere;
  max-height: 92px; overflow: hidden;
  border-left: 2px solid var(--bord); padding-left: 8px;
}
.of-actions { display: flex; gap: 7px; margin-top: 4px; }

/* --------------------------------------------------- éditeur de filtre */

.flottant.editeur-filtre { width: 384px; }
.editeur-filtre .fl-corps { max-height: 64vh; overflow-y: auto; }

.gradient-reglage { display: flex; align-items: center; gap: 8px; }
.gradient-bande {
  flex: 1; height: 14px; border-radius: 7px; border: 1px solid var(--bord);
}

.bloc-tests { gap: 6px; }
.jointure select { font-size: 11px; }
.ligne-test { display: flex; align-items: center; gap: 5px; }
.ligne-test select, .ligne-test input { font-size: 11px; padding: 4px 6px; }
.ligne-test select:first-child { flex: 1.2; min-width: 0; }
.ligne-test select:nth-child(2) { flex: 1; min-width: 0; }
.ligne-test input { flex: 1; min-width: 0; }

/* Listes nommées : cocher ce qui existe, ajouter le reste à la main. */
.flottant.editeur-liste { width: 320px; }
.editeur-liste .fl-corps { max-height: 62vh; overflow-y: auto; }
.liste-valeurs {
  max-height: 190px; overflow-y: auto;
  border: 1px solid var(--bord); border-radius: 8px; padding: 4px 6px;
  background: var(--fond-3);
}
.valeur-observee {
  display: flex; align-items: center; gap: 7px;
  font-size: 11.5px; padding: 2px 0; cursor: pointer;
}
.valeur-observee input { width: auto; flex: 0 0 auto; }
.puces-valeurs { display: flex; flex-wrap: wrap; gap: 4px; }
.puce-valeur {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; padding: 2px 4px 2px 7px; border-radius: 11px;
  background: var(--accent-doux); border: 1px solid var(--bord);
}
.puce-retirer {
  border: 0; background: none; cursor: pointer; color: var(--texte-faible);
  font-size: 11px; line-height: 1; padding: 1px 2px;
}
.puce-retirer:hover { color: #c0392b; }

.apercu-filtre {
  border: 1px solid var(--bord); border-radius: 8px; padding: 7px 9px;
  background: var(--fond-3);
}
.apercu-resume {
  display: flex; justify-content: space-between; gap: 8px;
  font-size: 11px; color: var(--texte-faible); margin-bottom: 5px;
}
.apercu-exclus { color: #c0392b; }
.apercu-segments { list-style: none; margin: 0; padding: 0; }
.apercu-segments li {
  display: flex; align-items: center; gap: 7px; font-size: 11.5px; padding: 2px 0;
}
.apercu-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.champ-avec-pastille { display: flex; align-items: center; gap: 7px; }
.champ-avec-pastille select { flex: 1; }
.fl-pastille { width: 12px; height: 12px; border-radius: 3px; flex: 0 0 12px; }

.bouton-danger { color: #c0392b; border-color: #e3b4ae; }
.bouton-danger:hover { background: #fdecea; border-color: #c0392b; color: #c0392b; }
.bouton-danger.arme { background: #c0392b; border-color: #c0392b; color: #fff; }
.bouton-danger.arme:hover { background: #a93226; color: #fff; }

/* --------------------------------------------------- bibliothèque (rail) */

.liste-sauvegardes { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.sauvegarde {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 8px; border-radius: 8px; cursor: pointer;
  border: 1px solid transparent; user-select: none;
}
.sauvegarde:hover { background: var(--fond-3); }
.sauvegarde.actif { background: var(--accent-doux); border-color: var(--accent); cursor: default; }
/* Un arbre qu'on nous a ouvert (11.B) : bordure en pointillé, pour qu'on ne le
   prenne pas d'un coup d'œil pour l'une des siennes. */
.sauvegarde.partage { border-style: dashed; }
.sauvegarde.partage .sv-pastille { background: #7fa8c9; }
.sv-pastille {
  width: 8px; height: 8px; border-radius: 50%; flex: 0 0 8px;
  border: 1.5px solid var(--bord-clair);
}
.sauvegarde.actif .sv-pastille { background: var(--accent); border-color: var(--accent); }
.sv-corps { min-width: 0; }
.sv-nom { font-size: 12.5px; color: var(--texte); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sauvegarde.actif .sv-nom { font-weight: 600; }
.sv-meta { font-size: 10px; color: var(--texte-faible); font-variant-numeric: tabular-nums; }
.rail-actions { display: flex; gap: 4px; margin-top: 6px; }
.rail-actions .bouton { flex: 1; font-size: 11px; padding: 5px 4px; }
.rail-actions .bouton:hover { background: var(--fond-3); border-color: var(--bord); }

.groupe-cadrage { display: contents; }
.groupe-cadrage[hidden] { display: none; }

/* ------------------------------------------- référentiels (rail + éditeurs) */

/* Un cercle ou un type sans occurrence affichée reste dans la liste : il
   faut bien pouvoir modifier ce qu'on vient de créer. */
.legende li.inutilise { opacity: .5; cursor: default; }
.legende li.inutilise:hover { background: transparent; }
.legende li.inutilise .nombre { opacity: .6; }

.editeur-referentiel { width: 320px; }
.champ-couleur-edit { display: flex; flex-direction: column; gap: 6px; }
.champ-couleur-edit input[type='color'] {
  width: 100%; height: 30px; padding: 2px;
  border: 1px solid var(--bord); border-radius: 6px;
  background: var(--fond-3); cursor: pointer;
}
.nuancier { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.nuance {
  height: 18px; border-radius: 4px; padding: 0; cursor: pointer;
  border: 1px solid rgba(0, 0, 0, .18);
  transition: transform .12s ease, box-shadow .12s ease;
}
.nuance:hover { transform: scale(1.12); }
.nuance.actif { box-shadow: 0 0 0 2px var(--fond-2), 0 0 0 3px var(--texte); }

.segments { display: flex; gap: 4px; }
.segment {
  flex: 1; padding: 5px 4px; font-size: 11px; cursor: pointer;
  border: 1px solid var(--bord); border-radius: 6px;
  background: var(--fond-3); color: var(--texte-doux);
}
.segment:hover { border-color: var(--bord-clair); color: var(--texte); }
.segment.actif { background: var(--accent); border-color: var(--accent); color: #fff; }

.fl-apercu {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 11px; border-radius: 7px;
  background: var(--fond-3); border: 1px solid var(--bord);
  font-size: 12.5px; color: var(--texte);
}
.ap-pastille { width: 13px; height: 13px; border-radius: 4px; flex: 0 0 13px; }
.ap-trait {
  width: 44px; height: 0; flex: 0 0 44px;
  border-top-width: 3px; border-top-style: solid; border-radius: 2px;
}
.ap-fleche { font-size: 10px; margin-left: -6px; }
.ap-fleche[hidden] { display: none; }

/* ------------------------------------------------------------- photos */

.pn-photo-boite { position: relative; flex: 0 0 44px; }
.pn-photo {
  position: relative; overflow: hidden;
  width: 44px; height: 44px; border-radius: 50%; flex: 0 0 44px;
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; color: #fff; font-size: 15px;
  cursor: pointer; user-select: none;
}
.pn-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pn-photo-voile {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, .5); color: #fff; font-size: 16px;
  opacity: 0; transition: opacity .15s ease;
}
.pn-photo:hover .pn-photo-voile,
.pn-photo.survol .pn-photo-voile { opacity: 1; }
.pn-photo.survol { box-shadow: 0 0 0 2px var(--accent); }
.pn-photo-retirer {
  position: absolute; top: -5px; right: -7px;
  width: 19px; height: 19px; padding: 0; font-size: 10px; line-height: 1;
  border-radius: 50%; background: var(--fond-2); border: 1px solid var(--bord);
  opacity: 0; transition: opacity .15s ease;
}
.pn-photo-boite:hover .pn-photo-retirer { opacity: 1; }

.item-avatar.avec-photo { overflow: hidden; }
.item-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Pas d'overflow:hidden ici : le † des défunts est un ::after qui doit
   pouvoir déborder du cercle. C'est l'image elle-même qu'on arrondit. */
.carte-photo.avec-photo {
  /* La photo mange l'aplat de couleur : on garde le rappel de cercle en cerne. */
  box-shadow: 0 0 0 1px var(--couleur-carte), var(--carte-ombre);
}
.carte-photo img {
  width: 100%; height: 100%; border-radius: 50%;
  object-fit: cover; display: block;
}

/* ------------------------------------------------------- vue « tableau » */

/* ----------------------------------------------------------- vue cercles
 *
 * Écran partagé : l'histoire à gauche, ce que le cercle *est* à droite. Le
 * partage tient jusqu'à 900 px, en dessous les deux moitiés s'empilent — sur
 * un téléphone, deux colonnes de 180 px ne sont plus deux colonnes.
 */
.vue-cercles {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  background: var(--fond-2);
}
.mz-onglets {
  display: flex; gap: 2px; padding: 8px 12px 0; flex-wrap: wrap;
  border-bottom: 1px solid var(--bord); flex: 0 0 auto;
}
.mz-onglet {
  display: flex; align-items: center; gap: 7px;
  background: none; border: 1px solid transparent; border-bottom: none;
  border-radius: 8px 8px 0 0; padding: 7px 13px; cursor: pointer;
  color: var(--texte-doux); font-size: 12px; font-family: inherit;
}
.mz-onglet:hover { color: var(--texte); background: var(--fond-3); }
.mz-onglet.actif {
  color: var(--texte); background: var(--fond); border-color: var(--bord);
  border-bottom: 1px solid var(--fond); margin-bottom: -1px; font-weight: 600;
}
.mz-onglet-pastille {
  width: 9px; height: 9px; border-radius: 50%; background: var(--couleur-cercle);
}
.mz-onglet .nombre {
  font-size: 10px; color: var(--texte-faible); background: var(--fond-3);
  border-radius: 9px; padding: 0 6px;
}

.mz-colonnes { flex: 1; display: flex; min-height: 0; }
.mz-colonne { flex: 1 1 50%; min-width: 0; overflow-y: auto; padding: 16px 18px 40px; }
.mz-histoire { border-right: 1px solid var(--bord); }
.mz-fiche { background: var(--fond); }

.mz-entete { display: flex; align-items: baseline; gap: 10px; margin-bottom: 12px; }
.mz-entete h2 { font-size: 15px; margin: 0; }
.mz-entete-bloc { display: flex; align-items: baseline; gap: 10px; }
.mz-entete-bloc h3 { margin: 0; }
.mz-entete .bouton { margin-left: auto; }
.mz-etat { margin-left: auto; font-size: 10.5px; color: var(--texte-faible); }
.mz-etat.erreur { color: #c0392b; }
.mz-sous-titre { font-size: 11px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--texte-faible); margin: 22px 0 4px; }
.mz-aide { font-size: 11px; color: var(--texte-faible); line-height: 1.5; margin: 6px 0 0; }
.mz-vide { padding: 10px 0; line-height: 1.6; }

.mz-bloc { padding: 14px 0; border-bottom: 1px solid var(--bord); }
.mz-bloc:last-child { border-bottom: 0; }
.mz-bloc h3 {
  font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--texte-faible); margin: 0 0 10px;
}
.mz-bloc textarea {
  width: 100%; background: var(--fond-3); border: 1px solid var(--bord);
  border-radius: 7px; padding: 7px 9px; font-size: 12px; line-height: 1.5;
  resize: vertical; outline: none; font-family: inherit; color: inherit;
}
.mz-bloc textarea:focus { border-color: var(--accent); }

/* Événements : une pastille de date, un titre, un récit, des visages. */
.mz-evenement {
  border-left: 2px solid var(--bord-clair);
  padding: 8px 0 10px 12px; margin-bottom: 4px;
}
.mz-evenement-lie { border-left-color: var(--couleur-type); }
.mz-evenement-lie.revolu { opacity: .6; }
.mz-evenement-haut { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.mz-annee {
  font-variant-numeric: tabular-nums; font-size: 10.5px; font-weight: 600;
  color: var(--texte-faible); background: var(--fond-3);
  border-radius: 9px; padding: 1px 7px; white-space: nowrap;
}
.mz-evenement-titre { font-size: 12.5px; font-weight: 600; }
.mz-lieu { font-size: 10.5px; color: var(--texte-faible); }
.mz-modifier { margin-left: auto; opacity: 0; padding: 2px 6px; }
.mz-evenement:hover .mz-modifier, .mz-lien:hover .mz-modifier { opacity: 1; }
.mz-evenement-texte {
  margin: 5px 0 0; font-size: 12px; line-height: 1.55; color: var(--texte-doux);
  white-space: pre-wrap;
}

/* Une mention : cliquable, à la couleur de la personne ou de le cercle. */
.mz-personnes { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 7px; }
.mz-personne {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--fond-3); border: 1px solid var(--bord); border-radius: 20px;
  padding: 3px 9px; font-size: 11px; color: var(--texte-doux);
  cursor: pointer; font-family: inherit;
}
.mz-personne:hover { border-color: var(--couleur-personne); color: var(--texte); }
.mz-personne.morte { opacity: .62; }
.mz-personne-pastille {
  width: 8px; height: 8px; border-radius: 50%; background: var(--couleur-personne);
  flex: 0 0 8px;
}
.mz-personne-retirable { cursor: default; }
.mz-retirer {
  background: none; border: 0; cursor: pointer; color: var(--texte-faible);
  padding: 0 0 0 2px; font-size: 11px; font-family: inherit;
}
.mz-retirer:hover { color: #c0392b; }

/* Caractéristiques : le nom, une jauge, le chiffre. La jauge sert à comparer
   deux cercles d'un coup d'œil ; le chiffre reste ce qu'on écrit. */


.mz-lien {
  display: flex; align-items: center; gap: 8px; padding: 5px 0;
  border-bottom: 1px dashed var(--bord); font-size: 12px;
}
.mz-lien:last-child { border-bottom: 0; }
.mz-lien.revolu { opacity: .58; }
.mz-lien.orphelin .mz-personne { text-decoration: line-through; }
.mz-lien-type { font-size: 11px; font-weight: 600; }
.mz-lien-fleche { color: var(--texte-faible); }
.mz-revolu {
  font-size: 10px; color: var(--texte-faible); border: 1px solid var(--bord);
  border-radius: 9px; padding: 0 6px;
}

@media (max-width: 900px) {
  .mz-colonnes { flex-direction: column; }
  .mz-colonne { flex: 0 0 auto; overflow-y: visible; }
  .mz-colonnes { overflow-y: auto; }
  .mz-histoire { border-right: 0; border-bottom: 1px solid var(--bord); }
}

.plan-tableau {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  background: var(--fond-2);
}
.tb-onglets {
  display: flex; gap: 2px; padding: 8px 12px 0; flex-wrap: wrap;
  border-bottom: 1px solid var(--bord);
}
.tb-onglet {
  display: flex; align-items: center; gap: 7px;
  background: none; border: 1px solid transparent; border-bottom: none;
  border-radius: 8px 8px 0 0; padding: 7px 13px; cursor: pointer;
  font-size: 12.5px; color: var(--texte-doux); margin-bottom: -1px;
}
.tb-onglet:hover { background: var(--fond-3); }
.tb-onglet.actif {
  background: var(--fond-2); border-color: var(--bord); color: var(--texte);
  font-weight: 600;
}
.tb-onglet .nombre {
  font-size: 10px; color: var(--texte-faible); background: var(--fond-3);
  border-radius: 20px; padding: 1px 7px; font-variant-numeric: tabular-nums;
}
.tb-barre {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px; border-bottom: 1px solid var(--bord);
}
.tb-espace { flex: 1; }
.tb-filtre {
  width: 240px; padding: 6px 10px; font-size: 12px; font-family: inherit;
  background: var(--fond-3); border: 1px solid var(--bord);
  border-radius: 8px; color: var(--texte);
}
.tb-filtre:focus { outline: none; border-color: var(--accent); }
.tb-info { font-size: 11px; color: var(--texte-faible); font-variant-numeric: tabular-nums; }
/* La barre flottante du bas passe par-dessus : on garde de quoi faire
   défiler la dernière ligne au-dessus d'elle. */
.tb-zone { flex: 1; overflow: auto; padding: 0 0 72px; }
.tb-table { border-collapse: separate; border-spacing: 0; width: 100%; font-size: 12px; }
.tb-table th {
  position: sticky; top: 0; z-index: 2;
  background: var(--fond-3); color: var(--texte-doux);
  text-align: left; font-weight: 600; white-space: nowrap;
  padding: 8px 12px; border-bottom: 1px solid var(--bord-clair);
  cursor: pointer; user-select: none;
}
.tb-table th:hover { color: var(--texte); }
.tb-table th.trie { color: var(--accent); }
.tb-fleche { font-size: 9px; }
.tb-table td {
  padding: 6px 12px; border-bottom: 1px solid var(--bord);
  max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--texte-doux);
}
.tb-table tbody tr:hover td { background: var(--fond-3); }
.tb-table tr.cliquable { cursor: pointer; }
.tb-table td.nombre, .tb-table th.nombre { text-align: right; font-variant-numeric: tabular-nums; }
.tb-table td:first-child { color: var(--texte-faible); font-size: 11px; }
.tb-plus { display: block; margin: 14px auto; }

/* ------------------------------------------------- édition par procuration
 *
 * Un administrateur écrit dans l'arbre de quelqu'un d'autre. Le bandeau ne se
 * referme pas : on ne doit jamais oublier chez qui l'on est. Ce qui porterait
 * sur *son* compte à lui (tout télécharger, instantané) sort de la barre —
 * ces gestes n'auraient pas le sens qu'on leur prêterait.
 */
.bandeau-procuration {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 7px 14px; font-size: 12px; line-height: 1.4;
  background: #fdf3d8; color: #7a5c12; border-bottom: 1px solid #e0c169;
}
.bandeau-procuration .bouton { margin-left: auto; }
body.sombre .bandeau-procuration { background: #352c12; color: #e8c96a; border-bottom-color: #6b5620; }
body.en-procuration #btn-telecharger,
body.en-procuration #btn-instantane { display: none; }

/* ------------------------------------------------ arbre partagé (11.B)
 *
 * Le contraire de la procuration : on regarde sans pouvoir écrire. Le serveur
 * refuse déjà tout verbe autre que GET sur `/api/partages/<id>/lecture` — ces
 * règles ne sont donc pas la sécurité, elles sont l'honnêteté. **Une interface
 * qui propose ce que l'API refuse ment**, et laisse croire qu'on a cassé
 * quelque chose alors qu'on a simplement tenté ce qui n'existe pas.
 */
.bandeau-procuration .bouton { margin-left: auto; }
body.en-partage .bandeau-procuration {
  background: #e7f0f7; color: #2d4f6b; border-bottom-color: #a8c4d8;
}
body.sombre.en-partage .bandeau-procuration {
  background: #16242e; color: #93c1de; border-bottom-color: #2c4657;
}
body.en-partage #btn-telecharger,
body.en-partage #btn-instantane,
body.en-partage #btn-nouveau-profil,
body.en-partage #btn-annee,
body.en-partage .rail-actions,
body.en-partage #btn-nouveau-filtre,
body.en-partage .etat-ecriture { display: none; }
/* La liste des personnes reste ouvrable — c'est de la lecture — mais la fiche
   n'y est plus modifiable : `pointer-events` couperait aussi le défilement. */
body.en-partage .sauvegarde { cursor: default; }

/* ------------------------------------------------------ essai sans compte
 *
 * Le contraire de la procuration : ici il ne s'agit pas d'avertir mais
 * d'inviter. Le bandeau est neutre tant que le visiteur regarde, et prend de
 * la voix — sans jamais bloquer — dès qu'il a modifié quelque chose.
 */
.bandeau-essai {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 7px 14px; font-size: 12px; line-height: 1.4;
  background: var(--fond-3); color: var(--texte-faible);
  border-bottom: 1px solid var(--bord);
}
.bandeau-essai-texte { flex: 1; min-width: 200px; }
.bandeau-essai .bouton { flex: 0 0 auto; }
.bandeau-essai-fermer { opacity: .6; }
.bandeau-essai-fermer:hover { opacity: 1; }
.bandeau-essai.presse {
  background: var(--accent-doux); color: var(--accent-fonce);
  border-bottom-color: var(--accent);
}
body.sombre .bandeau-essai.presse { color: #7fd8c6; }

.groupe-essai { display: flex; align-items: center; gap: 6px; }
/* Un essai n'a pas d'instantané à ranger : la copie datée n'a de sens que
   pour quelqu'un qui reviendra la chercher. */
body.en-essai #btn-instantane { display: none; }

/* --------------------------------------------------------- tutoriel (14.C)
 *
 * Le trou du projecteur est fait par une seule ombre de 9999 px : l'élément
 * couvre la cible, et son ombre assombrit tout le reste. Un calque en quatre
 * morceaux aurait quatre positions à tenir d'accord avec celle de la cible.
 */
.tuto { position: fixed; inset: 0; z-index: 90; }
.tuto.tuto-sans-cible { background: rgba(12, 18, 28, .55); }
.tuto-halo {
  position: fixed; border-radius: 10px; pointer-events: none;
  box-shadow: 0 0 0 9999px rgba(12, 18, 28, .55), 0 0 0 2px var(--accent) inset;
  transition: all .18s ease;
}
.tuto-carte {
  position: fixed; width: min(340px, calc(100vw - 24px));
  background: var(--carte-fond); color: var(--texte);
  border: 1px solid var(--bord); border-radius: var(--rayon);
  box-shadow: var(--carte-ombre-forte); padding: 14px 16px 12px;
}
.tuto-compteur { font-size: 11px; color: var(--texte-faible); letter-spacing: .04em; }
.tuto-titre { margin: 2px 0 6px; font-family: var(--police-titre); font-size: 16px; }
.tuto-texte { margin: 0 0 12px; font-size: 12.5px; line-height: 1.5; color: var(--texte-doux); }
.tuto-texte b { color: var(--texte); }
.tuto-actions { display: flex; gap: 6px; align-items: center; }
/* « Plus tard » à gauche, seul : une sortie ne se cherche pas parmi les
   boutons qui font avancer. */
.tuto-passer { margin-right: auto; color: var(--texte-faible); }

/* ---------------------------------------------------------------- carnet
 *
 * Le carnet a **deux places** et un seul jeu de règles : volet à côté du plan
 * (étroit, sommaire replié) ou pleine scène (`.carnet-large`, sommaire en
 * colonne permanente). Ce qui change tient en trois déclarations — le reste
 * est commun, sinon les deux places se mettraient à diverger. */

.volet-carnet {
  width: 400px; flex: 0 0 400px;
  background: var(--fond-2);
  border-left: 1px solid var(--bord);
  min-height: 0; min-width: 0;
  display: flex;
}

.carnet {
  position: relative; /* la liste de complétion se pose dedans */
  display: flex; flex-direction: column;
  flex: 1; min-width: 0; min-height: 0;
  background: var(--fond-2);
}
.carnet-large { background: var(--fond-2); }

.cn-barre {
  display: flex; align-items: center; gap: 6px;
  padding: 7px 8px; flex: 0 0 auto;
  border-bottom: 1px solid var(--bord);
}
.cn-fil {
  flex: 1; min-width: 0; display: flex; align-items: baseline; gap: 5px;
  font-size: 12.5px; white-space: nowrap; overflow: hidden;
}
.cn-fil-chapitre { color: var(--texte-faible); }
.cn-fil-sep { color: var(--texte-faible); }
.cn-fil-note { color: var(--texte); font-weight: 600; overflow: hidden; text-overflow: ellipsis; }
.cn-etat { font-size: 11px; color: var(--texte-faible); white-space: nowrap; }
.cn-etat.modifie { color: var(--texte-doux); }
.cn-etat.ok { color: var(--accent-fonce); }
.cn-etat.erreur { color: #b4483a; }
.cn-btn-mode { white-space: nowrap; }

/* Un avertissement au-dessus du texte, quand il y a lieu d'en donner un.
   Une ligne, pas un bandeau : il ne doit pas manger la place du texte. */
.cn-avertissement {
  flex: 0 0 auto; margin: 0; padding: 5px 10px;
  background: var(--accent-doux); border-bottom: 1px solid var(--bord);
  font-size: 11px; line-height: 1.4; color: var(--accent-fonce);
}

.cn-corps { flex: 1; display: flex; min-height: 0; min-width: 0; position: relative; }

/* sommaire */
.cn-sommaire {
  display: none;
  flex-direction: column; gap: 2px;
  padding: 8px; overflow-y: auto;
  background: var(--fond-3);
  border-right: 1px solid var(--bord);
}
/* Étroit : le sommaire se pose **par-dessus** la note. Le volet fait 400 px ;
   lui prendre 230 pour une liste laisserait 170 px de texte, ce qui n'est plus
   une note mais une colonne de mots. */
.cn-sommaire-ouvert .cn-sommaire {
  display: flex;
  position: absolute; left: 0; top: 0; bottom: 0; width: 78%;
  z-index: 5; box-shadow: var(--ombre-panneau);
}
.carnet-large .cn-sommaire {
  display: flex; position: static; width: 250px; flex: 0 0 250px; box-shadow: none;
}
.carnet-large .cn-btn-sommaire { display: none; }

.cn-sommaire-entete { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; }
.cn-sommaire-entete h3 {
  flex: 1; margin: 0; font-size: 10.5px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--texte-faible);
}
.cn-groupe { margin-bottom: 10px; }
.cn-groupe-titre { display: flex; align-items: center; gap: 4px; margin-bottom: 3px; }
.cn-groupe-titre .nombre {
  font-size: 10.5px; color: var(--texte-faible); font-variant-numeric: tabular-nums;
}
.cn-hors-chapitre {
  font-size: 11px; color: var(--texte-faible); text-transform: uppercase; letter-spacing: .08em;
}
.cn-chap-titre {
  flex: 1; min-width: 0; background: transparent; border: 1px solid transparent;
  border-radius: 5px; padding: 3px 5px; font-size: 12px; font-weight: 600;
}
.cn-chap-titre:hover:not([readonly]) { border-color: var(--bord); }
.cn-chap-titre:focus { background: var(--fond-2); border-color: var(--accent); outline: none; }

.cn-ligne {
  display: flex; align-items: center; gap: 6px; width: 100%;
  background: transparent; border: 0; border-radius: 6px;
  padding: 6px 8px; text-align: left; cursor: pointer; color: var(--texte-doux);
  font-size: 12.5px;
}
.cn-ligne:hover { background: var(--fond-2); color: var(--texte); }
.cn-ligne.actif { background: var(--accent-doux); color: var(--accent-fonce); font-weight: 600; }
.cn-ligne-titre { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cn-ligne-cites { font-size: 10.5px; color: var(--texte-faible); white-space: nowrap; }
.cn-nouvelle-note { width: 100%; margin-top: 4px; }
.cn-danger:hover { color: #b4483a; border-color: #e0b4ac; }

/* la note */
.cn-note { flex: 1; display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.cn-titre {
  flex: 0 0 auto; margin: 10px 12px 6px; padding: 4px 6px;
  background: transparent; border: 1px solid transparent; border-radius: 6px;
  font-family: var(--police-titre); font-size: 17px; font-weight: 600;
}
.cn-titre:hover:not([readonly]) { border-color: var(--bord); }
.cn-titre:focus { background: var(--fond-3); border-color: var(--accent); outline: none; }

.cn-outils {
  flex: 0 0 auto; display: flex; align-items: center; gap: 2px;
  padding: 0 10px 6px; overflow-x: auto; scrollbar-width: thin;
}
.cn-outil { min-width: 26px; height: 26px; font-size: 11.5px; padding: 0 5px; flex: 0 0 auto; }
.cn-outil-gras { font-weight: 800; }
.cn-outil-italique { font-style: italic; font-family: var(--police-titre); }
.cn-outil-barre { text-decoration: line-through; }
.cn-outil-balise { color: var(--accent-fonce); font-weight: 700; }
.cn-outils-sep { width: 1px; height: 16px; background: var(--bord); margin: 0 3px; flex: 0 0 auto; }

.cn-source {
  flex: 1; min-height: 0; resize: none;
  margin: 0 10px; padding: 10px 12px;
  background: var(--fond-3); border: 1px solid var(--bord); border-radius: var(--rayon);
  font-size: 13.5px; line-height: 1.65; tab-size: 2;
}
.cn-source:focus { outline: none; border-color: var(--accent); background: var(--fond-2); }

.cn-rendu {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: 2px 14px 10px; font-size: 13.5px; line-height: 1.65; color: var(--texte);
}

.cn-pied {
  flex: 0 0 auto; display: flex; align-items: center; gap: 6px;
  padding: 7px 10px; border-top: 1px solid var(--bord);
}
.cn-pied-aide { flex: 1; min-width: 0; font-size: 10.5px; color: var(--texte-faible); }
.cn-chapitre-choix { font-size: 11.5px; max-width: 45%; }

.cn-vide { padding: 26px 20px; color: var(--texte-doux); font-size: 12.5px; line-height: 1.6; }
.cn-vide-titre { font-family: var(--police-titre); font-size: 16px; color: var(--texte); margin: 0 0 8px; }
.cn-vide .bouton { margin-top: 12px; }

/* complétion « / » */
.cn-suggestions {
  position: absolute; z-index: 20; margin: 0; padding: 4px; list-style: none;
  min-width: 230px; max-width: 320px;
  background: var(--fond-2); border: 1px solid var(--bord-clair);
  border-radius: var(--rayon); box-shadow: var(--ombre-panneau);
}
.cn-suggestions li {
  display: flex; align-items: baseline; gap: 6px;
  padding: 5px 7px; border-radius: 5px; cursor: pointer; font-size: 12.5px;
}
.cn-suggestions li.survol { background: var(--accent-doux); }
.cn-sug-ico { flex: 0 0 auto; font-size: 11px; }
.cn-sug-nom { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cn-sug-detail { font-size: 10.5px; color: var(--texte-faible); white-space: nowrap; }

/* --------------------------------------------------------------- markdown */

.cn-rendu h1, .cn-rendu h2, .cn-rendu h3,
.cn-rendu h4, .cn-rendu h5, .cn-rendu h6 {
  font-family: var(--police-titre); margin: 16px 0 6px; line-height: 1.3;
}
.cn-rendu h1 { font-size: 19px; }
.cn-rendu h2 { font-size: 16.5px; }
.cn-rendu h3 { font-size: 14.5px; }
.cn-rendu h4, .cn-rendu h5, .cn-rendu h6 { font-size: 13.5px; color: var(--texte-doux); }
.cn-rendu p { margin: 8px 0; }
.cn-rendu ul, .cn-rendu ol { margin: 8px 0; padding-left: 22px; }
.cn-rendu li { margin: 2px 0; }
.cn-rendu blockquote {
  margin: 10px 0; padding: 4px 12px;
  border-left: 3px solid var(--accent); color: var(--texte-doux); font-style: italic;
}
.cn-rendu hr { border: 0; border-top: 1px solid var(--bord); margin: 14px 0; }
.cn-rendu code {
  background: var(--fond-3); border: 1px solid var(--bord);
  border-radius: 4px; padding: 0 4px; font-size: 12px;
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
}
.cn-rendu pre.md-code {
  margin: 10px 0; padding: 9px 11px; overflow-x: auto;
  background: var(--fond-3); border: 1px solid var(--bord); border-radius: var(--rayon);
}
.cn-rendu pre.md-code code { background: none; border: 0; padding: 0; }
.cn-rendu a { color: var(--accent-fonce); }
/* Un tableau large défile **dans sa boîte** : sans ça, c'est la note entière
   qui se met à glisser latéralement, et le texte autour part avec. */
.md-table-boite { overflow-x: auto; margin: 10px 0; }
.md-table { border-collapse: collapse; font-size: 12.5px; min-width: 100%; }
.md-table th, .md-table td {
  border: 1px solid var(--bord); padding: 5px 8px; text-align: left; vertical-align: top;
}
.md-table th { background: var(--fond-3); font-weight: 600; }

/* les balises */
.balise {
  display: inline-flex; align-items: baseline; gap: 3px;
  background: var(--accent-doux); border: 1px solid transparent;
  border-radius: 5px; padding: 0 5px; margin: 0 1px;
  color: var(--accent-fonce); font: inherit; font-size: .95em; font-weight: 600;
  cursor: pointer; vertical-align: baseline;
}
.balise:hover { border-color: var(--accent); }
.balise-ico { font-size: .8em; opacity: .8; }
/* Une cible supprimée : la note garde ce qu'elle disait, mais elle ne mène
   plus nulle part — et ça se voit. */
.balise-perdue {
  background: var(--fond-3); color: var(--texte-faible);
  border-style: dashed; border-color: var(--bord-clair);
  text-decoration: line-through; cursor: not-allowed;
}
.balise-visee {
  outline: 2px solid var(--accent); outline-offset: 2px;
  background: var(--accent); color: #fff;
}

/* citations, dans la fiche d'une personne */
/* Une section repliable de la fiche : le titre prend la place du `<h3>` et
   porte le chevron. Les citations du carnet s'en servent, et toute autre
   section qui deviendrait trop longue. */
.pn-repliable > summary {
  cursor: pointer; list-style: none;
  font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--texte-faible);
}
.pn-repliable > summary::-webkit-details-marker { display: none; }
/* Le chevron dit d'un coup d'œil qu'il y a quelque chose dessous — et de quel
   côté. Sans lui, un `<summary>` déshabillé de sa flèche n'a plus l'air
   cliquable du tout. */
.pn-repliable > summary::before { content: '▸ '; letter-spacing: 0; }
.pn-repliable[open] > summary::before { content: '▾ '; }
.pn-repliable[open] > summary { margin-bottom: 8px; }
.pn-repliable > summary:hover { color: var(--texte-doux); }
.pn-repli-titre { display: inline-flex; align-items: baseline; gap: 6px; }
.pn-repli-nombre {
  font-size: 10.5px; color: var(--texte-faible); font-variant-numeric: tabular-nums;
}
.pn-cit-chapitre {
  margin: 10px 0 4px; font-size: 10.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--texte-faible);
}
.pn-cit-note { margin-bottom: 8px; }
.pn-cit-note-titre {
  display: flex; align-items: baseline; gap: 6px;
  font-size: 12px; font-weight: 600; color: var(--texte-doux); margin-bottom: 3px;
}
.pn-cit-extrait {
  display: block; width: 100%; text-align: left;
  background: var(--fond-3); border: 1px solid var(--bord); border-radius: 6px;
  padding: 5px 8px; margin: 3px 0; cursor: pointer;
  font-size: 12px; line-height: 1.5; color: var(--texte-doux);
}
.pn-cit-extrait:hover { border-color: var(--accent); color: var(--texte); }
.pn-cit-extrait b { color: var(--accent-fonce); }

/* ------------------------------------------------------------ responsive */

@media (max-width: 1180px) {
  .rail { position: absolute; left: 0; top: 0; bottom: 0; z-index: 18; box-shadow: var(--ombre-panneau); }
  .fil-ariane { display: none; }
}
@media (max-width: 860px) {
  .panneau { position: absolute; right: 0; top: 0; bottom: 0; z-index: 19; width: 300px; flex-basis: 300px; }
}

/* Le carnet en volet mange la scène avant tout le monde : à 1180 px il reste
   large, à 1040 il passe par-dessus le plan plutôt que de le réduire à une
   bande. Un plan de 200 px de large ne montre plus de réseau — autant assumer
   le recouvrement et laisser une sortie visible (le ✕ de son en-tête). */
@media (max-width: 1180px) {
  .volet-carnet { width: 360px; flex-basis: 360px; }
}
@media (max-width: 1040px) {
  .volet-carnet {
    position: absolute; right: 0; top: 0; bottom: 0; z-index: 20;
    width: 380px; flex-basis: 380px; box-shadow: var(--ombre-panneau);
  }
}

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--bord-clair); border-radius: 6px; border: 2px solid var(--fond-2); }
::-webkit-scrollbar-thumb:hover { background: var(--texte-faible); }

/* ------------------------------------------------- compte et téléphone */

.groupe-compte { display: flex; align-items: center; gap: 6px; }
.compte {
  font-size: 11px; color: var(--texte-faible);
  max-width: 140px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#aide-plafonds { margin: 7px 0 0; }

/* Boutons qui n'existent que sur téléphone : sur écran large, les deux volets
   sont déjà là et n'ont besoin ni d'être ouverts ni d'être fermés. */
.btn-telephone { display: none; }
.btn-fermer-volet { margin-left: auto; align-self: center; margin-right: 6px; }

/* L'en-tête du tiroir de gauche a disparu au lot 13.A, y compris son balisage.
 * Il ne servait que sur téléphone, où il portait le mot « Menu » et une croix
 * — mesuré **341 × 61 px, collants**, sur un tiroir de 694 px de haut. Neuf
 * pour cent de la hauteur utile, en permanence, pour un titre qu'on n'a pas
 * besoin de lire et une sortie qui existe ailleurs. */

/* ------------------------------------------------------------ téléphone
 *
 * L'arbre s'édite au doigt depuis le lot 8 : l'appui long ouvre le même menu
 * que le clic droit (fiche, lien, fond), « ＋ Profil » crée quelqu'un sans
 * viser, et un lien armé se termine d'une simple touche. Restent à la souris
 * le glisser d'une fiche et la poignée ＋.
 *
 * Les deux volets deviennent des tiroirs plein écran, ouverts par ☰ et 👤.
 *
 * **Repris le 13/08/2026 (lot 11.C).** La barre du haut réclamait 512 px de
 * commandes dans 375 px d'écran : les quatre derniers boutons débordaient à
 * droite, dont le ☰ lui-même, à 75 px hors de l'écran. Le rail — sauvegardes,
 * vues, liens, cercles, options — était donc entier et strictement
 * inatteignable, et c'est ce qu'on nous a signalé.
 *
 * Depuis, la barre ne garde que de quoi **naviguer** : la marque, ☰, 👤 (et
 * « Créer un compte » pour un visiteur d'essai). Tout le reste descend dans le
 * rail, en tête, par `public/js/telephone.js` — déplacé et non dupliqué, pour
 * qu'il n'y ait jamais deux boutons pour un même geste.
 */
@media (max-width: 760px) {
  .btn-telephone { display: inline-flex; }

  .barre-haut { gap: 8px; padding: 7px 10px; flex-wrap: nowrap; }
  /* Un plancher, et non `min-width: 0`. Mesuré le 14/08/2026, boutons d'essai
     encore dans la barre : la marque tombait à **9 px** de large — ni épée, ni
     nom d'univers. `.marque-univers` sait déjà se rogner tout seul ; ce plancher
     fait que c'est lui qui perd des lettres, et non l'ensemble qui disparaît. */
  .marque { min-width: 5.5rem; }
  .marque-titre { display: none; }
  .marque-univers { max-width: 40vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* `flex: none` sur les deux boutons de tiroir : sans ça, un nom d'univers
     long les comprimerait jusqu'à l'illisible plutôt que de se laisser rogner
     lui-même — et c'est lui qui peut se permettre de perdre des lettres. */
  .barre-controles { margin-left: auto; gap: 6px; flex: none; }
  /* La marque doit rester lisible. Mesuré le 14/08/2026 avec les boutons
     d'essai encore dans la barre : elle tombait à **9 px** de large — ni épée,
     ni nom d'univers. Un plancher, pour que ce soit le nom qui perde des
     lettres et non l'ensemble qui disparaisse. */
  .marque { min-width: 5.5rem; }
  /* ☰ et 👤 sont la navigation entière de cet écran : ils méritent la même
     cible que le reste. `flex: none` en plus, pour qu'un nom d'univers long
     les comprime jamais — c'est lui qui peut se permettre de perdre des
     lettres, pas eux. */
  .barre-haut .bouton { min-height: 40px; }
  #btn-panneau, #btn-compte { flex: none; min-width: 40px; }

  /* ☰ s'en va (13.A). Signalé le 14/08/2026 : « retire le kebab menu, qui
     prend les mêmes options que la petite icône de tête ». C'est exact — il
     ouvrait le même tiroir que 👤, et que « ⛨ Filtres » de la barre du bas.
     Trois boutons pour un tiroir, sur l'écran où la place manque le plus.
     Restent les deux qui disent *où* ils mènent : ⛨ aux filtres, 👤 au compte. */
  #btn-rail { display: none; }
  /* Ce qui ne sert pas à naviguer quitte la barre. `telephone.js` le descend
     dans le rail ; ces règles restent la ceinture, si le script n'a pas encore
     tourné — sauf pour ☰ et 👤, qui doivent tenir dans tous les cas. */
  .barre-haut .champ-couleur,
  .barre-haut #lien-document,
  .barre-haut #btn-vue-generale,
  .barre-haut #btn-annee,
  .barre-haut #btn-theme,
  .barre-haut #lien-admin,
  .barre-haut #lien-donnees,
  .barre-haut #btn-deconnexion,
  .barre-haut .etat-ecriture,
  .barre-haut .compte { display: none; }

  /* Éteints tout court, pas déplacés. Un `.zip` de toutes ses sauvegardes sur
     un téléphone ne mène nulle part, et un instantané se prend quand on
     travaille. « Vos données » (🛡) reste, et c'est le vrai endroit pour sortir
     ses données. */
  #btn-telecharger,
  #btn-instantane { display: none; }

  /* L'ordre du tiroir, refait pour un pouce.
   *
   * On l'ouvre pour filtrer — les cercles et les types de liens passent donc en
   * tête, et les réglages de compte à la fin. L'ordre du HTML, lui, ne bouge
   * pas : c'est celui d'un écran large, où tout est visible d'un coup.
   *
   * Trois blocs n'ont pas d'identifiant et se désignent par ce qu'ils
   * contiennent. Là où `:has()` manquerait, eux seuls resteraient à leur place
   * du HTML : l'ordre serait moins bon, rien ne casserait. */
  .rail { display: flex; flex-direction: column; }
  #bloc-cercles { order: 1; }
  #bloc-liens { order: 2; }
  .rail > section:has(#liste-vues) { order: 3; }
  .rail > section:has(#options-vue) { order: 4; }
  .rail > section:has(#liste-sauvegardes) { order: 6; }
  #bloc-partages { order: 7; }
  .rail > section:has(#stats) { order: 9; }
  #bloc-compte { order: 10; }
  #bloc-telephone { order: 11; }

  /* Les commandes descendues : en grille, avec des cibles qu'un doigt atteint
     sans viser. 44 px est la hauteur en dessous de laquelle on tape à côté. */
  #accueil-telephone,
  #accueil-compte {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
    gap: 8px; align-items: stretch;
  }
  #accueil-telephone .bouton { min-height: 44px; justify-content: center; }
  #accueil-telephone .champ { flex-direction: column; align-items: stretch; gap: 3px; }
  #accueil-telephone .champ select { min-height: 44px; }

  /* Le bloc « Votre compte » (13.B). Une colonne, pleine largeur : ce sont
     quatre gestes rares et distincts — voir son compte, administrer, sortir ses
     données, se déconnecter — et non une grille de réglages à parcourir. */
  #accueil-compte { grid-template-columns: 1fr; }
  #accueil-compte .bouton {
    min-height: 46px; justify-content: flex-start; gap: 8px; font-size: 14px;
  }
  /* C'est ici, et ici seulement, que ⚙ 🛡 ⏻ disent leur nom. */
  #accueil-compte #lien-admin .lib,
  #accueil-compte #lien-donnees .lib,
  #accueil-compte #btn-deconnexion .lib { display: inline; }
  #accueil-compte .bouton .ico { margin-right: 2px; font-size: 16px; opacity: 1; }
  #accueil-compte #btn-deconnexion { border-color: var(--bord); color: var(--texte-faible); }
  /* L'adresse du compte n'est pas un bouton : elle occupe sa propre ligne. */
  #accueil-compte .compte { max-width: none; font-size: 13px; padding: 2px 0; }
  /* « Créer un compte » et « Se connecter », descendus ici depuis la barre du
     haut. Ils se partagent la ligne : c'est tout ce que voit un visiteur sans
     compte qui touche 👤, et il n'a rien à chercher. */
  #accueil-compte .groupe-essai { gap: 8px; }
  #accueil-compte .groupe-essai .bouton { flex: 1; min-height: 46px; justify-content: center; }

  /* Le bandeau d'essai : le texte, pas le bouton.
   *
   * Il portait la troisième « Créer un compte » de l'écran, et réclamait 103 px
   * de haut sur 812 — 13 % de l'écran pour un rappel. Le bouton s'en va tant
   * que le bandeau est calme : le 👤 de la barre est à un doigt, et le texte
   * dit déjà quoi faire.
   *
   * Il revient dès que le bandeau est `.presse`, c'est-à-dire dès qu'on a
   * modifié quelque chose et qu'il y a du travail à perdre. C'est exactement la
   * distinction sur laquelle ce bandeau a été construit — discret tant qu'on
   * regarde, insistant dès qu'on écrit — et non une exception de plus. */
  .bandeau-essai { padding: 6px 10px; font-size: 11.5px; gap: 8px; }
  .bandeau-essai:not(.presse) .bouton-primaire { display: none; }
  .bandeau-essai.presse .bouton-primaire { min-height: 36px; }
  .bandeau-essai-texte { min-width: 0; }
  .bandeau-essai-fermer { min-width: 36px; min-height: 36px; }

  /* Cibles tactiles dans le rail.
   *
   * Mesuré le 13/08/2026, tiroir ouvert sur 375 px : une entrée de légende
   * faisait **24 px** de haut, la poignée ＋ des filtres 28×19, une puce d'axe
   * 52×21, la case « masquer les liens révolus » 13×13. Ce sont exactement les
   * commandes qu'on nous disait ne pas pouvoir utiliser — atteignables, mais
   * pas touchables. En dessous de 40 px, un doigt tape à côté.
   *
   * On agrandit par le remplissage plutôt que par la police : la légende doit
   * pouvoir montrer vingt cercles sans devenir un livre. */
  /* « ＋ Nouveau cercle », « ＋ Nouveau type » : 26 px
     de haut et 11 px de police. Ce sont les « options d'ajouts » qu'on nous
     disait inutilisables — elles étaient là, simplement trop fines pour un
     doigt. */
  .rail .rail-actions { gap: 6px; }
  .rail .rail-actions .bouton { min-height: 44px; padding: 8px 6px; font-size: 12.5px; }
  .rail .legende li { min-height: 40px; padding: 8px 8px; }
  .rail .liste-vues li,
  .rail .liste-sauvegardes li { min-height: 44px; }
  .rail .axe-puce { min-height: 36px; padding: 6px 12px; font-size: 12px; }
  .rail .btn-entete { min-width: 40px; min-height: 40px; font-size: 16px; }
  .rail .option { min-height: 40px; }
  .rail .option input[type='checkbox'] { width: 20px; height: 20px; flex: 0 0 20px; }
  /* Les options numériques d'une vue (taille des cartes, écartement…). */
  .rail .option input[type='number'] { min-height: 38px; font-size: 16px; }
  /* Les libellés d'aide occupaient un tiers du tiroir. On les garde — ils
     enseignent l'appui long — mais lisibles plutôt que minuscules. */
  .rail .rail-aide { font-size: 11.5px; }

  /* Le volet de droite, aux mêmes mesures. `font-size: 16px` sur la recherche
     n'est pas une coquetterie : en dessous, iOS zoome sur le champ au premier
     appui et laisse la page décadrée. */
  .panneau #recherche { min-height: 42px; font-size: 16px; }
  .panneau #selecteur-groupe { min-height: 42px; }
  #btn-fermer-panneau { min-width: 40px; min-height: 40px; font-size: 16px; }

  /* La fiche, éditable au doigt.
   *
   * Mesuré le 13/08/2026, fiche ouverte sur 375 px : les champs de saisie
   * faisaient **21 à 29 px**, le ✕ de la fiche 30. Le
   * `font-size: 16px` sur tout ce qui se saisit est là pour iOS, qui zoome sur
   * un champ plus petit et laisse la page décadrée — impossible à récupérer
   * d'une main. */
  .panneau .champ-edit input,
  .panneau .champ-edit select,
  .panneau .champ-edit textarea,
  .panneau .champ-suggere input { min-height: 40px; font-size: 16px; }
  .panneau .pn-fermer { min-width: 40px; min-height: 40px; }
  /* La liste des personnes : une ligne se touche sans viser. */
  .panneau .item-personne { min-height: 48px; }

  /* Tiroirs : hors écran par défaut, amenés par-dessus la scène au clic. */
  .rail, .panneau {
    position: absolute; top: 0; bottom: 0; z-index: 30;
    width: 100%; flex-basis: 100%; max-width: none;
    margin-left: 0; box-shadow: var(--ombre-panneau);
    transition: transform .22s ease;
  }
  .rail { left: 0; transform: translateX(-100%); }
  .panneau { right: 0; transform: translateX(100%); }
  .rail.ouvert, .panneau.ouvert { transform: translateX(0); }
  .rail.replie { margin-left: 0; }
  /* La barre du bas flotte maintenant par-dessus : sans cette réserve, le
     dernier bloc du tiroir se termine dessous et ne se lit jamais en entier. */
  .rail, .panneau { padding-bottom: 72px; }

  /* Tiroirs fermés : hors de l'écran, mais ils comptaient encore dans la
     largeur de défilement — on pouvait faire glisser la page vers le vide. */
  .corps { overflow: hidden; }

  /* La barre basse sert au doigt, mais elle ne doit pas manger le tiers de
     l'écran : les commandes de cadrage passent en icônes, seul « ＋ Profil »
     — le seul bouton qui écrit — garde son libellé.
   *
   * **`z-index: 40`, au-dessus des tiroirs (13.A).** Mesuré le 14/08/2026,
   * tiroir ouvert : `elementFromPoint` sur « ⛨ Filtres » ne rendait plus le
   * bouton mais le tiroir posé par-dessus. Tant que le tiroir avait sa barre et
   * sa croix, cela ne se voyait pas ; sans elles, la barre du bas est l'une des
   * deux sorties, et une sortie recouverte n'est pas une sortie. */
  .barre-basse {
    flex-wrap: nowrap; gap: 2px; padding: 5px 7px;
    max-width: calc(100vw - 20px); z-index: 40;
  }
  /* 40 px de haut, comme le reste : c'est ici que vit « ＋ Profil », le seul
     bouton de cette barre qui écrit. Le curseur de zoom passe de 16 à 34 px —
     en dessous, on attrape sa poignée une fois sur deux. */
  .barre-basse .bouton { padding: 6px 7px; min-height: 40px; }
  /* « Carnet » perd son libellé ici, et pas ailleurs.
   *
   * Mesuré le 15/08/2026 sur 375 px : la barre tenait à 354 px pour 354
   * disponibles — au caractère près. Le bouton du carnet, libellé compris,
   * la faisait déborder de 48 px, et ce qui débordait était le curseur de
   * zoom, hors de l'écran et donc perdu. En pastille, ✎ tient dans ce qui
   * reste ; « ＋ Profil » et « ⛨ Filtres » gardent les leurs, ce sont les deux
   * seuls dont le geste n'est pas devinable à l'icône. */
  .barre-basse #btn-ajuster .lib,
  .barre-basse #btn-carnet .lib,
  .barre-basse #btn-focus .lib { display: none; }
  .barre-basse .bouton .ico { margin-right: 0; }
  #btn-nouveau-profil { flex: 0 0 auto; }
  /* 60 px de large et non 68 : les huit derniers pixels de débordement, une
     fois « ✎ » réduit à sa pastille. C'est la **largeur** qui cède, jamais la
     hauteur — 34 px reste ce en dessous de quoi on rate la poignée. */
  #zoom-curseur { width: 60px; height: 34px; }
  .separateur-vertical { margin: 0 1px; }

  /* Le carnet, au doigt.
   *
   * En volet il prend tout l'écran : à 375 px il n'y a pas de « à côté du
   * plan », et un carnet de 380 px sur un écran de 375 est un carnet qui
   * déborde. Le ✕ de son en-tête est donc la sortie, et il reste visible.
   *
   * Le sommaire repasse en calque **même en pleine page** : une colonne de
   * 250 px sur 375, c'est les deux tiers de l'écran pour une liste. */
  .volet-carnet {
    position: absolute; left: 0; right: 0; top: 0; bottom: 0;
    width: 100%; flex-basis: 100%; z-index: 32;
    border-left: 0; padding-bottom: 0;
  }
  .carnet-large .cn-sommaire { display: none; }
  .carnet-large.cn-sommaire-ouvert .cn-sommaire {
    display: flex; position: absolute; width: 84%; box-shadow: var(--ombre-panneau);
  }
  .carnet-large .cn-btn-sommaire { display: inline-flex; }

  .cn-barre .bouton { min-height: 38px; }
  .cn-outil { min-width: 34px; height: 34px; font-size: 12.5px; }
  .cn-ligne { min-height: 42px; }
  .cn-chap-titre, .cn-titre { min-height: 38px; }
  /* 16 px : en dessous, iOS zoome sur le champ dès qu'on y pose le doigt, et
     la note se retrouve à moitié hors de l'écran. */
  .cn-source { font-size: 16px; }
  .cn-suggestions { min-width: 60vw; max-width: 88vw; }
  .cn-suggestions li { min-height: 40px; align-items: center; }
  .cn-chapitre-choix { min-height: 36px; }
}

/* ==========================================================================
   Le plan collectif (lot 17)

   La page `/collectif.html` réemploie tout ce qui précède — `.plan`, `.carte`,
   `.rail`, `.legende`, `.menu-contextuel`. Ne sont ajoutés ici que les objets
   qui n'existaient pas : le rail des membres, le panneau « qui l'a », et le
   panneau de geste.

   **Aucune ombre floue de plus sur les cartes.** Le lot 16.I a ramené le plan
   de 665 couches floues à 309 pour qu'il cesse de ramer ; marquer les
   divergences par un halo aurait rendu tout ce travail. Un trait, donc, et une
   pastille — les deux se peignent sans flou.
   ========================================================================== */

.liste-membres { list-style: none; margin: 0; padding: 0; }
.membre {
  display: flex; align-items: center; gap: 7px;
  padding: 4px 6px; border-radius: 6px; font-size: 11.5px;
}
.membre:hover { background: var(--fond-3); }
.membre input { margin: 0; flex: 0 0 auto; }
.membre-pastille { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 9px; }
.membre-qui { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.membre-nom {
  min-width: 0; text-align: left; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--texte); font: inherit;
}
.membre-nom:hover { color: var(--accent); }
/* L'arbre regardé, sous le nom. Toujours dit, toujours changeable : sans lui, un
   plan pourrait montrer une autre campagne que celle qu'on croit lire — et un
   geste irait y écrire. */
.membre-arbre {
  min-width: 0; text-align: left; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--texte-faible); font: inherit; font-size: 10px;
  border-bottom: 1px dotted var(--bord-clair); align-self: flex-start; max-width: 100%;
}
.membre-arbre:hover { color: var(--accent); }
/* Un membre dont aucun arbre n'a été travaillé : il reste au rail, sinon il
   disparaîtrait de la table sans explication — et c'est de sa ligne qu'on lui
   choisit un arbre à la main. */
.membre-absent { opacity: .55; }
.membre-absent .membre-arbre { font-style: italic; }
.membre-compte {
  color: var(--texte-faible); font-size: 10.5px; font-variant-numeric: tabular-nums;
}

/* Ce que la superposition révèle, dit sur la carte elle-même. */
.carte.partielle { border-style: dashed; }
.carte.desaccord .carte-nom::after {
  content: ' ⚖'; color: var(--texte-faible); font-size: 10px;
}

/* Le panneau de droite : qui a quoi. */
.pn-titre { font-size: 13px; font-weight: 600; }
.pn-aide { margin: 0 0 9px; font-size: 11.5px; color: var(--texte-faible); line-height: 1.5; }
.pn-sous-titre {
  margin: 14px 0 6px; font-size: 10px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--texte-faible);
}
.pn-porteurs { list-style: none; margin: 0 0 10px; padding: 0; }
.pn-porteurs li {
  display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap;
  padding: 3px 0; font-size: 11px; border-bottom: 1px solid var(--bord);
}
.pn-porteur-qui { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.pn-porteurs code { font-size: 10px; color: var(--texte-faible); }
.pn-autre { font-size: 10px; color: var(--accent); }

.pn-candidat {
  border: 1px solid var(--bord); border-radius: 8px;
  padding: 8px 9px; margin-bottom: 8px; background: var(--fond-3);
}
.pn-candidat-noms {
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
  font-size: 11.5px; margin-bottom: 3px;
}
.pn-score {
  font-size: 10px; padding: 1px 5px; border-radius: 999px;
  background: var(--fond-2); border: 1px solid var(--bord);
  font-variant-numeric: tabular-nums;
}
.pn-candidat-qui { font-size: 10px; color: var(--texte-faible); }
.pn-candidat-verdict { font-size: 10.5px; color: var(--accent); margin-top: 3px; }
.pn-candidat-actions { display: flex; gap: 5px; flex-wrap: wrap; margin-top: 7px; }

/* Le panneau de geste : un lot, posé depuis le plan. */
.flottant.flottant-geste { width: 372px; }
.gc-portee { display: block; font-size: 10.5px; color: var(--texte-faible); margin-top: 2px; }
.gc-bascule { display: flex; align-items: center; gap: 7px; font-size: 11.5px; }
.gc-rapport { border-top: 1px solid var(--bord); padding-top: 9px; }
.gc-lignes { list-style: none; margin: 0; padding: 0; max-height: 30vh; overflow: auto; }
.gc-lignes li {
  display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap;
  padding: 3px 0; font-size: 11px; border-bottom: 1px solid var(--bord);
}
.gc-qui { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.gc-etat { font-size: 10px; padding: 1px 5px; border-radius: 999px; border: 1px solid var(--bord); }
.gc-quoi { flex-basis: 100%; font-size: 10px; color: var(--texte-faible); }
.gc-cree .gc-etat { color: #2f7d52; border-color: #a8d3ba; }
.gc-mis_a_jour .gc-etat { color: #2f6f9e; border-color: #a9c9e0; }
.gc-inchange .gc-etat { color: var(--texte-faible); }
.gc-refuse .gc-etat { color: #b03a2e; border-color: #e0b0a9; }
body.sombre .gc-cree .gc-etat { color: #7fd6b2; border-color: #2b5a49; }
body.sombre .gc-mis_a_jour .gc-etat { color: #8fc0e8; border-color: #2c4356; }
body.sombre .gc-refuse .gc-etat { color: #e0a196; border-color: #5b3636; }

/* Le curseur de seuil : une ligne, pas une grille de formulaire. */
#bloc-rapprochement .option { gap: 9px; }
#bloc-rapprochement input[type="range"] { flex: 1; min-width: 0; }
#seuil-valeur { font-variant-numeric: tabular-nums; font-size: 11px; }

/* Les deux tiroirs du plan collectif.
 *
 * L'application les ouvre depuis sa barre basse et son `telephone.js`, qui
 * déplacent les commandes dans le rail. Cette page-là n'a ni l'un ni l'autre :
 * ses deux boutons restent donc dans la barre du haut, à toutes les largeurs,
 * et c'est ce que ces trois règles disent. Sans elles, sous 760 px, le rail
 * était traduit hors de l'écran **sans plus rien pour l'y ramener** — le même
 * défaut que le lot 11.C avait réparé dans l'application. */
/* Les menus du plan collectif portent des détails plus longs qu'ailleurs — le
   nom d'un arbre suivi de son compte de fiches et de son état. Dans les 280 px
   du menu ordinaire, « Westeros » se voyait rogné en « Wes… » au profit de
   « ouvert par son propriétaire ». On élargit ici, et ici seulement. */
body.collectif .menu-contextuel { min-width: 264px; max-width: 340px; }

body.collectif #btn-panneau { display: none; }
@media (max-width: 860px) {
  body.collectif #btn-panneau { display: inline-flex; }
}
@media (max-width: 760px) {
  body.collectif #btn-rail { display: inline-flex; }
}

/* Les blocs du plan collectif portent des identifiants à eux —
   `#bloc-types-collectif`, `#bloc-cercles-collectif`, `#releve-plan` — et non
   ceux du rail de l'application. Ce n'est pas une coquetterie : sous 760 px,
   `#bloc-cercles { order: 1 }` et `#bloc-liens { order: 2 }` remontent ces deux
   blocs en tête du tiroir. C'est le bon ordre pour l'arbre d'une personne, et
   le mauvais pour un plan collectif, où l'on cherche d'abord ses membres. */
