/* Balisia — feuille de style commune.
 *
 * Les valeurs viennent de la charte graphique Balisia (artefact « Design
 * System »), pas d'un choix refait ici : `ink-900` et `brand-gold` sont les
 * deux couleurs exactes du logo Experientiel.
 *
 * Deux règles de la charte à respecter en faisant évoluer ce fichier :
 *   — l'or est un accent (bouton principal, sélection, focus), jamais un aplat ;
 *   — les couleurs de catégorie et de statut ne servent QUE sur la carte et les
 *     badges, pour que l'œil les reconnaisse instantanément.
 *
 * Pas de thème sombre : l'outil est consulté en extérieur en plein jour
 * (chantier, sentier), le fond clair à fort contraste sert mieux cet usage.
 */

:root {
  --surface-100: #FFFFFF;
  --surface-200: #F4F2EE;
  --surface-300: #E7E3DB;
  --ink-900: #191715;
  --ink-600: #5B564F;
  --ink-400: #8B857A;
  /* L'or du logo officiel livré le 29.09.2026, au pixel près. L'interface
     s'aligne sur la marque et non l'inverse : on ne recolore pas un logo pour
     qu'il tombe sur une variable CSS. La luminance est la même qu'avant
     (5,26:1 contre 5,28:1 pour --brand-gold-ink), seule la teinte change :
     moins orangée, plus proche du jaune de la signalisation pédestre. */
  --brand-gold: #f3bb44;
  --brand-gold-ink: #5C4400;
  /* La face lisible d'un panneau, sur le plan d'implantation. Plus vive que
     l'or de la marque : c'est un repère de lecture sur fond sombre, pas une
     couleur de charte, et l'or s'y éteignait. */
  --face-lisible: #FFD400;

  --route-closed: #B0392E;
  --route-deviation: #3F7D4A;
  --category-a: #AF7691;
  --category-b: #F63F94;
  --category-c: #5BB3C9;

  --info: #3E6FA6;
  --success: #3F7D4A;
  --warning: #B8720F;
  --danger: #A63328;

  --font-sans: "Open Sans", -apple-system, "Segoe UI", sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", monospace;

  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-6: 24px;
  --space-8: 32px;

  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 14px;
  --radius-pill: 999px;

  --ombre-panneau: 0 2px 10px rgba(25, 23, 21, .08);
  --ombre-flottant: 0 8px 28px rgba(25, 23, 21, .14);
}

* { box-sizing: border-box; }

/* `display` posé par une classe l'emporte sur la règle par défaut du
 * navigateur pour [hidden] : sans ce !important, un bouton masqué en JS
 * (« Nouveau projet » pour un compte client) reste affiché. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--surface-200);
  color: var(--ink-900);
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 22px;
}

h1 { font-size: 26px; line-height: 32px; font-weight: 700; margin: 0; }
h2 { font-size: 21px; line-height: 27px; font-weight: 700; margin: 0; }
h3 { font-size: 16px; line-height: 22px; font-weight: 600; margin: 0; }
a { color: var(--info); }

.mono { font-family: var(--font-mono); font-size: 13px; }
.petit { font-size: 13px; line-height: 18px; }
.sourdine { color: var(--ink-600); }
.tres-sourdine { color: var(--ink-400); }

.etiquette {
  font-size: 11px;
  line-height: 14px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: var(--ink-400);
}

/* ─── Mise en page ───────────────────────────────────────────────────────── */

.appli { display: flex; flex-direction: column; height: 100vh; }

header.barre {
  background: var(--surface-100);
  border-bottom: 1px solid var(--surface-300);
  padding: var(--space-2) var(--space-4);
  display: flex;
  align-items: center;
  gap: 18px;
  flex-shrink: 0;
}

/* La marque. Le signe dessiné — une boucle de balisage refermée par sa flèche
   de retour — remplace le carré d'encre qui tenait lieu de logo. Deux fichiers
   qui ne diffèrent que par la couleur du mot : une image ne peut pas hériter
   de la couleur de la page, et le bandeau de signalement est sombre. */
.marque { display: flex; align-items: center; gap: 10px; text-decoration: none; color: inherit; }
.marque-logo { height: 26px; width: auto; display: block; flex-shrink: 0; }
.marque-signe {
  height: 24px; width: auto; display: block; flex-shrink: 0;
}
/* Le nom du projet, là où il prend la place du mot : page publique et écran
   de signalement. Ailleurs, le mot est dans le logo et ne se répète pas. */
.marque-nom { font-weight: 700; font-size: 16px; letter-spacing: -.2px; }

.fil {
  display: flex; align-items: center; gap: 6px;
  padding: 5px 12px;
  border: 1px solid var(--surface-300);
  border-radius: var(--radius-md);
  background: var(--surface-200);
  font-size: 13px; color: var(--ink-600);
  text-decoration: none;
}
.fil:hover { border-color: var(--ink-400); }
.fil b { color: var(--ink-900); font-weight: 600; }

.compteurs { margin-left: auto; display: flex; gap: 22px; }
.compteur { text-align: right; }
.compteur .valeur {
  font-family: var(--font-mono); font-size: 17px; font-weight: 500; line-height: 1.1;
}
.compteur .nom {
  font-size: 10px; color: var(--ink-400); text-transform: uppercase;
  letter-spacing: .5px; margin-top: 2px;
}

.pastille-compte {
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--brand-gold); color: var(--brand-gold-ink);
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 12px; cursor: pointer; border: none;
  font-family: var(--font-sans);
}

.corps { flex: 1; display: flex; min-height: 0; }
.contenu { flex: 1; overflow-y: auto; padding: var(--space-8); }
.contenu-etroit { max-width: 980px; margin: 0 auto; }

/* ─── Boutons ────────────────────────────────────────────────────────────── */

.bouton {
  display: inline-flex; align-items: center; gap: 6px; justify-content: center;
  font-family: var(--font-sans); font-size: 13px; font-weight: 600;
  padding: 8px var(--space-3);
  border-radius: var(--radius-md);
  border: 1px solid var(--surface-300);
  background: var(--surface-100); color: var(--ink-600);
  cursor: pointer;
}
.bouton:hover:not(:disabled) { border-color: var(--ink-400); color: var(--ink-900); }
.bouton:disabled { opacity: .5; cursor: not-allowed; }
.bouton-principal {
  background: var(--brand-gold); border-color: var(--brand-gold);
  color: var(--brand-gold-ink);
}
.bouton-principal:hover:not(:disabled) { filter: brightness(.95); color: var(--brand-gold-ink); }
.bouton-encre { background: var(--ink-900); border-color: var(--ink-900); color: var(--surface-100); }
.bouton-encre:hover:not(:disabled) { color: var(--surface-100); filter: brightness(1.25); }
.bouton-danger { border-color: var(--danger); color: var(--danger); background: none; }
.bouton-danger:hover:not(:disabled) { background: var(--danger); color: #fff; }
.bouton-petit { font-size: 12px; padding: 5px 10px; }

:focus-visible {
  outline: 2px solid var(--brand-gold);
  outline-offset: 2px;
}

/* ─── Champs ─────────────────────────────────────────────────────────────── */

.champ { display: block; margin-bottom: var(--space-3); }
.champ > label {
  display: block; font-size: 11px; font-weight: 600;
  color: var(--ink-600); margin-bottom: var(--space-1);
}
input[type=text], input[type=email], input[type=password], input[type=date],
input[type=number], input[type=search], select, textarea {
  width: 100%;
  font-family: var(--font-sans); font-size: 13px;
  padding: 7px 9px;
  border: 1px solid var(--surface-300);
  border-radius: var(--radius-sm);
  background: var(--surface-100); color: var(--ink-900);
  outline: none;
}
input:focus, select:focus, textarea:focus { border-color: var(--brand-gold); }
textarea { resize: vertical; min-height: 56px; line-height: 20px; }
select { cursor: pointer; }

/* Un champ verrouillé doit SE VOIR verrouillé.
 *
 * Les règles ci-dessus imposent un fond blanc et une encre sombre, ce qui
 * écrasait l'apparence que le navigateur donne d'office à un champ désactivé :
 * une liste déroulante en lecture seule ressemblait trait pour trait à une
 * liste modifiable, et ne s'ouvrait pas quand on cliquait dessus. Le défaut
 * valait pour toute l'application — y compris tous les champs d'un compte en
 * lecture seule. */
input:disabled, select:disabled, textarea:disabled {
  background: var(--surface-200); color: var(--ink-400);
  border-color: var(--surface-300); cursor: not-allowed;
  -webkit-text-fill-color: var(--ink-400);   /* Safari ignore `color` */
  opacity: 1;                                /* et sa transparence d'office */
}
select:disabled { cursor: not-allowed; }
input[type=checkbox]:disabled, input[type=radio]:disabled { cursor: not-allowed; opacity: .45; }
input[type=color]:disabled { opacity: .45; cursor: not-allowed; }

.ligne-champs { display: flex; gap: var(--space-3); }
.ligne-champs > * { flex: 1; }

/* ─── Cartes et tableaux ─────────────────────────────────────────────────── */

.carte-bloc {
  background: var(--surface-100);
  border: 1px solid var(--surface-300);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  box-shadow: var(--ombre-panneau);
}

.grille-cartes {
  display: grid; gap: var(--space-4);
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}

.carte-projet {
  background: var(--surface-100);
  border: 1px solid var(--surface-300);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  text-decoration: none; color: inherit;
  display: flex; flex-direction: column; gap: var(--space-2);
  transition: border-color .12s, box-shadow .12s;
}
.carte-projet:hover { border-color: var(--ink-400); box-shadow: var(--ombre-panneau); }

table.liste { width: 100%; border-collapse: collapse; font-size: 13px; }
table.liste th {
  text-align: left; font-size: 11px; text-transform: uppercase;
  letter-spacing: .5px; color: var(--ink-400); font-weight: 600;
  padding: var(--space-2); border-bottom: 1px solid var(--surface-300);
}
table.liste td { padding: var(--space-2); border-bottom: 1px solid var(--surface-300); }
table.liste tr:last-child td { border-bottom: none; }

/* ─── Badges ─────────────────────────────────────────────────────────────── */

.badge {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11px; font-weight: 600; line-height: 14px;
  padding: 4px 10px; border-radius: var(--radius-pill);
  border: 1px solid var(--surface-300); background: var(--surface-100);
  color: var(--ink-600);
}
.badge-publie { border-color: var(--success); color: var(--success); }
/* Posé et contrôlé : le mandat est fini et vérifié sur place. Plus affirmé
   que « publié », et distinct de l'archive, qui, elle, est grise. */
/* « badge-pose » est déjà pris par l'état d'un relevé du volet 1 : celui-ci
   parle du PROJET, d'où le nom entier. */
.badge-pose_controle { border-color: var(--brand-gold); color: var(--brand-gold-ink); }
.badge-brouillon { border-color: var(--ink-400); color: var(--ink-400); }
.badge-lecture { border-color: var(--info); color: var(--info); }
/* Un accès accordé en dehors de l'organisation du compte. Il reste listé pour
   pouvoir être retiré, et se signale pour qu'on y pense. */
.hors-perimetre > div { color: var(--warning); }

/* Les raccourcis du filtre par parcours : « tous » et « aucun » en tête de
   section, « seul » sur chaque ligne. Trente-cinq parcours à décocher un par
   un pour n'en regarder qu'un, c'est trente-quatre gestes de trop. */
.raccourcis-filtre { margin-left: auto; display: flex; gap: var(--space-2); }
.raccourcis-filtre .lien-bouton { font-size: 11px; color: var(--ink-400); }
.raccourcis-filtre .lien-bouton:hover { color: var(--ink-900); }
.filtre-seul {
  margin-left: auto; font-size: 11px; color: var(--ink-400);
  opacity: 0; transition: opacity .12s;
}
.ligne-filtre:hover .filtre-seul, .filtre-seul:focus { opacity: 1; }
@media (hover: none) { .filtre-seul { opacity: 1; } }

.badge-archive { border-color: var(--ink-400); color: var(--ink-400);
                 background: var(--surface-200); }

/* Les deux actions d'une carte de projet. La carte est un lien : les boutons
   n'apparaissent qu'au survol, pour ne pas inviter au clic pendant qu'on lit.
   Ils restent visibles au clavier, sans quoi ils seraient inatteignables. */
.carte-actions {
  display: flex; gap: 6px; margin-top: var(--space-3);
  opacity: 0; transition: opacity .12s;
}
.carte-projet:hover .carte-actions,
.carte-actions:focus-within { opacity: 1; }
@media (hover: none) { .carte-actions { opacity: 1; } }

/* Un projet archivé se lit encore, mais il ne réclame plus l'attention. */
.carte-projet.archivee { opacity: .62; }
.badge-garder { border-color: var(--success); color: var(--success); }
.badge-remplacer { border-color: var(--warning); color: var(--warning); }
.badge-retirer { border-color: var(--danger); color: var(--danger); }
.badge-a_poser { border-color: var(--info); color: var(--info); }
.badge-pose { border-color: var(--success); color: var(--success); }

/* Le statut d'un document de production : sa pastille et sa liste, sur une
   ligne. La pastille redit la couleur de la liste pour qu'on lise l'état sans
   ouvrir la liste déroulante. */
/* « Afficher » dans un champ de mot de passe : posé sur le bord droit du
   champ, à hauteur de la saisie. Le label sert de repère de position, d'où le
   `position: relative` qu'on lui ajoute. Le champ se réserve la place à
   droite pour que le texte tapé ne passe jamais dessous. */
.champ-mot-de-passe { position: relative; }
.champ-mot-de-passe input { padding-right: 74px; }
.voir-mot-de-passe {
  position: absolute; right: 8px; bottom: 7px;
  border: 0; background: none; padding: 2px 4px;
  font-family: var(--font-sans); font-size: 12px; color: var(--ink-600);
  cursor: pointer; border-radius: var(--radius-sm);
}
.voir-mot-de-passe:hover { color: var(--ink-900); background: var(--surface-200); }
.voir-mot-de-passe:focus-visible { outline: 2px solid var(--brand-gold); }

/* Un bouton qui porte l'état de ce qu'il déclenche plutôt qu'un ordre.
   Vert : c'est fait, et abouti. Ambre : c'est lancé, on attend — ou il faut
   relancer. Le bouton reste cliquable dans les deux cas : on peut toujours
   renvoyer une invitation. */
.bouton-fait {
  border-color: var(--success); color: var(--success); background: var(--surface-100);
}
.bouton-fait:hover:not(:disabled) { background: var(--surface-200); color: var(--success); }
.bouton-attente {
  border-color: var(--warning); color: var(--warning); background: var(--surface-100);
}
.bouton-attente:hover:not(:disabled) { background: var(--surface-200); color: var(--warning); }

/* Une ligne « projet » dans la fiche d'une organisation : le nom, son rôle,
   et le retrait poussé au bout. */
.ligne-projet-organisation { display: flex; align-items: baseline; gap: 6px; }
.ligne-projet-organisation .lien-bouton.danger { margin: 0 0 0 auto; }

/* Un lien-bouton qui détruit. Rouge, et détaché du bloc qui le précède : ce
   n'est pas une action qu'on enchaîne par mégarde. */
.lien-bouton.danger {
  color: var(--danger); margin-top: 8px; display: inline-block;
}
.lien-bouton.danger:hover { color: var(--danger); text-decoration: underline; }

.champ-statut {
  display: flex; align-items: center; gap: 7px; margin: 6px 0 2px;
}
.champ-statut select { flex: 1; min-width: 0; }
.entete-version {
  display: flex; align-items: center; gap: var(--space-3);
  margin-bottom: 4px;
}
.entete-version .etiquette { flex-shrink: 0; margin: 0; }
.entete-version .champ-statut { flex: 1; margin: 0; }

.puce-couleur {
  width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0;
  display: inline-block;
}

/* ─── Messages ───────────────────────────────────────────────────────────── */

.message {
  border-radius: var(--radius-md);
  padding: var(--space-3);
  font-size: 13px; line-height: 19px;
  border: 1px solid var(--surface-300);
  background: var(--surface-200);
  margin-bottom: var(--space-4);
}
.message-erreur { border-color: var(--danger); color: var(--danger); background: #fdf3f2; }
.message-succes { border-color: var(--success); color: var(--success); background: #f2f8f3; }
.message-info { border-color: var(--info); color: var(--info); background: #f2f6fb; }

.vide {
  text-align: center; color: var(--ink-400); font-size: 13px;
  padding: var(--space-8) var(--space-4); line-height: 22px;
}

/* ─── Barre d'outils de l'éditeur ────────────────────────────────────────── */

.outils {
  background: var(--surface-100);
  border-bottom: 1px solid var(--surface-300);
  padding: var(--space-2) var(--space-4);
  display: flex; flex-direction: column; gap: var(--space-2);
  flex-shrink: 0;
}

/* Deux rangées : ce qui filtre en haut, ce qui agit en bas. */
.rangee-outils {
  display: flex; align-items: center; gap: var(--space-2);
  flex-wrap: wrap;
}
.rangee-actions { align-items: flex-end; gap: var(--space-4); }

/* Un groupe d'actions porte son nom. Poser un panneau à la main et déverser un
 * dossier de photos produisent le même résultat sur la carte mais ne sont pas
 * le même geste : sans ces intitulés, les deux séries de boutons se ressemblent
 * et on clique à côté. */
.groupe-outils { display: flex; flex-direction: column; gap: 3px; }
.groupe-outils::before {
  content: attr(data-titre);
  font-size: 9px; font-weight: 700; letter-spacing: .6px;
  text-transform: uppercase; color: var(--ink-400);
  padding-left: 2px; white-space: nowrap;
}
.boutons-groupe { display: flex; gap: 6px; }
.groupe-outils + .groupe-outils {
  border-left: 1px solid var(--surface-300);
  padding-left: var(--space-4); margin-left: 0;
}

.bouton svg { width: 14px; height: 14px; flex-shrink: 0; }

/* Les outils à main levée changent d'état : ils s'allument tant qu'on est
 * dedans. Les boutons d'import, eux, agissent une fois et retombent. */
.bouton-mode { border-color: var(--ink-400); color: var(--ink-900); }
.bouton-import { border-style: dashed; }
.recherche { position: relative; }
.recherche input { width: 230px; padding-left: 30px; background: var(--surface-200); }
.recherche input:focus { background: var(--surface-100); }
.recherche svg {
  position: absolute; left: 9px; top: 50%; transform: translateY(-50%);
  width: 14px; height: 14px; color: var(--ink-400); pointer-events: none;
}
.separateur { width: 1px; height: 20px; background: var(--surface-300); }

.segments { display: flex; border: 1px solid var(--surface-300); border-radius: var(--radius-md); overflow: hidden; }
.segments button {
  border: none; background: var(--surface-100); color: var(--ink-600);
  font-size: 12px; font-family: var(--font-sans); padding: 6px 12px; cursor: pointer;
}
.segments button + button { border-left: 1px solid var(--surface-300); }
.segments button.actif { background: var(--ink-900); color: var(--surface-100); font-weight: 600; }

.outils select, .outils .bouton { font-size: 12px; padding: 6px 10px; width: auto; }
.bouton.actif-or { background: var(--brand-gold); border-color: var(--brand-gold); color: var(--brand-gold-ink); }
.bouton.actif-trace { background: var(--warning); border-color: var(--warning); color: #fff; }

/* ─── Carte ──────────────────────────────────────────────────────────────── */

.zone-carte { flex: 1; position: relative; min-width: 0; }
#carte { position: absolute; inset: 0; background: var(--surface-200); }

.legende {
  position: absolute; left: 16px; bottom: 26px; z-index: 500;
  background: var(--surface-100); border: 1px solid var(--surface-300);
  border-radius: var(--radius-md); padding: 10px 12px;
  font-size: 11px; color: var(--ink-600); box-shadow: var(--ombre-panneau);
  max-height: 44vh; overflow-y: auto; min-width: 170px;
}
.legende h4 { margin: 0 0 4px; }
.legende .rangee {
  display: flex; align-items: center; gap: 7px; margin-top: 5px; cursor: pointer;
}
.legende .rangee.eteinte { opacity: .38; }

.tiroir {
  position: absolute; right: 16px; bottom: 26px; z-index: 500; width: 244px;
  background: var(--surface-100); border: 1px solid var(--surface-300);
  border-radius: var(--radius-lg); box-shadow: var(--ombre-flottant); overflow: hidden;
}
.tiroir-entete {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px; border-bottom: 1px solid var(--surface-300);
}
.tiroir-entete b { font-size: 12px; flex: 1; }
.tiroir-corps { padding: 10px 12px; display: flex; flex-direction: column; gap: 8px; }

/* Marqueurs dessinés en HTML (divIcon Leaflet) */
.marqueur {
  width: 15px; height: 15px; border-radius: 50%;
  border: 2.5px solid var(--surface-100);
  box-shadow: 0 1px 4px rgba(0, 0, 0, .25);
  box-sizing: content-box;
}
.marqueur.anneau { box-shadow: 0 0 0 3px var(--danger), 0 1px 4px rgba(0, 0, 0, .25); }
.marqueur.choisi {
  box-shadow: 0 0 0 4px rgba(243, 187, 68, .55), 0 1px 6px rgba(0, 0, 0, .35);
}
.marqueur-numero {
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 9px; font-weight: 700;
  width: 19px; height: 19px;
}

/* ─── Panneau de propriétés ──────────────────────────────────────────────── */

.panneau {
  width: var(--largeur-volet, 320px); flex-shrink: 0;
  background: var(--surface-100);
  border-left: 1px solid var(--surface-300);
  display: flex; flex-direction: column; overflow-y: auto;
}
.panneau-photo {
  width: 100%; aspect-ratio: 4 / 3; background: var(--surface-200);
  position: relative; object-fit: cover; display: block;
}
.panneau-photo-vide {
  width: 100%; aspect-ratio: 4 / 3; background: var(--surface-200);
  display: flex; flex-direction: column; gap: 6px;
  align-items: center; justify-content: center;
  color: var(--ink-400); font-size: 12px;
}
/* Le lien y est centré, et non repoussé à droite comme dans un en-tête de champ. */
.panneau-photo-vide .lien-discret { margin-left: 0; }

/* Une image dont le fichier a vraiment disparu : le cadre reste, pour que la
   place de la photo se voie, mais il ne fait pas semblant d'en montrer une. */
.image-perdue {
  background: repeating-linear-gradient(45deg, var(--surface-200),
              var(--surface-200) 8px, var(--surface-100) 8px, var(--surface-100) 16px);
  object-fit: contain;
}

/* Choisir dans une liste longue : un filtre au clavier plutôt qu'un déroulant. */
.champ-recherche {
  box-sizing: border-box; margin: var(--space-3) 0 var(--space-2);
}
.liste-choix { max-height: 44vh; overflow-y: auto; display: flex; flex-direction: column; }
.ligne-choix {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  padding: 7px 8px; border: none; border-bottom: 1px solid var(--surface-200);
  background: none; cursor: pointer; font-family: var(--font-sans);
  font-size: 13px; color: var(--ink-900);
}
.ligne-choix:hover { background: var(--surface-100); }
.ligne-choix:last-child { border-bottom: none; }
.vignette-choix {
  width: 56px; height: 42px; object-fit: cover; flex: none;
  border-radius: var(--radius-sm); background: var(--surface-200);
}
.panneau-corps { padding: var(--space-3) var(--space-4) var(--space-6); }
.panneau-meta { display: flex; gap: var(--space-4); margin-bottom: var(--space-3); }
.panneau-meta .valeur { font-family: var(--font-mono); font-size: 11px; color: var(--ink-600); }

.jeu-pastilles { display: flex; flex-wrap: wrap; gap: 6px; }
.pastille {
  font-size: 11px; padding: 4px 10px; border-radius: var(--radius-pill);
  border: 1px solid var(--surface-300); background: var(--surface-100);
  color: var(--ink-600); cursor: pointer; font-family: var(--font-sans);
}
/* Sélectionnée. La couleur et le crochet suffisent à eux seuls : certains
   appelants posent en plus un fond en ligne, mais ceux qui n'en posent pas
   écrivaient jusqu'ici en blanc sur blanc. */
.pastille.active {
  color: var(--success); font-weight: 600;
  border-color: var(--success); background: rgba(63, 125, 74, .1);
}
.pastille.active::before { content: '✓ '; font-weight: 700; }

.rangee-statuts { display: flex; gap: 6px; }
.rangee-statuts button {
  flex: 1; font-size: 11px; padding: 7px 2px; border-radius: var(--radius-sm);
  border: 1px solid var(--surface-300); background: none; cursor: pointer;
  font-weight: 600; font-family: var(--font-sans); color: var(--ink-400);
}
.rangee-statuts button[data-statut=garder] { border-color: var(--success); color: var(--success); }
.rangee-statuts button[data-statut=remplacer] { border-color: var(--warning); color: var(--warning); }
.rangee-statuts button[data-statut=retirer] { border-color: var(--danger); color: var(--danger); }
.rangee-statuts button[data-statut=a_poser] { border-color: var(--info); color: var(--info); }
.rangee-statuts button[data-statut=pose] { border-color: var(--success); color: var(--success); }
.rangee-statuts button.actif[data-statut=garder],
.rangee-statuts button.actif[data-statut=pose] { background: var(--success); color: #fff; }
.rangee-statuts button.actif[data-statut=remplacer] { background: var(--warning); color: #fff; }
.rangee-statuts button.actif[data-statut=retirer] { background: var(--danger); color: #fff; }
.rangee-statuts button.actif[data-statut=a_poser] { background: var(--info); color: #fff; }

.encadre {
  background: var(--surface-200); border: 1px solid var(--surface-300);
  border-radius: var(--radius-md); padding: 10px 12px;
  font-size: 11px; color: var(--ink-600); line-height: 17px;
}
.encadre b { color: var(--ink-900); }

/* ─── Volet 2 : conception ───────────────────────────────────────────────── */

/* Sélecteur de volet, dans l'en-tête du projet. */
.volets { display: flex; gap: 2px; background: var(--surface-200);
  border: 1px solid var(--surface-300); border-radius: var(--radius-md); padding: 2px; }
.volet {
  font-size: 12px; font-weight: 600; padding: 5px 12px;
  border-radius: 6px; color: var(--ink-600); text-decoration: none; white-space: nowrap;
}
.volet:hover { color: var(--ink-900); }
.volet.actif { background: var(--surface-100); color: var(--ink-900);
  box-shadow: 0 1px 2px rgba(25, 23, 21, .12); }
.volet.a-venir { color: var(--ink-400); cursor: default; }

/* Barre des sept étapes. Elle reste visible en permanence : dans ce volet,
 * savoir où l'on en est compte autant que ce qu'on est en train de faire. */
.etapes {
  display: flex; gap: 0; margin: 0; padding: var(--space-2) var(--space-4);
  list-style: none; background: var(--surface-100);
  border-bottom: 1px solid var(--surface-300);
  overflow-x: auto; scrollbar-width: none; flex-shrink: 0;
}
.etapes::-webkit-scrollbar { display: none; }
.etape {
  display: flex; align-items: center; gap: 8px;
  padding: 0 var(--space-4) 0 var(--space-3); flex-shrink: 0;
  border-right: 1px solid var(--surface-300);
}
.etape:last-child { border-right: none; }
.etape-numero {
  width: 20px; height: 20px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 10px; font-weight: 700;
  background: var(--surface-300); color: var(--ink-600);
}
.etape-texte { display: flex; flex-direction: column; line-height: 1.25; }
.etape-titre { font-size: 12px; font-weight: 600; white-space: nowrap; }
.etape-statut { font-size: 10px; color: var(--ink-400); white-space: nowrap; }

.etape-valide .etape-numero { background: var(--success); color: #fff; }
.etape-valide .etape-statut { color: var(--success); }
.etape-en_attente .etape-numero { background: var(--brand-gold); color: var(--brand-gold-ink); }
.etape-en_attente .etape-statut { color: var(--warning); }
.etape-refuse .etape-numero { background: var(--danger); color: #fff; }
.etape-refuse .etape-statut { color: var(--danger); }
.etape-a_faire .etape-numero { background: var(--ink-900); color: var(--surface-100); }
/* Grisé : l'étape existe dans le processus mais n'est pas encore construite,
 * ou attend la validation de celle qui la précède. */
.etape-bloquee { opacity: .42; cursor: not-allowed; }
/* La barre d'étapes sert aussi de navigation : une étape ouverte se clique. */
.etape-accessible { cursor: pointer; }
.etape-accessible:hover .etape-titre { text-decoration: underline; }
.etape-courante { background: var(--surface-200); border-radius: var(--radius-md); }
.etape-courante .etape-titre { color: var(--ink-900); }

/* Colonne de gauche : la liste, qui deviendra la navigation par parcours. */
.colonne-liste {
  /* `--largeur-volet` est posée par static/js/redim.js quand on tire la
   * poignée ; sans elle, la largeur d'origine s'applique. */
  width: var(--largeur-volet, 260px); flex-shrink: 0; overflow-y: auto;
  background: var(--surface-100); border-right: 1px solid var(--surface-300);
  padding: var(--space-2) 0 var(--space-6);
}
.groupe-liste { margin-bottom: var(--space-4); }
.entete-liste {
  display: flex; align-items: center; gap: 7px;
  padding: var(--space-2) var(--space-3);
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .5px; color: var(--ink-600);
}
.entete-liste .compte { margin-left: auto; color: var(--ink-400); font-family: var(--font-mono); }

/* Un titre de section se replie. Sur Châtel-St-Denis la colonne fait plusieurs
   écrans : chercher un poste revenait à faire défiler tout le reste. */
.entete-poignee {
  display: flex; align-items: center; gap: 7px;
  cursor: pointer; user-select: none; min-width: 0;
}
.entete-poignee:hover { color: var(--ink-900); }
.entete-poignee:focus-visible { outline: 2px solid var(--brand-gold); outline-offset: 2px; }
.entete-chevron { color: var(--ink-400); font-size: 9px; width: 9px; flex-shrink: 0; }
.entete-liste.repliee { color: var(--ink-400); }
/* Ouvrir ou fermer tout, en tête de colonne. Discret : c'est un recours, pas
   la commande principale — celle-ci est le titre lui-même. */
.barre-accordeons {
  display: flex; gap: var(--space-3);
  padding: 6px var(--space-3); border-bottom: 1px solid var(--surface-300);
}
.barre-accordeons .lien-bouton { font-size: 11px; color: var(--ink-400); }
.barre-accordeons .lien-bouton:hover { color: var(--ink-900); }
.ligne-liste {
  display: flex; flex-direction: column; gap: 1px; width: 100%; text-align: left;
  border: none; background: none; cursor: pointer;
  font-family: var(--font-sans); font-size: 13px; color: var(--ink-900);
  padding: 6px var(--space-3); border-left: 3px solid transparent;
}
.ligne-liste:hover { background: var(--surface-200); }
.ligne-liste.choisie { border-left-color: var(--brand-gold); background: var(--surface-200); }
.vide-liste { padding: 2px var(--space-3) var(--space-2); }

/* Le filtre par parcours, en tête du volet de gauche. Séparé du reste par un
   trait : ce n'est pas une section de la liste, c'est ce qui décide de son
   contenu. */
.filtre-parcours {
  border-bottom: 1px solid var(--surface-300);
  padding-bottom: var(--space-2);
}
.ligne-filtre {
  display: flex; align-items: center; gap: 7px;
  padding: 4px var(--space-3); font-size: 13px; cursor: pointer;
}
.ligne-filtre:hover { background: var(--surface-200); }
.ligne-filtre input { margin: 0; flex-shrink: 0; }
.filtre-nom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* À l'étape des parcours, le nom ouvre la fiche : c'est donc un bouton, qui
   doit se lire comme le texte qu'il remplace ailleurs. Souligné au survol
   seulement — un filtre souligné en permanence ressemblerait à une liste de
   liens et non à des cases à cocher. */
button.filtre-nom {
  flex: 1; min-width: 0; text-align: left; padding: 0;
  background: none; border: 0; cursor: pointer;
  font: inherit; color: inherit;
}
button.filtre-nom:hover { text-decoration: underline; }
button.filtre-nom.choisie { font-weight: 700; color: var(--brand-gold-ink); }
/* Un faisceau : les parcours qui partent du même point. L'en-tête commande
   tout le groupe, les lignes filles s'indentent sous lui. */
.ligne-faisceau { font-weight: 600; margin-top: 4px; }
.ligne-faisceau .compte {
  margin-left: auto; color: var(--ink-400);
  font-family: var(--font-mono); font-size: 11px; font-weight: 400;
}
.ligne-fille { padding-left: calc(var(--space-3) + 20px); }
/* Les parcours servis par une structure, en pastilles de couleur. */
.puces-parcours { display: flex; gap: 3px; margin-top: 3px; }
/* L'en-tête d'un faisceau dans une fiche, avec son bouton « tous / aucun ». */
.entete-faisceau {
  display: flex; align-items: baseline; gap: 8px;
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .4px; color: var(--ink-600);
  margin: 10px 0 5px;
}
/* Le titre d'un champ, avec son lien de réglage poussé à droite. Le lien mène
   là où l'on règle ce que le champ propose — les catégories d'un projet, par
   exemple — sans quitter la fiche des yeux. */
.entete-champ {
  display: flex; align-items: baseline; gap: 8px;
}
.entete-champ label { margin: 0; }

.lien-discret {
  margin-left: auto; border: none; background: none; cursor: pointer;
  font-family: var(--font-sans); font-size: 11px; color: var(--ink-400);
  text-transform: none; letter-spacing: 0; text-decoration: underline;
  padding: 0;
}
.lien-discret:hover { color: var(--ink-900); }
.ligne-avec-puce { display: flex; align-items: center; gap: 7px; }

/* Le choix de couleur d'un parcours : une palette qui suffit presque toujours,
   et le sélecteur du navigateur pour le reste. */
.nuancier { display: flex; flex-wrap: wrap; gap: 6px; }
.nuance {
  width: 22px; height: 22px; border-radius: var(--radius-sm);
  border: 2px solid transparent; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .15);
  cursor: pointer; padding: 0;
}
.nuance:disabled { cursor: default; }
.nuance.choisie { border-color: var(--ink-900); }
.nuance-libre { background: none; }

/* Les libellés proposés : une ligne par candidat, le bouton d'ajout d'abord —
   c'est le geste, et il doit tomber sous la main au même endroit. */
.candidat {
  display: flex; align-items: center; gap: 8px;
  padding: 4px 0; font-size: 13px;
}
.candidat-textes { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.candidat-textes > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.candidats-autres { margin-top: 6px; }
.candidats-autres > summary { cursor: pointer; color: var(--ink-600); }

/* Voile sur le fond de carte. Il ne porte que sur la couche des tuiles : tout
   ce que nous ajoutons vit dans les couches du dessus et garde ses couleurs
   exactes. Retirer la classe suffit à revenir au fond net. */
#carte.fond-assombri { background: #0B0A09; }
#carte.fond-assombri .leaflet-tile-pane { filter: brightness(.45) saturate(.75); }
/* Éclaircir, c'est fondre vers le blanc : un filtre de luminosité brûlerait
   les surfaces déjà claires au lieu de les effacer. */
#carte.fond-eclairci { background: #FFFFFF; }
#carte.fond-eclairci .leaflet-tile-pane { opacity: .34; }

/* Le menu du compte, sous la pastille des initiales. Posé sur le document et
   non dans l'en-tête : celui-ci coupe ce qui déborde. */
.menu-compte {
  position: fixed; z-index: 4000; min-width: 220px;
  background: var(--surface-100); color: var(--ink-900);
  border: 1px solid var(--surface-300); border-radius: var(--radius-md);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .18);
  padding: 6px 0; overflow: hidden;
}
.menu-compte-entete {
  padding: 8px var(--space-3) 10px;
  border-bottom: 1px solid var(--surface-300); margin-bottom: 4px;
}
.menu-compte-entree {
  display: block; width: 100%; text-align: left;
  padding: 8px var(--space-3); border: none; background: none;
  font-family: var(--font-sans); font-size: 13px; color: var(--ink-900);
  cursor: pointer;
}
.menu-compte-entree:hover { background: var(--surface-200); }

/* Le repère qui ouvre la fiche d'une organisation, à droite de sa ligne. */
.ouvrir-fiche {
  margin-left: 8px; color: var(--ink-400); cursor: pointer;
  padding: 0 4px; border-radius: var(--radius-sm); line-height: 1;
}
.ouvrir-fiche:hover { color: var(--ink-900); background: var(--surface-300); }

/* ─── Panneaux de chantier ───────────────────────────────────────────────
   Repris du prototype Payerne. Un panneau se reconnaît à son pictogramme,
   pas à la couleur d'une pastille. */
.palette-panneaux {
  display: flex; flex-wrap: wrap; gap: 6px; max-width: 520px;
}
.panneau-choix {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  width: 68px; padding: 5px 3px; cursor: pointer;
  border: 1px solid var(--surface-300); border-radius: var(--radius-sm);
  background: var(--surface-100); font-family: var(--font-sans);
}
.panneau-choix:hover { background: var(--surface-200); }
.panneau-choix.arme {
  border-color: var(--brand-gold); background: rgba(243, 187, 68, .14);
  box-shadow: inset 0 0 0 1px var(--brand-gold);
}
.panneau-choix img { width: 28px; height: 28px; object-fit: contain; }
.panneau-nom {
  font-size: 9px; line-height: 1.15; text-align: center; color: var(--ink-600);
  overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.panneau-sans-image { display: block; width: 28px; height: 28px; border-radius: 3px; }
.ligne-groupe-actif {
  display: flex; align-items: center; gap: 6px; margin-bottom: 6px;
  font-size: 11px; color: var(--ink-600);
}
.ligne-groupe-actif select { font-size: 11px; padding: 3px 6px; }

/* Le marqueur lui-même : une boîte de dimension nulle, centrée, qui tourne.
   Même principe que les supports de signalétique — des marges fixes ne
   centrent qu'une seule taille, et celle-ci est réglable. */
.marqueur-panneau {
  position: absolute; width: 0; height: 0;
  display: flex; align-items: center; justify-content: center;
  transform-origin: center;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .45));
  cursor: pointer;
}
.marqueur-panneau.choisi {
  filter: drop-shadow(0 0 3px var(--brand-gold)) drop-shadow(0 0 3px var(--brand-gold));
}
.marqueur-panneau img, .marqueur-panneau .panneau-sans-image { flex-shrink: 0; }
/* L'étiquette ne tourne PAS avec le panneau : un texte à l'envers ne se lit
   pas, et c'est le pictogramme qui porte la direction. */
.panneau-etiquette {
  position: absolute; left: 14px; top: -8px; white-space: nowrap;
  background: rgba(20, 18, 16, .9); color: #fff;
  font-size: 11px; padding: 2px 6px; border-radius: 3px;
}
/* Le chevron qui donne le sens d'une déviation. Boîte de dimension nulle,
   centrée : le chevron tourne autour de son propre milieu. */
.fleche-deviation {
  position: absolute; width: 0; height: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 15px; line-height: 1; transform-origin: center;
  text-shadow: 0 0 3px #fff, 0 0 3px #fff;
}
.ligne-curseur { display: flex; align-items: center; gap: 10px; }
.ligne-curseur input[type=range] { flex: 1; }

/* Une porte d'un point d'orientation : un petit disque, franchement plus
   discret que la goutte du point lui-même. C'est une prise de tracé, pas une
   destination, et la hiérarchie doit se voir. */
.marqueur-acces-po {
  width: 11px; height: 11px; border-radius: 50%;
  border: 2px solid var(--surface-100); box-sizing: border-box;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .35);
  margin: -5.5px 0 0 -5.5px;
  cursor: pointer;
}

/* Marqueur en goutte, pour distinguer POE et POI des pastilles rondes du
 * volet 1 : ce ne sont pas des relevés, ce sont des destinations. */
.marqueur-po {
  width: 22px; height: 22px; border-radius: 50% 50% 50% 0;
  transform: rotate(-45deg); border: 2px solid var(--surface-100);
  box-shadow: 0 1px 4px rgba(0, 0, 0, .3); box-sizing: border-box;
}
.marqueur-po.choisi { box-shadow: 0 0 0 4px rgba(243, 187, 68, .55), 0 1px 6px rgba(0, 0, 0, .35); }
/* À l'étape des parcours, les POE/POI restent lisibles mais cessent d'être le
 * sujet : ils deviennent le décor sur lequel on trace. */
.marqueur-po.en-retrait { opacity: .5; width: 16px; height: 16px; }
.puce-po { width: 9px; height: 9px; border-radius: 50% 50% 50% 0;
  transform: rotate(-45deg); display: inline-block; }
.puce-poe { background: #F63F94; }
.puce-poi { background: #3E6FA6; }

.bandeau-po {
  color: #fff; font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .5px; padding: 6px 10px; border-radius: var(--radius-sm);
  margin-bottom: var(--space-3); display: inline-block;
}

@media (max-width: 860px) {
  .colonne-liste { display: none; }
  .volets { order: 10; width: 100%; }
}

/* Structures : un rectangle portant son code, pour qu'on lise 1P ou 2T1 sans
 * ouvrir la fiche. Ce n'est pas une pastille : une structure est un objet
 * physique, pas un relevé. */
.marqueur-structure {
  min-width: 30px; height: 20px; border-radius: var(--radius-sm);
  border: 2px solid var(--surface-100); box-sizing: content-box;
  color: #fff; font-size: 10px; font-weight: 700; letter-spacing: .3px;
  display: flex; align-items: center; justify-content: center; padding: 0 4px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .3); font-family: var(--font-mono);
}
.marqueur-structure.choisi {
  box-shadow: 0 0 0 4px rgba(243, 187, 68, .6), 0 1px 6px rgba(0, 0, 0, .35);
}

/* L'aperçu du panneau, posé sur la carte et tourné dans l'orientation de la
 * face. C'est ce qui rend le plan d'implantation vérifiable avant qu'un seul
 * visuel n'existe : on voit d'un coup d'œil qu'une flèche pointe du mauvais
 * côté, ce qu'aucun tableau ne montre. */
/* La taille se règle par projet (roue crantée → Projet → Aperçus sur la
 * carte) : `--echelle-apercu` est posée sur le conteneur de la carte. 9 px
 * était illisible ; la base passe à 11 px et se multiplie de là. */
/* Une boîte de dimension nulle, centrée sur le point : le bloc s'y centre
   quelle que soit sa largeur, et c'est elle qui porte le décalage vers le
   côté par lequel on lit la face. */
.marqueur-apercu {
  position: absolute; width: 0; height: 0;
  display: flex; align-items: center; justify-content: center;
}
.panneau-apercu {
  flex-shrink: 0;
  background: rgba(20, 18, 16, .92); color: #fff;
  border-radius: 3px; padding: 5px 7px;
  min-width: calc(128px * var(--echelle-apercu, 1));
  font-size: calc(11px * var(--echelle-apercu, 1));
  line-height: 1.45; white-space: nowrap;
  transform-origin: center; cursor: pointer;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .35);
  /* Le liseré marque la face lisible, et il est TOUJOURS en bas du bloc : le
     bloc est écrit comme le voit celui qui se tient devant le panneau, donc
     son bord bas est celui qui regarde le lecteur. */
  border-bottom: 2px solid var(--face-lisible);
}
.apercu-entete {
  display: flex; align-items: center; gap: 6px;
  margin-bottom: 3px; padding-bottom: 3px;
  border-bottom: 1px solid rgba(255, 255, 255, .18);
}
/* La silhouette est un repère, pas une mesure : on la dimensionne à la main
 * plutôt que de la mettre à l'échelle, sinon elle ne prendrait pas la place
 * qu'elle occupe et chevaucherait le code de la face. */
.apercu-forme { flex-shrink: 0; display: inline-flex; }
.apercu-forme .forme { transform: scale(calc(0.62 * var(--echelle-apercu, 1))); }
.apercu-lignes { display: grid; grid-template-columns: 1fr auto auto; gap: 0 7px; }
.apercu-libelle {
  overflow: hidden; text-overflow: ellipsis;
  max-width: calc(170px * var(--echelle-apercu, 1));
}
.apercu-mesure { font-family: var(--font-mono); opacity: .85; }
.apercu-fleche {
  font-weight: 700; display: inline-block; text-align: center;
  width: calc(11px * var(--echelle-apercu, 1));
  transform-origin: center;
}
.apercu-code {
  font-family: var(--font-mono); opacity: .6; margin-left: auto;
  font-size: calc(8px * var(--echelle-apercu, 1));
}

/* Le code d'une face, en évidence : c'est son identité. */
.code-face {
  font-family: var(--font-mono); font-size: 16px; font-weight: 500;
  background: var(--surface-200); border: 1px solid var(--surface-300);
  border-radius: var(--radius-sm); padding: 8px 10px; text-align: center;
  margin-bottom: var(--space-2);
}

/* Un écart entre ce qui est figé et ce qui est calculé. Le rouge n'est pas
 * une erreur de saisie : c'est le plan et le terrain qui divergent. */
.divergent { color: var(--danger); }

.fil-fiche {
  font-size: 11px; color: var(--ink-400); margin-bottom: var(--space-2);
  display: flex; flex-wrap: wrap; align-items: center;
}
.lien-fil {
  border: none; background: none; padding: 0; cursor: pointer;
  font-family: var(--font-sans); font-size: 11px; color: var(--info);
}
.lien-fil:hover { text-decoration: underline; }

/* Un libellé affiché sur un panneau : la référence, puis ses mesures. */
.contenu-ligne {
  border: 1px solid var(--surface-300); border-radius: var(--radius-sm);
  padding: 6px; margin-bottom: 6px; background: var(--surface-100);
}
.contenu-mesures { display: flex; gap: 4px; margin-top: 4px; align-items: center; }
.contenu-mesures select { width: 84px; }
.contenu-mesures input { width: 64px; }

.liste-cases { max-height: 280px; overflow-y: auto; border: 1px solid var(--surface-300);
  border-radius: var(--radius-sm); padding: 4px; }
/* Une case à cocher avec son libellé, sur une ligne, cliquable en entier.
   Le tiroir de tracé s'en sert pour « boucle » et « suivre les chemins ». */
.case {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 8px 0;
  font-size: .9rem;
  cursor: pointer;
}
.case input { width: auto; margin: 0; }

.case-relevé {
  display: flex; align-items: center; gap: 8px; padding: 4px 6px;
  font-size: 13px; cursor: pointer; border-radius: var(--radius-sm);
}
.case-relevé:hover { background: var(--surface-200); }
.case-relevé input { width: auto; }
.case-relevé span:nth-child(2) { flex: 1; }

/* ─── Relecture d'un import CSV ───────────────────────────────────────────── */

.modale-large { width: min(760px, 100%); }

.lignes-import {
  max-height: 46vh; overflow-y: auto; border: 1px solid var(--surface-300);
  border-radius: var(--radius-sm); margin: var(--space-3) 0;
}
.ligne-import {
  display: flex; gap: var(--space-3); align-items: flex-start;
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--surface-300);
}
.ligne-import:last-child { border-bottom: none; }
/* Une ligne écartée reste lisible : on doit pouvoir revenir dessus. */
.ligne-import.ecartee { opacity: .4; }
.ligne-import input[type=checkbox] { width: auto; margin-top: 10px; flex-shrink: 0; }
.import-detail { flex: 1; min-width: 0; }
.import-nom { font-weight: 600; }
.import-reglages {
  display: flex; gap: 6px; align-items: center; margin: 4px 0; flex-wrap: wrap;
}
.import-reglages select { width: auto; min-width: 128px; }

/* Ce que vaut une adresse géocodée. Le vocabulaire dit l'incertitude plutôt
 * que de la masquer : « approximatif » n'est pas une erreur, c'est ce que
 * l'adresse permettait. */
.verdict-ok { border-color: var(--success); color: var(--success); }
.verdict-moyen { border-color: var(--warning); color: var(--warning); }
.verdict-absent { border-color: var(--ink-400); color: var(--ink-400); }

/* Un point posé au centre du projet faute d'adresse : hachuré tant qu'on ne
 * l'a pas placé. */
.marqueur-po.a-preciser {
  background-image: repeating-linear-gradient(45deg,
    rgba(255, 255, 255, .75) 0 3px, transparent 3px 6px);
  border-color: var(--warning);
}

/* ─── Choix d'un lieu ────────────────────────────────────────────────────── */

.resultats-lieu {
  border: 1px solid var(--surface-300);
  border-radius: var(--radius-sm);
  max-height: 168px; overflow-y: auto;
  margin: -8px 0 var(--space-3);
  background: var(--surface-100);
}
.resultat-lieu {
  display: block; width: 100%; text-align: left;
  border: none; border-bottom: 1px solid var(--surface-300);
  background: none; cursor: pointer;
  font-family: var(--font-sans); font-size: 13px;
  padding: 8px 10px; color: var(--ink-900);
}
.resultat-lieu:last-child { border-bottom: none; }
.resultat-lieu:hover { background: var(--surface-200); }
.resultat-lieu b { display: block; font-weight: 600; }
.resultat-lieu span {
  display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.resultats-lieu .message { margin: 0; border: none; }

.cadre-carte-lieu {
  position: relative;
  border: 1px solid var(--surface-300);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.carte-lieu { height: 260px; }

/* La mire marque le point retenu : ce que vous voyez est ce qui est
 * enregistré. `pointer-events: none` pour ne pas gêner le déplacement. */
.mire {
  position: absolute; left: 50%; top: 50%; z-index: 500;
  width: 30px; height: 30px; margin: -15px 0 0 -15px;
  pointer-events: none;
}
.mire::before, .mire::after {
  content: ''; position: absolute; background: var(--ink-900);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .85);
}
.mire::before { left: 50%; top: 0; width: 2px; height: 30px; margin-left: -1px; }
.mire::after { top: 50%; left: 0; height: 2px; width: 30px; margin-top: -1px; }

.mire-pastille {
  position: absolute; left: 50%; top: 50%;
  width: 12px; height: 12px; margin: -6px 0 0 -6px;
  border-radius: 50%; background: var(--brand-gold);
  box-shadow: 0 0 0 2px var(--ink-900);
}

/* ─── Modale ─────────────────────────────────────────────────────────────── */

.voile {
  position: fixed; inset: 0; z-index: 2000;
  background: rgba(25, 23, 21, .45);
  display: flex; align-items: center; justify-content: center;
  padding: var(--space-4);
}
.modale {
  background: var(--surface-100); border-radius: var(--radius-lg);
  box-shadow: var(--ombre-flottant); width: min(560px, 100%);
  max-height: 88vh; overflow-y: auto; padding: var(--space-6);
}

/* Une fenêtre de configuration s'élargit : les tableaux de référentiels ont
 * huit colonnes, et 880 px ne suffisent pas toujours. La poignée est celle du
 * navigateur, en bas à droite ; la largeur choisie est retenue par
 * static/js/redim.js. */
.modale.etirable {
  resize: horizontal;
  min-width: 380px;
  max-width: calc(100vw - 2 * var(--space-4));
}
.modale.etirable::-webkit-resizer { background: transparent; }
.modale h2 { margin-bottom: var(--space-4); }
.modale-actions {
  display: flex; gap: var(--space-2); justify-content: flex-end;
  margin-top: var(--space-4);
}

/* ─── Connexion ──────────────────────────────────────────────────────────── */

/* Une modale qui porte un tableau : la largeur par défaut serre trop. */
.modale-large { max-width: 820px; }

.titre-connexion {
  font-size: 17px; font-weight: 600; margin: 0 0 4px; text-align: center;
}
.page-connexion {
  /* En colonne, pour que les liens légaux ajoutés sous la carte se posent
     dessous et non à côté d'elle. */
  min-height: 100vh; display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  padding: var(--space-4); background: var(--surface-200);
}
.bloc-connexion {
  width: min(380px, 100%); background: var(--surface-100);
  border: 1px solid var(--surface-300); border-radius: var(--radius-lg);
  padding: var(--space-8); box-shadow: var(--ombre-panneau);
}
.bloc-connexion .marque { justify-content: center; margin-bottom: var(--space-6); }

/* ─── Notification passagère ─────────────────────────────────────────────── */

.notif {
  position: fixed; left: 50%; bottom: 26px; transform: translateX(-50%);
  z-index: 3000; background: var(--ink-900); color: var(--surface-100);
  padding: 10px 18px; border-radius: var(--radius-pill);
  font-size: 13px; box-shadow: var(--ombre-flottant);
}
.notif.erreur { background: var(--danger); }

/* ─── Téléphone et tablette ──────────────────────────────────────────────────
 *
 * L'outil est consulté sur le terrain — chantier, sentier — donc sur un
 * téléphone. Deux partis pris pour que l'écran reste utilisable à 375 px :
 *   — la barre d'outils défile horizontalement au lieu de s'empiler sur dix
 *     lignes et de manger la carte ;
 *   — le panneau de propriétés devient une feuille qui monte du bas, ouverte
 *     seulement quand on a touché un élément, et refermable.
 */
.panneau-fermer { display: none; }

@media (max-width: 860px) {
  .compteurs { display: none; }
  .contenu { padding: var(--space-4); }
  /* `.volets` demande déjà toute la largeur et passe en dernier (`order: 10`) :
   * il lui manquait l'autorisation de passer à la ligne. Sans elle, tout tient
   * sur une rangée trop courte et le nom du projet — avec sa roue crantée — se
   * retrouve écrasé à zéro pixel. */
  header.barre { gap: 10px; padding: var(--space-2) var(--space-3); flex-wrap: wrap; }
  /* Base zéro, et non `auto` : une base `auto` vaut la largeur du texte, et
   * un conteneur qui a le droit de passer à la ligne renvoie alors la pastille
   * de compte sur une rangée à elle. Avec une base nulle, les trois tiennent
   * sur la première rangée et le nom du projet occupe ce qui reste. */
  .groupe-projet { min-width: 0; flex: 1 1 0; }
  .fil { min-width: 0; }
  .fil span, .fil b {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 42vw;
  }

  .rangee-outils {
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .rangee-outils::-webkit-scrollbar { display: none; }
  .rangee-outils > * { flex-shrink: 0; }
  .rangee-actions { gap: var(--space-3); }
  .groupe-outils + .groupe-outils { padding-left: var(--space-3); }
  .recherche input { width: 150px; }
  .outils select { max-width: 160px; }
  #fond-carte { margin-left: 0 !important; }

  .corps { position: relative; }

  .panneau {
    position: absolute; left: 0; right: 0; bottom: 0; top: auto;
    width: auto; max-height: 72vh;
    border-left: none; border-top: 1px solid var(--surface-300);
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    box-shadow: var(--ombre-flottant);
    z-index: 900;
    transform: translateY(101%);
    transition: transform .18s ease-out;
  }
  .panneau.ouvert { transform: translateY(0); }
  /* Sans élément choisi, la feuille reste en bas : le message d'invite ne sert
     à rien sur un écran où la carte est déjà l'essentiel. */
  #panneau-vide { display: none; }

  .panneau-fermer {
    display: block; position: sticky; top: 0; z-index: 2;
    width: 100%; border: none; border-bottom: 1px solid var(--surface-300);
    background: var(--surface-100); color: var(--ink-600);
    font-family: var(--font-sans); font-size: 12px; font-weight: 600;
    padding: 10px; cursor: pointer; text-align: center;
  }
  .panneau-photo, .panneau-photo-vide { aspect-ratio: 16 / 9; }

  .legende { max-height: 26vh; font-size: 10px; padding: 8px 10px; left: 10px; bottom: 18px; }
  .tiroir { left: 10px; right: 10px; width: auto; bottom: 18px; }
}

/* ─── Poignées de redimensionnement ──────────────────────────────────────── */
/*
 * Six pixels de large, et une zone sensible plus grande que le trait visible :
 * la cible doit être attrapable sans viser. Le trait ne se montre qu'au
 * survol, pour ne pas ajouter une ligne permanente à une interface qui en a
 * déjà (bordure du volet, bord de la carte).
 */
.poignee {
  flex: 0 0 6px; width: 6px; align-self: stretch;
  cursor: col-resize; position: relative; z-index: 600;
  background: transparent; border: none; padding: 0;
  touch-action: none;
}
.poignee::before {
  content: ''; position: absolute; top: 0; bottom: 0; left: 2px;
  width: 2px; border-radius: 2px; background: transparent;
  transition: background .12s ease;
}
/* La cible réelle déborde de quatre pixels de chaque côté du trait. Sans ce
 * débord, viser six pixels demande une précision que personne n'a : à l'essai,
 * un clic à un pixel du bord atterrissait sur la carte et la faisait glisser
 * au lieu de déplacer le volet. */
.poignee::after { content: ''; position: absolute; inset: 0 -5px; }
.poignee:hover::before { background: var(--surface-300); }
.poignee:focus-visible { outline: none; }
.poignee:focus-visible::before, .poignee:active::before { background: var(--brand-gold); }

/* Pendant le glissement, le curseur ne doit pas changer au survol de la carte
 * et la sélection de texte ne doit pas s'emballer. */
body.redim-en-cours { cursor: col-resize; user-select: none; }
body.redim-en-cours .leaflet-container { cursor: col-resize !important; }

/* ─── Configuration du projet ────────────────────────────────────────────── */

.roue {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; flex-shrink: 0;
  border: 1px solid var(--surface-300); border-radius: var(--radius-md);
  background: var(--surface-200); color: var(--ink-600); cursor: pointer;
}
.roue:hover { border-color: var(--ink-400); color: var(--ink-900); }
.roue svg { width: 17px; height: 17px; }

.modale-config { width: min(880px, 100%); }
.onglets-config {
  display: flex; gap: 2px; margin-bottom: var(--space-4);
  border-bottom: 1px solid var(--surface-300); flex-wrap: wrap;
}
.onglets-config button {
  border: none; background: none; cursor: pointer;
  font-family: var(--font-sans); font-size: 13px; font-weight: 600;
  color: var(--ink-400); padding: 8px 12px;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.onglets-config button:hover { color: var(--ink-900); }
.onglets-config button.actif { color: var(--ink-900); border-bottom-color: var(--brand-gold); }

.bloc-config { margin-bottom: var(--space-6); }
.bloc-config > h3 { margin-bottom: var(--space-1); }
.bloc-config > .petit { margin: 0 0 var(--space-3); }

/* Une entrée de référentiel : case de sélection, pastille de couleur, nom,
 * champs propres au type, puis les commandes d'ordre et de suppression. */
.liste-ref {
  border: 1px solid var(--surface-300); border-radius: var(--radius-md);
  overflow: hidden;
}
.ligne-ref {
  display: flex; align-items: center; gap: var(--space-2);
  padding: 7px var(--space-3); border-bottom: 1px solid var(--surface-300);
  font-size: 13px;
}
.ligne-ref:last-child { border-bottom: none; }
.ligne-ref.ecartee { background: var(--surface-200); color: var(--ink-400); }
.ligne-ref input[type=checkbox], .ligne-ref input[type=radio] { width: auto; flex-shrink: 0; }
.ligne-ref .nom-ref { flex: 1; min-width: 90px; }
.ligne-ref .champ-ref { width: 74px; flex-shrink: 0; }
.ligne-ref .champ-ref-large { width: 128px; flex-shrink: 0; }
.ligne-ref input[type=color] {
  width: 30px; height: 26px; padding: 1px; flex-shrink: 0;
  border: 1px solid var(--surface-300); border-radius: var(--radius-sm);
  background: var(--surface-100); cursor: pointer;
}
.ligne-ref .drapeau {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; color: var(--ink-600); white-space: nowrap;
}
.ligne-ref .commandes { display: flex; gap: 2px; margin-left: auto; flex-shrink: 0; }
.ligne-ref .commandes button {
  border: 1px solid var(--surface-300); background: var(--surface-100);
  color: var(--ink-600); border-radius: var(--radius-sm);
  width: 24px; height: 24px; cursor: pointer; font-size: 12px; line-height: 1;
  padding: 0; font-family: var(--font-sans);
}
.ligne-ref .commandes button:hover:not(:disabled) { border-color: var(--ink-400); color: var(--ink-900); }
.ligne-ref .commandes button:disabled { opacity: .3; cursor: not-allowed; }

.marque-base {
  font-size: 10px; text-transform: uppercase; letter-spacing: .4px;
  color: var(--ink-400); white-space: nowrap;
}
.marque-projet {
  font-size: 10px; text-transform: uppercase; letter-spacing: .4px;
  color: var(--brand-gold-ink); background: rgba(243, 187, 68, .25);
  padding: 2px 6px; border-radius: var(--radius-pill); white-space: nowrap;
}
.compte-usage {
  font-family: var(--font-mono); font-size: 11px; color: var(--ink-400);
  white-space: nowrap;
}

.avertissement-base {
  background: rgba(166, 51, 40, .08); border: 1px solid rgba(166, 51, 40, .35);
  color: var(--danger); border-radius: var(--radius-md);
  padding: 8px 12px; font-size: 12px; line-height: 17px; margin-bottom: var(--space-3);
}
.bascule-base {
  display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  font-size: 12px; color: var(--ink-600); margin-bottom: var(--space-3);
}
.bascule-base input { width: auto; }

/* Le fil d'Ariane et sa roue crantée forment un bloc : la roue reste collée
 * au nom du projet qu'elle configure, et non à la distance de l'en-tête. */
/* Pas de `min-width: 0` ici : le groupe pourrait alors se réduire à rien sur
 * un écran étroit, emportant la roue avec lui. Le rétrécissement est porté par
 * le fil d'Ariane lui-même (`.fil { min-width: 0 }`), de sorte que le nom du
 * projet se tronque mais que la roue reste atteignable. */
.groupe-projet { display: flex; align-items: center; gap: 6px; }

@media (max-width: 860px) {
  .poignee { display: none; }
}

/* ─── Itinéraires calculés : terrain, points de passage, accès ────────────── */

/* Ce qui arrête quelqu'un se dit en rouge et se lit avant le reste : un
 * parcours qui comporte cent mètres d'escaliers n'est pas une variante
 * commode, c'est un parcours impraticable pour une partie du public. */
.alerte-terrain {
  background: rgba(166, 51, 40, .08); border: 1px solid rgba(166, 51, 40, .32);
  border-radius: var(--radius-md); padding: 8px 10px; margin-bottom: 6px;
  font-size: 12px; line-height: 17px; color: var(--danger);
}
.alerte-terrain b { display: block; color: var(--danger); }
.alerte-terrain div { color: var(--ink-600); margin-top: 2px; }

.ligne-passage {
  display: flex; align-items: center; gap: 7px; margin-bottom: 4px;
}
.ligne-passage .mono { flex: 1; }
.numero-passage {
  display: inline-flex; align-items: center; justify-content: center;
  width: 19px; height: 19px; border-radius: 50%; flex-shrink: 0;
  background: var(--ink-900); color: var(--surface-100);
  font-size: 10px; font-weight: 700; font-family: var(--font-mono);
}

/* Un point de forme n'est pas un lieu : rond, sombre, numéroté, et nettement
 * distinct de la goutte d'un point d'orientation. */
.marqueur-passage {
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--ink-900); color: var(--surface-100);
  border: 2px solid var(--surface-100); box-sizing: border-box;
  display: flex; align-items: center; justify-content: center;
  font-size: 9px; font-weight: 700; font-family: var(--font-mono);
  box-shadow: 0 1px 4px rgba(0, 0, 0, .35); cursor: move;
}

.marqueur-acces {
  width: 20px; height: 20px; border-radius: var(--radius-sm);
  background: var(--surface-100); color: var(--ink-600);
  border: 2px solid var(--ink-400); box-sizing: border-box;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; line-height: 1; box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
}
.marqueur-acces.pmr { border-color: var(--success); color: var(--success); }
/* Tant que personne n'est allé voir, le bord reste ouvert : la carte propose,
 * le terrain confirme. */
.marqueur-acces.a-confirmer { border-style: dashed; opacity: .75; }

/* ─── Colonne des organisations (écran d'accueil) ─────────────────────────── */

.colonne-organisations {
  width: 260px; flex-shrink: 0; overflow-y: auto;
  background: var(--surface-100); border-right: 1px solid var(--surface-300);
  padding: var(--space-2) 0 var(--space-6);
}
.entete-colonne {
  display: flex; align-items: center; gap: 8px;
  padding: var(--space-3) var(--space-3) var(--space-2);
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .5px; color: var(--ink-600);
}
.entete-colonne span { flex: 1; }
.entete-colonne .bouton { padding: 2px 9px; }

.ligne-organisation {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  border: none; background: none; cursor: pointer;
  font-family: var(--font-sans); font-size: 13px; color: var(--ink-900);
  padding: 7px var(--space-3); border-left: 3px solid transparent;
}
.ligne-organisation:hover { background: var(--surface-200); }
.ligne-organisation.choisie { border-left-color: var(--brand-gold); background: var(--surface-200); }
.ligne-organisation .nom { flex: 1; }
.recherche-organisations {
  width: calc(100% - 2 * var(--space-3)); margin: 0 var(--space-3) 8px;
  font-size: 12px; padding: 5px 8px;
}
.ligne-organisation .compte {
  color: var(--ink-400); font-family: var(--font-mono); font-size: 11px;
}

@media (max-width: 860px) {
  .colonne-organisations { display: none; }
}

/* Où en est un projet, sur sa carte d'accueil. */
.avancement { margin-top: var(--space-1); }
.avancement-barre {
  height: 4px; border-radius: 2px; background: var(--surface-300);
  overflow: hidden; margin-bottom: 4px;
}
.avancement-fait { height: 100%; background: var(--ink-400); }
/* Une étape qui attend une décision du client se voit : c'est la seule qui
 * demande quelque chose à quelqu'un. */
.avancement.attend .avancement-fait { background: var(--brand-gold); }
.avancement.attend .tres-sourdine { color: var(--brand-gold-ink); font-weight: 600; }

/* ─── Formes des supports, et en-têtes des référentiels ──────────────────── */

.entete-ref {
  background: var(--surface-200);
  font-size: 10px; text-transform: uppercase; letter-spacing: .4px;
  color: var(--ink-400); font-weight: 700; padding-top: 5px; padding-bottom: 5px;
}
.entete-ref .colonne-case, .ligne-ref input.colonne-case {
  width: 15px; flex-shrink: 0; text-align: center;
}
.entete-ref .entete-etroit { width: 30px; flex-shrink: 0; }
/* 128 px de liste + 5 px d'écart + 34 px de vignette. */
.entete-ref .entete-forme { width: 167px; flex-shrink: 0; }
.entete-ref .entete-drapeau { width: auto; flex-shrink: 0; white-space: nowrap; }
.entete-ref .commandes { width: 54px; }
.entete-ref [title] { cursor: help; border-bottom: 1px dotted var(--ink-400); }

.champ-forme { display: flex; align-items: center; gap: 5px; flex-shrink: 0; }
.vignette-forme {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 22px; flex-shrink: 0;
}

/* Les silhouettes sont dessinées en SVG par static/js/configuration.js : un
 * même dessin sert la configuration et la carte, de sorte que ce qu'on règle
 * est exactement ce qu'on verra. Le SVG porte ses propres dimensions ; il ne
 * reste ici que l'alignement. */
.forme {
  display: inline-block; box-sizing: border-box;
  border-style: solid; border-width: 2px;
  background: var(--fond, #E7E3DB); border-color: var(--bord, #191715);
}
.forme-rectangle { width: 30px; height: 14px; border-radius: 1px; }
.forme-totem { width: 30px; height: 14px; border-radius: 2px; border-width: 3px; }
.forme-carre { width: 16px; height: 16px; border-radius: 1px; }
.forme-cercle { width: 16px; height: 16px; border-radius: 50%; }
.forme-bandeau { width: 32px; height: 8px; border-radius: 1px; }
/* La pointe est EN HAUT, comme le devant de toutes les autres formes : c'est
   le haut de la boîte qui regarde la direction, et la rotation part de là.
   Avec la pointe à droite, une orientation « nord » dessinait une flèche vers
   l'est. La lame est haute et étroite : c'est une lame, pas une plaque. */
.forme-fleche {
  width: 15px; height: 32px; border: none; position: relative;
  background: var(--bord, #191715);
  clip-path: polygon(50% 0, 100% 26%, 100% 100%, 0 100%, 0 26%);
}
.forme-fleche::after {
  content: ''; position: absolute; inset: 2.5px;
  background: var(--fond, #E7E3DB);
  clip-path: polygon(50% 0, 100% 26%, 100% 100%, 0 100%, 0 26%);
}
/* La pointe est la face lisible d'une lame : c'est elle qu'on colore. */
.forme-fleche.faces-1, .forme-fleche.faces-2,
.forme-fleche.faces-3, .forme-fleche.faces-4, .forme-fleche.cote-recto,
.forme-fleche.cote-verso {
  background: linear-gradient(to bottom, var(--face, var(--bord)) 34%, var(--bord) 34%);
}
/* Deux formes découpées : la bordure est alors remplacée par un liseré posé
   sous la forme, faute de quoi `clip-path` la rognerait. */
.forme-triangle, .forme-trapeze {
  width: 20px; height: 18px; border: none; position: relative;
  background: var(--bord, #191715);
}
.forme-triangle { clip-path: polygon(50% 0, 100% 100%, 0 100%); }
/* Grand côté parallèle devant : c'est lui qui porte la bande de face. */
.forme-trapeze { width: 22px; height: 16px; clip-path: polygon(0 0, 100% 0, 82% 100%, 18% 100%); }
.forme-triangle::after, .forme-trapeze::after {
  content: ''; position: absolute; inset: 2.5px;
  background: var(--fond, #E7E3DB);
}
.forme-triangle::after { clip-path: polygon(50% 0, 100% 100%, 0 100%); }
.forme-trapeze::after { clip-path: polygon(0 0, 100% 0, 82% 100%, 18% 100%); }

/* Le côté qui porte une face lisible. Combien de côtés sont marqués découle du
   nombre de faces du type : un seul devant, deux en vis-à-vis, ou tout le tour. */
.forme.faces-1, .forme.cote-recto { border-top-color: var(--face, var(--bord)); }
.forme.faces-2 {
  border-top-color: var(--face, var(--bord));
  border-bottom-color: var(--face, var(--bord));
}
.forme.faces-3, .forme.faces-4 { border-color: var(--face, var(--bord)); }
/* Le verso d'une plaque présente l'autre côté : c'est le bas de la silhouette
   qui porte alors la face lisible. */
.forme.cote-verso { border-bottom-color: var(--face, var(--bord)); }

/* Les deux formes découpées ne savent pas désigner une arête : `clip-path`
   supprime la bordure. On colore la moitié qui fait face — cela dit « ce
   côté-ci vous regarde » plutôt que « cette arête est la face », et c'est la
   limite assumée du choix de rester en CSS. */
.forme-triangle.faces-3, .forme-triangle.faces-4,
.forme-trapeze.faces-3, .forme-trapeze.faces-4 { background: var(--face, var(--bord)); }
.forme-triangle.faces-1, .forme-triangle.faces-2, .forme-triangle.cote-recto,
.forme-trapeze.faces-1, .forme-trapeze.faces-2, .forme-trapeze.cote-recto {
  background: linear-gradient(to bottom, var(--face, var(--bord)) 50%, var(--bord) 50%);
}
.forme-triangle.cote-verso, .forme-trapeze.cote-verso {
  background: linear-gradient(to bottom, var(--bord) 50%, var(--face, var(--bord)) 50%);
}

/* ─── Volet 3 : la carte et les annonces côte à côte ──────────────────────── */

.colonne-suivi {
  width: var(--largeur-volet, 420px); flex-shrink: 0; overflow-y: auto;
  background: var(--surface-200); border-left: 1px solid var(--surface-300);
  padding: var(--space-4);
}
.colonne-suivi > h2 { margin: var(--space-4) 0 var(--space-2); font-size: 16px; }
.colonne-suivi > h2:first-child { margin-top: 0; }

/* Une annonce ouverte se distingue : c'est elle que la carte montre. */
.carte-bloc.choisie {
  border-color: var(--brand-gold); box-shadow: 0 0 0 2px rgba(243, 187, 68, .35);
}
.carte-bloc[data-cliquable] { cursor: pointer; }
.carte-bloc[data-cliquable]:hover { border-color: var(--ink-400); }

/* Le mât visé par l'annonce ouverte, et l'endroit d'où elle a été faite. */
.marqueur-structure.vise {
  box-shadow: 0 0 0 4px rgba(166, 51, 40, .55), 0 1px 6px rgba(0, 0, 0, .35);
}
.marqueur-signaleur {
  width: 13px; height: 13px; border-radius: 50%;
  background: var(--danger); border: 2px solid var(--surface-100);
  box-sizing: content-box; box-shadow: 0 1px 4px rgba(0, 0, 0, .35);
}
.legende-suivi-ligne { display: flex; align-items: center; gap: 7px; margin-top: 4px; }

@media (max-width: 860px) {
  .colonne-suivi {
    width: auto; border-left: none; border-top: 1px solid var(--surface-300);
  }
  .corps { flex-direction: column; }
  .zone-carte { min-height: 240px; flex: 0 0 240px; }
}

/* ─── Marqueur d'une structure : sa silhouette, tournée, et son code ──────── */
/*
 * Le fond dit ce qu'est la structure (le type), le bord dit dans quel état
 * elle est. Le code reste à côté, jamais tourné : une étiquette illisible
 * n'identifie plus rien.
 */
.marqueur-structure2 {
  position: absolute; left: -11px; top: -11px;
  display: flex; align-items: center; gap: 4px; white-space: nowrap;
}
.forme-structure {
  flex-shrink: 0; display: inline-flex; transform-origin: center;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .45));
  /* Ancre de la poignée de rotation : c'est la silhouette qui tourne, donc
     c'est elle qui porte la poignée. */
  position: relative;
}
.forme-structure .forme { display: block; }

.etiquette-structure {
  font-family: var(--font-mono); font-size: 10px; font-weight: 700;
  color: var(--ink-900); background: rgba(255, 255, 255, .85);
  border-radius: 3px; padding: 0 3px; line-height: 14px;
}
.marqueur-structure2.choisi .forme-structure {
  filter: drop-shadow(0 0 3px var(--brand-gold)) drop-shadow(0 0 3px var(--brand-gold));
}
.marqueur-structure2.choisi .etiquette-structure {
  background: var(--brand-gold); color: var(--brand-gold-ink);
}

/* ─── En-tête d'une fenêtre, avec sa croix ───────────────────────────────── */
/*
 * La fenêtre de configuration ne se ferme plus au clic à côté : on y règle des
 * listes entières, et un clic manqué faisait perdre ce qui n'était pas encore
 * enregistré. Il faut donc une sortie visible — la croix — en plus d'Échap et
 * du bouton « Fermer ».
 */
.fenetre-entete {
  display: flex; align-items: flex-start; gap: var(--space-3);
  margin-bottom: var(--space-4);
}
.fenetre-entete h2 { flex: 1; margin-bottom: 0; }
.fenetre-fermer {
  flex-shrink: 0; width: 30px; height: 30px; margin: -2px -2px 0 0;
  border: 1px solid var(--surface-300); border-radius: var(--radius-md);
  background: var(--surface-100); color: var(--ink-600);
  font-family: var(--font-sans); font-size: 14px; line-height: 1;
  cursor: pointer;
}
.fenetre-fermer:hover {
  border-color: var(--danger); color: var(--danger); background: var(--surface-100);
}

/* Un support, posé à côté de son mât. Le décalage est en pixels : un support
   mesure quelques décimètres et disparaîtrait à tout zoom utile. Ce qu'on
   dessine est un symbole de montage, pas une mesure. */
/* Une boîte de dimension nulle, centrée en flex : la forme déborde alors
   également des deux côtés, donc elle est centrée sur le point quelle que soit
   sa taille. Des marges fixes ne marchaient que pour une seule forme. */
.marqueur-support {
  position: absolute; transform-origin: center;
  width: 0; height: 0;
  display: flex; align-items: center; justify-content: center;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .45));
  cursor: pointer;
}
.marqueur-support .forme { display: block; flex-shrink: 0; }

/* ─── Poignée de rotation d'un support ───────────────────────────────────── */
/* L'orientation se choisissait dans une liste de seize points cardinaux, sur
   la fiche : il fallait traduire ce qu'on voyait en « NNE ». On tourne
   maintenant la silhouette à la main. La poignée est DANS le bloc tourné,
   donc elle montre la direction avant même qu'on l'attrape. */
.tige-rotation {
  position: absolute; left: -1px; top: -30px;
  width: 2px; height: 22px;
  background: var(--brand-gold);
  box-shadow: 0 0 2px rgba(0, 0, 0, .6);
  pointer-events: none;
}
.poignee-rotation {
  position: absolute; left: -8px; top: -38px;
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--brand-gold); border: 2px solid #fff;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .55);
  cursor: grab; touch-action: none;
}
.poignee-rotation:hover { transform: scale(1.15); }
.en-rotation .poignee-rotation { cursor: grabbing; transform: scale(1.15); }
/* Sur une structure, la poignée s'accroche à la silhouette, qui a une taille.
   On la place donc depuis son CENTRE et non depuis un coin, pour qu'elle
   tombe aux mêmes distances que sur un support, dont la boîte est de
   dimension nulle. */
.forme-structure .tige-rotation { left: calc(50% - 1px); top: 50%; margin-top: -30px; }
.forme-structure .poignee-rotation { left: calc(50% - 8px); top: 50%; margin-top: -38px; }

/* Pendant la rotation, la silhouette suit le pointeur sans transition : une
   animation de 0,1 s suffit à donner l'impression que la poignée décroche. */
.en-rotation .marqueur-support,
.en-rotation .forme-structure { transition: none; }
.marqueur-support.choisi .forme {
  filter: drop-shadow(0 0 3px var(--brand-gold)) drop-shadow(0 0 3px var(--brand-gold));
}

/* ─── Listes réordonnables au glisser-déposer ────────────────────────────── */
/* Les flèches ↑ ↓ déplaçaient d'un cran : ramener le onzième point en second
   demandait neuf clics, et neuf recalculs d'itinéraire. */
.reordonnable { cursor: grab; }
.reordonnable:active { cursor: grabbing; }
.reordonnable.en-deplacement { opacity: .4; }
.reordonnable.cible-dessus { box-shadow: 0 -2px 0 0 var(--brand-gold, #f3bb44); }
.reordonnable.cible-dessous { box-shadow: 0 2px 0 0 var(--brand-gold, #f3bb44); }

/* ─── Volet 4 — le budget ────────────────────────────────────────────────── */
/* Une page de lecture, pas une carte : une colonne étroite, des montants
   alignés à droite, et rien qui bouge quand on déplie un détail. */

.page-budget {
  flex: 1; overflow: auto; padding: var(--space-6) var(--space-4) 80px;
}
.page-budget #contenu {
  max-width: 760px; margin: 0 auto;
  display: flex; flex-direction: column; gap: var(--space-6);
}

.budget-chapeau {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--space-6); flex-wrap: wrap;
}
.budget-somme-nom { font-size: 12px; color: var(--ink-400); }
.budget-somme-valeur {
  font-size: 30px; font-weight: 600; letter-spacing: -.01em;
}
.budget-chapeau-reglages { width: 200px; }
.budget-chapeau-reglages .champ { margin-bottom: var(--space-1); }

.budget-bloc {
  background: var(--surface-100);
  border: 1px solid var(--surface-300);
  border-radius: var(--radius-md);
  padding: var(--space-4);
}
.budget-bloc-tete {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--space-3);
}
.budget-bloc-tete h2 { font-size: 15px; margin: 0; }
.budget-bloc-total { font-weight: 600; font-variant-numeric: tabular-nums; }
.budget-bloc > p { margin: var(--space-1) 0 var(--space-3); }

.budget-ligne {
  border-top: 1px solid var(--surface-300);
  padding: var(--space-3) 0;
}
.budget-ligne:last-child { padding-bottom: 0; }

/* La tête d'une ligne calculée est un bouton : il faut donc lui retirer tout
   ce qu'un bouton porte par défaut, sans lui retirer son focus visible. */
.budget-ligne-tete {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--space-3); width: 100%;
  background: none; border: none; padding: 0; margin: 0;
  font: inherit; color: inherit; text-align: left;
}
button.budget-ligne-tete { cursor: pointer; }
button.budget-ligne-tete:hover .budget-ligne-nom { color: var(--ink-900); }
.budget-ligne-nom { font-weight: 600; }
.budget-ligne-montant { font-variant-numeric: tabular-nums; white-space: nowrap; }
.budget-chevron { color: var(--ink-400); font-weight: 400; }

.budget-postes { display: flex; flex-direction: column; gap: 6px; margin: var(--space-2) 0; }
.budget-poste { display: flex; gap: 6px; align-items: center; }
.budget-poste input { margin: 0; }
.budget-poste input.budget-poste-libelle { flex: 1; min-width: 60px; width: auto; }
.budget-poste input.budget-poste-jours { width: 78px; flex: none; }
.budget-poste input.budget-poste-montant {
  width: 108px; flex: none; text-align: right;
}

.budget-detail {
  margin-top: var(--space-2);
  border-left: 2px solid var(--surface-300);
  padding-left: var(--space-3);
}
.budget-detail-ligne {
  display: grid; grid-template-columns: 1fr auto auto;
  gap: var(--space-3); padding: 3px 0; font-size: 13px;
}
.budget-detail-ligne > :last-child {
  min-width: 96px; text-align: right; font-variant-numeric: tabular-nums;
}
.budget-detail-tete { color: var(--ink-400); font-size: 11px; }

.budget-total {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--space-3);
  background: var(--ink-900); color: var(--surface-100);
  border-radius: var(--radius-md); padding: var(--space-4);
}
.budget-total-nom { font-weight: 600; }
.budget-total-valeur {
  font-size: 22px; font-weight: 600; font-variant-numeric: tabular-nums;
}

/* Ce qui revient chaque année n'est pas du même ordre que l'investissement :
   le fond le dit avant qu'on ait lu la note. */
.budget-annuel { background: var(--surface-200); }

/* Un montant retenu qui s'écarte du calcul. Le liseré suffit : le montant
   lui-même se lit comme les autres, c'est bien lui qui fait foi. */
.budget-ligne-ajustee { border-left: 2px solid var(--warning); padding-left: 10px; }
.budget-ajuste {
  display: flex; align-items: baseline; gap: var(--space-2);
  flex-wrap: wrap; margin: 4px 0 var(--space-2);
  font-size: 12px; color: var(--warning);
}
.lien-bouton {
  background: none; border: none; padding: 0; font: inherit; color: inherit;
  text-decoration: underline; cursor: pointer;
}
.lien-bouton:hover { color: var(--ink-900); }

@media (max-width: 720px) {
  .budget-chapeau-reglages { width: 100%; }
  .budget-poste { flex-wrap: wrap; }
  .budget-poste-libelle { flex: 1 1 100%; }
}

/* Le pied de la page de connexion : les textes légaux, lisibles sans compte. */
.pied-connexion {
  display: flex; justify-content: center; gap: var(--space-4);
  flex-wrap: wrap; margin: var(--space-6) 0 0; text-align: center;
  width: min(380px, 100%);
}
.pied-connexion a { color: var(--ink-400); text-decoration: none; }
.pied-connexion a:hover { color: var(--ink-900); text-decoration: underline; }
