/* Palette inspirée des maquettes (sidebar navy, accent bleu, fond gris clair) */
:root {
  /* Navy : tons un cran plus clairs qu'a l'origine (#1a2340/#2d3a5e) pour
     adoucir l'impression "trop sombre" du header / sidebar / total bars.
     Garde un contraste AAA avec texte blanc (#fff). */
  --navy: #2a3656;
  --navy-2: #3d4a6e;
  /* Sidebar : palette dediee plus sombre (slate-800-ish), inspiree d'Intus.
     Decouple du `--navy` global qui sert aussi de couleur de texte ailleurs. */
  --sidebar-bg: #1e293b;
  --sidebar-bg-2: #334155;
  /* Hauteur de la barre d'onglets de projets : 0 hors PWA, 32px dans la PWA
     quand elle est rendue (cf. `.onglets-bar`). Le side panel s'en sert pour
     tenir dans ce qui reste de la fenetre. */
  --onglets-h: 0px;
  --blue: #3b6ef5;
  --blue-2: #2d5dd4;
  --bg: #f4f6f9;
  --surface: #ffffff;
  /* Texte principal : reste sur l'ancien navy foncé pour la lisibilité du
     corps de texte sur fond clair (le navy clair serait trop pâle). */
  --text: #1a2340;
  --muted: #888;
  --border: #dde1ea;
  --danger: #d64545;
  --danger-bg: #fdecec;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html {
  /* Gouttiere d'ascenseur TOUJOURS reservee, meme sans debordement.
     Sans ca, une page haute (Analytique, Chiffrage) affiche l'ascenseur et
     retrecit la largeur utile de ~15 px, une page courte (Informations) non :
     la barre d'onglets, centree via `justify-content:center`, sautait de 7 px
     d'un onglet a l'autre. Mesure du 2026-09-21 a 1400 px : `.projet-tabs-inner`
     a gauche=302 avec ascenseur, 309 sans -- exactement la moitie des 15 px.
     Corriger ici plutot que de decentrer la barre : le probleme est la largeur
     utile qui change, il toucherait tout autre contenu centre.
     Navigateurs sans support (Safari < 18.2) : comportement actuel, pas pire. */
  scrollbar-gutter: stable;
  /* Le fond ne vient que de `body` : sans cette ligne, le canvas reste blanc
     tant que la feuille n'est pas appliquee. */
  background: var(--bg);
}

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  background: var(--bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--blue); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ----- Page de login (centrée verticalement) ----- */
.login-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.login-card {
  background: var(--surface);
  border-radius: 16px;
  box-shadow: 0 8px 32px rgba(26, 35, 64, 0.08);
  padding: 40px 36px;
  width: 100%;
  max-width: 400px;
}

.login-card h1 {
  font-size: 22px;
  font-weight: 700;
  margin-bottom: 6px;
  color: var(--navy);
}

.login-card .subtitle {
  font-size: 13px;
  color: var(--muted);
  margin-bottom: 28px;
}

.login-footer {
  margin-top: 18px;
  text-align: center;
  font-size: 13px;
}
.login-footer a { color: var(--blue); }

/* Page de consentement OAuth du connecteur Claude (templates/connecteur/
   consentement.html) : meme carte que la connexion, un peu plus large pour
   la liste de ce que Claude pourra faire. */
.login-card.consentement { max-width: 480px; }
.login-card.consentement .subtitle { margin-bottom: 16px; }
.consentement-liste {
  margin: 0 0 24px;
  padding-left: 18px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--text);
}
.consentement-liste li + li { margin-top: 6px; }
.consentement-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

/* Page « Connecteur Claude » (templates/connecteur/connexion.html). */
.claude-etat { padding: 20px 24px; margin-bottom: 24px; }
.claude-etat-titre {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 8px;
  font-weight: 700;
  color: var(--navy);
}
.claude-etat-detail { margin: 0 0 14px; font-size: 13px; color: var(--muted); }
.claude-etapes { margin: 0 0 12px; padding-left: 18px; font-size: 13px; line-height: 1.6; }
.claude-pastille {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--muted);
}
.claude-pastille--on { background: #2e9e5b; }
.claude-titre-section { margin: 0 0 12px; font-size: 15px; color: var(--navy); }
.claude-refus { color: #b3412c; }

.field {
  margin-bottom: 18px;
}

.field label {
  display: block;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  font-weight: 600;
  margin-bottom: 6px;
}

.field input[type="text"],
.field input[type="password"],
.field input[type="email"] {
  width: 100%;
  padding: 11px 14px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 14px;
  font-family: inherit;
  background: var(--surface);
  color: var(--text);
  transition: border-color 0.15s, box-shadow 0.15s;
}

.field input:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(59, 110, 245, 0.15);
}

.btn {
  display: inline-block;
  background: var(--blue);
  color: #fff;
  border: none;
  padding: 11px 22px;
  border-radius: 8px;
  cursor: pointer;
  font-size: 14px;
  font-weight: 600;
  font-family: inherit;
  text-decoration: none;
  transition: background 0.15s;
}

.btn:hover { background: var(--blue-2); text-decoration: none; }
.btn-block { display: block; width: 100%; }
.btn-ghost {
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--border);
}
.btn-ghost:hover { background: var(--bg); color: var(--text); }
/* Variante verte : actions de validation / archivage / cloture. Echo
   du V vert dans la sidebar lots et du bouton "Valider le chiffrage". */
.btn-success {
  background: #1f8a4c;
  color: #fff;
}
.btn-success:hover { background: #176c3a; }
/* Variante rouge : actions destructives (suppression, revert avec
   perte de donnees). Usage rare, exige `hx-confirm` cote template. */
.btn-danger {
  background: var(--danger);
  color: #fff;
}
.btn-danger:hover { background: #b53838; }
/* Variante orange : actions semi-destructives mais recuperables
   (revert vers une version archivee : on perd la modif live, mais
   la version archivee de depart reste intacte). */
.btn-warning {
  background: #d6841a;
  color: #fff;
}
.btn-warning:hover:not(:disabled) { background: #b56d10; }
.btn-warning:disabled {
  background: #e8d6b7;
  color: #fff;
  cursor: not-allowed;
}

.alert {
  background: var(--danger-bg);
  color: var(--danger);
  border-radius: 8px;
  padding: 10px 14px;
  font-size: 13px;
  margin-bottom: 16px;
  border: 1px solid rgba(214, 69, 69, 0.2);
}

/* ----- App layout (sidebar + main) ----- */
.app {
  display: grid;
  /* `minmax(0, 1fr)` et non `1fr` : une piste `1fr` ne descend jamais sous la
     largeur minimale de son contenu. Un tableau trop large élargissait donc
     toute la colonne au-delà de la fenêtre, et la page défilait de côté avec
     le bouton « + Nouveau projet » coupé (recette 2026-10-21, B7). */
  grid-template-columns: 240px minmax(0, 1fr);
  min-height: calc(100vh - var(--onglets-h));
}

/* Side panel calqué sur Intus : dégradé slate vertical (700 -> 800 -> 900),
   nav à icônes avec barre d'accent bleu/violet sur l'item actif.

   Collé à la fenêtre, PAS étiré sur la hauteur de la page. Étiré (le
   comportement par défaut d'une cellule de grille), il mesurait la hauteur
   du contenu : dès que la page dépassait l'écran, le bloc du bas (carte
   utilisateur, Déconnexion) partait sous la ligne de flottaison, et il
   montait ou descendait à chaque groupe de projets replié / déplié. Le
   dégradé s'étirait avec lui : la teinte à l'écran changeait d'une page à
   l'autre (bas du panneau #10182b sur une page courte, #2e3b4f sur une
   page de 6 000px).
   `overflow-y` : sur une fenêtre très basse, le panneau défile au lieu de
   couper son pied.
   Dans la PWA, la barre d'onglets (non collante) occupe le haut de page : le
   panneau fait donc 100vh moins sa hauteur, pour tenir entier au chargement.
   Une fois la barre sortie par le défilement, l'ombre pleine comble les
   32px restants sous le panneau, du ton du bas du dégradé. */
.sidebar {
  position: sticky;
  top: 0;
  align-self: start;
  height: calc(100vh - var(--onglets-h));
  overflow-y: auto;
  box-shadow: 0 var(--onglets-h) 0 #0f172a;
  background: linear-gradient(to bottom, #334155 0%, #1e293b 55%, #0f172a 100%);
  color: #fff;
  padding: 24px 0;
  display: flex;
  flex-direction: column;
}
/* En-tête : logo, filet bas discret (comme le header Intus). */
.sidebar-header {
  padding: 4px 22px 18px;
  border-bottom: 1px solid rgba(148, 163, 184, 0.18);
}

/* Brand : logotype Quanto en haut de la sidebar. Le "Q" est mis en
   valeur (gros, gradient bleu cyan, weight extra-bold) et "uanto"
   l'accompagne en regular weight. Pas de container/box autour du Q --
   c'est juste une lettre stylee qui sert de marque visuelle.
   Cliquable -> retour au dashboard. */
.sidebar .brand {
  display: flex;
  align-items: baseline;        /* baseline pour aligner le Q et uanto sur la meme ligne typo */
  gap: 0;                       /* Q et uanto collés, c'est un logotype unifie */
  text-decoration: none;
  user-select: none;
}
.sidebar .brand:hover { text-decoration: none; }
/* Logotype : rebrand charte Batiprisme 2026-07 -> composant .bp-logo
   (static/batiprisme/css/logo.css : Poppins self-host, "Q" orange plein,
   sans degrade). Les anciennes regles .brand-mark / .brand-name (Q gradient
   bleu, Helvetica Neue) ont ete retirees. On garde juste le hover du wrapper. */
.sidebar .brand .bp-logo__ini {
  transition: filter 0.2s, transform 0.2s;
}
.sidebar .brand:hover .bp-logo__ini {
  filter: brightness(1.08);
  transform: translateY(-1px);
}

.sidebar nav {
  margin-top: 16px;
  padding: 0 12px;            /* insets pour que la pastille active ne touche pas les bords */
}

/* Nav à icônes (Heroicons) + libellé. Item actif = barre d'accent à gauche
   (bleu -> violet) + léger voile blanc (UI Intus). */
.sidebar nav a {
  position: relative;
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 12px;
  margin-bottom: 2px;
  border-radius: 8px;
  color: #cbd5e1;
  font-size: 14px;
  transition: background 0.12s, color 0.12s;
}
/* Barre d'accent à gauche : hauteur 0 par défaut, grandit sur l'item actif. */
.sidebar nav a::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 0;
  background: linear-gradient(to bottom, #3b82f6, #8b5cf6);
  border-radius: 0 3px 3px 0;
  transition: height 0.2s ease;
}
.sidebar nav a.active::before { height: 60%; }
.sidebar nav a .ic {
  width: 1.05em;
  height: 1.05em;
  flex: none;
  opacity: 0.92;
  transition: transform 0.15s ease;
}
.sidebar nav a:hover .ic { transform: scale(1.1); }

.sidebar nav a:hover {
  background: rgba(255, 255, 255, 0.06);
  color: #fff;
  text-decoration: none;
}
.sidebar nav a.active {
  background: rgba(255, 255, 255, 0.06);
  color: #fff;
  text-decoration: none;
}
.sidebar nav a.active:hover { background: rgba(255, 255, 255, 0.09); }
/* Lien qui s'ouvre dans une autre fenetre (Quantify) : fleche discrete a droite. */
.sidebar nav a .ic-externe { margin-left: auto; width: 0.85em; height: 0.85em; opacity: 0.45; }
.sidebar nav a:hover .ic-externe { transform: none; opacity: 0.9; }

/* Bloc bas du sidebar (Utilisateurs + carte user). margin-top: auto pousse
   tout le bloc en bas du sidebar, juste au-dessus du bord, sans qu'on ait
   besoin de combiner plusieurs `margin-top: auto` qui se feraient
   concurrence sur la repartition du flex remaining-space. */
.sidebar-bottom-block {
  margin-top: auto;
}

/* Le nav "secondaire" (Utilisateurs) reutilise le styling du nav principal
   pour la coherence visuelle. Petit separateur subtil au-dessus pour
   marquer la rupture entre les sections fonctionnelles (Projets/Annuaire/
   Bibliotheque) et l'administration (Utilisateurs). */
/* Le nav du bas (Utilisateurs) est aussi un <nav> dans .sidebar : il hérite
   donc du style "bullet list" + pastille bleue de `.sidebar nav a` ci-dessus.
   On ne garde ici que le séparateur + les insets horizontaux pour aligner
   la pastille sur celle du nav principal. */
.sidebar-bottom-nav {
  border-top: 1px solid rgba(148, 163, 184, 0.18);
  padding: 8px 12px 0;
  margin-top: 0;
}

/* User card en bas de sidebar : avatar avec initiales + pastille de presence
   verte pulsante, nom + statut (fonction / role), bouton "Deconnexion" avec
   cadenas. Inspire de la design Intus (Tailwind reecrit en CSS custom).
   Classes prefixees `sidebar-` pour eviter le conflit avec `.user-card` /
   `.user-avatar` / `.user-name` deja utilises sur la page Utilisateurs. */
.sidebar-user-card-wrap {
  /* margin-top: auto vit desormais sur .sidebar-bottom-block (le parent),
     qui pousse l'ensemble (utilisateurs nav + carte user) en bas du sidebar.
     Cf. layout/_sidebar.html. */
  padding: 12px;
  border-top: 1px solid rgba(148, 163, 184, 0.18);
}
.sidebar-user-card {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px;
  border-radius: 8px;
  background: transparent;
}
.sidebar-user-avatar-wrap {
  position: relative;
  flex-shrink: 0;
}
.sidebar-user-avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: linear-gradient(135deg, #5dade2 0%, #3b6ef5 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
  user-select: none;
}
/* La pastille verte « en ligne » a ete RETIREE le 2026-09-22 (BUG-028).
   Elle etait purement decorative : toujours verte, pour tout le monde,
   sans aucune donnee derriere -- ni WebSocket, ni polling, ni classe
   d'etat. Elle suggerait une presence multi-utilisateur qui n'existe pas.
   Mieux vaut rien promettre que promettre faux. */
.sidebar-user-info {
  flex: 1;
  min-width: 0;
}
.sidebar-user-name {
  font-size: 13px;
  color: #fff;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.3;
}
.sidebar-user-status {
  font-size: 10px;
  color: #cbd5e0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: 2px;
  line-height: 1.3;
}
.sidebar-user-card-wrap .logout-form {
  display: block;
  margin-top: 6px;
}
.btn-logout {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  padding: 8px 12px;
  background: transparent;
  border: none;
  color: #cbd5e0;
  font-size: 12px;
  font-family: inherit;
  cursor: pointer;
  border-radius: 8px;
  transition: background 0.15s, color 0.15s;
}
.btn-logout:hover {
  background: rgba(255, 255, 255, 0.06);
  color: #fff;
}
.btn-logout-icon {
  width: 14px;
  height: 14px;
  transition: transform 0.15s;
}
.btn-logout:hover .btn-logout-icon { transform: scale(1.1); }

.main { padding: 32px; }

.topbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 28px;
}
.topbar h1 { font-size: 22px; font-weight: 700; }

.card {
  background: var(--surface);
  border-radius: 12px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
  padding: 24px;
}

.empty-state {
  text-align: center;
  padding: 48px 24px;
  color: var(--muted);
}

.empty-state .icon { font-size: 36px; margin-bottom: 12px; }

/* ----- Dashboard : stats cards ----- */
.stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  margin-bottom: 28px;
}

.stat-card {
  background: var(--surface);
  border-radius: 12px;
  padding: 20px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
}

.stat-card .label {
  font-size: 12px;
  color: var(--muted);
  margin-bottom: 8px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 600;
}

.stat-card .value {
  font-size: 22px;
  font-weight: 700;
  color: var(--navy);
  line-height: 1.2;
}

.stat-card .sub {
  font-size: 12px;
  color: var(--blue);
  margin-top: 4px;
}

@media (max-width: 1100px) {
  .stats { grid-template-columns: repeat(2, 1fr); }
}

/* ----- Filtres ----- */
.filters {
  display: flex;
  gap: 10px;
  margin-bottom: 18px;
  flex-wrap: wrap;
  align-items: center;
}

.filters input[type="text"],
.filters select {
  height: 38px;          /* hauteur uniforme : aligne le select natif sur l'input */
  padding: 0 14px;       /* horizontal seul, le vertical est gere par height */
  box-sizing: border-box;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 14px;
  background: var(--surface);
  font-family: inherit;
  color: var(--text);
}

.filters input[type="text"] {
  width: 280px;
  max-width: 100%;
}

.filters input[type="text"]:focus,
.filters select:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(59, 110, 245, 0.15);
}

.filters .btn { padding: 9px 18px; }

/* Indicateur HTMX pendant le filtrage live */
.htmx-indicator {
  opacity: 0;
  transition: opacity 0.2s;
  font-size: 16px;
  color: var(--blue);
}
.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator { opacity: 1; }

/* ----- Tableau projets ----- */
.projets-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--surface);
  border-radius: 12px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
}
/* Coins arrondis portes par les cellules d'angle, et NON par un
   `overflow: hidden` sur le tableau : ce dernier rognait tout element
   debordant d'une ligne. Mesure du 2026-09-10 : il ne restait que 22 px sous
   la derniere icone d'alerte, donc son infobulle etait coupee. Meme famille de
   bug que le menu DPGF de l'onglet Consultations. */
.projets-table thead th:first-child { border-top-left-radius: 12px; }
.projets-table thead th:last-child { border-top-right-radius: 12px; }
.projets-table tbody tr:last-child td:first-child { border-bottom-left-radius: 12px; }
.projets-table tbody tr:last-child td:last-child { border-bottom-right-radius: 12px; }

.projets-table thead { background: #f8f9fb; }

.projets-table th {
  padding: 13px 16px;
  text-align: left;
  font-size: 11px;
  color: var(--muted);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
/* En-tete colonne Actions aligne a droite, comme les icones Modifier /
   Dupliquer (cf. .actions-row justify-content: flex-end). Meme padding
   horizontal (16px) -> le mot "ACTIONS" tombe au-dessus des icones. */
.projets-table th.th-actions { text-align: right; }

.projets-table td {
  padding: 14px 16px;
  font-size: 14px;
  border-top: 1px solid #f0f2f6;
  vertical-align: middle;
}

.projets-table tr:hover td { background: #fafbfc; }

/* Toute la ligne ouvre sa cible (static/js/lignes-cliquables.js) : tableau
   des projets, liste des retours. */
[data-row-link] { cursor: pointer; }

/* Le nom du projet est un vrai lien (clavier, Ctrl-clic) mais garde l'allure
   du texte : c'est la ligne entiere qui se lit comme cliquable, le nom passe
   au bleu au survol pour le confirmer. */
.projets-table .projet-lien {
  color: inherit;
  text-decoration: none;
}
.projets-table tr[data-row-link]:hover .projet-lien { color: var(--blue); }

/* Colonne actions du tableau des projets.
   Le <td.actions> reste en table-cell standard (centrage vertical via td).
   Un wrapper interne `.actions-row` fait le flex pour pousser les icones
   tout a droite -- mettre flex sur le td casserait son comportement de
   cellule (laisse un blanc en bas quand la row est plus haute). */
.projets-table .actions-row {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 4px;
}
/* Icones seules (Modifier, Dupliquer), sans texte : une cible de 36 px,
   franche a viser puisque cliquer a cote ouvre le projet. `cursor: pointer`
   l'emporte sur le `help` du composant `.tip` qui porte le libelle. */
.projets-table .action-ico-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 8px;
  color: var(--muted);
  cursor: pointer;
}
.projets-table .action-ico-btn:hover,
.projets-table .action-ico-btn:focus-visible {
  color: var(--blue);
  background: #eef2fe;
}
.projets-table .action-ico {
  width: 21px;
  height: 21px;
  flex-shrink: 0;
}

/* ----- Badges statut ----- */
.badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 20px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* Palette des badges statut projet. 4 statuts (Consultation a ete fusionne
   dans Chiffrage en 2026-05 ; Non retenu ajoute en 2026-10). Logique :
   - Chiffrage  : bleu doux -> phase d'exploration / pre-chantier (par defaut).
   - Travaux    : gold -> phase active / chantier en cours (attire l'attention).
   - Archive    : navy fonce -> projet finalise.
   - Non retenu : gris neutre -> ce n'est ni un echec a souligner en rouge,
                  ni une affaire vivante ; c'est de l'histoire, qu'on garde
                  pour ses prix. */
.badge-chiffrage { background: #e8f0fe; color: #2d5dd4; }
.badge-travaux   { background: #fdf2cc; color: #8a6814; }
.badge-clos      { background: #2a3656; color: #ffffff; }
.badge-perdu     { background: #eceff3; color: #5b6472; }

/* Tableau de bord : UNE CARTE PAR STATUT, chacune avec son tableau
   (demande 2026-10-02 : « X cartes pour X categories »). */
.projets-carte { padding: 12px 20px 8px; margin-bottom: 16px; }
/* L'en-tete de carte est un <summary> : Archive et Non retenu sont REPLIES
   par defaut (demande 2026-10-02) -- de l'histoire, discrete tant qu'on ne
   la cherche pas. La petite fleche tourne a l'ouverture. */
.projets-carte-corps > summary { list-style: none; cursor: pointer; }
.projets-carte-corps > summary::-webkit-details-marker { display: none; }
.projets-carte-titre h2 {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 4px 0 6px;
  font-size: 13px;
  font-weight: 700;
}
.projets-carte-corps[open] .projets-carte-titre h2 { margin-bottom: 6px; }
.projets-carte-fleche { width: 16px; height: 16px; color: var(--muted); transition: transform 0.15s; }
.projets-carte-corps[open] .projets-carte-fleche { transform: rotate(90deg); }
.projets-carte-corps:not([open]) .projets-carte-titre .badge { opacity: 0.75; }
.projets-carte .projets-table { box-shadow: none; border-radius: 0; margin: 0; }
/* Entre 1024 px (seuil du mode desktop) et 1280 px, le tableau des projets ne
   tient pas avec ses marges confortables (B7). On les resserre plutôt que de
   le faire défiler dans sa carte : un conteneur défilant rognerait le menu de
   statut et les infobulles des lignes (cf. `.projets-table` plus haut). */
@media (max-width: 1279px) {
  .main { padding: 24px; }
  .projets-carte { padding-left: 12px; padding-right: 12px; }
  .projets-table th,
  .projets-table td { padding-left: 8px; padding-right: 8px; }
}
.projets-carte-vide { margin: 0 0 10px; font-size: 13px; }
.projets-groupe-nb {
  display: inline-block;
  min-width: 18px;
  padding: 0 6px;
  border-radius: 9px;
  background: #eceff3;
  color: #5b6472;
  font-size: 10.5px;
  font-weight: 700;
  text-align: center;
}
/* Les perdus se lisent autrement : un cran plus discrets. */
.projets-carte-perdu td { color: #6b7280; }
.projets-carte-perdu td strong { font-weight: 600; color: #4b5563; }

/* Le badge de statut est un menu (<details>) : les va-et-vient libres en
   boutons, les autres transitions expliquees. */
.statut-menu { position: relative; display: inline-block; }
.statut-menu-badge { list-style: none; cursor: pointer; display: inline-block; }
.statut-menu-badge::-webkit-details-marker { display: none; }
.statut-menu-badge:hover .badge { box-shadow: 0 0 0 2px rgba(59, 110, 245, 0.25); }
.statut-menu[open] .statut-menu-badge .badge { box-shadow: 0 0 0 2px var(--blue); }
.statut-menu-options {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 60;
  min-width: 260px;
  padding: 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(26, 35, 64, 0.14);
}
.statut-menu-option {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 6px 8px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.statut-menu-option:hover { background: var(--bg); }
.statut-menu-option .ic { width: 14px; height: 14px; color: var(--muted); }
.statut-menu-aide { margin: 6px 8px 2px; font-size: 11.5px; line-height: 1.4; color: var(--muted); }

/* ----- Petits utilitaires partagés ----- */
.muted { color: var(--muted); }
.muted.small, .small { font-size: 12px; }

.tabs {
  display: flex;
  gap: 0;
  border-top: 1px solid #eef0f5;
  margin: 0 -24px;
  padding: 0 24px;
}

.tab {
  padding: 12px 18px;
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}

.tab:hover { color: var(--text); text-decoration: none; }
.tab.active { color: var(--blue); border-bottom-color: var(--blue); }

/* ----- Formulaire dense ----- */
.form-card {
  background: var(--surface);
  border-radius: 12px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
  padding: 8px 24px 24px;
  /* pas de margin-top pour s'aligner avec .form-aside-card en grid */
}

/* Pas de filet en tete de section : chaque titre porte deja son propre
   soulignement, le second trait faisait doublon sous la derniere ligne de
   la section precedente (signale 2026-09-21 : sous Code postal / Ville et
   sous les dates). L'espacement suffit a separer. */
.form-section {
  padding: 28px 0 0;
  margin: 0;
}
.form-section:first-of-type { padding-top: 8px; }

.form-section .form-section-title {
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--navy);
  font-weight: 700;
  margin: 0 0 10px 0;
  padding-bottom: 6px;
  border-bottom: 1px solid #e0e4eb;
}

.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px 18px;
}

/* Libelle a GAUCHE du champ (demande 2026-09-21) : l'oeil descend une seule
   colonne de valeurs au lieu d'alterner libelle / champ. La colonne des
   libelles est FIXE, donc ils s'alignent d'une ligne a l'autre, et entre les
   deux colonnes de la grille. */
.form-field {
  display: grid;
  grid-template-columns: 148px minmax(0, 1fr);
  align-items: center;
  column-gap: 14px;
  row-gap: 4px;
  min-width: 0;
}
.form-field.span-2 { grid-column: span 2; }
/* Tout ce qui n'est pas le libelle (champ, wrapper BAN, aide, erreur) tient
   dans la colonne de droite : sans cette regle, l'aide et les erreurs
   iraient se placer sous le libelle. */
.form-field > label { grid-column: 1; }
.form-field > :not(label) { grid-column: 2; }

.form-field label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  font-weight: 600;
  margin-bottom: 0;
  line-height: 1.3;
}

/* Sous 720px la colonne fixe etouffe le champ : on repasse en empile. */
@media (max-width: 720px) {
  .form-field {
    grid-template-columns: minmax(0, 1fr);
  }
  .form-field > label,
  .form-field > :not(label) { grid-column: 1; }
  .form-field label { margin-bottom: 4px; }
}

.form-field input[type="text"],
.form-field input[type="number"],
.form-field input[type="date"],
.form-field input[type="email"],
.form-field input[type="password"],
.form-field input[type="tel"],
.form-field select,
.form-field textarea {
  width: 100%;
  height: 36px;          /* hauteur uniforme : aligne select et input[type=date] sur Mac */
  padding: 0 12px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 14px;
  font-family: inherit;
  background: var(--surface);
  color: var(--text);
  box-sizing: border-box;
  line-height: 1.4;
}
/* Suppression des fleches natives sur les inputs number (surface, etc.) */
.form-field input[type="number"]::-webkit-outer-spin-button,
.form-field input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.form-field input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
.form-field textarea { height: auto; padding: 8px 12px; }

.form-field select {
  /* Retire le styling natif du <select> pour avoir la même hauteur que les autres inputs */
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path fill='%23888' d='M0 0l5 6 5-6z'/></svg>");
  background-repeat: no-repeat;
  background-position: right 10px center;
  padding-right: 28px;
}

.form-field input:focus,
.form-field select:focus,
.form-field textarea:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(59, 110, 245, 0.15);
}

.field-error {
  color: var(--danger);
  font-size: 12px;
  margin-top: 4px;
}

.form-help {
  display: block;
  font-size: 11px;
  color: var(--muted);
  margin-top: 4px;
}

/* ----- Autocomplete adresse (BAN) ----- */
.ban-autocomplete-wrapper {
  position: relative;
}

.ban-suggestions {
  position: absolute;
  top: calc(100% + 2px);
  left: 0;
  right: 0;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 6px;
  list-style: none;
  padding: 4px 0;
  margin: 0;
  max-height: 260px;
  overflow-y: auto;
  z-index: 100;
  box-shadow: 0 4px 16px rgba(26, 35, 64, 0.10);
}
.ban-suggestions[hidden] { display: none; }

.ban-suggestion {
  display: block;
  padding: 7px 12px;
  cursor: pointer;
  font-size: 13px;
  border-bottom: 1px solid #f3f4f7;
  line-height: 1.35;
}
.ban-suggestion:last-child { border-bottom: none; }
.ban-suggestion:hover { background: #f5f8ff; }

.ban-suggestion strong { display: block; color: var(--text); font-weight: 600; }
.ban-suggestion .ban-meta { color: var(--muted); font-size: 11.5px; }

/* Flash visuel quand un champ est auto-rempli */
.ban-filled {
  background: #e7f3ff !important;
  transition: background 0.8s ease-out;
}

/* Paragraphe descriptif sous le titre d'une section (compact, pas de marges
   parasites du navigateur qui creeraient un espace bizarre avec le titre) */
.form-section-description {
  font-size: 12px;
  color: var(--muted);
  margin: 0 0 10px 0;
  line-height: 1.4;
}

/* ----- Sélection utilisateurs (cards cliquables avec avatar) ----- */
.users-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 8px;
}

.user-card {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: #fff;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
.user-card:hover {
  border-color: var(--blue);
  background: #fafbff;
}

/* Checkbox custom : on cache la native, on la remplace par un carré coloré
   avec un check SVG-like fait en CSS. */
.user-card input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  margin: 0;
  border: 1.5px solid var(--border);
  border-radius: 4px;
  background: #fff;
  position: relative;
  flex-shrink: 0;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s;
}
.user-card input[type="checkbox"]:checked {
  background: var(--blue);
  border-color: var(--blue);
}
.user-card input[type="checkbox"]:checked::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 5px;
  width: 4px;
  height: 9px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* Highlight de la carte quand sa checkbox est cochée (modern CSS, supporté
   par Safari 15.4+, Chrome 105+, Firefox 121+ — largement assez récent). */
.user-card:has(input:checked) {
  border-color: var(--blue);
  background: #eef3ff;
}

.user-avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: linear-gradient(135deg, #3b6ef5, #1a2340);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
  flex-shrink: 0;
  text-transform: uppercase;
}

.user-name {
  font-size: 13.5px;
  font-weight: 500;
  color: var(--text);
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Checkbox-card simple : utilisé pour les choix isolés (ex: "Charger lots standard") */
.checkbox-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: #fff;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
.checkbox-card:hover { border-color: var(--blue); background: #fafbff; }
.checkbox-card input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  margin: 0;
  border: 1.5px solid var(--border);
  border-radius: 4px;
  background: #fff;
  position: relative;
  flex-shrink: 0;
  cursor: pointer;
}
.checkbox-card input[type="checkbox"]:checked { background: var(--blue); border-color: var(--blue); }
.checkbox-card input[type="checkbox"]:checked::after {
  content: '';
  position: absolute;
  top: 2px; left: 5px;
  width: 4px; height: 9px;
  border: solid #fff; border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.checkbox-card:has(input:checked) { border-color: var(--blue); background: #eef3ff; }

/* ----- Section Zones (colonne aside) ----- */
.zones-section .form-section-title { margin-bottom: 4px; }
.zones-section .form-section-description { margin-bottom: 14px; }

.zones-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-bottom: 10px;
}

.zone-row,
.zone-add-form {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 0;
}

.zone-add-form {
  border-top: 1px dashed var(--border);
  padding-top: 12px;
  margin-top: 4px;
}

.zones-empty {
  padding: 12px 0;
  font-style: italic;
}

/* Inputs in-row, façon tableur */
.zone-nom,
.zone-surface {
  height: 32px;
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: 5px;
  font-size: 13px;
  font-family: inherit;
  background: var(--surface);
  color: var(--text);
  box-sizing: border-box;
}

/* Suppression des fleches haut/bas natives sur les inputs number */
.zone-surface::-webkit-outer-spin-button,
.zone-surface::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.zone-surface { -moz-appearance: textfield; appearance: textfield; }

/* Drag handle pour le reordonnancement des zones */
.zone-drag-handle {
  cursor: grab;
  color: var(--muted);
  font-size: 14px;
  padding: 0 2px;
  user-select: none;
  flex-shrink: 0;
  letter-spacing: -3px;
  font-weight: 700;
}
.zone-drag-handle:hover { color: var(--text); }
.zone-drag-handle:active { cursor: grabbing; }

/* Etats SortableJS pendant le drag */
.zone-row-ghost { opacity: 0.4; background: #eef3ff; }
.zone-row-chosen { background: #fafbff; }
.zone-row-dragging { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12); }
.zone-nom:focus,
.zone-surface:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(59, 110, 245, 0.12);
}

.zone-nom { flex: 1; min-width: 0; }
/* Projet passé en facturation : zones en lecture seule (cf. _zones_list.html) */
.zone-nom:disabled,
.zone-surface:disabled {
  color: var(--muted);
  background: var(--bg);
  cursor: not-allowed;
}
.zone-surface-wrapper {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
}
.zone-surface { width: 70px; text-align: right; }
.zone-surface-wrapper .suffix { font-size: 11px; color: var(--muted); }

/* Bouton supprimer (rouge discret) */
.zone-delete {
  width: 28px;
  height: 28px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 5px;
  color: var(--muted);
  cursor: pointer;
  font-size: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.zone-delete:hover {
  background: var(--danger-bg);
  color: var(--danger);
  border-color: rgba(214, 69, 69, 0.3);
}

/* Bouton ajouter (vert discret) */
.zone-add-btn {
  width: 32px;
  height: 32px;
  background: #eef7ee;
  border: 1px solid #c8e0c8;
  border-radius: 5px;
  color: #2e7d2e;
  cursor: pointer;
  font-size: 18px;
  font-weight: 700;
  line-height: 1;
  flex-shrink: 0;
  transition: background 0.12s, border-color 0.12s;
}
.zone-add-btn:hover { background: #d8ecd8; border-color: #2e7d2e; }

/* ===== Selecteur d'entreprise (annuaire partage) ========================
   Un bouton au repos, un panneau de recherche au clic. Le panneau est
   deplace dans <body> par entreprise-picker.js et positionne en `fixed` :
   les conteneurs a `overflow: clip` le rogneraient. */
.ent-pick { position: relative; min-width: 0; }

.ent-pick-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-width: 0;
  height: 36px;
  padding: 0 10px 0 12px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
  font-family: inherit;
  font-size: 14px;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.12s, box-shadow 0.12s;
}
.ent-pick-btn:hover:not(:disabled) { border-color: #b9c8ea; }
.ent-pick-btn:focus-visible,
.ent-pick-btn[aria-expanded="true"] {
  outline: none;
  border-color: #3b6ef5;
  box-shadow: 0 0 0 3px rgba(59, 110, 245, 0.12);
}
.ent-pick-btn:disabled { background: #f4f6fa; color: var(--muted); cursor: not-allowed; }

.ent-pick-txt {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Le texte suggestif se distingue d'une valeur choisie. */
.ent-pick-txt.est-vide { color: var(--muted); }
.ent-pick-chevron { width: 16px; height: 16px; flex: none; color: var(--muted); }
.ent-pick-btn[aria-expanded="true"] .ent-pick-chevron { transform: rotate(180deg); }

/* Rendu dense, pour une cellule de tableau du chiffrage. */
.ent-pick--compact .ent-pick-btn {
  height: 28px;
  padding: 0 6px 0 8px;
  font-size: 13px;
  border-radius: 5px;
}
.ent-pick--compact .ent-pick-chevron { width: 14px; height: 14px; }

/* ----- Le panneau ------------------------------------------------------ */
/* `display: flex` l'emporte sur l'attribut `hidden` du navigateur (qui
   n'est qu'une regle `display: none` de la feuille par defaut) : sans cette
   ligne, les panneaux FERMES restent affiches — champ de recherche visible
   en permanence, et hauteur de ligne gonflee dans le chiffrage. */
.ent-pick-panneau[hidden] { display: none; }
.ent-pick-panneau {
  z-index: 3000;
  display: flex;
  flex-direction: column;
  min-width: 280px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 6px 12px rgba(26, 35, 64, 0.08), 0 18px 40px rgba(26, 35, 64, 0.16);
  overflow: hidden;
}
.ent-pick-recherche-zone {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
  flex: none;
}
.ent-pick-loupe { width: 16px; height: 16px; flex: none; color: var(--muted); }
.ent-pick-recherche {
  flex: 1 1 auto;
  min-width: 0;
  border: none;
  outline: none;
  font-family: inherit;
  font-size: 13.5px;
  color: var(--text);
  background: transparent;
}
.ent-pick-recherche::-webkit-search-cancel-button { display: none; }

/* Le conteneur swappe par HTMX ne defile PAS lui-meme : il empile la liste
   (qui defile) et le pied (qui reste visible). Avant, le pied vivait DANS
   la zone de defilement -- il fallait derouler quarante fiches pour
   atteindre « + Creer dans l'annuaire », qu'on croyait donc absent. */
.ent-pick-resultats { display: flex; flex-direction: column; min-height: 0; }
.ent-pick-liste {
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  min-height: 0;
  /* `contain` et non `auto` : arrive en butee, haut ou bas, le defilement
     se propageait a la PAGE derriere, qui filait sous un panneau reste
     fixe a l'ecran (signale 2026-09-22). */
  overscroll-behavior: contain;
}

.ent-pick-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 12px;
  border: none;
  background: transparent;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
}
.ent-pick-item:hover { background: #eef2fb; }
/* Pastille a l'initiale : repere visuel dans une longue liste. */
.ent-pick-avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  flex: none;
  border-radius: 6px;
  background: #eef2fb;
  color: #3b6ef5;
  font-size: 11px;
  font-weight: 700;
}
.ent-pick-infos { display: flex; flex-direction: column; min-width: 0; }
.ent-pick-nom {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--navy);
  text-transform: uppercase;
  letter-spacing: 0.01em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ent-pick-lieu { font-size: 11px; color: var(--muted); margin-top: 1px; }

.ent-pick-message {
  margin: 0;
  padding: 14px 12px;
  font-size: 12.5px;
  color: var(--muted);
  line-height: 1.5;
}

.ent-pick-pied {
  flex: none;
  border-top: 1px solid var(--border);
  background: #fafbfd;
}
.ent-pick-pied button {
  display: block;
  width: 100%;
  padding: 9px 12px;
  border: none;
  background: transparent;
  text-align: left;
  font-family: inherit;
  font-size: 12.5px;
  cursor: pointer;
}
.ent-pick-libre { color: var(--text); }
.ent-pick-libre:hover { background: #eef2fb; }
.ent-pick-creer { color: #2e7d2e; font-weight: 600; }
.ent-pick-creer:hover { background: #eef7ee; }
.ent-pick-pied button + button { border-top: 1px solid var(--border); }

/* ----- Acteurs de l'operation ------------------------------------------
   Meme grammaire visuelle que les zones juste au-dessus : lignes facon
   tableur, formulaire d'ajout separe par un filet pointille. Trois champs
   par ligne au lieu de deux, donc on empile role+nom sur une rangee et
   l'adresse en dessous plutot que de tasser trois champs sur 312px. */
.acteurs-card {
  grid-column: 1;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 20px 22px 22px;
  box-shadow: 0 1px 3px rgba(26, 35, 64, 0.04);
}
.acteurs-section { margin-top: 0; }
.acteurs-section .form-section-title { margin-bottom: 4px; }
.acteurs-section .form-section-description { margin-bottom: 14px; }

/* Desigation a GAUCHE, nom puis adresse a DROITE (demande 2026-09-21) :
       Designation | Nom
                   | Adresse
   La colonne de gauche reste vide sur la seconde rangee, l'adresse se lit
   donc comme un complement du nom et non comme un troisieme champ de meme
   rang. Meme logique que les libelles a gauche du formulaire projet. */
.acteur-row,
.acteur-add-form {
  display: grid;
  grid-template-columns: 220px minmax(0, 1fr) 32px;
  align-items: center;
  column-gap: 10px;
  row-gap: 6px;
  padding: 10px 0;
}
.acteur-role { grid-column: 1; grid-row: 1; }
.acteur-nom-wrapper { grid-column: 2; grid-row: 1; }
.acteur-adresse { grid-column: 2; grid-row: 2; }
/* Sans ca l'auto-placement pose le bouton a cote de l'ADRESSE, une rangee
   trop bas : on le cale explicitement sur la premiere. */
.acteur-delete,
.acteur-add-btn {
  grid-column: 3;
  grid-row: 1;
}
.acteur-row + .acteur-row { border-top: 1px solid var(--border); }
.acteur-add-form {
  border-top: 1px dashed var(--border);
  padding-top: 12px;
  margin-top: 4px;
}
@media (max-width: 720px) {
  .acteur-row,
  .acteur-add-form { grid-template-columns: minmax(0, 1fr) 32px; }
  .acteur-role { grid-column: 1; grid-row: 1; }
  .acteur-nom-wrapper { grid-column: 1; grid-row: 2; }
  .acteur-adresse { grid-column: 1; grid-row: 3; }
}

.acteurs-empty {
  padding: 12px 0;
  font-style: italic;
}

.acteur-nom-wrapper { position: relative; min-width: 0; }
.acteur-nom-wrapper .acteur-nom { width: 100%; }

.acteur-role,
.acteur-nom,
.acteur-adresse {
  height: 32px;
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: 5px;
  font-size: 13px;
  font-family: inherit;
  background: var(--surface);
  color: var(--text);
  box-sizing: border-box;
  min-width: 0;
}
.acteur-role:focus,
.acteur-nom:focus,
.acteur-adresse:focus {
  outline: none;
  border-color: var(--primary, #3b6ef5);
  box-shadow: 0 0 0 2px rgba(59, 110, 245, 0.12);
}

.acteur-delete {
  width: 28px;
  height: 28px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 5px;
  color: var(--muted);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.acteur-delete:hover {
  background: var(--danger-bg);
  color: var(--danger);
  border-color: rgba(214, 69, 69, 0.3);
}

.acteur-add-btn {
  width: 32px;
  height: 32px;
  background: #eef7ee;
  border: 1px solid #c8e0c8;
  border-radius: 5px;
  color: #2e7d2e;
  cursor: pointer;
  font-size: 18px;
  font-weight: 700;
  line-height: 1;
  flex-shrink: 0;
}
.acteur-add-btn:hover { background: #d8ecd8; border-color: #2e7d2e; }

.acteurs-plafond {
  margin: 12px 0 0;
  padding: 10px 12px;
  border: 1px dashed var(--border);
  border-radius: 6px;
  font-style: italic;
}

/* ----- Acteurs, fiche en lecture seule ----------------------------------
   Une liste d'entites, pas une suite de couples champ/valeur : chacune a
   un monogramme, un role en micro-libelle et une adresse en retrait. La
   pastille « annuaire » dit d'un coup d'oeil lesquelles viennent de
   l'annuaire partage plutot que d'une saisie libre. */
/* La carte prenant toute la largeur, la liste se repartit d'elle-meme sur
   deux colonnes des qu'il y a la place. Pas de filet entre les entrees : en
   grille il faudrait des regles `nth-child` dependant du nombre de colonnes,
   fragiles ; le monogramme ancre deja chaque ligne. */
.infos-acteurs {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  column-gap: 26px;
  row-gap: 2px;
}
.infos-acteur {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr);
  align-items: start;
  column-gap: 11px;
  padding: 9px 0;
}

.infos-acteur-mono {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 9px;
  background: #eef2fb;
  color: #3b6ef5;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.02em;
}
.infos-acteur-corps { display: flex; flex-direction: column; min-width: 0; }
.infos-acteur-role {
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
}
.infos-acteur-nom {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--navy);
  line-height: 1.35;
  margin-top: 1px;
}
/* Provenance annuaire : discrete, elle qualifie le nom sans le concurrencer. */
.infos-acteur-lien {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 999px;
  background: #eef7ee;
  color: #2e7d2e;
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  vertical-align: 1px;
}
.infos-acteur-adresse {
  font-size: 11.5px;
  color: var(--muted);
  line-height: 1.4;
  margin-top: 2px;
}

.form-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 22px;
  padding-top: 18px;
}

@media (max-width: 720px) {
  .form-grid { grid-template-columns: 1fr; }
  .form-field.span-2 { grid-column: span 1; }
}

/* ----- Placeholder vue chiffrage ----- */
.placeholder-card {
  background: var(--surface);
  border-radius: 12px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
  padding: 40px 28px;
  text-align: center;
}
.placeholder-icon { font-size: 40px; margin-bottom: 12px; }
.placeholder-card h2 { font-size: 18px; font-weight: 700; margin-bottom: 8px; }
.placeholder-card p { color: var(--text); margin-bottom: 6px; }
.placeholder-card details { text-align: left; max-width: 720px; margin: 24px auto 0; }
.placeholder-card summary { cursor: pointer; font-weight: 600; color: var(--blue); }

/* =========================================================================
   VUE CHIFFRAGE — densité tableur
   ========================================================================= */

body.chiffrage-page {
  font-size: 13px;
}

/* ----- Header navy plein écran ----- */
.chiffrage-header {
  background: var(--navy);
  color: #fff;
  padding: 10px 16px;
  display: flex;
  align-items: center;
  gap: 14px;
  height: 52px;
  border-bottom: 1px solid #0d1426;
}

.back-btn {
  background: var(--navy-2);
  color: #ccd;
  border: none;
  padding: 6px 12px;
  border-radius: 5px;
  font-size: 14px;
  text-decoration: none;
  line-height: 1;
}
.back-btn:hover { background: #3a4d70; color: #fff; text-decoration: none; }

.chiffrage-header-title { line-height: 1.2; }
.chiffrage-header-title { flex: 1; min-width: 0; }
.chiffrage-header-title .project-name { font-size: 15px; font-weight: 700; }
.chiffrage-header-title .project-meta {
  font-size: 12px;
  color: #8899aa;
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ===== Barre d'onglets de PROJETS (PWA uniquement) =====================
   A ne pas confondre avec `.projet-tabs-bar` juste dessous, qui est la
   navigation INTERNE a un projet (Chiffrage / Analytique / Resume...).
   Celle-ci est l'equivalent des onglets du navigateur : un onglet = un
   projet ouvert.

   MASQUEE PAR DEFAUT, et c'est le coeur du dispositif. Dans un navigateur
   ordinaire, les onglets natifs font deja mieux -- ils se detachent en
   vraies fenetres systeme. L'app installee, elle, tourne en
   `display: standalone` : ni onglets, ni barre d'URL, donc aucun moyen
   d'ouvrir deux projets. `@media (display-mode: standalone)` est la SEULE
   detection fiable, parce qu'elle vaut PAR FENETRE : le serveur ne peut pas
   trancher, l'app installee partageant les cookies du navigateur, un
   drapeau en session fuirait de l'une a l'autre.
   Cf. core/services/onglets.py. */
.onglets-bar { display: none; }

@media (display-mode: standalone) {
  /* La barre n'est rendue que hors mode solo (cf. _onglets_projets.html) :
     sa hauteur ne compte que si elle est la. */
  body:has(> .onglets-bar) { --onglets-h: 32px; }
  .onglets-bar {
    display: flex;
    align-items: stretch;
    gap: 2px;
    /* Compacte : elle mange la hauteur utile de TOUTES les pages, y compris
       le chiffrage qui est deja a l'etroit. */
    height: var(--onglets-h);
    padding: 0 8px;
    background: var(--sidebar-bg);
    border-bottom: 1px solid #0f172a;
    overflow: hidden;
  }
  .onglets-bar .onglet {
    display: flex;
    align-items: center;
    gap: 6px;
    max-width: 240px;
    padding: 0 6px 0 10px;
    border-radius: 6px 6px 0 0;
    font-size: 12.5px;
    font-weight: 600;
    color: #cbd5e1;
    text-decoration: none;
    background: transparent;
    transition: background 0.12s, color 0.12s;
  }
  .onglets-bar .onglet:hover { background: var(--sidebar-bg-2); text-decoration: none; }
  .onglets-bar .onglet.est-actif {
    background: var(--bg);
    color: var(--text);
  }
  .onglets-bar .onglet-accueil { flex: 0 0 auto; padding-right: 10px; }
  .onglets-bar .onglet-lien {
    /* `min-width: 0` : sans lui le lien refuse de retrecir sous la largeur
       de son texte et le `text-overflow` ci-dessous ne s'applique jamais. */
    min-width: 0;
    color: inherit;
    text-decoration: none;
  }
  .onglets-bar .onglet-nom {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .onglets-bar .onglet-action {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    padding: 2px;
    border: 0;
    border-radius: 4px;
    background: transparent;
    color: inherit;
    opacity: 0.55;
    cursor: pointer;
  }
  .onglets-bar .onglet-action:hover { opacity: 1; background: rgba(148, 163, 184, 0.28); }
  .onglets-bar .onglet-action .ic { width: 13px; height: 13px; }
  .onglets-bar .onglet-accueil .ic { width: 15px; height: 15px; }
  /* La fleche « retour » du header projet fait doublon avec l'onglet
     Accueil : deux controles pour le meme geste, a 40 px l'un de l'autre.
     `:has(.onglets-bar)` et pas la seule media query : une fenetre DETACHEE
     est elle aussi en standalone mais n'a pas de barre -- sans cette garde
     elle n'aurait plus aucun chemin de retour. */
  body:has(.onglets-bar) .chiffrage-header .back-btn { display: none; }

  .onglets-bar .onglets-plafond {
    display: flex;
    align-items: center;
    padding: 0 10px;
    font-size: 11.5px;
    font-weight: 600;
    color: #fbbf24;
  }
}

/* Barre d'onglets sous le header navy : centree, plus aeree (refonte v28).
   La densite du header progresse au fil des features, on contrebalance ici
   par une bande blanche generique avec onglets espaces et centres. */
.projet-tabs-bar {
  /* Trois colonnes : bouton Quantify a gauche, onglets centres, vide a
     droite. Les deux colonnes laterales egales gardent les onglets au
     centre de la page, comme avant l'ajout du bouton. */
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  background: #f8f9fb;
  border-bottom: 1px solid #dde3ea;
  height: 52px;
  align-items: stretch;
}
.projet-tabs-side {
  display: flex;
  align-items: center;
  padding-left: 16px;
}
/* Acces au metre de l'affaire dans Quantify : un bouton qui ressort (pas un
   onglet), en bleu d'action -- l'orange Quantify est reserve au logo. */
.projet-tabs-bar .ptab-quantify {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 34px;
  padding: 0 12px;
  border: 1px solid #c9d6fb;
  border-radius: 8px;
  background: #eef3fe;
  color: var(--blue);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  text-decoration: none;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.projet-tabs-bar .ptab-quantify .ic { width: 18px; height: 18px; }
.projet-tabs-bar .ptab-quantify .ic-externe { width: 13px; height: 13px; opacity: 0.6; }
.projet-tabs-bar .ptab-quantify:hover {
  background: var(--blue);
  border-color: var(--blue);
  color: #fff;
  text-decoration: none;
}
.projet-tabs-bar .ptab-quantify:hover .ic-externe { opacity: 0.9; }
/* Ecran etroit (portable ~1024 px) : la colonne de gauche ne laisse pas la
   place au libelle, le bouton se reduit a son icone (l'infobulle dit
   « Quantify »). Sans ca il chevauchait l'onglet « Chiffrage ». */
@media (max-width: 1240px) {
  .projet-tabs-bar .ptab-quantify { padding: 0 8px; }
  .projet-tabs-bar .ptab-quantify-label,
  .projet-tabs-bar .ptab-quantify .ic-externe { display: none; }
}
.projet-tabs-inner {
  display: flex;
  align-items: stretch;
  gap: 4px;
}
.projet-tabs-bar .ptab {
  padding: 0 16px;
  display: flex;
  align-items: center;
  /* Labels multi-mots (« Aléas et Remise »…) : centrés et équilibrés pour
     tenir sur 2 lignes max quand la barre se resserre (portables ~1024px).
     Le liant est figé côté template avec &nbsp; pour empêcher une 3e ligne. */
  text-align: center;
  text-wrap: balance;
  line-height: 1.15;
  font-size: 14px;
  font-weight: 600;
  color: var(--muted);
  text-decoration: none;
  border-bottom: 3px solid transparent;
  margin-bottom: -1px;
  transition: color 0.15s, border-bottom-color 0.15s, background 0.15s;
}
.projet-tabs-bar .ptab:hover {
  color: var(--text);
  background: #eef1f5;
  text-decoration: none;
}
.projet-tabs-bar .ptab.active {
  color: var(--blue);
  border-bottom-color: var(--blue);
  background: #fff;
}
/* Separateur visuel entre les 3 groupes d'onglets (pre-chantier / chantier
   / metadonnees). Trait vertical bien marque, prend toute la hauteur du
   bandeau pour signaler clairement la rupture entre phases du projet. */
.projet-tabs-bar .ptab-group-sep {
  align-self: stretch;
  width: 2px;
  background: #9ca3b0;
  margin: 8px 9px;
  border-radius: 1px;
}

/* =========================================================================
   Icônes Heroicons (inline SVG, variante outline)
   -------------------------------------------------------------------------
   Rendues via {% heroicon_outline "name" class="ic" %}. La variante outline
   utilise stroke=currentColor : l'icône hérite donc de la couleur du texte
   ambiant. La taille CSS (em) prime sur l'attribut width/height du SVG ->
   l'icône suit la taille de police du contexte, cohérente partout.
   ========================================================================= */
.ic {
  display: inline-block;
  width: 1.1em;
  height: 1.1em;
  vertical-align: -0.2em;
  flex: none;
  /* 1.25 : trait fin. On etait a 1.6, soit PLUS gras que le 1.5 natif
     d'Heroicons -> les pictos denses (table-cells) paraissaient en gras. */
  stroke-width: 1.25;
}

.chiffrage-header-totals {
  margin-left: auto;
  display: flex;
  gap: 22px;
  font-size: 12px;
}

.chiffrage-header-totals .lbl { color: #8899aa; margin-right: 6px; }
.chiffrage-header-totals .val { font-weight: 700; color: #fff; }
/* Pastilles colorees pour les totaux "hors operation principale" :
   Options en orange (supplements), Variantes en violet (alternatives),
   Total HT client en bleu clair (resultat final, echo du footer total-lot-bar). */
.chiffrage-header-totals .val-options { color: #ffb878; }
.chiffrage-header-totals .val-variantes { color: #d8b4e4; }
.chiffrage-header-totals .val-highlight { color: #5dade2; }

.chiffrage-logout button {
  background: var(--navy-2);
  border: none;
  color: #8899aa;
  padding: 6px 10px;
  border-radius: 5px;
  cursor: pointer;
  font-size: 14px;
}
.chiffrage-logout button:hover { color: #fff; background: #3a4d70; }
/* Bouton « Bibliotheque de prix » du bandeau projet : meme famille que le
   bouton de deconnexion, un cran plus visible (c'est un outil, pas une sortie). */
.chiffrage-biblio-btn {
  background: var(--navy-2);
  border: none;
  color: #bcd0ff;
  padding: 6px 10px;
  margin-right: 6px;
  border-radius: 5px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
}
.chiffrage-biblio-btn:hover { color: #fff; background: #3a4d70; }
.chiffrage-biblio-btn .ic { width: 18px; height: 18px; }

/* ===== Panneau flottant « Bibliotheque de prix » (lot 5, 2026-10-02) =====
   Enfant direct de <body>, `fixed`, deplace par sa poignee (panneau-prix.js).
   z-index SOUS les modales (.modal-overlay = 1000) : une modale ouverte depuis
   le chiffrage passe devant, le panneau n'a pas a se fermer. */
.panneau-prix {
  position: fixed;
  top: 84px;
  right: 24px;
  z-index: 900;
  width: 680px;
  max-width: calc(100vw - 32px);
  max-height: 72vh;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 16px 48px rgba(26, 35, 64, 0.22);
}
.panneau-prix.en-deplacement { box-shadow: 0 24px 64px rgba(26, 35, 64, 0.3); opacity: 0.96; }
.panneau-prix-tete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px 10px 14px;
  border-bottom: 1px solid var(--border);
  border-radius: 12px 12px 0 0;
  background: var(--bg);
  cursor: grab;
  user-select: none;
}
.panneau-prix.en-deplacement .panneau-prix-tete { cursor: grabbing; }
.panneau-prix-titre { display: flex; align-items: center; gap: 8px; font-size: 13.5px; }
.panneau-prix-titre .ic { width: 18px; height: 18px; color: var(--blue); }
.panneau-prix-titre .muted { font-size: 12px; }
.panneau-prix-outils { display: flex; align-items: center; gap: 4px; }
.panneau-prix-outils .link-btn { font-size: 16px; line-height: 1; }
.panneau-prix-outils .ic { width: 15px; height: 15px; }
/* Le corps : les filtres restent en place, seule la LISTE defile. */
.panneau-prix-corps { display: flex; flex-direction: column; min-height: 0; }
.panneau-prix-filtres {
  display: grid;
  grid-template-columns: 1.4fr 1fr 0.8fr;
  gap: 8px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
}
.panneau-prix-filtres .cell-input { width: 100%; font-size: 12.5px; }
.panneau-prix-liste {
  overflow-y: auto;
  overscroll-behavior: contain; /* sinon le defilement part a la page en butee */
  padding: 4px 0 8px;
}
.panneau-prix-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.panneau-prix-table th {
  position: sticky;
  top: 0;
  padding: 6px 14px;
  background: var(--surface);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
  text-align: left;
  border-bottom: 1px solid var(--border);
}
.panneau-prix-table td { padding: 7px 14px; border-bottom: 1px solid #eef1f5; vertical-align: top; }
.panneau-prix-table .num, .panneau-prix-table th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.panneau-prix-table .badge { font-size: 9.5px; padding: 1px 7px; }
.panneau-prix-vide, .panneau-prix-pied { margin: 0; padding: 14px; font-size: 12.5px; }

/* ----- Layout 2 colonnes plein écran ----- */
.chiffrage-layout {
  display: flex;
  /* 52px header navy + 53px barre d'onglets (52px + 1px border) */
  height: calc(100vh - 105px);
}

/* Conteneur de la page formulaire (édition / création projet) */
.form-page-main {
  background: var(--bg);
  padding: 24px;
  min-height: calc(100vh - 93px);
}

/* Grid 2 colonnes : formulaire à gauche, zones à droite (mode edition).
   Dans la version creation, on tombe sur 1 colonne centrée (.no-aside) */
.form-page-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 380px;
  gap: 20px;
  max-width: 1320px;
  margin: 0 auto;
  align-items: start;
}
.form-page-grid.no-aside {
  grid-template-columns: minmax(0, 920px);
  justify-content: center;
}

@media (max-width: 1100px) {
  .form-page-grid { grid-template-columns: 1fr; max-width: 920px; }
}

/* Card de la colonne aside (zones du projet) */
.form-aside-card {
  background: var(--surface);
  border-radius: 12px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
  padding: 8px 24px 24px;     /* meme padding que .form-card pour aligner top */
  position: sticky;
  top: 16px;     /* reste visible au scroll */
}

/* Banniere de bienvenue (apres creation projet) */
.welcome-banner {
  max-width: 1320px;
  margin: 0 auto 16px;
  padding: 12px 18px;
  background: linear-gradient(90deg, #e7f3ff, #f0f8ff);
  border: 1px solid #c5d9f5;
  border-radius: 10px;
  font-size: 13.5px;
  color: var(--navy);
  line-height: 1.4;
}

/* ----- Sidebar lots ----- */
.lots-sidebar {
  width: 430px;          /* Place pour les controles (toggle, V validation, RG)
                            + nom de lot long sans le serrer. */
  min-width: 430px;
  background: #fff;
  border-right: 1px solid #dde3ea;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.lots-sidebar-head {
  padding: 10px 14px;
  font-weight: 700;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  border-bottom: 1px solid #eee;
  background: #fafbfc;
}

/* Legende du code couleur des statuts de lot (juste sous le header "Lots").
   Trois rectangles equilarges aux memes teintes (fond + texte) que les
   statuts correspondants dans la liste des lots, pour une lecture immediate. */
.lots-legend {
  display: flex;
  gap: 6px;
  padding: 10px 12px 12px;
  background: #fafbfc;
  border-bottom: 1px solid #eee;
}
.lots-legend .legend-item {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 7px 6px;
  border-radius: 5px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
}
/* Pastille = couleur EXACTE du liseré de statut correspondant (mapping direct
   avec .lot-item-wrapper.status-*::before). */
.lots-legend .legend-item::before {
  content: '';
  width: 10px;
  height: 10px;
  border-radius: 2px;
  flex-shrink: 0;
}
.lots-legend .legend-validated {
  background: #eef7f1;
  color: #157a43;
}
.lots-legend .legend-validated::before { background: #18a05a; }   /* = liseré verrouillé */
.lots-legend .legend-in-progress {
  background: #fdf3e6;
  color: #a8650f;
}
.lots-legend .legend-in-progress::before { background: #e88a1e; }  /* = liseré en cours */
.lots-legend .legend-todo {
  background: #fdeeee;
  color: #c0352f;
}
.lots-legend .legend-todo::before { background: #e04444; }         /* = liseré à chiffrer */

.lots-list { flex: 1; overflow-y: auto; }

/* Wrapper d'une ligne de lot : contient le bouton toggle + le lien de sélection */
.lot-item-wrapper {
  display: flex;
  align-items: center;
  gap: 10px;
  /* min-height + box-sizing : hauteur de ligne CONSTANTE. Les lots actifs
     portent le cluster contrôles (verrou/RG, ~22px) + le montant, absents des
     lots inactifs -> sans ça, les lignes grisées faisaient 35px vs 41px. */
  min-height: 41px;
  box-sizing: border-box;
  padding: 9px 12px 9px 18px;   /* +left pour laisser place à la pastille de statut */
  border-bottom: 1px solid #f5f6f9;
  position: relative;
  transition: background 0.12s;
}
/* Pastille de statut à gauche : SEUL indicateur d'état (couleur posée par
   .status-* ci-dessous). Refonte 2026-07-21 : ex-liseré pleine hauteur à bords
   carrés -> pilule arrondie insérée (rendu plus moderne). */
.lot-item-wrapper::before {
  content: '';
  position: absolute;
  left: 7px;
  top: 50%;
  transform: translateY(-50%);
  width: 4px;
  height: calc(100% - 16px);
  min-height: 14px;
  border-radius: 4px;
  background: #d4d7de;          /* neutre par défaut */
  transition: background 0.12s, height 0.15s ease;
}
/* Lot ouvert : la pastille s'étire un peu (feedback visuel). */
.lot-item-wrapper.active::before { height: calc(100% - 10px); }
.lot-item-wrapper:hover { background: #f8fafe; }
/* Lot ouvert (courant) : surlignage de fond bleu doux. Le liseré gauche garde
   la couleur du statut (pas de barre bleue qui écraserait l'info de statut). */
.lot-item-wrapper.active { background: #eef3ff; }
.lot-item-wrapper.inactive .lot-link { opacity: 0.45; }

/* Lien de sélection (nom du lot + total). Le toggle reste à pleine opacité même
   si le lot est inactif, sinon on ne peut plus le voir/cliquer pour réactiver. */
.lot-link {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  /* Rapproche le bloc n°+nom du toggle (réduit l'espace toggle↔texte
     sans toucher au gap des contrôles à droite). */
  margin-left: -4px;
  text-decoration: none;
  color: var(--text);
  min-width: 0;
}
.lot-link:hover { text-decoration: none; }

/* Bouton toggle (ex-span, devenu <button> pour cliquer en HTMX) */
.lot-toggle {
  width: 28px;
  height: 16px;
  background: #c5cad3;
  border-radius: 8px;
  position: relative;
  flex-shrink: 0;
  transition: background 0.18s;
  border: none;
  padding: 0;
  cursor: pointer;
}
.lot-toggle.on { background: var(--blue); }
.lot-toggle::after {
  content: '';
  position: absolute;
  width: 12px;
  height: 12px;
  background: #fff;
  border-radius: 50%;
  top: 2px;
  left: 2px;
  transition: left 0.18s;
}
.lot-toggle.on::after { left: 14px; }
.lot-toggle:hover:not(:disabled) { filter: brightness(0.95); }
.lot-toggle:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
/* Chiffrage figé : le toggle d'activation et le cadenas par lot ne répondent
   plus (leur POST `lot_update` est refusé par ChiffrageLockMiddleware). Sans
   cette règle ils gardaient leur aspect cliquable, curseur main compris. */
.lot-toggle:disabled,
.lot-lock:disabled {
  opacity: .45;
  cursor: not-allowed;
}

/* Cluster de contrôles à droite (verrou + RG), juste avant le montant. */
.lot-ctrls {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  flex-shrink: 0;
}

/* Verrou du lot (refonte 2026-05-26) :
   - .is-locked  : 🔒 vert PERMANENT (lot verrouillé) -> clic = déverrouille
   - .lock-add   : 🔒 gris révélé AU SURVOL de la ligne -> clic = verrouille
   Au repos, un lot non verrouillé n'affiche donc rien (propre). */
.lot-lock {
  width: 22px;
  height: 22px;
  border-radius: 4px;
  border: 1px solid transparent;
  background: #fff;
  padding: 0;
  cursor: pointer;
  font-size: 12px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: background 0.15s, border-color 0.15s, color 0.15s, opacity 0.12s;
}
.lot-lock.is-locked {
  background: #e6f7ec;
  border-color: #b8e3c6;
  color: #1f8a4c;
}
.lot-lock.is-locked:hover {
  background: #d0eedb;
  border-color: #82c69b;
}
.lot-lock.lock-add {
  border-color: #d6d9e0;
  color: var(--muted);
  opacity: 0;
}
.lot-item-wrapper:hover .lot-lock.lock-add { opacity: 1; }
.lot-lock.lock-add:hover {
  border-color: #1f8a4c;
  color: #1f8a4c;
  background: #e6f7ec;
}
.lot-lock:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }

/* =========================================================================
   STATUTS DE LOT EN SIDEBAR
   Le statut renseigne d'un coup d'oeil ou en est le chiffrage du lot.
   Couleurs tres faibles, juste pour un reperage visuel.
     - a_chiffrer : actif + aucun poste                  → rouge tres faible
     - en_cours   : actif + au moins un poste, non verrouille → orange tres faible
     - verrouille : chiffrage finalise                   → vert (cf. .locked)
     - inactif    : toggle off                           → grise (cf. .inactive)
   .active (lot ouvert dans le main) renforce la teinte avec une bordure laterale
   de la couleur du statut, pour rester coherent (et non bleue).
   ========================================================================= */
/* Refonte 2026-05-26 : le statut se lit UNIQUEMENT via la couleur du liseré
   gauche (.lot-item-wrapper::before). Plus de fond coloré ni de texte rouge :
   les lignes restent blanches/neutres, la liste respire. */
.lot-item-wrapper.status-a-chiffrer::before { background: #cc1030; }   /* rouge foncé (distinct de l'orange) */
.lot-item-wrapper.status-en-cours::before   { background: #e88a1e; }   /* orange */
.lot-item-wrapper.status-verrouille::before { background: #18a05a; }   /* vert */
.lot-item-wrapper.status-inactif::before    { background: #cfd3da; }   /* gris */

/* Tag "désactivé" à côté du nom du lot dans la zone principale */
.lot-inactif-tag {
  display: inline-block;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #888;
  background: #f0f0f0;
  padding: 2px 8px;
  border-radius: 12px;
  margin-left: 10px;
  vertical-align: middle;
}

/* Tag "verrouillé" : pendant vert du tag desactive */
.lot-verrouille-tag {
  display: inline-block;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #1f8a4c;
  background: #e6f7ec;
  padding: 2px 8px;
  border-radius: 12px;
  margin-left: 10px;
  vertical-align: middle;
}

/* Banniere read-only en haut de la zone principale quand le lot est non-editable.
   Couleur differente selon la cause : verrouille (vert) ou desactive (gris). */
.lot-readonly-banner {
  padding: 10px 14px;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 500;
  margin-bottom: 12px;
  border: 1px solid transparent;
}
.lot-readonly-banner.is-locked {
  background: #e6f7ec;
  color: #1f8a4c;
  border-color: #b8e3c6;
}
.lot-readonly-banner.is-inactive {
  background: #f3f4f7;
  color: #6b6f78;
  border-color: #dadde4;
}

/* Quand le lot courant est non-editable, on grise la zone principale (sauf la
   banniere) et on bloque tout pointeur. Les inputs ont aussi un disabled cote
   HTML, donc double protection : visuelle + fonctionnelle. */
.chiffrage-layout.lot-inactive .chiffrage-main .postes-grid,
.chiffrage-layout.lot-locked .chiffrage-main .postes-grid,
.chiffrage-layout.lot-inactive .chiffrage-main .lot-title-bar,
.chiffrage-layout.lot-locked .chiffrage-main .lot-title-bar,
.chiffrage-layout.lot-inactive .chiffrage-main .total-lot-bar,
.chiffrage-layout.lot-locked .chiffrage-main .total-lot-bar,
.chiffrage-layout.lot-inactive .chiffrage-main .postes-actions-top,
.chiffrage-layout.lot-locked .chiffrage-main .postes-actions-top,
.chiffrage-layout.lot-inactive .chiffrage-main .legend,
.chiffrage-layout.lot-locked .chiffrage-main .legend {
  opacity: 0.55;
}
.chiffrage-layout.lot-inactive .chiffrage-main .postes-actions-top button,
.chiffrage-layout.lot-locked .chiffrage-main .postes-actions-top button,
.chiffrage-layout.lot-inactive .chiffrage-main .marge-inline-input,
.chiffrage-layout.lot-locked .chiffrage-main .marge-inline-input,
.chiffrage-layout.lot-inactive .chiffrage-main .cell-input,
.chiffrage-layout.lot-locked .chiffrage-main .cell-input {
  cursor: not-allowed;
  background: #fafafa;
}

.lot-name {
  flex: 1;
  font-size: 13px;
  font-weight: 500;
  color: var(--text);              /* encre neutre, plus de rouge */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* N° aligné à droite sur une colonne fixe. Police de l'app (pas de mono) ;
   chiffres alignés via tabular-nums pour garder une colonne propre. */
.lot-num {
  font-size: 12px;
  color: var(--muted);
  font-weight: 600;
  min-width: 22px;
  text-align: right;
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}

/* Montant à l'extrême droite : colonne fixe alignée et scannable. Police de
   l'app (pas de mono), chiffres alignés via tabular-nums. */
.lot-total {
  font-size: 12.5px;
  color: var(--text);
  font-weight: 600;
  min-width: 72px;
  text-align: right;
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}

/* Lot custom : nom en italique violet pour le distinguer visuellement */
.lot-item-wrapper:has(.lot-link) .lot-link .lot-name { /* default */ }
/* Pas de class JS pour le moment — on style via .lot-link a partir de la classe parent */
.lots-list .lot-item-wrapper.lot-custom .lot-name {
  color: #8e44ad;
  font-style: italic;
}

/* Form de création de lot custom dans la sidebar */
.lot-custom-add-form {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 10px 12px;
  border-top: 1px dashed var(--border);
  background: #fafbfc;
}

.lot-custom-add-form input[type="text"] {
  flex: 1;
  height: 28px;
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: 5px;
  font-size: 12px;
  font-family: inherit;
  background: var(--surface);
  color: var(--text);
  min-width: 0;
}

.lot-custom-add-form input[type="text"]:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(59, 110, 245, 0.12);
}

.lot-custom-add-form button {
  width: 28px;
  height: 28px;
  background: #eef7ee;
  border: 1px solid #c8e0c8;
  border-radius: 5px;
  color: #2e7d2e;
  cursor: pointer;
  font-size: 16px;
  font-weight: 700;
  line-height: 1;
  flex-shrink: 0;
}
.lot-custom-add-form button:hover { background: #d8ecd8; border-color: #2e7d2e; }

/* Bouton "Modifier les lots" en bas de sidebar (mode normal) */
.lots-edit-trigger {
  display: block;
  padding: 10px 14px;
  text-align: center;
  font-size: 12px;
  color: var(--muted);
  text-decoration: none;
  border-top: 1px solid var(--border);
  background: #fafbfc;
  font-weight: 500;
  cursor: pointer;
}
.lots-edit-trigger:hover {
  background: #f0f4ff;
  color: var(--blue);
  text-decoration: none;
}

/* Mode édition : grise le main area pour focus sur la sidebar */
.chiffrage-layout.edit-mode .chiffrage-main {
  pointer-events: none;
  opacity: 0.35;
  filter: grayscale(0.4);
  transition: opacity 0.15s, filter 0.15s;
}

/* Form d'édition des lots */
.lots-edit-form {
  display: flex;
  flex-direction: column;
  flex: 1;
  overflow: hidden;
}

.lots-edit-help {
  padding: 10px 14px;
  font-size: 11.5px;
  color: var(--muted);
  background: #fffbe7;
  border-bottom: 1px solid #f5e9b8;
  margin: 0;
  line-height: 1.4;
}

.lots-edit-list {
  flex: 1;
  overflow-y: auto;
  padding: 8px 10px;
}

.lot-edit-row {
  display: grid;
  grid-template-columns: 60px 1fr;
  gap: 6px;
  margin-bottom: 6px;
  align-items: center;
}

.lot-edit-row.has-error .lot-edit-numero,
.lot-edit-row.has-error .lot-edit-nom {
  border-color: var(--danger);
  background: var(--danger-bg);
}

.lot-edit-row .lot-edit-error {
  grid-column: 1 / -1;
  font-size: 11px;
  color: var(--danger);
  padding: 2px 4px;
}

.lot-edit-numero,
.lot-edit-nom {
  height: 28px;
  padding: 0 8px;
  border: 1px solid var(--border);
  border-radius: 4px;
  font-size: 12px;
  font-family: inherit;
  background: #fff;
  color: var(--text);
  box-sizing: border-box;
}
.lot-edit-numero { font-weight: 700; text-align: center; }
.lot-edit-numero:focus,
.lot-edit-nom:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(59, 110, 245, 0.12);
}

.lots-edit-actions {
  display: flex;
  gap: 8px;
  padding: 10px 12px;
  border-top: 1px solid var(--border);
  background: #fafbfc;
}
.lots-edit-actions .btn-cancel,
.lots-edit-actions .btn-validate {
  flex: 1;
  padding: 8px 12px;
  border: none;
  border-radius: 5px;
  font-size: 12px;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  text-align: center;
}
.lots-edit-actions .btn-cancel {
  background: #fff;
  border: 1px solid var(--border);
  color: var(--muted);
}
.lots-edit-actions .btn-cancel:hover { background: var(--bg); color: var(--text); }
.lots-edit-actions .btn-validate {
  background: var(--blue);
  color: #fff;
}
.lots-edit-actions .btn-validate:hover { background: var(--blue-2); }

/* Input marge inline dans la barre titre du lot (a cote du recap chiffres) */
.marge-inline {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
}
.marge-inline-input {
  width: 56px;
  padding: 3px 6px;
  border: 1px solid var(--border);
  border-radius: 4px;
  font-size: 13px;
  font-weight: 700;
  font-family: inherit;
  color: var(--blue);
  background: #fff;
  text-align: right;
  box-sizing: border-box;
}
.marge-inline-input:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(59, 110, 245, 0.15);
}
/* Supprimer les fleches natives sur ce input number */
.marge-inline-input::-webkit-outer-spin-button,
.marge-inline-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.marge-inline-input { -moz-appearance: textfield; appearance: textfield; }

/* ----- Main content chiffrage -----
   Layout vertical : seul le tableau .postes-grid scrolle (sticky header inside).
   Le bandeau lot, la legende, les boutons + et la barre de total restent figes.
   La sidebar a son propre scroll. */
.chiffrage-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;     /* indispensable pour que le child overflow auto fonctionne */
  overflow: hidden;
  padding: 16px 20px;
}

/* Vue PAR ZONE : meme principe que le mode par poste (header du lot fige en
   haut, total fige en bas, scroll au milieu), mais le conteneur scrollable est
   .zones-scroll (qui enveloppe les N sections de zones) au lieu d'une unique
   .postes-grid. Les sections s'y enchainent a hauteur naturelle ; sans ce
   wrapper, chaque section etait un flex-child de .chiffrage-main qui se faisait
   ecraser (flex-shrink) -> ~4 lignes visibles, scroll impossible (bug 2026-06-02).
   .chiffrage-main reste flex column overflow:hidden -> le header (lot-title-bar,
   selecteur de mode, legende) NE defile PAS, seul .zones-scroll defile. */
.zones-scroll {
  flex: 1 1 auto;
  overflow-y: auto;
  min-height: 0;     /* indispensable pour que l'overflow auto fonctionne en flex */
}
/* En vue par zone, la grille ne doit defiler QU'EN HORIZONTAL : son contenu
   tient en hauteur (c'est .zones-scroll qui gere le defilement vertical de
   toutes les zones). Si on laissait overflow-y:auto, la grille deviendrait un
   conteneur scrollable qui capte la molette verticale SANS pouvoir defiler
   (0 debordement vertical) et SANS la propager a .zones-scroll -> scroll
   vertical mort des qu'une zone a beaucoup de lignes (bug 2026-06-02).
   overflow-y:hidden la rend non-scrollable verticalement -> la molette est
   propagee au parent. overflow-x:auto conserve le scroll horizontal du tableau
   large. (overflow-y:hidden ne masque rien : la grille fait la hauteur de son
   contenu.) */
.zones-scroll .postes-grid {
  overflow-x: auto;
  overflow-y: hidden;
  padding-bottom: 10px;
}

/* Barre de defilement horizontale de la vue PAR ZONE, posee en bas de
   .chiffrage-main (hors du conteneur scrollable) -> toujours visible, quelle
   que soit la position dans la liste des zones. Elle pilote le scroll
   horizontal de toutes les grilles de zone (cf. chiffrage-scroll.js).
   Creee/dimensionnee en JS ; absente en vue par poste (barre native deja en bas
   du viewport) et sur les ecrans assez larges pour tout afficher. */
.zones-hbar {
  flex: none;
  overflow-x: scroll;
  overflow-y: hidden;
  height: 12px;
  margin-top: 3px;
}
.zones-hbar > div {
  height: 1px; /* seule la LARGEUR compte : elle cree le debordement a defiler */
}
/* macOS/WebKit : sans -webkit-appearance:none la barre est en mode "overlay",
   donc invisible au repos -> impossible a saisir a la souris. On force une
   barre permanente et visible, c'est tout l'interet de ce composant.
   ⚠️ NE PAS ajouter `scrollbar-width` ici : dans Chromium la propriete standard
   DESACTIVE ::-webkit-scrollbar et on retombe en overlay invisible (mesure le
   2026-09-07 : 0px consomme avec, 10px sans). Elle est donc reservee a Firefox
   plus bas, qui lui ignore ::-webkit-scrollbar. */
.zones-hbar::-webkit-scrollbar {
  -webkit-appearance: none;
  height: 10px;
}
.zones-hbar::-webkit-scrollbar-track {
  background: #eef1f6;
  border-radius: 5px;
}
.zones-hbar::-webkit-scrollbar-thumb {
  background: #b6bfd2;
  border-radius: 5px;
  border: 2px solid #eef1f6;
}
.zones-hbar::-webkit-scrollbar-thumb:hover {
  background: #8e9cba;
}
/* Firefox : ignore ::-webkit-scrollbar -> proprietes standard, scopees ici pour
   ne pas neutraliser le bloc WebKit ci-dessus (cf. avertissement). */
@supports not selector(::-webkit-scrollbar) {
  .zones-hbar {
    scrollbar-width: thin;
    scrollbar-color: #b6bfd2 #eef1f6;
  }
}

.lot-title-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
  min-height: 28px;        /* hauteur stable, evite le saut quand le badge */
                           /* desactive apparait/disparait */
}
.lot-title-bar h2 {
  font-size: 15px;
  font-weight: 700;
  color: var(--navy);
  line-height: 1.6;        /* assez d'espace vertical pour contenir le badge */
                           /* sans pousser le contenu vers le bas */
}
.lot-title-bar .lot-summary {
  display: flex;
  align-items: center;     /* centre verticalement Prix achat / Marge / Total */
  gap: 22px;
  font-size: 12px;
}
.lot-summary .s-item { color: var(--muted); }
.lot-summary .s-val { font-weight: 700; color: var(--navy); }
.lot-summary .s-val.blue { color: var(--blue); }

/* Selecteur de template par lot : visible juste sous la lot-title-bar.
   Toggle entre "Par poste" (template historique, matrice) et "Par zone"
   (postes regroupes par zone). Verrouille des qu'un poste est cree. */
.lot-template-selector {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 12px 0;
  flex-wrap: wrap;
}
.lot-template-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  font-weight: 600;
}
.lot-template-toggle {
  display: inline-flex;
  background: #eef0f5;
  border-radius: 999px;
  padding: 3px;
  margin: 0;
}
.lot-template-toggle label {
  cursor: pointer;
  padding: 5px 14px;
  font-size: 12px;
  font-weight: 500;
  border-radius: 999px;
  color: var(--muted);
  transition: background 0.15s, color 0.15s;
  user-select: none;
}
.lot-template-toggle label.active {
  background: var(--surface);
  color: var(--blue);
  box-shadow: 0 1px 2px rgba(26, 35, 64, 0.08);
}
.lot-template-toggle label input { display: none; }
.lot-template-hint {
  font-size: 11px;
  color: var(--muted);
  font-style: italic;
}
.lot-template-badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
}
.lot-template-badge--poste { background: #eef3ff; color: var(--blue); }
.lot-template-badge--zone  { background: #fef3cd; color: #8a6814; }

/* Bouton "Importer Excel" : placeholder feature Phase 3, desactive
   visuellement pour signaler le perimetre. Pousse a droite via
   margin-left:auto pour finir la rangee proprement. */
.lot-template-import-btn {
  margin-left: auto;
  padding: 6px 14px;
  font-size: 12px;
  font-weight: 500;
  font-family: inherit;
  background: var(--bg);
  color: var(--muted);
  border: 1px dashed var(--border);
  border-radius: 6px;
  cursor: not-allowed;
  opacity: 0.7;
}

/* Bouton "↩ Annuler" (undo de la derniere edition de cellule). Cliquable,
   pousse a droite (avant le bouton import, lui aussi margin-left:auto). */
.chiffrage-undo-btn {
  margin-left: auto;
  padding: 6px 14px;
  font-size: 12px;
  font-weight: 600;
  font-family: inherit;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  transition: background .12s ease, border-color .12s ease, color .12s ease;
}
.chiffrage-undo-btn:hover {
  background: #eef3ff;
  border-color: var(--blue);
  color: var(--blue-2);
}
.chiffrage-undo-btn:active { background: #e2ebff; }
/* Quand le bouton undo est present, le bouton import n'a plus besoin de l'auto
   (l'undo l'a deja pousse a droite) : ils se suivent a droite. */
.chiffrage-undo-btn + .lot-template-import-btn { margin-left: 8px; }

/* ----- Menu "Valider" de la barre d'outils du chiffrage -------------------
   Raccourci vers les 2 actions de fin de chiffrage (valider une version /
   passer en facturation), sinon disponibles seulement sur Resume & Exports.
   Bati sur <details>/<summary> natif : l'ouverture ne coute pas de JS, ce qui
   compte ici car #chiffrage-content est re-rendu en boucle par HTMX. */
.chiffrage-actions {
  position: relative;
  margin-left: auto;      /* pousse le groupe a droite si "Annuler" est absent */
}
/* "Annuler" porte deja margin-left:auto : deux `auto` cote a cote se
   partageraient l'espace libre et decolleraient les boutons l'un de l'autre.
   Le premier element a droite garde l'auto, les suivants un simple gap. */
.chiffrage-undo-btn + .chiffrage-actions { margin-left: 8px; }
.chiffrage-actions + .lot-template-import-btn { margin-left: 8px; }

/* Declencheur : meme gabarit que le bouton "Annuler" voisin, teinte vert au
   survol / a l'ouverture pour annoncer la couleur des actions du menu. */
.chiffrage-actions-trigger {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  font-size: 12px;
  font-weight: 600;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  user-select: none;
  list-style: none;       /* retire le triangle natif du <summary> (Firefox) */
  transition: background .12s ease, border-color .12s ease, color .12s ease;
}
.chiffrage-actions-trigger::-webkit-details-marker { display: none; }
.chiffrage-actions-trigger:hover,
.chiffrage-actions[open] .chiffrage-actions-trigger {
  background: #e6f7ec;
  border-color: #82c69b;
  color: #136634;
}
/* Chevron du declencheur (heroicon micro, dessine plein). Taille FIXE en px et
   non en em comme .ic : un chevron est un affordance de menu, il ne doit pas
   grossir avec le libelle. La regle vient apres .ic dans la feuille, elle gagne
   donc a specificite egale. Legerement estompe au repos pour rester en retrait
   du libelle, plein a l'ouverture. */
/* Le triangle des entrees du menu se detache du libelle : colles, ils se
   lisaient comme un seul mot. */
.chiffrage-actions-puce { margin-right: 6px; }

.chiffrage-actions-caret {
  width: 16px;
  height: 16px;
  margin-left: 3px;
  opacity: 0.55;
  transition: transform .12s ease, opacity .12s ease;
}
.chiffrage-actions[open] .chiffrage-actions-caret {
  transform: rotate(180deg);
  opacity: 1;
}

/* Panneau : meme langage visuel que .poste-insert-menu, l'autre menu
   contextuel du chiffrage. Ancre a droite, le declencheur etant colle au bord
   droit de la barre. z-index 60 = au-dessus d'une cellule focus (50), sous les
   modales (1000). */
.chiffrage-actions-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 60;
  min-width: 232px;
  padding: 4px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(26, 35, 64, 0.14);
}
.chiffrage-actions-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 10px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}
/* Memes couleurs que les boutons .resume-action-* de Resume & Exports : c'est
   la meme action, elle doit se reconnaitre d'un ecran a l'autre. */
.chiffrage-actions-item--validate { color: #1f8a4c; }
.chiffrage-actions-item--validate:hover { background: #e6f7ec; color: #136634; }
.chiffrage-actions-item--facturation { color: #8a6814; }
.chiffrage-actions-item--facturation:hover { background: #fdf2cc; color: #6b5010; }

/* ----- Copier / coller des lignes (barre du lot) -------------------------
   Cf. services/copier_coller.py. Toujours precede du bouton « Importer
   Excel » (rendu sans condition) : un simple gap suffit. Le menu reprend le
   gabarit du menu « Valider », teinte bleue : copier n'est pas une action de
   validation. « Coller » n'apparait qu'avec un presse-papier rempli, en bleu
   plein pour qu'on le trouve en arrivant dans le lot cible. */
.lot-template-import-btn + .lot-lignes-actions { margin-left: 8px; }
.lot-lignes-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}
.lot-lignes-actions .chiffrage-actions { margin-left: 0; }
.lot-lignes-menu .chiffrage-actions-trigger:hover,
.lot-lignes-menu[open] .chiffrage-actions-trigger {
  background: #eef3ff;
  border-color: var(--blue);
  color: var(--blue-2);
}
.lot-lignes-menu .chiffrage-actions-item { color: var(--text); white-space: nowrap; }
.lot-lignes-menu .chiffrage-actions-item:hover { background: #eef3ff; color: var(--blue-2); }
.lot-lignes-coller {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  font-size: 12px;
  font-weight: 600;
  font-family: inherit;
  background: var(--blue);
  color: #fff;
  border: 1px solid var(--blue);
  border-radius: 6px;
  cursor: pointer;
}
.lot-lignes-coller:hover { background: var(--blue-2); border-color: var(--blue-2); }

/* ----- Légende ----- */
.legend {
  display: flex;
  gap: 18px;
  margin-bottom: 10px;
  font-size: 11px;
  color: var(--muted);
  align-items: center;
}
.legend-item { display: flex; align-items: center; gap: 6px; }
.legend-dot { width: 11px; height: 11px; border-radius: 2px; }
.legend-dot.visible { background: #eef3ff; border: 1px solid var(--blue); }
.legend-dot.internal { background: #fff8f2; border: 1px solid #e67e22; }
.legend-dot.option { background: #fffbf0; border: 1px solid #f39c12; }

/* =========================================================================
   POSTES — CSS GRID (refonte from scratch)
   Chaque ligne est une grid avec exactement les memes 10 colonnes.
   Alignement deterministe par construction, plus de quirks de table HTML.
   ========================================================================= */

.postes-grid {
  background: #fff;
  border: 1px solid #eaecef;
  border-radius: 4px;
  overflow: auto;          /* x ET y : scroll local au tableau */
  width: 100%;
  flex: 1 1 auto;          /* prend tout l'espace restant dans .chiffrage-main */
  min-height: 0;           /* permet au container flex de retreindre la hauteur */
}

.row {
  display: grid;
  grid-template-columns:
    76px                 /* col-numero : + (inserer) | N° cliquable | ⋮⋮ | 🗑 */
    350px                /* col-designation : largeur FIXE (+20) ; texte long -> wrap 2 lignes */
    60px                 /* col-unite */
    334px                /* col-qte : P2 -> 3 sous-colonnes Chrome / Entr. / Retenue (+5 chacune) */
    110px                /* col-pu */
    130px                /* col-total */
    130px                /* col-achat (bumpe pour eviter wrap des montants honoraires) */
    110px                /* col-marge (checkbox + input + %, evite la troncature) */
    minmax(140px, 1fr)   /* col-fournisseur : flex (grandit avec la fenêtre) */
    120px                /* col-ref-devis : largeur FIXE (ne grandit jamais avec la fenêtre) */
    minmax(140px, 1fr)   /* col-commentaire : flex (grandit avec la fenêtre) */
    44px;                /* col-flag : checkbox surligner */
  /* DOIT valoir EXACTEMENT la somme des colonnes ci-dessus (les deux `1fr`
     comptant pour leur minimum de 140) :
       76+350+60+334+110+130+130+110+140+120+140+44 = 1744
     Si min-width est INFERIEUR a cette somme, la grille deborde de sa propre
     boite sur ecran etroit (13", ou les `1fr` sont a leur minimum) : le fond de
     la ligne s'arrete avant la derniere colonne et la case "surligner" se
     retrouve sur bande blanche au lieu du jaune. C'etait le cas a 1720 (24 px
     de trop peu). A recalculer a chaque ajout/redimensionnement de colonne. */
  min-width: 1744px;
  width: 100%;
}

/* ===== P2 : colonne Qté = 3 sous-parties Chrome / Entreprise / Retenue ===== */
.qte3 { display: flex; gap: 3px; width: 100%; align-items: center; justify-content: flex-end; }
.qte3 > * { flex: 0 0 auto; }
/* Chrome / Entreprise : input qté + bouton ƒx (calcul minute) côte à côte.
   Bande de couleur derrière chaque sous-colonne (violet pâle Chrome / vert pâle
   Entreprise) reprise de la maquette pour bien distinguer les deux colonnes. */
.q3-chrome,
.q3-entre  { width: 102px; display: flex; align-items: center; gap: 3px; justify-content: flex-end;
             border-radius: 6px; padding: 1px 3px; }
.q3-chrome { background: #ece5ff; }   /* bande violet pâle (Chrome) — couleur maquette */
.q3-entre  { background: #d8f5ec; }   /* bande vert pâle (Entreprise) */
.q3-ret    { width: 120px; display: flex; align-items: center; justify-content: flex-end; gap: 4px; }
.qte3 input.cell-input-num { width: 100%; }
/* dans Chrome/Entr : l'input prend la place restante, le ƒx garde sa largeur.
   On ne force AUCUN fond : `.cell-input` est déjà transparent (bordure
   transparente, texte bleu, focus jaune pâle) -> la bande colorée de la
   sous-colonne transparaît à travers l'input, pas de boîte blanche. */
.q3-chrome > input.cell-input-num,
.q3-entre  > input.cell-input-num { flex: 1 1 auto; width: auto; min-width: 0; text-align: right; }
/* en-tête (fond navy) : pas de bande colorée derrière les sous-libellés. */
.row-header .q3-chrome,
.row-header .q3-entre { background: transparent; padding: 0; }
/* input piloté par un métré (readonly) : on garde la bande de la colonne
   (fond transparent, pas de boîte ni de liseré) ; le repère « piloté » = valeur
   en gras + ƒx bleu. */
.qte3 input.cell-input-num[readonly] { background: transparent; font-weight: 700;
                                       color: var(--navy); cursor: pointer; }
/* bouton ƒx : ouvre la modale Calcul minute ; bleu quand un métré pilote la cellule. */
.metre-fx { flex: 0 0 auto; font-size: 9px; font-weight: 700; line-height: 1.4; cursor: pointer;
            border: 1px solid #d4d9e6; background: #fff; color: #8a93a6; border-radius: 4px;
            padding: 1px 3px; user-select: none; }
.metre-fx:hover { border-color: #b9c2d6; color: #5a48b0; }
.metre-fx.driven { background: #2d5bff; color: #fff; border-color: #2d5bff; }
/* en-tête : sous-libellés colorés (sur fond navy) */
.row-header .qte3 > span { font-size: 10.5px; letter-spacing: .04em; text-align: right; line-height: 1.1; white-space: nowrap; }
.q3lab-chrome { color: #cdbcff; }
.q3lab-entre  { color: #9fe6d8; }
.q3lab-ret    { color: #fff; }
/* sommes (ligne poste, lecture seule) */
.q3sum { font-weight: 700; }
.q3sum.c { color: #5a48b0; }
.q3sum.e { color: #1b8b7f; }
.q3sum.r { color: var(--navy); }
.q3sum.r.low { color: #c0392b; }
/* retenue : valeur + chips C/E */
.q3ret-val { font-weight: 700; color: var(--navy); }
.q3ret-val.low { color: #c0392b; }
.q3chip { font-size: 9px; font-weight: 800; border-radius: 4px; padding: 0 4px; cursor: pointer;
          border: 1px solid #d4d9e6; background: #fff; color: #8a93a6; line-height: 1.6; user-select: none; }
.q3chip:hover:not(.is-readonly) { border-color: #b9c2d6; }
.q3chip.active.c { background: #ece7ff; color: #5a48b0; border-color: #cdbcff; }
.q3chip.active.e { background: #d8f5ef; color: #1b8b7f; border-color: #a6e6da; }
/* Lot non éditable : les puces ne restent qu'un indicateur (quelle quantité est
   retenue). Ce sont des <span>, pas des <button> — `disabled` glisse dessus, le
   partial chiffrage/_q3_chips.html rend donc une variante sans attribut hx-*. */
.q3chip.is-readonly { cursor: default; }
.q3warn { color: #c0392b; font-weight: 800; cursor: help; margin-right: 2px; }

/* Cellules numeriques : pas de wrap, sinon les montants longs (honoraires
   a 15 000 €) s'affichent sur 2 lignes et cassent l'alignement vertical. */
.cell.col-num {
  white-space: nowrap;
}

/* Colonne "surligner" : checkbox centree, header avec icone. */
.cell.col-flag {
  justify-content: center;
  padding: 7px 4px;
}
.row-header .cell.col-flag {
  color: #f0c869;       /* warning subtil dans le header */
  font-size: 14px;
}
.flag-cell .flag-checkbox {
  width: 18px;
  height: 18px;
  cursor: pointer;
  accent-color: #d4a017;  /* jaune-orange pour la coherence visuelle avec le highlight */
  margin: 0;
}

/* Ligne surlignee : fond jaune subtil, plus marque au hover. */
.row.is-flagged {
  background: #fff8dc !important;
}
.row.is-flagged:hover {
  background: #fdf3c3 !important;
}
/* Les cells "internal" (oranges) gardent leur teinte mais en jaunatre.
   Ici on force la cellule a heriter du fond de la ligne pour eviter le
   patchwork visuel (orange melange avec jaune). */
.row.is-flagged .cell.cell-internal {
  background: transparent;
}

.cell {
  padding: 7px 9px;
  font-size: 12.5px;
  border-bottom: 1px solid #f0f2f6;
  display: flex;
  align-items: center;
  white-space: normal;
  overflow-wrap: anywhere;
}

/* ---- Colonnes alignees a droite (chiffres) ---- */
.cell.col-num { justify-content: flex-end; }

/* ---- Header (navy) ---- */
.row-header {
  background: var(--navy);
  color: #fff;
  /* Reste fige en haut du tableau pendant le scroll vertical des postes.
     z-index 5 pour passer au-dessus des inputs/cellules qui scrollent dessous. */
  position: sticky;
  top: 0;
  z-index: 5;
}
.row-header .cell {
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-bottom: none;
  border-right: 1px solid #2a3550;
}
.row-header .cell:last-child { border-right: none; }
.row-header .cell.cell-internal {
  background: #3d2800;
  color: #ffa94d;
  border-right-color: #4d3500;
}
.row-header .cell.cell-internal-first { border-left: 3px solid #e67e22; }

/* ---- Numero d'item ---- */
.cell.col-numero {
  justify-content: center;
  font-size: 11px;
  color: var(--muted);
  font-weight: 600;
}
.row-header .cell.col-numero { color: #fff; }

/* ---- Lignes postes ---- */
.row-poste,
.row-option {
  background: #fff;
  border-top: 2px solid #c5cad3;     /* separation marquee entre groupes poste/option */
}
.row-poste:hover { background: #fafbff; }

/* Vue par zone (.postes-dropzone) : separation entre postes plus fine et plus
   claire. La vue par poste (.poste-block) garde le 2px marque ci-dessus. */
.postes-dropzone .row-poste {
  border-top-width: 1px;
  border-top-color: #dce0ea;
}

/* ---- Cellules internes (oranges, masquees export) ---- */
.cell.cell-internal {
  background: #fff8f2;
  border-left: 1px solid #fde0c0;
}
.cell.cell-internal-first {
  border-left: 3px solid #e67e22;
}

/* ---- Cellules calculees (non-editables) : NOIR ---- */
.qte-cell { font-weight: 700; color: var(--text); }       /* somme des qty zones (vue par poste) */
/* Vue par zone : Chrome / Entreprise sont des champs éditables (pas une somme)
   -> poids NORMAL. Le gras .qte-cell reste réservé aux sommes de la vue par
   poste ; la retenue garde son gras (.q3ret-val). */
.qte-cell.zone-qty .q3-chrome,
.qte-cell.zone-qty .q3-entre,
.qte-cell.zone-qty .q3-chrome input,
.qte-cell.zone-qty .q3-entre input,
.qte-cell.zone-qty .q3-chrome input[readonly],
.qte-cell.zone-qty .q3-entre input[readonly] { font-weight: 400; }
.total-cell { font-weight: 700; color: var(--navy); }     /* qty * PU */
.option-total { color: #c0392b; }                          /* exception : option en rouge */

/* ---- Lignes zones (compactes, plus serrees que les postes) ---- */
.row-zone {
  background: #f7f9ff;
}
.row-zone .cell {
  padding: 2px 9px;                /* tres compact, feeling tableur dense */
  font-size: 11px;
  color: #555;
  border-bottom: 1px solid #eef0f5;
}
.row-zone .cell-input {
  padding: 2px 6px;
  height: auto;
}
.row-zone .zone-label {
  padding-left: 24px;
  color: var(--text);              /* nom zone non-editable = noir */
  font-weight: 500;
  white-space: nowrap;
}
.row-zone .zone-qty {
  font-weight: 700;
  color: var(--blue);              /* qty zone editable = bleu */
}
.row-zone-empty .zone-empty-cell {
  color: var(--muted);
  font-style: italic;
}

/* ---- Section row (banner "Options du lot") ---- */
.row-section {
  display: block;        /* pas de grid : c'est une banniere full-width */
  background: #fef9f0;
  padding: 6px 12px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: #c07000;
  font-weight: 700;
  border-top: 2px solid #f39c12;
  border-bottom: 1px solid #fdecc8;
}

/* ---- Lignes options ---- */
.row-option {
  background: #fffbf0;
  border-bottom: 1px solid #fdecc8;
  font-style: italic;
}
.row-option .cell { color: #7d5a00; }
.row-option .cell.cell-internal { background: #fff8e8; }
.row-option .cell:first-child { border-left: 3px solid #f39c12; }

/* ============= EDITION INLINE DES POSTES (iter 4a) ============= */

/* Regle generale : tout ce qui est editable (cell-input) en BLEU.
   Les cellules calculees (qte sum, PU client, total) en NOIR. */
.cell-input {
  width: 100%;
  border: 1px solid transparent;
  background: transparent;
  font: inherit;
  color: var(--blue);          /* editable = bleu */
  padding: 4px 6px;
  border-radius: 3px;
  box-sizing: border-box;
  outline: none;
}
.cell-input:hover:not(:disabled) {
  background: #fafbff;
  border-color: #e0e4eb;
}
.cell-input:focus {
  background: #fffbe7;
  border-color: var(--blue);
  box-shadow: 0 0 0 2px rgba(59, 110, 245, 0.15);
}
.cell-input:disabled {
  color: #aaa;
  cursor: not-allowed;
}
.cell-input-num { text-align: right; }
.cell-input-num::-webkit-outer-spin-button,
.cell-input-num::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.cell-input-num { -moz-appearance: textfield; appearance: textfield; }

/* Designation = <textarea> : largeur fixe (colonne), auto-hauteur 1 -> 2 lignes
   quand le texte est long (field-sizing), puis scroll au-delà. Pas de poignée
   de resize, retour à la ligne sur mots longs. */
/* Texte d'aide de la designation : une ligne neuve n'a plus la vraie valeur
   "Nouveau poste" qu'il fallait effacer avant de saisir (remonte 2026-09-07),
   mais un placeholder -- il s'efface donc tout seul a la frappe, et n'apparait
   JAMAIS sur une ligne deja renseignee. En italique + gris clair pour qu'on
   voie au premier coup d'oeil que c'est une aide, pas un contenu. */
.cell-input-designation::placeholder {
  color: #a9b0be;
  font-style: italic;
  opacity: 1;   /* Firefox applique une opacite par defaut */
}

.cell-input-designation {
  resize: none;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  line-height: 1.3;
  field-sizing: content;     /* auto-grandit avec le contenu (Chrome ≥ 123) */
  min-height: 1.55em;        /* ~1 ligne */
  max-height: 2.85em;        /* ~2 lignes, puis overflow */
  overflow-y: auto;
}

/* Custom dropdown unite : long form en dropdown, short form en cellule.
   Trick : <select> rendu transparent par CSS, <span> superpose montre la
   forme courte. Le dropdown deplie reste en long form (lisible). */
.unite-picker {
  position: relative;
  width: 100%;
  height: 100%;
}
.unite-short {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  padding: 4px 8px;
  pointer-events: none;
  color: var(--blue);
  font-weight: 500;
  z-index: 1;
}
.unite-select {
  width: 100%;
  border: 1px solid transparent;
  background: transparent;
  font: inherit;
  padding: 4px 18px 4px 6px;
  border-radius: 3px;
  box-sizing: border-box;
  outline: none;
  color: transparent;          /* cache le texte de la valeur selectionnee */
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='8' height='5' viewBox='0 0 8 5'><path fill='%233b6ef5' d='M0 0l4 5 4-5z'/></svg>");
  background-repeat: no-repeat;
  background-position: right 4px center;
}
.unite-select option {
  color: var(--text);          /* long form en noir dans le dropdown deplie */
  background: #fff;
}
.unite-select:hover {
  background-color: #fafbff;
  border-color: #e0e4eb;
}
.unite-select:focus {
  background-color: #fffbe7;
  border-color: var(--blue);
  box-shadow: 0 0 0 2px rgba(59, 110, 245, 0.15);
}

.marge-cell {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px 6px;
}
.forcer-marge-toggle {
  display: flex;
  align-items: center;
  cursor: pointer;
}
.forcer-marge-toggle input[type="checkbox"] {
  margin: 0;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  width: 12px;
  height: 12px;
  border: 1.5px solid var(--border);
  border-radius: 2px;
  background: #fff;
  position: relative;
  flex-shrink: 0;
}
.forcer-marge-toggle input[type="checkbox"]:checked {
  background: #c07000;
  border-color: #c07000;
}
.forcer-marge-toggle input[type="checkbox"]:checked::after {
  content: '';
  position: absolute;
  top: 1px; left: 3px;
  width: 3px; height: 6px;
  border: solid #fff; border-width: 0 1.5px 1.5px 0;
  transform: rotate(45deg);
}
.cell-input-marge {
  flex: 1;
  min-width: 0;
  font-weight: 600;
  text-align: right;
  /* color: hérite de .cell-input (bleu si editable, gris si disabled) */
}
.marge-cell .suffix {
  font-size: 11px;
  color: var(--muted);
  flex-shrink: 0;
}

/* Cellule N° avec bouton supprimer au hover de la ligne */
/* Cellule N° = petite barre d'outils de ligne :
     [+]  N°  [⋮⋮]                        [🗑]
   Le "+" et la corbeille sont en position absolue (donc sans effet sur la
   largeur) et n'apparaissent qu'au survol ; les paddings reservent leur place
   pour que le numero ne se decale pas quand ils apparaissent. */
.cell.col-numero {
  position: relative;
  padding-left: 30px;
  padding-right: 20px;
}
.poste-numero {
  display: block;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
/* Numero cliquable (changement de position). Se donne des airs de simple texte
   au repos : c'est un numero avant d'etre un bouton. */
.poste-numero-btn {
  background: transparent;
  border: 1px solid transparent;
  border-radius: 4px;
  padding: 1px 4px;
  font: inherit;
  color: inherit;
  cursor: pointer;
}
.row-poste:hover .poste-numero-btn,
.row-option:hover .poste-numero-btn {
  border-color: #d3d9e4;
  background: #fff;
  color: var(--navy);
}
.poste-numero-btn:hover {
  border-color: var(--primary, #3b6ef5);
  color: var(--primary, #3b6ef5);
}
/* Champ de saisie de la position (remplace le bouton le temps de la saisie). */
.poste-numero-input {
  width: 34px;
  padding: 1px 2px;
  font: inherit;
  font-variant-numeric: tabular-nums;
  text-align: center;
  border: 1px solid var(--primary, #3b6ef5);
  border-radius: 4px;
  background: #fff;
  color: var(--navy);
  -moz-appearance: textfield;
  appearance: textfield;
}
.poste-numero-input::-webkit-outer-spin-button,
.poste-numero-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
/* Bouton "+" d'insertion contextuelle, a l'extreme gauche de la ligne. */
.poste-insert {
  display: none;
  position: absolute;
  left: 1px;
  top: 50%;
  transform: translateY(-50%);
  width: 15px;
  height: 15px;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid #d3d9e4;
  border-radius: 4px;
  background: #fff;
  color: var(--muted);
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
}
.poste-insert:hover {
  border-color: var(--primary, #3b6ef5);
  color: var(--primary, #3b6ef5);
}
/* Menu "au-dessus / en dessous". Rattache au <body> (et non a la cellule) pour
   echapper au clipping du tableau scrollable -> positionne en JS. */
.poste-insert-menu {
  position: absolute;
  z-index: 60;
  min-width: 168px;
  padding: 4px;
  background: #fff;
  border: 1px solid var(--border, #dde1ea);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(26, 35, 64, 0.14);
}
.poste-insert-menu button {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 7px 10px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  font: inherit;
  font-size: 12.5px;
  color: var(--navy, #1a2340);
  text-align: left;
  cursor: pointer;
}
.poste-insert-menu button:hover {
  background: #eef2fb;
  color: var(--primary, #3b6ef5);
}
/* Corbeille : posee a DROITE de la cellule N° (donc entre le numero et la
   designation). Elle remplacait le numero au survol ; le numero etant devenu
   cliquable, il doit rester visible -> elle prend sa propre place. */
.poste-delete {
  display: none;
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid transparent;
  color: var(--danger);
  cursor: pointer;
  font-size: 12px;
  padding: 0 2px;
  border-radius: 3px;
}
.poste-delete:hover {
  background: var(--danger-bg);
  border-color: rgba(214, 69, 69, 0.3);
}
/* Le numero RESTE visible au survol : il est cliquable (changement de
   position). La corbeille ne le remplace donc plus -- elle est posee a droite
   de la cellule, et le "+" d'insertion a gauche ; les deux n'apparaissent qu'au
   survol pour garder la colonne calme au repos. */
.row-poste:hover .poste-delete,
.row-option:hover .poste-delete,
.row-poste:hover .poste-insert,
.row-option:hover .poste-insert { display: inline-flex; }

/* Boutons ajouter poste / option */
/* Barre des boutons "+ Ajouter poste/option" AU-DESSUS de la table postes */
.postes-actions-top {
  display: flex;
  gap: 8px;
  margin-bottom: 8px;
  align-items: center;
}

/* Template par zone : sections groupant les postes par zone du projet.
   Chaque section a un header avec le nom de zone + surface, suivi de la
   grille de postes (meme structure que template par poste), puis des
   boutons "+ Ajouter un poste" / "+ Ajouter une option" specifiques a
   cette zone. */
.lot-zone-section {
  margin-bottom: 26px;
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
  background: var(--surface);
}
.lot-zone-header {
  padding: 8px 16px;
  background: #f4f6fa;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.lot-zone-name {
  font-size: 14px;
  font-weight: 700;
  color: var(--navy);
  margin: 0;
  /* baseline interne pour aligner nom + surface sur la meme ligne de texte */
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.lot-zone-surface {
  font-size: 12px;
  font-weight: 500;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
/* Boutons d'ajout : a droite du nom de zone (dans le header). */
.lot-zone-actions {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}
/* Rappel d'ajout en bas de zone : deux boutons pleine largeur a bordure
   pointillee, sobres, texte centre nommant la zone (style maquette 2026-06-02).
   Hors de la .postes-grid -> restent fixes pendant le scroll horizontal. */
.lot-zone-footer {
  display: flex;
  gap: 10px;
  padding: 10px 12px 12px;
  border-top: 1px solid var(--border);
}
.zone-footer-add {
  flex: 1;
  padding: 11px 14px;
  text-align: center;
  border-radius: 8px;
  cursor: pointer;
  font-size: 12.5px;
  font-weight: 600;
  font-family: inherit;
  color: var(--muted);
  background: transparent;
  border: 1px dashed #c8d0dc;
  transition: color 0.12s, border-color 0.12s, background 0.12s;
}
.zone-footer-add:hover:not(:disabled) {
  color: var(--blue);
  border-color: var(--blue);
  background: #f5f9ff;
}
.zone-footer-add--option:hover:not(:disabled) {
  color: #c47d1a;
  border-color: #e0a64d;
  background: #fff9f0;
}
.zone-footer-add:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.row-empty {
  display: flex;
  padding: 24px 14px;
  align-items: center;
  justify-content: center;
}
.btn-add-poste, .btn-add-option {
  padding: 6px 14px;
  border-radius: 5px;
  cursor: pointer;
  font-size: 12px;
  font-weight: 600;
  font-family: inherit;
  border: 1px dashed;
}
.btn-add-poste {
  background: #eef3ff;
  border-color: var(--blue);
  color: var(--blue);
}
.btn-add-poste:hover { background: #dce8ff; }
/* Desactives (lot verrouille/desactive, ou projet fige apres passage en
   facturation) : sans ca ils gardaient leur aspect cliquable et seul le
   curseur trahissait l'etat -- on cliquait pour rien. Meme traitement que
   .btn-add-texte, leur voisin de barre. */
.btn-add-poste:disabled,
.btn-add-option:disabled {
  opacity: .5;
  cursor: not-allowed;
}
.btn-add-poste:disabled:hover { background: #eef3ff; }
.btn-add-option:disabled:hover { background: #fffbf0; }
.btn-add-option {
  background: #fffbf0;
  border-color: #f39c12;
  color: #c07000;
}
.btn-add-option:hover { background: #fff3d6; }

/* Input quantité par zone (inline dans la ligne zone) */
.cell-input-zone-qte {
  font-weight: 700;
  color: var(--blue);
  text-align: right;
}

/* Alerte marge forcée dans le recap lot */
.marge-forcee-alert {
  display: inline-flex;
  align-items: center;
  background: #fff3cd;
  color: #856404;
  border: 1px solid #ffe89e;
  padding: 4px 10px;
  border-radius: 12px;
  font-size: 11.5px;
  font-weight: 600;
  cursor: help;
}

/* Total lot bar (footer navy) */
.total-lot-bar {
  display: flex;
  justify-content: flex-end;
  gap: 28px;
  margin-top: 14px;
  padding: 12px 18px;
  background: var(--navy);
  color: #fff;
  border-radius: 6px;
}
.total-lot-bar .t-item { font-size: 11px; color: #8899aa; margin-right: 6px; text-transform: uppercase; letter-spacing: 0.04em; font-weight: 600; }
.total-lot-bar .t-val { font-size: 14px; font-weight: 700; color: #fff; }
.total-lot-bar .t-val.highlight { color: #5dade2; }
/* Options : orange (suppléments, hors total operation principale). Echo du
   header navy. Pas de pastille Variantes ici : le footer est scopé au lot
   courant, les variantes sont au niveau projet (cf. header). */
.total-lot-bar .t-val-options { color: #ffb878; }

/* =============================================================================
   Page Utilisateurs
   ============================================================================= */

/* Tableau des utilisateurs : meme structure visuelle que .projets-table */
.utilisateurs-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--surface);
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 1px 4px rgba(26,35,64,0.05);
}
.utilisateurs-table thead { background: #f8f9fb; }
.utilisateurs-table th {
  text-align: left;
  padding: 12px 16px;
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-bottom: 1px solid var(--border);
}
.utilisateurs-table td {
  padding: 14px 16px;
  font-size: 13px;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
.utilisateurs-table tr:last-child td { border-bottom: none; }
.utilisateurs-table tr:hover td { background: #fafbfc; }
.utilisateurs-table tr.row-disabled td { opacity: 0.55; }

/* Badges roles + statuts (s'ajoute aux .badge existants pour les projets).
   Un badge par role applicatif (cf. UserProfile.Role) : la valeur du role
   (charge/economiste/admin) est utilisee comme suffixe de classe cote template
   -> .badge-charge / .badge-economiste / .badge-admin. */
.badge-super      { background: #ede7f6; color: #5e35b1; }   /* violet  - super admin */
.badge-admin      { background: #fff3e0; color: #e65100; }   /* orange  - admin */
.badge-economiste { background: #e0f2f1; color: #00897b; }   /* teal    - economiste */
.badge-charge     { background: #e3f2fd; color: #1565c0; }   /* bleu    - charge d'operation */
.badge-actif      { background: #d4edda; color: #155724; }
.badge-inactif    { background: #f0f0f0; color: #666; }

/* Boutons-icones dans la colonne actions du tableau */
.utilisateurs-table .actions { white-space: nowrap; }
.link-btn {
  background: transparent;
  border: none;
  cursor: pointer;
  font-size: 16px;
  padding: 4px 8px;
  border-radius: 4px;
  line-height: 1;
}
.link-btn:hover { background: var(--bg); }
.link-btn-disabled {
  display: inline-block;
  padding: 4px 8px;
  color: var(--muted);
  cursor: not-allowed;
}

/* Variants alert (succes / info), en complement du .alert danger par defaut */
.alert-success {
  background: #e6f4ea;
  color: #1e6c2c;
  border-color: rgba(30, 108, 44, 0.2);
}
.alert-info {
  background: #e8f0fe;
  color: #1c4ba0;
  border-color: rgba(28, 75, 160, 0.2);
}
.alert-error {
  background: var(--danger-bg);
  color: var(--danger);
  border-color: rgba(214, 69, 69, 0.2);
}
.messages-zone { margin-bottom: 16px; }

/* =============================================================================
   Modal HTMX (utilisee pour creation/edition utilisateur)
   ============================================================================= */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(26, 35, 64, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: 20px;
  backdrop-filter: blur(2px);
}
.modal {
  background: var(--surface);
  border-radius: 12px;
  box-shadow: 0 20px 50px rgba(26, 35, 64, 0.25);
  width: 100%;
  max-width: 580px;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 24px;
  border-bottom: 1px solid var(--border);
}
.modal-header h2 {
  font-size: 17px;
  font-weight: 600;
  color: var(--text);
}
.modal-close {
  background: transparent;
  border: none;
  font-size: 24px;
  color: var(--muted);
  cursor: pointer;
  line-height: 1;
  padding: 4px 10px;
  border-radius: 4px;
}
.modal-close:hover { background: var(--bg); color: var(--text); }
/* `.modal` est en flex column avec `max-height: 90vh`. Quand le contenu est
   wrappe dans un `<form>` (cas des modals utilisateur / poste / etc), le
   form doit aussi etre un flex item qui prend la hauteur restante pour que
   `.modal-body { overflow-y: auto }` puisse declencher le scroll. Sans ca,
   le form garde sa hauteur de contenu et le body deborde sans scroll. */
.modal > form {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
}
.modal-body {
  padding: 20px 24px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 14px;
  flex: 1 1 auto;
  min-height: 0;
}
.modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  padding: 14px 24px;
  border-top: 1px solid var(--border);
  background: #fafbfc;
}

/* ===== Modale « Calcul minute » (P2/B2) ===== */
.metre-modal { width: 460px; max-width: 94vw; }
/* en-tête sur 3 niveaux : titre / poste · zone / badge du champ edite */
.metre-modal-header { align-items: flex-start; }
.metre-modal-titles { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.metre-modal-titles h2 { margin: 0; }
.metre-modal-loc { margin: 0; font-size: 13px; font-weight: 500; color: var(--muted); }
.metre-loc-sep { color: #c8cedb; margin: 0 4px; }
.metre-modal-champ { align-self: flex-start; font-size: 11px; font-weight: 800; padding: 2px 9px;
                     border-radius: 6px; text-transform: uppercase; letter-spacing: .03em; }
.metre-champ-chrome     { background: #ece7ff; color: #5a48b0; }
.metre-champ-entreprise { background: #d8f5ef; color: #1b8b7f; }
.metre-form { display: flex; flex-direction: column; min-height: 0; flex: 1 1 auto; }
/* champ « quantité retenue » : libellé à gauche, valeur à droite (même ligne) ;
   le hint passe sous la ligne quand un métré pilote la cellule. */
.metre-direct { display: flex; flex-direction: row; align-items: center; justify-content: space-between;
                gap: 12px; flex-wrap: wrap; }
.metre-direct > label { font-size: 13px; font-weight: 600; color: var(--text); }
.metre-direct .metre-valeur { width: 120px; font-size: 16px; font-weight: 700; text-align: right; padding: 6px 8px; }
.metre-direct .metre-valeur[readonly] { background: #eef3ff; border-style: dashed; color: var(--navy); cursor: default; }
.metre-driven-hint { display: none; flex-basis: 100%; font-size: 11px; color: #2d5bff; font-weight: 600; }
.metre-modal.is-driven .metre-driven-hint { display: block; }
/* tableau du métré */
.metre-table { width: 100%; border-collapse: collapse; }
.metre-table th { font-size: 9.5px; text-transform: uppercase; letter-spacing: .03em; color: var(--muted);
                  text-align: left; font-weight: 600; padding: 0 4px 5px; }
.metre-table th.r { text-align: right; }
.metre-table td { padding: 2px 4px; vertical-align: middle; }
.metre-table input { width: 100%; border: 1px solid var(--border); border-radius: 5px; padding: 4px 7px;
                     font: inherit; font-size: 12px; }
.metre-table input.metre-formule { text-align: right; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.metre-table td.metre-st { text-align: right; font-weight: 700; color: var(--navy); white-space: nowrap;
                           min-width: 54px; font-size: 12px; }
.metre-table td.metre-st.err { color: #c0392b; }
.metre-del { color: #c0392b; cursor: pointer; font-weight: 700; padding: 0 4px; user-select: none; }
.metre-del:hover { color: #e05a4a; }
.metre-actions { display: flex; gap: 14px; margin-top: 4px; }
.metre-addrow { font-size: 12px; color: #2d5bff; cursor: pointer; font-weight: 600; }
.metre-clear  { font-size: 12px; color: #c0392b; cursor: pointer; }
.metre-sum { display: flex; justify-content: space-between; align-items: baseline; font-weight: 700;
             color: var(--navy); border-top: 1px solid var(--border); padding-top: 8px; margin-top: 4px; }
.metre-sum .metre-total { font-size: 17px; }
.metre-help { font-size: 11px; margin: 0; }
.metre-help code { font-size: 11px; }

/* ===== Multi-fournisseurs : cellule Px Achat (bouton ⊞ + somme verrouillée) ===== */
/* bouton ⊞ Détail du prix d'achat ; bleu plein quand >=2 fournisseurs. */
.achats-detail-btn { flex: 0 0 auto; font-size: 12px; line-height: 1; cursor: pointer;
                     border: 1px solid #d4d9e6; background: #fff; color: #8a93a6;
                     border-radius: 5px; padding: 2px 5px; margin-left: 3px; }
.achats-detail-btn:hover { border-color: #b9c2d6; color: var(--blue); }
.achats-detail-btn.on { background: var(--blue); color: #fff; border-color: var(--blue); }
/* ===== Bibliothèque de prix : volets Catalogue / Prix observés ============ */
.biblio-onglets {
  display: flex;
  gap: 4px;
  margin: 0 0 18px;
  border-bottom: 1px solid var(--border);
}
.biblio-onglet {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 14px;
  margin-bottom: -1px;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--muted);
  border-bottom: 3px solid transparent;
  text-decoration: none;
}
.biblio-onglet:hover { color: var(--text); text-decoration: none; }
/* `aria-current` plutot qu'une classe : l'attribut conditionnel entier passe
   djlint, un `{% if %}` dans la valeur de `class` non (CONVENTIONS §8). */
.biblio-onglet[aria-current="page"] { color: var(--blue); border-bottom-color: var(--blue); }
.biblio-onglet .ic { width: 16px; height: 16px; }

/* Filtres de la vue Prix observés : les 4 statuts en cases à cocher, rendus
   comme les badges du tableau de bord pour qu'on les reconnaisse. */
.prix-filtres { flex-wrap: wrap; row-gap: 8px; }
.prix-statuts { display: flex; gap: 6px; align-items: center; border: 0; padding: 0; margin: 0; }
.prix-statut { display: inline-flex; align-items: center; gap: 4px; cursor: pointer; }
.prix-statut input { margin: 0; }
.prix-statut input:not(:checked) + .badge { opacity: 0.4; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

.prix-vues { display: flex; gap: 4px; margin: 0 0 12px; }
.prix-vue {
  padding: 5px 12px;
  border: 1px solid var(--border);
  border-radius: 16px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--muted);
  text-decoration: none;
  background: var(--surface);
}
.prix-vue:hover { color: var(--text); text-decoration: none; }
.prix-vue[aria-current="page"] { background: var(--blue); border-color: var(--blue); color: #fff; }
.prix-table td.num, .prix-table th.num { text-align: right; font-variant-numeric: tabular-nums; }
.prix-pagination { display: flex; gap: 16px; align-items: center; justify-content: center; padding: 14px 0; font-size: 13px; }

/* ===== Bibliothèque : file « Rapprochements à confirmer » ================ */
.rappro-intro { max-width: 70ch; margin: 0 0 14px; font-size: 13px; line-height: 1.45; }
.rappro-intro mark, .rappro-ligne mark { background: #fff1b8; color: inherit; padding: 0 2px; border-radius: 3px; }
.rappro-titre { margin: 26px 0 6px; font-size: 15px; font-weight: 700; color: var(--text); }
.rappro-file { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.rappro-ligne {
  display: grid;
  grid-template-columns: minmax(260px, 1.2fr) minmax(300px, 1.6fr) minmax(280px, 1fr);
  gap: 14px;
  align-items: start;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.rappro-designation { font-weight: 600; color: var(--text); line-height: 1.35; }
.rappro-unite { margin-left: 4px; font-size: 11px; font-weight: 600; color: var(--muted); }
.rappro-contexte { margin-top: 3px; font-size: 12px; }
.rappro-erreur { margin: 6px 0 0; font-size: 12.5px; color: var(--danger); }
.rappro-candidats { display: flex; flex-direction: column; gap: 6px; }
.rappro-candidat { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 13px; }
.rappro-score {
  flex: 0 0 auto; min-width: 44px; text-align: center;
  padding: 1px 7px; border-radius: 10px; font-size: 11px; font-weight: 700;
  background: #eceff3; color: #5b6472; font-variant-numeric: tabular-nums;
}
.rappro-score.est-exact { background: #d4edda; color: #155724; }
.rappro-nom { flex: 1 1 auto; min-width: 0; }
.rappro-variante { display: inline-flex; align-items: center; gap: 3px; font-size: 11px; font-weight: 600;
                   color: #a8650f; cursor: help; }
.rappro-variante .ic { width: 13px; height: 13px; }
.rappro-actions { display: flex; flex-direction: column; gap: 6px; align-items: stretch; }
.rappro-actions form { display: flex; gap: 6px; align-items: center; }
.rappro-actions select { flex: 1 1 auto; min-width: 0; font-size: 12px; }
.rappro-ignorer { align-self: flex-end; color: var(--muted); }
.btn-xs { font-size: 11.5px; padding: 3px 9px; }

/* Prix issu de la BASE DE PRIX (pas de devis fournisseur actualisé en face) :
   pastille ambre à côté du prix. Ambre et non rouge : ce n'est pas une
   erreur, c'est un prix a verifier avant de remettre l'offre. */
.px-base { flex: 0 0 auto; display: inline-flex; align-items: center; margin-left: 3px;
           padding: 2px 4px; border-radius: 5px; background: #fff4d6; color: #a8650f;
           border: 1px solid #f3dca3; cursor: help; }
.px-base .ic { width: 13px; height: 13px; }
/* Compteur « Prix de base » du header navy : meme ambre, lisible sur fond sombre. */
.chiffrage-header-totals .val-base { color: #f2d39b; }
/* Modale Détail du prix d'achat : colonne Origine. */
.achats-table .ach-origine { font-size: 12px; padding: 4px 6px; border: 1px solid #d4d9e6;
                             border-radius: 5px; background: #fff; color: var(--text); }

/* Px Achat piloté par le détail (>=2 fournisseurs) : somme verrouillée, fond bleuté. */
.px-driven { display: inline-flex; align-items: center; justify-content: flex-end; min-width: 56px;
             font-weight: 700; color: var(--navy); border: 1px dashed #b9c6ef; background: #eef3ff;
             border-radius: 5px; padding: 3px 6px; }
/* noms de fournisseurs (lecture seule) quand multi-fournisseurs. */
/* Multi-fournisseurs : tags en scroll horizontal (option « scroll »).
   cf. chiffrage/_poste_row.html (.ftags-wrap) + fournisseurs-scroll.js. */
.ftags-wrap { position: relative; flex: 1 1 auto; min-width: 0; display: flex; align-items: center; }
.ftags { display: flex; gap: 5px; overflow-x: auto; scrollbar-width: none; padding: 1px 0; width: 100%; }
.ftags::-webkit-scrollbar { display: none; }
.fchip { flex: 0 0 auto; display: inline-flex; align-items: center; font-size: 11px; font-weight: 600;
         border-radius: 10px; padding: 2px 9px; background: #eef1f8; color: #3a4566;
         border: 1px solid #dfe4f0; white-space: nowrap; }
.fchip .fmeta { display: flex; flex-direction: column; align-items: flex-start; line-height: 1.15; }
.fchip .frole { font-size: 8.5px; font-weight: 700; color: #7a5cff; text-transform: uppercase;
                letter-spacing: .02em; margin-top: 1px; }
/* flèches ‹ › : cachées par défaut, montrées par JS (.show) quand ça déborde. */
.fnav { position: absolute; top: 0; bottom: 0; width: 22px; display: flex; align-items: center;
        justify-content: center; border: none; cursor: pointer; opacity: 0; pointer-events: none;
        transition: opacity .15s; z-index: 3; font-size: 15px; color: #5a6b8c; padding: 0; }
.fnav.show { opacity: 1; pointer-events: auto; }
.fnav:hover { color: var(--blue); }
.fnav-l { left: 0; background: linear-gradient(90deg, #fff8f2 62%, rgba(255, 248, 242, 0)); }
.fnav-r { right: 0; background: linear-gradient(270deg, #fff8f2 62%, rgba(255, 248, 242, 0)); }

/* ===== Modale « Détail du prix d'achat » (multi-fournisseurs) ===== */
.achats-modal { width: 660px; max-width: 95vw; }
.achats-table input.ach-refdevis { font-size: 11.5px; }
/* La modale Détail du prix d'achat héberge des autocompletes annuaire dont le
   menu (position:absolute) serait clippé par le scroll du body / l'overflow du
   modal. On laisse déborder : la liste de fournisseurs est courte par nature,
   donc pas besoin de scroll interne ici. Sans ça, le dropdown (suggestions ou
   message « Annuaire indisponible… ») reste invisible. */
.achats-modal { overflow: visible; }
.achats-modal .modal-body { overflow: visible; }
.achats-modal-titles h2 { margin: 0; }
.achats-modal-sub { margin: 2px 0 0; font-size: 12px; color: var(--muted); }
.achats-form { display: flex; flex-direction: column; min-height: 0; flex: 1 1 auto; }
.achats-table { width: 100%; border-collapse: collapse; }
.achats-table th { font-size: 9.5px; text-transform: uppercase; letter-spacing: .03em; color: var(--muted);
                   text-align: left; font-weight: 600; padding: 0 5px 5px; }
.achats-table th.r { text-align: right; }
.achats-table td { padding: 3px 5px; vertical-align: middle; }
.achats-table input { width: 100%; border: 1px solid var(--border); border-radius: 6px; padding: 5px 7px;
                      font: inherit; font-size: 12px; }
.achats-table input.ach-prix { text-align: right; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.achats-table td.ach-st { text-align: right; font-weight: 700; color: var(--navy); white-space: nowrap;
                          min-width: 68px; font-size: 12px; }
.achats-table td.ach-st.err { color: #c0392b; }
.ach-del { color: #c0392b; cursor: pointer; font-weight: 700; padding: 0 4px; user-select: none; }
.ach-del:hover { color: #e05a4a; }
.achats-actions { margin-top: 4px; }
.achats-addrow { font-size: 12px; color: var(--blue); cursor: pointer; font-weight: 600; }
.achats-sum { display: flex; justify-content: space-between; align-items: baseline; font-weight: 700;
              color: var(--navy); border-top: 1px solid var(--border); padding-top: 9px; margin-top: 6px; }
.achats-sum .achats-total { font-size: 16px; }
.achats-help { font-size: 11px; margin: 6px 0 0; }
.achats-help code { font-size: 11px; }
/* Modale Achats en mode ré-imputation (chiffrage figé) : bandeau d'info. */
.achats-verrou-hint { background: #fdf3e7; border: 1px solid #f0c896; color: #8a5a12; border-radius: 8px; padding: 8px 12px; font-size: 12.5px; margin: 0 0 12px; }

/* Modale « Passer en facturation » (honoraires déjà facturés avant travaux). */
.fact-warn { background: #fdf3e7; border: 1px solid #f0c896; color: #8a5a12; border-radius: 8px; padding: 9px 12px; font-size: 13px; margin: 0 0 14px; }
.fact-h3 { font-size: 13.5px; font-weight: 700; margin: 6px 0 4px; }
.fact-help { font-size: 12px; margin: 0 0 10px; }
.fact-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.fact-table th { text-align: left; font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; color: #94a0b8; padding: 6px 8px; border-bottom: 1px solid #e6e9f0; }
.fact-table th.r, .fact-table td.r { text-align: right; }
.fact-table td { padding: 6px 8px; border-bottom: 1px solid #f2f4f9; }
.fact-in { width: 84px; text-align: right; padding: 5px 8px; border: 1px solid #d8dce6; border-radius: 7px; font: inherit; }
.fact-unit { padding: 5px 6px; border: 1px solid #d8dce6; border-radius: 7px; font: inherit; margin-left: 5px; }
/* cellule Fournisseur de la modale : ancre le dropdown autocomplete annuaire. */
.ach-fournisseur-cell { position: relative; }
/* Modale empilee (#modal-container-2 : ex. « + Ajouter a l'annuaire » depuis la
   modale Detail) -> au-dessus de la modale d'origine. */
#modal-container-2 .modal-overlay { z-index: 1100; }

/* Radio group pour le role (super admin / charge) :
   options affichees comme des cards cliquables, plus grosses et visibles. */
/* Grille 2x2 et non un flex sur une ligne : il y a QUATRE roles, et en flex
   les options ne descendent pas sous leur largeur min-content (min-width:auto
   par defaut). Elles debordaient donc la modale de 135px -- barre de scroll
   horizontale et 4e role coupe hors de l'ecran. Une grille a colonnes 1fr
   impose la largeur au lieu de la subir. */
.radio-group {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  margin-top: 6px;
}
/* Sous 720px `.form-field` repasse en empile : une seule colonne de roles. */
@media (max-width: 720px) {
  .radio-group { grid-template-columns: minmax(0, 1fr); }
}
.radio-option {
  min-width: 0;          /* le libelle retourne a la ligne au lieu d'elargir la piste */
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  padding: 12px 14px;
  border: 1.5px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  transition: border-color 0.15s, background 0.15s, box-shadow 0.15s;
}
.radio-option:hover {
  border-color: var(--blue);
  background: #f6f9ff;
}
.radio-option input[type="radio"] {
  /* Radio plus gros et plus visible */
  width: 18px;
  height: 18px;
  margin: 0;
  accent-color: var(--blue);
  cursor: pointer;
  flex-shrink: 0;
}
/* Card "selectionnee" : bordure bleue + halo discret */
.radio-option:has(input[type="radio"]:checked) {
  border-color: var(--blue);
  background: #f0f5ff;
  box-shadow: 0 0 0 3px rgba(59, 110, 245, 0.12);
}

.field-help {
  display: block;
  margin-top: 4px;
  font-size: 11.5px;
  color: var(--muted);
}

/* =============================================================================
   Page Analytique projet (resume financier + ratios + camemberts)
   ============================================================================= */
.analytique-main {
  padding: 24px 32px 40px;
  max-width: 1400px;
  margin: 0 auto;
}

.analytique-section {
  margin-bottom: 32px;
  background: var(--surface);
  border-radius: 10px;
  padding: 20px 24px;
  box-shadow: 0 1px 4px rgba(26, 35, 64, 0.05);
}

/* Meme graisse que les autres titres de tuiles (Note, Exports, Synthese
   financiere) : 700, pas 600. La classe sert aussi a l'onglet Analytique,
   qui suit donc la meme regle. Seule la couleur reste propre au bloc. */
.analytique-section-title {
  font-size: 16px;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 16px;
  letter-spacing: -0.01em;
}

/* --- Section 1 : Resume financier (3 sous-blocs Generalites/Hono/Travaux) --- */
.analytique-resume-block {
  margin-bottom: 18px;
}
.analytique-resume-block:last-child {
  margin-bottom: 0;
}
.analytique-resume-subtitle {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  margin-bottom: 8px;
  padding-bottom: 6px;
  border-bottom: 1px solid #eef0f4;
}
.analytique-resume-subtitle-honoraires {
  color: #a05a14;
  border-bottom-color: #f0e1b6;
}
.analytique-resume-subtitle-travaux {
  color: #1565c0;
  border-bottom-color: #cfdaf7;
}
.analytique-resume-subtitle-options {
  /* Orange : echo de la couleur "Options du lot" dans le chiffrage. */
  color: #c67100;
  border-bottom-color: #f5d9b2;
}
.analytique-resume-subtitle-rg {
  /* Bronze : assorti a la pastille RG par lot dans la sidebar chiffrage. */
  color: #8b6914;
  border-bottom-color: #c9a875;
}
.analytique-resume-subtitle-variantes {
  color: #6a1b9a;
  border-bottom-color: #e1bee7;
}
.analytique-resume-subtitle-note {
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
  font-size: 11px;
  color: var(--muted);
  margin-left: 8px;
}

.analytique-resume {
  display: grid;
  gap: 10px;
}
/* auto-fit + minmax : le nombre de colonnes s'adapte a la place disponible,
   au lieu d'un nombre fige qui deborde entre deux points de rupture (la rangee
   a 6 colonnes debordait deja son conteneur autour de 1100-1300px, et les
   montants a 7 chiffres — desormais insecables — l'accentuaient). */
/* Dernier bloc de la colonne financiere (Resume & Exports) : sa marge basse
   (32px) creait un espace MORT en bas de colonne, qui s'ajoutait au row-gap de
   la grille (28px) -> 60px avant l'« Historique des versions ». */
.resume-financier-col > .analytique-section:last-child {
  margin-bottom: 0;
}

/* Plancher 176px : un montant a 7 chiffres (« 12 345 678,90 € » = 142px de
   texte) + 28px de padding + 2px de bordure = 172px. En dessous, le montant
   — desormais insecable — depassait le bord droit de la tuile. */
.analytique-resume-6 { grid-template-columns: repeat(auto-fit, minmax(176px, 1fr)); }
.analytique-resume-4 { grid-template-columns: repeat(auto-fit, minmax(176px, 1fr)); }
.analytique-resume-2 { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.ar-card {
  background: #f8f9fb;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
}
.ar-card .label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  margin-bottom: 6px;
}
.ar-card .value {
  font-size: 18px;
  font-weight: 700;
  color: var(--text);
}
.ar-card-vente {
  background: #eef3ff;
  border-color: #cfdaf7;
}
.ar-card-vente .value { color: var(--blue); }
.ar-card-marge {
  background: #f4fbf6;
  border-color: #d6ecde;
}
.ar-card-marge .value { color: #1f8a4c; }
.ar-card .sub {
  font-size: 11px;
  color: var(--muted);
  margin-top: 4px;
  font-style: italic;
}

/* --- Sections 2 & 3 : Tableau a gauche, camembert a droite --- */
.analytique-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 380px;
  gap: 24px;
  align-items: start;
}
@media (max-width: 1100px) {
  .analytique-grid { grid-template-columns: 1fr; }
}

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

.analytique-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
.analytique-table th,
.analytique-table td {
  padding: 9px 12px;
  border-bottom: 1px solid #eef0f4;
  text-align: left;
}
.analytique-table thead th {
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  background: #fafbfc;
  border-bottom: 1px solid var(--border);
}
.analytique-table tfoot th {
  background: #f4f6fa;
  font-weight: 700;
  color: var(--text);
  border-top: 2px solid var(--border);
}
.analytique-table .num {
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.analytique-table tbody tr:hover td {
  background: #fafbfc;
}
.analytique-table .lot-num {
  display: inline-block;
  min-width: 24px;
  padding-right: 6px;
  color: var(--muted);
  font-weight: 600;
  font-size: 11.5px;
}

/* Matrice lot x zone : un peu plus compact pour gerer la largeur. */
.analytique-matrice th,
.analytique-matrice td {
  padding: 7px 10px;
  font-size: 12.5px;
}

.analytique-chart-wrap {
  background: #fafbfc;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 16px;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.analytique-chart-title {
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 12px;
  align-self: flex-start;
}
/* Boite qui BORNE la taille du donut.
   Chart.js est en `responsive: true` : il dimensionne le canvas sur son parent.
   Tant que ce parent etait la carte entiere, le donut suivait la largeur de la
   carte — et quand la grille passe en une colonne (<= 1100 px), il s'etalait
   sur toute la page. On lui donne donc un parent plafonne a sa taille de
   reference (l'attribut width=320 du canvas) : le diagramme reste petit, la
   legende en dessous garde la pleine largeur de la carte. */
.analytique-chart-canvas {
  width: 100%;
  max-width: 320px;
  margin: 0 auto;
}
.analytique-chart-wrap canvas {
  max-width: 100%;
}

.analytique-empty {
  padding: 24px;
  text-align: center;
  color: var(--muted);
  font-size: 13px;
  background: #fafbfc;
  border-radius: 6px;
}

/* =============================================================================
   Sidebar chiffrage : tabs Lots | Honoraires
   ============================================================================= */
.sidebar-tabs {
  display: flex;
  background: #f8f9fb;
  border-bottom: 1px solid #eee;
}
.sidebar-tab {
  flex: 1;
  text-align: center;
  padding: 10px 12px;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.sidebar-tab:hover {
  color: var(--text);
  background: #f0f2f6;
  text-decoration: none;
}
.sidebar-tab.active {
  color: var(--blue);
  border-bottom-color: var(--blue);
  background: var(--surface);
}

/* Pied de sidebar honoraires : total HT */
.honoraires-sidebar-footer {
  padding: 12px 14px;
  background: #f4f6fa;
  border-top: 1px solid var(--border);
  font-size: 12px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.honoraires-sidebar-footer .t-item {
  color: var(--muted);
  text-transform: uppercase;
  font-weight: 600;
  letter-spacing: 0.04em;
}
.honoraires-sidebar-footer .t-val {
  font-weight: 700;
  color: var(--text);
  font-size: 13px;
}

/* Cellule en lecture seule (typiquement un PU achat agrege au niveau
   intervenant -- l'edition se fait sur les lignes phase en dessous). */
.cell-readonly {
  display: inline-block;
  color: var(--muted);
  font-style: italic;
  font-size: 13px;
  padding: 0 4px;
}

/* Dropdown "+ Ajouter une phase" inline en haut du tableau honoraires */
.phase-add-inline {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: 8px;
}
.phase-add-inline select {
  height: 32px;
  padding: 0 10px;
  font-size: 12.5px;
  border: 1px dashed var(--border);
  border-radius: 5px;
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
}
.phase-add-inline button {
  height: 32px;
  width: 32px;
  border: 1px solid var(--border);
  border-radius: 5px;
  background: var(--surface);
  color: var(--blue);
  font-weight: 700;
  cursor: pointer;
}
.phase-add-inline button:hover {
  background: #eef3ff;
}

/* =============================================================================
   Page Resume & Exports (onglet entre Chiffrage et Analytique)
   ============================================================================= */

.resume-main {
  padding: 24px 32px;
  max-width: 1400px;
  margin: 0 auto;
}

/* Layout : 3 blocs editables a gauche, synthese sticky a droite */
.resume-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 360px;
  gap: 28px;
  align-items: start;
}
@media (max-width: 1100px) {
  .resume-layout {
    grid-template-columns: 1fr;
  }
}

.resume-form {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.resume-block {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 20px 22px;
  box-shadow: 0 1px 3px rgba(26, 35, 64, 0.04);
}
.resume-block-title {
  font-size: 14px;
  font-weight: 700;
  color: var(--navy);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: 0 0 14px;
  padding-bottom: 10px;
  border-bottom: 1px solid #eef0f4;
}
.resume-block-note {
  display: block;
  text-transform: none;
  letter-spacing: normal;
  font-weight: 400;
  font-size: 12px;
  color: var(--muted);
  margin-top: 4px;
}

/* Toggle 3 modes : radios stylises en pills */
.resume-mode-toggle {
  display: flex;
  gap: 6px;
  margin-bottom: 14px;
  background: #f4f6f9;
  padding: 4px;
  border-radius: 8px;
  width: max-content;
}
.resume-mode-toggle label {
  display: flex;
  align-items: center;
  padding: 6px 14px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
  border-radius: 6px;
  transition: background 0.15s, color 0.15s;
}
.resume-mode-toggle label:hover { color: var(--text); }
/* L'état ACTIF est piloté par :has(:checked) ci-dessous (fiable, suit le radio
   coché côté client). Les formulaires RG / aléas re-rendent en hx-swap="none"
   -> la classe serveur .active devient obsolète après un clic (les DEUX
   libellés restaient surlignés). On force donc l'état INACTIF des libellés dont
   le radio n'est pas coché, ce qui neutralise un .active resté figé. */
.resume-mode-toggle label:not(:has(input[type="radio"]:checked)) {
  background: transparent;
  color: var(--muted);
  box-shadow: none;
}
/* Feedback optimiste : on cible aussi `:has(:checked)` directement —
   le highlight apparait des le clic, sans attendre le round-trip serveur
   qui re-render le partial avec .active applique cote Django.
   Cf. rapport Cowork Campagne 2 bug n°19 (sensation que le clic ne fait rien). */
.resume-mode-toggle label:has(input[type="radio"]:checked) {
  background: var(--surface);
  color: var(--navy);
  box-shadow: 0 1px 3px rgba(26, 35, 64, 0.06);
}
.resume-mode-toggle input[type="radio"] {
  display: none;
}

/* Sous-bloc : reste visible mais grise quand le mode courant ne le selectionne pas */
.resume-subblock {
  transition: opacity 0.15s;
}
.resume-subblock.is-disabled {
  opacity: 0.45;
  pointer-events: none;
}
/* Stage 2 OOB : le serveur ne re-rend plus la classe .is-disabled quand on
   change de mode (il ne renvoie que les montants par lot). On grise donc
   chaque sous-bloc gate PAR DEFAUT en CSS (selon data-mode) ; les regles
   :has() ci-dessous le degrisent instantanement quand le bon mode/toggle est
   coche. Sans ca, un sous-bloc reste fige dans l'etat (grise/actif) du
   chargement de page -> le toggle "ne verrouille plus" la table par lot. */
.resume-subblock[data-mode="global"],
.resume-subblock[data-mode="par_lot"],
.resume-subblock[data-mode="non-aucun"],
.resume-subblock[data-mode="non-aucune"],
.resume-subblock[data-mode="rg"] {
  opacity: 0.45;
  pointer-events: none;
}
/* Sous-blocs : annule .is-disabled des le clic sur le radio correspondant,
   sans attendre le re-render serveur. Les <input> n'ont plus de HTML
   `disabled` (cf. resume_content.html) donc le user peut taper
   instantanement et la valeur est bien dans le POST suivant.
   Cf. rapport Cowork Campagne 3 bug n°31 (valeur saisie retombait a 0). */
.resume-block:has(input[name="aleas_mode"][value="global"]:checked)
  .resume-subblock[data-mode="global"],
.resume-block:has(input[name="aleas_mode"][value="par_lot"]:checked)
  .resume-subblock[data-mode="par_lot"],
.resume-block:has(input[name="aleas_moa_type"]:not([value="aucun"]):checked)
  .resume-subblock[data-mode="non-aucun"],
.resume-block:has(input[name="remise_type"]:not([value="aucune"]):checked)
  .resume-subblock[data-mode="non-aucune"] {
  opacity: 1;
  pointer-events: auto;
}

/* ===== Onglet Retenue & Remise (refonte 2026-06-03) ===== */
/* La Retenue de garantie a quitté cet onglet (-> Situations, bloc 4.1) : le
   conteneur remplit désormais toute la largeur, la mise en 2 colonnes se joue
   à l'intérieur du form (cf. .retenue-remise-ajustements). */
.retenue-remise-layout {
  display: block;
}
/* Form ajustements en 2 colonnes : à GAUCHE « Aléas entreprise » (avec sa
   table par lot, colonne plus large), à DROITE « Aléas MOA » + « Remise »
   empilés (cf. demande 2026-07-21). Sous 1100px -> 1 colonne. */
.retenue-remise-ajustements {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: 20px;
  align-items: start;
}
.ar-col-side {
  display: flex;
  flex-direction: column;
  gap: 20px;
}
@media (max-width: 1100px) {
  .retenue-remise-ajustements {
    grid-template-columns: 1fr;
  }
}
/* Sous-bloc RG : se de-grise des que "RG applicable" est coche (meme pattern
   :has() que les aleas, sans disabled HTML -> saisie instantanee). */
.retenue-rg-block:has(input[name="retenue_garantie_applicable"][value="1"]:checked)
  .resume-subblock[data-mode="rg"] {
  opacity: 1;
  pointer-events: auto;
}

/* ----- Bascule pourcent / forfait des champs "Valeur" (cote client) -----
   Stage 2 OOB : les vues ne renvoient plus que les montants calcules, elles
   ne re-rendent plus les <input>. On rend donc les DEUX variantes (% et €) et
   on n'affiche que celle du type coche, en CSS pur (meme philosophie :has()
   que le gating ci-dessus). Bonus : bascule instantanee, sans round-trip. */
.resume-val-forfait { display: none; }   /* defaut : variante pourcent visible */
.resume-block:has(input[name="aleas_moa_type"][value="forfait"]:checked) .resume-val-pourcent,
.resume-block:has(input[name="remise_type"][value="forfait"]:checked) .resume-val-pourcent {
  display: none;
}
.resume-block:has(input[name="aleas_moa_type"][value="forfait"]:checked) .resume-val-forfait,
.resume-block:has(input[name="remise_type"][value="forfait"]:checked) .resume-val-forfait {
  display: flex;
}
/* Aleas par lot : la valeur (%/€) d'une ligne bascule selon SON <select>.
   Scope a .resume-lots-table ; la table RG (meme classe) n'a pas de select. */
.resume-aleas-frf { display: none; }
.resume-lots-table tr:has(select option[value="forfait"]:checked) .resume-aleas-pct {
  display: none;
}
.resume-lots-table tr:has(select option[value="forfait"]:checked) .resume-aleas-frf {
  display: inline-block;
}
.rg-derogation-note {
  margin: 12px 0 8px;
}
.rg-lot-toggle {
  display: inline-flex;
  align-items: center;
  cursor: pointer;
}
.rg-lot-toggle input[type="checkbox"] {
  width: 16px;
  height: 16px;
  cursor: pointer;
  accent-color: var(--blue, #2563eb);
}

.resume-field-row {
  margin-bottom: 10px;
}
.resume-field-row:last-child { margin-bottom: 0; }

.resume-field-inline {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: var(--text);
}
.resume-field-inline > span:first-child {
  min-width: 110px;
  font-weight: 500;
}
.resume-field-inline .suffix {
  color: var(--muted);
  font-weight: 600;
}
.resume-num {
  width: 100px;
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 4px 8px;
  text-align: right;
}
.resume-num:disabled {
  background: #f4f6f9;
  color: #999;
  cursor: not-allowed;
}

/* Tableau aleas par lot */
.resume-lots-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  margin-top: 10px;
}
.resume-lots-table th {
  text-align: left;
  padding: 8px 10px;
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-bottom: 1px solid var(--border);
  background: #fafbfc;
}
.resume-lots-table th.num { text-align: right; }
.resume-lots-table td {
  padding: 8px 10px;
  border-bottom: 1px solid #eef0f4;
  vertical-align: middle;
}
.resume-lots-table td.num { text-align: right; }
.resume-lots-table tr:last-child td { border-bottom: none; }
.resume-num-cell {
  width: 80px;
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 3px 6px;
  text-align: right;
}
.resume-num-cell:disabled,
.resume-lots-table select:disabled {
  background: #f4f6f9;
  color: #999;
  cursor: not-allowed;
}
.resume-lots-table select {
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 3px 6px;
  font-size: 12.5px;
}
.resume-lot-montant {
  font-weight: 600;
  color: var(--navy);
}

/* Aside : synthese sticky a droite */
.resume-synthese {
  background: var(--navy);
  color: #fff;
  border-radius: 10px;
  padding: 22px 24px;
  position: sticky;
  top: 16px;
  box-shadow: 0 2px 8px rgba(26, 35, 64, 0.1);
}
/* Meme typographie que les autres titres de tuiles (Note, Exports) : seule
   la couleur reste propre a la carte sombre. */
.resume-synthese-title {
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: #8899aa;
  margin: 0 0 14px;
  padding-bottom: 10px;
  border-bottom: 1px solid #3d4a6e;
}
.resume-line {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 6px 0;
  font-size: 13px;
}
.resume-line .val {
  font-weight: 700;
  font-size: 14px;
}
.resume-line.is-subtotal {
  border-top: 1px solid #3d4a6e;
  padding-top: 8px;
  margin-top: 4px;
  font-weight: 600;
  color: #cfd6e6;
}
.resume-line.is-final {
  border-top: 2px solid #5dade2;
  margin-top: 8px;
  padding-top: 12px;
  font-size: 14px;
  font-weight: 700;
}
.resume-line.is-final .val {
  color: #5dade2;
  font-size: 18px;
}
.resume-line-aleas .val { color: #ffb878; }
.resume-line-remise .val { color: #ff9090; }
.resume-line-moa {
  font-size: 11.5px;
  color: #99a3b8;
  border-top: 1px dashed #3d4a6e;
  margin-top: 10px;
  padding-top: 10px;
  font-style: italic;
}

/* Boutons exports */
.resume-exports {
  margin-top: 22px;
  padding-top: 16px;
  border-top: 1px solid #3d4a6e;
}
.resume-exports h3 {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #8899aa;
  margin: 0 0 10px;
}

/* ===== Section Exports (pleine largeur, EN TETE du layout) =================
   Sortie de l'aside synthese (312px, trop etroit pour 2 colonnes lisibles) et
   placee au-dessus de la Synthese financiere. Deux groupes cote a cote :
   INTERNE (ambre) / CLIENT (bleu). Sous 900px -> une seule colonne. */
/* Bandeau de tete : note a gauche (70%), exports a droite (30%).
   `7fr / 3fr` plutot que des pourcentages : le `gap` est alors pris sur la
   piste, pas en plus, donc pas de debordement horizontal. */
/* Rangee « Resume financier | Synthese financiere » : `stretch` aligne les
   deux cartes en hauteur. Sans cette rangee dediee, la synthese vivait dans
   la meme cellule que TOUTE la colonne financiere et ne pouvait s'aligner
   sur sa premiere carte. */
.resume-financier-tete {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 360px;
  gap: 28px;
  align-items: stretch;
}
/* La marge basse de la carte (32px) decalait le bas des deux cartes d'autant :
   c'est le `row-gap` de la grille qui espace, pas elle. */
.resume-financier-tete > .analytique-section { margin-bottom: 0; }
@media (max-width: 1100px) {
  .resume-financier-tete { grid-template-columns: 1fr; }
}

.resume-tete {
  grid-column: 1 / -1;
  display: grid;
  /* Memes pistes que `.resume-layout` (360px, gap 28) : la carte Exports se
     cale alors exactement sur la carte Synthese financiere posee juste en
     dessous, bords droits et gauches alignes a la verticale. */
  grid-template-columns: minmax(0, 1fr) 360px;
  gap: 28px;
  /* `stretch` (et non `start`) : les deux cartes prennent la hauteur de la
     rangee, donc leurs bas s'alignent. C'est la carte Exports qui mene — le
     `min-height` de l'editeur est volontairement bas (cf. plus loin). */
  align-items: stretch;
}
@media (max-width: 1100px) {
  .resume-tete { grid-template-columns: 1fr; }
}

.resume-exports-section {
  background: var(--surface, #fff);
  border: 1px solid var(--border, #dde1ea);
  border-radius: 12px;
  padding: 20px 22px 22px;
  /* Pas de margin-bottom : la grille .resume-layout a deja un row-gap (28px).
     Ajouter une marge doublait l'espace sous la section (48px). */
  box-shadow: 0 1px 3px rgba(26, 35, 64, 0.04);
}
/* ----- Note de page de garde (sous l'encart Exports) --------------------
   Même traitement que la section Exports : pleine largeur de la grille, même
   carte. Pas de margin-bottom, la grille porte déjà son row-gap. */
.resume-note-section {
  display: flex;
  flex-direction: column;
  background: var(--surface, #fff);
  border: 1px solid var(--border, #dde1ea);
  border-radius: 12px;
  padding: 20px 22px 22px;
  box-shadow: 0 1px 3px rgba(26, 35, 64, 0.04);
}
.resume-note-section-title {
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--navy);
  margin-bottom: 4px;
}
.resume-note-hint {
  font-size: 12.5px;
  color: var(--muted);
  margin-bottom: 14px;
}
/* Le textarea reste utilisable tel quel si TinyMCE n'est pas chargé. */
.resume-note-section textarea {
  width: 100%;
  flex: 1 1 auto;
  min-height: 220px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: inherit;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--text);
  resize: vertical;
}
.resume-note-etat {
  margin-top: 8px;
  min-height: 16px;
  font-size: 12px;
  color: var(--muted);
}
/* L'editeur occupe tout l'espace restant de la carte. `min-height` reste
   sous la hauteur naturelle de la carte Exports, sinon c'est la Note qui
   imposerait la hauteur et les Exports s'etireraient a vide. */
#note-chiffrage-form {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}
.resume-note-section .tox-tinymce {
  flex: 1 1 auto;
  min-height: 280px;
  border: 1px solid var(--border);
  border-radius: 8px;
  transition: border-color 0.12s, box-shadow 0.12s;
}
/* Meme halo de focus que les champs de la carte « Page de garde » : le
   liseré bleu franc d'origine de TinyMCE jurait a cote (signale
   2026-09-21). On s'accroche a `.tox-edit-focus`, la classe que TinyMCE
   pose lui-meme : `:focus-within` ne marche pas ici, le curseur vit dans
   une IFRAME et le focus ne remonte pas au document parent. */
.resume-note-section .tox-tinymce.tox-edit-focus {
  border-color: #3b6ef5;
  box-shadow: 0 0 0 3px rgba(59, 110, 245, 0.12);
}
/* La zone d'edition ne porte plus son propre liseré : il doublerait celui
   du conteneur. */
.resume-note-section .tox .tox-edit-area::before { display: none; }
@media (max-width: 1100px) {
  /* Cartes empilees : plus de voisine a suivre, on retrouve une hauteur
     confortable de saisie. */
  .resume-note-section .tox-tinymce { min-height: 380px; }
}
.resume-note-etat.est-erreur { color: var(--danger); }

/* ----- Carte « Page de garde » -----------------------------------------
   Pleine largeur sous le bandeau : la synthese fait trois paragraphes, elle
   etouffe dans une colonne. */
.resume-garde-section {
  grid-column: 1 / -1;
  background: var(--surface, #fff);
  border: 1px solid var(--border, #dde1ea);
  border-radius: 12px;
  padding: 20px 22px 22px;
  box-shadow: 0 1px 3px rgba(26, 35, 64, 0.04);
}
.resume-garde-title {
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--navy);
  margin-bottom: 4px;
}
.resume-garde-hint {
  font-size: 12.5px;
  color: var(--muted);
  margin-bottom: 16px;
}
.resume-garde-champ + .resume-garde-champ { margin-top: 16px; }
.resume-garde-label {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  margin-bottom: 6px;
}
/* Le badge dit d'ou vient le texte affiche : calcule, ou repris a la main.
   Son libelle est pose par le JS, qui le met a jour a chaque frappe. */
.resume-garde-badge {
  font-size: 10.5px;
  font-weight: 600;
  text-transform: none;
  letter-spacing: 0;
  padding: 2px 8px;
  border-radius: 999px;
  background: #eef2fb;
  color: #3b6ef5;
}
.resume-garde-badge[data-personnalise="1"] {
  background: #fbf1de;
  color: #b5811f;
}
.resume-garde-section input[type="text"],
.resume-garde-section textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: inherit;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--text);
}
.resume-garde-section textarea { resize: vertical; min-height: 170px; }
.resume-garde-section input[type="text"]:focus,
.resume-garde-section textarea:focus {
  outline: none;
  border-color: #3b6ef5;
  box-shadow: 0 0 0 3px rgba(59, 110, 245, 0.12);
}
.resume-garde-etat {
  margin-top: 8px;
  min-height: 16px;
  font-size: 12px;
  color: var(--muted);
}
.resume-garde-etat.est-erreur { color: var(--danger); }

/* ----- Frise des actions de la carte Synthese --------------------------
   Les deux actions s'enchainent : on valide le chiffrage, PUIS on passe en
   facturation. La fleche dit cet ordre, que deux boutons empiles laissaient
   deviner. */
.resume-actions-frise {
  display: flex;
  align-items: stretch;
  gap: 8px;
}
.resume-actions-frise .resume-action-btn {
  flex: 1 1 0;
  min-width: 0;
  margin: 0;
  font-size: 12px;
  padding-left: 8px;
  padding-right: 8px;
  text-align: center;
}
.resume-actions-fleche {
  display: flex;
  align-items: center;
  flex: none;
  color: #8899aa;
}
.resume-actions-fleche .ic { width: 18px; height: 18px; }

/* Montants hors total, sous le trait du total client final. */
.resume-line-hors-total {
  font-size: 12px;
  color: #b8c2d4;
}
.resume-line-hors-total .val { color: #d7dfec; }

/* ----- Barre d'outils TinyMCE ------------------------------------------
   Les pictos d'origine sont des traces PLEINS (le jeu « oxide » n'a aucun
   `stroke`) : on ne peut donc pas les affiner par l'epaisseur du trait. On
   joue sur ce qui reste, le poids visuel — un gris franc au repos, la
   couleur du texte au survol et sur un outil actif — plus une taille de
   picto un rien reduite. */
.resume-note-section .tox .tox-tbtn {
  color: #7b879e;
}
.resume-note-section .tox .tox-tbtn svg {
  fill: currentColor;
  transform: scale(0.92);
}
.resume-note-section .tox .tox-tbtn:hover,
.resume-note-section .tox .tox-tbtn:focus {
  color: var(--navy, #1a2340);
}
.resume-note-section .tox .tox-tbtn--enabled,
.resume-note-section .tox .tox-tbtn--enabled:hover {
  color: var(--navy, #1a2340);
}
/* Les libelles des listes deroulantes (Paragraphe, police, taille) suivent le
   meme gris, sinon ils ecrasent les pictos voisins. */
.resume-note-section .tox .tox-tbtn--select .tox-tbtn__select-label {
  color: #7b879e;
  font-weight: 400;
}
.resume-note-section .tox .tox-tbtn--select:hover .tox-tbtn__select-label {
  color: var(--navy, #1a2340);
}
/* Oxide fige les listes deroulantes a 130px chacune, soit 425px pour les
   trois : la 1re rangee debordait et se repliait sur une 3e ligne. On les
   laisse prendre la largeur de leur libelle — deux rangees pleines, et une
   barre moins massive. */
.resume-note-section .tox .tox-tbtn--select {
  width: auto;
  min-width: 0;
  padding: 0 4px;
}
.resume-note-section .tox .tox-tbtn--select .tox-tbtn__select-label {
  width: auto;
  margin: 0 2px;
}

.resume-exports-section-title {
  font-size: 16px;
  font-weight: 700;
  color: var(--navy, #1a2340);
  margin: 0 0 16px;
  letter-spacing: -0.01em;
}
/* Une seule colonne : l'encart ne fait plus que 30% de la largeur, les deux
   groupes INTERNE / CLIENT se lisent l'un sous l'autre. */
.resume-exports-cols {
  display: grid;
  grid-template-columns: 1fr;
  gap: 18px;
  align-items: start;
}
.resume-exports-group-title {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted, #5b6580);
  margin: 0 0 12px;
}
/* Pastille de couleur : repere immediat interne (ambre) / client (bleu). */
.resume-exports-group-dot {
  width: 9px;
  height: 9px;
  border-radius: 3px;
  flex: none;
}
.resume-exports-group--interne .resume-exports-group-dot { background: #d79a2c; }
.resume-exports-group--client .resume-exports-group-dot { background: #3b6ef5; }
.resume-exports-group-note {
  flex-basis: 100%;
  font-size: 11.5px;
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
  color: var(--muted, #94a0b8);
}
.resume-exports-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 10px;
}
/* Carte d'export : plus imposante que l'ancien bouton (icone en pastille +
   nom + format), et cliquable sur toute sa surface. */
.resume-export-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border: 1px solid var(--border, #dde1ea);
  border-radius: 10px;
  background: #fff;
  text-decoration: none;
  color: var(--text, #1a2340);
  transition: border-color 0.14s, box-shadow 0.14s, transform 0.14s;
}
.resume-export-card:hover {
  text-decoration: none;
  border-color: #b9c8ea;
  box-shadow: 0 2px 4px rgba(26, 35, 64, 0.06), 0 8px 20px rgba(26, 35, 64, 0.08);
  transform: translateY(-1px);
}
.resume-export-card-ic {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  flex: none;
  border-radius: 9px;
  background: #eef2fb;
  color: #3b6ef5;
  font-size: 18px;
}
.resume-exports-group--interne .resume-export-card-ic {
  background: #fbf1de;
  color: #b5811f;
}

/* Tuile d'export bloquee : elle reste CLIQUABLE, mais mene a la saisie
   manquante au lieu du telechargement. Un bouton grise n'indiquerait pas
   quoi faire pour le debloquer. */
.resume-export-card--bloque {
  border-color: #f0c9c4;
  background: #fdf7f6;
}
.resume-export-card--bloque:hover {
  border-color: #d97b6c;
  box-shadow: 0 2px 4px rgba(179, 38, 30, 0.08), 0 8px 20px rgba(179, 38, 30, 0.1);
}
.resume-export-card--bloque .resume-export-card-ic {
  background: #fbe6e2;
  color: #b3261e;
}
.resume-export-card--bloque .resume-export-card-fmt { color: #b3261e; }

/* Tuile a deux sorties : le PDF client existe en version avancee et
   simplifiee. `<details>` porte le repli nativement -- fermeture a l'Echap
   et au clic exterieur, navigation au clavier, sans une ligne de script. */
.resume-export-menu { position: relative; }
.resume-export-menu > summary {
  list-style: none;
  cursor: pointer;
}
.resume-export-menu > summary::-webkit-details-marker { display: none; }
.resume-export-chevron {
  width: 16px;
  height: 16px;
  flex: none;
  /* Cale le chevron sur le bord DROIT de la tuile : sans cette marge
     automatique il se colle au texte, au milieu de la carte. */
  margin-left: auto;
  color: var(--muted);
  transition: transform 0.14s;
}
.resume-export-menu[open] .resume-export-chevron { transform: rotate(180deg); }

.resume-export-menu-liste {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  z-index: 20;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 4px 8px rgba(26, 35, 64, 0.08), 0 12px 28px rgba(26, 35, 64, 0.12);
  overflow: hidden;
}
.resume-export-menu-liste a {
  display: block;
  padding: 10px 14px;
  text-decoration: none;
  color: var(--text);
}
.resume-export-menu-liste a + a { border-top: 1px solid var(--border); }
.resume-export-menu-liste a:hover { background: #eef2fb; text-decoration: none; }
.resume-export-menu-liste .nom {
  display: block;
  font-size: 13px;
  font-weight: 700;
  color: var(--navy);
}
.resume-export-menu-liste .fmt {
  display: block;
  font-size: 11.5px;
  color: var(--muted);
  margin-top: 2px;
}
/* Ouverture de la modale d'export PDF : elle compte les pages, donc met tout
   le document en page avant de s'afficher. Pendant ce temps (htmx pose
   `.htmx-request` sur le lien), la ligne le dit au lieu de rester inerte. */
.resume-export-menu-liste .attente { display: none; }
.resume-export-menu-liste a.htmx-request { cursor: progress; background: #eef2fb; }
.resume-export-menu-liste a.htmx-request .fmt { display: none; }
.resume-export-menu-liste a.htmx-request .attente {
  display: flex;
  align-items: center;
  gap: 5px;
  margin-top: 2px;
  font-size: 11.5px;
  color: var(--blue);
}
.resume-export-menu-liste .attente .ic { width: 14px; height: 14px; animation: export-tourne 1s linear infinite; }
@keyframes export-tourne { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .resume-export-menu-liste .attente .ic { animation: none; }
}

.resume-export-card-txt {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.resume-export-card-nom {
  font-size: 13.5px;
  font-weight: 700;
  color: var(--navy, #1a2340);
  line-height: 1.25;
}
.resume-export-card-fmt {
  font-size: 11.5px;
  color: var(--muted, #94a0b8);
  margin-top: 2px;
}

/* Bloc "Actions" (Valider le chiffrage) : pose au-dessus du bloc Exports
   dans l'aside synthese. Bouton vert pour marquer l'action principale. */
.resume-actions {
  margin-top: 22px;
  padding-top: 16px;
  border-top: 1px solid #3d4a6e;
}
.resume-actions h3 {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #8899aa;
  margin: 0 0 10px;
}
.resume-action-btn {
  display: block;
  width: 100%;
  padding: 11px 12px;
  margin-bottom: 8px;
  border: 1px solid;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 700;
  text-align: center;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.resume-action-validate {
  background: #e6f7ec;
  color: #1f8a4c;
  border-color: #b8e3c6;
}
.resume-action-validate:hover {
  background: #d0eedb;
  border-color: #82c69b;
  color: #136634;
}
/* Bouton "Passer en facturation" : palette gold qui matche le badge
   `.badge-travaux`. Signal visuel fort = decision metier importante
   (bascule en phase chantier, modules Pilotage/Situations actifs). */
.resume-action-facturation {
  background: #fdf2cc;
  color: #8a6814;
  border-color: #e8d68a;
}
.resume-action-facturation:hover {
  background: #fae8a4;
  border-color: #c9a227;
  color: #6b5010;
}
/* Bouton "Comparer les versions" : palette bleue, distincte du vert
   (valider) et de l'or (facturation) -- c'est une action de LECTURE, pas
   une decision. Separe des deux autres par un filet : il vit hors de la
   frise chiffrage -> facturation et reste present dans toutes les phases. */
.resume-action-comparer {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: 12px;
  background: #e8efff;
  color: #2d5dd4;
  border-color: #bccdf7;
}
.resume-action-comparer:hover {
  background: #d6e2ff;
  border-color: #3b6ef5;
  color: #1f47a8;
}
.resume-action-comparer .ic { width: 16px; height: 16px; }
.resume-action-compte {
  min-width: 20px;
  padding: 1px 7px;
  border-radius: 10px;
  background: #3b6ef5;
  color: #fff;
  font-size: 11px;
  line-height: 16px;
}
/* Moins de deux versions : visible (decouvrabilite) mais estompe. Il ouvre
   quand meme la fenetre, qui explique ce qu'il manque. */
.resume-action-comparer.is-indisponible { opacity: .55; }
.resume-action-comparer.is-indisponible:hover { opacity: .8; }
/* Info statut affichee a la place du bouton "Passer en facturation"
   quand le projet n'est plus en CHIFFRAGE. Cosmetique uniquement,
   pas une action (pas de bouton). */
.resume-phase-info {
  padding: 11px 12px;
  margin-bottom: 8px;
  border: 1px solid #e8d68a;
  border-radius: 6px;
  font-size: 13px;
  text-align: center;
  background: #fdf2cc;
  color: #8a6814;
}
.resume-phase-info strong { font-weight: 700; }
.resume-phase-info-clos {
  background: #2a3656;
  color: #ffffff;
  border-color: #1d2a5b;
}

/* Bandeau verrou du chiffrage (bloc 2 volet 2) : haut des onglets Chiffrage +
   Aléas et Remise quand le projet est passé en facturation. */
.chiffrage-verrou {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin: 14px 20px;
  padding: 11px 16px;
  border: 1px solid;
  border-radius: 10px;
  font-size: 13.5px;
}
.chiffrage-verrou .cv-ico { font-size: 16px; flex: 0 0 auto; }
.chiffrage-verrou .cv-txt { flex: 1; min-width: 200px; }
.chiffrage-verrou .cv-btn {
  flex: 0 0 auto;
  border: 0;
  border-radius: 8px;
  padding: 7px 14px;
  font-size: 13px;
  font-family: inherit;
  cursor: pointer;
  color: #fff;
}
.chiffrage-verrou-locked { background: #fdf3e7; border-color: #f0c896; color: #8a5a12; }
.chiffrage-verrou-locked .cv-btn { background: #bf7a08; }
.chiffrage-verrou-locked .cv-btn:hover { background: #a56906; }
.chiffrage-verrou-open { background: #eef3ff; border-color: #b9cdf7; color: #2f4a86; }
.chiffrage-verrou-open .cv-btn { background: #3b6ef5; }
.chiffrage-verrou-open .cv-btn:hover { background: #2f5fd6; }

/* Modal validation version : reprend la palette `.modal` existante.
   Class supplementaire `.version-modal` pour ajuster la largeur. */
.version-modal {
  max-width: 480px;
}
/* Numero auto-calcule, non-modifiable : visuel "lecture seule" pour
   signaler qu'il n'est pas saisi par l'utilisateur. La valeur change
   au change de phase (cf. script de sync dans le modal). */
.version-numero-auto {
  background: #f4f6f9;
  color: var(--navy);
  font-weight: 700;
  font-size: 16px;
  text-align: center;
  cursor: default;
  width: 100px;
}
.version-numero-auto:focus {
  outline: none;
  box-shadow: none;
}

/* Historique des versions : tableau pleine largeur sous le layout 2 colonnes
   du Resume. Le grid `.resume-layout` n'a que 2 colonnes, on etale via
   grid-column: 1 / -1 pour traverser les 2. */
.resume-historique {
  grid-column: 1 / -1;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 20px 22px;
  box-shadow: 0 1px 3px rgba(26, 35, 64, 0.04);
  /* Pas de margin-top : la grille .resume-layout a deja un row-gap (28px).
     La marge s'y ajoutait -> 48px d'espace au-dessus de l'historique. */
}
.resume-historique-title {
  font-size: 14px;
  font-weight: 700;
  color: var(--navy);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: 0 0 14px;
  padding-bottom: 10px;
  border-bottom: 1px solid #eef0f4;
}
.resume-historique-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12.5px;
}
.resume-historique-table thead {
  background: #fafbfc;
}
.resume-historique-table th {
  padding: 8px 10px;
  text-align: left;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.resume-historique-table th.num,
.resume-historique-table td.num {
  text-align: right;
}
.resume-historique-table td {
  padding: 8px 10px;
  border-bottom: 1px solid #eef0f4;
  vertical-align: middle;
}
.resume-historique-table tr:last-child td {
  border-bottom: none;
}
.resume-historique-table tr:hover td {
  background: #fafbfc;
}
.resume-historique-final {
  font-weight: 700;
  color: var(--blue);
}
.resume-historique-moa {
  color: var(--muted);
  font-style: italic;
}
.resume-historique-commentaire {
  color: var(--muted);
  font-style: italic;
  max-width: 240px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Ligne historique : la cellule Phase est cliquable (ouvre le detail),
   la cellule Actions porte les boutons Voir / Restaurer / Supprimer. */
.resume-historique-row {
  transition: background 0.12s;
}
.resume-historique-row:hover td {
  background: #fafbfc;
}
/* Premiere cellule (Phase) cliquable + curseur pointer = signal d'affordance. */
.resume-historique-row td:first-child {
  cursor: pointer;
  color: var(--blue);
}
.resume-historique-row td:first-child:hover {
  text-decoration: underline;
}
.resume-historique-actions {
  display: flex;
  gap: 4px;
  align-items: center;
  white-space: nowrap;
}
.resume-historique-actions .link-btn {
  font-size: 14px;
  padding: 4px 6px;
  background: transparent;
  border: none;
  cursor: pointer;
  border-radius: 4px;
}
.resume-historique-actions .link-btn:hover {
  background: #eef3ff;
}
.resume-historique-empty {
  padding: 24px 8px;
  text-align: center;
}

/* Modal detail version : reprend la palette modale, plus large pour
   accommoder les 2 tableaux financiers + metadonnees. */
.version-detail-modal {
  max-width: 620px;
}
.version-detail-badge {
  display: inline-block;
  margin-left: 8px;
  padding: 3px 10px;
  border-radius: 999px;
  background: #eef3ff;
  color: var(--blue);
  font-size: 12px;
  font-weight: 600;
  vertical-align: middle;
}
.version-detail-meta {
  display: flex;
  gap: 24px;
  padding-bottom: 12px;
  border-bottom: 1px solid #eef0f4;
  margin-bottom: 12px;
}
.version-detail-meta .lbl {
  display: block;
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  font-weight: 600;
  margin-bottom: 2px;
}
.version-detail-meta .val {
  font-size: 13px;
  color: var(--text);
  font-weight: 500;
}
.version-detail-commentaire {
  padding-bottom: 12px;
  border-bottom: 1px solid #eef0f4;
  margin-bottom: 12px;
}
.version-detail-commentaire .lbl {
  display: block;
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  font-weight: 600;
  margin-bottom: 4px;
}
.version-detail-commentaire p {
  margin: 0;
  font-size: 13px;
  color: var(--text);
  font-style: italic;
}
.version-detail-section {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  font-weight: 600;
  margin: 14px 0 6px;
}
.version-detail-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  margin-bottom: 8px;
}
.version-detail-table td {
  padding: 6px 8px;
  border-bottom: 1px solid #eef0f4;
}
.version-detail-table td.num {
  text-align: right;
  font-weight: 600;
  color: var(--navy);
  font-variant-numeric: tabular-nums;
}
.version-detail-table tr:last-child td {
  border-bottom: none;
}
.version-detail-aleas td.num { color: #c67100; }
.version-detail-remise td.num { color: #c0392b; }
.version-detail-final {
  background: #eef3ff;
}
.version-detail-final td {
  font-weight: 700;
  font-size: 15px;
  padding: 10px 8px;
}
.version-detail-final td.num { color: var(--blue); }
.version-detail-moa td {
  color: var(--muted);
  font-style: italic;
}
.version-detail-moa td.num { color: var(--muted); }
.version-detail-note {
  font-size: 11.5px;
  color: var(--muted);
  font-style: italic;
  margin: 14px 0 0;
  padding-top: 10px;
  border-top: 1px dashed var(--border);
}

/* Footer du modal detail : actions destructives/recuperatrices a gauche
   (Supprimer + Revenir), action neutre (Fermer) a droite.
   `justify-content: space-between` pour clairement separer les 2 zones
   -- l'utilisateur ne clique pas sur l'un par erreur en visant l'autre. */
.version-detail-footer {
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
}
.version-detail-actions-left {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

/* =============================================================================
   Autocomplete entreprise (annuaire partage Chrome)
   Pose sur les cellules Fournisseur des postes et intervenants.
   Le dropdown est en position:absolute pour flotter au-dessus du tableau.
   ============================================================================= */
.entreprise-autocomplete-wrapper {
  position: relative;       /* base d'ancrage pour le dropdown absolu */
}
.entreprise-autocomplete-results {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 50;             /* au-dessus des autres cellules + bordures */
  /* Vide par defaut (innerHTML="") -> le children .dropdown porte les styles */
}
.entreprise-autocomplete-dropdown {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: 0 4px 12px rgba(26, 35, 64, 0.12);
  max-height: 260px;
  overflow-y: auto;
  min-width: 240px;
  padding: 4px 0;
}
.entreprise-autocomplete-item {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: 100%;
  padding: 6px 10px;
  background: transparent;
  border: none;
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: var(--text);
  border-bottom: 1px solid #f0f2f6;
}
.entreprise-autocomplete-item:last-child {
  border-bottom: none;
}
.entreprise-autocomplete-item:hover {
  background: #eef3ff;
}
.entreprise-autocomplete-item .ent-name {
  font-weight: 600;
  font-size: 13px;
  line-height: 1.2;
}
.entreprise-autocomplete-item .ent-meta {
  font-size: 11px;
  color: var(--muted);
  margin-top: 1px;
}
/* Badge "kind" coloré : palette discrete par type d'entreprise. */
.ent-kind {
  display: inline-block;
  padding: 1px 5px;
  border-radius: 3px;
  font-size: 9.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.ent-kind-moa { background: #fde7ec; color: #b8254b; }
.ent-kind-moe { background: #e0e8f7; color: #1e3a8a; }
.ent-kind-moex { background: #e8eaf6; color: #3949ab; }
.ent-kind-entreprise { background: #e7f3ec; color: #1b5e2c; }
.ent-kind-autre { background: #efefef; color: #555; }

.entreprise-autocomplete-empty {
  padding: 8px 10px;
  font-size: 12px;
  font-style: italic;
}

/* Modal de creation entreprise (annuaire partage). Reprend les classes
   `.modal` / `.modal-overlay` / `.modal-body` / `.modal-footer`. Plus
   large que la modal version pour laisser respirer les 12 champs. */
.entreprise-create-modal {
  max-width: 720px;
}
/* Ligne de plusieurs champs cote a cote (SIRET + contact ; CP + ville + pays...). */
.form-field-row {
  display: flex;
  gap: 12px;
  margin-bottom: 12px;
}
.form-field-row > .form-field {
  flex: 1;
  margin-bottom: 0;       /* le row gere deja le margin-bottom */
}

/* =============================================================================
   Page Annuaire entreprises -- refonte UI 2026-05-25 inspiree d'Intus
   (cf. /Users/thibautmartel/DEV/Intus/backend/templates/partners/).
   Reproduit le look "Tailwind stone" en CSS vanilla : palette grise douce,
   rounded-2xl sur la card de la table, header sticky, badges arrondis,
   icones SVG pour les actions. Toutes les classes sont prefixees `.ann-*`
   pour eviter les collisions avec les anciens styles `.annuaire-*` qui
   restent en place tant qu'on n'a pas migre tous les usages.
   ============================================================================= */

/* Header sticky : titre + sous-titre count + bouton primaire a droite */
.ann-header {
  background: #fff;
  border-bottom: 1px solid #e7e5e4;
  padding: 24px 32px;
  position: sticky;
  top: 0;
  z-index: 10;
  margin: -20px -20px 0;   /* compense le padding de .main pour aller bord a bord */
}
.ann-header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
  gap: 16px;
  flex-wrap: wrap;
}
.ann-header-title h1 {
  font-size: 22px;
  font-weight: 600;
  color: #292524;
  margin: 0;
  line-height: 1.2;
}
.ann-header-title .ann-subtitle {
  font-size: 13px;
  color: #a8a29e;
  margin-top: 2px;
}
.ann-btn-primary {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 9px 16px;
  background: #2563eb;
  color: #fff;
  border: none;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.12s ease;
}
.ann-btn-primary:hover { background: #1d4ed8; }
.ann-btn-primary:disabled,
.ann-btn-primary[disabled] {
  background: #d4d4d4;
  cursor: not-allowed;
}

/* Form de filtres : ligne horizontale recherche + selects + indicator + reset */
.ann-filters {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.ann-search {
  flex: 1;
  min-width: 280px;
  height: 36px;
  padding: 0 14px;
  border: 1px solid #e7e5e4;
  border-radius: 8px;
  font-size: 13px;
  background: #fff;
  color: #292524;
}
.ann-search::placeholder { color: #a8a29e; }
.ann-search:focus {
  outline: none;
  border-color: #2563eb;
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15);
}
.ann-select {
  height: 36px;
  padding: 0 12px;
  border: 1px solid #e7e5e4;
  border-radius: 8px;
  font-size: 13px;
  background: #fff;
  color: #292524;
  cursor: pointer;
}
.ann-select:focus {
  outline: none;
  border-color: #2563eb;
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15);
}
.ann-htmx-indicator {
  opacity: 0;
  transition: opacity 0.2s ease;
  color: #2563eb;
  font-size: 13px;
}
.htmx-request .ann-htmx-indicator { opacity: 1; }
.ann-reset {
  padding: 7px 12px;
  color: #78716c;
  font-size: 13px;
  text-decoration: none;
  border-radius: 6px;
  transition: background 0.12s ease, color 0.12s ease;
}
.ann-reset:hover {
  background: #f5f5f4;
  color: #292524;
}

/* Body de la page : zone sous le header sticky avec padding lateral */
.ann-body {
  padding: 24px 32px;
}

/* Card englobant la table : bord arrondi 16px + bordure stone */
.ann-table-card {
  background: #fff;
  border: 1px solid #e7e5e4;
  border-radius: 16px;
  overflow: hidden;
}
.ann-table {
  width: 100%;
  border-collapse: collapse;
}
.ann-table thead tr {
  border-bottom: 1px solid #f5f5f4;
}
.ann-table th {
  padding: 12px 20px;
  text-align: left;
  font-size: 11px;
  font-weight: 600;
  color: #57534e;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.ann-table th.ann-th-right { text-align: right; }
.ann-table tbody tr {
  border-bottom: 1px solid #fafaf9;
  transition: background 0.1s ease;
}
.ann-table tbody tr:last-child { border-bottom: none; }
.ann-table tbody tr:hover { background: #fafaf9; }
.ann-table tbody tr.is-inactive { opacity: 0.6; }
.ann-table td {
  padding: 14px 20px;
  font-size: 13px;
  color: #57534e;
  vertical-align: middle;
}
.ann-table td.ann-td-right { text-align: right; white-space: nowrap; }
.ann-table .ann-cell-name {
  font-size: 13px;
  font-weight: 500;
  color: #292524;
}
.ann-table .ann-cell-name-meta {
  font-size: 11px;
  color: #a8a29e;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  margin-top: 2px;
}
.ann-table .ann-cell-email a {
  color: #2563eb;
  text-decoration: none;
}
.ann-table .ann-cell-email a:hover { text-decoration: underline; }
.ann-table .ann-cell-empty { color: #d6d3d1; }

/* Badge "Rôle" -- garde la palette existante (.ent-kind-*) pour cohérence
   visuelle, mais on neutralise text-transform pour un rendu plus moderne. */
.ann-table .ent-kind {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  text-transform: none;
  letter-spacing: 0;
}

/* Badge statut : pill arrondie type Intus */
.ann-badge-statut {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 500;
}
.ann-badge-actif {
  background: #d1fae5;
  color: #047857;
}
.ann-badge-inactif {
  background: #f5f5f4;
  color: #78716c;
}

/* Boutons d'action en icones SVG -- carre 32x32, hover colorise */
.ann-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  background: transparent;
  border: none;
  border-radius: 6px;
  color: #a8a29e;
  cursor: pointer;
  text-decoration: none;
  transition: background 0.12s ease, color 0.12s ease;
}
.ann-icon-btn:hover { background: #f5f5f4; color: #57534e; }
.ann-icon-btn-edit:hover { background: #eff6ff; color: #2563eb; }
.ann-icon-btn-danger:hover { background: #fef2f2; color: #dc2626; }
.ann-icon-btn-success:hover { background: #ecfdf5; color: #059669; }
.ann-icon-btn[disabled],
.ann-icon-btn:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}
.ann-icon-btn svg { width: 16px; height: 16px; }

/* Form inline pour la toggle (action POST) : evite que le <form> default
   prenne toute la largeur et casse l'alignement des icones. */
.ann-action-form { display: inline-block; }
.ann-readonly-tag {
  display: inline-block;
  padding: 3px 8px;
  background: #f5f5f4;
  color: #a8a29e;
  border-radius: 4px;
  font-size: 11px;
  font-style: italic;
}

/* Etat vide stylise : icone + message centres dans la card */
.ann-empty {
  padding: 56px 24px;
  text-align: center;
}
.ann-empty .ann-empty-icon {
  font-size: 40px;
  margin-bottom: 8px;
  opacity: 0.5;
}
.ann-empty .ann-empty-title {
  font-size: 14px;
  font-weight: 600;
  color: #292524;
  margin-bottom: 4px;
}
.ann-empty .ann-empty-msg {
  font-size: 13px;
  color: #78716c;
}
.ann-empty a {
  color: #2563eb;
  text-decoration: none;
  font-weight: 500;
}
.ann-empty a:hover { text-decoration: underline; }

/* Alerte annuaire indisponible : carte rouge clair en haut de body */
.ann-alert {
  background: #fef2f2;
  border: 1px solid #fecaca;
  border-radius: 12px;
  padding: 16px 20px;
  font-size: 13px;
  color: #991b1b;
  margin-bottom: 16px;
}

/* ----- Anciennes classes .annuaire-* conservees pour fallback si d'autres
        pages les utilisent. A retirer dans un coup de balai futur. ----- */
.annuaire-filters {
  display: flex;
  gap: 12px;
  align-items: center;
  margin: 16px 0 12px;
  flex-wrap: wrap;
}
.annuaire-search {
  flex: 1;
  min-width: 240px;
  height: 38px;
  padding: 0 12px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 13px;
}
.annuaire-search:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(59, 110, 245, 0.12);
}
.annuaire-kind-filter {
  height: 38px;
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 13px;
  background: var(--surface);
  cursor: pointer;
}
.annuaire-toggle-inactive {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--muted);
  cursor: pointer;
}
.annuaire-toggle-inactive input { margin: 0; }
.annuaire-reset {
  font-size: 13px;
  color: var(--muted);
  text-decoration: underline;
}
.annuaire-reset:hover { color: var(--text); }

/* Bouton-icone "disabled" : actions pas encore disponibles, on garde la
   place pour eviter le shift visuel quand on les activera en Sub 3 et 4. */
.link-btn-disabled {
  opacity: 0.3;
  cursor: not-allowed;
  display: inline-block;
  margin: 0 4px;
}

/* Dans une modale, les champs APPAIRES passent le libelle au-dessus.

   En pleine page (projet_form) la grille a 2 colonnes a la place : chaque
   champ garde sa colonne de libelles de 148px ET un champ confortable. Dans
   une modale de 580px, la meme grille ne laissait que 95px au champ -- trop
   court pour ses propres placeholders (« 06 12 34 56 78 » en demande 125,
   « Chargé d'affaires senior » 181).

   Libelle au-dessus plutot que colonne unique : passer les paires en pleine
   largeur reglait la largeur mais ajoutait deux lignes, et la modale se
   mettait a defiler -- le champ « Mot de passe initial », obligatoire,
   repassait sous la ligne de flottaison. Or c'est lui qui bloque
   silencieusement l'envoi quand on ne l'a pas vu. Les libelles a gauche
   restent la regle pour les champs pleine largeur, qui portent l'alignement
   vertical des valeurs. */
.modal-body .form-grid .form-field {
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
}
.modal-body .form-grid .form-field > label,
.modal-body .form-grid .form-field > :not(label) {
  grid-column: 1;
}
.modal-body .form-grid .form-field label {
  margin-bottom: 2px;
}

/* Titre de section dans un modal (standalone, hors .form-section).
   Reprend les codes typo des sections de form mais sans le wrapper. */
.modal-body .form-section-title {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  font-weight: 700;
  margin: 18px 0 10px;
  padding-bottom: 6px;
  border-bottom: 1px solid #eef0f4;
}
.modal-body .form-section-help {
  font-size: 12px;
  color: var(--muted);
  line-height: 1.5;
  margin: -4px 0 12px;
}
/* Liste de cases a cocher pour les permissions par groupe (page Utilisateurs).
   Chaque option = checkbox + intitule (titre + description en italique).

   Grille explicite a UNE colonne pleine largeur : ce bloc portait `.form-field`
   et heritait donc de sa grille `148px | 1fr`. Or chaque option est un
   `<label>`, et `.form-field > label { grid-column: 1 }` les envoyait toutes
   dans la colonne des libellés -- trois cartes de 148px de large, avec un
   intitule qui se cassait sur cinq lignes. Le bloc n'est pas un couple
   libelle/champ : il ne doit pas porter `.form-field`, et pose sa grille. */
.perm-checkboxes {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 8px;
}
.perm-option {
  min-width: 0;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
.perm-option:hover {
  border-color: #c7cdd8;
  background: #fafbfc;
}
.perm-option input[type="checkbox"] {
  margin: 2px 0 0 0;
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  cursor: pointer;
}
.perm-option span {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.perm-option strong {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}
.perm-option em {
  font-size: 12px;
  color: var(--muted);
  font-style: normal;
}

/* =============================================================================
   Diagramme surface par zone (modal popup pour copier-coller en présentation).
   ============================================================================= */
.modal-overlay[hidden] { display: none; }

/* Selecteur de tri de la vue par entreprise, pose dans le titre de section
   a cote du bouton "Afficher diagramme". Discret : c'est un reglage de lecture,
   pas une action. */
.analytique-tri {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: 12px;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--muted);
}
.analytique-tri select {
  padding: 5px 8px;
  font: inherit;
  font-weight: 500;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
}
.analytique-tri select:hover {
  background: #eef0f4;
}
.analytique-tri select:focus-visible {
  outline: 2px solid var(--primary, #3b6ef5);
  outline-offset: 1px;
}

.zone-diag-trigger {
  margin-left: 12px;
  padding: 6px 12px;
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  vertical-align: middle;
}
.zone-diag-trigger:hover {
  background: #eef0f4;
  border-color: #d4d7df;
}

.zone-diag-modal { max-width: 880px; }
.zone-diag-modal:has(.zone-diag-table--quad) { max-width: 1080px; }
.zone-diag-modal .modal-body { padding: 28px 32px; gap: 0; }

.zone-diag-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
  color: #1a2340;
}
.zone-diag-table thead th {
  background: #1d2a5b;
  color: #fff;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 14px 16px;
  text-align: left;
}
.zone-diag-table thead th.num { text-align: right; }
.zone-diag-table thead th:last-child { text-align: left; }

.zone-diag-table tbody tr { background: #f4f6fa; }
.zone-diag-table tbody tr:nth-child(even) { background: #fff; }
.zone-diag-table tbody td {
  padding: 14px 16px;
  border-bottom: 1px solid #e4e7ee;
}
.zone-diag-table tbody td.num { text-align: right; font-variant-numeric: tabular-nums; }

.zone-diag-bar-cell { width: 45%; min-width: 280px; }
/* Variante 4 colonnes (2 barres : surface + cout) : on retrecit chaque
   barre pour tenir dans la largeur du modal sans casser la mise en page. */
.zone-diag-table--quad .zone-diag-bar-cell { width: 30%; min-width: 220px; }
.zone-diag-bar-row {
  display: flex;
  align-items: center;
  gap: 12px;
}
.zone-diag-bar-track {
  flex: 1;
  height: 22px;
  background: #e4e9f2;
  border-radius: 3px;
  overflow: hidden;
}
.zone-diag-bar-fill { height: 100%; border-radius: 3px; }
.zone-diag-bar-fill--gold  { background: #c9a227; }
.zone-diag-bar-fill--navy  { background: #1d2a5b; }
.zone-diag-bar-fill--blue  { background: #4a73a8; }
.zone-diag-bar-fill--light { background: #b3cbe4; }
.zone-diag-bar-label {
  min-width: 60px;
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-size: 13px;
  color: #6a7080;
}
.zone-diag-bar-label--strong { color: #1a2340; font-weight: 700; }

.zone-diag-table tfoot tr { background: #c9a227; color: #fff; }
.zone-diag-table tfoot th {
  padding: 14px 16px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.zone-diag-table tfoot th.num { text-align: right; font-variant-numeric: tabular-nums; }
.zone-diag-table tfoot th:last-child { text-align: left; }

/* Boutons d'export image dans le footer du modal (taille reduite pour ne pas
   ecraser visuellement le contenu printable au-dessus). */
.zone-diag-modal .modal-footer { padding: 14px 24px; }
.zone-diag-modal .modal-footer .btn {
  padding: 8px 16px;
  font-size: 13px;
}
.zone-diag-feedback {
  font-size: 13px;
  color: #1f8a4c;
  font-weight: 500;
  align-self: center;
  margin-right: auto;
  opacity: 0;
  transition: opacity 0.2s;
  pointer-events: none;
}
.zone-diag-feedback.show { opacity: 1; }
.zone-diag-feedback--err { color: var(--danger); }

/* Actions Copier / PNG sous chaque camembert pour export direct du
   graphe (sans passer par le modal diagramme barres). */
.analytique-chart-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
  width: 100%;
  justify-content: flex-end;
  /* Si la carte est vraiment trop etroite, les deux BOUTONS passent l'un sous
     l'autre -- jamais l'icone au-dessus de son propre libelle. */
  flex-wrap: wrap;
}
/* inline-flex + nowrap : l'icone et le libelle restent TOUJOURS sur une seule
   ligne. Sans ca (bouton en `display:block`, `white-space:normal`), le libelle
   passait sous l'icone des que la carte se resserrait -- fenetre PWA, petit
   ecran (mesure : 42px de haut au lieu de 28px). */
.btn-chart-action {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  flex: none;
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 500;
}
/* Meme garde-fou pour les boutons d'export des modals (icone + libelle). */
.modal-footer .btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}
/* Titre de section portant des actions a droite (ex. Croisement Lot x Zone). */
.analytique-section-title--actions {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.analytique-title-actions {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

/* === Toasts (notifications transitoires) ===
   Floating en haut a droite. CSS = animation + couleurs.
   JS = static/js/toasts.js (auto-dismiss + click-to-close). */
.toast-container {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 9999;
  display: flex;
  flex-direction: column;
  gap: 8px;
  pointer-events: none; /* le conteneur lui-meme ne capture pas les clicks */
  max-width: 380px;
}
.toast {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px 10px 14px;
  border-radius: 8px;
  background: var(--surface, #fff);
  border: 1px solid var(--border, #dde1ea);
  box-shadow: 0 4px 16px rgba(15, 26, 61, 0.15);
  font-size: 13.5px;
  color: var(--text, #1A2340);
  opacity: 0;
  transform: translateX(20px);
  transition: opacity 200ms ease, transform 200ms ease;
}
.toast.show { opacity: 1; transform: translateX(0); }
.toast.hide { opacity: 0; transform: translateX(20px); }
.toast-msg { flex: 1; line-height: 1.35; }
.toast-close {
  background: transparent;
  border: none;
  cursor: pointer;
  color: var(--muted, #6A7080);
  font-size: 20px;
  line-height: 1;
  padding: 0 4px;
}
.toast-close:hover { color: var(--text, #1A2340); }
/* Barre coloree a gauche selon le niveau (Django messages tags). */
.toast-success { border-left: 4px solid #2A9D8F; }
.toast-info    { border-left: 4px solid #5C7AEA; }
.toast-warning { border-left: 4px solid #F4A261; }
.toast-error   { border-left: 4px solid #E76F51; }

/* === Pages d'erreur 404/500 (audit Cowork F-001) === */
.error-page-body { margin: 0; background: var(--bg, #f4f6fa); }
.error-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.error-page-card {
  max-width: 500px;
  background: var(--surface, #fff);
  border: 1px solid var(--border, #dde1ea);
  border-radius: 12px;
  padding: 40px;
  text-align: center;
  box-shadow: 0 4px 20px rgba(15, 26, 61, 0.08);
}
.error-page-code {
  font-size: 64px;
  font-weight: 800;
  color: var(--navy, #1D2A5B);
  line-height: 1;
  margin-bottom: 8px;
  letter-spacing: -0.02em;
}
.error-page-title {
  font-size: 22px;
  font-weight: 700;
  margin: 0 0 12px;
  color: var(--text, #1A2340);
}
.error-page-msg {
  font-size: 14px;
  color: var(--muted, #6A7080);
  line-height: 1.5;
  margin: 0 0 24px;
}
.error-page-actions { display: flex; justify-content: center; gap: 12px; }

/* Banner warning surface != zones (audit Cowork v2 F-003) */
.surface-mismatch-banner {
  margin: 0 0 18px;
  padding: 12px 16px;
  border-radius: 6px;
  font-size: 13.5px;
  line-height: 1.5;
}

/* === Responsive guard (audit Cowork v2 R-001/R-002) ===
   En dessous de 1024px, on masque le contenu et on affiche un message
   bloquant. L'app est desktop-only, refactor responsive en backlog. */
.responsive-guard {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 99999;
  background: var(--bg, #f4f6fa);
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.responsive-guard-card {
  max-width: 420px;
  text-align: center;
  background: var(--surface, #fff);
  border: 1px solid var(--border, #dde1ea);
  border-radius: 12px;
  padding: 32px 28px;
  box-shadow: 0 4px 20px rgba(15, 26, 61, 0.08);
}
.responsive-guard-icon { font-size: 56px; margin-bottom: 8px; }
.responsive-guard-card h1 {
  font-size: 20px;
  font-weight: 700;
  margin: 0 0 12px;
  color: var(--text, #1A2340);
}
.responsive-guard-card p {
  font-size: 14px;
  line-height: 1.5;
  color: var(--muted, #6A7080);
  margin: 0 0 8px;
}
.responsive-guard-meta { font-size: 12.5px; font-style: italic; opacity: 0.8; }

/* Active la garde sous 1024px et masque tout le reste du body.
   `body.ecran-libre` en exempte les pages qui DOIVENT marcher sur un
   telephone : la connexion et le consentement du connecteur Claude. Un
   membre de l'equipe qui connecte Claude depuis l'app mobile passe par ces
   deux pages dans le navigateur du telephone ; bloquees, la connexion du
   connecteur y etait impossible (constate 2026-10-17). */
@media (max-width: 1023.98px) {
  body:not(.ecran-libre) .responsive-guard { display: flex; }
  body:not(.ecran-libre) > *:not(.responsive-guard):not(script) {
    display: none !important;
  }
}

/* === Skip-link accessibilité (audit Cowork v2 A-003) ===
   Lien "Aller au contenu principal" placé tout en haut du <body>.
   Invisible par défaut (positionné hors viewport), il apparaît dès
   qu'il prend le focus clavier (Tab depuis le début de page). Permet
   aux utilisateurs clavier / lecteur d'écran de sauter la sidebar et
   la navbar pour atterrir directement sur le <main id="main-content">. */
.skip-link {
  position: absolute;
  top: -100px;
  left: 12px;
  z-index: 100000;
  background: var(--accent, #2D5BFF);
  color: #fff;
  padding: 10px 16px;
  border-radius: 6px;
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  box-shadow: 0 4px 12px rgba(15, 26, 61, 0.15);
  transition: top 0.15s ease-out;
}
.skip-link:focus {
  top: 12px;
  outline: 2px solid #fff;
  outline-offset: 2px;
}

/* =============================================================================
   Page Informations projet -- refonte 2026-05-26 (hero + cartes + zones bars)
   ============================================================================= */
.infos-page {
  padding: 24px 32px 48px;
  max-width: 1100px;
  margin: 0 auto;
  width: 100%;
}

/* --- HERO --- */
.infos-hero {
  position: relative;
  border-radius: 14px;
  overflow: hidden;
  margin-bottom: 24px;
  background: var(--navy);
  color: #fff;
}
.infos-hero-bg {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 140% at 88% -10%, rgba(59, 110, 245, 0.55) 0%, transparent 55%),
    linear-gradient(135deg, #2a3656 0%, #1e2740 100%);
}
.infos-hero-content { position: relative; padding: 26px 30px; }
.infos-hero-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
}
.infos-hero-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.6);
  font-weight: 600;
}
.infos-hero-name {
  font-size: 27px;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 6px 0 4px;
  line-height: 1.1;
}
.infos-hero-sub { font-size: 13.5px; color: rgba(255, 255, 255, 0.75); }
.infos-edit-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 9px 16px;
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.25);
  color: #fff;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 500;
  text-decoration: none;
  flex-shrink: 0;
  transition: background 0.12s, border-color 0.12s;
}
.infos-edit-btn:hover { background: var(--blue); border-color: var(--blue); text-decoration: none; }
.infos-edit-btn svg { width: 15px; height: 15px; }

/* KPI chips dans le hero */
.infos-hero-kpis {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  margin-top: 22px;
  background: rgba(255, 255, 255, 0.12);
  border-radius: 10px;
  overflow: hidden;
}
.infos-kpi {
  background: rgba(15, 22, 45, 0.35);
  padding: 13px 16px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.infos-kpi-lbl {
  font-size: 10px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
}
.infos-kpi-val {
  font-size: 19px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.infos-kpi-val.accent { color: #8fb0ff; }

/* --- Badge statut (hero + section Planning) --- */
.infos-status-badge {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 12px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.01em;
}
.infos-status-chiffrage { background: #e8f0fe; color: #2d5dd4; }
.infos-status-travaux   { background: #fdf0d8; color: #a8650f; }
.infos-status-clos      { background: #e3ebe5; color: #2f6b43; }
.infos-status-perdu     { background: #eceff3; color: #5b6472; }
/* Dans le hero (fond sombre), versions plus lumineuses. */
.infos-hero-eyebrow .infos-status-chiffrage { background: rgba(143, 176, 255, 0.2); color: #bcd0ff; }
.infos-hero-eyebrow .infos-status-travaux   { background: rgba(240, 200, 120, 0.2); color: #f2d39b; }
.infos-hero-eyebrow .infos-status-clos      { background: rgba(160, 220, 180, 0.2); color: #bfe6cd; }
.infos-hero-eyebrow .infos-status-perdu     { background: rgba(203, 213, 225, 0.2); color: #d5dbe4; }

/* --- Grille sections + aside --- */
.infos-grid {
  display: grid;
  grid-template-columns: 1fr 320px;
  gap: 20px;
  align-items: start;
}
.infos-col-main { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
/* Les acteurs portent nom + adresse sur une ligne : ils etouffent dans une
   demi-colonne, la carte prend donc toute la largeur. */
.infos-card--large { grid-column: 1 / -1; }
.infos-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 18px 20px 20px;
}
.infos-card-title {
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 700;
  margin-bottom: 14px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 8px;
}
.infos-card-count {
  margin-left: auto;
  background: var(--bg);
  color: var(--muted);
  border-radius: 10px;
  padding: 1px 9px;
  font-size: 11px;
}

/* Champs clé/valeur en grille 2 colonnes interne. */
.infos-fields {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px 18px;
}
/* Libelle AU-DESSUS de la valeur, et non a gauche comme dans le formulaire
   d'edition : ces cartes-ci font ~215px de large, une colonne de libelles
   fixe n'y laisse plus assez de place et la valeur se rend a la verticale
   (essaye le 2026-09-21, rendu inutilisable). */
.infos-field { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.infos-field-wide { grid-column: 1 / -1; }
.infos-field dt {
  font-size: 10.5px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
  line-height: 1.35;
}
.infos-field dd {
  font-size: 14px;
  color: var(--text);
  font-weight: 500;
  word-break: break-word;
}
.infos-respos { display: flex; flex-wrap: wrap; gap: 6px; }
.infos-respo-chip {
  display: inline-block;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 3px 11px;
  font-size: 12.5px;
  font-weight: 500;
}

/* --- Aside zones avec barres --- */
.infos-col-aside .infos-card { position: sticky; top: 16px; }
.infos-zones { list-style: none; display: flex; flex-direction: column; gap: 13px; }
.infos-zone-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 5px;
}
.infos-zone-name { font-size: 13px; font-weight: 500; color: var(--text); }
.infos-zone-surface { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.infos-zone-bar {
  height: 7px;
  background: var(--bg);
  border-radius: 4px;
  overflow: hidden;
}
.infos-zone-fill {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, #5dade2, var(--blue));
  border-radius: 4px;
}
.infos-zones-total {
  display: flex;
  justify-content: space-between;
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.infos-empty { color: var(--muted); font-style: italic; font-size: 13px; padding: 8px 0; }

/* Responsive : sous 980px, une seule colonne. */
@media (max-width: 980px) {
  .infos-grid { grid-template-columns: 1fr; }
  .infos-col-main { grid-template-columns: 1fr; }
  .infos-hero-kpis { grid-template-columns: repeat(2, 1fr); }
}

/* ============================================================
   Feedbacks dashboard (admin tech) — bug reports + annotations
   ============================================================
   Réutilise massivement les styles `.ann-*` (header sticky,
   filtres, table card, actions) pour cohérence cross-app.
   Spécifique ici : badges type/severite/statut, page détail,
   capture d'écran avec pin, panneau résolution. */

/* --- Liste : ajustements colonne ID + lignes ----------------- */
.fb-table th.fb-th-id { width: 56px; text-align: right; padding-right: 12px; }
.fb-table td.fb-cell-id {
  text-align: right;
  padding-right: 12px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
  color: var(--muted);
}
/* Ligne cliquable : cf. static/js/lignes-cliquables.js (curseur commun a
   toutes les lignes `[data-row-link]`, regle du tableau des projets). */
.fb-row:hover { background: #f8fafc; }
.fb-row-resolu { opacity: .65; }
.fb-row-rejete { opacity: .55; }
.fb-cell-title {
  color: var(--text);
  text-decoration: none;
  font-weight: 600;
  display: block;
  line-height: 1.3;
}
.fb-cell-title:hover { color: var(--blue); text-decoration: underline; }
.fb-cell-excerpt {
  color: var(--muted);
  font-size: 12px;
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 380px;
}
.fb-cell-user { font-size: 13px; }
.fb-cell-projet {
  color: var(--muted);
  text-decoration: none;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
}
.fb-cell-projet:hover { color: var(--blue); text-decoration: underline; }
.fb-cell-date {
  font-size: 12px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* --- Badges Type --------------------------------------------- */
.fb-type {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .02em;
  white-space: nowrap;
}
.fb-type-bug         { background: #fde2dd; color: #b3261e; }
.fb-type-annotation  { background: #ede7f6; color: #5e35b1; }
.fb-type-suggestion  { background: #e1f0fa; color: #0c6cb3; }

/* --- Badges Sévérité (bugs uniquement) ----------------------- */
.fb-severite {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 4px;
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  margin-left: 4px;
}
.fb-severite-bloquant { background: #fee2e2; color: #b91c1c; }
.fb-severite-gene     { background: #fef3c7; color: #92400e; }
.fb-severite-info     { background: #f1f5f9; color: #64748b; }

/* --- Badges Statut ------------------------------------------- */
.fb-statut {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: .02em;
  white-space: nowrap;
}
.fb-statut-nouveau  { background: #dbeafe; color: #1d4ed8; }
.fb-statut-en_cours { background: #fef3c7; color: #92400e; }
.fb-statut-resolu   { background: #d1fae5; color: #065f46; }
.fb-statut-rejete   { background: #e5e7eb; color: #4b5563; }

/* --- Empty state liste --------------------------------------- */
.fb-empty {
  text-align: center;
  padding: 64px 24px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
}
.fb-empty-icon { font-size: 40px; margin-bottom: 12px; opacity: .6; }
.fb-empty h2 { margin: 0 0 6px; font-size: 18px; color: var(--text); font-weight: 700; }
.fb-empty p { margin: 0; color: var(--muted); font-size: 14px; }
.fb-empty a { color: var(--blue); }

/* --- Page détail : header ------------------------------------ */
.fb-detail-header {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--bg);
  padding: 18px 28px 14px;
  border-bottom: 1px solid var(--border);
}
.fb-detail-header-row {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  max-width: 1200px;
  margin: 0 auto;
}
.fb-back-btn {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text);
  text-decoration: none;
  transition: background .15s;
}
.fb-back-btn:hover { background: #eef2f7; }
.fb-back-btn svg { width: 18px; height: 18px; }
.fb-detail-titles { flex: 1; min-width: 0; }
.fb-detail-eyebrow {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 6px;
}
.fb-detail-id {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 13px;
  color: var(--muted);
}
.fb-detail-title {
  margin: 0;
  font-size: 22px;
  font-weight: 700;
  color: var(--text);
  line-height: 1.3;
}

/* --- Page détail : grille ------------------------------------ */
.fb-detail-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 16px;
  max-width: 1200px;
  margin: 0 auto;
}
.fb-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 18px 20px;
}
.fb-card-meta { grid-column: 1 / -1; }
.fb-card-actions { grid-column: 1 / -1; }
.fb-card-title {
  margin: 0 0 12px;
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--muted);
}
.fb-description {
  color: var(--text);
  font-size: 14px;
  line-height: 1.6;
  white-space: pre-wrap;
  word-wrap: break-word;
}
.fb-empty-inline { color: var(--muted); font-style: italic; font-size: 13px; margin: 0; }

/* --- Capture + pin ------------------------------------------- */
.fb-screenshot-wrap {
  position: relative;
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  background: #f8fafc;
}
.fb-screenshot { display: block; width: 100%; height: auto; }

/* Capture cliquable -> lightbox plein ecran (CSS :target, cf. feedbacks/feedbacks_detail.html).
   Retour Thibaut 2026-07-07 : la miniature etait illisible, il faut pouvoir
   l'agrandir au clic. */
.fb-screenshot-link { display: block; cursor: zoom-in; }
.fb-screenshot-hint { display: block; margin-top: 8px; font-size: 12px; color: #6a7080; }
.fb-lightbox { display: none; }
.fb-lightbox:target {
  display: flex;
  align-items: center;
  justify-content: center;
  position: fixed;
  inset: 0;
  z-index: 1000;
  padding: 28px;
  background: rgba(9, 14, 30, 0.92);
  cursor: zoom-out;
}
.fb-lightbox img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border-radius: 4px;
  box-shadow: 0 12px 48px rgba(0, 0, 0, 0.6);
}
.fb-lightbox-close {
  position: fixed;
  top: 16px;
  right: 26px;
  color: #fff;
  font-size: 34px;
  line-height: 1;
  text-decoration: none;
}
.fb-pin {
  position: absolute;
  pointer-events: none;
  width: 24px;
  height: 24px;
  margin: -12px 0 0 -12px;
  border-radius: 50%;
  background: #b3261e;
  border: 3px solid #fff;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .35);
  animation: fb-pin-pulse 1.8s ease-in-out infinite;
}
@keyframes fb-pin-pulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.18); }
}

/* --- Métadonnées --------------------------------------------- */
.fb-meta { margin: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 24px; }
.fb-meta-row { display: flex; flex-direction: column; gap: 2px; }
.fb-meta-row dt {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted);
}
.fb-meta-row dd { margin: 0; font-size: 13px; color: var(--text); }
.fb-meta-row dd a { color: var(--blue); text-decoration: none; }
.fb-meta-row dd a:hover { text-decoration: underline; }
.fb-meta-mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; }
.fb-meta-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fb-meta-empty { color: var(--muted); font-style: italic; }

/* --- Résolution : panneau de statut + note ------------------- */
.fb-form-statut { display: flex; flex-direction: column; gap: 14px; }
.fb-statut-choices {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  padding: 0;
  margin: 0;
  border: none;
}
.fb-statut-legend {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted);
  margin-bottom: 8px;
  width: 100%;
}
.fb-statut-choice {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  cursor: pointer;
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
  transition: all .15s;
}
.fb-statut-choice input { margin: 0; }
.fb-statut-choice:hover { background: #f1f5f9; }
.fb-statut-choice:has(input:checked) { border-color: var(--blue); background: #eff6ff; color: var(--blue); font-weight: 600; }
.fb-statut-choice.is-current { box-shadow: inset 0 0 0 1px var(--blue); }

.fb-note-label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted);
}
.fb-note-input {
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 10px 12px;
  font-size: 13px;
  color: var(--text);
  font-family: inherit;
  resize: vertical;
  min-height: 70px;
  background: var(--surface);
  text-transform: none;
  letter-spacing: normal;
  font-weight: 400;
}
.fb-note-input:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(59, 110, 245, .15);
}

.fb-form-actions { display: flex; justify-content: flex-end; }
.fb-btn-primary {
  background: var(--blue);
  color: #fff;
  border: none;
  border-radius: 10px;
  padding: 9px 18px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: background .15s;
}
.fb-btn-primary:hover { background: var(--blue-2); }

.fb-form-delete {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px dashed var(--border);
  display: flex;
  justify-content: flex-end;
}
.fb-btn-danger {
  background: var(--surface);
  color: var(--danger);
  border: 1px solid var(--danger);
  border-radius: 10px;
  padding: 8px 16px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: background .15s;
}
.fb-btn-danger:hover { background: var(--danger-bg); }

/* --- Responsive feedbacks ------------------------------------ */
@media (max-width: 980px) {
  .fb-detail-grid { grid-template-columns: 1fr; }
  .fb-meta { grid-template-columns: 1fr; }
  .fb-cell-excerpt { max-width: 200px; }
}

/* ============================================================
   Feedback report — bouton flottant + modal de saisie
   ============================================================
   JS = static/js/feedback-report.js (html2canvas + submit AJAX).
   Visible a tout user authentifie sur toutes les pages. */

/* --- FAB (bouton flottant bottom-right) ---------------------- */
.fbr-fab {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 9000;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--navy);
  color: #fff;
  border: none;
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(0, 0, 0, .18), 0 2px 4px rgba(0, 0, 0, .12);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: transform .15s ease, box-shadow .15s ease, background .15s ease;
}
.fbr-fab svg { width: 24px; height: 24px; }
.fbr-fab:hover {
  background: var(--navy-2);
  transform: translateY(-1px) scale(1.04);
  box-shadow: 0 6px 20px rgba(0, 0, 0, .22), 0 3px 6px rgba(0, 0, 0, .14);
}
.fbr-fab:active { transform: scale(0.97); }

/* --- Modal overlay ------------------------------------------- */
.fbr-overlay {
  position: fixed;
  inset: 0;
  z-index: 10000;
  background: rgba(15, 23, 42, .55);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  opacity: 0;
  transition: opacity .18s ease;
}
.fbr-overlay.is-open { opacity: 1; }
.fbr-overlay[hidden] { display: none; }

.fbr-modal {
  background: var(--surface);
  border-radius: 16px;
  box-shadow: 0 24px 48px rgba(0, 0, 0, .25), 0 6px 12px rgba(0, 0, 0, .1);
  width: 100%;
  max-width: 540px;
  max-height: calc(100vh - 48px);
  overflow-y: auto;
  transform: translateY(8px) scale(0.98);
  transition: transform .2s ease;
}
.fbr-overlay.is-open .fbr-modal { transform: translateY(0) scale(1); }

.fbr-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 22px 12px;
  border-bottom: 1px solid var(--border);
}
.fbr-modal-title {
  margin: 0;
  font-size: 17px;
  font-weight: 700;
  color: var(--text);
}
.fbr-close {
  width: 30px;
  height: 30px;
  border-radius: 8px;
  background: transparent;
  border: none;
  color: var(--muted);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.fbr-close:hover { background: #f1f5f9; color: var(--text); }

/* --- Form layout --------------------------------------------- */
.fbr-form {
  padding: 16px 22px 20px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.fbr-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  border: none;
  padding: 0;
  margin: 0;
}
.fbr-field legend, .fbr-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted);
  padding: 0;
}
.fbr-label em { color: var(--danger); font-style: normal; margin-left: 2px; }

.fbr-field-type, .fbr-field-severite {
  flex-direction: row;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}
.fbr-field-type legend, .fbr-field-severite legend {
  width: 100%;
  margin-bottom: 4px;
}
.fbr-radio {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  cursor: pointer;
  font-size: 13px;
  color: var(--text);
  transition: all .15s;
}
.fbr-radio input { margin: 0; }
.fbr-radio:hover { background: #f1f5f9; }
.fbr-radio:has(input:checked) {
  border-color: var(--blue);
  background: #eff6ff;
  color: var(--blue);
  font-weight: 600;
}

.fbr-input, .fbr-textarea {
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 10px 12px;
  font-size: 14px;
  color: var(--text);
  background: var(--surface);
  font-family: inherit;
}
.fbr-textarea { resize: vertical; min-height: 84px; }
.fbr-input:focus, .fbr-textarea:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(59, 110, 245, .15);
}

/* --- Capture preview (definition complete plus bas avec ovelray annoter) */
.fbr-field-capture { gap: 8px; }
.fbr-capture-status {
  font-size: 12px;
  color: var(--muted);
  font-style: italic;
}
.fbr-checkbox {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  color: var(--text);
  cursor: pointer;
}

/* --- Actions ------------------------------------------------- */
.fbr-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 6px;
}
.fbr-btn {
  border: 1px solid transparent;
  border-radius: 10px;
  padding: 9px 18px;
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
}
.fbr-btn-primary {
  background: var(--blue);
  color: #fff;
}
.fbr-btn-primary:hover { background: var(--blue-2); }
.fbr-btn-primary:disabled { opacity: 0.6; cursor: wait; }
.fbr-btn-ghost {
  background: transparent;
  color: var(--muted);
  border-color: var(--border);
}
.fbr-btn-ghost:hover { background: #f1f5f9; color: var(--text); }

.fbr-form-error {
  background: var(--danger-bg);
  color: var(--danger);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 13px;
  margin-top: 6px;
}

/* --- Responsive ---------------------------------------------- */
@media (max-width: 600px) {
  .fbr-fab { right: 16px; bottom: 16px; }
  .fbr-overlay { padding: 12px; }
}

/* --- Preview cliquable (bouton "Annoter") -------------------- */
.fbr-capture-preview {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
  max-height: 180px;
  background: transparent;
  cursor: pointer;
  transition: opacity .15s, border-color .15s, box-shadow .15s;
}
.fbr-capture-preview:hover {
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(59, 110, 245, .15);
}
.fbr-capture-preview img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 180px;
  object-fit: cover;
  object-position: top;
}
.fbr-capture-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  background: rgba(15, 23, 42, .55);
  color: #fff;
  font-size: 13px;
  font-weight: 600;
  opacity: 0;
  transition: opacity .15s;
  pointer-events: none;
}
.fbr-capture-overlay svg { width: 18px; height: 18px; }
.fbr-capture-preview:hover .fbr-capture-overlay { opacity: 1; }
.fbr-capture-preview.is-annotated { border-color: var(--blue); }
.fbr-capture-preview.is-annotated::before {
  content: "✏️ Annoté";
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 1;
  padding: 3px 9px;
  background: var(--blue);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  border-radius: 999px;
  letter-spacing: .02em;
}

/* ============================================================
   Annotation editor — overlay full-screen au-dessus du modal
   ============================================================
   JS = static/js/feedback-annotate.js. Toolbar haut, canvas
   centré, actions bas. Outils : crayon / rect / flèche / texte. */

.fbra-overlay {
  position: fixed;
  inset: 0;
  z-index: 11000;  /* au-dessus du fbr-overlay (10000) */
  background: rgba(15, 23, 42, .85);
  display: flex;
  flex-direction: column;
  align-items: stretch;
  padding: 16px;
  gap: 14px;
  opacity: 0;
  transition: opacity .18s ease;
}
.fbra-overlay.is-open { opacity: 1; }
.fbra-overlay[hidden] { display: none; }

/* --- Toolbar -------------------------------------------------- */
.fbra-toolbar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
  background: var(--surface);
  border-radius: 14px;
  padding: 8px 14px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .2);
}
.fbra-tools, .fbra-colors, .fbra-actions {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.fbra-tool, .fbra-action {
  width: 36px;
  height: 36px;
  border-radius: 8px;
  background: transparent;
  border: 1px solid transparent;
  color: var(--text);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background .12s, border-color .12s, color .12s;
}
.fbra-tool svg, .fbra-action svg { width: 18px; height: 18px; }
.fbra-tool:hover, .fbra-action:hover { background: #f1f5f9; }
.fbra-tool.is-active {
  background: #eff6ff;
  border-color: var(--blue);
  color: var(--blue);
}
.fbra-sep {
  width: 1px;
  height: 24px;
  background: var(--border);
}
.fbra-color {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 2px solid transparent;
  background: var(--c);
  cursor: pointer;
  padding: 0;
  transition: transform .12s, border-color .12s;
}
.fbra-color:hover { transform: scale(1.08); }
.fbra-color.is-active {
  border-color: var(--text);
  box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--c);
}

/* --- Canvas wrapper ------------------------------------------ */
.fbra-canvas-wrap {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  min-height: 0;
}
.fbra-canvas-wrap canvas {
  max-width: 100%;
  max-height: 100%;
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .3);
  cursor: crosshair;
}
.fbra-canvas-wrap canvas[data-tool="text"] { cursor: text; }
.fbra-canvas-wrap canvas[data-tool="eraser"] { cursor: cell; }

/* --- Widget texte flottant (wrapper draggable + input editable) ---- */
/* Le cadre dashed = move handle (cursor move). L'input interne = saisie
   (cursor text). User drague le cadre pour repositionner avant Enter. */
.fbra-text-widget {
  position: absolute;
  z-index: 2;
  padding: 4px;
  border: 2px dashed rgba(255, 255, 255, .9);
  background: rgba(15, 23, 42, .5);
  border-radius: 4px;
  cursor: move;
  min-width: 120px;
  transition: border-color .12s, background .12s;
}
.fbra-text-widget.is-dragging,
.fbra-text-widget:hover {
  border-color: var(--blue);
  background: rgba(15, 23, 42, .7);
}
.fbra-text-input {
  display: block;
  width: 100%;
  border: none;
  background: transparent;
  outline: none;
  padding: 0;
  font-family: system-ui, sans-serif;
  cursor: text;
}
.fbra-text-input::placeholder { color: rgba(255, 255, 255, .55); font-size: 14px; }

/* --- Bottom bar ---------------------------------------------- */
.fbra-bottombar {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

/* ============================================================
   Page Offline (PWA Bloc B)
   ============================================================
   Rendue par le SW en fallback navigation HTML quand reseau KO.
   Pre-cachee a l'install du SW (cf. templates/sw.js APP_SHELL).
   Volontairement minimaliste, identite Quanto preservee. */

body.offline-page {
  min-height: 100vh;
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  margin: 0;
}
.offline-main { width: 100%; max-width: 480px; }
.offline-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 36px 32px 28px;
  text-align: center;
  box-shadow: 0 4px 12px rgba(0, 0, 0, .06);
}
.offline-icon {
  width: 56px;
  height: 56px;
  margin: 0 auto 18px;
  color: var(--muted);
}
.offline-icon svg { width: 100%; height: 100%; }
.offline-title {
  margin: 0 0 12px;
  font-size: 22px;
  font-weight: 700;
  color: var(--text);
}
.offline-text {
  margin: 0 0 22px;
  color: var(--muted);
  font-size: 14px;
  line-height: 1.55;
}
.offline-retry {
  background: var(--blue);
  color: #fff;
  border: none;
  border-radius: 10px;
  padding: 11px 22px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: background .15s;
}
.offline-retry:hover { background: var(--blue-2); }
.offline-meta {
  margin: 22px 0 0;
  font-size: 12px;
  color: var(--muted);
  line-height: 1.5;
}

/* ============================================================
   Push notifications toggle (PWA Bloc C)
   ============================================================
   Bouton dans la sidebar bottom-block. Style cohérent avec les
   autres nav-links de la sidebar (couleur cassée sur fond
   transparent, bordure gauche -> blue quand actif). */
.sidebar-push-toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 14px;
  margin: 4px 12px;
  background: transparent;
  border: none;
  border-radius: 8px;
  color: rgba(255, 255, 255, .55);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: background .15s, color .15s;
  font-family: inherit;
  width: calc(100% - 24px);
  text-align: left;
}
.sidebar-push-toggle svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}
.sidebar-push-toggle:hover {
  background: rgba(255, 255, 255, .06);
  color: rgba(255, 255, 255, .85);
}
.sidebar-push-toggle[data-fbp-subscribed="1"] {
  color: #5dade2;  /* cyan brand-mark */
}
.sidebar-push-toggle[data-fbp-subscribed="1"] svg {
  /* Petit point indicateur "actif" sur l'icone (bordure subtile en glow). */
  filter: drop-shadow(0 0 4px rgba(93, 173, 226, .6));
}
.sidebar-push-toggle:disabled { opacity: .5; cursor: wait; }
.sidebar-push-toggle[hidden] { display: none; }

/* ============================================================
   Suppression projet : zone danger (page Informations) + corbeille
   ============================================================ */
.infos-danger {
  margin-top: 24px;
  padding: 18px 22px;
  border: 1px solid #f0c9c4;
  background: #fdf3f1;
  border-radius: 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
}
/* Zone danger (suppression projet) DANS la grille du formulaire d'edition :
   calee en colonne 1 -> meme largeur que la carte formulaire, pas toute la
   grille (qui inclut l'aside Zones a droite). Le row-gap de la grille gere
   l'espacement, on annule donc le margin-top par defaut de .infos-danger. */
.form-page-grid .infos-danger {
  grid-column: 1;
  margin-top: 0;
}
.infos-danger-title {
  margin: 0 0 4px;
  font-size: 14px;
  font-weight: 700;
  color: #b3261e;
}
.infos-danger-text p {
  margin: 0;
  font-size: 13px;
  color: var(--muted);
  line-height: 1.5;
  /* Pas de `max-width: 60ch` : il coupait la phrase apres « mais reste »
     alors que la carte avait la place. Le bouton, en `flex-shrink: 0`,
     borne deja la largeur du texte. */
}
.infos-danger-text a { color: var(--blue); }
.infos-danger-btn {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 9px 16px;
  border-radius: 10px;
  background: var(--surface);
  color: var(--danger);
  border: 1px solid var(--danger);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: background .15s, color .15s;
}
.infos-danger-btn svg { width: 16px; height: 16px; }
.infos-danger-btn:hover { background: var(--danger); color: #fff; }

/* Corbeille : bouton Restaurer (vert, sobre). */
.corbeille-restore-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 13px;
  border-radius: 8px;
  background: #ecfdf5;
  color: #047857;
  border: 1px solid #6ee7b7;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  transition: background .15s;
}
.corbeille-restore-btn svg { width: 15px; height: 15px; }
.corbeille-restore-btn:hover { background: #d1fae5; }

/* ---------------------------------------------------------------------------
   Drag & drop des postes (postes-sortable.js).
   - Vue par zone  : conteneur .postes-dropzone (1 par zone × principaux/options),
     items = lignes .row déplaçables entre zones.
   - Vue par poste : conteneur .postes-sortable (principaux/options), items =
     blocs .poste-block (poste + ses sous-lignes zones).
   On glisse par la poignée ⋮⋮ (handle) ; les autres cellules restent éditables.
   --------------------------------------------------------------------------- */
.postes-dropzone,
.postes-sortable,
.poste-block {
  /* S'aligne sur la largeur des .row (même min-width) pour rester collé au
     header pendant le scroll horizontal de .postes-grid. */
  min-width: 1396px;
}
/* TOUJOURS visible, calée tout à gauche de la ligne : position absolue dans la
   cellule N° (1re colonne, position:relative). Hors flux -> ne pousse ni le
   numéro ni la poubelle, qui restent centrés. C'est le handle SortableJS. */
.poste-drag-handle {
  position: absolute;
  /* Centree VISUELLEMENT entre le "+" (finit a 16px) et le numero (debute a
     35px) : boite de 12,7px dont 1px de letter-spacing en trainee a droite,
     d ou 20px plutot que 19,25px (centrage de boite). Mesure 2026-09-07. */
  left: 20px;
  top: 50%;
  transform: translateY(-50%);
  cursor: grab;
  color: #c2c8d2;
  font-size: 13px;
  line-height: 1;
  letter-spacing: 1px;        /* 2 colonnes de points distinctes (effet grip ⋮⋮) */
  user-select: none;
}
.poste-drag-handle:hover { color: var(--muted); }
.poste-drag-handle:active { cursor: grabbing; }
/* Le 🗑 reste un bouton cliquable (handle distinct = la poignée ⋮⋮). */
.postes-dropzone .row .poste-delete { cursor: pointer; }
/* Au survol, la poubelle file à droite de la cellule N° -> elle ne chevauche
   pas la poignée (absolue à gauche). Au repos, le numéro reste centré (aligné
   avec l'en-tête « N° »). */

/* États visuels SortableJS pendant le glisser. */
.poste-row-ghost {
  opacity: .45;
  background: #eef3ff;
}
.poste-row-chosen { background: #f4f7ff; }
.poste-row-dragging { box-shadow: 0 6px 18px rgba(15, 23, 42, .18); }

/* Zone vide : reste une cible de drop visible + invite explicite. */
.postes-dropzone--empty {
  min-height: 40px;
  margin: 2px 0;
  border: 1px dashed var(--border);
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.postes-dropzone--empty::after {
  content: "Glissez un poste ici, ou « + Ajouter un poste »";
  color: var(--muted);
  font-size: 12px;
  font-style: italic;
}

/* ---------------------------------------------------------------------------
   Lignes de texte libre intercalées entre les postes (modèle LigneTexte).
   .row-texte = ligne pleine largeur (override de la grille .row) : poignée +
   barre G/I/S/taille + éditeur contenteditable + suppression.
   --------------------------------------------------------------------------- */
.row.row-texte {
  display: block;
  position: relative;
  min-width: 1396px;
  /* gauche 85px = début aligné avec la désignation des postes (col-numero 76px
     + padding cellule). droite 40px = place pour le bouton supprimer. */
  padding: 8px 40px 8px 85px;
  background: #fff;           /* fond blanc (choix utilisateur) */
  border-top: 1px solid #f0f2f6;
  border-bottom: 1px solid #f0f2f6;
}
/* Poignée de glisse à l'extrême gauche (zone du N°), toujours visible. */
.row-texte .poste-drag-handle {
  position: absolute;
  left: 3px;          /* aligné sur la poignée des postes (offset 3px) */
  top: 50%;
  transform: translateY(-50%);
  display: block;
  cursor: grab;
}
/* Barre de mise en forme : flottante, révélée UNIQUEMENT pendant l'édition
   (focus dans la ligne) -> ne pousse plus le texte. Posée sous le début du
   texte. */
.rt-toolbar {
  position: absolute;
  left: 85px;
  bottom: calc(100% - 5px);   /* AU-DESSUS du texte -> ne masque pas les boutons
                                 d'ajout en bas de zone (vue par zone). */
  z-index: 6;
  display: none;
  align-items: center;
  gap: 3px;
  padding: 4px 6px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: 0 5px 16px rgba(15, 23, 42, 0.16);
}
.row-texte:focus-within .rt-toolbar { display: inline-flex; }
.rt-btn {
  width: 22px;
  height: 22px;
  border: 1px solid var(--border);
  background: var(--surface);
  border-radius: 4px;
  cursor: pointer;
  font-size: 12px;
  line-height: 1;
  color: var(--text);
  font-family: inherit;
  padding: 0;
}
.rt-btn:hover { background: #eef3ff; border-color: var(--blue); }
.rt-size {
  width: 46px;
  height: 22px;
  border: 1px solid var(--border);
  border-radius: 4px;
  font-size: 11px;
  padding: 0 4px;
  font-family: inherit;
}
/* Sélecteur de couleur du texte : pastille carrée alignée sur la barre. */
.rt-color {
  width: 24px;
  height: 22px;
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1px;
  cursor: pointer;
  background: var(--surface);
}
.rt-color::-webkit-color-swatch-wrapper { padding: 0; }
.rt-color::-webkit-color-swatch { border: none; border-radius: 2px; }
.rt-color::-moz-color-swatch { border: none; border-radius: 2px; }
.rt-editor,
.rt-content {
  font-size: 13px;
  color: var(--text);
  white-space: pre-wrap;
  word-break: break-word;
}
.rt-editor {
  min-height: 22px;
  padding: 2px 6px;
  margin-left: -6px;          /* compense le padding -> texte calé sur 85px */
  border: 1px dashed transparent;
  border-radius: 4px;
  outline: none;
}
.rt-editor:hover { border-color: #cdd9f5; }
.rt-editor:focus { border-color: var(--blue); border-style: solid; background: #fff; }
.rt-editor:empty::before {
  content: attr(data-placeholder);
  color: var(--muted);
  font-style: italic;
}
.ligne-texte-delete {
  position: absolute;
  left: 21px;        /* aligné sur la poubelle des postes (offset 21px au survol) */
  top: 50%;
  transform: translateY(-50%);
  background: transparent;
  border: 1px solid transparent;
  color: var(--danger);
  cursor: pointer;
  font-size: 12px;
  padding: 1px 3px;
  border-radius: 3px;
  line-height: 1;
  opacity: 0;                       /* visible uniquement au survol de la ligne */
  transition: opacity 0.12s ease;
}
.row-texte:hover .ligne-texte-delete { opacity: 1; }
.ligne-texte-delete:hover { background: var(--danger-bg); border-color: rgba(214, 69, 69, 0.3); }

/* Bouton "+ Insérer texte" (barre d'ajout poste + header de zone). */
.btn-add-texte {
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 600;
  font-family: inherit;
  background: #f4f7ff;
  color: var(--blue-2);
  border: 1px solid #cdd9f5;
  border-radius: 6px;
  cursor: pointer;
}
.btn-add-texte:hover { background: #e6eeff; border-color: var(--blue); }
.btn-add-texte:disabled { opacity: .5; cursor: not-allowed; }

/* ============================================================
   PILOTAGE PROJET (phase Travaux) — 5 briques colorées + édition inline.
   Design porté de la maquette validée en juillet 2026.
   Tout est scopé sous .pilotage pour éviter les collisions globales.
   ============================================================ */
.pilotage {
    --pil-line: #e2e7f1;
    --pil-line2: #eef1f7;
    --pil-ink: #182034;
    --pil-ink2: #5b6580;
    --pil-ink3: #94a0b8;
    --pil-card2: #f7f9fc;
}
.pilotage .t-exc { color: #0f7a37; }
.pilotage .t-good { color: #4f9d2b; }
.pilotage .t-low { color: #c07d0a; }
.pilotage .t-neg { color: #d42a2a; }

/* KPIs */
.pil-kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin: 18px 0 20px; }
.pil-kpi { background: #fff; border: 1px solid var(--pil-line); border-radius: 14px; padding: 15px 17px; box-shadow: 0 1px 2px rgba(20,27,46,.05), 0 4px 16px rgba(20,27,46,.05); }
.pil-kpi .l { font-size: 12.5px; color: var(--pil-ink2); }
.pil-kpi .v { font-size: 23px; font-weight: 600; margin-top: 7px; letter-spacing: -.5px; font-variant-numeric: tabular-nums; }
.pil-kpi .sub { font-size: 12px; color: var(--pil-ink3); margin-top: 3px; }
.pil-kpi.brut { background: #e7f5ec; border-color: transparent; }
.pil-kpi.brut .l, .pil-kpi.brut .v, .pil-kpi.brut .sub { color: #1f8a4c; }

/* Légende marge (4 paliers) : en colonne (aligne les 2 lignes de bascules). */
.pil-legend { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; font-size: 12px; color: var(--pil-ink2); background: #fff; border: 1px solid var(--pil-line); border-radius: 10px; padding: 10px 14px; }
.pil-legend b { color: var(--pil-ink); font-weight: 600; margin-bottom: 1px; }
.pil-legend .lg { display: inline-flex; align-items: center; gap: 7px; }
.pil-legend .lg i { width: 24px; height: 7px; border-radius: 4px; display: inline-block; }
.g-exc { background: #21a34a; }
.g-good { background: #7ab52f; }
.g-low { background: #e08a0b; }
.g-neg { background: #e04747; }

/* Briques (tuiles indépendantes) — couleur d'identité par brique */
.pilotage .brique { background: #fff; border: 1px solid var(--pil-line); border-left: 5px solid var(--acc, var(--pil-line)); border-radius: 14px; overflow: hidden; box-shadow: 0 1px 2px rgba(20,27,46,.05), 0 4px 16px rgba(20,27,46,.05); margin-bottom: 18px; }
.pilotage .brique-head { display: flex; align-items: center; gap: 12px; padding: 13px 18px; border-bottom: 1px solid var(--pil-line); background: var(--accbg, var(--pil-card2)); }
.pilotage .brique-title { font-size: 16px; font-weight: 600; color: var(--acc, var(--pil-ink)); display: flex; align-items: center; gap: 10px; margin: 0; }
.pilotage .brique-title::before { content: ""; width: 11px; height: 11px; border-radius: 3px; background: var(--acc, var(--pil-ink3)); flex: 0 0 auto; }
.br-tr { --acc: #2f6df0; --accbg: #eef3ff; }
.br-ftm { --acc: #0e93a3; --accbg: #e3f5f7; }
.br-hon { --acc: #7a53e3; --accbg: #f0ebfd; }
.br-ass { --acc: #bf7a08; --accbg: #faefd6; }
.br-div { --acc: #586576; --accbg: #eceff4; }

/* Table */
.pil-tablewrap { overflow-x: auto; }
.pil-table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.pil-table th { font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em; color: var(--pil-ink3); font-weight: 500; text-align: right; padding: 10px 14px; background: var(--pil-card2); border-bottom: 1px solid var(--pil-line); white-space: nowrap; }
.pil-table th.l { text-align: left; }
.pil-table td { padding: 6px 14px; border-bottom: 1px solid var(--pil-line2); font-size: 13.5px; text-align: right; vertical-align: middle; color: var(--pil-ink); }
.pil-table td.l { text-align: left; }
.pil-table td.num { white-space: nowrap; }
.pil-table td.neg { color: #d42a2a; }
.pil-table tbody tr:last-child td { border-bottom: 0; }
.pil-lg > td { padding: 9px 14px; }
.pil-lg .pil-badge { font-size: 10.5px; color: var(--pil-ink3); font-weight: 400; margin-left: 3px; }
/* Repli/dépli des lignes portant des dépenses (chevron devant la désignation).
   CSS aligné sur la maquette (.ln flex + gap 9px ; chevron .chev ▶ qui pivote
   à 90° quand déplié). État déplié par défaut -> chevron pointe vers le bas. */
.pil-ln { display: flex; align-items: center; gap: 9px; }
.pil-chev { color: var(--pil-ink3); font-size: 11px; transition: transform .18s; width: 10px; display: inline-block; flex: 0 0 auto; transform: rotate(90deg); border: 0; background: transparent; padding: 0; line-height: 1; cursor: pointer; text-align: left; }
.pil-chev:hover { color: var(--pil-ink); }
.pil-lg.is-collapsed .pil-chev { transform: none; }
.pil-chev-spacer { width: 10px; flex: 0 0 auto; display: inline-block; }
/* Seules les colonnes Marge € / % sont en gras (les autres restent normales). */
.pil-mg { font-weight: 700; }
.pil-dep > td { background: var(--pil-card2); }
.pil-dep td.l1 { padding-left: 30px; }
/* Montant d'une dépense (Tableau) : italique + fin du nombre alignée sur la
   colonne Achat. Les nombres statiques sont à 14px du bord de cellule ; l'input
   a 7px de padding + 1px de bordure -> on le décale de 8px vers la droite. */
.pil-dep .pil-in.num.r { font-style: italic; margin-right: -8px; }
/* Sous-total : même hauteur de ligne que l'en-tête de tuile (.brique-head). */
.pil-sub > td { padding: 13px 14px; border-top: 2px solid var(--pil-line); background: var(--accbg, var(--pil-card2)); }
.pil-sub > td.l { font-weight: 700; }
.pil-empty td { color: var(--pil-ink3); font-style: italic; text-align: center; padding: 12px; }
/* États vides des cartes : ligne discrète + bloc « riche » (honoraires). */
.pil-cardsec p.pil-empty { padding: 12px 18px; margin: 0 12px; color: var(--pil-ink3); font-style: italic; font-size: 12.5px; }
.pil-empty-rich { display: flex; align-items: center; gap: 13px; margin: 4px 12px 8px; padding: 15px 18px; background: var(--pil-card2); border: 1px dashed var(--pil-line); border-radius: 12px; }
.pil-empty-ic { width: 26px; height: 26px; fill: none; stroke: var(--pil-ink3); stroke-width: 1.5; stroke-linejoin: round; stroke-linecap: round; flex: 0 0 auto; }
.pil-empty-txt { display: flex; flex-direction: column; gap: 2px; }
.pil-empty-title { font-weight: 600; color: var(--pil-ink); font-size: 13.5px; }
.pil-empty-sub { font-size: 12px; color: var(--pil-ink3); line-height: 1.4; max-width: 60ch; }
.pil-addrow > td { background: var(--pil-card2); padding: 4px 14px 8px 30px; }
.pil-lg.alerte > td { background: #fcf4f4; }
.pilotage .vfy.ok { color: #1f8a4c; }
.pilotage .vfy.err { color: #d42a2a; }

/* Inputs inline */
.pil-in { border: 1px solid transparent; background: transparent; font: inherit; color: inherit; padding: 4px 7px; border-radius: 7px; font-variant-numeric: tabular-nums; max-width: 100%; }
.pil-in:hover { background: #fff; border-color: var(--pil-line); }
.pil-in:focus { outline: none; background: #fff; border-color: #3b6ef5; box-shadow: 0 0 0 3px #eaf0ff; }
.pil-in.num.r { text-align: right; width: 120px; }
.pil-in.pil-ent { min-width: 150px; }
.pil-in.pil-cmd { width: 120px; }
.pil-in.pil-cmt { min-width: 180px; font-style: italic; }
.pil-meta { display: inline-flex; align-items: center; gap: 4px; margin-left: 6px; font-size: 12px; color: var(--pil-ink3); }
.pil-pfx { color: var(--pil-ink3); font-size: 11px; }

/* Statut (select pilule) */
.pil-statut { border: 0; border-radius: 20px; padding: 4px 9px; font-size: 11px; font-weight: 500; font-family: inherit; cursor: pointer; -webkit-appearance: none; appearance: none; }
.pil-statut.s-valide { background: #e7f5ec; color: #1f8a4c; }
.pil-statut.s-commander { background: #e8f0fe; color: #2f6df0; }
.pil-statut.s-negociation { background: #f9f0dc; color: #b0730a; }
.pil-statut.s-clarifier { background: #fcebeb; color: #d92d2d; }
.pil-statut.s-previsionnel { background: #f0ebfd; color: #7a53e3; }

/* Boutons ajouter / supprimer */
/* « Ajouter … » : pastille « + » RONDE blanche sur fond bleu + libellé bleu
   sans fond (moins massif). Le « + » est dessiné par 2 barres blanches en
   dégradé -> centrage géométrique parfait (le glyphe "+" apparaît décalé). */
.pil-add { display: inline-flex; align-items: center; gap: 8px; background: transparent; border: 0; color: #3b6ef5; font-size: 12.5px; padding: 4px 8px 4px 4px; border-radius: 8px; cursor: pointer; font-family: inherit; }
.pil-add::before { content: ""; flex: 0 0 auto; width: 18px; height: 18px; border-radius: 50%; background: linear-gradient(#fff, #fff) center / 9px 2px no-repeat, linear-gradient(#fff, #fff) center / 2px 9px no-repeat, #3b6ef5; }
.pil-add:hover { background: var(--pil-card2); }
.pil-add:hover::before { background: linear-gradient(#fff, #fff) center / 9px 2px no-repeat, linear-gradient(#fff, #fff) center / 2px 9px no-repeat, #2f5fd6; }
.pil-add.head { margin-left: auto; }
/* « + dépense » compact dans la barre du lot (Travaux / Honoraires) :
   + blanc sur fond bleu plein, aligné à droite dans la dernière colonne. */
.pil-adddep { display: inline-flex; align-items: center; gap: 5px; background: #3b6ef5; border: 0; color: #fff; font-size: 12px; padding: 5px 11px; border-radius: 8px; cursor: pointer; font-family: inherit; white-space: nowrap; }
.pil-adddep:hover { background: #2f5fd6; }
.pil-del { background: transparent; border: 0; color: var(--pil-ink3); cursor: pointer; font-size: 14px; padding: 3px 6px; line-height: 1; }
.pil-del:hover { color: #d42a2a; }
.pil-actions { white-space: nowrap; }
.pil-flag { white-space: nowrap; }

@media (max-width: 900px) {
    .pil-kpis { grid-template-columns: repeat(2, 1fr); }
}

/* Pilotage — bascules Tableau/Cartes + Par lot/entreprise */
/* Barre d'outils : bascules sur 2 lignes à gauche + légende à droite. */
.pil-toolbar { display: flex; justify-content: space-between; align-items: flex-start; gap: 14px 24px; flex-wrap: wrap; margin: 4px 0 16px; }
.pil-toolbar-segs { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
.pil-seg { display: inline-flex; background: var(--pil-card2); border: 1px solid var(--pil-line); border-radius: 10px; padding: 3px; gap: 3px; }
/* Toggle « Par lot / Par entreprise » posé dans l'en-tête de la tuile Travaux
   (le groupement ne concerne que cette section) : à droite, fond blanc, compact. */
.pil-seg-head { margin-left: auto; background: #fff; }
.pil-seg-head .pil-segbtn { font-size: 12px; padding: 4px 11px; }
.pil-segbtn { border: 0; background: transparent; color: var(--pil-ink2); font-size: 13px; padding: 6px 13px; border-radius: 7px; cursor: pointer; font-family: inherit; text-decoration: none; display: inline-flex; align-items: center; gap: 7px; }
.pil-segico { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.4; flex: 0 0 auto; }
.pil-segbtn.on { background: #fff; color: var(--pil-ink); font-weight: 500; box-shadow: 0 1px 2px rgba(20,27,46,.08); }
.pil-segbtn:hover:not(.on):not(.disabled) { color: var(--pil-ink); }
.pil-segbtn.disabled { color: var(--pil-ink3); opacity: .5; cursor: not-allowed; pointer-events: none; }

/* Pilotage — vue CARTES */
.pil-cardsec { background: #fff; border: 1px solid var(--pil-line); border-left: 5px solid var(--acc, var(--pil-line)); border-radius: 14px; box-shadow: 0 1px 2px rgba(20,27,46,.05), 0 4px 16px rgba(20,27,46,.05); margin-bottom: 18px; padding-bottom: 6px; overflow: hidden; }
.pil-cardsec-head { display: flex; align-items: center; gap: 12px; padding: 13px 18px; border-bottom: 1px solid var(--pil-line); background: var(--accbg, var(--pil-card2)); }
.pil-cardsec-sub { padding: 10px 18px 4px; font-size: 12.5px; color: var(--pil-ink2); }
.pil-cardsec-sub b { color: var(--pil-ink); }
.pil-card { border-bottom: 1px solid var(--pil-line2); margin: 0 12px; }
.pil-card:last-of-type { border-bottom: 0; }
.pil-card-head { display: flex; align-items: center; gap: 14px; padding: 11px 6px; cursor: pointer; list-style: none; }
.pil-card-head::-webkit-details-marker { display: none; }
.pil-card-head::before { content: "▸"; color: var(--pil-ink3); font-size: 11px; transition: transform .15s; flex: 0 0 auto; }
details.pil-card[open] > .pil-card-head::before { transform: rotate(90deg); }
.pil-card-title { font-weight: 500; flex: 1; min-width: 0; }
.pil-card-kpi { font-size: 12.5px; color: var(--pil-ink2); white-space: nowrap; font-variant-numeric: tabular-nums; }
.pil-card-kpi .k { color: var(--pil-ink3); font-size: 11px; text-transform: uppercase; letter-spacing: .03em; margin-right: 3px; }
.pil-card-marge { font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums; }
.pil-card-body { padding: 4px 6px 12px 22px; display: flex; flex-direction: column; gap: 6px; }
/* Bouton « ＋ Ajouter » dans une carte : compact, aligné à gauche (sinon le
   flex-column l'étire sur toute la largeur). */
.pil-card-body .pil-add { align-self: flex-start; font-size: 12px; }
.pil-cdep, .pil-ccout { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.pil-cdep-lot { min-width: 150px; color: var(--pil-ink2); }
/* Ligne dépense carte : N° (compact) + commentaire (extensible pousse montant/
   statut à droite). Ordre partout : entité / N° / commentaire / montant / statut. */
.pil-cdep-num { display: inline-flex; align-items: center; gap: 4px; }
.pil-cdep-cmt { display: inline-flex; align-items: center; gap: 4px; flex: 1; min-width: 160px; }
.pil-cdep-cmt .pil-cmt { flex: 1; }
.pil-ccout .pil-cmt { flex: 1; }
.pil-card.alerte > .pil-card-head { background: #fcf4f4; }

/* Vue « Par entreprise » : sélecteur de lot inline + ligne d'ajout (affecte
   une nouvelle dépense à une entreprise + un lot). */
.pil-dep-arrow { color: var(--pil-ink3); margin-right: 2px; }
.pil-lotsel { min-width: 150px; -webkit-appearance: menulist; appearance: menulist; cursor: pointer; }
.pil-addent { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 2px 0; }
.pil-addent .pil-ent { min-width: 180px; }
.pil-addent .pil-lotsel { min-width: 170px; }

/* ============================================================
   FTM — Fiches de Travaux Modificatifs (phase Travaux, bloc 3).
   Mini-chiffrage isolé d'un avenant. Identité teal (dito brique
   FTM du Pilotage). Scopé sous .ftm-page / .ftm-editor.
   ============================================================ */
.ftm-page {
    --ftm-acc: #0e93a3;
    --ftm-acc-2: #0b7d8a;
    --ftm-accbg: #e3f5f7;
    --ftm-line: #e2e7f1;
    --ftm-line2: #eef1f7;
    --ftm-ink: #182034;
    --ftm-ink2: #5b6580;
    --ftm-ink3: #94a0b8;
    --ftm-card2: #f7f9fc;
}

/* ---- Liste des FTM ---- */
.ftm-list { max-width: 1080px; margin: 0 auto; }
.ftm-list-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; margin: 20px 0 22px; }
.ftm-list-title { font-size: 20px; font-weight: 700; color: var(--ftm-ink); margin: 0 0 4px; letter-spacing: -.3px; }
.ftm-list-sub { font-size: 13px; color: var(--ftm-ink2); margin: 0; max-width: 560px; line-height: 1.5; }
.ftm-create-form { flex: 0 0 auto; }

.ftm-btn-primary { display: inline-flex; align-items: center; gap: 8px; background: var(--ftm-acc); color: #fff; border: 0; border-radius: 10px; padding: 10px 16px; font-size: 14px; font-weight: 600; cursor: pointer; box-shadow: 0 1px 2px rgba(20,27,46,.08), 0 4px 14px rgba(14,147,163,.22); transition: background .12s; }
.ftm-btn-primary:hover { background: var(--ftm-acc-2); }
.ftm-btn-plus { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 50%; background: rgba(255,255,255,.22); font-size: 15px; line-height: 1; }

.ftm-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 15px; }
.ftm-card { position: relative; background: #fff; border: 1px solid var(--ftm-line); border-left: 5px solid var(--ftm-acc); border-radius: 13px; box-shadow: 0 1px 2px rgba(20,27,46,.05), 0 4px 16px rgba(20,27,46,.05); overflow: hidden; transition: box-shadow .12s, transform .12s; }
.ftm-card:hover { box-shadow: 0 2px 4px rgba(20,27,46,.08), 0 8px 24px rgba(20,27,46,.10); transform: translateY(-1px); }
.ftm-card-main { display: block; padding: 15px 16px 16px; text-decoration: none; color: inherit; }
.ftm-card-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 9px; padding-right: 26px; }
.ftm-card-num { font-size: 13px; font-weight: 700; color: var(--ftm-acc-2); letter-spacing: .01em; }
.ftm-card-libelle { font-size: 15px; font-weight: 600; color: var(--ftm-ink); margin-bottom: 14px; line-height: 1.35; min-height: 20px; }
.ftm-card-total { display: flex; align-items: baseline; justify-content: space-between; border-top: 1px solid var(--ftm-line2); padding-top: 10px; }
.ftm-card-total .lbl { font-size: 11.5px; color: var(--ftm-ink3); }
.ftm-card-total .val { font-size: 17px; font-weight: 700; color: var(--ftm-ink); font-variant-numeric: tabular-nums; }
.ftm-card-del { position: absolute; top: 10px; right: 10px; }
.ftm-card-del button { background: transparent; border: 0; cursor: pointer; font-size: 14px; opacity: .35; padding: 4px; border-radius: 6px; transition: opacity .12s, background .12s; }
.ftm-card-del button:hover { opacity: 1; background: var(--danger-bg); }
.ftm-card-lock { position: absolute; top: 10px; right: 10px; padding: 4px; color: var(--ftm-ink3); opacity: .8; cursor: not-allowed; display: inline-flex; }

/* Badge statut */
.ftm-badge { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; padding: 3px 8px; border-radius: 20px; white-space: nowrap; }
.ftm-badge--brouillon { background: #eef1f7; color: #6b7690; }
.ftm-badge--valide { background: #e2f5ea; color: #1f8a4c; }

/* État vide */
.ftm-empty { text-align: center; padding: 56px 20px; background: #fff; border: 1px dashed var(--ftm-line); border-radius: 14px; color: var(--ftm-ink2); }
.ftm-empty-ico { font-size: 34px; margin-bottom: 10px; }
.ftm-empty-title { font-size: 16px; font-weight: 600; color: var(--ftm-ink); margin: 0 0 5px; }
.ftm-empty-sub { font-size: 13px; margin: 0 auto; max-width: 420px; line-height: 1.5; }

/* ---- Éditeur d'une FTM ---- */
.ftm-editor { max-width: 1180px; margin: 0 auto; }
.ftm-ed-head { margin: 18px 0 14px; }
.ftm-back { display: inline-block; font-size: 12.5px; color: var(--ftm-ink2); text-decoration: none; margin-bottom: 10px; }
.ftm-back:hover { color: var(--ftm-acc-2); }
.ftm-ed-titlerow { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.ftm-ed-num { font-size: 20px; font-weight: 700; color: var(--ftm-ink); letter-spacing: -.3px; }
.ftm-ed-libelle { width: 100%; max-width: 640px; font-size: 15px; padding: 9px 13px; border: 1px solid var(--ftm-line); border-radius: 9px; color: var(--ftm-ink); background: #fff; }
.ftm-ed-libelle:focus { outline: none; border-color: var(--ftm-acc); box-shadow: 0 0 0 3px rgba(14,147,163,.14); }

/* Bandeau de totaux */
.ftm-ed-totals { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin: 0 0 20px; }
.ftm-tot { background: #fff; border: 1px solid var(--ftm-line); border-radius: 12px; padding: 12px 15px; }
.ftm-tot .l { display: block; font-size: 11.5px; color: var(--ftm-ink2); margin-bottom: 5px; }
.ftm-tot .v { font-size: 19px; font-weight: 700; color: var(--ftm-ink); font-variant-numeric: tabular-nums; letter-spacing: -.4px; }
.ftm-tot--hl { background: var(--ftm-accbg); border-color: transparent; }
.ftm-tot--hl .l, .ftm-tot--hl .v { color: var(--ftm-acc-2); }

/* Tuiles */
.ftm-tuile { background: #fff; border: 1px solid var(--ftm-line); border-radius: 14px; box-shadow: 0 1px 2px rgba(20,27,46,.05), 0 4px 16px rgba(20,27,46,.05); padding: 16px 18px 18px; margin-bottom: 18px; }
.ftm-tuile-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 14px; }
.ftm-tuile-head h3 { font-size: 15px; font-weight: 700; color: var(--ftm-ink); margin: 0; display: flex; align-items: center; gap: 9px; }
.ftm-tuile-head h3::before { content: ""; width: 10px; height: 10px; border-radius: 3px; background: var(--ftm-acc); }
.ftm-tuile-hint { font-size: 12px; color: var(--ftm-ink3); }
.ftm-tuile-empty { font-size: 13px; color: var(--ftm-ink3); font-style: italic; padding: 10px 2px; margin: 0; }
.ftm-warn { font-size: 12.5px; color: #9a6a00; background: #fbf3e0; border: 1px solid #f0e0bb; border-radius: 9px; padding: 9px 13px; margin: 0 0 14px; }

/* Lot FTM */
.ftm-lot { border: 1px solid var(--ftm-line); border-radius: 11px; margin-bottom: 14px; overflow: hidden; }
.ftm-lot-head { display: flex; align-items: center; gap: 12px; background: var(--ftm-card2); padding: 9px 13px; border-bottom: 1px solid var(--ftm-line); }
.ftm-lot-nom { font-size: 13.5px; font-weight: 700; color: var(--ftm-ink); flex: 1 1 auto; }
.ftm-lot-total { font-size: 13.5px; font-weight: 700; color: var(--ftm-acc-2); font-variant-numeric: tabular-nums; }
.ftm-lot-del { background: transparent; border: 0; cursor: pointer; font-size: 13px; opacity: .4; padding: 3px 5px; border-radius: 6px; }
.ftm-lot-del:hover { opacity: 1; background: var(--danger-bg); }
.ftm-lot-tablewrap { overflow-x: auto; }

/* Table des postes */
.ftm-postes-table { width: 100%; border-collapse: collapse; }
.ftm-postes-table th { font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--ftm-ink3); font-weight: 600; text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--ftm-line); white-space: nowrap; }
.ftm-postes-table td { padding: 5px 10px; border-bottom: 1px solid var(--ftm-line2); vertical-align: middle; }
.ftm-postes-table tbody tr:last-child td { border-bottom: 0; }
.ftm-postes-table .c-pu, .ftm-postes-table th.c-pu, .ftm-postes-table .c-marge, .ftm-postes-table th.c-marge, .ftm-postes-table .c-qte, .ftm-postes-table th.c-qte, .ftm-postes-table .c-total, .ftm-postes-table th.c-total { text-align: right; }
.ftm-postes-table .c-qte { font-variant-numeric: tabular-nums; color: var(--ftm-ink2); font-size: 13px; }
.ftm-postes-table .c-total { font-variant-numeric: tabular-nums; font-weight: 600; color: var(--ftm-ink); font-size: 13.5px; white-space: nowrap; }

.ftm-postes-table input[type="text"], .ftm-postes-table select { width: 100%; border: 1px solid transparent; border-radius: 7px; padding: 6px 8px; font-size: 13px; color: var(--ftm-ink); background: transparent; }
.ftm-postes-table input[type="text"]:hover, .ftm-postes-table select:hover { border-color: var(--ftm-line); }
.ftm-postes-table input[type="text"]:focus, .ftm-postes-table select:focus { outline: none; border-color: var(--ftm-acc); background: #fff; box-shadow: 0 0 0 3px rgba(14,147,163,.12); }
.ftm-postes-table .c-desig { min-width: 200px; }
.ftm-postes-table .c-desig input { font-weight: 500; }
.ftm-postes-table .c-pu input, .ftm-postes-table .c-marge input, .ftm-postes-table .c-qte { text-align: right; }
.ftm-postes-table .c-pu { width: 100px; }
.ftm-postes-table .c-marge { width: 78px; }
.ftm-postes-table .c-unite { width: 92px; }

/* Grille de saisie qté par zone */
.ftm-zonegrid { display: flex; flex-wrap: wrap; gap: 6px; }
.ftm-zoneinp { display: inline-flex; flex-direction: column; gap: 2px; }
.ftm-zoneinp .z { font-size: 10px; color: var(--ftm-ink3); padding-left: 2px; max-width: 74px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ftm-zoneinp input { width: 62px; text-align: right; border: 1px solid var(--ftm-line) !important; border-radius: 6px; padding: 4px 6px; font-size: 12.5px; background: #fff; }
.ftm-zoneinp input:focus { border-color: var(--ftm-acc) !important; box-shadow: 0 0 0 2px rgba(14,147,163,.14); }
.ftm-zones-none { color: var(--ftm-ink3); }

/* Flags ±value / option */
.ftm-postes-table .c-flags { white-space: nowrap; }
.ftm-flag { border: 1px solid var(--ftm-line); background: #fff; color: var(--ftm-ink2); border-radius: 7px; padding: 4px 8px; font-size: 12px; font-weight: 600; cursor: pointer; margin-right: 3px; transition: all .1s; }
.ftm-flag:hover { border-color: var(--ftm-ink3); }
.ftm-flag.on { background: var(--ftm-acc); border-color: var(--ftm-acc); color: #fff; }
.ftm-poste-row.is-mv .c-total { color: var(--danger); }
.ftm-poste-row.is-opt { background: #fbfbf4; }
.ftm-poste-del, .ftm-hono-del { background: transparent; border: 0; cursor: pointer; font-size: 13px; opacity: .4; padding: 4px 5px; border-radius: 6px; }
.ftm-poste-del:hover, .ftm-hono-del:hover { opacity: 1; background: var(--danger-bg); }
.ftm-poste-empty td { color: var(--ftm-ink3); font-style: italic; font-size: 12.5px; }

/* Boutons fantômes (ajout) */
.ftm-btn-ghost { display: inline-flex; align-items: center; gap: 6px; background: transparent; border: 1px dashed var(--ftm-line); color: var(--ftm-acc-2); border-radius: 9px; padding: 7px 13px; font-size: 13px; font-weight: 600; cursor: pointer; transition: all .12s; }
.ftm-btn-ghost:hover { border-color: var(--ftm-acc); background: var(--ftm-accbg); }
.ftm-addposte { margin: 10px 13px 12px; }

/* Barre d'ajout de lot */
.ftm-addlot { display: flex; align-items: center; flex-wrap: wrap; gap: 9px; margin-top: 6px; padding-top: 14px; border-top: 1px dashed var(--ftm-line); }
.ftm-addlot-select { border: 1px solid var(--ftm-line); border-radius: 9px; padding: 8px 11px; font-size: 13px; color: var(--ftm-ink); background: #fff; min-width: 220px; }
.ftm-addlot-select:focus { outline: none; border-color: var(--ftm-acc); }
.ftm-addlot-sep { font-size: 12px; color: var(--ftm-ink3); }
.ftm-addlot-custom { border: 1px solid var(--ftm-line); border-radius: 9px; padding: 8px 11px; font-size: 13px; color: var(--ftm-ink); background: #fff; min-width: 170px; }
.ftm-addlot-custom:focus { outline: none; border-color: var(--ftm-acc); }

/* Table honoraires */
.ftm-hono-table { width: 100%; border-collapse: collapse; margin-bottom: 12px; }
.ftm-hono-table th { font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--ftm-ink3); font-weight: 600; text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--ftm-line); }
.ftm-hono-table th.ftm-th-montant { text-align: right; }
.ftm-hono-table td { padding: 5px 10px; border-bottom: 1px solid var(--ftm-line2); vertical-align: middle; }
.ftm-hono-table tbody tr:last-child td { border-bottom: 0; }
.ftm-hono-table .ftm-th-desig { min-width: 260px; }
.ftm-hono-table .ftm-th-montant { width: 150px; }
.ftm-hono-table .ftm-th-act { width: 40px; }
.ftm-hono-table input { width: 100%; border: 1px solid transparent; border-radius: 7px; padding: 6px 8px; font-size: 13px; color: var(--ftm-ink); background: transparent; }
.ftm-hono-table input:hover { border-color: var(--ftm-line); }
.ftm-hono-table input:focus { outline: none; border-color: var(--ftm-acc); background: #fff; box-shadow: 0 0 0 3px rgba(14,147,163,.12); }
.ftm-hono-table .ftm-th-montant input { text-align: right; font-variant-numeric: tabular-nums; }

@media (max-width: 720px) {
    .ftm-list-head { flex-direction: column; }
    .ftm-ed-totals { grid-template-columns: repeat(2, 1fr); }
}

/* FTM — cycle validation (bloc 3.3) : barre d'action + verrou visuel. */
.ftm-actions { display: flex; align-items: center; gap: 14px; margin: 0 0 18px; flex-wrap: wrap; }
.ftm-lockbanner { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; color: #1f8a4c; background: #e2f5ea; border: 1px solid #b8e6cb; border-radius: 9px; padding: 8px 13px; }
.ftm-lockbanner .ico { font-size: 14px; }
.ftm-btn-validate { background: #1f8a4c; color: #fff; border: 0; border-radius: 9px; padding: 9px 16px; font-size: 14px; font-weight: 600; cursor: pointer; box-shadow: 0 1px 2px rgba(20,27,46,.08), 0 4px 14px rgba(31,138,76,.20); transition: background .12s; }
.ftm-btn-validate:hover { background: #18733f; }
.ftm-btn-outline { background: #fff; color: var(--ftm-acc-2); border: 1px solid var(--ftm-acc); border-radius: 9px; padding: 8px 15px; font-size: 13px; font-weight: 600; cursor: pointer; transition: background .12s; }
.ftm-btn-outline:hover { background: var(--ftm-accbg); }

/* Verrou visuel d'une FTM validée : saisies figées, contrôles d'ajout masqués.
   La garde serveur (ftm_edit._editable_or_403) est la vraie barrière ; ceci
   n'est que l'indication d'interface. La barre .ftm-actions reste active. */
.ftm-editor--locked .ftm-ed-libelle,
.ftm-editor--locked .ftm-postes-table input,
.ftm-editor--locked .ftm-postes-table select,
.ftm-editor--locked .ftm-zoneinp input,
.ftm-editor--locked .ftm-hono-table input,
.ftm-editor--locked .ftm-flag { pointer-events: none; opacity: .7; background: #f7f9fc; }
.ftm-editor--locked .ftm-poste-del,
.ftm-editor--locked .ftm-lot-del,
.ftm-editor--locked .ftm-hono-del,
.ftm-editor--locked .ftm-btn-ghost,
.ftm-editor--locked .ftm-addlot { display: none; }

/* Pilotage: FTM en lecture seule (bloc 3.4) — badge validée + lien éditeur. */
.pil-badge--ok { color: #1f8a4c; font-weight: 600; }
a.pil-add.head { text-decoration: none; }
.pil-ftm-edit { display: inline-block; font-size: 12px; color: #0e93a3; text-decoration: none; margin: 2px 0 8px; }
.pil-ftm-edit:hover { text-decoration: underline; }

/* FTM — choix de trame par lot (poste/zone), dito chiffrage. */
.ftm-trame { display: inline-flex; align-items: center; gap: 9px; padding: 6px 11px; border: 1px solid var(--ftm-line); border-radius: 9px; background: var(--ftm-card2); }
.ftm-trame-lbl { font-size: 12px; color: var(--ftm-ink3); }
.ftm-trame-opt { font-size: 12.5px; color: var(--ftm-ink2); display: inline-flex; align-items: center; gap: 4px; cursor: pointer; }
.ftm-trame-opt input { accent-color: var(--ftm-acc); }
.ftm-lot-trame { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--ftm-acc-2); background: var(--ftm-accbg); padding: 2px 7px; border-radius: 6px; margin-right: auto; cursor: help; }
/* Toggle de trame PAR LOT (segmented control compact) : visible quand le lot
   est encore vide. margin-right:auto -> pousse total + suppression à droite. */
.ftm-lot-trametog { display: inline-flex; gap: 2px; margin-right: auto; padding: 2px; background: var(--ftm-card2); border: 1px solid var(--ftm-line); border-radius: 7px; }
.ftm-lot-trametog label { display: inline-flex; align-items: center; font-size: 11px; font-weight: 600; color: var(--ftm-ink3); padding: 2px 9px; border-radius: 5px; cursor: pointer; transition: background .12s, color .12s; }
.ftm-lot-trametog label:hover { color: var(--ftm-ink); }
.ftm-lot-trametog input { position: absolute; opacity: 0; pointer-events: none; }
.ftm-lot-trametog label:has(input:checked) { background: var(--ftm-acc); color: #fff; }
.ftm-zonegroup { border-top: 1px solid var(--ftm-line); }
.ftm-zonegroup-head { font-size: 12px; font-weight: 700; color: var(--ftm-ink2); background: #fafbfd; padding: 7px 13px; }
.ftm-postes-table .c-qte1, .ftm-postes-table th.c-qte1 { width: 120px; text-align: right; }
.ftm-postes-table .c-qte1 input { text-align: right; border: 1px solid var(--ftm-line) !important; border-radius: 6px; background: #fff; }
.ftm-postes-table .c-qte1 input:focus { border-color: var(--ftm-acc) !important; box-shadow: 0 0 0 2px rgba(14,147,163,.14); }

/* ============================================================
   SITUATIONS — facturation à l'avancement (phase Travaux, bloc 4).
   Onglet + panneau « Paramètres du marché » (RG déplacée, acompte, paliers).
   ============================================================ */
.situations-page {
    --situ-acc: #5b57d6;
    --situ-acc-2: #4a46b8;
    --situ-accbg: #edecfb;
    --situ-line: #e2e7f1;
    --situ-line2: #eef1f7;
    --situ-ink: #182034;
    --situ-ink2: #5b6580;
    --situ-ink3: #94a0b8;
    --situ-card2: #f7f9fc;
}
/* 2 colonnes : à GAUCHE la liste des situations (cartes empilées à la
   verticale), à DROITE les paramètres du marché (RG, acompte, paliers).
   Sous 900px -> 1 colonne (cf. demande 2026-07-21). */
.situ-layout { max-width: 1120px; margin: 0 auto; display: grid; grid-template-columns: minmax(0, 320px) minmax(0, 1fr); gap: 24px; align-items: start; }
.situ-layout > #modal-container { grid-column: 1 / -1; }
@media (max-width: 900px) { .situ-layout { grid-template-columns: 1fr; } }

/* Liste des situations (placeholder 4.1 -> saisie en 4.2) */
.situ-list-head { margin: 20px 0 14px; }
.situ-list-title { font-size: 20px; font-weight: 700; color: var(--situ-ink); margin: 0 0 4px; letter-spacing: -.3px; }
.situ-list-sub { font-size: 13px; color: var(--situ-ink2); margin: 0; max-width: 620px; line-height: 1.5; }
.situ-empty { text-align: center; padding: 40px 20px; background: #fff; border: 1px dashed var(--situ-line); border-radius: 14px; color: var(--situ-ink2); margin-bottom: 26px; }
.situ-empty-ico { font-size: 30px; margin-bottom: 8px; }
.situ-empty-title { font-size: 15px; font-weight: 600; color: var(--situ-ink); margin: 0 0 4px; }
.situ-empty-sub { font-size: 12.5px; margin: 0; }

/* Panneau Paramètres du marché */
.situ-params { display: block; }
/* Espace sous l'encart Retenue de garantie (sinon collé à « Acompte »). */
#situations-params .retenue-rg-block { margin-bottom: 16px; }
.situ-params-title { font-size: 16px; font-weight: 700; color: var(--situ-ink); margin: 0 0 14px; display: flex; align-items: center; gap: 9px; }
.situ-params-title::before { content: ""; width: 10px; height: 10px; border-radius: 3px; background: var(--situ-acc); }

.situ-tuile { background: #fff; border: 1px solid var(--situ-line); border-radius: 14px; box-shadow: 0 1px 2px rgba(20,27,46,.05), 0 4px 16px rgba(20,27,46,.05); padding: 16px 18px 18px; margin-bottom: 16px; }
.situ-tuile-title { font-size: 14.5px; font-weight: 700; color: var(--situ-ink); margin: 0 0 4px; }
.situ-tuile-hint { font-size: 12px; color: var(--situ-ink3); margin: 0 0 12px; line-height: 1.45; }
.situ-tuile-empty { font-size: 13px; color: var(--situ-ink3); font-style: italic; margin: 0 0 12px; }

/* Acompte */
.situ-check { display: inline-flex; align-items: center; gap: 8px; font-size: 13.5px; font-weight: 600; color: var(--situ-ink); cursor: pointer; }
.situ-check input { accent-color: var(--situ-acc); width: 16px; height: 16px; }
.situ-acompte-sub { margin-top: 12px; display: flex; flex-direction: column; gap: 10px; transition: opacity .12s; }
.situ-acompte-sub.is-disabled { opacity: .45; pointer-events: none; }
.situ-field-row { display: flex; flex-wrap: wrap; gap: 16px; align-items: flex-end; }
.situ-field { display: inline-flex; align-items: center; gap: 7px; font-size: 13px; color: var(--situ-ink2); }
.situ-num { width: 78px; text-align: right; border: 1px solid var(--situ-line); border-radius: 8px; padding: 6px 9px; font-size: 13px; color: var(--situ-ink); font-variant-numeric: tabular-nums; }
.situ-num:focus { outline: none; border-color: var(--situ-acc); box-shadow: 0 0 0 3px rgba(91,87,214,.14); }
.situ-select { border: 1px solid var(--situ-line); border-radius: 8px; padding: 6px 9px; font-size: 13px; color: var(--situ-ink); background: #fff; }
.situ-select:focus { outline: none; border-color: var(--situ-acc); }
.situ-field .suffix { color: var(--situ-ink3); font-size: 12.5px; }

/* Paliers */
.situ-paliers-table { width: 100%; border-collapse: collapse; margin-bottom: 12px; }
.situ-paliers-table th { font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--situ-ink3); font-weight: 600; text-align: left; padding: 7px 8px; border-bottom: 1px solid var(--situ-line); }
.situ-paliers-table th.num { text-align: right; }
.situ-paliers-table td { padding: 5px 8px; border-bottom: 1px solid var(--situ-line2); vertical-align: middle; }
.situ-paliers-table td.num { text-align: right; }
.situ-paliers-table tbody tr:last-child td { border-bottom: 0; }
.situ-palier-lib { width: 100%; border: 1px solid transparent; border-radius: 7px; padding: 6px 8px; font-size: 13px; color: var(--situ-ink); background: transparent; }
.situ-palier-lib:hover { border-color: var(--situ-line); }
.situ-palier-lib:focus { outline: none; border-color: var(--situ-acc); background: #fff; box-shadow: 0 0 0 3px rgba(91,87,214,.12); }
.situ-del { background: transparent; border: 0; cursor: pointer; font-size: 13px; opacity: .4; padding: 4px 5px; border-radius: 6px; }
.situ-del:hover { opacity: 1; background: var(--danger-bg); }
.situ-palier-add { display: flex; align-items: center; gap: 9px; padding-top: 12px; border-top: 1px dashed var(--situ-line); }
.situ-palier-add .situ-palier-lib { flex: 1 1 auto; border: 1px solid var(--situ-line); background: #fff; }
.situ-btn-ghost { background: transparent; border: 1px dashed var(--situ-line); color: var(--situ-acc-2); border-radius: 9px; padding: 7px 13px; font-size: 13px; font-weight: 600; cursor: pointer; white-space: nowrap; transition: all .12s; }
.situ-btn-ghost:hover { border-color: var(--situ-acc); background: var(--situ-accbg); }

/* SITUATIONS — liste + éditeur d'avancement (bloc 4.2). */
.situ-list-head { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 14px; margin: 20px 0 16px; }
.situ-create-form { flex: 0 0 auto; }
.situ-btn-primary { display: inline-flex; align-items: center; gap: 8px; background: var(--situ-acc); color: #fff; border: 0; border-radius: 10px; padding: 10px 16px; font-size: 14px; font-weight: 600; cursor: pointer; box-shadow: 0 1px 2px rgba(20,27,46,.08), 0 4px 14px rgba(91,87,214,.22); transition: background .12s; }
.situ-btn-primary:hover { background: var(--situ-acc-2); }
.situ-btn-plus { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 50%; background: rgba(255,255,255,.22); font-size: 15px; line-height: 1; }

.situ-cards { display: flex; flex-direction: column; gap: 12px; margin-bottom: 0; }
.situ-card { position: relative; background: #fff; border: 1px solid var(--situ-line); border-left: 5px solid var(--situ-acc); border-radius: 13px; box-shadow: 0 1px 2px rgba(20,27,46,.05), 0 4px 16px rgba(20,27,46,.05); overflow: hidden; transition: box-shadow .12s, transform .12s; }
.situ-card:hover { box-shadow: 0 2px 4px rgba(20,27,46,.08), 0 8px 24px rgba(20,27,46,.10); transform: translateY(-1px); }
.situ-card-main { display: block; padding: 14px 16px 15px; text-decoration: none; color: inherit; }
/* padding-right : réserve la place du bouton corbeille (absolu, en haut à
   droite) pour que le badge « Validée » / « Brouillon » ne passe plus dessous. */
.situ-card-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; padding-right: 26px; }
.situ-card-num { font-size: 13px; font-weight: 700; color: var(--situ-acc-2); }
.situ-card-date { font-size: 12.5px; color: var(--situ-ink2); }
.situ-card-del { position: absolute; top: 9px; right: 9px; }
.situ-card-del button { background: transparent; border: 0; cursor: pointer; font-size: 13px; opacity: .35; padding: 4px; border-radius: 6px; transition: opacity .12s, background .12s; }
.situ-card-del button:hover { opacity: 1; background: var(--danger-bg); }
.situ-badge { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; padding: 3px 8px; border-radius: 20px; background: #eef1f7; color: #6b7690; white-space: nowrap; }
.situ-badge--valide { background: #e2f5ea; color: #1f8a4c; }

/* Éditeur */
.situ-editor { max-width: 1080px; margin: 0 auto; }
.situ-ed-head { margin: 18px 0 14px; }
.situ-back { display: inline-block; font-size: 12.5px; color: var(--situ-ink2); text-decoration: none; margin-bottom: 10px; }
.situ-back:hover { color: var(--situ-acc-2); }
.situ-ed-titlerow { display: flex; align-items: center; gap: 12px; }
.situ-ed-num { font-size: 20px; font-weight: 700; color: var(--situ-ink); letter-spacing: -.3px; }
.situ-ed-date { font-size: 13px; color: var(--situ-ink2); }
.situ-ed-totals { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin: 14px 0 20px; }
.situ-tot { background: #fff; border: 1px solid var(--situ-line); border-radius: 12px; padding: 12px 15px; }
.situ-tot .l { display: block; font-size: 11.5px; color: var(--situ-ink2); margin-bottom: 5px; }
.situ-tot .v { font-size: 18px; font-weight: 700; color: var(--situ-ink); font-variant-numeric: tabular-nums; letter-spacing: -.4px; }
.situ-tot--hl { background: var(--situ-accbg); border-color: transparent; }
.situ-tot--hl .l, .situ-tot--hl .v { color: var(--situ-acc-2); }

.situ-lot { border: 1px solid var(--situ-line); border-radius: 11px; margin-bottom: 14px; overflow: hidden; }
.situ-lot-head { display: flex; align-items: center; gap: 12px; background: var(--situ-card2); padding: 9px 13px; border-bottom: 1px solid var(--situ-line); flex-wrap: wrap; }
.situ-lot-nom { font-size: 13.5px; font-weight: 700; color: var(--situ-ink); flex: 1 1 auto; }
.situ-lot-pct { font-size: 13px; font-weight: 700; color: var(--situ-acc-2); font-variant-numeric: tabular-nums; }
.situ-lot-montant { font-size: 12.5px; color: var(--situ-ink2); font-variant-numeric: tabular-nums; }
.situ-lot-montant .sur { color: var(--situ-ink3); }
.situ-lot-apply { display: inline-flex; align-items: center; gap: 5px; }
.situ-num-sm { width: 58px; padding: 5px 7px; }
.situ-btn-mini { background: #fff; border: 1px solid var(--situ-acc); color: var(--situ-acc-2); border-radius: 7px; padding: 5px 9px; font-size: 12px; font-weight: 600; cursor: pointer; white-space: nowrap; }
.situ-btn-mini:hover { background: var(--situ-accbg); }
.situ-lot-tablewrap { overflow-x: auto; }
.situ-postes-table { width: 100%; border-collapse: collapse; }
.situ-postes-table th { font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--situ-ink3); font-weight: 600; text-align: left; padding: 7px 12px; border-bottom: 1px solid var(--situ-line); white-space: nowrap; }
.situ-postes-table td { padding: 5px 12px; border-bottom: 1px solid var(--situ-line2); vertical-align: middle; font-size: 13px; }
.situ-postes-table tbody tr:last-child td { border-bottom: 0; }
.situ-postes-table .c-desig { min-width: 220px; color: var(--situ-ink); }
.situ-postes-table .c-tot, .situ-postes-table th.c-tot, .situ-postes-table .c-mont, .situ-postes-table th.c-mont, .situ-postes-table .c-pct, .situ-postes-table th.c-pct { text-align: right; }
.situ-postes-table .c-tot, .situ-postes-table .c-mont { font-variant-numeric: tabular-nums; white-space: nowrap; }
.situ-postes-table .c-mont { font-weight: 600; color: var(--situ-ink); }
.situ-postes-table .c-pct { width: 92px; }
.situ-postes-table .c-pct .situ-num { width: 100%; text-align: right; }

/* SITUATIONS — certificat de paiement (bloc 4.3). */
.situ-cert { background: #fff; border: 1px solid var(--situ-line); border-left: 5px solid var(--situ-acc); border-radius: 14px; box-shadow: 0 1px 2px rgba(20,27,46,.05), 0 4px 16px rgba(20,27,46,.05); padding: 16px 18px 18px; margin-bottom: 20px; }
.situ-cert-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 12px; }
.situ-cert-title { font-size: 15px; font-weight: 700; color: var(--situ-ink); margin: 0; }
.situ-cert-sub { font-size: 12px; color: var(--situ-ink3); }
.situ-cert-wrap { overflow-x: auto; }
.situ-cert-table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.situ-cert-table th { font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--situ-ink3); font-weight: 600; padding: 8px 12px; border-bottom: 1px solid var(--situ-line); text-align: right; white-space: nowrap; }
.situ-cert-table th.l { text-align: left; }
.situ-cert-table td { padding: 7px 12px; border-bottom: 1px solid var(--situ-line2); font-size: 13.5px; text-align: right; color: var(--situ-ink); white-space: nowrap; }
.situ-cert-table td.l { text-align: left; color: var(--situ-ink); }
.situ-cert-table td.l .mut { color: var(--situ-ink3); font-size: 11.5px; font-weight: 400; }
.situ-cert-ded td { color: var(--situ-ink2); }
.situ-cert-ded td.num { color: var(--danger); }
.situ-cert-net td { border-top: 2px solid var(--situ-line); border-bottom: 0; font-weight: 800; font-size: 15px; color: var(--situ-acc-2); padding-top: 10px; }

/* SITUATIONS — paliers bloquants + déverrouillage (bloc 4.4). */
.situ-paliers-table .c-lock { text-align: center; white-space: nowrap; }
.situ-lock { background: #fbf3e0; border: 1px solid #f0e0bb; color: #9a6a00; border-radius: 7px; padding: 4px 9px; font-size: 11.5px; font-weight: 600; cursor: pointer; white-space: nowrap; transition: all .12s; }
.situ-lock:hover { border-color: #d9b04e; }
.situ-lock.on { background: #e2f5ea; border-color: #b8e6cb; color: #1f8a4c; }
.situ-plafond { font-size: 12.5px; color: #9a6a00; background: #fbf3e0; border: 1px solid #f0e0bb; border-radius: 9px; padding: 9px 13px; margin: 0 0 14px; }
.situ-plafond a { color: var(--situ-acc-2); font-weight: 600; }

/* SITUATIONS — cycle validation / gel (bloc 4.5). */
.situ-ed-actions { display: flex; align-items: center; gap: 14px; margin: 12px 0 18px; flex-wrap: wrap; }
.situ-frozen { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; color: #1f8a4c; background: #e2f5ea; border: 1px solid #b8e6cb; border-radius: 9px; padding: 8px 13px; }
.situ-frozen-note { font-size: 12.5px; color: var(--situ-ink3); }
.situ-btn-validate { background: #1f8a4c; color: #fff; border: 0; border-radius: 9px; padding: 9px 16px; font-size: 14px; font-weight: 600; cursor: pointer; box-shadow: 0 1px 2px rgba(20,27,46,.08), 0 4px 14px rgba(31,138,76,.20); transition: background .12s; }
.situ-btn-validate:hover { background: #18733f; }
.situ-btn-outline { display: inline-flex; align-items: center; gap: 8px; background: #fff; color: var(--situ-acc-2); border: 1px solid var(--situ-acc); border-radius: 10px; padding: 9px 15px; font-size: 14px; font-weight: 600; cursor: pointer; transition: background .12s; }
.situ-btn-outline:hover { background: var(--situ-accbg); }
.situ-btn-outline .situ-btn-plus { background: var(--situ-accbg); color: var(--situ-acc-2); }

/* ===== Onglet Situations : 2 panneaux distincts (demande 2026-07-21) ===== */
/* GAUCHE « Situations » / DROITE « Paramètres du marché », chacun dans un
   cadre teinté avec ses items (cartes / tuiles) blancs par-dessus. */
.situ-panel,
.situ-layout > #situations-params {
  background: var(--situ-card2);
  border: 1px solid var(--situ-line);
  border-radius: 16px;
  padding: 20px;
}
.situ-panel .situ-list-head { margin: 0 0 16px; }
.situ-layout > #situations-params .situ-params-title { margin-top: 0; }
.situ-layout > #situations-params > *:last-child { margin-bottom: 0; }
/* Boutons « + Acompte » / « + Nouvelle situation » : même largeur, empilés,
   pleine largeur du panneau (≈278px). */
.situ-head-actions { display: flex; flex-direction: column; gap: 10px; width: 100%; }
.situ-head-actions form { width: 100%; }
.situ-head-actions .situ-btn-primary,
.situ-head-actions .situ-btn-outline { width: 100%; justify-content: center; }
/* Acompte verrouillé (des situations existent) : cadenas non cliquable à la
   place de la corbeille, aligné comme elle. */
.situ-card-lock { position: absolute; top: 9px; right: 9px; padding: 4px; color: var(--situ-ink3); opacity: .8; cursor: not-allowed; display: inline-flex; }
/* Montant HT de l'acompte (tuile Paramètres) : récap sous les seuils. */
.situ-acompte-total { margin-top: 12px; padding-top: 12px; border-top: 1px dashed var(--situ-line); display: flex; flex-direction: column; gap: 2px; }
.situ-acompte-total-lbl { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .03em; color: var(--situ-ink3); }
.situ-acompte-total-val { font-size: 18px; font-weight: 800; color: var(--situ-ink); letter-spacing: -.3px; }
.situ-acompte-total-note { font-size: 11.5px; color: var(--situ-ink3); }

/* Carte « Acompte » en tête de liste : accent ambre pour la distinguer des
   situations (mauve), montant mis en avant. Non cliquable (pas de hover). */
.situ-card--acompte { border-left-color: #d79a2c; cursor: default; }
.situ-card--acompte:hover { transform: none; box-shadow: 0 1px 2px rgba(20,27,46,.05), 0 4px 16px rgba(20,27,46,.05); }
.situ-badge--acompte { background: #fbeecf; color: #a26c14; }
.situ-card-montant { font-size: 17px; font-weight: 800; color: var(--situ-ink); letter-spacing: -.3px; margin-bottom: 3px; }
/* Verrou visuel d'une situation validée : saisies figées (garde serveur en plus). */
.situ-editor--locked .situ-num,
.situ-editor--locked .situ-btn-mini,
.situ-editor--locked .situ-lot-apply { pointer-events: none; opacity: .6; }

/* =========================================================================
   Consultations — œil « détail du chiffrage » + groupes de DPGF
   ========================================================================= */

/* Utilitaire a11y : texte lu par les lecteurs d'écran, invisible à l'œil.
   Sert aux en-têtes de colonne purement décoratifs (colonne d'icônes). */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* =========================================================================
   Legende HTML des diagrammes (Analytique)
   -------------------------------------------------------------------------
   Chart.js dessine sa legende DANS le canvas : avec ~15 lots elle depassait
   du carre et se faisait couper net. On la rend donc en HTML sous le canvas
   (cf. renderLegend dans projet/projet_analytique.html) : le texte s'enroule, la
   carte grandit, plus rien n'est tronque. html2canvas la capture aussi, donc
   les boutons Copier / PNG restent complets.
   ========================================================================= */

.chart-legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 2px 16px;
  width: 100%;
  margin: 14px 0 0;
  padding: 0;
  list-style: none;
}
.chart-legend-item {
  display: inline-flex;
  align-items: flex-start;
  gap: 7px;
  max-width: 100%;
  padding: 3px 0;
  background: none;
  border: 0;
  font: inherit;
  font-size: 12px;
  line-height: 1.35;
  color: var(--text);
  text-align: left;
  cursor: pointer;
}
.chart-legend-swatch {
  width: 12px;
  height: 12px;
  margin-top: 2px;
  border-radius: 3px;
  flex-shrink: 0;
}
/* Le libelle peut s'enrouler sur plusieurs lignes : c'est tout l'interet. */
.chart-legend-label { min-width: 0; }
.chart-legend-item:hover .chart-legend-label { text-decoration: underline; }
.chart-legend-item:focus-visible {
  outline: 2px solid var(--accent, #3b6ef5);
  outline-offset: 2px;
  border-radius: 3px;
}
/* Part masquee (clic sur la legende) : meme convention que Chart.js. */
.chart-legend-item.is-hidden { opacity: 0.45; }
.chart-legend-item.is-hidden .chart-legend-label { text-decoration: line-through; }

/* Pictogramme « surface incoherente » du tableau de bord. La couleur etait
   posee en style inline ; elle rejoint la feuille maintenant que le nom de
   fichier est stable (plus de bump `app-vN.css`, donc plus de conflit a
   craindre en touchant le CSS). */
.surface-warn { color: var(--danger); }

/* =========================================================================
   INFOBULLE INSTANTANEE (.tip)
   -------------------------------------------------------------------------
   Le `title=` natif impose un delai d'environ une seconde avant de
   s'afficher, et ce delai n'est reglable ni en CSS ni en JS. Pour une alerte
   qu'on doit pouvoir lire d'un coup d'oeil en balayant un tableau, c'est trop
   lent -- d'ou ce composant, affiche sans aucun delai.

   Usage : <span class="tip" data-tip="texte" tabindex="0">…</span>
   Ne PAS laisser de `title` a cote : le navigateur superposerait les deux.
   ========================================================================= */
.tip {
  position: relative;
  display: inline-flex;
  cursor: help;
}
.tip::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 9px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 60;
  width: max-content;
  max-width: 300px;
  padding: 9px 11px;
  border-radius: 7px;
  background: var(--navy);
  color: #fff;
  font-size: 12px;
  font-weight: 500;
  line-height: 1.45;
  text-align: left;
  white-space: normal;
  box-shadow: 0 8px 22px rgba(10, 18, 40, 0.28);
  /* `visibility` et pas `display` : pas de transition, donc apparition
     immediate, tout en restant hors de l'arbre d'accessibilite au repos. */
  visibility: hidden;
  opacity: 0;
}
.tip::before {
  content: "";
  position: absolute;
  bottom: calc(100% + 3px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 61;
  border: 6px solid transparent;
  border-top-color: var(--navy);
  visibility: hidden;
  opacity: 0;
}
.tip:hover::after,
.tip:hover::before,
.tip:focus-visible::after,
.tip:focus-visible::before {
  visibility: visible;
  opacity: 1;
}
.tip:focus-visible {
  outline: 2px solid var(--navy);
  outline-offset: 2px;
  border-radius: 3px;
}
@media (prefers-reduced-motion: reduce) {
  .tip::after,
  .tip::before { transition: none; }
}

/* ===== Modale « contenu du document » (sélection des sections d'export) =====
   Pilotée par core/services/export_sections.py, ouverte depuis les tuiles
   d'export. Liste de cases à cocher : une section = un bloc de contenu, pas
   une page — le détail d'un lot volumineux peut déborder sur deux pages. */
.modal--export-sections { max-width: 560px; }

/* ===== Fenetres de copier-coller de lignes =====
   « Copier / deplacer », « Importer », « Coller » (cf. copier_coller.py). La
   liste des lignes defile dans son cadre, en-tete colle : sur un lot de
   quarante postes, le choix de portee et les boutons restent a l'ecran. */
.modal--lignes { max-width: 780px; }
.lignes-portee {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 22px;
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 14px;
}
.lignes-portee label { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; }
.lignes-liste {
  max-height: 45vh;
  overflow: auto;
  border: 1px solid var(--border);
  border-radius: 8px;
}
.lignes-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.lignes-table th {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 8px 10px;
  background: #fafbfc;
  border-bottom: 1px solid var(--border);
  color: var(--muted);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-align: left;
  text-transform: uppercase;
}
.lignes-table td { padding: 7px 10px; border-top: 1px solid #f0f2f6; vertical-align: top; }
.lignes-table tbody tr:first-child td { border-top: 0; }
.lignes-col-case { width: 30px; }
.lignes-col-num { width: 34px; color: var(--muted); font-variant-numeric: tabular-nums; }
.lignes-col-unite { width: 38px; color: var(--muted); }
.lignes-table .lignes-col-nb { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.lignes-libelle { display: block; cursor: pointer; }
.lignes-texte { color: var(--muted); font-style: italic; }
.lignes-tag {
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 3px;
  background: #fffbf0;
  color: #b9770e;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.lignes-vide { padding: 18px; text-align: center; }
.lignes-aide { margin: 0; font-size: 12px; }
.lignes-resume { margin: 0; font-size: 14px; line-height: 1.5; }
.lignes-zones-titre { margin: 0 0 8px; font-size: 13px; }
.lignes-import-corps { display: flex; flex-direction: column; gap: 14px; }
.lignes-select {
  width: 100%;
  height: 34px;
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: 13px;
}
/* Pied de la fenetre « Copier / deplacer » : le deplacement a gauche, les
   boutons de la fenetre a droite ; « Retour » de l'import, a gauche aussi. */
.lignes-footer { flex-wrap: wrap; align-items: center; }
.lignes-deplacer { display: flex; align-items: center; gap: 8px; margin-right: auto; }
.lignes-deplacer-label { color: var(--muted); font-size: 13px; white-space: nowrap; }
.lignes-deplacer .lignes-select { width: auto; max-width: 240px; }
.lignes-retour { margin-right: auto; }
.export-sections-intro {
  margin: 0 0 16px;
  font-size: 13px;
  line-height: 1.55;
  color: var(--muted);
}
.export-sections-liste {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.export-section > label {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: 10px 12px;
  border-radius: 8px;
  cursor: pointer;
}
.export-section > label:hover { background: #f4f6fa; }
/* Section non décochable (la synthèse porte les totaux) : on la montre cochée
   plutôt que de la retirer de la liste — l'utilisateur doit VOIR qu'elle est
   incluse. Le curseur dit qu'elle ne se clique pas. */
.export-section--figee > label { cursor: default; }
.export-section--figee > label:hover { background: none; }
.export-section input[type="checkbox"] {
  width: 15px;
  height: 15px;
  margin-top: 2px;
  accent-color: var(--blue, #3b6ef5);
  flex: none;
}
.export-section-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.export-section-nom {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: 7px;
}
.export-section-volume {
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
  background: #eef1f6;
  border-radius: 999px;
  padding: 1px 7px;
  font-variant-numeric: tabular-nums;
}
.export-section-aide { font-size: 12px; line-height: 1.45; color: var(--muted); }
/* Compteur de pages de la modale d'export : total mis à jour en direct, à
   gauche des boutons. N'existe que pour le PDF, seul format paginé. */
.export-sections-total {
  margin-right: auto;
  display: flex;
  flex-direction: column;
  gap: 1px;
  font-size: 13px;
  color: var(--text);
}
.export-sections-total strong { font-variant-numeric: tabular-nums; }
.export-sections-total-note { font-size: 11px; color: var(--muted); }

/* Barre de progression de la modale d'export : remplace la liste des sections
   pendant la generation. Le serveur ne publie pas son avancement : la barre
   suit une duree estimee et ne touche 100 % qu'a l'arrivee du fichier.
   Pendant la generation on retire aussi les boutons (fermer, annuler,
   exporter) : fermer n'annulerait rien, recliquer relancerait un rendu. */
.export-progression { padding: 6px 0 4px; }
.export-progression-titre {
  margin: 0 0 10px;
  font-size: 14px;
  font-weight: 700;
  color: var(--navy);
}
.export-progression-barre {
  height: 8px;
  border-radius: 999px;
  background: #e6eaf3;
  overflow: hidden;
}
.export-progression-remplissage {
  display: block;
  width: 0;
  height: 100%;
  border-radius: inherit;
  background: var(--blue);
  transition: width 0.15s linear;
}
.export-progression-note {
  margin: 10px 0 0;
  font-size: 12px;
  color: var(--muted);
}
.is-attente-longue .export-progression-note { color: var(--text); }
.is-attente-longue .export-progression-remplissage { background: var(--muted); }
.is-generation .export-sections-intro,
.is-generation .export-sections-liste,
.is-generation .modal-footer,
.is-generation .modal-close { display: none; }
@media (prefers-reduced-motion: reduce) {
  .export-progression-remplissage { transition: none; }
}

/* ============================================================
   COMPARAISON INTER-VERSIONS (lots en lignes, versions en colonnes)
   Remplace la feuille Excel « Synthese et analyse des variations ».
   Le tableau est large par nature : il scrolle horizontalement dans
   son propre conteneur, la page elle-meme ne scrolle jamais en X.
   ============================================================ */
.comparaison-main { padding: 20px 24px 40px; }

.cmp-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
.cmp-head h1 { margin: 0 0 4px; font-size: 20px; color: var(--text); }
.cmp-head .muted { margin: 0; font-size: 13px; color: var(--muted); }
.cmp-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.cmp-actions .btn { padding: 8px 14px; font-size: 13px; }

.cmp-avertissements {
  background: #fff8e6;
  border: 1px solid #e8d9a8;
  border-radius: 8px;
  padding: 10px 14px;
  margin-bottom: 16px;
  font-size: 13px;
  color: #6b5a22;
}
.cmp-avertissements p { margin: 0 0 4px; }
.cmp-avertissements p:last-child { margin-bottom: 0; }

/* Conteneur de scroll : c'est LUI qui deborde, jamais le body. */
.cmp-table-wrap {
  overflow-x: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
}
.cmp-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  white-space: nowrap;
}
.cmp-table th,
.cmp-table td {
  padding: 7px 12px;
  text-align: right;
  border-bottom: 1px solid var(--border);
}
.cmp-table th.lbl,
.cmp-table td.lbl { text-align: left; white-space: normal; min-width: 240px; }

/* La 1re colonne reste visible quand on fait defiler les versions :
   sans elle, on lit des montants sans savoir de quel lot il s'agit. */
.cmp-table th.lbl,
.cmp-table td.lbl {
  position: sticky;
  left: 0;
  background: var(--surface);
  z-index: 1;
}
.cmp-table thead th {
  position: sticky;
  top: 0;
  background: var(--navy);
  color: #fff;
  font-weight: 600;
  font-size: 12px;
  z-index: 2;
}
.cmp-table thead th.lbl { background: var(--navy); z-index: 3; }
.cmp-table thead th .date {
  display: block;
  font-weight: 400;
  font-size: 11px;
  opacity: .72;
}
/* Les deux colonnes dont on calcule l'ecart : reperables d'un coup d'oeil. */
.cmp-table thead th.col-comparee { background: var(--navy-2); }
.cmp-table thead th.ecart { background: var(--blue-2); }

.cmp-table td .num {
  display: inline-block;
  min-width: 26px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.cmp-table tr.section td {
  background: #eef3ff;
  color: var(--text);
  font-weight: 700;
  font-size: 11px;
  letter-spacing: .04em;
  text-transform: uppercase;
  text-align: left;
}
.cmp-table tr.section td.lbl { background: #eef3ff; }
.cmp-table tr.total td { background: #fbf3dc; font-weight: 700; }
.cmp-table tr.total td.lbl { background: #fbf3dc; }
.cmp-table tr:hover td { background: #f7f9fc; }
.cmp-table tr:hover td.lbl { background: #f7f9fc; }

.cmp-table td.vide { color: #b6bcc8; }
/* Une hausse de cout est un signal, pas une bonne nouvelle : rouge.
   Le sens est decide cote service (`delta.sens`), pas ici. */
.cmp-table td.d-hausse { color: var(--danger); }
.cmp-table td.d-baisse { color: #1f8a4c; }
.cmp-table td.d-neutre { color: var(--muted); }

/* --- Fenetre de parametrage ---
   Un seul tableau : « Afficher » (colonne du tableau) et « De / À » (bornes
   de l'ecart) se lisent sur la meme ligne. */
.comparaison-modal { max-width: 560px; }
.cmp-aide {
  margin: 0 0 14px;
  padding: 10px 14px 10px 30px;
  background: var(--bg);
  border-radius: 6px;
  font-size: 13px;
  color: var(--text);
  line-height: 1.5;
}
.cmp-choix {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
.cmp-choix th {
  padding: 6px 8px;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted);
  text-align: left;
  border-bottom: 1px solid var(--border);
}
.cmp-choix td {
  padding: 8px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
.cmp-choix .cmp-col-coche,
.cmp-choix .cmp-col-borne { width: 52px; text-align: center; }
.cmp-choix input { cursor: pointer; width: 16px; height: 16px; }
.cmp-choix input:disabled { cursor: not-allowed; }
/* Ligne choisie comme borne de l'ecart : reperable d'un coup d'oeil. */
.cmp-choix tr.is-borne td { background: #eef3ff; }
.cmp-version-label { font-weight: 600; color: var(--text); }
.cmp-version-date { color: var(--muted); font-size: 12px; white-space: nowrap; }
.cmp-version-warn {
  margin-left: 6px;
  font-size: 11px;
  color: #8a6d1f;
  background: #fff8e6;
  border: 1px solid #e8d9a8;
  border-radius: 4px;
  padding: 1px 6px;
}

/* Bouton « Comparer les versions » dans l'en-tete de l'historique. */
.resume-historique-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

/* --- Comparatif inclus dans les exports client ---
   Ligne d'etat sous les tuiles (onglet Exports) et bloc equivalent sur la
   page du tableau. Bleu = comparatif present ; gris = absent. */
.exports-comparatif,
.cmp-export-client {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 12px;
  padding: 9px 12px;
  border: 1px dashed var(--border);
  border-radius: 8px;
  font-size: 13px;
  color: var(--muted);
}
.cmp-export-client { margin: 0 0 16px; }
.exports-comparatif .ic,
.cmp-export-client .ic { width: 16px; height: 16px; flex-shrink: 0; }
.exports-comparatif.is-inclus {
  border-style: solid;
  border-color: #bccdf7;
  background: #eef3ff;
  color: var(--text);
}
.exports-comparatif-note { color: var(--muted); }
.exports-comparatif a { color: var(--blue); font-weight: 600; text-decoration: none; }
.exports-comparatif a:hover { text-decoration: underline; }
.exports-comparatif form,
.cmp-export-client form { margin: 0; }
.cmp-export-etat { display: inline-flex; align-items: center; gap: 6px; }
.cmp-export-etat.is-inclus { color: #1f8a4c; font-weight: 600; }
.cmp-export-client .btn { padding: 6px 12px; font-size: 12px; }
