/* ============================================================
   HeraHub — sistema de diseño v2 (paleta validada, tema claro,
   sidebar oscura, animaciones e interacción)
   ============================================================ */

/* ── Typographies auto-hébergées (RGPD : aucun appel aux serveurs Google au
   chargement). Fichiers « variables » : un seul woff2 couvre toutes les
   graisses. On garde 3 familles prêtes, mais le navigateur ne télécharge QUE
   celle désignée par --font-ui. Défaut : Manrope (pro + chaleureuse). ── */
@font-face { font-family: 'Manrope'; font-style: normal; font-weight: 200 800; font-display: swap;
  src: url("../fonts/manrope-latin.fc03edc2c673.woff2") format('woff2');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }
@font-face { font-family: 'Manrope'; font-style: normal; font-weight: 200 800; font-display: swap;
  src: url("../fonts/manrope-latin-ext.91e6441f12d2.woff2") format('woff2');
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF; }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 100 900; font-display: swap;
  src: url("../fonts/inter-latin.260c81a4759b.woff2") format('woff2');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 100 900; font-display: swap;
  src: url("../fonts/inter-latin-ext.1ad231aac0a8.woff2") format('woff2');
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF; }
@font-face { font-family: 'Plus Jakarta Sans'; font-style: normal; font-weight: 200 800; font-display: swap;
  src: url("../fonts/jakarta-latin.7660bd9909fb.woff2") format('woff2');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }
@font-face { font-family: 'Plus Jakarta Sans'; font-style: normal; font-weight: 200 800; font-display: swap;
  src: url("../fonts/jakarta-latin-ext.d147042bbd15.woff2") format('woff2');
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF; }

:root {
  --font-ui: 'Inter', system-ui, -apple-system, "Segoe UI", sans-serif;
  --page: #f6f6f3;
  --surface: #fcfcfb;
  --ink: #0b0b0b;
  --ink-2: #52514e;
  --muted: #898781;
  --hairline: #e1e0d9;
  --border: rgba(11, 11, 11, 0.10);
  --accent: #2a78d6;         /* serie 1 — azul (ASR) */
  --accent-strong: #1c5cab;
  --accent-soft: #cde2fb;
  --aqua: #1baf7a;           /* serie 2 — aqua (Rayser) */
  --good: #0ca30c;
  --good-text: #006300;
  --warning: #fab219;
  --serious: #ec835a;
  --critical: #d03b3b;
  --good-tint: #e9f6ef;          /* fond « fait » (chip de tâche, état bon) */
  --good-tint-border: #bfe6cf;
  --attention-bg: #fdf5e6;       /* fond d'une ligne qui demande attention */
  --side-bg: #151a2b;
  --side-ink: #b6bccf;
  --side-muted: #6d7590;
  --radius: 12px;
  --shadow: 0 1px 2px rgba(11, 11, 11, 0.05), 0 6px 18px rgba(11, 11, 11, 0.06);
  --shadow-lift: 0 4px 10px rgba(11, 11, 11, 0.08), 0 12px 32px rgba(11, 11, 11, 0.10);

  /* ── Système de couleur SÉMANTIQUE — source unique, réutilisable partout ──
     v1 : introduit sur le tableau de bord (Accueil). Par domaine :
       (sans suffixe) = remplissage / graphique  (contraste ≥ 3:1)
       -t             = texte                    (WCAG AA ≥ 4.5, validé)
       -bg            = fond pâle (tuile, chip)
     Le vert = tout ce qui touche à la facturation / l'encaissement. */
  --sem-facture: #1f9d5b;  --sem-facture-t: #147a46;  --sem-facture-bg: #e8f6ee;
  --sem-defaut:  #d03b3b;  --sem-defaut-t:  #c0392b;   --sem-defaut-bg:  #fbece9;
  --sem-attente: #c67d10;  --sem-attente-t: #8a5a0e;   --sem-attente-bg: #fbf1e0;
  --sem-vente:   #2a78d6;  --sem-vente-t:   #1c5cab;    --sem-vente-bg:   #e9f1fc;
  --sem-care:    #7a55d1;  --sem-care-t:    #6a45c0;    --sem-care-bg:    #efeafb;
  --sem-acces:   #0e9aa7;  --sem-acces-t:   #0a7b86;    --sem-acces-bg:   #e2f4f5;
  --sem-peda:    #4557c4;  --sem-peda-t:    #3d4eb0;    --sem-peda-bg:    #eaecf8;
  --sem-ops:     #5a6472;  --sem-ops-t:     #4c5561;    --sem-ops-bg:     #eef0f3;

  /* D'OÙ vient une offre — le catalogue. Volontairement HORS de la palette
     sémantique : rouge = impayé, vert = facturé, bleu = vente. Une boutique
     en rouge se lirait comme un incident, et un parcours en bleu comme une
     vente encaissée. Ce sont donc les couleurs des outils eux-mêmes — le
     violet de WooCommerce —, et l'ambre du « en attente » pour ce qui n'est
     pas encore renseigné, où il veut dire exactement ce qu'il veut dire. */
  --orig-boutique: #7f54b3;  --orig-boutique-t: #6b4499;  --orig-boutique-bg: #f2ecf9;
  --orig-parcours: #0e7490;  --orig-parcours-t: #0b5c73;  --orig-parcours-bg: #e3f2f6;
  --orig-manuel:   #64748b;  --orig-manuel-t:   #4d5a6b;  --orig-manuel-bg:   #eef1f5;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: var(--font-ui);
  background: var(--page);
  color: var(--ink);
  font-size: 14.5px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}
::selection { background: var(--accent-soft); }
/* `hidden` doit gagner, toujours. La feuille du navigateur le pose à
   `display:none` avec une spécificité nulle, donc n'importe quelle règle
   d'auteur qui donne un `display` à l'élément le rend visible malgré
   l'attribut. Ça s'est déjà produit deux fois ici (les outils d'en-tête, puis
   les trois états de la zone de dépôt, où le spinner tournait avant même
   qu'on ait déposé un fichier). Une seule ligne le règle partout. */
[hidden] { display: none !important; }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
h1 { font-size: 21px; font-weight: 650; margin: 0 0 2px; letter-spacing: -0.01em; }
h2 { font-size: 15px; margin: 0 0 10px; }
h3 { font-size: 13.5px; margin: 0 0 8px; color: var(--ink-2); }

/* ---------- Animaciones base ---------- */
@keyframes rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes grow-y { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes grow-x { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.18); } }
@keyframes toast-in { from { opacity: 0; transform: translateX(24px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* ---------- Estructura ---------- */
.layout { display: flex; min-height: 100vh; }
.sidebar {
  width: 240px; flex-shrink: 0; background: var(--side-bg);
  padding: 16px 12px 14px; position: fixed; left: 0; top: 0; height: 100vh; z-index: 60;
  display: flex; flex-direction: column; overflow: visible;
  transition: width .22s ease, box-shadow .22s ease;
  scrollbar-width: thin; scrollbar-color: #333a52 transparent;
}
.side-nav { flex: 1; overflow: visible; margin: 0 -4px; padding: 0 4px 10px; }
.side-footer {
  margin-top: 10px; padding: 12px 6px 2px; border-top: 1px solid rgba(255, 255, 255, .09);
  display: flex; align-items: center; gap: 9px;
}
.side-footer .avatar { width: 32px; height: 32px; font-size: 12px; flex-shrink: 0; }
.side-footer .who { flex: 1; min-width: 0; }
.side-footer b { color: #fff; font-size: 12.5px; display: block; line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.side-footer small {
  color: var(--side-muted); font-size: 10.5px;
  display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.side-footer .btn-exit {
  margin-left: auto; color: var(--side-muted); background: none; border: 1px solid rgba(255,255,255,.14);
  border-radius: 7px; padding: 4px 9px; font-size: 11.5px; cursor: pointer; font-family: inherit;
  transition: all .15s;
}
.side-footer .btn-exit:hover { color: #fff; border-color: rgba(255,255,255,.4); }
.brand { display: flex; align-items: center; gap: 9px; padding: 2px 8px 16px; }
.brand-logo {
  width: 32px; height: 32px; border-radius: 9px;
  background: var(--accent);
  color: #fff; display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 15px; box-shadow: 0 3px 8px rgba(42, 120, 214, .4);
}
.brand-mark { width: 34px; height: 34px; object-fit: contain; flex-shrink: 0;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, .35)); }
.brand b { font-size: 15.5px; color: #fff; }
.brand small { display: block; color: var(--side-muted); font-size: 10px; letter-spacing: .08em; }
.nav-section { margin-top: 14px; }
.nav-section > span {
  display: block; font-size: 9.5px; text-transform: uppercase; letter-spacing: .12em;
  color: var(--side-muted); padding: 0 10px 5px;
}
.nav-item {
  display: flex; align-items: center; gap: 9px; padding: 6px 10px; border-radius: 8px;
  color: var(--side-ink); font-size: 13px; margin-bottom: 1px;
  transition: background .15s, color .15s;
}
.nav-item:hover { background: rgba(255, 255, 255, .06); color: #fff; text-decoration: none; }
.nav-item.active {
  background: rgba(42, 120, 214, .22);
  color: #fff; font-weight: 600; box-shadow: inset 2px 0 0 var(--accent);
}
.nav-item .ico { width: 16px; text-align: center; color: var(--side-muted); font-size: 12px; display: inline-flex; align-items: center; justify-content: center; }
.nav-item .ico svg { display: block; }
.bell > summary svg { vertical-align: -2px; color: var(--ink-2); }
.nav-item:hover .ico, .nav-item.active .ico { color: #7db4ee; }

/* ---------- Sidebar : groupes repliables ---------- */
.nav-group { margin-bottom: 1px; }
.nav-group-head {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 6px 10px; border-radius: 8px; cursor: pointer;
  background: none; border: 0; text-align: left; font: inherit;
  color: var(--side-ink); font-size: 13px;
  transition: background .15s, color .15s;
}
.nav-group-head:hover { background: rgba(255, 255, 255, .06); color: #fff; }
.nav-group-head .ico { width: 16px; color: var(--side-muted); display: inline-flex; align-items: center; justify-content: center; }
.nav-group-head .ico svg { display: block; }
.nav-group-head:hover .ico { color: #7db4ee; }
.nav-group-head .lbl { flex: 1; }
.nav-group-head .chevron { color: var(--side-muted); display: inline-flex; transition: transform .18s; }
.nav-group-head .chevron svg { display: block; }
.nav-group.open > .nav-group-head .chevron { transform: rotate(180deg); }
.nav-group.active > .nav-group-head { color: #fff; font-weight: 600; }
.nav-group.active > .nav-group-head .ico { color: #7db4ee; }
.nav-group-items { display: none; margin: 2px 0 4px; padding-left: 24px; }
.nav-group.open > .nav-group-items { display: block; }
.nav-sub {
  /* Flex, et pas block : le badge « en dév. » doit rester SUR LA LIGNE du
     libellé. En flux normal il passait à la ligne dès que le libellé était
     long, et le menu se lisait comme deux entrées au lieu d'une. */
  display: flex; align-items: center; gap: 8px;
  padding: 5px 10px; border-radius: 7px; margin-bottom: 1px;
  /* `--side-muted` était trop sombre pour du texte qu'on lit : réservé aux
     intitulés de section, pas aux liens. */
  color: var(--side-ink); font-size: 12.5px; text-decoration: none;
  border-left: 2px solid transparent; transition: background .15s, color .15s;
}
/* Le libellé cède la place au badge plutôt que de le pousser à la ligne. */
.nav-sub-lbl { min-width: 0; overflow: hidden; text-overflow: ellipsis;
               white-space: nowrap; }
.nav-sub:hover { color: #fff; background: rgba(255, 255, 255, .05); text-decoration: none; }
.nav-sub.active { color: #fff; border-left-color: var(--accent); background: rgba(42, 120, 214, .14); font-weight: 600; }
.sidebar .entity-chip {
  background: rgba(255, 255, 255, .07); border-color: transparent; color: var(--side-ink);
}

/* ---------- Sidebar : rail d'icônes + sous-menus au SURVOL (façon Sellsy) ---------- */
.nav-item, .nav-group-head { white-space: nowrap; }
.nav-item .lbl, .nav-group-head .lbl { flex: 1; overflow: hidden; text-overflow: ellipsis; }
.brand { overflow: hidden; }
.brand-txt { min-width: 0; }
.brand-txt b, .brand-txt small { white-space: nowrap; }
.nav-group-head .chevron { display: none; }              /* fini les menus déroulants */
.nav-item .ico, .nav-group-head .ico { width: 28px; flex-shrink: 0; }   /* icônes plus grandes */
.nav-item .ico svg, .nav-group-head .ico svg { width: 22px; height: 22px; }
.nav-toggle {
  display: flex; align-items: center; gap: 10px; width: 100%; margin: 4px 0 2px;
  padding: 7px 10px; border-radius: 8px; border: 0; cursor: pointer;
  background: none; color: var(--side-muted); font: inherit; font-size: 12.5px;
  transition: background .15s, color .15s;
}
.nav-toggle:hover { background: rgba(255, 255, 255, .06); color: #fff; }
.nav-toggle::before { content: "«"; width: 22px; text-align: center; font-size: 17px; line-height: 1; flex-shrink: 0; }
html.nav-rail .nav-toggle::before { content: "»"; }
html.nav-rail .nav-toggle { justify-content: center; padding-left: 0; padding-right: 0; }
html.nav-rail .nav-toggle .lbl { display: none; }

/* Décalage du contenu : rail = 62px, épinglé = 240px (transition douce) */
.main { margin-left: 240px; transition: margin-left .22s ease; }
html.nav-rail .main { margin-left: 62px; }
html.nav-rail .sidebar { width: 62px; }

/* Sous-menus TOUJOURS au survol (flyout) — jamais déroulés en ligne, quel que soit le mode */
.nav-group { position: relative; }
.nav-group-items {
  display: block; position: absolute; left: calc(100% + 10px); top: -6px;
  min-width: 198px; padding: 7px; margin: 0;
  background: #1c2236; border: 1px solid rgba(255, 255, 255, .10); border-radius: 12px;
  box-shadow: 0 14px 44px rgba(0, 0, 0, .5);
  opacity: 0; visibility: hidden; transform: translateX(-5px);
  transition: opacity .13s ease, transform .13s ease; z-index: 80; pointer-events: none;
}
.nav-group:hover > .nav-group-items { opacity: 1; visibility: visible; transform: none; pointer-events: auto; }
.nav-group:hover::after { content: ""; position: absolute; left: 100%; top: 0; width: 16px; height: 100%; }
.nav-group-items .nav-sub { padding: 6px 10px; margin-bottom: 0; border-left: 0; }
/* En-tête du flyout (nom du groupe) : seulement en rail, où le nom n'est pas visible */
html.nav-rail .nav-group-items::before {
  content: attr(data-label); display: block; padding: 2px 10px 8px;
  font-size: 11px; font-weight: 700; color: #fff;
  border-bottom: 1px solid rgba(255, 255, 255, .08); margin-bottom: 5px;
}

/* Rail : seulement les icônes ; le nom et le libellé apparaissent en flyout */
html.nav-rail .brand-txt,
html.nav-rail .side-footer .who, html.nav-rail .side-footer .btn-exit { display: none; }
html.nav-rail .brand, html.nav-rail .side-footer { justify-content: center; padding-left: 0; padding-right: 0; }
html.nav-rail .nav-item { position: relative; }
html.nav-rail .nav-item, html.nav-rail .nav-group-head { justify-content: center; padding-left: 0; padding-right: 0; }
html.nav-rail .nav-group-head .lbl { display: none; }
html.nav-rail .nav-item:hover::after { content: ""; position: absolute; left: 100%; top: 0; width: 16px; height: 100%; }
/* Flyout : libellé d'un item simple (Accueil) — en rail seulement */
html.nav-rail .nav-item .lbl {
  position: absolute; left: calc(100% + 10px); top: 50%;
  transform: translateY(-50%) translateX(-5px); flex: none;
  background: #1c2236; color: #fff; padding: 7px 12px; border-radius: 9px;
  font-size: 12.5px; font-weight: 600; white-space: nowrap;
  border: 1px solid rgba(255, 255, 255, .10); box-shadow: 0 12px 34px rgba(0, 0, 0, .45);
  opacity: 0; visibility: hidden; pointer-events: none; z-index: 80;
  transition: opacity .13s ease, transform .13s ease;
}
html.nav-rail .nav-item:hover .lbl { opacity: 1; visibility: visible; transform: translateY(-50%); }
@media (max-width: 760px) { .main, html.nav-rail .main { margin-left: 62px; } }

/* ============================================================
   Tableau de bord des ventes — donut « ventes par offre » + prévision trésorerie
   ============================================================ */
.dg .c12 { grid-column: span 12; }
@media (max-width: 1000px) { .dg .c12 { grid-column: span 12; } }
.dg-top { align-items: start; }   /* cartes à hauteur naturelle (pas de vide) */

/* Donut coloré + légende */
.offre-wrap { display: flex; gap: 20px; align-items: center; }
.donut-chart { position: relative; width: 146px; height: 146px; flex-shrink: 0; }
.donut-svg { width: 146px; height: 146px; display: block; }
.donut-svg .dslice { transition: opacity .15s, filter .15s; cursor: default; }
.donut-svg:has(.dslice:hover) .dslice:not(:hover) { opacity: .38; }
.donut-svg .dslice:hover { filter: brightness(1.09); }
.donut-mid { position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; pointer-events: none; }
.donut-mid b { font-size: 24px; font-weight: 700; letter-spacing: -.02em; line-height: 1; }
.donut-mid span { font-size: 11px; color: var(--muted); }
.offre-legend { list-style: none; margin: 0; padding: 0; flex: 1; min-width: 0;
  max-height: 300px; overflow-y: auto; display: flex; flex-direction: column; gap: 1px; }
.offre-legend li { display: grid; grid-template-columns: 11px minmax(0, 1fr) auto auto 44px;
  gap: 9px; align-items: center; font-size: 12px; padding: 3px 6px; border-radius: 6px; }
.offre-legend li:hover { background: var(--page); }
.offre-legend .lg-dot { width: 11px; height: 11px; border-radius: 3px; }
.offre-legend .lg-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.offre-legend .lg-n { color: var(--muted); font-size: 11px; white-space: nowrap; }
.offre-legend .lg-eur { font-weight: 650; font-variant-numeric: tabular-nums; white-space: nowrap; }
.offre-legend .lg-pct { color: var(--muted); font-variant-numeric: tabular-nums; text-align: right; }

/* Prévision trésorerie — barres groupées (3 séries) + table */
.tr-legend { display: flex; gap: 18px; font-size: 12px; color: var(--ink-2); margin-bottom: 10px; }
.tr-legend .sw { display: inline-block; width: 11px; height: 11px; border-radius: 3px; margin-right: 5px; vertical-align: middle; }
.tr-wrap { display: flex; gap: 22px; align-items: stretch; }
.tr-chart { flex: 1; display: flex; align-items: flex-end; gap: 8px; height: 152px; min-width: 0; }
.tr-month { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 6px; height: 100%; cursor: default; }
.tr-bars { flex: 1; width: 100%; display: flex; align-items: flex-end; justify-content: center; gap: 2px; }
.tr-bars i { width: 30%; max-width: 13px; min-height: 2px; border-radius: 3px 3px 1px 1px; transition: filter .15s; }
.tr-bars .b1 { background: #4f6bed; } .tr-bars .b2 { background: #1fa97a; } .tr-bars .b3 { background: #f2a516; }
.tr-chart:has(.tr-month:hover) .tr-month:not(:hover) .tr-bars i { opacity: .38; }
.tr-month:hover .tr-bars i { filter: brightness(1.09); }
.tr-x { font-size: 10px; color: var(--muted); white-space: nowrap; }
.tr-month:hover .tr-x { color: var(--ink); font-weight: 600; }
.tr-table { width: 300px; flex-shrink: 0; max-height: 210px; overflow-y: auto; }
.tr-table table { width: 100%; }
@media (max-width: 900px) { .tr-wrap { flex-direction: column; } .tr-table { width: auto; max-height: none; } }

/* Retards & relances */
.rr-stats { display: flex; flex-direction: column; gap: 11px; margin-bottom: 12px; }
.rr { display: grid; grid-template-columns: 34px 1fr auto; align-items: baseline; gap: 2px 10px; }
.rr .rr-v { font-size: 20px; font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
.rr .rr-l { font-size: 12px; color: var(--ink-2); }
.rr .rr-s { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.rr-list { display: flex; flex-direction: column; gap: 2px; border-top: 1px solid var(--hairline); padding-top: 9px; }
.rr-row { display: grid; grid-template-columns: 1fr auto auto; align-items: center; gap: 8px;
  padding: 4px 6px; border-radius: 7px; text-decoration: none; color: inherit; font-size: 12px; }
.rr-row:hover { background: var(--page); text-decoration: none; }
.rr-row .rr-who { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: 500; }
.rr-row .rr-amt { font-weight: 600; font-variant-numeric: tabular-nums; }

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.topbar {
  display: flex; align-items: center; gap: 12px; padding: 12px 28px 0;
  position: sticky; top: 0; z-index: 40; pointer-events: none;
}
.topbar > * { pointer-events: auto; }
.topbar .spacer { flex: 1; }
.topbar-search {
  display: flex; align-items: center; gap: 8px; padding: 7px 12px;
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  backdrop-filter: blur(8px); border: 1px solid var(--hairline); border-radius: 99px;
  box-shadow: 0 1px 4px rgba(15, 23, 42, .06); color: var(--muted);
  transition: border-color .15s, box-shadow .15s, width .2s; width: 240px;
}
.topbar-search:focus-within {
  border-color: #7db4ee; box-shadow: 0 0 0 3px rgba(42, 120, 214, .12); width: 320px;
}
.topbar-search input {
  border: 0; outline: 0; background: transparent; flex: 1; min-width: 0;
  font: inherit; font-size: 13px; color: var(--ink); padding: 0;
}
.topbar-search input::placeholder { color: var(--muted); }
.topbar-search kbd {
  font: 600 10.5px/1 var(--mono, ui-monospace, monospace); color: var(--muted);
  border: 1px solid var(--hairline); border-radius: 5px; padding: 2px 5px;
  background: var(--surface);
}
.topbar-search:focus-within kbd { display: none; }
.content { padding: 22px 28px 44px; max-width: 2200px; display: flex; flex-direction: column; }

/* ---------- Onglets de module (tira de tabs bajo la topbar) ---------- */
.tabstrip {
  /* UNE seule ligne, toujours. Avec les rubans « en dév. » la tira passait sur
     deux rangs et poussait la page vers le bas ; si ça ne tient pas, ça défile
     latéralement — la barre d'onglets ne doit jamais gagner en hauteur. */
  display: flex; gap: 2px; flex-wrap: nowrap;
  overflow-x: auto; overflow-y: hidden; scrollbar-width: thin;
  border-bottom: 1px solid var(--hairline);
  margin: 6px 0 16px;
}
.tabstrip .tab { flex: none; }
.tabstrip .tab {
  padding: 9px 15px; color: var(--muted); font-weight: 500; font-size: 13.5px;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  text-decoration: none; white-space: nowrap; transition: color .12s;
}
.tabstrip .tab:hover { color: var(--ink); }
.tabstrip .tab.active { color: var(--accent); border-bottom-color: var(--accent); font-weight: 600; }
/* La tira va justo bajo el título (JS la coloca); evitamos doble línea. */
/* Tabs SIEMPRE bajo el título, vía flex-order (CSS puro, robusto ante colisiones). */
.content > .page-head { order: -2; }
.content > .tabstrip { order: -1; margin: 2px 0 20px; }
.content:has(> .tabstrip) > .page-head { margin-bottom: 6px; }

/* ---------- Tooltip d'échéancier (colonne « Éch. ») ---------- */
.ech-cell { position: relative; }
.ech-cell .ech { cursor: pointer; text-decoration: none; }
.ech-cell .ech:hover { text-decoration: underline; }
.ech-tip {
  position: fixed; z-index: 60;
  min-width: 250px; max-width: 340px; text-align: left;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: 12px; box-shadow: var(--shadow-lift); padding: 10px 12px;
  display: none;
}
.ech-tip.show, .ech-tip.pinned { display: block; }
.ech-tip.pinned { outline: 2px solid var(--accent-soft); }

/* Le bouton à cliquer, désigné.

   Ouvrir le bon panneau ne suffisait pas : la checklist porte cinq à sept
   boutons et l'échéancier jusqu'à douze lignes, sans que celui qui fait
   avancer la vente se distingue des autres. On arrivait au bon endroit sans
   savoir où appuyer.

   Deux battements, puis un anneau qui s'efface : assez pour attirer l'œil,
   trop court pour devenir un décor qu'on cesse de voir. */
.a-faire {
  position: relative; z-index: 1;
  box-shadow: 0 0 0 3px var(--accent-soft), 0 0 0 4px var(--accent);
  border-color: var(--accent) !important;
  animation: a-faire-bat 1.1s ease-out 2;
}
@keyframes a-faire-bat {
  0%   { box-shadow: 0 0 0 0 rgba(42, 120, 214, .55), 0 0 0 4px var(--accent); }
  70%  { box-shadow: 0 0 0 10px rgba(42, 120, 214, 0), 0 0 0 4px var(--accent); }
  100% { box-shadow: 0 0 0 0 rgba(42, 120, 214, 0), 0 0 0 4px var(--accent); }
}
/* Qui préfère l'immobilité garde l'anneau : c'est lui qui porte l'information,
   le battement ne fait que la rendre plus rapide à trouver. */
@media (prefers-reduced-motion: reduce) {
  .a-faire { animation: none; }
}
.ech-tip-head { font-weight: 600; font-size: 12px; margin-bottom: 6px; color: var(--ink); }
.ei-line { display: flex; align-items: center; gap: 8px; padding: 4px 0; font-size: 12px; border-top: 1px solid var(--page); }
.ei-idx { width: 16px; color: var(--muted); text-align: center; }
.ei-amt { font-weight: 600; }
/* Les deux montants d'un règlement partiel : reçu et restant. Sur sa propre
   ligne, en petit — c'est une précision du montant, pas une colonne de plus. */
.ei-part { display: block; font-style: normal; font-weight: 500; font-size: 10.5px;
  color: var(--sem-attente-t); letter-spacing: -.1px; }
.ei-line.partielle { box-shadow: inset 2px 0 0 var(--sem-attente); padding-left: 6px; }

/* Ce qu'on ne peut pas encaisser tant que la facture est un brouillon. Gris,
   pas rouge : ce n'est pas une erreur, c'est un geste qui vient après. */
.ei-bloque, .statut-bloque {
  display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px;
  border-radius: 999px; font-size: 10.5px; font-weight: 600; cursor: help;
  background: var(--sem-ops-bg); color: var(--sem-ops-t);
  border: 1px solid #d5dae0; }
.statut-bloque { margin-top: 4px; }
.ei-due { color: var(--muted); }
.ei-due.late { color: var(--critical); font-weight: 600; }
.ei-ok { margin-left: auto; color: var(--good-text); font-weight: 600; }
.ei-form { margin-left: auto; }
.ech-tip-foot { display: block; margin-top: 8px; font-size: 11.5px; color: var(--accent); }
.btn.xs { padding: 1px 8px; font-size: 11px; line-height: 1.5; }

/* Closer éditable inline (select filtrable) */
.closer-edit { margin: 0; }
/* La colonne garde la même largeur avant et après transformation du champ :
   le <select> fait 108 px, l'enveloppe du combo aussi. Sans ça, la colonne
   sautait au premier clic. */
.col-closer { width: 124px; }
.closer-edit .sel-search { width: 108px; }
.closer-input {
  width: 108px; border: 1px solid transparent; background: transparent;
  padding: 3px 6px; border-radius: 6px; font: inherit; font-size: 13px; color: var(--ink);
  /* Un nom long (« Marie-Charlotte ») ne doit pas élargir la cellule. */
  text-overflow: ellipsis;
}
/* La liste, elle, peut être plus large que le champ : les noms doivent se lire. */
.closer-edit .sel-search .combo-list { min-width: 170px; }
.closer-input:hover { border-color: var(--hairline); background: var(--page); }
.closer-input:focus { outline: none; border-color: var(--accent); background: var(--surface); }

/* --------------------------------------------- Facturation depuis le registre
   Le bouton « Facturer » n'est pas une case de plus : c'est l'action qui
   appelle la comptabilité. Il se distingue des autres chips (accent, pas de
   gris) pour que l'œil la trouve sur une ligne qui en compte cinq. */
.task-chip.do-invoice {
  background: rgba(42, 120, 214, .10);
  border-color: var(--accent); color: var(--accent); font-weight: 600;
}
.task-chip.do-invoice:hover { background: var(--accent); color: #fff; }
.task-chip.do-invoice .tick { font-weight: 700; }

/* Tableau dense : l'échéancier du modal de facturation tient sans faire
   scroller la boîte. */
table.data.compact th, table.data.compact td { padding: 4px 8px; font-size: 12.5px; }
/* Ligne d'aide sous un intitulé de choix. */
.db { display: block; margin-top: 2px; }

/* ====================== Fiche vente : le parcours ======================
   Réunion du 07/07 : « ça va vraiment être les couleurs qui vont aider,
   sinon c'est pas compréhensible » (Céline) et « le détail ne doit pas
   arriver tout de suite » (Delphine). La couleur porte donc UN sens, toujours
   le même : vert = fait, bleu = c'est ici qu'on en est, rouge = ça coince,
   gris = pas encore son tour. */
.parcours {
  display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px;
}
.pas {
  display: flex; align-items: center; gap: 9px; flex: 1 1 190px;
  padding: 9px 12px; border-radius: 11px; border: 1px solid var(--hairline);
  background: var(--surface); min-width: 0;
}
.pas-pastille {
  width: 22px; height: 22px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700; background: var(--page);
  color: var(--muted); border: 1px solid var(--hairline);
}
.pas-txt { display: flex; flex-direction: column; min-width: 0; line-height: 1.3; }
/* Un pas peut porter son action : elle est là où se lit le manque, pas dans
   un en-tête à l'autre bout de la page. Le pas s'élargit en conséquence — il
   vaut mieux une carte plus large qu'un bouton coupé. */
.pas:has(.pas-actions) { flex: 1 1 330px; }
.pas-actions { display: flex; align-items: center; gap: 6px; margin-left: auto;
               flex-shrink: 0; }
.pas-actions .btn { white-space: nowrap; }
/* Champ pleine largeur dans un modal (le .form-row met les champs côte à côte). */
.fld-bloc { display: block; font-size: 12px; color: var(--ink-2); font-weight: 600;
            margin-top: 10px; }
.fld-bloc input { margin-top: 4px; font-weight: 400; }
.pas-txt b { font-size: 13px; }
.pas-detail {
  font-size: 11.5px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Fait */
.pas.fait { background: var(--good-tint); border-color: var(--good-tint-border); }
.pas.fait .pas-pastille { background: var(--good); border-color: var(--good); color: #fff; }
.pas.fait .pas-detail { color: var(--good-text); }
/* C'est ici qu'on en est — le seul pas mis en avant */
.pas.encours { border-color: var(--accent); background: #f4f9ff; box-shadow: 0 0 0 2px rgba(42,120,214,.12); }
.pas.encours .pas-pastille { background: var(--accent); border-color: var(--accent); color: #fff; }
.pas.encours .pas-detail { color: var(--accent-strong); }
/* Ça coince */
.pas.alerte { border-color: #f2bcbc; background: #fdf2f2; }
.pas.alerte .pas-pastille { background: var(--critical); border-color: var(--critical); color: #fff; }
.pas.alerte .pas-detail { color: #8f2020; }
/* Pas encore son tour */
.pas.avenir { opacity: .62; }

/* Jauge d'encaissement : combien est rentré sur le total. */
.jauge {
  height: 7px; border-radius: 4px; background: var(--page);
  border: 1px solid var(--hairline); overflow: hidden; margin: 2px 0 10px;
}
.jauge-in { height: 100%; background: var(--good); transition: width .3s; }

/* Une ligne d'encaissement. */
.enc-row {
  display: flex; align-items: center; gap: 9px; font-size: 13px;
  padding: 6px 0; border-bottom: 1px dashed var(--hairline);
}
.enc-row:last-child { border-bottom: none; }
.enc-date { color: var(--muted); flex-shrink: 0; font-size: 12px; }
.enc-lib { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.enc-amt { font-weight: 650; flex-shrink: 0; }

/* Ce qui sert rarement : présent, replié, hors du chemin. */
.repli { margin-top: 10px; }
.repli > summary {
  cursor: pointer; font-size: 12.5px; color: var(--muted);
  padding: 5px 0; list-style: none; user-select: none;
}
.repli > summary::before { content: "▸ "; }
.repli[open] > summary::before { content: "▾ "; }
.repli > summary:hover { color: var(--accent); }
.repli[open] > summary { color: var(--ink-2); margin-bottom: 6px; }
.repli h3 { margin: 12px 0 6px; font-size: 13px; }
.repli-row { gap: 6px; margin-bottom: 5px; align-items: center; }

/* ---- Modal « Rattacher » : de l'air entre les éléments ----
   Le premier jet empilait cinq lignes de petit texte sans séparation ; on ne
   distinguait pas une facture de la suivante. Ici chaque candidate est une
   ligne cliquable avec son propre padding, deux lignes de texte au lieu de
   quatre, et le motif en étiquette. */
.rat-vente {
  display: flex; flex-direction: column; gap: 3px; line-height: 1.4;
  background: var(--page); border-radius: 10px; padding: 11px 14px;
  margin-bottom: 16px; font-size: 12.5px; color: var(--muted);
}
.rat-v-haut { display: flex; align-items: baseline; gap: 12px; }
.rat-v-haut b { font-size: 14.5px; color: var(--ink); }
.rat-v-montant { margin-left: auto; font-variant-numeric: tabular-nums; }
.rat-v-bas { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.rat-bloc { margin-bottom: 12px; }
.rat-bloc[data-ech-zone] { margin-bottom: 10px; }
.rat-vide { margin: 0; padding: 14px; text-align: center; font-size: 12.5px;
  color: var(--muted); border: 1px dashed var(--hairline); border-radius: 10px; }
.rat-aide, .rat-etat { font-size: 12px; color: var(--muted); }

.rat-opt {
  display: flex; align-items: center; gap: 12px; cursor: pointer;
  padding: 12px 14px; border: 1px solid var(--hairline); border-radius: 11px;
  background: var(--surface); margin-bottom: 8px;
  transition: border-color .12s, background .12s, box-shadow .12s;
}
.rat-opt:hover { border-color: var(--accent-soft); }
.rat-opt.choisi { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
/* La facture sûre : le vert de la facturation. */
.rat-opt.sure { border-color: var(--good-tint-border); background: var(--sem-facture-bg); }
.rat-opt.sure.choisi { border-color: var(--sem-facture);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--sem-facture) 18%, transparent); }
.rat-opt.probable .rat-motif { color: var(--sem-attente-t); background: var(--sem-attente-bg);
  border-color: #ecd3a1; }
.rat-opt.pris { opacity: .55; cursor: default; }
.rat-opt > input[type="radio"] { flex-shrink: 0; margin: 0; accent-color: var(--sem-facture); }
.rat-corps { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1; }
.rat-ligne1 { display: flex; align-items: center; gap: 8px; }
.rat-ligne1 b { font-size: 13.5px; font-variant-numeric: tabular-nums; }
.rat-montant { margin-left: auto; font-weight: 700; font-size: 14px; white-space: nowrap;
  font-variant-numeric: tabular-nums; }
.rat-ligne2 { font-size: 12px; color: var(--muted);
              overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rat-motif {
  align-self: flex-start; font-size: 11px; font-weight: 600; color: var(--ink-2);
  background: var(--page); border: 1px solid var(--hairline);
  border-radius: 999px; padding: 1px 9px;
}
.rat-opt.sure .rat-motif { color: var(--sem-facture-t); background: #fff;
  border-color: var(--good-tint-border); }
.rat-motif.pris { color: var(--sem-defaut-t); background: var(--sem-defaut-bg); border-color: transparent; }
/* L'état de la facture dans Sellsy : une pastille, la couleur dit tout. */
.rat-statut { font-size: 10.5px; font-weight: 700; padding: 1px 8px; border-radius: 999px;
  white-space: nowrap; }
.rat-statut.st-paid { color: var(--sem-facture-t); background: var(--good-tint); }
.rat-statut.st-payinprogress { color: var(--sem-vente-t); background: var(--sem-vente-bg); }
.rat-statut.st-due { color: var(--sem-attente-t); background: var(--sem-attente-bg); }
.rat-statut.st-late { color: var(--sem-defaut-t); background: var(--sem-defaut-bg); }
.rat-statut.st-cancelled { color: var(--muted); background: var(--page); }
.rat-voir { flex-shrink: 0; display: grid; place-items: center; width: 28px; height: 28px;
  border-radius: 8px; color: var(--muted); text-decoration: none; font-size: 14px; }
.rat-voir:hover { background: var(--page); color: var(--accent); }

.rat-autre { margin: 4px 0 0; }
.rat-autre summary { cursor: pointer; font-size: 12.5px; color: var(--accent); font-weight: 600;
  list-style: none; display: inline-flex; align-items: center; gap: 6px; }
.rat-autre summary::-webkit-details-marker { display: none; }
.rat-autre summary::before { content: "+"; font-weight: 700; }
.rat-autre[open] summary::before { content: "−"; }
.rat-autre form { margin: 8px 0 4px; }
.rat-autre input { width: 100%; }

.rat-actions {
  display: flex; align-items: center; gap: 8px;
  margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--hairline);
}
.rat-actions .rat-etat { margin: 0 auto 0 0; font-variant-numeric: tabular-nums; }

/* Quand il n'y a rien à arbitrer, une ligne suffit. */
.ech-ok {
  font-size: 12.5px; color: var(--good-text); background: var(--good-tint);
  border: 1px solid var(--good-tint-border); border-radius: 9px; padding: 8px 11px;
}
.ech-ok + .ech-ok { margin-top: 7px; }
.ech-ok.warn { color: #8a5f00; background: #fdf3dc; border-color: #f3dda6; }

/* Les deux échéanciers côte à côte, au moment de rattacher. La décision se
   prend en voyant les dates, pas en lisant un avertissement. */
.ech-compare {
  border: 1px solid #f3dda6; background: #fdf9f0; border-radius: 11px;
  padding: 11px 13px; margin-top: 10px;
}
.ech-compare-head { font-weight: 650; font-size: 13px; color: #8a5f00; margin-bottom: 8px; }
.ech-compare table.data th { background: transparent; }
.ech-compare .ech-late { color: var(--critical); font-weight: 600; }
.ech-compare .ech-neuf { color: var(--accent-strong); font-weight: 650; }
.ech-choix { display: flex; flex-direction: column; gap: 6px; margin: 10px 0 8px; }
.ech-choix .radio-tile { background: var(--surface); }
.ech-choix .radio-tile b { font-size: 13px; }

/* SweetAlert2 habillé avec NOTRE système : mêmes boutons, mêmes rayons, même
   typographie. Une boîte de confirmation qui ne ressemble pas au reste de
   l'outil se fait cliquer sans être lue. */
.swal2-container { z-index: 200; }
.sw-popup {
  border-radius: 16px; border: 1px solid var(--hairline);
  box-shadow: var(--shadow-lift); font-family: inherit;
  padding: 22px 24px 18px; background: var(--surface);
}
.sw-title { font-size: 17px; font-weight: 650; color: var(--ink); padding: 0; }
.sw-text { font-size: 13.5px; color: var(--ink-2); line-height: 1.5; margin-top: 6px; }
.sw-actions { gap: 8px; margin-top: 18px; }
.sw-actions .btn { min-width: 104px; justify-content: center; }
.swal2-icon { margin: 4px auto 10px; }

/* Modal « Régler une échéance ». */
.pay-cible {
  background: var(--page); border-radius: 9px; padding: 8px 11px;
  font-size: 13px; margin-bottom: 12px; color: var(--ink-2);
}
#paiement-modal .form-row { margin-bottom: 8px; }

/* ---- Calendrier des échéances : une colonne par semaine ---- */
.cal-strip {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 10px; align-items: start;
}
.cal-week {
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: 11px; padding: 9px 11px;
}
.cal-week.now { border-color: var(--accent); box-shadow: 0 0 0 2px rgba(42, 120, 214, .1); }
.cal-week.risk { border-color: #efb4b4; }
.cal-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 6px; }
.cal-when { font-weight: 650; font-size: 12.5px; }
.cal-sum { margin-left: auto; font-size: 12.5px; font-weight: 650; color: var(--muted); }
.cal-flag {
  font-size: 11px; font-weight: 650; color: #8d2020; background: #fdeeee;
  border-radius: 6px; padding: 1px 6px; display: inline-block; margin-bottom: 5px;
}
.cal-line {
  display: flex; align-items: center; gap: 6px; font-size: 12px;
  padding: 3px 0; border-top: 1px solid var(--hairline);
}
.cal-line:first-of-type { border-top: none; }
.cal-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; background: var(--muted); }
.cal-line.t-verde   .cal-dot { background: var(--good); }
.cal-line.t-naranja .cal-dot { background: var(--warning); }
.cal-line.t-rojo    .cal-dot { background: var(--critical); }
.cal-line.t-amarillo .cal-dot {
  background: linear-gradient(90deg, var(--good) 50%, #d8d8d0 50%); }
.cal-date { color: var(--muted); flex-shrink: 0; }
.cal-who { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cal-amt { font-weight: 600; flex-shrink: 0; }
.cal-ok { color: var(--good); font-weight: 700; flex-shrink: 0; }
.cal-act { display: flex; gap: 2px; flex-shrink: 0; }
.cal-act .btn.xs { padding: 0 5px; }

/* Modal « Encaissements » (remplace la page Virements). */
/* ======================= Modal « Encaissements » =======================
   Deux temps numérotés : ① le justificatif, ② la vérification. C'est l'ordre
   réel du geste d'Al — il a le papier dans la main avant d'avoir le clavier.
   Le vert sémantique est réservé à l'argent qui entre ; la sortie B-Sport
   prend l'ardoise, parce que ce n'est pas un encaissement. */
.modal-box.enc-box { width: min(1080px, 96vw); }
.enc-head {
  align-items: flex-start; margin: -20px -22px 18px; padding: 16px 22px 14px;
  background: var(--sem-facture-bg);
  border-bottom: 1px solid #d9ece2; border-radius: 16px 16px 0 0;
}
.enc-head .grow { line-height: 1.35; }
.enc-head > .grow > b { color: var(--sem-facture-t); font-size: 15.5px; }
.enc-count {
  display: flex; align-items: center; gap: 9px; margin-right: 14px;
  background: var(--sem-attente-bg); border: 1px solid #f0dcb4;
  border-radius: 10px; padding: 5px 11px; cursor: default;
}
.enc-count-n { font-size: 20px; font-weight: 700; color: var(--sem-attente-t); line-height: 1; }
.enc-count-l { font-size: 10.5px; color: var(--sem-attente-t); line-height: 1.25; }

.enc-grid { display: grid; grid-template-columns: minmax(0, 1.04fr) minmax(0, 1fr); gap: 24px; }
@media (max-width: 900px) { .enc-grid { grid-template-columns: minmax(0, 1fr); } }
.enc-form { margin: 0; }

/* ---- En-têtes d'étape ---- */
.enc-step { display: flex; align-items: center; gap: 9px; margin: 0 0 10px; }
.enc-step + .segmented, .enc-step + .dropzone { margin-top: 0; }
.enc-step h3 { margin: 0; font-size: 13.5px; }
.enc-step.plain { margin-bottom: 12px; }
.enc-step.gap { margin-top: 20px; }
.enc-num {
  display: inline-grid; place-items: center; width: 21px; height: 21px;
  border-radius: 50%; background: var(--sem-facture); color: #fff;
  font-size: 11px; font-weight: 700; flex: none;
  box-shadow: 0 0 0 3px var(--sem-facture-bg);
}
/* La colonne de droite n'est pas une étape : c'est la file d'attente, et
   l'ambre est la couleur de ce qui reste à traiter. */
.enc-queue .enc-step h3::before {
  content: ""; display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  background: var(--sem-attente); margin-right: 7px; vertical-align: 1px;
}
.enc-queue:has(.enc-empty) .enc-step h3::before { background: var(--sem-facture); }

/* ---- Zone de dépôt : un seul état à la fois (voir la règle `[hidden]`) ---- */
.dropzone {
  position: relative; overflow: hidden;
  border: 1.5px dashed #b6d8c4; border-radius: 14px;
  background: #f4fbf7;
  padding: 20px 16px; text-align: center; cursor: pointer;
  transition: border-color .14s, background .14s, box-shadow .14s;
}
.dropzone:hover, .dropzone:focus-visible {
  border-color: var(--sem-facture); background: var(--sem-facture-bg); outline: none;
  box-shadow: 0 0 0 3px rgba(31, 157, 91, .09);
}
.dropzone.over {
  border-color: var(--sem-facture); border-style: solid; background: var(--sem-facture-bg);
  box-shadow: 0 0 0 5px rgba(31, 157, 91, .14);
}
.dropzone.busy {
  cursor: progress; border-style: solid; border-color: var(--sem-vente);
  background: var(--sem-vente-bg);
}
.dropzone.done {
  cursor: default; border-style: solid; border-color: var(--sem-facture);
  background: var(--sem-facture-bg); text-align: left;
}
.dropzone.failed {
  border-color: var(--sem-attente); background: var(--sem-attente-bg);
}
.dz-busy, .dz-done { display: flex; align-items: center; gap: 12px; text-align: left; }

.dz-icon {
  width: 42px; height: 42px; margin: 0 auto 9px; display: grid; place-items: center;
  border-radius: 50%; background: var(--sem-facture-bg); color: var(--sem-facture-t);
  border: 1px solid #cfe8db; transition: transform .14s, background .14s;
}
.dropzone:hover .dz-icon { background: #d7f0e3; transform: translateY(-2px); }
.dropzone.over .dz-icon { background: var(--sem-facture); color: #fff; border-color: var(--sem-facture); transform: scale(1.06); }
.dz-title { font-size: 13px; font-weight: 600; color: var(--ink); }
.dz-sub { font-size: 11.5px; color: var(--ink-2); margin-top: 4px; }
.dz-sub b {
  color: #fff; background: var(--sem-facture); border-radius: 20px;
  padding: 2px 10px; font-size: 11px; margin-right: 4px;
}
.dz-busy .dz-title { color: var(--sem-vente-t); }
.dz-sub b.nom {
  background: rgba(42, 120, 214, .12); color: var(--sem-vente-t);
  border-radius: 5px; padding: 1px 6px; font-weight: 600;
}
.dz-sub b.nom:empty { display: none; }
.dropzone:hover .dz-sub b { background: var(--sem-facture-t); }
.dz-sub kbd {
  font: inherit; font-size: 10.5px; background: var(--surface); color: var(--ink-2);
  border: 1px solid var(--hairline); border-bottom-width: 2px; border-radius: 4px; padding: 0 4px;
}
.dz-thumb {
  width: 56px; height: 42px; object-fit: cover; border-radius: 8px; flex: none;
  border: 2px solid #fff; box-shadow: 0 1px 4px rgba(11, 11, 11, .14);
}
.dz-file {
  width: 42px; height: 42px; flex: none; display: grid; place-items: center;
  border-radius: 8px; background: var(--sem-peda-bg); border: 1px solid #d5daf1;
  font-size: 9.5px; font-weight: 700; color: var(--sem-peda-t); letter-spacing: .04em;
}
.dz-done .dz-title { color: var(--sem-facture-t); }
.dropzone.failed .dz-done .dz-title { color: var(--sem-attente-t); }
.dz-drop-x {
  border: none; background: none; cursor: pointer; color: var(--muted);
  font-size: 13px; padding: 4px 2px; line-height: 1; flex: none;
}
.dz-drop-x:hover { color: var(--critical); }

/* Pendant la lecture : le sablier tourne ET une barre traverse le bas de la
   zone. Deux signaux valent mieux qu'un quand on attend le résultat d'un
   modèle dont on ne peut pas connaître l'avancement. */
.spinner {
  width: 26px; height: 26px; flex: none; border-radius: 50%;
  border: 3px solid rgba(42, 120, 214, .18); border-top-color: var(--sem-vente);
  animation: spin .7s linear infinite;
}
/* La version BOUTON : elle prend la couleur du texte, donc elle se voit
   aussi bien sur un bouton bleu (texte blanc) que sur un bouton neutre. */
.spinner.sm { display: inline-block; width: 14px; height: 14px; border-width: 2px;
              border-color: color-mix(in srgb, currentColor 28%, transparent);
              border-top-color: currentColor; margin-right: 7px; vertical-align: -2px; }
button[aria-busy="true"] { cursor: progress; }
/* Pendant l'envoi, les AUTRES boutons s'effacent. Désactivés, ils gardaient
   leur couleur : « Valider la vente » restait bleu vif pendant que la
   facturation tournait, et se donnait l'air de pouvoir encore être cliqué. */
form[aria-busy="true"] button[type=submit]:disabled:not([aria-busy]) {
  opacity: .45; cursor: not-allowed; }
@media (prefers-reduced-motion: reduce) { .spinner.sm { animation-duration: 1.6s; } }
.dropzone.busy::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 3px;
  background: var(--sem-vente);
  animation: scan-bar 1.15s ease-in-out infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes scan-bar { 0% { transform: translateX(-100%); } 100% { transform: translateX(100%); } }
/* En mouvement réduit, le réglage global coupe les deux animations : c'est le
   libellé qui porte l'information (« Envoi… », « Lecture… »), pas le sablier. */

/* ---- Avis de lecture ---- */
.enc-alert {
  border-radius: 10px; padding: 9px 12px; font-size: 12.5px; margin: 10px 0 0;
  border: 1px solid; animation: rise .2s ease both; line-height: 1.45;
}
.enc-alert.ok   { background: var(--sem-facture-bg); border-color: #bfe6cf; color: var(--sem-facture-t); }
.enc-alert.warn { background: var(--sem-attente-bg); border-color: #f0dcb4; color: var(--sem-attente-t); }
.enc-alert.stop { background: var(--sem-defaut-bg);  border-color: #f2ccc4; color: var(--sem-defaut-t); }
.enc-alert b { font-weight: 700; }

/* ---- Sélecteur de type ---- */
.segmented { display: flex; gap: 0; border: 0; padding: 0; margin: 0 0 12px; flex-wrap: wrap; }
.segmented .seg { flex: 1; min-width: 84px; }
.segmented .seg input { position: absolute; opacity: 0; width: 0; height: 0; }
.segmented .seg span {
  display: block; text-align: center; font-size: 12px; font-weight: 600; color: var(--ink-2);
  background: var(--page); border: 1px solid var(--hairline); padding: 7px 6px; cursor: pointer;
  transition: background .12s, color .12s, border-color .12s;
}
.segmented .seg:first-child span { border-radius: 9px 0 0 9px; }
.segmented .seg:last-child span  { border-radius: 0 9px 9px 0; }
.segmented .seg + .seg span { border-left: none; }
.segmented .seg span:hover { background: var(--surface); color: var(--ink); }
.segmented .seg.in  input:checked + span {
  background: var(--sem-facture); border-color: var(--sem-facture); color: #fff;
}
.segmented .seg.out input:checked + span {
  background: var(--sem-ops); border-color: var(--sem-ops); color: #fff;
}
.segmented .seg input:focus-visible + span { box-shadow: 0 0 0 3px rgba(42, 120, 214, .22); position: relative; z-index: 1; }

/* ---- Champs ---- */
.enc-form .fld {
  display: block; position: relative; font-size: 12px; color: var(--ink-2);
  font-weight: 600; margin-bottom: 10px;
}
.enc-form .fld input { margin-top: 4px; font-weight: 400; }
.enc-form .form-row { margin-bottom: 0; }

/* ---- À quelle vente ? Le rapprochement, pendant la saisie --------------
   Il n'existait qu'après coup, dans une file séparée. Facultatif : sans
   choix, le mouvement part en file comme avant. */
.enc-vente { margin: 12px 0 4px; padding: 11px 12px; border-radius: 11px;
  background: var(--page); border: 1px solid var(--hairline); }
.ev-tete { display: flex; justify-content: space-between; align-items: baseline;
  font-size: 12px; font-weight: 600; color: var(--ink-2); margin-bottom: 8px; }
.ev-tete i { font-style: normal; font-weight: 400; font-size: 10.5px;
  color: var(--muted); }
.ev-etat { font-size: 11px; font-weight: 500; color: var(--muted); }

/* La recherche libre : la porte de sortie quand aucun montant ne colle. */
.ev-q { width: 100%; margin-bottom: 7px; padding: 7px 11px; font-size: 12px;
  border-radius: 8px; border: 1px solid var(--hairline); background: var(--surface); }
.ev-q:focus { outline: none; border-color: var(--accent); }

.ev-liste { display: flex; flex-direction: column; gap: 5px;
  max-height: 208px; overflow-y: auto; }
.ev-item { display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: 1px 10px; width: 100%; text-align: left; cursor: pointer;
  padding: 8px 11px; border-radius: 9px; font: inherit;
  background: var(--surface); border: 1px solid var(--hairline); }
.ev-item:hover { border-color: var(--accent); }
.ev-item b { font-size: 12.5px; color: var(--ink); }
.ev-item .ev-prod { grid-column: 1; font-size: 11px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Le motif est ce qui permet de trancher entre deux ventes du même montant :
   « montant exact » et « échéance n°2 » ne se valident pas pareil. */
.ev-item .ev-motif { grid-column: 2; grid-row: 2; font-size: 10.5px;
  color: var(--sem-attente-t); text-align: right; }
.ev-item.colle .ev-motif { color: var(--sem-facture-t); }
.ev-item:not(.colle) .ev-motif { color: var(--sem-attente-t); }
.ev-item .ev-mt { grid-column: 2; grid-row: 1; font-weight: 700; font-size: 12.5px;
  font-variant-numeric: tabular-nums; text-align: right; }

.ev-item.actif { border-color: var(--accent-strong); background: var(--accent-soft); }
.ev-item.actif b { color: var(--accent-strong); }
.ev-plus-tard { grid-template-columns: 1fr; }
.ev-plus-tard span { font-size: 11px; color: var(--muted); }
.ev-plus-tard.actif span { color: var(--accent-strong); }
.enc-form .form-row > .fld { flex: 1; min-width: 130px; }
.fld-in { position: relative; display: block; }
.fld-in i {
  position: absolute; right: 11px; top: calc(50% + 2px); transform: translateY(-50%);
  font-style: normal; color: var(--muted); font-size: 12.5px; pointer-events: none;
}
.fld.money input { padding-right: 26px; font-variant-numeric: tabular-nums; }
/* Rempli par la lecture automatique : visible mais pas criard, et ça
   disparaît dès qu'une personne y touche. */
.fld.auto > input, .fld.auto .fld-in > input {
  border-color: #bfe6cf;
  background: var(--sem-facture-bg);
}
.fld.auto::after {
  content: "lu"; position: absolute; right: 0; top: 0;
  font-size: 9.5px; font-weight: 700; letter-spacing: .04em;
  color: var(--sem-facture-t); background: var(--sem-facture-bg);
  border: 1px solid #bfe6cf; border-radius: 4px; padding: 0 4px;
}
.enc-actions { display: flex; align-items: center; gap: 12px; margin-top: 16px; flex-wrap: wrap; }
.enc-actions .btn { flex: none; }
/* De l'argent qui entre : vert, comme partout ailleurs dans la plateforme.
   Le bleu est la couleur des ventes, pas celle de l'encaissement. */
.enc-actions .btn.primary {
  background: var(--sem-facture);
  border-color: var(--sem-facture-t);
}
.enc-actions .btn.primary:hover {
  background: var(--sem-facture-t); box-shadow: 0 4px 12px rgba(31, 157, 91, .28);
}
.enc-queue .btn.primary {
  background: var(--sem-facture);
  border-color: var(--sem-facture-t);
}
.enc-queue .btn.primary:hover {
  background: var(--sem-facture-t); box-shadow: 0 4px 12px rgba(31, 157, 91, .28);
}

/* ---- File à rapprocher ---- */
.enc-queue { min-width: 0; }
.enc-item {
  border: 1px solid var(--hairline); border-radius: 11px; padding: 10px 12px;
  margin-bottom: 9px; background: var(--page);
}
.enc-item.accent { border-color: var(--sem-vente); background: var(--sem-vente-bg); }
.enc-item-head { display: flex; align-items: baseline; gap: 8px; }
.enc-amount { font-size: 15px; font-variant-numeric: tabular-nums; margin-left: auto; }
.enc-item-sub { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--ink-2); margin-top: 3px; }
.enc-item-sub .tag.pj { text-decoration: none; }
.enc-item-sub .tag.pj:hover { border-color: var(--sem-vente); color: var(--sem-vente-t); }
.enc-prop {
  display: flex; align-items: center; gap: 8px; font-size: 12.5px;
  border-top: 1px solid var(--hairline); padding: 7px 0 0; margin-top: 7px;
}
.enc-prop:first-of-type { margin-top: 9px; }
.chip {
  font-size: 10.5px; font-weight: 650; padding: 2px 8px; border-radius: 20px;
  white-space: nowrap; border: 1px solid transparent;
}
.chip.c-virement { background: var(--sem-facture-bg); color: var(--sem-facture-t); border-color: #cfe8db; }
.chip.c-cheque   { background: var(--sem-peda-bg);    color: var(--sem-peda-t);    border-color: #d5daf1; }
.chip.c-payout   { background: var(--sem-vente-bg);   color: var(--sem-vente-t);   border-color: #cbdff8; }
.chip.c-salida   { background: var(--sem-ops-bg);     color: var(--sem-ops-t);     border-color: #d9dee4; }
.enc-empty { display: flex; align-items: center; gap: 12px; padding: 20px 16px; color: var(--ink-2); }
.enc-empty-i {
  width: 34px; height: 34px; flex: none; display: grid; place-items: center;
  border-radius: 50%; background: var(--sem-facture-bg); color: var(--sem-facture-t);
  font-size: 16px; font-weight: 700;
}
.enc-journal { margin-top: 18px; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
/* La tira de alerta admite ahora un <button>, no solo un <a>. */
.alert-strip .al { font: inherit; text-align: left; cursor: pointer; }

/* ============================ Modal « Générer la facture » ============================
   Deux colonnes : saisie à gauche, aperçu à droite. L'aperçu imite une feuille
   de facture parce que c'est ce qu'Irina compare mentalement avec Sellsy. */
.modal-box.invoice { width: 1080px; }
.inv-loading { padding: 40px; text-align: center; color: var(--muted); }
.inv-form { margin: 0; }
.inv-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 420px); gap: 20px; }
@media (max-width: 980px) { .inv-grid { grid-template-columns: minmax(0, 1fr); } }
.inv-fields h3 { margin: 0 0 8px; }
.inv-fields .divider { margin: 14px 0 12px; }

.inv-client {
  display: flex; align-items: center; gap: 10px; padding: 8px 10px;
  background: var(--page); border-radius: 10px; margin-bottom: 10px;
}
.inv-client-id { flex: 1; display: flex; flex-direction: column; line-height: 1.35; }

/* Une ligne de facture : désignation · quantité · montant · suppression. */
.inv-line {
  display: grid; grid-template-columns: minmax(0, 1fr) 62px 116px 26px;
  gap: 6px; align-items: center; margin-bottom: 5px;
}
.inv-line input { width: 100%; }
.inv-line-head {
  font-size: 11px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted); margin-bottom: 4px;
}
.inv-line-head .num { text-align: right; }
.inv-del {
  border: none; background: none; color: var(--muted); cursor: pointer;
  font-size: 13px; line-height: 1; padding: 2px;
}
.inv-del:hover { color: var(--critical); }

.inv-alert {
  padding: 8px 11px; border-radius: 9px; margin-bottom: 10px; font-size: 13px;
  background: var(--warning-tint, #fff6e0); border: 1px solid #e8c98a; color: #6b4f11;
}
.inv-alert.stop { background: #fdecec; border-color: #efb4b4; color: #8d2020; }

/* Doublon détecté avant de facturer. */
.inv-dup {
  border: 1px solid #e8c98a; background: #fff9ec; border-radius: 11px;
  padding: 11px 13px; margin-bottom: 12px;
}
.inv-dup.sure { border-color: #efb4b4; background: #fdeeee; }
.inv-dup-head { font-weight: 650; font-size: 13.5px; margin-bottom: 3px; color: #6b4f11; }
.inv-dup.sure .inv-dup-head { color: #8d2020; }
.inv-dup p { margin: 0 0 8px; }
.inv-dup-row {
  display: flex; align-items: flex-start; gap: 10px; padding: 7px 0;
  border-top: 1px solid rgba(0, 0, 0, .07);
}
.inv-dup-id { flex: 1; display: flex; flex-direction: column; line-height: 1.4; min-width: 0; }
.inv-dup-act { display: flex; gap: 5px; align-items: center; flex-shrink: 0; }

/* Échéancier modifiable avant émission — après, la comptabilité le fige. */
.ech-edit-head, .ech-edit {
  display: grid; grid-template-columns: 26px 1fr 108px 62px;
  gap: 6px; align-items: center;
}
.ech-edit-head {
  font-size: 11px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted); margin-bottom: 4px;
}
.ech-edit-head .num { text-align: right; }
.ech-edit { margin-bottom: 5px; }
.ech-edit-n { font-size: 12.5px; color: var(--muted); text-align: center; }
.ech-edit input[readonly] { background: var(--page); color: var(--muted); cursor: default; }
.ech-edit-etat { font-size: 11px; }

/* ---- La feuille d'aperçu ---- */
.inv-preview-col { display: flex; flex-direction: column; gap: 12px; }
.inv-sheet {
  background: #fff; color: #14130f; border: 1px solid var(--hairline);
  border-radius: 12px; padding: 18px 20px; font-size: 12.5px;
}
.inv-sheet-head { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 14px; }
.inv-sheet-brand { font-weight: 700; letter-spacing: .16em; font-size: 15px; }
.inv-sheet-title { font-size: 17px; font-weight: 700; letter-spacing: .06em; }
.inv-sheet-to { margin-bottom: 10px; line-height: 1.45; }
.inv-sheet-subject {
  font-size: 12px; color: #55524a; padding: 6px 0; margin-bottom: 6px;
  border-top: 1px solid #ece9e1; border-bottom: 1px solid #ece9e1;
}
.inv-sheet-lines { width: 100%; border-collapse: collapse; }
.inv-sheet-lines th {
  text-align: left; font-size: 10.5px; text-transform: uppercase;
  letter-spacing: .04em; color: #7d7970; padding: 4px 0; border-bottom: 1px solid #ece9e1;
}
.inv-sheet-lines td { padding: 6px 0; border-bottom: 1px solid #f3f1ea; vertical-align: top; }
.inv-sheet-lines .num, .inv-sheet-totals .num { text-align: right; }
.inv-sheet-lines tr.remise td { color: #8d2020; }
/* Le récapitulatif de l'assiette de TVA, comme sur la facture Sellsy :
   petit, aligné à droite, au-dessus des totaux. Ce n'est pas décoratif — c'est
   la ligne que l'expert-comptable cherche. */
.inv-sheet-tva { margin: 10px 0 0 auto; border-collapse: collapse;
                 font-size: 11.5px; color: var(--muted); }
.inv-sheet-tva th { text-align: left; font-weight: 600; padding: 2px 0 2px 16px;
                    border-bottom: 1px solid #f3f1ea; }
.inv-sheet-tva td { padding: 2px 0 2px 16px; font-variant-numeric: tabular-nums; }
.inv-sheet-tva .num { text-align: right; }
/* Six colonnes au lieu de quatre : la désignation prend ce qui reste, les
   chiffres se serrent et s'alignent sur la virgule. */
.inv-sheet-lines td, .inv-sheet-lines th { font-variant-numeric: tabular-nums; }
.inv-sheet-lines td:first-child, .inv-sheet-lines th:first-child { width: 40%; }
.inv-sheet-totals { width: 100%; margin-top: 8px; border-collapse: collapse; }
.inv-sheet-totals td { padding: 3px 0; color: #55524a; }
.inv-sheet-totals tr.grand td {
  padding-top: 7px; border-top: 1px solid #d9d5cb; font-size: 14px;
  font-weight: 700; color: #14130f;
}
.inv-sheet-source { margin-top: 10px; font-size: 11px; color: #7d7970; line-height: 1.4; }
.inv-sheet-ech { margin-top: 12px; border-top: 1px solid #ece9e1; padding-top: 8px; }
.inv-sheet-ech-head { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: #7d7970; margin-bottom: 5px; }
.inv-ech-line {
  display: grid; grid-template-columns: 22px 1fr 74px 72px; gap: 6px;
  font-size: 11.5px; padding: 1.5px 0; color: #55524a;
}
.inv-ech-line .num { text-align: right; }
.inv-ech-line .ok { color: #1f7a44; font-weight: 600; }

.inv-effects {
  background: var(--page); border-radius: 11px; padding: 11px 13px; font-size: 12.5px;
}
.inv-effects-head { font-weight: 650; margin-bottom: 5px; }
.inv-effects ul { margin: 0; padding-left: 17px; line-height: 1.55; }
.inv-payload { margin-top: 9px; }
.inv-payload summary { cursor: pointer; color: var(--muted); font-size: 11.5px; }
.inv-payload pre {
  max-height: 230px; overflow: auto; margin-top: 6px; padding: 8px;
  background: var(--surface); border: 1px solid var(--hairline); border-radius: 8px;
  font-size: 11px; line-height: 1.45;
}
.inv-actions { display: flex; align-items: center; gap: 8px; margin-top: 16px; }
.inv-actions .right { margin-left: auto; }

/* Chip « Paiement » verrouillé (fractionné : régler les échéances) */
.task-chip.locked { cursor: default; opacity: .75; }
.task-chip.locked:hover { border-color: var(--hairline); color: var(--muted); }
/* Fermée MAIS elle mène quelque part : l'échéancier, ou le bouton qui émet la
   facture. Un curseur en main le promet, et le survol le confirme — c'est ce
   qui distingue « tu ne peux pas » de « pas ici, là ». */
.task-chip.locked[data-ouvrir-ech], .task-chip.locked[data-viser-facture] {
  cursor: pointer; opacity: .85;
}
.task-chip.locked[data-ouvrir-ech]:hover,
.task-chip.locked[data-viser-facture]:hover {
  border-color: var(--sem-attente); color: var(--sem-attente-t);
  background: var(--sem-attente-bg); opacity: 1;
}

/* ---------- Pagination ---------- */
.pagination { display: flex; align-items: center; justify-content: center; gap: 14px; margin-top: 16px; }
.pagination .btn.disabled { opacity: .4; pointer-events: none; }

/* ---------- Registre des ventes : suivi de réalisation (modèle Jimmy) ---------- */
.sales-log td { vertical-align: top; }
.nowrap { white-space: nowrap; }
.flag-warn { display: inline-block; margin-top: 2px; color: var(--serious); font-size: 11px; font-weight: 600; }
tr.row-attention > td { background: var(--attention-bg); }
tr.row-attention > td:first-child { box-shadow: inset 3px 0 0 var(--warning); }

/* Registre : la ligne n'est colorée QUE par le retard (jaune < J+7, rouge ≥ J+7).
   Les ventes « normales » en attente de validation/vérif gardent juste leur badge. */
tr.row-late-amber > td { background: var(--sem-attente-bg); }
tr.row-late-amber > td:first-child { box-shadow: inset 3px 0 0 var(--sem-attente); }
tr.row-late-amber:hover > td { background: #f7ead1; }
tr.row-late-red > td { background: var(--sem-defaut-bg); }
tr.row-late-red > td:first-child { box-shadow: inset 3px 0 0 var(--sem-defaut); }
tr.row-late-red:hover > td { background: #f8ddda; }
/* Registre plus compact */
.sales-log td { padding: 4px 10px; }
.sales-log .task-chip { padding: 2px 7px; }
/* Puce de couleur des filtres de retard */
.fdot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 6px; vertical-align: middle; }
.fdot.red { background: var(--sem-defaut); }
.fdot.amber { background: var(--sem-attente); }
/* Barre de filtres du registre : une seule ligne compacte (chips + recherche + selects) */
.filter-bar { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; margin-bottom: 12px; }
.filter-form { display: contents; }
/* Le champ de recherche et son témoin : « … » pendant l'aller-retour, « ⚠ »
   si le serveur n'a pas répondu. Sans lui, une frappe sans effet visible
   pendant trois cents millisecondes se lit comme une panne. */
.f-chercher { position: relative; display: inline-flex; align-items: center; }
.f-etat { position: absolute; right: 8px; font-size: 11px; color: var(--muted); pointer-events: none; }
.filter-sep { width: 1px; align-self: stretch; min-height: 22px; background: var(--hairline); margin: 0 3px; }
.filter-bar input, .filter-bar select {
  font: inherit; font-size: 12.5px; height: 30px; padding: 3px 7px;
  border: 1px solid var(--hairline); border-radius: 8px; background: var(--surface); color: var(--ink);
}
/* Tout ce qui vit dans cette barre a la MÊME hauteur et le même arrondi.
   Les `.btn.xs` sont dimensionnés par leur rembourrage (≈ 21 px) et les
   champs par une hauteur fixe (30 px) : côte à côte, la rangée était en
   escalier. Ça vaut aussi pour le registre des ventes, qui partage la barre. */
.filter-bar .btn {
  height: 30px; padding: 0 11px; font-size: 12.5px; border-radius: 8px;
}
.filter-bar .btn:hover { transform: none; box-shadow: none; }

.filter-bar .f-search { width: 146px; }
.filter-bar select { max-width: 116px; }
.filter-bar .f-date { width: 110px; }
.filter-count { margin-left: auto; white-space: nowrap; }
/* KPIs du registre : compacts et non étirés (capés à gauche) */
.kpi-strip.kpi-tight { grid-template-columns: repeat(auto-fit, minmax(108px, 152px)); justify-content: start; margin-bottom: 12px; }
.kpi-tight .kpi-s { padding: 7px 10px; }
.kpi-tight .kpi-s .l { font-size: 10.5px; }
.kpi-tight .kpi-s .v { font-size: 16px; }
.task-chips { display: flex; flex-wrap: wrap; gap: 4px; margin: 0; }
.task-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 9px; border-radius: 999px; font-size: 11.5px; line-height: 1.4; cursor: pointer;
  border: 1px solid var(--hairline); background: var(--surface); color: var(--muted);
  transition: background .12s, color .12s, border-color .12s;
}
.task-chip .tick { font-size: 11px; }
.task-chip:hover { border-color: var(--accent); color: var(--ink); }
.task-chip.done { background: var(--good-tint); border-color: var(--good-tint-border); color: var(--good-text); font-weight: 600; }
.task-chip.done .tick { color: var(--good); }

/* ---- Tâches : indicateur compact ●●●○○ n/total + popover interactif au survol ----
   Les puces dérivent des vraies cases (fulfillment_progress) ; le popover garde
   TOUS les contrôles réels (toggle, « Générer la facture », « Rattacher »).
   Il est en position:fixed (posé par un petit script) pour ne pas être rogné
   par le scroll de .table-scroll, exactement comme l'info-bulle d'échéancier. */
.tache-cell { position: relative; }
.tache-mini {
  display: inline-flex; align-items: center; gap: 7px; cursor: default;
  padding: 3px 8px; border-radius: 999px; border: 1px solid transparent;
  transition: background .12s, border-color .12s;
}
.tache-cell:hover .tache-mini { background: var(--page); border-color: var(--hairline); }
.tache-dots { display: inline-flex; gap: 3px; }
.tache-dots i { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.tache-dots i.on { background: var(--good); }
.tache-dots i.off { background: transparent; box-shadow: inset 0 0 0 1.5px var(--hairline); }
.tache-frac { font-size: 11.5px; font-weight: 700; color: var(--muted); font-variant-numeric: tabular-nums; }
.tache-frac.full { color: var(--good-text); }
.tache-pop {
  position: fixed; z-index: 60; display: none; min-width: 226px; max-width: 300px;
  background: var(--surface); border: 1px solid var(--hairline); border-radius: 12px;
  box-shadow: var(--shadow-lift); padding: 10px;
}
.tache-pop.open { display: block; }
.tache-pop-h { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); margin-bottom: 8px; }
.tache-pop .task-chips { flex-direction: column; align-items: stretch; gap: 5px; }
.tache-pop .task-chip { justify-content: flex-start; border-radius: 8px; padding: 5px 10px; font-size: 12px; }

/* ---- Closer : avatar à initiales + champ discret (au lieu d'une carte fade) ---- */
.col-closer, .col-closer-cell { width: 142px; }
.closer-edit { display: inline-flex; align-items: center; gap: 6px; margin: 0; max-width: 100%; }
.ava {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 9.5px; font-weight: 700; letter-spacing: .02em;
  background: var(--accent-soft); color: var(--accent-strong);
}
.ava-ghost { background: transparent; color: var(--muted); border: 1px dashed var(--hairline); font-weight: 400; font-size: 13px; }
.closer-view { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; }
.closer-edit.empty .closer-input { color: var(--muted); }
/* Assigné : un nom, et une croix qui n'arrive qu'au survol. Le <select> de
   chaque ligne était tronqué (« Virgin… ») et rouvrait un choix déjà fait. */
.closer-mis { display: inline-flex; align-items: center; gap: 6px; margin: 0;
  max-width: 100%; font-size: 13px; cursor: default; }
.closer-nom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.closer-x { flex: none; border: 0; background: none; padding: 0 2px; cursor: pointer;
  font-size: 12px; line-height: 1; color: var(--muted); opacity: 0;
  transition: opacity .12s, color .12s; }
.closer-mis:hover .closer-x, .closer-x:focus-visible { opacity: 1; }
.closer-x:hover { color: var(--sem-defaut-t); }
/* « Sans closer » : la même forme que « assigné », en gris — c'est une réponse
   de même nature, et la croix la rouvre. Plus de <details> qui s'ouvrait sous
   la ligne en poussant la colonne. */
.closer-mis.closer-aucun .closer-nom { color: var(--muted); font-size: 12.5px; }
/* Le temps de l'aller-retour : la cellule s'efface un peu, et rien ne bouge —
   pas de saut de hauteur, donc pas de tableau qui tressaute. */
.closer-attente { opacity: .45; pointer-events: none; transition: opacity .1s; }

/* « Pas de closer » : la ligne n'a plus de bouton, juste un mot gris qui dit
   que la question est réglée. Il rouvre le menu au clic — une erreur ne doit
   pas être définitive (HH-2566). */
.closer-sans > summary { list-style: none; cursor: pointer; font-size: 12px;
  color: var(--muted); padding: 2px 0; }
.closer-sans > summary::-webkit-details-marker { display: none; }
.closer-sans > summary:hover { color: var(--accent); }
.closer-sans[open] > summary { font-size: 11px; margin-bottom: 3px; }
.closer-input { width: 92px; appearance: none; -webkit-appearance: none;
  color: var(--muted); font-size: 12.5px; padding: 3px 5px; }
.closer-edit.empty .ava-ghost { width: 20px; height: 20px; font-size: 12px; }
/* Déplié, le champ cherchable doit pouvoir dépasser la colonne : un nom ne se
   choisit pas dans 90 px. */
.closer-edit .sel-search.open .combo-input { background: var(--surface); border-color: var(--accent); }
.closer-edit .sel-search { width: 90px; }
/* En-tête commun de page : barre d'une couleur distincte (propre, pro), sticky.
   Le titre change par page ; les outils communs (recherche, notifications,
   utilisateur) y sont injectés. Les sous-titres sont masqués. */
.page-head {
  display: flex; align-items: center; gap: 12px;
  background: var(--surface);
  margin: -22px -28px 18px; padding: 12px 28px;
  border-bottom: 1px solid var(--hairline);
  box-shadow: 0 8px 18px -16px rgba(11, 11, 11, .35);
  position: sticky; top: 0; z-index: 30;
}
/* PIÈGE — cette règle donne `margin-right:auto` au PREMIER enfant, et c'est
   elle qui pousse les outils vers la droite. Le bouton « Retour » (HH-2568)
   se glisse DEVANT le titre : sans les deux règles qui suivent, l'`auto`
   tomberait sur lui et collerait titre et outils au bord droit.
   `.page-head > .retour-btn:first-child` (0,3,0) passe devant (0,2,0), et
   l'`auto` est rendu à ce qui suit le bouton. */
.page-head > :first-child { margin-right: auto; min-width: 0; }
.page-head > .retour-btn:first-child { margin-right: 0; }
.page-head > .retour-btn + * { margin-right: auto; min-width: 0; }

/* Revenir n'est pas une action de la page : c'est le chemin par lequel on est
   arrivé. Donc pas un bouton — un cadre et un fond en faisaient le premier
   objet de l'en-tête, devant le titre de la page. Du texte, une flèche, la
   couleur des choses secondaires : on le trouve quand on le cherche, et il ne
   demande rien quand on ne le cherche pas.

   La surface cliquable reste large (le padding est là, seul le cadre est
   parti) : discret ne veut pas dire difficile à viser. */
.retour-btn {
  display: inline-flex; align-items: center; gap: 6px; flex: none;
  margin-left: -6px; padding: 4px 6px; border-radius: 6px;
  border: 0; background: none;
  font-size: 12.5px; color: var(--muted); text-decoration: none;
  white-space: nowrap; max-width: 220px; overflow: hidden; text-overflow: ellipsis;
  transition: color .12s;
}
.retour-btn:hover { color: var(--ink-2); }
/* La flèche recule d'un cheveu au survol : c'est tout ce qu'il faut pour dire
   « ça repart en arrière », et ça remplace le cadre qu'on vient d'enlever. */
.retour-btn span { font-size: 13px; line-height: 1; transition: transform .12s; }
.retour-btn:hover span { transform: translateX(-2px); }
.retour-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
  .retour-btn, .retour-btn span { transition: none; }
  .retour-btn:hover span { transform: none; }
}
.page-head h1 { margin: 0; font-size: 20px; letter-spacing: -.01em; }
.page-head .sub { display: none; }
.page-head .actions { display: flex; gap: 8px; align-items: center; }
/* Les boutons d'action de la PAGE ne vivent pas dans l'en-tête commun : le JS
   les déplace vers la barre d'onglets (ou juste sous l'en-tête si pas d'onglets).
   Cachés le temps du déplacement pour éviter tout clignotement. */
.page-head > .actions { visibility: hidden; }
.tab-actions { margin-left: auto; align-self: center; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; padding-bottom: 6px; visibility: visible; }
.page-actions { display: flex; justify-content: flex-end; gap: 8px; align-items: center; flex-wrap: wrap; margin: 0 0 16px; visibility: visible; }

/* Outils communs de l'en-tête */
.header-tools { display: flex; align-items: center; gap: 10px; }
.header-tools[hidden] { display: none; }
.page-head .header-tools { border-left: 1px solid var(--hairline); padding-left: 12px; }
.content > .header-tools { justify-content: flex-end; margin-bottom: 12px; }
.ht-search {
  display: flex; align-items: center; gap: 7px; width: 208px;
  background: var(--page); border: 1px solid var(--hairline); border-radius: 9px;
  padding: 6px 10px; color: var(--muted); transition: border-color .15s, background .15s;
}
.ht-search:focus-within { border-color: var(--accent-soft); background: var(--surface); }
.ht-search input { border: 0; background: none; outline: none; font: inherit; font-size: 13px; width: 100%; color: var(--ink); }
.ht-search input::placeholder { color: var(--muted); }
.ht-bell > summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 9px; border: 1px solid var(--hairline);
  background: var(--page); position: relative; color: var(--ink-2); transition: border-color .15s;
}
.ht-bell > summary::-webkit-details-marker { display: none; }
.ht-bell > summary:hover { border-color: #d7d5cc; color: var(--ink); }
.ht-bell .count {
  position: absolute; top: -6px; right: -6px; background: var(--critical); color: #fff;
  font-size: 10px; font-weight: 700; min-width: 16px; height: 16px; border-radius: 8px;
  display: flex; align-items: center; justify-content: center; padding: 0 3px;
}
.ht-user { display: flex; align-items: center; gap: 8px; }
.ht-user .avatar { width: 32px; height: 32px; font-size: 12px; flex-shrink: 0; }
.ht-user .ht-who { display: flex; flex-direction: column; line-height: 1.15; min-width: 0; }
.ht-user .ht-who b { font-size: 12.5px; white-space: nowrap; }
.ht-user .ht-who small { font-size: 10.5px; color: var(--muted); white-space: nowrap; }
@media (max-width: 780px) { .ht-search { width: 42px; } .ht-user .ht-who { display: none; } }

/* Modal « Calendrier & prévision » des échéances */
.modal-box.ech-box { width: 1000px; max-width: 94vw; }
.ech-cols { display: flex; gap: 24px; align-items: flex-start; }
.ech-cal-col { flex: 1.15; min-width: 0; max-height: 62vh; overflow-y: auto; padding-right: 4px; }
.ech-fc-col { flex: 1; min-width: 0; }
.ech-sub { font-size: 11px; font-weight: 650; color: var(--muted); text-transform: uppercase;
  letter-spacing: .05em; margin-bottom: 10px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.sem-attente-chip { background: var(--sem-attente-bg); color: var(--sem-attente-t); font-size: 11px;
  font-weight: 650; padding: 2px 9px; border-radius: 20px; text-transform: none; letter-spacing: 0; }
.ech-month { margin-bottom: 12px; }
.ech-month-h { display: flex; justify-content: space-between; font-size: 12px; font-weight: 650;
  padding: 3px 2px; border-bottom: 1px solid var(--hairline); margin-bottom: 2px; }
.ech-item { display: grid; grid-template-columns: 40px 1fr auto auto; align-items: center; gap: 8px;
  padding: 4px 6px; border-radius: 7px; font-size: 12px; text-decoration: none; color: inherit; }
.ech-item:hover { background: var(--page); text-decoration: none; }
.ech-item .ech-d { color: var(--muted); font-variant-numeric: tabular-nums; }
.ech-item .ech-c { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ech-item .ech-a { font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; }
.ech-item .ech-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--hairline); }
.ech-item .ech-dot.t-naranja { background: var(--sem-attente); }
.ech-item .ech-dot.t-rojo { background: var(--sem-defaut); }
.ech-item .ech-dot.t-verde { background: var(--sem-facture); }
/* Le jaune manquait : une échéance à moitié réglée avait exactement la
   couleur d'une échéance dont rien n'était arrivé. Un demi-disque plutôt
   qu'une teinte de plus — c'est littéralement ce que ça veut dire. */
.ech-item .ech-dot.t-amarillo {
  background: linear-gradient(90deg, var(--sem-facture) 50%, #e6e6df 50%); }
.ech-fc-bars { display: flex; align-items: flex-end; gap: 5px; height: 128px; margin-bottom: 14px; }
.ech-fc-b { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 6px; height: 100%; cursor: default; }
.ech-fc-fill { width: 100%; max-width: 22px; min-height: 2px; background: var(--sem-facture); border-radius: 4px 4px 1px 1px; transition: filter .15s; }
.ech-fc-b:hover .ech-fc-fill { filter: brightness(1.1); }
.ech-fc-bars:has(.ech-fc-b:hover) .ech-fc-b:not(:hover) .ech-fc-fill { opacity: .4; }
.ech-fc-x { font-size: 8.5px; color: var(--muted); white-space: nowrap; }
.ech-fc-b:hover .ech-fc-x { color: var(--ink); }
.ech-fc-table { width: 100%; }
.ech-fc-table .ech-fc-total td { border-top: 2px solid var(--hairline); }
@media (max-width: 820px) { .ech-cols { flex-direction: column; } .ech-cal-col { max-height: 38vh; width: 100%; } }

/* Bouton « Relances » reluisant quand il y a des impayés */
.relance-alert {
  background: var(--sem-defaut-bg);
  border-color: var(--sem-defaut); color: var(--sem-defaut-t); font-weight: 650;
  box-shadow: 0 0 0 3px rgba(208, 59, 59, .10);
  animation: relPulse 2.4s ease-in-out infinite;
}
.relance-alert:hover { background: var(--sem-defaut-bg); border-color: var(--sem-defaut); color: var(--sem-defaut-t); }
.relance-alert .rl-count {
  display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px;
  padding: 0 5px; margin-left: 5px; background: var(--sem-defaut); color: #fff; border-radius: 20px;
  font-size: 11.5px; font-weight: 700;
}
@keyframes relPulse { 0%, 100% { box-shadow: 0 0 0 3px rgba(208, 59, 59, .10); } 50% { box-shadow: 0 0 0 6px rgba(208, 59, 59, .04); } }
@media (prefers-reduced-motion: reduce) { .relance-alert { animation: none; } }

/* Modal Retards & relances */
.modal-box.rl-box { width: min(1400px, 96vw); border-top: 3px solid var(--sem-defaut); }
.rl-top { display: flex; justify-content: space-between; align-items: center; gap: 14px; flex-wrap: wrap;
  background: var(--sem-attente-bg); border: 1px solid #efdcb4; border-radius: 10px; padding: 9px 13px; margin-bottom: 16px; }
.rl-cadence { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.rl-step { background: var(--surface); border: 1px solid var(--hairline); border-radius: 20px; padding: 2px 10px; font-size: 11.5px; font-weight: 600; }
/* La cadence se lit comme une échelle de gravité : bleu → ambre → orange → rouge. */
.rl-step-blue   { background: var(--sem-vente-bg);   border-color: #cfe0f6; color: var(--sem-vente-t); }
.rl-step-amber  { background: var(--sem-attente-bg); border-color: #efd9ad; color: var(--sem-attente-t); }
.rl-step-orange { background: #fdeede;               border-color: #f6d3bf; color: #97591b; }
.rl-step-red    { background: var(--sem-defaut-bg);  border-color: #f1cfc9; color: var(--sem-defaut-t); }

/* Le réglage de la cadence. Il vit à la place des pastilles, pas au-dessus :
   c'est la même information sous deux formes, et les empiler ferait sauter la
   file de relances d'une ligne à chaque ouverture. */
.rl-cadence-vue { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.rl-cad-trace { margin-left: 2px; }
.rl-cadence-form { display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap; }
.rl-cad-fld { display: flex; flex-direction: column; gap: 2px;
              font-size: 11px; color: var(--muted); font-weight: 600; }
.rl-cad-in { display: flex; align-items: center; gap: 3px;
             font-size: 12px; color: var(--txt); font-weight: 600; }
.rl-cad-in input { width: 58px; padding: 3px 6px; font-size: 13px;
                   font-variant-numeric: tabular-nums;
                   border: 1px solid var(--line); border-radius: 6px;
                   background: var(--bg); color: var(--txt); }
.rl-cad-in input:focus-visible { outline: 2px solid var(--sem-vente-t); outline-offset: 1px; }
/* Le motif du refus tient la ligne entière : il explique QUELLE étape ne va
   pas, et coupé à la largeur d'un champ il ne servirait à rien. */
.rl-cad-err { flex-basis: 100%; margin: 0; font-size: 11.5px;
              color: var(--sem-defaut-t); }
.rl-cols { display: flex; gap: 24px; align-items: flex-start; }
.rl-col { flex: 1; min-width: 0; max-height: 58vh; overflow-y: auto; padding-right: 4px; }
.rl-item { display: grid; grid-template-columns: 1fr auto auto auto auto; align-items: center; gap: 8px; padding: 6px; border-radius: 8px; font-size: 12px; text-decoration: none; color: inherit; }
.rl-item:hover { background: var(--page); text-decoration: none; }
.rl-item .rl-who { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rl-item .rl-amt { font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; }
.rl-item .rl-mails { white-space: nowrap; }
.rl-stage { font-size: 10px; font-weight: 650; padding: 2px 8px; border-radius: 20px; white-space: nowrap; }
.rl-stage.rl-attente { background: var(--sem-attente-bg); color: var(--sem-attente-t); }
.rl-stage.rl-serious { background: #fdeede; color: #97591b; }
.rl-stage.rl-defaut { background: var(--sem-defaut-bg); color: var(--sem-defaut-t); }
/* Priorités de Loïc (01/10) : l'argent est arrivé, il reste à le relier. */
.rl-stage.rl-recu { background: var(--sem-facture-bg); color: var(--sem-facture-t); }
.rl-k.rl-k-green { background: var(--sem-facture-bg); border-left: 3px solid var(--sem-facture); } .rl-k.rl-k-green b { color: var(--sem-facture-t); }
.rl-row-recu td { opacity: .72; }
.rl-stage.rl-neutre { background: var(--surface); color: var(--muted); border: 1px solid var(--hairline); }
.rl-call { border: 1px solid var(--hairline); border-radius: 9px; margin-bottom: 6px; }
.rl-call > summary { display: flex; align-items: center; gap: 8px; padding: 7px 10px; cursor: pointer; list-style: none; font-size: 12px; }
.rl-call > summary::-webkit-details-marker { display: none; }
.rl-call > summary .rl-who { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rl-call[open] > summary { border-bottom: 1px solid var(--hairline); }
.rl-call-form { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 10px; align-items: center; }
/* `background-color` et non le raccourci : sur un `select`, `background`
   efface le `no-repeat` de la règle maison, et le chevron se répète en
   mosaïque au survol. Même défaut trouvé sur la pastille de groupe. */
.rl-call-form select, .rl-call-form input { font: inherit; font-size: 12px; padding: 5px 7px; border: 1px solid var(--hairline); border-radius: 7px; background-color: var(--surface); }
.rl-call-form input[name=note] { flex: 1; min-width: 140px; }
.sem-defaut-chip { background: var(--sem-defaut-bg); color: var(--sem-defaut-t); font-size: 11px; font-weight: 650; padding: 2px 9px; border-radius: 20px; text-transform: none; letter-spacing: 0; }
@media (max-width: 820px) { .rl-cols { flex-direction: column; } .rl-col { max-height: 40vh; } }

/* Modal relances — version large et détaillée */
.rl-kpis { display: grid; grid-template-columns: repeat(7, 1fr); gap: 8px; margin-bottom: 14px; }
.rl-k { background: var(--surface); border: 1px solid var(--hairline); border-radius: 10px; padding: 8px 11px; }
.rl-k b { display: block; font-size: 19px; font-weight: 700; letter-spacing: -.01em; line-height: 1; }
.rl-k span { font-size: 10.5px; color: var(--muted); }
/* Tuiles KPI teintées par étape (même échelle que la cadence), pas juste un liseré. */
.rl-k.rl-k-red { background: var(--sem-defaut-bg); border-color: #f1cfc9; border-left: 3px solid var(--sem-defaut); } .rl-k.rl-k-red b { color: var(--sem-defaut-t); }
.rl-k.rl-k-amber { background: var(--sem-attente-bg); border-color: #efd9ad; border-left: 3px solid var(--sem-attente); } .rl-k.rl-k-amber b { color: var(--sem-attente-t); }
.rl-k.rl-k-blue { background: var(--sem-vente-bg); border-color: #cfe0f6; border-left: 3px solid var(--sem-vente); } .rl-k.rl-k-blue b { color: var(--sem-vente-t); }
.rl-k.rl-k-orange { background: #fdeede; border-color: #f6d3bf; border-left: 3px solid var(--serious); } .rl-k.rl-k-orange b { color: #97591b; }
.rl-table-wrap { max-height: 42vh; margin-bottom: 16px; }
.rl-table td, .rl-table th { padding: 5px 9px; }
/* Cabeceras de los paneles coloreadas por su naturaleza (appels=ambre, escalades=rouge). */
.rl-panel .ech-sub.rl-h-amber { color: var(--sem-attente-t); border-bottom: 2px solid #efd9ad; padding-bottom: 5px; }
.rl-panel .ech-sub.rl-h-red { color: var(--sem-defaut-t); border-bottom: 2px solid #f1cfc9; padding-bottom: 5px; }
.rl-table td .muted { font-size: 10.5px; }
.rl-amt { font-weight: 600; font-variant-numeric: tabular-nums; }
.rl-panels { display: grid; grid-template-columns: 1.2fr 1fr; gap: 22px; align-items: start; }
.rl-panel { min-width: 0; max-height: 36vh; overflow-y: auto; padding-right: 4px; }
.rl-callcard { border: 1px solid var(--hairline); border-radius: 10px; padding: 9px 11px; margin-bottom: 8px; }
.rl-callcard-h { display: flex; align-items: center; gap: 8px; margin-bottom: 3px; }
.rl-callcard-h b { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; }
.rl-note { background: var(--page); border-radius: 7px; padding: 4px 8px; margin: 5px 0; }
.rl-esc { display: grid; grid-template-columns: 1fr auto auto; grid-template-rows: auto auto; gap: 1px 10px;
  align-items: center; padding: 7px 9px; border-radius: 8px; text-decoration: none; color: inherit;
  border: 1px solid var(--hairline); margin-bottom: 6px; }
.rl-esc:hover { background: var(--page); text-decoration: none; }
.rl-esc > b { grid-column: 1; grid-row: 1; }
.rl-esc > .small { grid-column: 1; grid-row: 2; }
.rl-esc > .badge { grid-column: 2; grid-row: 1 / 3; }
.rl-esc > .rl-amt { grid-column: 3; grid-row: 1 / 3; }
@media (max-width: 1100px) { .rl-kpis { grid-template-columns: repeat(4, 1fr); } .rl-panels { grid-template-columns: 1fr; } }

/* ---------- Entidades ---------- */
.entity-chip {
  display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600;
  border: 1px solid var(--hairline); border-radius: 99px; padding: 3px 10px;
  color: var(--ink-2); background: var(--surface);
}
.entity-dot { width: 8px; height: 8px; border-radius: 50%; }
.entity-switch { display: flex; gap: 6px; align-items: center; }
.entity-switch a {
  font-size: 12px; padding: 3px 11px; border-radius: 99px; border: 1px solid var(--hairline);
  color: var(--ink-2); transition: all .15s;
}
.entity-switch a.on { background: var(--ink); color: #fff; border-color: var(--ink); font-weight: 600; }
.entity-switch a:hover { text-decoration: none; border-color: var(--ink-2); transform: translateY(-1px); }

/* ---------- Tarjetas y grids ---------- */
.card {
  background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--radius);
  padding: 14px 16px; box-shadow: var(--shadow); margin-bottom: 13px;
  animation: rise .35s ease both;
}
.card:nth-child(2) { animation-delay: .04s; }
.card:nth-child(3) { animation-delay: .08s; }
.card > h2 {
  display: flex; align-items: center; gap: 8px; font-size: 13.5px;
  padding-bottom: 8px; border-bottom: 1px solid var(--hairline); margin-bottom: 10px;
}
.grid { display: grid; gap: 12px; align-items: start; }
.grid > .card { margin-bottom: 0; }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.grid-32 { grid-template-columns: 3fr 2fr; }
@media (max-width: 1100px) { .grid-32 { grid-template-columns: 1fr; } }

/* ---------- KPI (stat tiles) ---------- */
.kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 9px; margin-bottom: 13px; }
.kpi {
  background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--radius);
  padding: 11px 14px; box-shadow: var(--shadow); animation: rise .35s ease both;
  transition: box-shadow .2s, transform .2s;
}
.kpi:hover { box-shadow: var(--shadow-lift); transform: translateY(-2px); }
.kpis .kpi:nth-child(2) { animation-delay: .05s; }
.kpis .kpi:nth-child(3) { animation-delay: .1s; }
.kpis .kpi:nth-child(4) { animation-delay: .15s; }
.kpis .kpi:nth-child(5) { animation-delay: .2s; }
.kpis .kpi:nth-child(6) { animation-delay: .25s; }
.kpi .label { font-size: 12px; color: var(--ink-2); }
.kpi .value { font-size: 22px; font-weight: 650; margin-top: 2px; letter-spacing: -0.01em; }
.kpi .delta { font-size: 12px; margin-top: 2px; color: var(--muted); }
.kpi .delta.up { color: var(--good-text); }
.kpi .delta.down { color: var(--critical); }
.kpi.alert { border-color: #f2bcbc; background: #fdf6f6; }
.kpi.alert .value { color: var(--critical); }

/* ---------- Badges de estado (icono + etiqueta) ---------- */
.badge {
  display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 600;
  border-radius: 99px; padding: 2px 9px; white-space: nowrap;
  background: var(--page); color: var(--ink-2); border: 1px solid var(--hairline);
}
.badge::before { content: "●"; font-size: 8px; }
.badge.b-good { background: #e7f6e7; color: var(--good-text); border-color: #bfe6bf; }
.badge.b-warning { background: #fdf3dc; color: #8a5f00; border-color: #f3dda6; }
/* Facture à relier : la couleur de la facturation, pas celle d'une alerte —
   en CONTOUR, pour ne pas se lire « Complet » (vert plein) : c'est un geste
   à faire, pas un état atteint. */
.badge.b-facture { background: var(--surface); color: var(--sem-facture-t); border-color: var(--sem-facture); }
.badge.b-facture.badge-btn:hover { background: var(--sem-facture-bg); }
.badge.b-serious { background: #fdeae2; color: #99401d; border-color: #f6cdba; }
.badge.b-critical { background: #fbe4e4; color: #8f2020; border-color: #f2bcbc; }
.badge.b-accent { background: #e9f1fc; color: #1c5cab; border-color: #c4dcf6; }
.badge.b-aqua { background: #e2f6ee; color: #0c6b4a; border-color: #b5e6d3; }
.badge.b-muted::before { content: "○"; }

/* ---------- Tablas ---------- */
table.data { width: 100%; border-collapse: collapse; font-size: 13.5px; }
table.data th {
  text-align: left; font-size: 10.5px; text-transform: uppercase; letter-spacing: .07em;
  color: var(--muted); font-weight: 650; padding: 7px 10px; border-bottom: 1px solid var(--hairline);
  background: var(--page);
}
.table-scroll table.data th { position: sticky; top: 0; z-index: 2; }
table.data td { padding: 7px 10px; border-bottom: 1px solid #eceae4; vertical-align: middle; }
table.data tr:last-child td { border-bottom: none; }
table.data tbody tr, table.data tr { transition: background .12s; }
table.data tr:hover td { background: #f3f6fb; }
td.num, th.num, table.data th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.table-scroll { max-height: 72vh; overflow: auto; }

/* ---------- Botones y formularios ---------- */
.btn {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  border: 1px solid var(--hairline); background: var(--surface); color: var(--ink);
  border-radius: 9px; padding: 6px 13px; font-size: 13px; font-weight: 600;
  font-family: inherit; transition: all .15s; white-space: nowrap;
}
.btn:hover { border-color: var(--ink-2); text-decoration: none; transform: translateY(-1px); box-shadow: 0 3px 8px rgba(11,11,11,.08); }
.btn:active { transform: translateY(0); }
.btn.primary { background: var(--accent); border-color: var(--accent-strong); color: #fff; }
.btn.primary:hover { background: var(--accent-strong); }
.btn.good { background: var(--good); border-color: #0a8a0a; color: #fff; }
.btn.danger { background: #fff; border-color: var(--critical); color: var(--critical); }
.btn.danger:hover { background: var(--critical); color: #fff; }
.btn.sm { padding: 3px 10px; font-size: 12px; border-radius: 7px; }
.btn.ghost { border-color: transparent; background: transparent; color: var(--accent); box-shadow: none; }
input[type=text], input[type=number], input[type=date], input[type=email], input[type=password], select, textarea {
  font-family: inherit; font-size: 13.5px; color: var(--ink);
  border: 1px solid var(--hairline); border-radius: 9px; padding: 7px 10px;
  background: var(--surface); width: 100%; transition: border-color .15s, box-shadow .15s;
}
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft);
}
select {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23898781' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-color: #fbfbfa;
  background-repeat: no-repeat; background-position: right 11px center;
  background-size: 10px 6px;
  padding-right: 30px; cursor: pointer; text-overflow: ellipsis;
  font-weight: 500; color: var(--ink-2);
  box-shadow: 0 1px 2px rgba(11, 11, 11, .05);
  transition: border-color .15s, box-shadow .15s, color .15s, transform .12s;
}
select:hover {
  border-color: #b9b7ae; color: var(--ink); transform: translateY(-1px);
  box-shadow: 0 3px 8px rgba(11, 11, 11, .08);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%230b0b0b' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
select:focus {
  color: var(--ink); transform: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%231c5cab' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
select option { font-weight: 400; color: var(--ink); background: #fff; }
.form-row > label select { font-weight: 400; }
input[type=date] { cursor: pointer; }
input[type=date]:hover, input[type=text]:hover, input[type=number]:hover, input[type=search]:hover { border-color: #b9b7ae; }
form.inline { display: inline; }
.form-row { display: flex; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; }
.form-row > label { flex: 1; min-width: 130px; font-size: 12px; color: var(--ink-2); font-weight: 600; }
.form-row > label input, .form-row > label select, .form-row > label textarea { margin-top: 4px; font-weight: 400; }
.check { display: inline-flex; gap: 6px; align-items: center; font-size: 13px; color: var(--ink-2); font-weight: 500; }
.check input { width: auto; }
.filter-input { max-width: 280px; }

/* ---------- Avisos embebidos ---------- */
.msg { border-radius: 9px; padding: 9px 14px; font-size: 13.5px; border: 1px solid; margin-bottom: 12px; animation: rise .3s ease both; }
.msg.success { background: #e7f6e7; border-color: #bfe6bf; color: #063; }
.msg.info { background: #e9f1fc; border-color: #c4dcf6; color: #1c5cab; }
.msg.error { background: #fbe4e4; border-color: #f2bcbc; color: #8f2020; }
.msg.warning { background: #fdf3dc; border-color: #f3dda6; color: #8a5f00; }

/* ---------- Toasts (mensajes flash flotantes) ---------- */
.toasts { position: fixed; top: 62px; right: 20px; z-index: 200; display: flex; flex-direction: column; gap: 8px; max-width: 420px; }
.toast {
  display: flex; align-items: flex-start; gap: 10px;
  border-radius: 10px; padding: 11px 14px; font-size: 13px; border: 1px solid;
  background: var(--surface); box-shadow: var(--shadow-lift);
  animation: toast-in .3s ease both; transition: opacity .4s, transform .4s;
}
.toast.hide { opacity: 0; transform: translateX(24px); }
.toast .t-close { cursor: pointer; border: none; background: none; color: inherit; font-size: 14px; padding: 0 0 0 6px; opacity: .6; }
.toast .t-close:hover { opacity: 1; }
.toast.success { background: #ecf9ec; border-color: #bfe6bf; color: #063; }
.toast.info { background: #ecf3fd; border-color: #c4dcf6; color: #1c5cab; }
.toast.error { background: #fdecec; border-color: #f2bcbc; color: #8f2020; }
.toast.warning { background: #fdf5e0; border-color: #f3dda6; color: #8a5f00; }

/* ---------- Kanban (drag & drop) ---------- */
.kanban { display: grid; grid-template-columns: repeat(5, minmax(205px, 1fr)); gap: 12px; align-items: start; }
.kanban-col {
  background: #f0f0ec; border: 1px solid var(--hairline); border-radius: var(--radius);
  padding: 10px; border-top: 3px solid var(--muted); transition: background .15s, box-shadow .15s;
  animation: rise .35s ease both;
}
.kanban-col[data-col="prospecto"], .kanban-col[data-col="recibida"] { border-top-color: #86b6ef; }
.kanban-col[data-col="presupuesto"], .kanban-col[data-col="en_preparacion"] { border-top-color: var(--warning); }
.kanban-col[data-col="seguimiento"] { border-top-color: var(--serious); }
.kanban-col[data-col="firmado"], .kanban-col[data-col="lista"] { border-top-color: var(--good); }
.kanban-col[data-col="perdido"] { border-top-color: var(--muted); }
.kanban-col[data-col="expedida"] { border-top-color: var(--accent); }
.kanban-col.drop-hover { background: #e6effb; box-shadow: inset 0 0 0 2px var(--accent); }
.kanban-col > header { display: flex; justify-content: space-between; align-items: baseline; padding: 0 4px 8px; }
.kanban-col > header b { font-size: 12.5px; }
.kanban-col > header span { font-size: 11px; color: var(--muted); }
.kcard {
  background: var(--surface); border: 1px solid var(--hairline); border-radius: 9px;
  padding: 9px 10px; margin-bottom: 8px; box-shadow: var(--shadow); font-size: 12.5px;
  transition: box-shadow .15s, transform .15s;
}
.kcard[draggable="true"] { cursor: grab; }
.kcard[draggable="true"]:hover { box-shadow: var(--shadow-lift); transform: translateY(-2px); }
.kcard.dragging { opacity: .45; transform: rotate(1.5deg) scale(.98); cursor: grabbing; }
.kcard b { display: block; font-size: 13px; }
.kcard .meta { color: var(--muted); font-size: 11.5px; margin-top: 2px; }
.kcard.urgent { border-left: 3px solid var(--critical); }
.kanban-scroll { overflow-x: auto; padding-bottom: 6px; }
.drag-hint { font-size: 11.5px; color: var(--muted); }
.drag-hint kbd {
  font-family: inherit; background: var(--page); border: 1px solid var(--hairline);
  border-radius: 5px; padding: 0 6px; font-size: 11px;
}

/* ---------- Gráficos CSS (animados) ---------- */
.chart-cols { display: flex; align-items: flex-end; gap: 18px; height: 150px; padding: 6px 4px 0; }
.chart-group { flex: 1; display: flex; flex-direction: column; height: 100%; }
.chart-bars { flex: 1; display: flex; align-items: flex-end; justify-content: center; gap: 2px; }
.chart-bar {
  width: 22px; max-width: 22px; border-radius: 4px 4px 0 0; background: var(--accent);
  min-height: 2px; position: relative;
  transform-origin: bottom; animation: grow-y .7s cubic-bezier(.2, .7, .3, 1) both .1s;
}
.chart-bar.s2 { background: var(--aqua); animation-delay: .22s; }
.chart-bar .tip {
  position: absolute; top: -18px; left: 50%; transform: translateX(-50%);
  font-size: 10.5px; color: var(--ink-2); font-weight: 600; white-space: nowrap;
}
.chart-x { text-align: center; font-size: 11px; color: var(--muted); padding-top: 6px; border-top: 1px solid var(--hairline); }
.legend { display: flex; gap: 14px; font-size: 12px; color: var(--ink-2); margin-top: 10px; }
.legend i { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 5px; vertical-align: -1px; }

.hbars { display: flex; flex-direction: column; gap: 7px; }
.hbar { display: grid; grid-template-columns: 170px 1fr 64px; align-items: center; gap: 10px; font-size: 12.5px; }
.hbar .track { background: var(--page); border-radius: 4px; height: 16px; overflow: hidden; }
.hbar .fill {
  height: 100%; border-radius: 4px; background: var(--accent); min-width: 2px;
  transform-origin: left; animation: grow-x .7s cubic-bezier(.2, .7, .3, 1) both .15s;
}
.hbar .n { text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; }

.meter { background: var(--accent-soft); border-radius: 5px; height: 9px; overflow: hidden; min-width: 80px; }
.meter .fill {
  height: 100%; background: var(--accent); border-radius: 5px;
  transform-origin: left; animation: grow-x .8s cubic-bezier(.2, .7, .3, 1) both .2s;
}
.meter.warn .fill { background: var(--serious); }
.meter.over { background: #f6cdba; }
.meter.over .fill { background: var(--critical); }

/* ---------- Notificaciones ---------- */
.bell { position: relative; }
.bell > summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; gap: 5px;
  padding: 5px 10px; border-radius: 9px; border: 1px solid var(--hairline); font-size: 13px;
  transition: all .15s;
}
.bell > summary:hover { border-color: var(--ink-2); }
.bell > summary::-webkit-details-marker { display: none; }
.bell .count {
  background: var(--critical); color: #fff; font-size: 10.5px; font-weight: 700;
  border-radius: 99px; padding: 0 6px; animation: pulse 2.4s ease-in-out infinite;
}
.bell-menu {
  position: absolute; right: 0; top: 40px; width: 360px; background: var(--surface);
  border: 1px solid var(--hairline); border-radius: var(--radius); box-shadow: var(--shadow-lift);
  z-index: 60; max-height: 420px; overflow-y: auto; animation: rise .2s ease both;
}
.bell-menu a.notif { display: block; padding: 10px 14px; border-bottom: 1px solid var(--hairline); font-size: 12.5px; color: var(--ink); }
.bell-menu a.notif:hover { background: var(--page); text-decoration: none; }
.bell-menu a.notif small { color: var(--muted); display: block; }
.bell-menu .all { display: block; text-align: center; padding: 9px; font-size: 12.5px; font-weight: 600; }

/* ---------- Timeline ---------- */
.timeline { list-style: none; margin: 0; padding: 0; }
.timeline li { display: flex; gap: 12px; padding: 9px 0; border-bottom: 1px solid #eceae4; font-size: 13px; }
.timeline li:last-child { border-bottom: none; }
.timeline .t-ico {
  width: 30px; height: 30px; flex-shrink: 0; border-radius: 9px; background: var(--page);
  border: 1px solid var(--hairline); display: flex; align-items: center; justify-content: center; font-size: 13px;
}
.timeline .t-date { color: var(--muted); font-size: 11.5px; }

/* ---------- Checklist ---------- */
.checklist-cat { margin-bottom: 14px; }
.check-item { display: flex; align-items: center; gap: 10px; padding: 6px 0; border-bottom: 1px dashed var(--hairline); font-size: 13px; }
.check-item:last-child { border-bottom: none; }
.check-state {
  width: 27px; height: 27px; border-radius: 8px; border: 1px solid var(--hairline);
  background: var(--surface); cursor: pointer; font-size: 13px; transition: all .15s;
}
button.check-state:hover { transform: scale(1.12); border-color: var(--accent); }
.check-state.ok { background: #e7f6e7; border-color: var(--good); }
.check-state.na { background: var(--page); color: var(--muted); }
.check-state.falta { background: #fdf3dc; border-color: var(--warning); }

/* ---------- Portal: pasos ---------- */
.steps { display: flex; margin: 14px 0; }
.step { flex: 1; text-align: center; position: relative; font-size: 12px; color: var(--muted); }
.step::before {
  content: ""; display: block; width: 14px; height: 14px; border-radius: 50%;
  background: var(--surface); border: 2px solid var(--hairline); margin: 0 auto 6px; position: relative; z-index: 2;
}
.step::after { content: ""; position: absolute; top: 7px; left: 50%; width: 100%; height: 2px; background: var(--hairline); }
.step:last-child::after { display: none; }
.step.done { color: var(--good-text); font-weight: 600; }
.step.done::before { background: var(--good); border-color: var(--good); }
.step.done::after { background: var(--good); }

/* ---------- Login (selector de perfiles) ---------- */
.login-page {
  min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 30px 16px;
  background: var(--page);
}
.login-card {
  width: 720px; max-width: 96vw; background: var(--surface); border: 1px solid var(--hairline);
  border-radius: 18px; padding: 34px 38px; box-shadow: var(--shadow-lift); animation: rise .4s ease both;
}
.login-msg {
  text-align: center; font-size: 12.5px; border-radius: 9px; padding: 7px 12px; margin: 0 0 14px;
  background: #eef4e9; color: #2c5a24; border: 1px solid #d5e4cb;
}
.login-msg.error { background: #fbeeee; color: #8c2323; border-color: #efd3d3; }
.new-profile { margin-top: 2px; }
.new-profile > summary {
  list-style: none; cursor: pointer; text-align: center; font-size: 12.5px; font-weight: 600;
  color: var(--ink-2); border: 1px dashed var(--hairline); border-radius: 11px; padding: 9px;
  transition: all .15s; user-select: none;
}
.new-profile > summary::-webkit-details-marker { display: none; }
.new-profile > summary:hover { color: var(--accent-strong); border-color: var(--accent); background: #f6faff; }
.new-profile[open] > summary {
  color: var(--accent-strong); border-color: var(--accent-soft); background: #f6faff;
  border-bottom-left-radius: 0; border-bottom-right-radius: 0; border-bottom-style: solid;
}
.new-profile > form {
  border: 1px dashed var(--accent-soft); border-top: none; border-radius: 0 0 11px 11px;
  padding: 14px 16px 12px; background: #fbfdff; animation: rise .2s ease both;
}
.login-card .brand { justify-content: center; padding-bottom: 4px; }
.login-card .brand b, .login-card .brand small { color: inherit; }
.login-card .brand b { color: var(--ink); }
.login-card .brand small { color: var(--muted); }
.login-brand { text-align: center; margin-bottom: 10px; }
.login-logo { width: 132px; height: auto; display: block; margin: 0 auto 6px; }
.login-brand small {
  display: block; color: var(--muted); font-size: 10px; letter-spacing: .14em;
}
.login-sub { text-align: center; color: var(--muted); font-size: 13px; margin: 0 0 20px; }
.personas { display: grid; grid-template-columns: repeat(auto-fill, minmax(196px, 1fr)); gap: 9px; margin-bottom: 20px; }
.persona {
  display: flex; align-items: center; gap: 10px; padding: 9px 11px;
  border: 1px solid var(--hairline); border-radius: 11px; background: var(--surface);
  color: var(--ink); transition: all .15s; animation: rise .35s ease both;
}
.persona:hover {
  text-decoration: none; border-color: var(--accent); box-shadow: var(--shadow-lift);
  transform: translateY(-2px); background: #fbfdff;
}
.persona .avatar { width: 34px; height: 34px; font-size: 12.5px; flex-shrink: 0; }
.persona b { display: block; font-size: 13px; line-height: 1.2; }
.persona small { color: var(--muted); font-size: 11px; display: block; }
.login-divider {
  display: flex; align-items: center; gap: 12px; color: var(--muted); font-size: 11.5px;
  text-transform: uppercase; letter-spacing: .08em; margin: 4px 0 14px;
}
.login-divider::before, .login-divider::after { content: ""; flex: 1; height: 1px; background: var(--hairline); }
.login-free { display: flex; gap: 8px; }
.login-hint { font-size: 12px; color: var(--muted); margin-top: 16px; line-height: 1.6; text-align: center; }

/* ---------- Utilidades ---------- */
.muted { color: var(--muted); }
.small { font-size: 12px; }
.mt0 { margin-top: 0; } .mb0 { margin-bottom: 0; }
.flex { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.right { margin-left: auto; }
.tag { display: inline-block; white-space: nowrap; font-size: 11px; background: var(--page); border: 1px solid var(--hairline); border-radius: 6px; padding: 1px 7px; color: var(--ink-2); }

/* Canal de vente — le registre existe justement pour voir les 4 canaux au
   même endroit (§3.2), donc la colonne doit se lire d'un coup d'œil. Mêmes
   couleurs que le schéma du workflow eshop, pour garder un seul langage. */
.canal { display: inline-block; white-space: nowrap; font-size: 11px; font-weight: 600;
         border: 1px solid; border-radius: 6px; padding: 1px 7px; letter-spacing: .01em; }
.canal.c-woo       { background: #f3e8fa; color: #6b2f8f; border-color: #ddc2ec; }
.canal.c-systemeio { background: #e2f6ee; color: #0c6b4a; border-color: #b5e6d3; }
.canal.c-stripe    { background: #ecebff; color: #4b3fc4; border-color: #d3d0fb; }
/* `c-stripe_link` est la vraie valeur du canal ; `c-stripe` était écrit à la
   main et ne correspondait à rien, donc les ventes Stripe sortaient sans
   couleur dans le registre. Les deux sont là : la classe suit désormais la
   donnée, et l'ancienne ne casse rien si elle traîne quelque part. */
.canal.c-stripe,
.canal.c-stripe_link { background: #e9f1fc; color: #1c5cab; border-color: #c4dcf6; }
.canal.c-virement  { background: #fdf3dc; color: #8a5f00; border-color: #f3dda6; }
.canal.c-cheque    { background: var(--page);  color: var(--ink-2); border-color: var(--hairline); }
/* Origine automatique : un liseré indique que personne ne l'a saisie à la main. */
.canal.auto::after { content: "⟳"; margin-left: 4px; opacity: .65; font-weight: 400; }
/* Le canal se change SUR PLACE, depuis le registre et la fiche. Le <select>
   porte la pastille elle-même — mêmes couleurs, même taille que la version
   lue, la colonne ne saute donc pas selon qu'on peut ou non le modifier. Le
   chevron vit sur le formulaire, pas sur le <select> : les couleurs de canal
   sont posées en `background` raccourci, qui effacerait une image de fond. */
.canal-edit { position: relative; display: inline-flex; align-items: center; margin: 0; }
.canal-edit::after { content: ""; position: absolute; right: 8px; top: 50%; width: 5px; height: 5px;
  margin-top: -4px; border: solid currentColor; border-width: 0 1.5px 1.5px 0; transform: rotate(45deg);
  color: var(--ink-2); opacity: .45; pointer-events: none; }
select.canal { height: auto; line-height: 1.5; width: auto; min-width: 0; font-size: 11px; font-weight: 600;
  padding: 1px 21px 1px 7px !important; border-radius: 6px; box-shadow: none; text-overflow: clip;
  background-image: none; letter-spacing: .01em; }
select.canal:hover, select.canal:focus { transform: none; box-shadow: none; outline: none; filter: brightness(.965); }
table.data select.canal:hover { box-shadow: none; }
select.canal { min-height: 0; }
/* Au clavier, l'anneau de la maison ; à la souris, rien — la pastille suffit. */
select.canal:focus-visible { box-shadow: 0 0 0 3px var(--accent-soft); }
select.canal.c-vide { color: var(--muted); border-style: dashed; border-color: var(--hairline);
  background-color: var(--page); }

/* ---------- Vente automatique en attente de validation ----------
   La ligne se distingue sans crier : liseré à gauche et fond très léger. */
tr.row-avalider > td { background: #fffaf0; }
tr.row-avalider > td:first-child { box-shadow: inset 3px 0 0 var(--serious); }
.badge-btn { cursor: pointer; font-family: inherit; font-size: inherit; }
.badge-btn:hover { filter: brightness(.96); text-decoration: none; }

/* Modal de validation : le brut du webhook à gauche, ce qu'on confirme à droite. */
.val-warn {
  background: #fdf3dc; border: 1px solid #f3dda6; border-left-width: 3px;
  color: #8a5f00; border-radius: 8px; padding: 10px 13px; font-size: 12.5px;
  margin-bottom: 14px;
}
.val-warn div + div { margin-top: 5px; }
.val-cols { display: flex; gap: 20px; flex-wrap: wrap; align-items: flex-start; }
.val-raw { flex: 1; min-width: 280px; background: var(--page);
           border-radius: 10px; padding: 12px 14px; }
.val-edit { flex: 1; min-width: 280px; display: flex; flex-direction: column; gap: 10px; }
.val-edit label { display: flex; flex-direction: column; gap: 3px; }
/* « Reçu de Systeme.io » : un tableau en trois groupes (commande, cliente,
   paiement). Posé en carte blanche sur le fond du panneau, avec les mêmes
   filets que l'échéancier juste en dessous — les deux blocs se lisent comme
   une seule fiche. */
.val-table { width: 100%; border-collapse: separate; border-spacing: 0;
             background: var(--surface); border: 1px solid var(--hairline);
             border-radius: 8px; overflow: hidden; font-size: 12.5px; }
/* La colonne des libellés prend la largeur du plus long (« Code promo »),
   pas un pourcentage fixe : à 34 % elle volait la place de la valeur, et une
   adresse e-mail se coupait au milieu d'un mot. `overflow-wrap: anywhere`
   ne coupe plus qu'en dernier recours, quand la valeur ne tient vraiment pas. */
.val-table th { width: 1%; padding: 6px 14px 6px 10px; text-align: left;
                vertical-align: top; font-weight: 500; color: var(--muted);
                white-space: nowrap; }
.val-table td { padding: 6px 10px; font-weight: 500; color: var(--ink);
                overflow-wrap: anywhere; }
.val-table tr + tr > * { border-top: 1px solid var(--hairline); }
/* Entre deux groupes, un filet plus marqué : la séparation se voit sans titre. */
.val-table tbody + tbody tr:first-child > * {
  border-top: 1px solid color-mix(in srgb, var(--muted) 38%, transparent); }
.val-table td.vide { color: var(--muted); font-weight: 400; }
.val-sched { font-size: 12px; font-variant-numeric: tabular-nums; }
.vs-line { display: grid; grid-template-columns: 18px 1fr auto auto; gap: 8px;
           padding: 3px 0; border-bottom: 1px solid var(--hairline); }
.vs-line:last-child { border-bottom: 0; }
.vs-line.ok { color: var(--good-text); }
.vs-line span:first-child { color: var(--muted); }

/* Bandeaux d'alerte du tableau de bord (§3.1) — au-dessus des statistiques,
   cliquables, et absents quand il n'y a rien à traiter. */
.alert-strip { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.al {
  display: flex; align-items: baseline; gap: 8px; flex: 1; min-width: 260px;
  padding: 9px 13px; border-radius: 10px; border: 1px solid; font-size: 13px;
  text-decoration: none; transition: box-shadow .15s, transform .12s;
}
.al:hover { text-decoration: none; box-shadow: var(--shadow); transform: translateY(-1px); }
.al b { font-weight: 650; }
.al-critical { background: #fbe4e4; border-color: #f2bcbc; color: #8f2020; }
.al-warning  { background: #fdf3dc; border-color: #f3dda6; color: #8a5f00; }
.al-accent   { background: #e9f1fc; border-color: #c4dcf6; color: #1c5cab; }
.al-who { font-size: 11.5px; opacity: .8; margin-left: auto; text-align: right;
          white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 45%; }

/* « À régler » d'Accès à ouvrir (HH-2855) — une ligne par problème, le lien
   sur le texte, et « C'est réglé » à droite pour un mail non délivré. */
.care-alertes { flex-direction: column; gap: 6px; }
.care-alertes .al { flex: none; align-items: center; min-width: 0; }
.care-alertes .al:hover { transform: none; box-shadow: none; }
.ca-al-txt { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px;
             flex: 1; min-width: 0; color: inherit; text-decoration: none; }
a.ca-al-txt:hover { text-decoration: none; }
a.ca-al-txt:hover b { text-decoration: underline; }
.ca-al-qui { font-size: 11.5px; opacity: .8; margin-left: auto; }
.care-alertes form { margin: 0; flex: none; }
.ca-al-btn { font: inherit; font-size: 12px; color: inherit; background: none; cursor: pointer;
             border: 1px solid currentColor; border-radius: 7px; padding: 2px 9px; opacity: .8; }
.ca-al-btn:hover { opacity: 1; }
.ca-al-btn:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }

/* Échéancier — «payées / total» avec le même feu que l'écran de suivi (§3.5),
   pour repérer un dossier en défaut sans ouvrir la fiche. */
.ech { display: inline-block; white-space: nowrap; font-variant-numeric: tabular-nums;
       font-size: 12px; font-weight: 600; padding: 1px 6px; border-radius: 6px;
       border: 1px solid transparent; }
.ech::before { content: "●"; font-size: 7px; vertical-align: 2px; margin-right: 4px; }
.ech.t-vacio    { color: var(--muted); font-weight: 400; }
.ech.t-vacio::before { content: none; }
.ech.t-neutro   { color: var(--ink-2); background: var(--page); border-color: var(--hairline); }
.ech.t-neutro::before { color: var(--muted); }
.ech.t-good     { color: var(--good-text); background: #e7f6e7; border-color: #bfe6bf; }
.ech.t-warning  { color: #8a5f00;          background: #fdf3dc; border-color: #f3dda6; }
.ech.t-critical { color: #8f2020;          background: #fbe4e4; border-color: #f2bcbc; }
.empty {
  color: var(--muted); font-size: 13px; padding: 22px 10px; text-align: center;
  border: 1px dashed var(--hairline); border-radius: 9px; background: var(--page);
}
td.empty, tr .empty { border: none; background: none; padding: 16px 0; }
.divider { border: none; border-top: 1px solid var(--hairline); margin: 14px 0; }
.photo-cell { font-size: 20px; }
.avatar {
  width: 28px; height: 28px; border-radius: 50%; background: var(--ink); color: #fff;
  display: inline-flex; align-items: center; justify-content: center; font-size: 11.5px; font-weight: 700;
}

/* ---------- Impresión (PDF del presupuesto) ---------- */
@media print {
  .sidebar, .topbar, .no-print, .toasts { display: none !important; }
  .content { padding: 0; max-width: none; }
  body { background: #fff; }
  .card { box-shadow: none; animation: none; }
}

/* ---------- Capa de interacción: tooltips y gráficos vivos ---------- */
#viz-tip {
  position: fixed; z-index: 300; background: var(--ink); color: #fff;
  font-size: 12px; font-weight: 600; padding: 5px 10px; border-radius: 7px;
  pointer-events: none; opacity: 0; transform: translate(-50%, -100%) translateY(-8px);
  transition: opacity .12s; max-width: 280px; text-align: center;
  box-shadow: 0 6px 18px rgba(11, 11, 11, .28); line-height: 1.4; white-space: pre-line;
}
#viz-tip.on { opacity: 1; }
/* L'infobulle qui EXPLIQUE (HH-2629). Posée d'office sur toute infobulle riche
   (`data-tip-html`) : ce sont les statuts du registre, ce qu'il reste à faire,
   par quoi commencer. Sur fond sombre, centrée, tout en gras, c'était un pavé
   noir illisible. Ici : un titre, un texte, la liste de ce qui manque, et
   l'action à faire mise en avant. */
#viz-tip.riche {
  background: var(--surface); color: var(--ink); font-weight: 400; font-size: 12.5px;
  text-align: left; white-space: normal; max-width: 360px; padding: 12px 14px 11px;
  border: 1px solid var(--hairline); border-radius: 12px; line-height: 1.5;
  box-shadow: 0 12px 34px rgba(11, 11, 11, .16);
}
#viz-tip.riche b {
  display: block; font-size: 11px; font-weight: 800; letter-spacing: .07em;
  text-transform: uppercase; color: var(--ink-2); margin: 0 0 6px;
  padding-bottom: 6px; border-bottom: 1px solid var(--hairline);
}
/* La couleur du statut, la même que son badge : rouge « À valider », ambre
   « À checker », bleu « À traiter », vert « Complet ». Un point devant le
   titre et un filet en haut de la bulle — on sait de quoi on parle avant
   d'avoir lu. */
#viz-tip.riche b::before { content: ""; display: inline-block; width: 7px; height: 7px;
  border-radius: 50%; margin-right: 7px; vertical-align: 1px; background: var(--tt, var(--ink-2)); }
#viz-tip.riche b { color: var(--tt, var(--ink-2)); }
#viz-tip.riche .t-a_valider { --tt: var(--sem-defaut-t); }
#viz-tip.riche .t-a_checker { --tt: var(--sem-attente-t); }
#viz-tip.riche .t-a_facturer { --tt: var(--sem-facture-t); }
#viz-tip.riche .t-a_traiter { --tt: var(--accent-strong); }
#viz-tip.riche .t-complet   { --tt: var(--good-text); }
#viz-tip.riche:has(.t-a_valider) { border-top: 3px solid var(--sem-defaut); }
#viz-tip.riche:has(.t-a_checker) { border-top: 3px solid var(--sem-attente); }
#viz-tip.riche:has(.t-a_facturer) { border-top: 3px solid var(--sem-facture); }
#viz-tip.riche:has(.t-a_traiter) { border-top: 3px solid var(--accent); }
#viz-tip.riche:has(.t-complet)   { border-top: 3px solid var(--good-text); }
/* Les gabarits séparent titre et texte par un <br> : après un titre en bloc,
   il ne fait plus qu'un trou. */
#viz-tip.riche b + br, #viz-tip.riche u + br, #viz-tip.riche br:has(+ i), #viz-tip.riche .reste + br { display: none; }
#viz-tip.riche u {
  display: block; text-decoration: none; margin-top: 8px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--sem-attente-t);
}
/* Ce qu'il reste à faire, en liste : « Accès · Mail onboarding · Facture »
   collés sur une ligne ne se comptent pas. */
#viz-tip.riche .reste { display: flex; flex-wrap: wrap; gap: 4px; margin: 4px 0 0; }
#viz-tip.riche .reste span {
  font-size: 11.5px; padding: 1px 8px; border-radius: 999px;
  background: var(--sem-attente-bg); color: var(--sem-attente-t);
}
/* L'action : ce qu'on doit faire, là, maintenant. */
#viz-tip.riche i {
  display: flex; gap: 7px; align-items: flex-start; font-style: normal;
  margin-top: 10px; padding: 7px 10px; border-radius: 8px;
  background: var(--accent-soft); color: var(--accent-strong); font-weight: 600;
}
#viz-tip.riche i::before { content: "→"; flex: none; }
/* La variante claire : pour ce qui se LIT plutôt que se survole. Les notes
   d'un entretien font un paragraphe — aligné à gauche, sur fond clair, avec
   les intertitres qui respirent. Le fond sombre reste pour les trois mots
   d'une pastille. */
#viz-tip.clair {
  background: var(--surface); color: var(--ink); font-weight: 400;
  text-align: left; white-space: normal; max-width: 340px; padding: 11px 14px;
  border: 1px solid var(--hairline); border-radius: 11px;
  box-shadow: 0 10px 30px rgba(11, 11, 11, .14);
}
/* Les cinq blocs ne sont pas cinq champs au hasard : c'est LE DÉROULÉ de
   l'appel — où elle en est, ce qui fait mal, ce qui résiste, ce qui la fait
   basculer, ce qui débloque. Ils portent donc la progression sémantique de la
   plateforme, celle des étapes : gris (le contexte) → rouge (la douleur) →
   ambre (le frein) → violet (la bascule) → vert (la clé). On retrouve le stade
   du dossier à la couleur, sans lire l'intitulé — et l'infobulle cesse d'être
   un pavé gris de quatre paragraphes.
   Une seule variable par bloc : la pastille, le texte de l'intitulé et le
   filet du paragraphe en descendent tous les trois. */
#viz-tip.clair b, #viz-tip.clair i { --tc: var(--sem-ops); }
#viz-tip.clair .t-dou { --tc: var(--sem-defaut); }
#viz-tip.clair .t-fre { --tc: var(--sem-attente); }
#viz-tip.clair .t-bas { --tc: var(--sem-care); }
#viz-tip.clair .t-cle { --tc: var(--sem-facture); }
#viz-tip.clair b {
  display: inline-flex; align-items: center; gap: 5px;
  margin: 13px 0 5px; padding: 2px 9px 2px 7px; border-radius: 999px;
  font-size: 9.5px; letter-spacing: .085em; text-transform: uppercase;
  font-weight: 800; line-height: 14px;
  color: color-mix(in srgb, var(--tc) 76%, #000 24%);
  background: color-mix(in srgb, var(--tc) 13%, transparent);
}
#viz-tip.clair b::before { content: ""; flex: none; width: 5px; height: 5px;
  border-radius: 50%; background: var(--tc); }
#viz-tip.clair b:first-child { margin-top: 0; }
/* Les notes d'un appel en DEUX colonnes : en une seule, cinq blocs faisaient
   une infobulle plus haute que l'écran, coupée en bas. Chaque bloc (intitulé
   + paragraphe) reste d'un seul tenant. */
#viz-tip.clair:has(.tb) { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px 18px; max-width: min(640px, calc(100vw - 24px)); width: max-content; }
#viz-tip.clair:has(.tb:only-child) { grid-template-columns: 1fr; max-width: 340px; }
#viz-tip.clair .tb { display: flex; flex-direction: column; align-items: flex-start;
  min-width: 0; max-width: 300px; }
#viz-tip.clair .tb b { margin-top: 0; }
#viz-tip.clair .tb i { align-self: stretch; }
/* Recalée verticalement quand elle ne tient ni au-dessus ni en dessous. */
#viz-tip.cale { transform: translate(-50%, 0); }
/* Le paragraphe est rattaché à son intitulé par un filet de la même teinte :
   sur quatre blocs d'affilée, c'est ce qui dit où l'un finit et l'autre
   commence sans tracer quatre séparateurs en travers. */
#viz-tip.clair i { display: block; font-style: normal; font-size: 12px;
  line-height: 1.45; padding-left: 9px;
  border-left: 2px solid color-mix(in srgb, var(--tc) 30%, transparent); }

/* ── L'enregistrement de l'appel, saisi dans la ligne ──────────────────────
   Au repos ce n'est PAS un champ : c'est un tiret gris, ou le nom de
   l'enregistrement. Une bordure permanente sur soixante lignes ferait un mur
   de formulaire là où on vient balayer des prospectes. Le champ se révèle au
   survol de la cellule — là où on a l'intention d'écrire — et se pose au
   focus. Même parti que `input.inline-edit`, ailleurs dans la plateforme. */
/* 168px : un champ de date porte son icône de calendrier, et à 138 l'année
   se faisait couper — « 09/15/202 ». */
.c-acc { width: 168px; }
/* `.c-acc input.pv-acces` (0,2,1) et pas `.pv-acces` (0,1,0) : la règle
   générale des champs du tableau l'emportait, et tous les champs de date
   s'affichaient encadrés — le tableau ressemblait à un formulaire. C'est le
   même piège que `.c-fat input.fat-input`, trois lignes plus bas. */
.c-acc input.pv-acces {
  width: 100%; margin: 0; padding: 1px 2px; font-size: 11.5px;
  border: 1px solid var(--accent); background: var(--surface);
  color: var(--ink-2); font-variant-numeric: tabular-nums;
}
.pv-acces-voir {
  border: 0; background: none; padding: 2px 4px; cursor: pointer; font: inherit;
  font-size: 11.5px; color: var(--ink-2); font-variant-numeric: tabular-nums;
  border-bottom: 1px dashed transparent;
}
.pv-acces-voir.vide { color: var(--muted); }
.pv-acces-voir:hover { border-bottom-color: var(--hairline); color: var(--ink); }
.pv-seq { margin-top: 2px; font-variant-numeric: tabular-nums; }
.c-fat { width: 210px; }
.fat-form { display: block; margin: 0; min-width: 0; flex: 1 1 auto; }
/* `.c-fat input.fat-input` (0,2,1) et pas `.fat-input` (0,1,0) : la règle des
   types d'input oubliés — `input[type=url]`, plus bas dans la feuille — rendait
   au champ sa bordure, son fond blanc et ses 7 px de rembourrage. C'est le même
   piège de spécificité que celui déjà noté sur `input.inline-edit`. */
.c-fat input.fat-input {
  width: 100%; min-width: 0; font-size: 11.5px; padding: 2px 6px;
  font-family: inherit; color: var(--muted);
  border: 1px solid transparent; border-radius: 7px;
  background: none; box-shadow: none;
  text-overflow: ellipsis; transition: background .15s, border-color .15s;
}
/* Le survol se déclenche sur LA CELLULE, pas sur le champ : viser un texte de
   quinze pixels de haut pour découvrir qu'il est éditable, personne ne le
   fait. On passe sur la colonne, le champ apparaît. */
.pv-ligne:hover .c-fat input.fat-input,
.c-fat:hover input.fat-input {
  border-color: var(--hairline); background: var(--surface);
  color: var(--ink-2);
}
.c-fat input.fat-input:focus {
  border-color: var(--accent); background: var(--surface);
  outline: 0; box-shadow: 0 0 0 3px var(--accent-soft); color: var(--ink);
}
.c-fat input.fat-input::placeholder { color: var(--muted); }
/* Renseigné, le lien se lit comme un lien — et le champ le laisse voir. */
.c-fat.rempli input.fat-input { color: var(--accent); font-weight: 500; }
.c-fat > .fat-cell { display: flex; align-items: center; gap: 3px; }
.fat-voir { flex: none; display: inline-flex; color: var(--muted);
  padding: 2px; border-radius: 6px; }
.fat-voir:hover { color: var(--accent); background: var(--accent-soft); }
/* Basculée sous le curseur quand il n'y a pas la place au-dessus. */
#viz-tip.dessous { transform: translate(-50%, 0) translateY(12px); }
a[data-tip], .chart-group[data-tip] { cursor: pointer; }

.chart-bar { transition: opacity .15s, filter .15s; }
.chart-cols:has(.chart-group:hover) .chart-group:not(:hover) .chart-bar { opacity: .35; }
.chart-group:hover .chart-bar { filter: brightness(1.12); }
.chart-x { transition: color .15s; }
.chart-group:hover .chart-x { color: var(--ink); font-weight: 650; }

.hbar { border-radius: 8px; padding: 3px 6px; margin: 0 -6px; transition: background .15s; }
a.hbar { color: inherit; }
a.hbar:hover { text-decoration: none; }
.hbar .fill { transition: opacity .15s, filter .15s; }
.hbars:has(.hbar:hover) .hbar:not(:hover) .fill { opacity: .45; }
.hbar:hover { background: var(--page); }
.hbar:hover .fill { filter: brightness(1.12); }

.meter .fill { transition: filter .15s; }
.meter:hover .fill { filter: brightness(1.18); }

.card { transition: box-shadow .25s; }
.card:hover { box-shadow: 0 2px 4px rgba(11,11,11,.06), 0 10px 26px rgba(11,11,11,.09); }
.nav-item { transition: background .15s, color .15s, transform .15s; }
.nav-item:hover { transform: translateX(2px); }
.btn:active { transform: scale(.97); }

/* ---------- Respuesta rápida desde la bandeja (borrador IA) ---------- */
.quick-reply { position: relative; display: inline-block; margin-right: 4px; }
.quick-reply > summary {
  list-style: none; cursor: pointer; user-select: none; white-space: nowrap;
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12px; font-weight: 600; color: var(--ink);
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: 8px; padding: 4px 10px; transition: background .15s, border-color .15s, color .15s;
}
.quick-reply > summary::-webkit-details-marker { display: none; }
.quick-reply > summary:hover { border-color: var(--accent); color: var(--accent-strong); background: #f6faff; }
.quick-reply[open] > summary { border-color: var(--accent); color: var(--accent-strong); background: #eef5fd; }
.quick-reply.good > summary { background: var(--good); border-color: #0a8a0a; color: #fff; }
.quick-reply.good > summary:hover, .quick-reply.good[open] > summary { background: #0a8a0a; color: #fff; }
.qr-panel {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 60;
  width: 480px; max-width: 82vw; text-align: left; white-space: normal;
  background: var(--surface); border: 1px solid var(--hairline); border-radius: 12px;
  box-shadow: var(--shadow-lift); padding: 14px 16px; animation: rise .18s ease both;
}
.qr-panel textarea { width: 100%; font: inherit; font-size: 13px; }
.qr-quote {
  font-size: 12px; color: var(--muted); background: var(--page);
  border-left: 3px solid var(--hairline); border-radius: 0 8px 8px 0;
  padding: 7px 10px; margin-bottom: 10px;
}

/* ---------- Ma journée ---------- */
a.day-block { text-decoration: none; color: inherit; display: block; }
a.day-block:hover { text-decoration: none; }
.day-ico {
  width: 32px; height: 32px; border-radius: 9px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent-soft); color: var(--accent-strong);
}
.day-ico.critical { background: #f8dcdc; color: var(--critical); }
.day-ico.warning { background: #fdeecb; color: #8a6510; }
.meter .fill.good { background: var(--good); }

/* ---------- Fil de conversation (care) ---------- */
.bubble {
  max-width: 88%; border-radius: 12px; padding: 9px 12px; margin-bottom: 8px;
  border: 1px solid var(--hairline);
}
.bubble.in { background: var(--page); border-top-left-radius: 4px; }
.bubble.out {
  background: #eef5fd; border-color: var(--accent-soft);
  margin-left: auto; border-top-right-radius: 4px;
}
.bubble .b-meta { font-size: 11px; color: var(--muted); margin-top: 4px; }

/* ---------- Gráfico de meses clicable (KPIs) ---------- */
a.chart-group { text-decoration: none; color: inherit; cursor: pointer; }
a.chart-group:hover { text-decoration: none; }
a.chart-group.on .chart-bar { background: var(--accent-strong); }
a.chart-group.on .chart-x { color: var(--accent-strong); font-weight: 700; }

/* La cliente choisie, à la place des champs de création : l'écran ne montre
   plus les deux chemins ouverts en même temps. */
.client-choisi { display: flex; align-items: center; gap: 10px; margin-bottom: 10px;
  padding: 9px 12px; border-radius: 10px;
  background: var(--good-tint); border: 1px solid var(--good-tint-border); }
.client-choisi .cc-ok { flex: none; display: grid; place-items: center;
  width: 20px; height: 20px; border-radius: 50%; font-size: 11px; font-weight: 700;
  background: var(--sem-facture); color: #fff; }
.client-choisi > div { flex: 1; min-width: 0; font-size: 12.5px; color: var(--ink-2); }
.client-choisi b { color: var(--ink); }
.client-choisi span { color: var(--muted); }
.client-choisi .btn { flex: none; }

/* ---------- Combobox de recherche (client, etc.) ---------- */
.combo { position: relative; }
.combo-input { width: 100%; }
.combo-list {
  position: absolute; z-index: 50; left: 0; right: 0; top: calc(100% + 4px);
  max-height: 260px; overflow-y: auto; display: none;
  background: var(--surface); border: 1px solid var(--hairline); border-radius: 10px;
  box-shadow: var(--shadow-lift); padding: 4px;
}
.combo.open .combo-list { display: block; }
.combo-item {
  padding: 7px 10px; border-radius: 7px; cursor: pointer; font-size: 13px;
  line-height: 1.3;
}
.combo-item.hidden { display: none; }
.combo-item:hover, .combo-item.active { background: var(--accent-soft); }
.combo-item.is-new { color: var(--accent-strong); font-weight: 600; border-bottom: 1px solid var(--hairline); border-radius: 7px 7px 0 0; }
/* La recherche d'adresses ouvre la LISTE, pas le conteneur : elle n'a pas de
   `.combo.open` à qui s'accrocher. Sans cette règle la liste se remplit et ne
   s'affiche jamais — un bug muet, puisque tout le reste marche. */
.combo-list.open { display: block; }
/* Le repli à l'étranger. Un pied de liste, pas un bouton dans le formulaire :
   il ne se lit qu'au moment où l'on constate qu'aucune proposition ne convient,
   et il disparaît avec la liste. */
.combo-monde {
  display: flex; align-items: center; gap: 7px; width: 100%;
  margin-top: 4px; padding: 8px 10px; border: 0; border-top: 1px solid var(--hairline);
  border-radius: 0 0 7px 7px; background: none; cursor: pointer;
  font: inherit; font-size: 12px; color: var(--ink-2); text-align: left;
}
.combo-monde:hover { background: var(--accent-soft); color: var(--accent-strong); }
.combo-monde u { text-underline-offset: 2px; }
.combo-vide { padding: 8px 10px; font-size: 12.5px; color: var(--muted); }
/* ---------- Select filtrable ----------
   Garde l'aspect d'un select fermé (chevron, curseur), devient un champ de
   recherche à l'ouverture. La liste est une vraie surface flottante : ombre,
   coins arrondis, ligne active marquée — pas la liste système. */
.sel-search .combo-input {
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23898781' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center;
  padding-right: 28px; cursor: pointer; text-overflow: ellipsis;
  transition: border-color .14s, box-shadow .14s, background-color .14s;
}
.sel-search .combo-input:hover { border-color: var(--muted); }
.sel-search.open .combo-input {
  cursor: text; border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
  background-color: var(--surface);
}
/* Chevron retourné quand c'est ouvert : l'état se lit sans réfléchir. */
.sel-search.open .combo-input {
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 5l4-4 4 4' fill='none' stroke='%232a78d6' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E");
}
.sel-search .combo-list {
  box-shadow: var(--shadow-lift); border-radius: 10px; padding: 4px;
  max-height: 280px; scrollbar-width: thin;
  /* Au-dessus du modal : la liste est en `fixed`, donc elle sort de la boîte
     et doit passer devant tout ce qu'elle survole. */
  z-index: 200;
}
/* Les pastilles d'une option : à droite, alignées entre elles, pour qu'on
   compare les taux d'un coup d'œil au lieu de les chercher dans le texte. */
.sel-search .combo-item:has(.sel-badge), .sel-search .combo-item:has(.sel-tag) {
  display: flex; align-items: center; gap: 7px;
}
.sel-badge, .sel-tag {
  margin-left: auto; flex: none; padding: 1px 8px; border-radius: 999px;
  font-size: 10.5px; font-weight: 600; font-variant-numeric: tabular-nums;
}
.sel-badge { background: var(--sem-facture-bg); color: var(--sem-facture-t); }
/* L'en-tête d'un groupe : un repère, pas une ligne de la liste. Il ne se
   survole pas, ne se choisit pas, et porte le trait de sa famille à gauche —
   la même couleur que la pastille des options qu'il coiffe. */
.combo-groupe {
  padding: 7px 10px 3px; font-size: 10.5px; font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase; color: var(--muted);
  border-left: 3px solid var(--gc, var(--hairline)); cursor: default;
  position: sticky; top: 0; background: var(--surface); z-index: 1;
}
.combo-groupe + .combo-item { border-left: 3px solid transparent; }
/* « externe » n'est pas une valeur, c'est une qualité : ton neutre, et elle
   passe AVANT le taux — on lit qui c'est, puis combien. */
.sel-tag { margin-left: auto; background: var(--sem-ops-bg); color: var(--sem-ops-t); }
.sel-tag + .sel-badge { margin-left: 0; }
.combo-item.chosen .sel-badge, .combo-item.active .sel-badge { background: #fff; }

.sel-search .combo-item {
  border-radius: 7px; padding: 6px 10px 6px 26px; position: relative;
  line-height: 1.35;
}
.sel-search .combo-item.chosen { font-weight: 600; color: var(--accent-strong); }
.sel-search .combo-item.chosen::before {
  content: "✓"; position: absolute; left: 9px; color: var(--accent); font-size: 11px;
}
/* La ligne survolée et la ligne au clavier se ressemblent : une seule cible. */
.sel-search .combo-item.active, .sel-search .combo-item:hover {
  background: var(--accent-soft); box-shadow: none;
}
.sel-search .combo-list:empty::after,
.sel-search .combo-item.no-hit {
  content: "Aucun résultat"; display: block; padding: 8px 10px;
  color: var(--muted); font-size: 12.5px; font-style: italic;
}

/* ---------- Bouton flottant de support (portail élève) ---------- */
.fab-support { position: fixed; right: 26px; bottom: 26px; z-index: 80; }
.fab-support > summary {
  list-style: none; cursor: pointer; width: 56px; height: 56px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; color: #fff;
  background: var(--accent);
  box-shadow: 0 6px 20px rgba(28, 92, 171, .45); transition: transform .15s, box-shadow .15s;
}
.fab-support > summary::-webkit-details-marker { display: none; }
.fab-support > summary:hover { transform: translateY(-2px); box-shadow: 0 10px 26px rgba(28, 92, 171, .5); }
.fab-support[open] > summary { transform: scale(.94); }
.fab-panel {
  position: absolute; right: 0; bottom: calc(100% + 12px); width: 320px; max-width: 86vw;
  background: var(--surface); border: 1px solid var(--hairline); border-radius: 14px;
  box-shadow: var(--shadow-lift); padding: 16px 18px; animation: rise .18s ease both;
}
.fab-head { display: flex; align-items: center; font-weight: 650; font-size: 14px; margin-bottom: 12px; }
.fab-close { margin-left: auto; color: var(--muted); font-size: 15px; }

/* ---------- Modal générique ---------- */
.modal-overlay {
  position: fixed; inset: 0; z-index: 100; display: none;
  background: rgba(11, 11, 11, .42); backdrop-filter: blur(2px);
  align-items: center; justify-content: center; padding: 24px;
  /* Les animations d'Animate.css partent parfois de très loin — `backInUp`
     commence à 1 200 px sous l'écran. Sans ça, chacune ferait apparaître une
     barre de défilement le temps de son trajet. Découper ici rend TOUS les
     effets interchangeables sans y penser. */
  overflow: hidden;
}
/* Le modal ARRIVE : on doit voir le geste, pas le résultat.

   Trois erreurs successives ici, gardées en note parce qu'elles se
   ressemblent. D'abord l'animation portait sur l'overlay ENTIER : le voile
   sombre glissait avec la boîte, ce qui ne se lit pas. Ensuite elle était
   trop discrète — 14 px et 2,5 % d'échelle sur un modal de 1 400 px de large,
   c'est invisible. Et enfin le réglage « mouvement réduit » du système la
   coupait entièrement, sans rien mettre à la place.

   Maintenant : le voile s'installe et se floute, la boîte monte de 28 px en
   partant à 92 %, sur une courbe qui dépasse franchement en fin de course —
   c'est ce dépassement qui fait qu'elle « se pose » au lieu de s'afficher. */
/* Pas d'animation CSS sur l'ouverture : js/modal-anim.js pilote le voile ET
   la boîte avec GSAP, et deux moteurs sur la même propriété se battent. Le
   CSS reprend la main sous « mouvement réduit », plus bas. */
.modal-overlay.open { display: flex; }
/* Quand le morphing depuis le bouton prend la main (js/modal-morph.js), il
   pilote l'opacité de la boîte lui-même : les deux animations se battraient.
   Le CSS reste le chemin par défaut — clavier, ouverture par URL, navigateur
   sans Web Animations. */
@keyframes voile {
  from { opacity: 0; backdrop-filter: blur(0); }
  to   { opacity: 1; backdrop-filter: blur(2px); }
}
/* Mouvement réduit : on retire le DÉPLACEMENT, pas le repère. Un fondu ne
   déclenche pas de gêne vestibulaire, et sans lui le modal réapparaît d'un
   coup — ce qui est précisément ce qu'on cherchait à corriger. Le `!important`
   est nécessaire : la règle globale du haut de fichier coupe tout avec la
   même arme. */
@keyframes fondu { from { opacity: 0; } to { opacity: 1; } }
/* Mouvement réduit : Animate.css se coupe tout seul (sa feuille contient la
   requête média), et la règle globale du haut de fichier coupe le voile. On
   remet un fondu court : sans lui, le modal réapparaît d'un coup — ce qu'on
   cherchait justement à corriger. Un fondu ne déclenche pas de gêne
   vestibulaire, c'est le déplacement qui la déclenche. */
@media (prefers-reduced-motion: reduce) {
  .modal-overlay.open { animation: fondu .15s ease-out both !important; }
  .modal-overlay.open > .modal-box { animation: fondu .15s ease-out both !important; }
}
.modal-box {
  background: var(--surface); border-radius: 16px; box-shadow: var(--shadow-lift);
  width: 620px; max-width: 94vw; max-height: 88vh; overflow-y: auto; padding: 20px 22px;
}
.modal-box.wide { width: 860px; }
.modal-head { display: flex; align-items: center; font-size: 15px; margin-bottom: 14px; }
.modal-head b { flex: 1; }
/* Onglets d'un modal : deux vues du même sujet, sans deuxième fenêtre. */
.modal-tabs { display: flex; gap: 2px; margin: 0 14px; }
.modal-tab {
  font: inherit; font-size: 12.5px; font-weight: 600; color: var(--muted);
  background: none; border: none; border-bottom: 2px solid transparent;
  padding: 4px 12px 6px; cursor: pointer; transition: color .12s, border-color .12s;
}
.modal-tab:hover { color: var(--ink); }
.modal-tab.actif { color: var(--ink); border-bottom-color: var(--accent); }
.modal-tab .tag { margin-left: 5px; }
.modal-close { cursor: pointer; color: var(--muted); font-size: 16px; }
.modal-close:hover { color: var(--ink); }

/* ---------- « À traiter » : bouton + modal animé (remplace la rangée de tuiles) ---------- */
.worktoday-btn { display: inline-flex; align-items: center; gap: 7px; font-weight: 600; }
.wt-badge { display: inline-flex; align-items: center; justify-content: center; min-width: 20px; height: 20px;
  padding: 0 6px; border-radius: 999px; background: var(--accent); color: #fff; font-size: 12px;
  font-weight: 700; font-variant-numeric: tabular-nums; }
.worktoday-btn.glow { border-color: var(--sem-defaut); color: var(--sem-defaut-t); animation: wt-glow 2.2s ease-in-out infinite; }
.worktoday-btn.glow .wt-badge { background: var(--sem-defaut); }
@keyframes wt-glow { 0%,100% { box-shadow: 0 0 0 0 rgba(208,59,59,0); } 50% { box-shadow: 0 0 0 4px rgba(208,59,59,.16); } }

.modal-box.wt-box { width: 580px; }
.wt-head-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; font-weight: 400; }
.wt-list { display: flex; flex-direction: column; gap: 8px; }
.wt-item { display: flex; align-items: center; gap: 13px; text-decoration: none; color: inherit;
  padding: 11px 14px; border: 1px solid var(--hairline); border-left-width: 3px; border-radius: 11px;
  background: var(--surface); transition: background .14s, border-color .14s, box-shadow .16s, transform .14s;
  opacity: 0; transform: translateY(7px); animation: wt-in .34s ease forwards; }
@keyframes wt-in { to { opacity: 1; transform: none; } }
.wt-item:hover { background: var(--page); box-shadow: var(--shadow); transform: translateY(-1px); }
.wt-ico { flex: 0 0 auto; width: 34px; height: 34px; border-radius: 9px; display: flex; align-items: center; justify-content: center; }
.wt-count { flex: 0 0 auto; min-width: 26px; text-align: right; font-size: 18px; font-weight: 800; font-variant-numeric: tabular-nums; }
.wt-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.wt-label { font-size: 14px; font-weight: 600; line-height: 1.25; }
.wt-sub { font-size: 12px; color: var(--muted); max-height: 0; opacity: 0; overflow: hidden;
  transition: max-height .24s ease, opacity .2s ease, margin-top .22s ease; }
.wt-item:hover .wt-sub { max-height: 22px; opacity: 1; margin-top: 2px; }
.wt-go { flex: 0 0 auto; font-size: 12.5px; font-weight: 700; color: var(--accent); white-space: nowrap;
  opacity: 0; transform: translateX(6px); transition: opacity .18s ease, transform .18s ease; }
.wt-item:hover .wt-go { opacity: 1; transform: none; }
.wt-item.tone-critical { border-left-color: var(--sem-defaut); }
.wt-item.tone-critical .wt-ico { background: var(--sem-defaut-bg); color: var(--sem-defaut-t); }
.wt-item.tone-critical .wt-count, .wt-item.tone-critical .wt-go { color: var(--sem-defaut-t); }
.wt-item.tone-warning { border-left-color: var(--sem-attente); }
.wt-item.tone-warning .wt-ico { background: var(--sem-attente-bg); color: var(--sem-attente-t); }
.wt-item.tone-warning .wt-count { color: var(--sem-attente-t); }
.wt-item.tone-neutral { border-left-color: var(--hairline); }
.wt-item.tone-neutral .wt-ico { background: var(--page); color: var(--ink-2); }
.wt-item:nth-child(1){animation-delay:.03s} .wt-item:nth-child(2){animation-delay:.07s}
.wt-item:nth-child(3){animation-delay:.11s} .wt-item:nth-child(4){animation-delay:.15s}
.wt-item:nth-child(5){animation-delay:.19s} .wt-item:nth-child(6){animation-delay:.23s}
.wt-item:nth-child(7){animation-delay:.27s} .wt-item:nth-child(8){animation-delay:.31s}
.wt-item:nth-child(9){animation-delay:.35s} .wt-item:nth-child(10){animation-delay:.39s}
.wt-item:nth-child(n+11){animation-delay:.42s}
@media (prefers-reduced-motion: reduce) { .worktoday-btn.glow, .wt-item { animation: none; opacity: 1; transform: none; } }

/* Mise en évidence à l'arrivée sur le registre depuis « À traiter » (filtre rapido) */
@keyframes rowflash {
  0%,12% { box-shadow: inset 3px 0 0 var(--accent), inset 0 0 0 200px rgba(42,120,214,.12); }
  100%   { box-shadow: inset 0 0 0 0 rgba(42,120,214,0); }
}
.sales-log.just-filtered td { animation: rowflash 1.7s ease-out; }
@media (prefers-reduced-motion: reduce) { .sales-log.just-filtered td { animation: none; } }

/* ---------- Tutoriel guidé « spotlight » ---------- */
.tour-btn { flex: 0 0 auto; width: 32px; height: 32px; border-radius: 50%; cursor: pointer;
  border: 1px solid var(--hairline); background: var(--surface); color: var(--muted);
  font-weight: 700; font-size: 15px; line-height: 1; display: inline-flex; align-items: center; justify-content: center;
  transition: color .14s, border-color .14s; }
.tour-btn:hover { color: var(--accent); border-color: var(--accent); }
.tour-ov { position: fixed; inset: 0; z-index: 9998; display: none; }
.tour-ov.dim { background: rgba(15, 16, 22, .62); }
.tour-spot { position: fixed; z-index: 9999; display: none; border-radius: 12px; border: 2px solid var(--accent);
  box-shadow: 0 0 0 9999px rgba(15, 16, 22, .62); pointer-events: none;
  transition: top .28s cubic-bezier(.4,.9,.3,1), left .28s cubic-bezier(.4,.9,.3,1), width .28s cubic-bezier(.4,.9,.3,1), height .28s cubic-bezier(.4,.9,.3,1), opacity .18s; }
.tour-spot.hidden { opacity: 0; }
/* Dans une modale : pas d'assombrissement (la modale a son propre fond), juste un halo. */
.tour-spot.ring { box-shadow: 0 0 0 4px var(--accent-soft); }
.tour-card { position: fixed; z-index: 10000; display: none; width: 340px; max-width: calc(100vw - 24px);
  background: var(--surface); border: 1px solid var(--hairline); border-radius: 14px;
  box-shadow: var(--shadow-lift); padding: 16px 18px 13px; color: var(--ink); animation: tour-in .2s ease; }
@keyframes tour-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.tour-eyebrow { display: flex; align-items: center; gap: 7px; font-size: 11px; font-weight: 700;
  letter-spacing: .09em; text-transform: uppercase; color: var(--accent-strong); margin-bottom: 7px; }
.tour-eyebrow .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); flex: 0 0 auto; }
.tour-close { position: absolute; top: 9px; right: 10px; width: 24px; height: 24px; border: none; background: none;
  color: var(--muted); font-size: 14px; line-height: 1; cursor: pointer; border-radius: 7px;
  display: flex; align-items: center; justify-content: center; transition: background .12s, color .12s; }
.tour-close:hover { background: var(--page); color: var(--ink); }
.tour-eyebrow, .tour-title { padding-right: 22px; }
.tour-title { font-size: 17px; font-weight: 700; line-height: 1.25; margin: 0 0 6px; letter-spacing: -.01em; text-wrap: balance; }
.tour-body { font-size: 13.5px; line-height: 1.5; color: var(--ink-2); margin: 0; }
.tour-bar { height: 3px; border-radius: 3px; background: var(--hairline); overflow: hidden; margin: 13px 0 0; }
.tour-bar > i { display: block; height: 100%; background: var(--accent); border-radius: 3px; width: 0; transition: width .3s ease; }
.tour-foot { display: flex; align-items: center; gap: 8px; margin-top: 11px; }
.tour-prog { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; margin-right: auto; }
.tour-skip { background: none; border: none; color: var(--muted); font: inherit; font-size: 12.5px; cursor: pointer; padding: 4px 2px; }
.tour-skip:hover { color: var(--ink); text-decoration: underline; }
/* flèche de la carte pointant vers la cible */
.tour-card::before { content: ""; position: absolute; width: 11px; height: 11px; background: var(--surface);
  border: 1px solid var(--hairline); transform: rotate(45deg); display: none; }
.tour-card.ar-top::before { display: block; top: -6px; left: var(--ar, 26px); border-right: none; border-bottom: none; }
.tour-card.ar-bottom::before { display: block; bottom: -6px; left: var(--ar, 26px); border-left: none; border-top: none; }
.tour-card.ar-left::before { display: block; left: -6px; top: var(--ar, 22px); border-top: none; border-right: none; }
.tour-card.ar-right::before { display: block; right: -6px; top: var(--ar, 22px); border-bottom: none; border-left: none; }
@media (prefers-reduced-motion: reduce) { .tour-spot, .tour-card, .tour-bar > i { transition: none; animation: none; } }

/* Assistant IA du tutoriel : petit personnage animé + chat (gpt-5.5) */
.tour-ai { margin-top: 12px; border-top: 1px solid var(--hairline); padding-top: 10px; }
.tour-ai-toggle { display: flex; align-items: center; gap: 9px; width: 100%; background: none; border: none;
  cursor: pointer; padding: 2px 0; text-align: left; font: inherit; }
.tour-mascot { flex: 0 0 auto; display: inline-flex; }
.tour-ai-say { flex: 1; font-size: 12.5px; font-weight: 600; color: var(--ink-2); }
.tour-ai-cta { flex: 0 0 auto; font-size: 12px; font-weight: 700; color: var(--accent); }
.tour-ai-toggle:hover .tour-ai-cta { text-decoration: underline; }
.tour-ai-panel { margin-top: 10px; }
.tour-ai-msgs { display: flex; flex-direction: column; gap: 7px; max-height: 172px; overflow-y: auto; margin-bottom: 9px; }
.tour-ai-msg { font-size: 12.5px; line-height: 1.45; padding: 7px 10px; border-radius: 11px; max-width: 88%;
  white-space: pre-wrap; overflow-wrap: anywhere; }
.tour-ai-msg.me { align-self: flex-end; background: var(--sem-vente-bg); color: var(--sem-vente-t); border-bottom-right-radius: 4px; }
.tour-ai-msg.bot { align-self: flex-start; background: var(--page); color: var(--ink); border: 1px solid var(--hairline); border-bottom-left-radius: 4px; }
.tour-ai-msg.typing { display: inline-flex; gap: 4px; align-items: center; }
.tour-ai-msg.typing .td { width: 6px; height: 6px; border-radius: 50%; background: var(--muted); animation: ai-td 1s infinite; }
.tour-ai-msg.typing .td:nth-child(2) { animation-delay: .15s; }
.tour-ai-msg.typing .td:nth-child(3) { animation-delay: .3s; }
/* Le tuteur répond en Markdown — tous les modèles le font, et le leur
   interdire dans la consigne ne marche qu'une fois sur deux. Cinq balises
   suffisent, et ce sont les seules que le rendu autorise (voir `md()`). */
.tour-ai-msg.bot strong { font-weight: 650; color: var(--ink); }
.tour-ai-msg.bot em { font-style: italic; }
.tour-ai-msg.bot code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .92em; padding: 1px 4px; border-radius: 4px;
  background: var(--surface); border: 1px solid var(--hairline); }
.tour-ai-msg.bot ul { margin: 4px 0; padding-left: 16px; }
.tour-ai-msg.bot li { margin-bottom: 2px; }
/* La bulle grandit pendant que la réponse s'écrit : sans hauteur minimale,
   elle passe de 0 à trois lignes par à-coups. */
.tour-ai-msg.bot { min-height: 1.45em; }
@keyframes ai-td { 0%, 60%, 100% { opacity: .3; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-3px); } }
.tour-ai-form { display: flex; gap: 6px; }
.tour-ai-form input { flex: 1; min-width: 0; font: inherit; font-size: 12.5px; padding: 7px 10px;
  border: 1px solid var(--hairline); border-radius: 9px; background: var(--surface); color: var(--ink); }
.tour-ai-form input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.tour-ai-send { flex: 0 0 auto; width: 34px; border: 1px solid var(--accent); background: var(--accent); color: #fff;
  border-radius: 9px; cursor: pointer; font-size: 13px; }
.tour-ai-send:hover { background: var(--accent-strong); }
/* la mascotte */
.tour-mascot svg { display: block; animation: mascot-bob 2.6s ease-in-out infinite; }
.tour-mascot .m-head { fill: var(--sem-vente-bg); stroke: var(--accent); stroke-width: 2; }
.tour-mascot .m-eye { fill: var(--accent-strong); transform-box: fill-box; transform-origin: center; animation: mascot-blink 4.2s infinite; }
.tour-mascot .m-mouth { fill: none; stroke: var(--accent-strong); stroke-width: 2; stroke-linecap: round; }
.tour-mascot .m-ant { stroke: var(--accent); stroke-width: 2; stroke-linecap: round; }
.tour-mascot .m-tip { fill: var(--accent); transform-box: fill-box; transform-origin: center; animation: mascot-tip 1.8s ease-in-out infinite; }
.tour-mascot.thinking svg { animation-duration: 1.1s; }
.tour-mascot.thinking .m-tip { animation-duration: .7s; }
@keyframes mascot-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-2.5px); } }
@keyframes mascot-blink { 0%, 92%, 100% { transform: scaleY(1); } 96% { transform: scaleY(.12); } }
@keyframes mascot-tip { 0%, 100% { transform: scale(1); opacity: .55; } 50% { transform: scale(1.25); opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .tour-mascot svg, .tour-mascot .m-eye, .tour-mascot .m-tip { animation: none; } }

/* ---------- Liste des e-mails d'une séquence ---------- */
.mail-list { max-height: 440px; overflow-y: auto; display: flex; flex-direction: column; gap: 3px; }
.mail-row {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  background: var(--page); border: 1px solid var(--hairline); border-radius: 9px;
  padding: 8px 10px; cursor: pointer; font: inherit; transition: border-color .12s, background .12s;
}
.mail-row:hover { border-color: var(--accent); background: #f6faff; }
.mail-row.hidden { display: none; }
.mail-n {
  flex-shrink: 0; width: 30px; height: 30px; border-radius: 8px; font-size: 12px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent-soft); color: var(--accent-strong);
}
.mail-obj { flex: 1; min-width: 0; font-size: 13px; }
.mail-obj b { display: inline; }
.mail-go { color: var(--accent); font-size: 12px; font-weight: 600; flex-shrink: 0; }

/* ---------- Calendrier éditorial (vue mensuelle) ---------- */
.cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px; }
.cal-head { font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted); font-weight: 650; text-align: center; padding: 2px 0; }
.cal-cell {
  min-height: 88px; background: var(--page); border: 1px solid var(--hairline);
  border-radius: 9px; padding: 5px 6px; display: flex; flex-direction: column; gap: 3px;
}
.cal-cell.out { background: transparent; border-color: transparent; }
.cal-cell.out .cal-daynum { color: #cccabf; }
.cal-cell.today { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.cal-daynum { font-size: 11.5px; font-weight: 650; color: var(--ink-2); }
.cal-post {
  font: inherit; font-size: 10.5px; text-align: left; line-height: 1.25; cursor: pointer;
  border: none; border-radius: 6px; padding: 3px 6px; color: #fff; width: 100%;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; transition: filter .12s;
}
.cal-post:hover { filter: brightness(1.08); }
.net-instagram { background: #c2418b; } .net-facebook { background: #2f6fd6; }
.net-youtube  { background: #d03b3b; } .net-linkedin { background: #1c5cab; }
.cal-dot { display: inline-block; width: 9px; height: 9px; border-radius: 3px; vertical-align: -1px; margin-right: 2px; }
.cal-preview { border-radius: 12px; padding: 14px 16px; border: 1px solid var(--hairline); background: var(--page); border-left: 4px solid var(--accent); }
.cal-preview.net-instagram { border-left-color: #c2418b; }
.cal-preview.net-facebook { border-left-color: #2f6fd6; }
.cal-preview.net-youtube { border-left-color: #d03b3b; }
.cal-preview.net-linkedin { border-left-color: #1c5cab; }
.cal-preview-net { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
@media (max-width: 900px) { .cal-cell { min-height: 66px; } .cal-post { font-size: 9.5px; } }

/* ============================================================
   Pulido estético v3 — desplegables, controles y micro-detalles
   ============================================================ */

/* --- Selects : garantizar hueco para el chevron incluso en los pequeños,
       y evitar el "salto" al pasar el ratón dentro de tablas densas --- */
select { padding-right: 28px !important; }
table.data select, .flex select, td select { transform: none !important; }
table.data select:hover { transform: none !important; box-shadow: 0 1px 2px rgba(11,11,11,.06); }

/* --- Checkboxes & radios : color de marca, tamaño cómodo --- */
input[type=checkbox], input[type=radio] {
  accent-color: var(--accent); width: 16px; height: 16px; cursor: pointer;
  vertical-align: -2px;
}
.check { cursor: pointer; }
.check:hover { color: var(--ink); }
label.check.radio-tile {
  border: 1px solid var(--hairline); border-radius: 9px; padding: 8px 10px;
  background: var(--surface); transition: border-color .12s, background .12s;
}
label.check.radio-tile:hover { border-color: var(--accent-soft); background: #f6faff; }

/* --- Date / heure : indicador del picker más discreto y clicable --- */
input[type=date], input[type=datetime-local], input[type=time] { cursor: pointer; }
input[type=date]::-webkit-calendar-picker-indicator,
input[type=datetime-local]::-webkit-calendar-picker-indicator,
input[type=time]::-webkit-calendar-picker-indicator {
  opacity: .5; cursor: pointer; transition: opacity .12s;
}
input[type=date]:hover::-webkit-calendar-picker-indicator,
input[type=datetime-local]:hover::-webkit-calendar-picker-indicator { opacity: .85; }

/* --- Focus visible cohérent (accessibilité clavier) --- */
a:focus-visible, button:focus-visible, .nav-item:focus-visible,
.combo-item:focus-visible, summary:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px;
}

/* --- Scrollbars : elles doivent SE VOIR ---------------------------------
   Elles étaient d'un gris presque blanc sur fond clair, et sans rail. Sur un
   modal qui coupe son contenu, personne ne les remarquait : on croyait avoir
   tout lu. Ce n'est pas un détail d'esthétique — une barre invisible cache la
   moitié d'une liste et l'écran ment par omission.

   Un rail visible, un curseur assez foncé pour se détacher, et pas de
   `thin` : la largeur par défaut est celle que l'œil cherche. */
.mail-list, .combo-list, .table-scroll, .bell-menu, .qr-panel, .modal-box,
.perm-boite {
  scrollbar-color: #a8a69c #eceae4;
}
.mail-list::-webkit-scrollbar, .combo-list::-webkit-scrollbar,
.table-scroll::-webkit-scrollbar, .modal-box::-webkit-scrollbar,
.perm-boite::-webkit-scrollbar { width: 12px; height: 12px; }
.mail-list::-webkit-scrollbar-track, .combo-list::-webkit-scrollbar-track,
.table-scroll::-webkit-scrollbar-track, .modal-box::-webkit-scrollbar-track,
.perm-boite::-webkit-scrollbar-track {
  background: #eceae4; border-radius: 8px;
}
.mail-list::-webkit-scrollbar-thumb, .combo-list::-webkit-scrollbar-thumb,
.table-scroll::-webkit-scrollbar-thumb, .modal-box::-webkit-scrollbar-thumb,
.perm-boite::-webkit-scrollbar-thumb {
  background: #a8a69c; border-radius: 8px; border: 3px solid #eceae4;
  background-clip: content-box;
}
.mail-list::-webkit-scrollbar-thumb:hover, .modal-box::-webkit-scrollbar-thumb:hover,
.perm-boite::-webkit-scrollbar-thumb:hover { background: #7d7b73; background-clip: content-box; }

/* --- KPI : ligera elevación al pasar el ratón --- */
.kpi { transition: box-shadow .18s, transform .18s, border-color .18s; }
.kpi:hover { transform: translateY(-2px); box-shadow: var(--shadow-lift); border-color: #d7d5cc; }
a.kpi:hover { text-decoration: none; }

/* --- Botón primario : sombra de color al pasar el ratón --- */
.btn.primary:hover { box-shadow: 0 4px 12px rgba(42,120,214,.28); }
.btn.good:hover { box-shadow: 0 4px 12px rgba(12,163,12,.24); }

/* --- Tablas : cabecera con sutil separación al hacer scroll --- */
.table-scroll table.data th { box-shadow: 0 1px 0 var(--hairline); }
table.data tr:hover td { background: #f5f8fd; }

/* --- Tags : un pelín más suaves --- */
.tag { transition: border-color .12s, background .12s; }

/* --- Combobox : ítem activo con acento a la izquierda --- */
.combo-item.active, .combo-item:hover { box-shadow: inset 2px 0 0 var(--accent); }

/* --- Modal : cierre con giro sutil --- */
.modal-close, .fab-close { transition: color .12s, transform .12s; }
.modal-close:hover, .fab-close:hover { transform: rotate(90deg); }

/* --- Inputs : placeholder más claro y foco uniforme --- */
input::placeholder, textarea::placeholder { color: #b0aea6; }
textarea { resize: vertical; min-height: 40px; }

/* ============================================================
   Pulido v5 — utilidades, variantes y correcciones transversales
   (auditoría visual de las 34 páginas)
   ============================================================ */

/* Énfasis siempre visible, independientemente de la fuente del sistema */
b, strong { font-weight: 700; }

/* Utilidades de layout y texto */
.nowrap { white-space: nowrap; }
.grow { flex: 1; min-width: 0; }
.clamp-1 { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mt6 { margin-top: 6px; } .mt8 { margin-top: 8px; } .mt10 { margin-top: 10px; }
.mb8 { margin-bottom: 8px; } .mb14 { margin-bottom: 14px; }

/* Enlaces-componente sin cromo de hipervínculo */
a.card, a.card:hover { color: inherit; text-decoration: none; }
a.kpi { color: inherit; text-decoration: none; display: block; }

/* Avatar de persona (morado de marca, antes inline en 4 templates) */
.avatar-person { background: #4a3aa7; }

/* Tarjeta anidada dentro de otra tarjeta: plana, sin sombra ni animación */
.card .card { background: var(--page); box-shadow: none; animation: none; margin-bottom: 10px; }
.card .card:hover { box-shadow: none; }

/* Cabecera de tarjeta con título + tag que nunca se descuelga */
.card-head { display: flex; align-items: flex-start; gap: 8px; flex-wrap: nowrap; }
.card-head h2, .card-head h3 { min-width: 0; margin-bottom: 0; font-size: 13.5px; }
.card-head .tag { flex: none; margin-left: auto; }

/* Variantes de tarjeta */
.card.accent { background: #f4f9ff; border-color: var(--accent-soft); }
.card.accent > h2 { border-bottom: none; padding-bottom: 0; }
.card.accent table.data th { background: transparent; }
.card.critical { border-color: #f2bcbc; }

/* Un td nunca debe perder su display de celda (defensa ante td.flex) */
td.flex, th.flex { display: table-cell; }

/* Badges en columna alineada (listas de alertas) */
.badge.col { min-width: 112px; justify-content: center; }

/* Filas de lista con contenido multilínea: fecha/tag alineados arriba */
.check-item.top { align-items: flex-start; }
.check-item.top .tag, .check-item.top .badge { margin-top: 2px; }

/* Notificaciones no leídas: indicador real, no solo font-weight */
.timeline li.unread .t-ico { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
.timeline li.unread b { font-weight: 700; }

/* Cabeceras de tabla ordenables */
table.data th a { color: inherit; }
table.data th a:hover { text-decoration: underline; }

/* ============================================================
   Portail élève v4 — espace personnel (onboarding/portal)
   ============================================================ */
.portal-hero {
  position: relative; overflow: hidden; border-radius: 16px; padding: 24px 28px;
  background: #1c3a66;
  color: #fff; display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  box-shadow: var(--shadow-lift); margin-bottom: 16px; animation: rise .35s ease both;
}
.portal-hero .avatar {
  width: 56px; height: 56px; font-size: 19px; font-weight: 700;
  background: rgba(255, 255, 255, .14); border: 2px solid rgba(255, 255, 255, .38);
  box-shadow: 0 4px 14px rgba(0, 0, 0, .25);
}
.portal-hero .hello {
  font-size: 11px; color: #a9bbdd; text-transform: uppercase; letter-spacing: .12em;
  margin-bottom: 3px; font-weight: 650;
}
.portal-hero h1 { color: #fff; font-size: 23px; margin: 0; letter-spacing: -0.01em; }
.portal-chips { display: flex; gap: 7px; flex-wrap: wrap; margin-top: 9px; }
.portal-chip {
  display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 600;
  color: #dce6f5; background: rgba(255, 255, 255, .10); border: 1px solid rgba(255, 255, 255, .17);
  border-radius: 99px; padding: 3.5px 11px; white-space: nowrap;
}
.portal-chip svg { opacity: .75; }
.portal-hero .actions { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }
.btn.on-dark { background: rgba(255, 255, 255, .10); border-color: rgba(255, 255, 255, .30); color: #fff; }
.btn.on-dark:hover { background: rgba(255, 255, 255, .22); border-color: rgba(255, 255, 255, .55); box-shadow: none; }

.portal-cols { display: grid; grid-template-columns: 5fr 4fr; gap: 0 14px; align-items: start; }
@media (max-width: 1100px) { .portal-cols { grid-template-columns: 1fr; } }

.formation-item {
  border: 1px solid var(--hairline); border-radius: 12px; background: var(--page);
  padding: 13px 15px;
}
.formation-item + .formation-item { margin-top: 10px; }
.f-head { display: flex; align-items: center; gap: 11px; }
.f-head b { font-size: 13.5px; line-height: 1.25; }
.f-ico {
  width: 36px; height: 36px; border-radius: 10px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent-soft); color: var(--accent-strong);
}
.f-meta { color: var(--muted); font-size: 12px; margin-top: 2px; }
.f-progress { display: flex; align-items: center; gap: 10px; margin-top: 12px; }
.f-progress .meter { flex: 1; height: 8px; }
.f-progress .pct {
  font-size: 12px; font-weight: 650; color: var(--accent-strong);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.f-actions {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 12px; padding-top: 11px; border-top: 1px dashed var(--hairline);
}
.f-actions form.inline { display: inline-flex; align-items: center; gap: 6px; }
.f-actions select { width: auto; min-width: 84px; font-size: 12px; padding: 4px 26px 4px 8px; }

.echeance-strip {
  display: flex; gap: 6px; flex-wrap: wrap; align-items: center;
  margin-top: 9px; padding: 8px 11px; font-size: 12px;
  background: var(--page); border: 1px dashed var(--hairline); border-radius: 9px;
}
.echeance-strip .lbl { color: var(--muted); font-weight: 600; margin-right: 2px; }

.date-tile {
  width: 42px; flex-shrink: 0; text-align: center; padding: 4px 0 5px;
  border: 1px solid var(--hairline); border-radius: 10px; background: var(--surface);
}
.date-tile b { display: block; font-size: 15px; line-height: 1.05; letter-spacing: -0.01em; }
.date-tile small {
  font-size: 9px; text-transform: uppercase; letter-spacing: .07em; color: var(--muted);
}
.session-item {
  display: flex; align-items: center; gap: 11px; padding: 8px 0;
  border-bottom: 1px dashed var(--hairline); font-size: 13px;
}
.session-item:last-child { border-bottom: none; padding-bottom: 2px; }

.empty.sm { padding: 13px 10px; font-size: 12.5px; }

/* ---- Chercheur de rapprochement (Ventes / Échéances) ---- */
.rec-target { margin-bottom: 9px; font-size: 14px; }
#rec-search { width: 100%; margin-bottom: 4px; }
.rec-hint { margin-bottom: 6px; }
.rec-list {
  list-style: none; margin: 0; padding: 2px; max-height: 46vh; overflow-y: auto;
  display: flex; flex-direction: column; gap: 6px;
}
.rec-item {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 10px; border: 1px solid var(--hairline); border-radius: 9px;
  background: var(--page);
}
.rec-item.rec-match { border-color: var(--good-tint-border); background: var(--good-tint); }
.rec-main { min-width: 0; }
.rec-badge {
  display: inline-block; font-size: 11px; font-weight: 650; color: var(--good);
  background: var(--surface); border: 1px solid var(--good-tint-border);
  border-radius: 20px; padding: 1px 7px;
}
.rec-empty { padding: 16px; text-align: center; color: var(--muted); }

/* ============================================================
   Tableau de bord « Ma journée » (Accueil) — dense, structuré, role-aware
   ============================================================ */
.sem-facture-t { color: var(--sem-facture-t); }
.sem-defaut-t  { color: var(--sem-defaut-t); }
.sem-attente-t { color: var(--sem-attente-t); }
.sem-vente-t   { color: var(--sem-vente-t); }
/* Ces deux-là manquaient, et trois chiffres de « Accès à ouvrir » s'écrivaient
   donc en noir : la variable existait (`--sem-acces-t`), la classe utilitaire
   non. Un token défini ne suffit pas — il faut que quelque chose s'en serve. */
.sem-acces-t   { color: var(--sem-acces-t); }
.sem-care-t    { color: var(--sem-care-t); }
.section-lbl {
  font-size: 11px; font-weight: 650; color: var(--muted); text-transform: uppercase;
  letter-spacing: .05em; margin: 2px 0 8px;
}

/* Bandeau de KPIs compact */
.kpi-strip {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(112px, 1fr));
  gap: 8px; margin-bottom: 16px;
}
.kpi-s { background: var(--surface); border: 1px solid var(--hairline); border-radius: 10px; padding: 9px 11px; }
.kpi-s .l { font-size: 11px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kpi-s .v { font-size: 18px; font-weight: 680; letter-spacing: -.01em; margin-top: 2px; font-variant-numeric: tabular-nums; }
.kpi-s .s { font-size: 10.5px; color: var(--muted); }

/* Rail d'actions — compact, coloré par urgence */
.day-rail { display: grid; grid-template-columns: repeat(auto-fill, minmax(156px, 1fr)); gap: 8px; margin-bottom: 18px; }
.day-tile {
  display: grid; grid-template-columns: auto 1fr; gap: 0 9px; align-items: center;
  padding: 8px 11px; background: var(--surface); border: 1px solid var(--hairline);
  border-left-width: 3px; border-radius: 10px; text-decoration: none; color: inherit;
  transition: transform .12s, box-shadow .12s;
}
.day-tile:hover { transform: translateY(-1px); box-shadow: var(--shadow); text-decoration: none; }
.day-tile .day-ico { grid-row: 1 / 3; width: 26px; height: 26px; border-radius: 7px; display: grid; place-items: center; }
.day-tile .day-n { font-size: 17px; font-weight: 700; line-height: 1.05; }
.day-tile .day-lbl { font-size: 11.5px; font-weight: 600; line-height: 1.15; color: var(--ink-2); }
.day-tile.tone-critical { border-left-color: var(--sem-defaut); }
.day-tile.tone-warning  { border-left-color: var(--sem-attente); }
.day-tile.tone-good     { border-left-color: var(--sem-facture); }
.day-tile.tone-neutral  { border-left-color: var(--hairline); }
.day-tile.tone-critical .day-n { color: var(--sem-defaut-t); }
.day-ico.good    { background: var(--sem-facture-bg); color: var(--sem-facture-t); }
.day-ico.neutral { background: var(--page); color: var(--ink-2); }

/* Grille de l'aperçu — 12 colonnes, hauteurs alignées */
.dg { display: grid; grid-template-columns: repeat(12, 1fr); gap: 12px; align-items: stretch; margin-bottom: 12px; }
.dg > .card { margin: 0; display: flex; flex-direction: column; }
.dg .c3 { grid-column: span 3; } .dg .c4 { grid-column: span 4; }
.dg .c5 { grid-column: span 5; } .dg .c6 { grid-column: span 6; }
.dg .c7 { grid-column: span 7; } .dg .c8 { grid-column: span 8; }
@media (max-width: 1000px) {
  .dg .c3, .dg .c4, .dg .c5 { grid-column: span 6; }
  .dg .c6, .dg .c7, .dg .c8 { grid-column: span 12; }
}
@media (max-width: 600px) { .dg > .card { grid-column: span 12; } }
.card-h { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; margin-bottom: 11px; }
.card-h h2 { margin: 0; font-size: 13.5px; }

/* HH-2569 — commissions sur l'encaissé : le mois se choisit dans l'en-tête de
   la carte, là où il est nommé, pas dans une barre de filtres au-dessus. */
.fiche-offre { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  margin: 2px 0 4px; font-size: 15px; font-weight: 600; color: var(--ink); }
.fiche-offre .fiche-prix { font-weight: 700; color: var(--sem-vente-t); }
/* B6 — les produits d'une commande qui en porte plusieurs. */
.lignes-plus { margin-left: 4px; background: var(--sem-vente-bg); color: var(--sem-vente-t);
  border-color: var(--border); cursor: help; }
.fiche-lignes { border-collapse: collapse; margin: 2px 0 6px; font-size: 12.5px; }
.fiche-lignes td { padding: 2px 14px 2px 0; border: 0; }
.fiche-lignes td.num { text-align: right; font-variant-numeric: tabular-nums; font-weight: 600; }

.cm-choix { margin: 0; }
.cm-choix select { font-size: 12px; padding: 3px 6px; }
.cm-total td { border-top: 2px solid var(--border); background: var(--page); }

/* CA par semaine — barres verticales */
.bars-col { display: flex; align-items: flex-end; gap: 8px; height: 122px; margin-top: auto; }
.cbar-v { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 6px; height: 100%; cursor: default; }
.cbar-v .bar { width: 100%; max-width: 30px; min-height: 3px; background: var(--sem-facture); border-radius: 5px 5px 2px 2px; transition: filter .15s; }
.cbar-v .x { font-size: 10px; color: var(--muted); }
.cbar-v:hover .x { color: var(--ink); font-weight: 600; }
.bars-col:has(.cbar-v:hover) .cbar-v:not(:hover) .bar { opacity: .4; }
.cbar-v:hover .bar { filter: brightness(1.08); }

/* Donut de facturation */
.donut {
  width: 112px; height: 112px; border-radius: 50%; margin: 0 auto 12px;
  background: conic-gradient(var(--sem-facture) calc(var(--pct) * 1%), var(--sem-facture-bg) 0);
  display: grid; place-items: center;
}
.donut .donut-c {
  width: 78px; height: 78px; border-radius: 50%; background: var(--surface);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  box-shadow: inset 0 0 0 1px var(--hairline);
}
.donut .donut-c b { font-size: 22px; font-weight: 700; color: var(--sem-facture-t); line-height: 1; }
.donut .donut-c span { font-size: 10.5px; color: var(--muted); margin-top: 2px; }
.legend-row { display: flex; flex-direction: column; gap: 5px; font-size: 12px; }
.legend-row .dot { display: inline-block; width: 9px; height: 9px; border-radius: 3px; margin-right: 7px; vertical-align: middle; }
.dot.sem-facture { background: var(--sem-facture); }
.dot.neutral { background: var(--hairline); }

/* Listes compactes à barres (canal, offres, closers) */
.mlist { display: flex; flex-direction: column; gap: 9px; }
.mrow { display: grid; grid-template-columns: 1fr auto; gap: 2px 8px; font-size: 12px; cursor: default; }
.mrow .nm { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mrow .vl { font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; }
.mrow .br { grid-column: 1 / 3; height: 5px; border-radius: 3px; background: var(--page); overflow: hidden; }
.mrow .br > i { display: block; height: 100%; border-radius: 3px; background: var(--sem-vente); transition: filter .15s; }
.mlist:has(.mrow:hover) .mrow:not(:hover) .br > i { opacity: .4; }
.mrow:hover .br > i { filter: brightness(1.1); }

/* Suivi des paiements — mini-stats empilées */
.suivi { display: flex; flex-direction: column; gap: 9px; }
.sv { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; padding-bottom: 9px; border-bottom: 1px dashed var(--hairline); }
.sv:last-child { border-bottom: 0; padding-bottom: 0; }
.sv .sv-l { font-size: 12px; color: var(--ink-2); }
.sv .sv-v { font-weight: 680; font-variant-numeric: tabular-nums; }
.sv .sv-v small { font-weight: 500; color: var(--muted); font-size: 11px; margin-left: 4px; }

/* Bande de stats des autres modules — cellules compactes */
.mini-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin-bottom: 12px; }
.mini-cell {
  display: grid; grid-template-columns: auto 1fr; gap: 0 11px; align-items: center;
  padding: 10px 13px; background: var(--surface); border: 1px solid var(--hairline);
  border-left-width: 3px; border-radius: 10px; text-decoration: none; color: inherit;
  transition: box-shadow .12s;
}
a.mini-cell:hover { box-shadow: var(--shadow); text-decoration: none; }
.mini-cell .mc-v { grid-row: 1 / 3; font-size: 22px; font-weight: 700; letter-spacing: -.02em; }
.mini-cell .mc-l { font-size: 12px; font-weight: 600; }
.mini-cell .mc-s { font-size: 11px; color: var(--muted); }
.mini-cell.sem-care-card  { border-left-color: var(--sem-care); }  .mini-cell.sem-care-card  .mc-v { color: var(--sem-care-t); }
.mini-cell.sem-acces-card { border-left-color: var(--sem-acces); } .mini-cell.sem-acces-card .mc-v { color: var(--sem-acces-t); }
.mini-cell.sem-peda-card  { border-left-color: var(--sem-peda); }  .mini-cell.sem-peda-card  .mc-v { color: var(--sem-peda-t); }
.mini-cell.sem-ops-card   { border-left-color: var(--sem-ops); }   .mini-cell.sem-ops-card   .mc-v { color: var(--sem-ops-t); }

/* Chip sémantique */
.chip-sem { font-size: 11.5px; font-weight: 650; padding: 2px 10px; border-radius: 20px; white-space: nowrap; }
.chip-sem.sem-facture { background: var(--sem-facture-bg); color: var(--sem-facture-t); }

/* Tooltip enrichi (data-tip-html) */
#viz-tip { max-width: 250px; text-align: left; white-space: normal; }
#viz-tip b { color: #fff; font-weight: 700; }

/* ---- Reconnaissance de l'émetteur d'un virement (P1.C) ---- */
.qui-liste {
  position: absolute; left: 0; right: 0; z-index: 4; margin-top: 2px;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: 9px; box-shadow: var(--shadow-lift); overflow: hidden;
  max-height: 216px; overflow-y: auto;
}
#enc-emetteur { position: relative; }
.qui-item {
  display: block; width: 100%; text-align: left; border: 0; background: none;
  font: inherit; padding: 7px 11px; cursor: pointer; border-bottom: 1px solid var(--hairline);
}
.qui-item:last-child { border-bottom: 0; }
.qui-item:hover, .qui-item:focus-visible { background: var(--sem-vente-bg); outline: none; }
.qui-item b { display: block; font-size: 13px; font-weight: 600; color: var(--ink); }
.qui-item span { display: block; font-size: 11px; color: var(--muted); font-weight: 400; }
.qui-item.sure b::after {
  content: "reconnue"; margin-left: 7px; font-size: 9.5px; font-weight: 700;
  letter-spacing: .04em; color: var(--sem-facture-t); background: var(--sem-facture-bg);
  border: 1px solid #bfe6cf; border-radius: 4px; padding: 0 4px; vertical-align: 1px;
}
.qui-choisi {
  display: flex; align-items: center; gap: 7px; margin-top: 5px;
  background: var(--sem-facture-bg); border: 1px solid #bfe6cf; border-radius: 7px;
  padding: 4px 6px 4px 10px; font-size: 12px; color: var(--sem-facture-t); font-weight: 400;
}
.qui-choisi .qui-nom { flex: 1; min-width: 0; }
.qui-x { border: 0; background: none; cursor: pointer; color: var(--sem-facture-t);
         font-size: 12px; line-height: 1; padding: 3px; }
.qui-x:hover { color: var(--critical); }
.qui-pastille { color: var(--sem-facture); font-size: 9px; vertical-align: 2px; margin-right: 2px; }
.enc-autres { border-top: 1px dashed var(--hairline); margin-top: 8px; padding-top: 7px; }
.enc-autre {
  display: flex; align-items: center; gap: 8px; font-size: 12.5px; padding: 5px 0;
  text-decoration: none; color: var(--ink-2);
}
.enc-autre:hover { color: var(--sem-vente-t); text-decoration: none; }
.enc-autre:hover .tag { border-color: var(--sem-vente); }

/* ---- Page Encaissements : deux onglets, deux gestes ---- */
.enc-onglets { display: flex; align-items: center; gap: 4px; margin-bottom: 16px;
               border-bottom: 1px solid var(--hairline); }
.enc-onglet {
  font-size: 13.5px; font-weight: 600; color: var(--muted); text-decoration: none;
  padding: 7px 14px 9px; border-bottom: 2px solid transparent; margin-bottom: -1px;
  transition: color .12s, border-color .12s;
}
.enc-onglet:hover { color: var(--ink); text-decoration: none; }
.enc-onglet.actif { color: var(--ink); border-bottom-color: var(--sem-facture); }
.enc-onglet .tag { margin-left: 5px; }
.enc-onglet-alerte {
  margin-left: auto; margin-bottom: 4px; font-size: 11.5px; font-weight: 600;
  color: var(--sem-attente-t); background: var(--sem-attente-bg);
  border: 1px solid #f0dcb4; border-radius: 20px; padding: 2px 11px; cursor: default;
}
.enc-totaux { display: flex; gap: 26px; padding: 10px 2px 14px; }
.enc-totaux b { display: block; font-size: 17px; line-height: 1.1;
                font-variant-numeric: tabular-nums; }
.enc-totaux span { display: block; font-size: 11px; color: var(--muted); margin-top: 3px; }
.mb14 { margin-bottom: 14px; }
.f-date { display: inline-flex; align-items: center; gap: 5px; font-size: 12px;
          color: var(--muted); }
.f-date input { width: 140px; }

/* ---- Modal Encaissements : 90 % de l'écran, deux onglets ----
   Taille FIXE et pas « au plus 90 % » : l'historique fait quarante lignes ou
   zéro selon le filtre, et un modal qui change de taille à chaque clic de
   filtre est désagréable. La boîte tient donc sa hauteur, et c'est le contenu
   qui défile — d'où la colonne flex : en-tête et pied fixes, panneau au
   milieu qui prend ce qui reste. */
.modal-box.enc-box {
  width: 90vw; max-width: 90vw; height: 90vh; max-height: 90vh;
  display: flex; flex-direction: column; overflow: hidden;
}
.modal-box.enc-box > .modal-head,
.modal-box.enc-box > .flex { flex: none; }
.modal-box.enc-box > .enc-corps {
  flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden;
}
.enc-a-faire { background: var(--sem-attente-bg); border: 1px solid #f0dcb4;
               border-radius: 11px; padding: 12px 14px; margin-bottom: 14px;
               flex: none; max-height: 34%; display: flex; flex-direction: column; }
.enc-a-faire .enc-queue { overflow-y: auto; min-height: 0; }
.enc-filtres { margin-bottom: 4px; flex: none; }
.enc-totaux { flex: none; }
/* Le tableau prend toute la place restante et défile seul : l'en-tête de
   colonnes reste visible pendant qu'on descend dans le journal. */
.enc-table-wrap { flex: 1; min-height: 0; overflow-y: auto; }
.enc-table-wrap table.data th {
  position: sticky; top: 0; z-index: 1; background: var(--surface);
  box-shadow: 0 1px 0 var(--hairline);
}
.enc-pages { display: flex; align-items: center; gap: 12px; justify-content: center;
             padding: 10px 0 2px; flex: none; }

/* ---- Filtres du modal Encaissements ----
   La barre générique du registre suppose des champs courts : `.f-date` y vaut
   110 px de LARGE, ce qui va pour un `<input>` nu mais écrase le nôtre, qui
   est un `<label>` contenant « du » ET son champ. D'où des dates qui se
   chevauchaient. Ici chaque champ a la largeur de ce qu'il contient. */
.enc-filtres { gap: 7px; margin-bottom: 8px; }
/* Une seule ligne, et qui le reste. `flex-wrap: nowrap` sur le formulaire +
   `min-width: 0` sur la recherche : sans le second, un champ flexible refuse
   de descendre sous la largeur de son texte et pousse tout le reste à la
   ligne — c'est ce qui renvoyait le tri et l'export en dessous. La recherche
   absorbe ce qui reste, les autres champs gardent leur taille. */
.enc-filtres { flex-wrap: nowrap; }
.enc-filtres .filter-form {
  display: flex; flex-wrap: nowrap; align-items: center; gap: 7px;
  flex: 1 1 auto; min-width: 0;
}
.enc-filtres .f-search { width: auto; flex: 1 1 auto; min-width: 0; }
.enc-filtres .f-date {
  width: auto; display: inline-flex; align-items: center; gap: 5px;
  font-size: 12px; color: var(--muted); white-space: nowrap; flex: none;
}
.enc-filtres .f-date input { width: 132px; }
.enc-filtres select { max-width: none; width: 124px; flex: none; }
.enc-filtres .btn { flex: none; }
/* La rangée des raccourcis, elle, a le droit de passer à la ligne : ce sont
   huit boutons de largeur fixe, et sur un portable ils ne tiennent pas. */
.enc-filtres.enc-chips { flex-wrap: wrap; }
/* Les raccourcis à compteur se lisent comme un ensemble, séparés du reste. */
.enc-filtres .btn.xs .tag { margin-left: 5px; }

/* ---- Un modal par-dessus un modal ----
   Saisir une réception s'ouvre au-dessus de l'historique des encaissements.
   Le voile du second assombrit le premier, ce qui est exactement le repère
   attendu : on est monté d'un cran, on redescendra. */
.modal-overlay.modal-imbrique { z-index: 120; background: rgba(11, 11, 11, .34); }
/* Un modal ouvert depuis un autre passe devant lui, quel que soit l'ordre du
   DOM — la profondeur suit le geste, pas le gabarit. */
.modal-overlay.modal-par-dessus { z-index: 140; }

/* Un bouton qui en cache deux : ils vivent au même endroit (Brevo), et les
   mettre à plat dans l'en-tête faisait quatre boutons sans hiérarchie. Le
   menu s'ouvre au survol ET au clavier (`focus-within`) ; la zone du dessus
   reste survolable pour que la souris puisse descendre. */
/* La croix d'un cours repris : au bout de sa ligne, au survol seulement. */
.lb-fiche > summary .ct-x { margin-left: auto; display: inline-flex; }
.lb-fiche > summary .ct-x .sp-x { opacity: 0; font-size: 12px; padding: 2px 5px; }
.lb-fiche:hover > summary .ct-x .sp-x, .ct-x .sp-x:focus-visible { opacity: .6; }
.ct-x .sp-x:hover { opacity: 1; }
.btn-menu { position: relative; display: inline-flex; }
.btn-menu-fleche { width: 5px; height: 5px; margin-left: 2px; border: solid currentColor;
  border-width: 0 1.5px 1.5px 0; transform: rotate(45deg) translate(-1px, -1px);
  opacity: .5; transition: transform .15s; }
.btn-menu:hover .btn-menu-fleche { transform: rotate(45deg) translate(0, 0); opacity: .8; }
.btn-menu-liste { position: absolute; top: 100%; right: 0; z-index: 30; min-width: 268px;
  margin-top: 6px; padding: 5px; border-radius: 12px; background: var(--surface);
  border: 1px solid var(--hairline); box-shadow: var(--shadow-fort, 0 10px 30px rgba(11,11,11,.13));
  opacity: 0; visibility: hidden; transform: translateY(-4px);
  transition: opacity .12s, transform .12s, visibility .12s; }
.btn-menu-liste::before { content: ""; position: absolute; left: 0; right: 0; top: -8px; height: 8px; }
/* Le panneau est sorti dans <body> par le script : c'est LUI qui porte l'état
   ouvert, plus son parent — resté dans la tira d'onglets, il y était rogné. */
/* Sorti dans <body>, il n'a plus de parent pour le rétrécir : un bloc y prend
   toute la largeur de la page. On lui redonne sa taille de contenu. */
.btn-menu-liste.btn-menu-flottant { position: fixed; top: 0; left: 0; margin: 0; z-index: 90;
  width: max-content; max-width: min(340px, 92vw); }
.btn-menu-liste.ouvert, .btn-menu:focus-within .btn-menu-liste {
  opacity: 1; visibility: visible; transform: translateY(0); }
.btn-menu.ouvert .btn-menu-fleche { transform: rotate(-135deg) translate(-2px, -2px); opacity: .8; }
.btn-menu-liste > button { display: grid; grid-template-columns: 1fr auto; align-items: center;
  gap: 2px 10px; width: 100%; text-align: left; font: inherit; cursor: pointer;
  padding: 8px 10px; border: 0; border-radius: 9px; background: none; color: var(--ink); }
.btn-menu-liste > button:hover, .btn-menu-liste > button:focus-visible {
  background: var(--page); outline: none; }
.btn-menu-liste b { font-size: 13px; font-weight: 600; }
.btn-menu-liste i { grid-column: 1; font-size: 11.5px; font-style: normal; color: var(--muted); }
.btn-menu-liste .badge { grid-row: 1 / span 2; grid-column: 2; }
.modal-box.saisie-box { width: 620px; max-width: 94vw; }

/* ---- Modal avoir : le flux P1.F ------------------------------------------
   Trois pas à gauche, ce qui va se passer à droite, en permanence. La couleur
   n'est pas là pour décorer : vert = imputé (rien ne bouge), ambre = dette
   envers la cliente, rouge = argent qui sort. Ce sont les mêmes trois sens
   que partout ailleurs dans la plateforme. */
.modal-box.avoir-box { width: min(1060px, 95vw); max-height: 92vh; }

.av-head {
  display: flex; align-items: flex-start; gap: 12px;
  margin: -20px -22px 15px; padding: 12px 22px 11px;
  background: var(--sem-ops-bg); border-bottom: 1px solid #dfe3e9;
  border-radius: 16px 16px 0 0;
}
.av-eyebrow { display: block; font-size: 10.5px; letter-spacing: .1em;
              text-transform: uppercase; color: var(--muted); margin-bottom: 2px; }
.av-head > .grow > b { font-size: 15.5px; color: var(--ink); line-height: 1.2; }
.av-meta { font-size: 12.5px; color: var(--ink-2); margin-top: 2px; }
.av-sep { color: var(--hairline-strong, #c9cdd4); margin: 0 5px; }
.av-fact { font-variant-numeric: tabular-nums; }
.av-definitif {
  align-self: center; flex: none; font-size: 10.5px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; padding: 4px 10px;
  border-radius: 999px; background: var(--sem-attente-bg);
  border: 1px solid #efdcb4; color: var(--sem-attente-t); cursor: help;
}

.avoir-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 350px);
              gap: 24px; align-items: start; }
@media (max-width: 900px) { .avoir-grid { grid-template-columns: minmax(0, 1fr); } }
.av-pas > section + section { margin-top: 14px; padding-top: 13px;
                              border-top: 1px solid var(--hairline); }
.av-pas .enc-step { margin-bottom: 8px; }
.av-pas .form-row { margin-bottom: 8px; }
.av-pas .fld { display: block; font-size: 12px; color: var(--ink-2); font-weight: 600; }
.av-pas .fld > input { margin-top: 4px; font-weight: 400; }
/* Une annotation, pas un encadré : elle commente le champ au-dessus. */
.av-note { font-size: 12px; color: var(--muted); margin: -3px 0 9px; line-height: 1.45; }

/* Le barème — aujourd'hui vide, et il le dit au lieu d'inventer un chiffre. */
.av-bareme { display: flex; gap: 10px; align-items: flex-start;
             background: var(--sem-vente-bg); border: 1px solid #cbdff8;
             border-radius: 10px; padding: 8px 12px; margin-bottom: 9px; }
.av-bareme-ico { flex: none; width: 22px; height: 22px; border-radius: 50%;
                 display: grid; place-items: center; font-size: 12px; font-weight: 700;
                 background: var(--sem-vente); color: #fff; }

.av-bareme b { display: block; font-size: 13px; color: var(--sem-vente-t); }

.av-bareme span:not(.av-bareme-ico) { display: block; font-size: 12px;
                                      color: var(--muted); margin-top: 2px;
                                      line-height: 1.5; }
.av-tout { flex: none; align-self: flex-end; margin-bottom: 2px; white-space: nowrap; }

/* Ce que chaque voie de sortie peut porter — le plafond, puis ce que le
   montant saisi y ferait passer. Les trois options ne sont jamais à égalité,
   et l'écran ne doit pas les présenter comme si elles l'étaient. */
.seg-radio .sr-cap, .seg-radio .sr-live {
  display: block; font-style: normal; font-size: 11px; margin-top: 3px;
  font-variant-numeric: tabular-nums; }
.seg-radio .sr-live { color: var(--sem-facture-t); font-weight: 600; }
/* Le report n'est pas un choix neutre : il laisse une dette ouverte. Il reste
   possible — on émet l'avoir aujourd'hui et on rembourse quand on a le RIB —
   mais il ne doit pas avoir l'air d'une option comme les autres. */
.seg-radio.report .sr-live { color: var(--sem-attente-t); }
.seg-radio.report input:checked ~ span { color: var(--sem-attente-t); }
.seg-radio.report input:checked ~ span b::after {
  content: "à solder"; margin-left: 7px; padding: 1px 7px; border-radius: 999px;
  font-size: 10px; font-weight: 600; letter-spacing: .02em;
  background: var(--sem-attente-bg); color: var(--sem-attente-t); }

/* L'imputation : un FAIT, pas une option. Elle s'annonce au-dessus du choix,
   avec le ton d'une information et non d'une case à cocher. */
.av-impute { padding: 9px 12px; margin-bottom: 9px; border-radius: 9px;
  font-size: 12.5px; line-height: 1.45; color: var(--sem-facture-t);
  background: var(--good-tint); border: 1px solid var(--good-tint-border); }

.avoir-soldes { display: grid; gap: 5px; margin-bottom: 10px; }
.seg-radio { display: flex; align-items: flex-start; gap: 9px; cursor: pointer;
             border: 1px solid var(--hairline); border-radius: 10px; padding: 7px 11px;
             background: var(--surface); transition: border-color .12s, background .12s; }
.seg-radio:hover { border-color: var(--sem-vente); }
.seg-radio input { width: auto; margin-top: 2px; flex: none; }
.seg-radio b { display: block; font-size: 13px; font-weight: 600; color: var(--ink); }
.seg-radio small { display: block; font-size: 11.5px; color: var(--muted); margin-top: 0;
                   line-height: 1.4; }
.seg-radio:has(input:checked) { border-color: var(--sem-vente);
                                background: var(--sem-vente-bg); }

/* Collé au bas du modal : la sortie ne doit jamais se chercher en
   scrollant, et sur un portable c'est elle qui passait sous le pli. */
.av-pied { position: sticky; bottom: -20px; z-index: 2;
           display: flex; align-items: center; justify-content: flex-end; gap: 10px;
           margin: 14px -22px -20px; padding: 11px 22px; background: var(--page);
           border-top: 1px solid var(--hairline); border-radius: 0 0 16px 16px; }
.av-pied-note { margin-right: auto; font-size: 12px; color: var(--muted); }

/* ---- L'aperçu : la colonne qu'on lit avant de cliquer ---- */
.avoir-apercu { background: var(--page); border: 1px solid var(--hairline);
                border-radius: 12px; padding: 14px 16px; position: sticky; top: 0; }
.ap-l { font-size: 10.5px; letter-spacing: .09em; text-transform: uppercase;
        color: var(--muted); }
.ap-somme { text-align: center; padding-bottom: 12px; }
.ap-somme b { display: block; font-size: 32px; line-height: 1.1; color: var(--ink);
              font-variant-numeric: tabular-nums; margin-top: 4px; }

/* La barre : imputé contre dette, d'un coup d'œil. Deux natures différentes
   que deux chiffres alignés ne distinguent pas. */
.ap-barre { display: flex; gap: 2px; height: 9px; border-radius: 999px;
            overflow: hidden; background: var(--hairline); }
.ap-part { display: block; min-width: 3px; }
.ap-part.impute { background: var(--sem-facture); }
.ap-part.dette  { background: var(--sem-attente); }
.ap-legende { display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: 9px;
              font-size: 12px; color: var(--ink-2); }
.ap-legende i.pt { display: inline-block; width: 8px; height: 8px; border-radius: 50%;
                   margin-right: 6px; vertical-align: 0; }
.ap-legende i.pt.impute { background: var(--sem-facture); }
.ap-legende i.pt.dette  { background: var(--sem-attente); }

.ap-table { width: 100%; border-collapse: collapse; margin-top: 14px; font-size: 12.5px; }
.ap-table td { padding: 6px 0; border-bottom: 1px solid var(--hairline);
               color: var(--ink-2); }
.ap-table tr:last-child td { border-bottom: 0; }
.ap-table td.num { text-align: right; font-variant-numeric: tabular-nums;
                   color: var(--ink); font-weight: 600; }

/* Ce que fera le prestataire — ou ce qu'il faudra faire à sa place. */
.ap-canal { margin-top: 14px; padding: 11px 13px; border-radius: 10px;
            background: var(--sem-facture-bg); border: 1px solid #bfe4cd; }
.ap-canal.manuel { background: var(--sem-attente-bg); border-color: #efdcb4; }
.ap-canal-head { display: flex; align-items: center; gap: 8px; }
.ap-chip { margin-left: auto; font-size: 11.5px; font-weight: 650; padding: 2px 9px;
           border-radius: 999px; background: var(--surface);
           border: 1px solid #bfe4cd; color: var(--sem-facture-t); white-space: nowrap; }
.ap-canal.manuel .ap-chip { border-color: #e6cf9f; color: var(--sem-attente-t); }
.ap-canal p { margin: 7px 0 0; font-size: 12px; line-height: 1.55; color: var(--ink-2); }

.ap-suites { list-style: none; margin: 14px 0 0; padding: 0; }
.ap-suites li { position: relative; padding-left: 16px; font-size: 12.5px;
                color: var(--ink-2); margin-bottom: 7px; line-height: 1.5; }
.ap-suites li:last-child { margin-bottom: 0; }
.ap-suites li::before { content: ""; position: absolute; left: 1px; top: 7px;
                        width: 6px; height: 6px; border-radius: 50%;
                        background: var(--sem-attente); }

.ap-stop { display: flex; gap: 11px; align-items: flex-start; }
.ap-stop-ico { flex: none; width: 26px; height: 26px; border-radius: 50%;
               display: grid; place-items: center; font-size: 14px; font-weight: 700;
               background: var(--sem-defaut); color: #fff; }
.ap-stop b { font-size: 13.5px; color: var(--sem-defaut-t); }
.ap-stop p { margin: 5px 0 0; font-size: 12.5px; line-height: 1.55; color: var(--ink-2); }

/* ── La carte des avoirs sur la fiche vente ──────────────────────────────
   Elle était repliée sous « cas particuliers » : il fallait déplier pour
   apprendre qu'une vente avait été annulée. Un avoir change ce que la
   cliente doit — ça se lit sans cliquer. */
.avoir-ligne { padding: 11px 0; border-bottom: 1px solid var(--hairline); }
.avoir-ligne:last-child { border-bottom: 0; padding-bottom: 2px; }
.avoir-ligne > .flex { align-items: baseline; gap: 8px; }
.avoir-ligne > .flex > b { font-size: 15px; color: var(--sem-defaut-t);
                           font-variant-numeric: tabular-nums; }
.avoir-solde { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 6px; }
.avoir-solde:empty { display: none; }
.pastille { font-size: 11.5px; line-height: 1.5; padding: 2px 9px; border-radius: 999px;
            border: 1px solid transparent; white-space: nowrap; }
.pastille.bon     { background: var(--sem-facture-bg); border-color: #bfe4cd;
                    color: var(--sem-facture-t); }
.pastille.attente { background: var(--sem-attente-bg); border-color: #f0dcb4;
                    color: var(--sem-attente-t); }
.pastille.sortie  { background: var(--sem-defaut-bg); border-color: #f2ccc4;
                    color: var(--sem-defaut-t); }
.avoir-ligne .small a { color: var(--sem-vente-t); }

/* ============================ Workflows ============================ */
/* Diagrama del parcours d'achat: cajas como el PDF, simulable, con correo de
   ejemplo. Colores = leyenda del PDF (woo=morado, sellsy=azul, brevo=verde,
   tutor=naranja, bsport=rojo, campo=amarillo, decisión=gris). */
.wf-controls { padding: 12px 14px; }
.wf-ctl-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.wf-field { display: flex; flex-direction: column; gap: 3px; font-size: 11px;
            font-weight: 600; color: #6a7681; }
.wf-mode { margin-left: auto; font-size: 12px; color: var(--sem-attente-t);
           background: var(--sem-attente-bg); padding: 4px 11px; border-radius: 999px; }
.wf-email-chip { border: 1px dashed var(--sem-vente); background: var(--sem-vente-bg);
  color: var(--sem-vente-t); border-radius: 999px; padding: 5px 13px; font-size: 12px;
  font-weight: 600; cursor: pointer; transition: filter .15s; }
.wf-email-chip.set { border-style: solid; }
.wf-email-chip:hover { filter: brightness(.97); }
.wf-log-send { margin-left: 7px; font-size: 11.5px; }
.wf-log-send.ok { color: var(--sem-facture-t); font-weight: 600; }
.wf-log-send.err { color: var(--sem-attente-t); }
.wf-log-send.muted { color: #9aa6b2; }

.wf-wrap { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 14px;
           align-items: start; }
@media (max-width: 920px) { .wf-wrap { grid-template-columns: 1fr; } }
/* Le schéma défile dans SA carte, pas dans la page : à 45 cases la page
   faisait presque deux mètres, et le panneau d'explication — pourtant collant —
   finissait hors champ. */
.wf-canvas { padding: 16px; overflow: auto; max-height: calc(100vh - 200px);
  min-height: 420px; overscroll-behavior: contain; }
.wf-canvas svg { display: block; }

.wf-zoom { display: inline-flex; align-items: center; gap: 2px;
  border: 1px solid var(--hairline); border-radius: 9px; background: var(--surface);
  padding: 2px; }
.wf-zoom button { width: 26px; height: 26px; padding: 0; border: 0; cursor: pointer;
  background: none; border-radius: 7px; font: 600 15px var(--font-ui, system-ui);
  color: var(--ink-2); }
.wf-zoom button:hover { background: var(--accent-soft); color: var(--accent-strong); }
.wf-zoom #wf-zoom-niveau { min-width: 44px; text-align: center; font-size: 11.5px;
  font-weight: 600; color: var(--muted); font-variant-numeric: tabular-nums; }
.wf-zoom .wf-zoom-fit { width: auto; padding: 0 9px; font-size: 11.5px;
  font-weight: 600; }
#wf-svg { width: 100%; height: auto; display: block; margin: 0 auto; }

/* Badge « en développement » del sidebar (secciones aún sin terminar). Sobre
   fondo oscuro del menú; se oculta en modo rail (columna estrecha). */
.nav-wip { flex: none; margin-left: 6px; padding: 1px 6px; border-radius: 999px;
           font-size: 9px; font-weight: 700; letter-spacing: .04em;
           text-transform: uppercase; line-height: 1.5; white-space: nowrap;
           color: #f0c987; background: rgba(198, 125, 16, .16);
           border: 1px solid rgba(198, 125, 16, .42); }
html.nav-rail .nav-wip { display: none; }

/* Nodos de correo: invitan a clicar (tooltip + bocadillo) */
.wf-has-mail { cursor: pointer; }
.wf-mail-badge circle { transition: r .15s ease; }
.wf-has-mail:hover .wf-mail-badge circle { r: 11.5; }

.wf-tip { position: fixed; z-index: 90; transform: translate(-50%, -100%);
  background: #22303a; color: #fff; font-size: 12px; font-weight: 600;
  padding: 6px 10px; border-radius: 8px; white-space: nowrap; pointer-events: none;
  box-shadow: 0 8px 22px rgba(20, 30, 45, .22); opacity: 0; transition: opacity .12s; }
.wf-tip.show { opacity: 1; }
.wf-tip::after { content: ""; position: absolute; left: 50%; top: 100%;
  transform: translateX(-50%); border: 6px solid transparent; border-top-color: #22303a; }

.wf-pop { position: fixed; z-index: 91; width: 270px; background: var(--surface, #fff);
  border: 1px solid var(--hairline, #e5e9ee); border-radius: 14px;
  box-shadow: 0 18px 48px rgba(20, 30, 45, .24); padding: 15px 15px 14px; display: none; }
.wf-pop.open { display: block; animation: wf-pop-in .16s ease; }
@keyframes wf-pop-in { from { opacity: 0; transform: translateY(6px) scale(.98); } to { opacity: 1; transform: none; } }
.wf-pop-arrow { position: absolute; width: 12px; height: 12px; background: var(--surface, #fff);
  border-left: 1px solid var(--hairline, #e5e9ee); border-bottom: 1px solid var(--hairline, #e5e9ee);
  transform: rotate(45deg); }
.wf-pop h5 { margin: 0 14px 3px 0; font-size: 13.5px; }
.wf-pop > p { margin: 0 0 11px; font-size: 12px; color: #6a7681; line-height: 1.45; }
.wf-pop-row { display: flex; gap: 6px; }
.wf-pop input { flex: 1; min-width: 0; border: 1px solid var(--hairline, #dfe4ea);
  border-radius: 8px; padding: 7px 9px; font-size: 13px; }
.wf-pop input:focus { outline: none; border-color: var(--sem-vente); box-shadow: 0 0 0 3px var(--sem-vente-bg); }
.wf-pop-close { position: absolute; top: 8px; right: 9px; border: 0; background: none;
  cursor: pointer; color: #9aa6b2; font-size: 15px; line-height: 1; padding: 2px; }
.wf-pop-close:hover { color: #22303a; }
.wf-pop-status { margin: 9px 0 0; font-size: 12px; min-height: 15px; line-height: 1.4; }
.wf-pop-status.ok { color: var(--sem-facture-t); }
.wf-pop-status.err { color: var(--sem-defaut-t); }
.wf-pop-continue { margin-top: 11px; width: 100%; border: 1px solid var(--hairline, #dfe4ea);
  background: var(--page, #f4f5f7); border-radius: 8px; padding: 7px; font-size: 12.5px;
  font-weight: 600; color: #22303a; cursor: pointer; }
.wf-pop-continue:hover { background: #fff; border-color: var(--sem-vente); color: var(--sem-vente-t); }

/* Animación de envío de correo durante la simulación */
.wf-fly { font-size: 17px; fill: #1f9d5b; transform-box: fill-box; transform-origin: center;
  animation: wf-fly-k 1.05s ease-out forwards; pointer-events: none; }
@keyframes wf-fly-k {
  0% { opacity: 0; transform: translate(0, 0) scale(.5); }
  20% { opacity: 1; }
  100% { opacity: 0; transform: translate(34px, -42px) scale(1.25); } }
.wf-ripple { fill: none; stroke: #1f9d5b; stroke-width: 2; transform-box: fill-box;
  transform-origin: center; animation: wf-ripple-k 1s ease-out forwards; pointer-events: none; }
@keyframes wf-ripple-k { from { opacity: .5; } to { opacity: 0; transform: scale(3.4); } }
.wf-node.wf-sending .wf-box { animation: wf-send-glow 1.1s ease; }
@keyframes wf-send-glow { 0% {} 45% { filter: drop-shadow(0 0 9px #1f9d5b); stroke-width: 3.4; } 100% {} }

.cat-woo      { --wc: #8e44ad; --wbg: #f4ecfa; }
.cat-sellsy   { --wc: #2a78d6; --wbg: #e9f1fc; }
.cat-brevo    { --wc: #1f9d5b; --wbg: #e8f6ee; }
.cat-tutor    { --wc: #e67e22; --wbg: #fdefe0; }
.cat-bsport   { --wc: #c0392b; --wbg: #fbece9; }
.cat-campo    { --wc: #b7950b; --wbg: #f9f4dc; }
.cat-decision { --wc: #5a6472; --wbg: #eef0f3; }

.wf-node { cursor: pointer; transform-box: fill-box; transform-origin: center; }
.wf-node:focus { outline: none; }
.wf-box { fill: var(--wbg); stroke: var(--wc); stroke-width: 1.6;
          transition: stroke-width .15s, filter .15s; }
.wf-decision .wf-box { stroke-dasharray: 5 3; }
.wf-label { font: 600 10.5px var(--font-ui, system-ui); fill: #22303a;
            pointer-events: none; }
.wf-node:hover .wf-box, .wf-node:focus .wf-box { stroke-width: 2.6;
            filter: drop-shadow(0 2px 6px rgba(0, 0, 0, .12)); }
.wf-mail-badge circle { fill: var(--wc); }
.wf-mail-ico { font-size: 11px; fill: #fff; }

.wf-edge { stroke: #c2ccd6; stroke-width: 2; transition: stroke .2s; }
.wf-edge.is-done { stroke: var(--sem-vente); stroke-width: 2.6; }
.wf-edge-label { font: 600 10.5px var(--font-ui, system-ui); fill: #6a7681;
  /* Les étiquettes croisent des traits : sans halo elles se lisent à moitié.
     `paint-order` fait passer le contour blanc SOUS le glyphe. */
  stroke: #fff; stroke-width: 3px; paint-order: stroke; }
/* La branche « opportunité perdue » est en pointillé dans l'original. */
.wf-edge-pointille { stroke-dasharray: 6 4; }
/* Et les liens que NOUS avons reconstruits : le PDF est un vectoriel, on en
   tire les cases mais pas les flèches. Les montrer autrement empêche de les
   prendre pour une spécification. */
.wf-edge-incertain { stroke-dasharray: 2 4; stroke: #b9a25f; }

/* La couverture, à l'encre la plus faible possible. Un liseré au pied des
   45 cases faisait 45 traits de couleur pour une information qui n'en concerne
   que 19 — le schéma n'était plus lisible. Deux signes suffisent : les cases
   que personne ne couvre chez nous sont estompées, les autres portent un point
   dans le coin. Le détail se lit au survol. */
.wf-etat-ombre   { fill: var(--sem-facture); --etat: var(--sem-facture); }
.wf-etat-partiel { fill: var(--sem-attente); --etat: var(--sem-attente); }
.wf-etat-manuel  { fill: var(--sem-care);    --etat: var(--sem-care); }
.wf-etat-hors    { --etat: #b9c2cc; }
.wf-pastille { stroke: #fff; stroke-width: 1.2; }
/* Les cases NE sont PAS estompées selon la couverture, et c'est une correction :
   la couleur appartient au schéma d'origine — violet WooCommerce, bleu Sellsy,
   vert Brevo… — c'est sa légende, et le diagramme n'existe que pour la
   reproduire. En pâlissant les 26 cases que nous ne couvrons pas, une
   information de second plan effaçait celle de premier. La couverture se dit
   donc uniquement par le point dans le coin, et par le décompte en légende. */

.wf-couv { display: flex; flex-wrap: wrap; gap: 4px 12px; margin: 8px 0 12px;
  padding-top: 9px; border-top: 1px solid var(--hairline); }
.wf-couv .wf-leg i { background: var(--etat); border-color: var(--etat); }
.wf-panel-etat { display: inline-block; margin: 0 0 8px; padding: 2px 9px;
  border-radius: 999px; font-size: 11.5px; font-weight: 600; color: #fff;
  background: var(--etat, #cdd4dc); }
.wf-panel-etat.wf-etat-hors { color: #4c5561; }

.wf-running .wf-node:not(.is-active):not(.is-done) { opacity: .38; transition: opacity .3s; }
.wf-node.is-active .wf-box { stroke-width: 3.2; filter: drop-shadow(0 0 5px var(--wc)); }
.wf-node.is-done .wf-box { fill: #fff; }

.wf-side { display: flex; flex-direction: column; gap: 14px; position: sticky; top: 14px; }
.wf-panel { padding: 15px; }
.wf-legend { display: flex; flex-wrap: wrap; gap: 6px 12px; margin-bottom: 12px;
             padding-bottom: 12px; border-bottom: 1px solid rgba(0, 0, 0, .08); }
.wf-leg { display: inline-flex; align-items: center; gap: 5px; font-size: 11px;
          font-weight: 600; color: #4c5561; }
.wf-leg i { width: 10px; height: 10px; border-radius: 3px; background: var(--wc);
            display: inline-block; }
#wf-panel-title { margin: 0 0 6px; font-size: 15px; }
#wf-panel-text { margin: 0; font-size: 13px; line-height: 1.55; color: #4c5561; }
#wf-panel-email { margin-top: 13px; padding-top: 13px; border-top: 1px solid rgba(0, 0, 0, .08); }

.wf-log { padding: 15px; }
.wf-log h4 { margin: 0 0 9px; font-size: 11px; text-transform: uppercase;
             letter-spacing: .04em; color: #6a7681; }
.wf-log ol { list-style: none; margin: 0; padding: 0; display: flex;
             flex-direction: column; gap: 7px; }
.wf-log li { display: flex; align-items: center; gap: 8px; font-size: 12.5px;
             color: #22303a; animation: wf-fade .3s ease; }
.wf-log li i { width: 8px; height: 8px; border-radius: 50%; background: var(--wc); flex: none; }
.wf-log li span { flex: 1; line-height: 1.35; }
.wf-log-mail { border: 1px solid var(--wc); color: var(--wc); background: transparent;
               border-radius: 999px; font-size: 11px; padding: 2px 9px; cursor: pointer;
               white-space: nowrap; }
.wf-log-mail:hover { background: var(--wc); color: #fff; }
@keyframes wf-fade { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

/* L'offre ouvre la fiche de la vente — le seul chemin depuis le registre,
   donc il doit se voir. Le nº a porté ce lien un temps, en gris : une
   référence grise ne se lit pas comme un lien, et personne ne le trouvait. */
.lien-offre { color: var(--accent); font-weight: 550; }
tr:hover .lien-offre { text-decoration: underline; }
/* Le nº, lui, reste une donnée : on le cherche une fois par mois, pour le
   rapprocher de Sellsy ou de la boutique. */
td.col-date { font-variant-numeric: tabular-nums; }
/* Le geste qui reste à faire sur un avoir : virement à envoyer, code promo à
   créer. Ambre — ce n'est pas une erreur, c'est une tâche. */
.avoir-reste { margin-top: 8px; padding: 9px 11px; border-radius: 9px;
               background: var(--sem-attente-bg); border: 1px solid #efdcb4; }
.avoir-reste .small b { color: var(--sem-attente-t); }
.avoir-reste form { margin-top: 8px; gap: 6px; }
.avoir-reste input { font-size: 12px; padding: 5px 8px; min-width: 0; }
/* Montant, « tout », et la justification de l'écart : une seule ligne. Le
   montant a une largeur fixe — un champ de 6 chiffres qui s'étire sur la
   moitié de la colonne se lit mal, et la place sert mieux au texte libre. */
.av-montant-row > .fld.money { flex: none; width: 170px; min-width: 170px; }
.av-montant-row > .fld.grow { min-width: 200px; }

/* ══ Événements : registre, formulaire et tableau de bord ══════════════════
   Les couleurs de remplissage ne sont pas trois nuances d'une même chose :
   « il reste de la place » se regarde une fois par semaine, « presque
   complet » se surveille, et « complet » se ferme. */
.j-ouvert  { --jauge: var(--sem-attente); }
.j-moyen   { --jauge: var(--sem-vente); }
.j-presque { --jauge: var(--sem-facture); }
.j-complet { --jauge: var(--sem-ops); }

/* ---- Le registre ---- */
.ev-table td { vertical-align: middle; }
.ev-table tr.ev-passe td { opacity: .58; }
.ev-quand { display: block; font-size: 11px; color: var(--muted);
            font-variant-numeric: tabular-nums; }
.ev-quand.proche { color: var(--sem-attente-t); font-weight: 650; }
.ev-quand.today  { color: var(--sem-defaut-t); font-weight: 700; }
.ev-sous { display: block; margin-top: 2px; font-size: 11px; color: var(--muted); }
.ev-woo { color: var(--sem-care-t); }
.ev-adr { font-size: 11px; margin-top: 1px; }
.ev-alerte { color: var(--sem-attente-t); cursor: help; margin-left: 3px; }
.ev-actions { text-align: right; }
.ev-actions .btn + .btn, .ev-actions .btn + a { margin-left: 5px; }

.ev-jauge { height: 7px; border-radius: 999px; background: var(--hairline);
            overflow: hidden; }
.ev-jauge-in { height: 100%; background: var(--jauge, var(--sem-vente));
               border-radius: 999px; transition: width .3s ease; }
.ev-chiffres { display: flex; align-items: baseline; gap: 6px; margin-top: 5px;
               font-size: 12px; }
.ev-chiffres b { font-size: 14px; font-variant-numeric: tabular-nums; }
.fq { opacity: .55; font-variant-numeric: tabular-nums; margin-left: 3px; }
.fdot.green { background: var(--sem-facture); }

/* ---- Le formulaire ---- */
.modal-box.ev-box { width: min(880px, 95vw); max-height: 92vh; }
.ev-head { display: flex; align-items: flex-start; gap: 12px;
           margin: -20px -22px 16px; padding: 12px 22px 11px;
           background: var(--sem-ops-bg); border-bottom: 1px solid #dfe3e9;
           border-radius: 16px 16px 0 0; }
.ev-eyebrow { display: block; font-size: 10.5px; letter-spacing: .1em;
              text-transform: uppercase; color: var(--muted); margin-bottom: 2px; }
.ev-head > .grow > b { font-size: 15.5px; color: var(--ink); line-height: 1.2; }
.ev-meta { font-size: 12.5px; color: var(--ink-2); margin-top: 2px; }
.ev-box section + section { margin-top: 14px; padding-top: 13px;
                            border-top: 1px solid var(--hairline); }
.ev-box .enc-step { margin-bottom: 8px; }
.ev-box .form-row { margin-bottom: 8px; }
.ev-box .fld { display: block; font-size: 12px; color: var(--ink-2); font-weight: 600; }
.ev-box .fld > input, .ev-box .fld > select { margin-top: 4px; font-weight: 400; }
/* Marquer un champ facultatif évite de le remplir « au cas où ». */
.opt { font-weight: 400; font-size: 10.5px; color: var(--muted);
       text-transform: none; letter-spacing: 0; }
.ev-repli > summary { font-size: 13px; font-weight: 600; }
.ev-actif { margin-right: auto; font-size: 12.5px; }

/* ---- Tableau de bord ---- */
.ev-alertes { flex-wrap: wrap; }
.al-jour { font-variant-numeric: tabular-nums; font-weight: 700; margin: 0 8px;
           opacity: .8; }

.rmp { display: flex; flex-direction: column; gap: 2px; }
.rmp-row { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 2fr) 64px;
           align-items: center; gap: 12px; padding: 7px 6px; border-radius: 8px;
           color: inherit; }
.rmp-row:hover { background: var(--page); text-decoration: none; }
.rmp-nom { font-size: 12.5px; color: var(--ink); min-width: 0; }
.rmp-nom i { display: block; font-style: normal; font-size: 11px; color: var(--muted);
             font-variant-numeric: tabular-nums; margin-top: 1px; }
.rmp-bar { display: block; height: 9px; border-radius: 999px;
           background: var(--hairline); overflow: hidden; }
.rmp-bar i { display: block; height: 100%; border-radius: 999px;
             background: var(--jauge, var(--sem-vente)); }
.rmp-n { text-align: right; font-size: 12px; color: var(--muted);
         font-variant-numeric: tabular-nums; }
.rmp-n b { font-size: 14px; color: var(--ink); }

.reg-list { display: flex; flex-direction: column; }
.reg-row { display: flex; align-items: center; gap: 10px; padding: 7px 0;
           border-bottom: 1px solid var(--hairline); font-size: 12.5px; }
.reg-row:last-child { border-bottom: 0; }
.reg-n { flex: none; min-width: 26px; height: 22px; padding: 0 7px; border-radius: 999px;
         display: grid; place-items: center; font-size: 12px; font-weight: 700;
         background: var(--sem-acces-bg); color: var(--sem-acces-t); }
/* Une allergie n'est pas une préférence : elle se distingue au premier regard. */
.reg-n.alg { background: var(--sem-defaut-bg); color: var(--sem-defaut-t); }
.reg-l { flex: 1; min-width: 0; color: var(--ink); }
.reg-k { font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase;
         color: var(--muted); }

.pay-bars { display: flex; flex-direction: column; gap: 9px; }
.pay-row { display: grid; grid-template-columns: 76px 1fr 28px; align-items: center;
           gap: 9px; font-size: 12px; }
.pay-l { color: var(--ink-2); }
.pay-b { display: block; height: 8px; border-radius: 999px; background: var(--hairline);
         overflow: hidden; }
.pay-b i { display: block; height: 100%; border-radius: 999px; min-width: 2px; }
.p-ok  { background: var(--sem-facture); }
.p-att { background: var(--sem-attente); }
.p-ko  { background: var(--sem-defaut); }
.p-inc { background: var(--sem-ops); }
.pay-row b { text-align: right; font-variant-numeric: tabular-nums; }

/* ---- La carte de France, dessinée par nous ----------------------------
   Pas de tuiles, pas d'iframe, pas de clé : les contours officiels sont figés
   dans `adv/carte_france.py`. Rien ne part chez un tiers à l'ouverture de la
   page, et la carte prend la palette du reste. */
/* La carte Google prend exactement la place de la vectorielle — même hauteur,
   mêmes coins — pour que le tableau ne bouge pas selon qu'elle se charge ou
   non. Elle arrive `hidden` et ne se montre qu'une fois vraiment prête. */
.carte-google {
  height: 300px; min-height: 300px; flex: 1; border-radius: 10px; overflow: hidden;
  border: 1px solid var(--hairline); margin: 4px 0 2px;
}
/* Google dessine sa propre bulle : on ne peut habiller que le contenu. */
.cg-bulle { font: 13px/1.4 var(--font-ui); color: var(--ink); padding: 2px 2px 0; }
.cg-bulle a { color: var(--accent-strong); text-decoration: none; }
.cg-bulle a:hover { text-decoration: underline; }
.cg-bulle div { color: var(--ink-2); margin-top: 2px; }
.cg-bulle .cg-n { color: var(--muted); font-size: 12px; }

.carte-fr { position: relative; padding: 4px 0 2px; }
.carte-fr svg { display: block; width: 100%; height: auto; max-height: 300px;
                /* La molette zoome au lieu de faire défiler la page, et le
                   glissement déplace la carte au lieu de sélectionner. */
                touch-action: none; -webkit-user-select: none; user-select: none;
                overflow: hidden; }
.carte-fr.zoome svg { cursor: grab; }
.carte-fr.zoome svg:active { cursor: grabbing; }

/* Les commandes : discrètes, et visibles au survol de la carte. Le bouton de
   retour n'apparaît qu'une fois qu'on s'est éloigné — proposer « revoir toute
   la France » quand on voit déjà toute la France ne veut rien dire. */
.cf-ctl { position: absolute; right: 4px; top: 4px; display: flex;
          flex-direction: column; gap: 3px; opacity: 0; transition: opacity .15s; }
.carte-fr:hover .cf-ctl, .carte-fr:focus-within .cf-ctl, .carte-fr.zoome .cf-ctl {
  opacity: 1; }
.cf-ctl button { width: 24px; height: 24px; padding: 0; display: grid;
                 place-items: center; font: inherit; font-size: 14px; line-height: 1;
                 color: var(--ink-2); background: var(--surface); cursor: pointer;
                 border: 1px solid var(--hairline); border-radius: 7px;
                 box-shadow: var(--shadow); }
.cf-ctl button:hover { border-color: var(--sem-vente); color: var(--sem-vente-t); }
.cf-ctl button[hidden] { display: none; }
/* Le découpage par régions donne l'échelle sans écrire un seul nom de ville. */
.cf-fond path { fill: var(--page); stroke: var(--hairline); stroke-width: 1;
                stroke-linejoin: round; }
.cf-points a { cursor: pointer; }
/* Le halo sépare deux villes proches sans grossir le point lui-même. */
.cf-halo { fill: var(--jauge, var(--sem-vente)); opacity: .16; }
/* `stroke-width` en pixels d'écran grâce à `vector-effect` sur l'élément :
   sans ça le liseré grossit avec le zoom et mange le point. */
.cf-pt { fill: var(--jauge, var(--sem-vente)); stroke: var(--surface);
         stroke-width: 1.5; }
.cf-points a:hover .cf-pt { stroke-width: .8; }
.cf-points a:hover .cf-halo { opacity: .3; }
.cf-vide { position: absolute; inset: 0; display: grid; place-items: center;
           text-align: center; font-size: 12px; color: var(--muted);
           padding: 0 24px; }

/* La liste de suggestions d'adresse réutilise le combo du reste du site ;
   seul l'état du champ est propre à elle. */
[data-adresse] { position: relative; }
[data-adresse-etat].ok { color: var(--sem-facture-t); }
/* L'état de l'adresse est une phrase SOUS le champ, pas la suite de la ligne :
   en `inline` il se collait au bloc suivant, et ses marges verticales étaient
   ignorées. */
[data-adresse-etat] { display: block; margin-top: 5px; }
/* Les boutons « + Ajouter … » ferment leur bloc. Sans marge basse, le champ
   qui suit remonte à leur hauteur. */
[data-ligne-ajouter] { display: inline-block; margin-bottom: 10px; }

/* La jauge des cupos. Verte tant qu'on tient dans la session, rouge dès qu'on
   promet plus de chambres qu'il n'y a de places. */
.cupo-jauge { margin-top: 4px; padding: 10px 12px; border-radius: 10px;
  background: var(--page); border: 1px solid var(--hairline); }
.cj-tete { display: flex; justify-content: space-between; align-items: baseline;
  font-size: 11.5px; color: var(--ink-2); font-weight: 600; }
.cj-tete b { font-size: 13px; font-variant-numeric: tabular-nums;
  color: var(--sem-facture-t); }
.cj-barre { height: 7px; margin: 6px 0 5px; border-radius: 999px;
  background: #e6e6df; overflow: hidden; }
.cj-barre span { display: block; height: 100%; border-radius: 999px;
  background: var(--sem-facture); transition: width .18s ease, background .18s ease; }
.cj-note { font-size: 11.5px; color: var(--muted); line-height: 1.4; }

/* Exactement plein : l'état qu'on vise, il mérite de se distinguer du « il
   reste de la place », qui est seulement acceptable. */
.cupo-jauge.juste .cj-barre span { background: var(--sem-facture); }
.cupo-jauge.juste .cj-note { color: var(--sem-facture-t); }

.cupo-jauge.trop { background: var(--sem-defaut-bg); border-color: #f2ccc4; }
.cupo-jauge.trop .cj-tete b { color: var(--sem-defaut-t); }
.cupo-jauge.trop .cj-barre span { background: var(--sem-defaut); }
.cupo-jauge.trop .cj-note { color: var(--sem-defaut-t); font-weight: 600; }

/* ---- Tarifs d'un événement : une ligne par chose qu'on peut acheter ----
   C'était un champ libre — « 1 290 € (hébergement en sus) ». Le prix et la
   formule sont sur la même ligne parce que l'un dépend de l'autre. */
.tarifs { display: flex; flex-direction: column; gap: 5px; margin-bottom: 9px; }
.tarif-tete, .tarif-ligne {
  display: grid; grid-template-columns: minmax(0, 1fr) 108px 168px 74px 26px;
  gap: 6px; align-items: center;
}
.tarif-tete { font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase;
              color: var(--muted); padding: 0 2px; }
.tarif-ligne input, .tarif-ligne select { font-size: 12.5px; padding: 5px 8px; }
.tarif-ligne .fld-in i { right: 8px; font-size: 11.5px; }
.tarif-ligne input[type=number] { font-variant-numeric: tabular-nums; }
.tarif-x { width: 24px; height: 24px; padding: 0; display: grid; place-items: center;
           font: inherit; font-size: 12px; color: var(--muted); cursor: pointer;
           background: none; border: 1px solid transparent; border-radius: 7px; }
.tarif-x:hover { color: var(--sem-defaut-t); background: var(--sem-defaut-bg);
                 border-color: #f2ccc4; }
@media (max-width: 720px) {
  .tarif-tete { display: none; }
  .tarif-ligne { grid-template-columns: 1fr 1fr; }
}

/* Le bandeau de la fiche : les tarifs se lisent, les cupos aussi. */
.ev-bandeau { display: flex; flex-wrap: wrap; gap: 6px; margin: -8px 0 14px; }
.ev-tarif { font-size: 12px; padding: 3px 10px; border-radius: 999px;
            background: var(--surface); border: 1px solid var(--hairline);
            color: var(--ink-2); }
.ev-tarif b { color: var(--ink); font-variant-numeric: tabular-nums; }
.ev-tarif i { font-style: normal; margin-left: 6px; padding: 1px 6px;
              border-radius: 999px; font-size: 11px;
              background: var(--sem-facture-bg); color: var(--sem-facture-t); }
/* Une formule pleine se voit : c'est la chambre qu'on ne peut plus vendre. */
.ev-tarif i.plein { background: var(--sem-defaut-bg); color: var(--sem-defaut-t); }

.av-note.attention { color: var(--sem-attente-t); }
/* Le rappel « les trois sont un avoir ». Il n'alerte pas — il situe : un
   filet à gauche et le fond du panneau, pour qu'on le lise avant de choisir
   sans qu'il crie plus fort que le choix lui-même. */
.av-rappel { border-left: 2px solid var(--sem-facture-b, var(--line));
             padding: 6px 0 6px 9px; margin: 0 0 10px; }
.av-rappel b { color: var(--txt); font-weight: 600; }

/* La remise annoncée sous le formulaire de vente. Discrète : c'est une
   conséquence de ce qu'on vient de saisir, pas une alerte. */
.sale-remise { margin: -4px 0 10px; font-size: 12px; color: var(--sem-facture-t);
               font-variant-numeric: tabular-nums; }

/* L'équipe d'un événement. Une grille de cases : on en coche deux ou trois
   dans une quinzaine, et il faut voir d'un coup d'œil qui est déjà dessus —
   une liste verticale d'une quinzaine de lignes ferait défiler le modal. */
.eq-bloc { border: 1px solid var(--hairline); border-radius: 8px;
           padding: 10px 12px 12px; margin: 0 0 14px; }
.eq-bloc legend { font-size: 11px; font-weight: 600; color: var(--muted);
                  letter-spacing: .04em; padding: 0 5px; }
.eq-liste { display: grid; grid-template-columns: repeat(auto-fill, minmax(215px, 1fr));
            gap: 5px 12px; }
.eq-membre { display: flex; align-items: center; gap: 7px; font-size: 12.5px;
             padding: 3px 0; cursor: pointer; }
.eq-membre input { flex: none; }
.eq-nom { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis;
          white-space: nowrap; }
.eq-nom i { color: var(--sem-attente-t); font-style: normal; font-size: 11px; }
.eq-role { flex: none; max-width: 132px; font-size: 11.5px; padding: 1px 4px; }
/* Le référent est là pour qu'on le VOIE dans l'équipe, mais il se gère au
   champ du dessus : sa case est cochée et morte, pas absente. */
.eq-ref { opacity: .62; cursor: default; }
.eq-role-fixe { flex: none; font-size: 11px; color: var(--muted);
                font-style: italic; }
/* Sur la fiche : une ligne par personne, le rôle en gris à côté du nom. */
.eq-fiche { display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap; }
.eq-fiche + .eq-fiche { margin-top: 3px; }

/* L'écart de l'échéancier. Il s'affiche pendant la saisie, avec le geste qui
   le referme à côté : la règle vient de la comptabilité et ne se négocie pas,
   mais rester coincé devant, si. */
.ech-ecart { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
             margin: 8px 0 4px; padding: 7px 10px; border-radius: 7px;
             font-size: 12px; background: var(--sem-attente-bg);
             border: 1px solid var(--sem-attente-b, #efd9ad);
             color: var(--sem-attente-t); }
.ech-ecart span { flex: 1; min-width: 200px; font-variant-numeric: tabular-nums; }
.av-note a { color: var(--sem-vente-t); white-space: nowrap; }

/* ---- Le modal des animateurs ----
   Une liste, pas une page : gérer trois fiches ne justifie pas une
   destination, et depuis le formulaire d'un événement on veut corriger une
   adresse sans perdre ce qu'on saisissait. */
.modal-box.anim-box { width: min(920px, 95vw); max-height: 90vh; }
.modal-box.prod-box { width: min(680px, 95vw); max-height: 92vh; }
.prod-form .fld { display: block; font-size: 12px; color: var(--ink-2); font-weight: 600; }
.prod-form .fld > input, .prod-form .fld > select { margin-top: 4px; font-weight: 400; }
.prod-form > .fld + .fld, .prod-form > .form-row { margin-top: 11px; }
.prod-form .repli { margin-top: 14px; }

/* ---- Les façons de payer d'une offre (HH-2528) ----
   Un tableau, parce que ce sont des lignes comparables : on lit une colonne
   du haut en bas (« combien coûte chaque plan ») avant de lire une ligne.
   Sous chaque ligne, ce qui se CALCULE — jamais saisi — et la date de fin de
   remise, qui n'apparaît que s'il y a une remise. */
.prod-form .plans, .oa-nouvelle .plans {
  margin: 13px 0 4px; padding: 10px 12px 11px; border: 1px solid var(--hairline);
  border-radius: 10px; background: var(--page);
}
.prod-form .plans > legend, .oa-nouvelle .plans > legend {
  padding: 0 6px; font-size: 11.5px; font-weight: 700; letter-spacing: .03em;
  text-transform: uppercase; color: var(--ink-2);
}
/* La même grille pour l'en-tête et pour chaque ligne : deux grilles
   séparées se désalignent au premier ajustement de largeur. */
.plans-tete, .plan-ligne {
  display: grid; align-items: center; gap: 8px;
  /* 46px et non 20 : la colonne porte maintenant son en-tête « Défaut », et
     à 20px le mot débordait sur « Échéances ». */
  grid-template-columns: 46px minmax(96px, 1.1fr) minmax(90px, 1fr) minmax(90px, 1fr) 24px;
}
.plans-tete {
  font-size: 11px; font-weight: 600; color: var(--muted); padding: 0 0 4px;
}
.plan-ligne + .plan-ligne { margin-top: 7px; }
.plan-ligne > select, .plan-ligne .fld-in > input {
  width: 100%; margin: 0; font-weight: 400;
}
.plan-ligne .fld-in > input { text-align: right; padding-right: 22px;
                              font-variant-numeric: tabular-nums; }
.plan-ligne .fld-in i { right: 7px; font-size: 11.5px; }
.plan-def { display: flex; align-items: center; justify-content: center; margin: 0; }
.plan-def > input { margin: 0; cursor: pointer; }
.plan-x {
  border: 0; background: none; cursor: pointer; padding: 2px; line-height: 1;
  color: var(--muted); font-size: 13px; border-radius: 6px;
}
.plan-x:hover { color: var(--critical); background: var(--surface); }
/* La ligne d'en dessous s'aligne sous la colonne des montants, pas sous le
   bord : c'est le chiffre qu'elle commente. */
.plan-sous {
  grid-column: 3 / -1; display: flex; flex-wrap: wrap; gap: 10px;
  align-items: center; font-size: 11.5px; color: var(--muted);
}
.plan-sous:empty { display: none; }
.plan-mensuel { font-variant-numeric: tabular-nums; }
.plan-jusquau { display: flex; align-items: center; gap: 5px; font-size: 11.5px; }
.plan-jusquau > input { margin: 0; padding: 3px 6px; font-size: 11.5px; }
.plans-pied {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 10px; padding-top: 9px; border-top: 1px dashed var(--hairline);
}
.plans-tete > span:first-child { text-align: center; font-size: 10.5px; }

/* ---- Le choix de la façon de payer, dans le modal de vente ----
   Des pastilles et non une liste déroulante : il y en a deux ou trois, on les
   compare d'un coup d'œil, et le montant mensuel doit se lire SANS ouvrir
   quoi que ce soit — c'est lui qu'on annonce à la cliente au téléphone. */
.sale-plans { margin-top: 10px; margin-bottom: 12px; }
.sale-plans-t {
  display: block; font-size: 11.5px; font-weight: 600; color: var(--ink-2);
  margin-bottom: 5px;
}
.sale-plans-choix { display: flex; flex-wrap: wrap; gap: 7px; }
.sale-plan {
  display: flex; align-items: baseline; gap: 7px; cursor: pointer;
  padding: 7px 11px; border: 1px solid var(--hairline); border-radius: 9px;
  background: var(--surface); font-size: 12px; line-height: 1.25;
}
.sale-plan > input { margin: 0; }
.sale-plan > b { font-weight: 650; color: var(--ink); }
.sale-plan > span { color: var(--ink-2); font-variant-numeric: tabular-nums; }
.sale-plan-plein {
  font-style: normal; color: var(--muted); text-decoration: line-through;
  font-variant-numeric: tabular-nums;
}
.sale-plan:hover { border-color: var(--accent-soft); }
.sale-plan:has(> input:checked) {
  border-color: var(--accent); background: var(--sem-vente-bg, #e9f1fc);
}
.sale-plan:focus-within { outline: 2px solid var(--accent-soft); outline-offset: 1px; }

/* Les autres façons de payer, sous le prix, dans le catalogue. */
.prod-plans {
  display: block; margin-top: 2px; font-size: 11px; color: var(--muted);
  font-weight: 400; font-variant-numeric: tabular-nums;
}
.prod-plans > span + span::before { content: " · "; }

/* ---- Le nom, corrigé sur place dans le registre (HH-2569) ----
   Le crayon ne sort qu'au survol de la LIGNE : sur trois cents lignes, trois
   cents crayons visibles feraient une colonne de bruit devant chaque nom. Il
   reste atteignable au clavier — `:focus-within` le rend visible aussi. */
.nom { display: inline; margin: 0; }
.nom-lu { display: inline-flex; align-items: baseline; gap: 4px; }
.nom-crayon {
  border: 0; background: none; padding: 0 2px; cursor: pointer; font: inherit;
  font-size: 11px; line-height: 1; color: var(--muted); opacity: 0;
  transition: opacity .12s;
}
tr:hover .nom-crayon, .nom:focus-within .nom-crayon { opacity: 1; }
.nom-crayon:hover { color: var(--ink-2); }
.nom-saisie { display: flex; gap: 4px; align-items: center; }
.nom-saisie > input { width: 88px; margin: 0; padding: 3px 6px; font-size: 11.5px; }
/* Sur la fiche, le nom EST le titre : la saisie prend la place du <h1> et
   doit peser autant, sinon l'en-tête saute de deux crans à l'ouverture.
   Deux classes + l'élément (0,2,1) pour passer devant `.nom-saisie > input`
   (0,1,1) : à égalité de classes c'est l'ordre qui trancherait, et ce bloc
   suivra l'autre de peu — on ne parie pas là-dessus.

   `.nom-lu` porte `display:inline-flex`, qui écraserait l'attribut `hidden`
   du navigateur ; c'est `[hidden] { display:none !important }` (tout en haut
   de ce fichier) qui le rattrape. Ne pas retirer cette règle-là. */
.nom-lu { margin: 0; }
.nom-saisie-h1 { margin: 2px 0 4px; }
.nom-saisie.nom-saisie-h1 > input { width: 150px; padding: 5px 8px; font-size: 14px; }

/* La vente que le système propose de garder dans une paire de doublons. */
.db-reco {
  font-size: 9.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--sem-facture-t); cursor: help;
}

/* ---- L'adresse, corrigée sur place dans le registre ---- */
.adr { margin-top: 2px; }
.adr-ouvrir {
  border: 0; background: none; padding: 0; cursor: text; text-align: left;
  font: inherit; font-size: 11.5px; color: var(--muted); line-height: 1.3;
  border-bottom: 1px dashed transparent;
}
.adr-ouvrir:hover { color: var(--ink-2); border-bottom-color: var(--hairline); }
/* Manquante, elle garde l'alerte : c'est d'abord un signal, et seulement
   ensuite un champ. */
.adr-ouvrir.flag-warn { cursor: pointer; color: var(--serious); font-weight: 600; }
.adr-ouvrir.flag-warn:hover { color: var(--serious); border-bottom-color: var(--serious); }
.adr-saisie { display: flex; gap: 5px; align-items: center; margin-top: 2px; }
.adr-saisie > input {
  flex: 1; min-width: 140px; margin: 0; padding: 3px 6px; font-size: 11.5px;
}

/* La paire vue par un closer : deux cartes à LIRE, pas à choisir. Sans le
   bouton radio, la carte garderait son retrait — et un blanc à gauche se
   lirait comme une case qu'on a oublié de cocher. */
.db-carte.db-lecture { cursor: default; padding-left: 12px; }
.db-carte.db-lecture:hover { border-color: var(--hairline); }
/* Le badge du registre : un bouton qui ouvre la paire, habillé comme le lien
   qu'il remplace. */

.statut-doublon-voir {
  border: 0; background: none; padding: 0; font: inherit; cursor: pointer;
  color: inherit; text-decoration: underline;
}
/* La paire qu'on vient d'ouvrir : signalée une fois, puis elle redevient une
   paire comme les autres. Un surlignage permanent deviendrait du décor. */
.db-visee { animation: db-visee 1.6s ease-out; }
@keyframes db-visee {
  0%, 40% { box-shadow: 0 0 0 2px var(--accent); }
  100% { box-shadow: 0 0 0 2px transparent; }
}
@media (prefers-reduced-motion: reduce) { .db-visee { animation: none; } }

/* Sous 560 px le tableau se replie en deux lignes plutôt que de comprimer
   les montants jusqu'à l'illisible. */
@media (max-width: 560px) {
  .plans-tete { display: none; }
  .plan-ligne { grid-template-columns: 46px 1fr 24px; }
  .plan-ligne > .fld-in { grid-column: 2 / 3; }
  .plan-sous { grid-column: 2 / -1; }
}

/* Le catalogue : la colonne qui compte est « ce qu'elle déclenche ». Une offre
   n'est pas un prix, c'est ce qu'elle ouvre — et personne ne relie
   spontanément « type = e-learning » à « la vente ouvrira un accès ». */
.prod-liste { table-layout: fixed; width: 100%; }
/* Cinq colonnes depuis que « Ventes » est partie : le catalogue répond à
   « que vend-on ? », pas à « combien s'en est vendu » — le registre a un écran
   entier pour ça. La place récupérée va au nom de l'offre, qui déborde encore
   sur « 9. Transmission Onde & mouvements avec hébergement ». */
.prod-liste th:nth-child(1), .prod-liste td:nth-child(1) { width: 40%; }
.prod-liste th:nth-child(2), .prod-liste td:nth-child(2) { width: 26%; }
.prod-liste th:nth-child(5), .prod-liste td:nth-child(5) { width: 17%; }
/* La légende n'a plus que les rattachements : vide sur la plupart des lignes,
   elle ne doit pas laisser un blanc sous le nom. */
.prod-meta:empty { display: none; }
.prod-liste td { vertical-align: top; }
.prod-nom { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.prod-nom b { font-size: 13px; }

/* La cellule d'une offre : le nom, puis UNE ligne calme.

   Elle portait une pastille ambre pleine « Origine à préciser », au même
   poids visuel que le nom de l'offre et répétée sur 31 des 40 lignes : le
   modal virait à l'ambre, et l'œil ne trouvait plus les titres. Posée en fin
   de phrase, elle tombait en plus tantôt sur la même ligne, tantôt en
   dessous, selon la longueur du titre — trois alignements différents sur un
   même écran.

   Ici l'origine se lit à la COULEUR : un liseré à gauche de la ligne et un
   point en tête de la légende, toujours à la même place. Ce qui manque garde
   l'ambre, parce que c'est la seule chose du tableau qui appelle une action. */
table.data td.prod-offre { box-shadow: inset 3px 0 0 var(--hairline); padding-left: 13px; }
.prod-offre.o-boutique { box-shadow: inset 3px 0 0 var(--orig-boutique); }
.prod-offre.o-parcours { box-shadow: inset 3px 0 0 var(--orig-parcours); }
.prod-offre.o-manuel   { box-shadow: inset 3px 0 0 var(--orig-manuel); }
.prod-offre.o-vide     { box-shadow: inset 3px 0 0 var(--sem-attente); }
/* Les onglets du catalogue sont des FAMILLES : même teinte que dans le modal
   fournisseur, pour qu'une ligne d'offre se reconnaisse d'un écran à l'autre. */
.prod-offre.o-onde { box-shadow: inset 3px 0 0 var(--fam-onde); }
.prod-offre.o-mouvement { box-shadow: inset 3px 0 0 var(--fam-mouvement); }
.prod-offre.o-chant { box-shadow: inset 3px 0 0 var(--fam-chant); }
.prod-offre.o-ata { box-shadow: inset 3px 0 0 var(--fam-ata); }
.prod-offre.o-voix { box-shadow: inset 3px 0 0 var(--fam-voix); }
.prod-offre.o-estudio { box-shadow: inset 3px 0 0 var(--fam-estudio); }
.prod-offre.o-logistique { box-shadow: inset 3px 0 0 var(--fam-logistique); }

/* Les onglets du catalogue portent la couleur de leur provenance : le liseré
   sous l'onglet actif et celui des lignes en dessous sont le même trait. Une
   seule couleur à l'écran à la fois — on sait dans quel catalogue on est sans
   relire l'onglet. */
/* Le trait de l'onglet actif mange celui de la barre : sans le -1 px, les
   deux se superposent et l'onglet actif paraît doublement souligné. */
.prod-tabs { margin: 0 0 10px; border-bottom: 1px solid var(--hairline); }
.prod-tabs .modal-tab { margin-bottom: -1px; }
.prod-tabs .modal-tab.t-boutique.actif { border-bottom-color: var(--orig-boutique); }
.prod-tabs .modal-tab.t-parcours.actif { border-bottom-color: var(--orig-parcours); }
.prod-tabs .modal-tab.t-manuel.actif   { border-bottom-color: var(--orig-manuel); }
.prod-tabs .modal-tab.t-vide.actif     { border-bottom-color: var(--sem-attente); }
/* Le compteur de « à préciser » est le seul qui appelle une action. */
.prod-tabs .modal-tab.t-vide .tag { background: var(--sem-attente-bg);
  border-color: #f0dcb4; color: var(--sem-attente-t); font-weight: 600; }

/* Ranger sans ouvrir la fiche : un menu dans la ligne même de l'offre.

   Il porte l'ambre du « en attente » et la forme d'une pastille, parce qu'il
   occupe la place où l'origine se lira une fois posée : c'est le trou, montré
   comme tel. Une fois rempli, il disparaît — la ligne rejoint son onglet.

   Le rendu est celui de `[data-search]`, le menu déroulant de la maison :
   surface flottante, chevron, ligne active. La liste système n'obéit à aucune
   feuille de style — elle arrivait bleue, au milieu d'un tableau ambre. */
.prod-inline { display: inline-block; margin: 0; }
.prod-inline .combo { width: 148px; }

/* Le repli sans JS garde exactement la même allure : c'est le même champ. */
.prod-inline select.prod-origine,
.combo-input.prod-origine {
  font: inherit; font-size: 11px; font-weight: 600; letter-spacing: -.1px;
  padding: 3px 22px 3px 10px; border-radius: 999px;
  border: 1px solid #ecd6ac; background-color: var(--sem-attente-bg);
  color: var(--sem-attente-t); cursor: pointer;
}
.prod-inline select.prod-origine { padding-right: 8px; max-width: 148px; }
.combo-input.prod-origine::placeholder { color: var(--sem-attente-t); opacity: .75; }

/* Chevron ambre, pas gris : sur ce fond, le gris de série paraît éteint. */
.sel-search .combo-input.prod-origine {
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%238a5a0e' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
  background-position: right 8px center;
}
.sel-search .combo-input.prod-origine:hover { border-color: var(--sem-attente); }
/* Ouvert, le halo reste ambre : le bleu d'accent le ferait changer de sujet. */
.sel-search.open .combo-input.prod-origine {
  border-color: var(--sem-attente); box-shadow: 0 0 0 3px #fbf1e0;
  background-color: var(--surface);
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 5l4-4 4 4' fill='none' stroke='%238a5a0e' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
}
/* La liste s'ouvre sur trois lignes : elle n'a pas à être aussi étroite que
   le champ, les libellés portent l'adresse de la boutique. */
.prod-inline .combo-list { min-width: 232px; }
.prod-inline + span::before { content: none; }   /* pas de « · » après le menu */
.ev-actions .btn + .btn { margin-left: 5px; }

/* Une seule légende, dont les séparateurs se posent tout seuls : un « · »
   écrit à la main dangle dès qu'un champ est vide. */
.prod-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 0 6px;
  margin-top: 3px; font-size: 11px; color: var(--muted); line-height: 1.6; }
.prod-meta > span + span::before { content: "·"; margin-right: 6px;
  color: var(--hairline); }
.prod-meta .prod-id { font-variant-numeric: tabular-nums; }

/* L'origine : un point de couleur et un mot. Pas une pastille — elle pesait
   autant que le titre qu'elle accompagnait. */
.prod-orig { display: inline-flex; align-items: center; gap: 5px;
  font-weight: 600; letter-spacing: -.1px; }
.prod-orig::before { content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: currentColor; flex: none; }
.o-boutique .prod-orig { color: var(--orig-boutique-t); }
.o-parcours .prod-orig { color: var(--orig-parcours-t); }
.o-manuel   .prod-orig { color: var(--orig-manuel-t); }
/* À préciser : creux, parce que c'est un trou, pas une valeur. */
.o-vide .prod-orig { color: var(--sem-attente-t); }
.o-vide .prod-orig::before { background: transparent;
  box-shadow: inset 0 0 0 1.5px currentColor; }

/* « À chaque vente » : ce que l'offre déclenche, en pastilles, et la carte
   eStudio sur la même ligne de lecture. Mêmes pictogrammes qu'au catalogue. */
.prod-vente { margin-top: 12px; }
.prod-declenche { display: flex; flex-wrap: wrap; gap: 6px; margin: 2px 0 12px; }
.prod-pill {
  display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600;
  padding: 5px 11px; border-radius: 99px;
  background: var(--sem-acces-bg); color: var(--sem-acces-t);
}
.prod-pill svg { flex: none; }
.prod-pill.carte { background: var(--sem-attente-bg); color: var(--sem-attente-t); }
.prod-pill.vide { background: var(--page); color: var(--muted); border: 1px dashed var(--hairline); font-weight: 500; }
.prod-pill[hidden] { display: none; }
.prod-carte {
  display: flex; align-items: center; gap: 12px; padding-top: 10px;
  border-top: 1px dashed var(--hairline); font-size: 13px; font-weight: 600; color: var(--ink-2);
}
.prod-carte span { flex: none; }
.prod-carte select { flex: 1; min-width: 0; }
/* La carte B-Sport : le menu, et le nom d'une nouvelle carte à côté (HH-2740). */
.prod-carte .carte-bsport, .carte-bsport { display: flex; gap: 8px; flex: 1; min-width: 0; }
.carte-bsport select, .carte-bsport input { flex: 1; min-width: 0; }
.carte-bsport input { font-weight: 400; }
.carte-bsport input[hidden] { display: none; }
.oa-nouvelle .carte-bsport { width: 100%; }
.anim-box .ev-head { margin-bottom: 14px; align-items: center; }
.anim-box .ev-head .btn { flex: none; }
.anim-rattach { margin: 12px 0; }

/* La liste des animateurs. Quatre colonnes qui répondent à trois questions —
   qui est-ce, comment le joindre, quand travaille-t-il — au lieu d'une colonne
   par champ. À sept colonnes le tableau débordait de sa boîte pour trois
   lignes. */
.anim-liste { table-layout: fixed; width: 100%; }
.anim-liste th:nth-child(1), .anim-liste td:nth-child(1) { width: 32%; }
.anim-liste th:nth-child(2), .anim-liste td:nth-child(2) { width: 30%; }
.anim-liste th:nth-child(3), .anim-liste td:nth-child(3) { width: 28%; }
.anim-liste td { vertical-align: top; }

.an-qui { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.an-qui b { font-size: 13px; }

/* Le nom d'une session est long et n'a pas à casser la ligne : on le coupe,
   et l'infobulle rend l'entier. */
.an-prochain { display: block; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }

/* L'adresse peut être longue : elle se coupe plutôt que d'élargir la colonne. */
.anim-liste .inline-mail { display: block; max-width: 100%; }
.anim-liste .im-voir { max-width: 100%; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }

.anim-liste .ev-actions { text-align: right; }
.anim-liste .ev-actions .btn { margin-left: 4px; }

@media (max-width: 700px) {
  .anim-liste, .anim-liste tr, .anim-liste td, .anim-liste th { display: block; width: auto; }
  .anim-liste tr { padding: 8px 0; border-bottom: 1px solid var(--hairline); }
  .anim-liste th { display: none; }
  .anim-liste .ev-actions { text-align: left; margin-top: 6px; }
  .anim-liste .ev-actions .btn { margin: 0 4px 0 0; }
}

/* ---- Fiche d'un événement ---------------------------------------------
   Quatre questions dans l'ordre où on se les pose : le remplissage, ce qu'il
   faut préparer, qui vient, et si l'argent est rentré. */
.ed-tete { display: grid; grid-template-columns: minmax(0, 1.6fr) repeat(3, minmax(0, 1fr));
           gap: 10px; margin-bottom: 12px; }
@media (max-width: 860px) { .ed-tete { grid-template-columns: 1fr 1fr; } }
.ed-jauge-bloc, .ed-chiffre {
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--radius); padding: 11px 14px;
}
.ed-jauge-bloc { display: flex; flex-direction: column; justify-content: center; gap: 8px; }
.ed-jauge-haut { display: flex; align-items: baseline; gap: 6px; font-size: 12.5px;
                 color: var(--muted); flex-wrap: wrap; }
.ed-jauge-haut b { font-size: 22px; color: var(--ink); line-height: 1;
                   font-variant-numeric: tabular-nums; }
.ed-jauge-haut .pastille { margin-left: auto; }
.ed-chiffre { display: flex; flex-direction: column; justify-content: center; }
.ed-chiffre .l { font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase;
                 color: var(--muted); }
.ed-chiffre b { font-size: 20px; line-height: 1.2; margin-top: 2px;
                font-variant-numeric: tabular-nums; }
.ed-chiffre .s { font-size: 11.5px; color: var(--muted); margin-top: 1px; }

/* Les informations qu'on cherche la veille : une définition par ligne. */
.ed-infos { margin: 0; display: grid; grid-template-columns: 82px minmax(0, 1fr);
            gap: 8px 12px; align-items: start; }
.ed-infos dt { font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase;
               color: var(--muted); padding-top: 2px; }
.ed-infos dd { margin: 0; font-size: 13px; color: var(--ink); min-width: 0; }
.ed-infos dd .small { margin-top: 2px; line-height: 1.45; }

.ed-tarifs { display: flex; flex-direction: column; }
.ed-tarif { display: grid; grid-template-columns: minmax(0, 1fr) auto auto;
            align-items: center; gap: 10px; padding: 7px 0;
            border-bottom: 1px solid var(--hairline); font-size: 12.5px; }
.ed-tarif:last-child { border-bottom: 0; }
.ed-t-lab { min-width: 0; color: var(--ink); }
.ed-t-lab i { display: block; font-style: normal; font-size: 11px; color: var(--muted); }
.ed-tarif b { font-variant-numeric: tabular-nums; }
.ed-sous { font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase;
           color: var(--muted); margin-bottom: 7px; }
.ed-heb { display: flex; flex-wrap: wrap; gap: 6px; }
.ed-h { font-size: 12px; padding: 3px 10px; border-radius: 999px;
        background: var(--page); border: 1px solid var(--hairline); color: var(--ink-2); }
.ed-h b { color: var(--ink); font-variant-numeric: tabular-nums; }

/* Un régime est une préférence, une allergie ne l'est pas. */
.pastille.info { background: var(--sem-vente-bg); border-color: #cfe0f6;
                 color: var(--sem-vente-t); }
.btn.attention { border-color: #efdcb4; background: var(--sem-attente-bg);
                 color: var(--sem-attente-t); }

/* ---- Modal d'inscription : plus large, et des étiquettes -------------- */
.modal-box.insc-box { width: min(760px, 95vw); max-height: 92vh; }
.insc-box .fld { display: block; font-size: 12px; color: var(--ink-2); font-weight: 600; }
.insc-box .fld > input, .insc-box .fld > select { margin-top: 4px; font-weight: 400; }
.insc-box .divider { margin: 14px 0 12px; }

/* Les étiquettes. En texte libre, « sans gluten » devenait « sans-gluten » à
   la troisième saisie et le traiteur recevait deux régimes pour un. */
.chips { margin-top: 4px; }
.chips-zone { display: flex; flex-wrap: wrap; gap: 5px; align-items: center;
              min-height: 36px; padding: 5px 8px; cursor: text;
              border: 1px solid var(--hairline); border-radius: 9px;
              background: var(--surface); transition: border-color .15s, box-shadow .15s; }
.chips-zone:focus-within { border-color: var(--accent);
                           box-shadow: 0 0 0 3px var(--accent-soft); }
.chips-in { flex: 1; min-width: 130px; border: 0 !important; padding: 2px !important;
            background: none !important; box-shadow: none !important;
            font-size: 12.5px; font-weight: 400; }
.chip { display: inline-flex; align-items: center; gap: 5px; font-size: 12px;
        padding: 2px 4px 2px 9px; border-radius: 999px;
        background: var(--sem-vente-bg); border: 1px solid #cfe0f6;
        color: var(--sem-vente-t); }
/* Une allergie n'est pas une préférence : elle ne se lit pas de la même façon. */
.chips.alg .chip { background: var(--sem-defaut-bg); border-color: #f2ccc4;
                   color: var(--sem-defaut-t); }
.chip-x { border: 0; background: none; padding: 0 3px; cursor: pointer;
          font-size: 10px; line-height: 1; color: inherit; opacity: .55; }
.chip-x:hover { opacity: 1; }
.chips-sugg { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.chips-sugg button { font: inherit; font-size: 11.5px; font-weight: 400;
                     padding: 2px 9px; border-radius: 999px; cursor: pointer;
                     color: var(--muted); background: var(--page);
                     border: 1px dashed var(--hairline); }
.chips-sugg button:hover { color: var(--ink); border-style: solid;
                           border-color: var(--sem-vente); }

/* ---- Choix de l'hébergement : trois cartes, pas un déroulé -------------
   Les options sont trois et ne changent jamais. On veut COMPARER leur
   disponibilité, ce qu'un menu fermé empêche par construction — et un
   `<option>` ne peut pas porter de pastille. */
.lodg-choix { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
              gap: 6px; margin-top: 5px; }
@media (max-width: 620px) { .lodg-choix { grid-template-columns: 1fr; } }
.lodg { display: flex; flex-direction: column; align-items: flex-start; gap: 5px;
        cursor: pointer; padding: 9px 11px; border-radius: 10px;
        border: 1px solid var(--hairline); background: var(--surface);
        transition: border-color .12s, background .12s; }
.lodg:hover { border-color: var(--sem-vente); }
.lodg input { position: absolute; opacity: 0; width: 0; height: 0; }
.lodg-l { font-size: 12.5px; font-weight: 600; color: var(--ink); line-height: 1.3; }
.lodg i { font-style: normal; font-size: 11px; color: var(--muted); }
.lodg:has(input:checked) { border-color: var(--sem-vente); background: var(--sem-vente-bg); }
/* Une formule complète reste choisissable — c'est un avertissement, pas une
   interdiction : quelqu'un sait si le lieu supporte un lit de plus. */
.lodg.plein { background: var(--page); }
.lodg.plein .lodg-l { color: var(--ink-2); }
.lodg.plein:has(input:checked) { border-color: var(--sem-defaut);
                                 background: var(--sem-defaut-bg); }
.pastille.neutre { background: var(--page); border-color: var(--hairline);
                   color: var(--muted); }

/* Une alerte qui n'apparaît que quand elle apprend quelque chose : dernière
   place, ou formule déjà complète. Un avertissement permanent cesse d'en
   être un — d'où le `hidden` par défaut. */
.mini-alerte { display: flex; align-items: flex-start; gap: 8px; margin-top: 8px;
               padding: 7px 11px; border-radius: 9px; font-size: 12px;
               line-height: 1.45; animation: mini-pop .18s ease-out; }
.mini-alerte::before { content: "!"; flex: none; width: 16px; height: 16px;
                       margin-top: 1px; border-radius: 50%; display: grid;
                       place-items: center; font-size: 10px; font-weight: 700;
                       color: #fff; }
.mini-alerte.douce { background: var(--sem-attente-bg); border: 1px solid #efdcb4;
                     color: var(--sem-attente-t); }
.mini-alerte.douce::before { background: var(--sem-attente); }
.mini-alerte.grave { background: var(--sem-defaut-bg); border: 1px solid #f2ccc4;
                     color: var(--sem-defaut-t); }
.mini-alerte.grave::before { background: var(--sem-defaut); }
@keyframes mini-pop { from { opacity: 0; transform: translateY(-3px); } }
@media (prefers-reduced-motion: reduce) { .mini-alerte { animation: none; } }

/* Le reste dû, calculé pendant la frappe. L'encaissement partiel était prévu
   par la plateforme depuis toujours ; c'est de ne pas le MONTRER qui le
   rendait invisible — 50 € entrés sur 113,33 laissaient la ligne « en
   attente », c'est-à-dire de l'argent reçu que l'écran niait. */
.pay-reste { display: flex; align-items: baseline; justify-content: space-between;
             gap: 10px; margin: 10px 0 2px; padding: 8px 12px; border-radius: 9px;
             border: 1px solid var(--hairline); background: var(--page); }
.pay-reste .l { font-size: 11.5px; color: var(--muted); }
.pay-reste b { font-size: 16px; font-variant-numeric: tabular-nums; color: var(--ink); }
.pay-reste.solde { background: var(--sem-facture-bg); border-color: #bfe4cd; }
.pay-reste.solde b, .pay-reste.solde .l { color: var(--sem-facture-t); }
.pay-reste.ouvert { background: var(--sem-attente-bg); border-color: #efdcb4; }
.pay-reste.ouvert b, .pay-reste.ouvert .l { color: var(--sem-attente-t); }
.pay-reste.trop { background: var(--sem-vente-bg); border-color: #cfe0f6; }
.pay-reste.trop b, .pay-reste.trop .l { color: var(--sem-vente-t); }
.pay-deja { font-size: 12px; color: var(--sem-attente-t); margin: -4px 0 8px; }
.ech-partiel { margin-top: 2px; font-variant-numeric: tabular-nums; }

/* ---- Programmer un envoi ----------------------------------------------
   Un calendrier de neuf semaines a été essayé et jeté : la question n'est pas
   « quelle date » mais « combien de jours avant ». Chaque option porte donc sa
   date et son jour — ce que la grille était censée apporter, sans les
   cinquante-cinq cases grises. */
.modal-box.ml-box { width: min(620px, 96vw); max-height: 90vh; }
.ml-head { display: flex; align-items: flex-start; gap: 12px;
           margin: -20px -22px 16px; padding: 13px 22px 12px;
           background: var(--sem-ops-bg); border-bottom: 1px solid #dfe3e9;
           border-radius: 16px 16px 0 0; }
.ml-head > .grow > b { font-size: 15.5px; color: var(--ink); line-height: 1.2; }

/* Une seule colonne : l'aperçu vit dans son modal, pas dans un rail qui
   l'écrase à 300 px — le lire dans un ascenseur, c'est ne pas le lire. */
.ml-col .fld { display: block; font-size: 12px; color: var(--ink-2); font-weight: 600; }
.ml-col .fld > input, .ml-col .fld > textarea { margin-top: 4px; font-weight: 400; }
.ml-col > .fld + .fld { margin-top: 9px; }

.ml-lbl { font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase;
          color: var(--muted); margin-bottom: 7px; }
.ml-col .ml-lbl:not(:first-child) { margin-top: 18px; }

/* Une option par délai, avec sa date. C'est la décision, en entier. */
.ml-choix { display: flex; flex-direction: column; gap: 4px; }
.ml-opt { display: flex; align-items: center; gap: 10px; cursor: pointer;
          padding: 8px 12px; border-radius: 9px; background: var(--surface);
          border: 1px solid var(--hairline);
          transition: border-color .12s, background .12s; }
.ml-opt:hover { border-color: var(--sem-vente); }
.ml-opt input[type=radio] { width: auto; flex: none; margin: 0; }
.ml-opt-j { flex: none; min-width: 42px; font-size: 13px; font-weight: 700;
            color: var(--ink); font-variant-numeric: tabular-nums; }
.ml-opt-d { flex: 1; font-size: 12.5px; color: var(--ink-2); }
.ml-opt-we { font-size: 10.5px; padding: 1px 8px; border-radius: 999px;
             background: var(--sem-attente-bg); color: var(--sem-attente-t);
             border: 1px solid #efdcb4; }
.ml-opt:has(input:checked) { border-color: var(--sem-vente);
                             background: var(--sem-vente-bg); }
.ml-opt.autre .ml-opt-date { flex: 1; margin: 0; font-size: 12.5px; padding: 4px 8px; }

/* Elle n'apparaît qu'une fois un moment choisi : une boîte qui dit
   « choisissez » occupe la place sans rien apprendre. */
.ml-quand { margin-top: 10px; padding: 9px 13px; border-radius: 9px;
            font-size: 12.5px; line-height: 1.45; color: var(--muted);
            background: var(--page); border: 1px solid var(--hairline); }
.ml-quand[hidden] { display: none; }
.ml-quand.pret { background: var(--sem-facture-bg); border-color: #bfe4cd;
                 color: var(--sem-facture-t); }
.ml-quand.pret.we { background: var(--sem-attente-bg); border-color: #efdcb4;
                    color: var(--sem-attente-t); }
.ml-quand.rate { background: var(--sem-defaut-bg); border-color: #f2ccc4;
                 color: var(--sem-defaut-t); }
.ml-we { display: block; margin-top: 2px; font-size: 11.5px; opacity: .85; }

/* L'aperçu : ce que la personne recevra, pas un gabarit générique. */
.ml-apercu { position: sticky; top: 0; }
.ml-ap-tete { display: flex; align-items: center; gap: 8px; }
.ml-ap-tete .ml-lbl { margin-bottom: 0; }
.ml-ap-tete .pastille { margin-left: auto; }
.ml-mail { margin-top: 7px; border: 1px solid var(--hairline); border-radius: 11px;
           overflow: hidden; background: var(--surface); }
.ml-mail-tete { padding: 10px 13px; background: var(--page);
                border-bottom: 1px solid var(--hairline); }
.ml-mail-de { font-size: 12px; font-weight: 700; color: var(--ink); }
.ml-mail-a { font-size: 11.5px; color: var(--ink-2); margin-top: 1px;
             overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ml-mail-obj { font-size: 12.5px; font-weight: 650; color: var(--ink); margin-top: 6px;
               line-height: 1.35; }
.ml-mail-corps { margin: 0; padding: 12px 13px; font: inherit; font-size: 11.5px;
                 line-height: 1.6; color: var(--ink-2); white-space: pre-wrap;
                 max-height: 260px; overflow-y: auto; }
.ml-mail-pj { padding: 8px 13px; border-top: 1px solid var(--hairline);
              font-size: 11.5px; color: var(--muted); background: var(--page); }
.ml-mail-pj::before { content: "📎 "; }

/* Sans destinataire, pas de formulaire : ce qui manque, et par où le corriger. */
.ml-vide { display: flex; gap: 13px; align-items: flex-start; padding: 18px 4px 8px; }
.ml-vide-ico { flex: none; width: 26px; height: 26px; border-radius: 50%;
               display: grid; place-items: center; font-size: 14px; font-weight: 700;
               background: var(--sem-attente); color: #fff; }
.ml-vide b { font-size: 14px; color: var(--ink); }
.ml-vide p { margin: 5px 0 11px; font-size: 12.5px; line-height: 1.55;
             color: var(--ink-2); max-width: 52ch; }

/* Ce qui va partir. Programmé et invisible, c'est programmé et oublié — et
   celui-ci part tout seul, donc l'oubli se découvre après coup. */
.ml-prevus { display: flex; flex-direction: column; gap: 5px; margin-bottom: 12px; }
.ml-prevu { display: flex; align-items: center; gap: 10px; padding: 8px 13px;
            border-radius: 9px; font-size: 12.5px; background: var(--sem-vente-bg);
            border: 1px solid #cfe0f6; color: var(--sem-vente-t); }
.ml-prevu.fait { background: var(--sem-facture-bg); border-color: #bfe4cd;
                 color: var(--sem-facture-t); }
.ml-prevu.rate { background: var(--sem-defaut-bg); border-color: #f2ccc4;
                 color: var(--sem-defaut-t); }
.ml-prevu.retard { background: var(--sem-attente-bg); border-color: #efdcb4;
                   color: var(--sem-attente-t); }
.ml-p-quoi { flex: 1; min-width: 0; }

/* ---- Une adresse qu'on corrige sur place -------------------------------
   C'est UN champ, et c'est celui qui bloque tout : sans lui, la liste des
   régimes et allergies ne part chez personne. Ouvrir une fiche pour le
   saisir, revenir, rouvrir le modal — trois gestes pour un. */
.inline-mail { display: inline-flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.im-voir { font: inherit; font-size: 12px; padding: 2px 8px; border-radius: 7px;
           cursor: pointer; color: var(--sem-vente-t); background: none;
           border: 1px solid transparent; text-align: left; }
.im-voir:hover { background: var(--page); border-color: var(--hairline); }
/* L'absence d'adresse se signale comme une tâche, pas comme une donnée. */
.im-voir.vide { color: var(--sem-attente-t); background: var(--sem-attente-bg);
                border-color: #efdcb4; }
.im-voir.vide:hover { border-color: var(--sem-attente); }
.im-champ { font-size: 12.5px !important; padding: 4px 8px !important;
            min-width: 190px; }
.im-err { font-size: 11px; color: var(--sem-defaut-t); }

.ml-fix { display: flex; gap: 6px; align-items: center; max-width: 420px; }
.ml-fix input { font-size: 12.5px; padding: 6px 10px; }
.ml-fix button { flex: none; }
.ml-fix-erreur { margin: 6px 0 0; font-size: 12px; color: var(--sem-defaut-t); }

/* ---- Heure, pièces jointes, grand aperçu -------------------------------
   L'heure : quatre choix qui veulent dire quelque chose plutôt qu'un champ
   nu — « en arrivant » se décide, « 08:30 » se tape. */
.ml-heures { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
             gap: 4px; }
@media (max-width: 620px) { .ml-heures { grid-template-columns: repeat(2, 1fr); } }
.ml-h { display: flex; flex-direction: column; align-items: center; gap: 1px;
        cursor: pointer; padding: 7px 4px; border-radius: 9px;
        background: var(--surface); border: 1px solid var(--hairline);
        transition: border-color .12s, background .12s; }
.ml-h:hover { border-color: var(--sem-vente); }
.ml-h input[type=radio] { position: absolute; opacity: 0; width: 0; height: 0; }
.ml-h b { font-size: 13px; font-variant-numeric: tabular-nums; color: var(--ink); }
.ml-h span { font-size: 10px; color: var(--muted); text-align: center; line-height: 1.2; }
.ml-h:has(input:checked) { border-color: var(--sem-vente); background: var(--sem-vente-bg); }
.ml-h.autre { gap: 2px; }
/* Le champ libre a la même hauteur et la même graisse que les autres : une
   cellule dépareillée au bout d'une rangée se lit comme un bug. */
.ml-h-libre { width: 100%; font-size: 12.5px !important; font-weight: 600;
              padding: 1px 2px !important; text-align: center;
              border: 0 !important; background: none !important;
              box-shadow: none !important; color: var(--ink);
              font-variant-numeric: tabular-nums; }
.ml-h.autre b { font-size: 11px; color: var(--muted); font-weight: 600; }
.ml-h.autre:has(input[type=radio]:checked) b { color: var(--sem-vente-t); }

/* Le CSV se trie dans Excel, le PDF se lit dans le train. Deux besoins. */
.ml-pieces { display: flex; flex-wrap: wrap; gap: 5px; }
.ml-pc { cursor: pointer; }
.ml-pc input { position: absolute; opacity: 0; width: 0; height: 0; }
.ml-pc span { display: inline-block; font-size: 12px; padding: 5px 12px;
              border-radius: 999px; color: var(--ink-2); background: var(--surface);
              border: 1px solid var(--hairline);
              transition: border-color .12s, background .12s, color .12s; }
.ml-pc:hover span { border-color: var(--sem-vente); }
.ml-pc:has(input:checked) span { background: var(--sem-vente); border-color: var(--sem-vente);
                                 color: #fff; font-weight: 600; }

/* L'aperçu compact appelle le grand : le tenir entier dans 300 px obligeait
   à le lire dans un ascenseur, c'est-à-dire à ne pas le lire. */
.ml-mail-mini { display: block; width: 100%; padding: 0; text-align: left;
                font: inherit; cursor: pointer; }
.ml-mail-mini .ml-mail-corps { max-height: 150px; overflow: hidden;
                               -webkit-mask-image: linear-gradient(#000 60%, transparent);
                               mask-image: linear-gradient(#000 60%, transparent); }
.ml-mail-plus { display: block; padding: 7px 13px; font-size: 11.5px; font-weight: 600;
                color: var(--sem-vente-t); background: var(--page);
                border-top: 1px solid var(--hairline); }
.ml-mail-mini:hover { border-color: var(--sem-vente); }
.ml-mail-mini:hover .ml-mail-plus { background: var(--sem-vente-bg); }

/* L'aperçu est large : deux colonnes, l'e-mail et ce qui part avec. À 620 px
   il n'y avait la place que pour la première, et la pièce jointe s'y réduisait
   à une phrase — alors que c'est le document qu'on veut relire. */
.modal-box.ml-ap-box { width: min(1180px, 96vw); max-height: 92vh;
  display: flex; flex-direction: column; }
.ml-ap-sous { font-size: 11.5px; color: var(--muted); margin-top: 2px; }
.ml-ap-grille { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 420px);
  gap: 14px; min-height: 0; flex: 1; }
@media (max-width: 900px) { .ml-ap-grille { grid-template-columns: 1fr; } }

.ml-ap-grille .ml-grand { display: flex; flex-direction: column; min-height: 0; }
.ml-ap-grille .ml-grand-corps { flex: 1; overflow: auto; }

/* La colonne des pièces jointes. Fond léger : c'est ce qui ACCOMPAGNE le
   message, pas le message. */
.ml-ap-pj { display: flex; flex-direction: column; gap: 10px; min-height: 0;
  padding: 12px; border-radius: 11px; background: var(--page);
  border: 1px solid var(--hairline); }
.ml-pj-tete { font-size: 10.5px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted); font-weight: 600; }

.ml-pj-doc { margin: 0; display: flex; flex-direction: column; min-height: 0; flex: 1; }
.ml-pj-doc figcaption { display: flex; align-items: baseline; gap: 8px;
  margin-bottom: 6px; font-size: 12px; }
.ml-pj-doc figcaption b { flex: 1; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.ml-pj-doc figcaption a { font-size: 11.5px; color: var(--accent-strong);
  text-decoration: none; flex: none; }
.ml-pj-doc figcaption a:hover { text-decoration: underline; }
/* Le document lui-même, sur fond blanc et sans bordure de navigateur : c'est
   une feuille, elle doit ressembler à une feuille. */
.ml-pj-doc iframe { flex: 1; min-height: 340px; width: 100%; border: 0;
  border-radius: 8px; background: #fff; box-shadow: var(--shadow); }

/* Le CSV ne se prévisualise pas — il s'ouvre dans un tableur. Une carte de
   fichier honnête vaut mieux qu'un aperçu bricolé. */
.ml-pj-fichier { display: flex; align-items: center; gap: 10px; padding: 10px 12px;
  border-radius: 9px; background: var(--surface); border: 1px solid var(--hairline); }
.ml-pj-ico { flex: none; display: grid; place-items: center; width: 38px; height: 44px;
  border-radius: 5px; background: var(--sem-facture-bg); color: var(--sem-facture-t);
  font-size: 10px; font-weight: 700; letter-spacing: .04em; }
.ml-pj-fichier b { display: block; font-size: 12.5px; }
.ml-pj-fichier span { font-size: 11.5px; color: var(--muted); }

.ml-pj-vide { padding: 14px; border-radius: 9px; border: 1px dashed var(--hairline);
  font-size: 12.5px; color: var(--muted); text-align: center; }
.ml-grand { border: 1px solid var(--hairline); border-radius: 11px; overflow: hidden; }
.ml-grand-tete { padding: 13px 16px; background: var(--page);
                 border-bottom: 1px solid var(--hairline); }
.ml-g-ligne { display: flex; gap: 12px; font-size: 12.5px; padding: 2px 0; }
.ml-g-ligne span { flex: none; width: 44px; color: var(--muted); font-size: 11px;
                   letter-spacing: .05em; text-transform: uppercase; padding-top: 2px; }
.ml-g-ligne b { flex: 1; min-width: 0; color: var(--ink); font-weight: 600; }
.ml-grand-corps { margin: 0; padding: 20px 22px; font: inherit; font-size: 13px;
                  line-height: 1.7; color: var(--ink); white-space: pre-wrap;
                  background: var(--surface); max-height: 52vh; overflow-y: auto; }
.ml-grand-pj { padding: 10px 16px; border-top: 1px solid var(--hairline);
               font-size: 12px; color: var(--muted); background: var(--page); }
.ml-grand-pj::before { content: "📎 "; }

/* ---- L'aperçu de la liste de présence ----------------------------------
   Un `<iframe>` sur la page imprimable et pas une reproduction : ce qu'on
   regarde EST le document, aux proportions du papier. Deux rendus séparés
   finiraient par différer, et c'est celui qu'on n'a pas regardé qui partirait. */
.modal-box.pres-box { width: min(900px, 96vw); max-height: 92vh;
                      display: flex; flex-direction: column; }
.pres-cadre { flex: 1; min-height: 0; background: #f4f4f2; border-radius: 10px;
              border: 1px solid var(--hairline); overflow: hidden; }
.pres-cadre iframe { display: block; width: 100%; height: 62vh; border: 0; }

/* ---------- Annulation d'une inscription ---------- */
/* Le délai, en tête du modal : c'est lui qui choisit la règle, donc il se lit
   avant tout le reste. */
.an-jours { flex: none; padding: 4px 10px; border-radius: 999px; font-weight: 700;
  font-size: 13px; font-variant-numeric: tabular-nums;
  background: var(--sem-vente-bg); color: var(--sem-vente-t); }
.an-jours.passe { background: var(--sem-ops-bg); color: var(--sem-ops-t); }

.an-portee { margin-bottom: 8px; }

/* L'échelle du barème. Elle répond à « pourquoi ce montant », qui est la
   question que pose toute personne à qui l'on annonce un avoir partiel. */
.an-echelle { list-style: none; margin: 0; padding: 0;
  border: 1px solid var(--hairline); border-radius: 10px; overflow: hidden; }
.an-echelle li { display: flex; align-items: baseline; gap: 8px;
  padding: 7px 11px; font-size: 13px; color: var(--ink-2);
  border-bottom: 1px solid var(--hairline); }
.an-echelle li:last-child { border-bottom: 0; }
.an-echelle li.apres { color: var(--muted); }
/* Celle qui gagne : c'est le seul renseignement que l'œil doit trouver seul. */
.an-echelle li.gagne { background: var(--accent-soft); color: var(--ink);
  font-weight: 600; box-shadow: inset 3px 0 0 var(--accent-strong); }
.an-seuil { flex: none; min-width: 54px; font-variant-numeric: tabular-nums; }
.an-fleche { flex: none; color: var(--muted); }
.an-pct { flex: none; min-width: 44px; font-variant-numeric: tabular-nums;
  font-weight: 650; }
.an-appliquee { margin-left: auto; font-size: 11px; letter-spacing: .06em;
  text-transform: uppercase; color: var(--accent-strong); }
.an-note-r { color: var(--muted); font-size: 12px; }
.an-precision { margin: 9px 0 0; font-size: 12.5px; color: var(--ink-2); }

/* Les règles telles qu'elles s'affichent sur la fiche de l'événement. */
.an-chip { display: inline-block; margin: 0 4px 4px 0; padding: 2px 9px;
  border-radius: 999px; font-size: 12px; font-variant-numeric: tabular-nums;
  background: var(--sem-facture-bg); color: var(--sem-facture-t); }
.an-chip.zero { background: var(--sem-ops-bg); color: var(--sem-ops-t); }

/* Quand il n'y aura pas d'avoir : on le dit, plutôt que d'afficher « 0,00 € »
   qui se lit comme une erreur de calcul. */
.ap-somme.neutre b { color: var(--muted); font-weight: 600; }
.ap-pourquoi { margin: 6px 0 14px; font-size: 12.5px; color: var(--ink-2); }

/* La place rendue. C'est la moitié que l'argent fait oublier, et c'est celle
   qui se voit le jour de l'événement. */
.ap-libere { margin: 14px 0 10px; padding: 10px 12px; border-radius: 10px;
  background: var(--good-tint); border: 1px solid var(--good-tint-border); }
.ap-libere ul { margin: 5px 0 0; padding-left: 17px; font-size: 12.5px;
  color: var(--ink-2); }
.ap-libere li { margin-bottom: 3px; }

/* Une inscription annulée reste visible, barrée : une annulation qu'on ne voit
   plus est une annulation qu'on refait. */
.reg-annulee { background: repeating-linear-gradient(-45deg,
  transparent, transparent 7px, rgba(11,11,11,.018) 7px, rgba(11,11,11,.018) 14px); }
.reg-annulee td { color: var(--muted); }
.ev-barre { text-decoration: line-through; text-decoration-thickness: 1px; }

/* Les règles d'annulation dans le formulaire — mêmes colonnes que les tarifs,
   en plus étroit : deux nombres et une précision. */
.regles { display: flex; flex-direction: column; gap: 6px; margin-bottom: 9px; }
.regle-tete, .regle-ligne {
  display: grid; grid-template-columns: 110px 100px 1fr 30px; gap: 8px;
  align-items: center; }
.regle-tete { font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted); }
.regle-ligne input { font-size: 12.5px; padding: 5px 8px; width: 100%; }
.regle-ligne input[type=number] { font-variant-numeric: tabular-nums; }
.regle-ligne .fld-in i { right: 8px; font-size: 11.5px; }
/* Le préfixe « J− » collé au champ : sans lui, « 30 » ne dit pas s'il s'agit
   de jours, d'euros ou d'un pourcentage. L'`<i>` de `.fld-in` est absolu et
   calé à droite ; ici il passe à gauche et l'entrée lui fait de la place. */
.regle-ligne .fld-in.pre i { left: 9px; right: auto; }
.regle-ligne .fld-in.pre input { padding-left: 28px; }
.enc-step.petit { margin-top: 18px; }
.enc-step.petit h4 { margin: 0; font-size: 13.5px; }
@media (max-width: 720px) {
  .regle-tete { display: none; }
  .regle-ligne { grid-template-columns: 1fr 1fr; }
}

/* Clôturer / archiver un événement passé — discret et réversible */
.btn.clore { color: #8a7a52; border-color: #e3dcc9; }
.btn.clore:hover { color: #6a5c38; border-color: #cdbf9a; background: #faf6ec; }
.ev-archived { display: inline-flex; align-items: center; gap: 4px; font-size: 11.5px;
  font-weight: 600; color: #8a7a52; background: #f6f0e0; border: 1px solid #e6dfcb;
  border-radius: 999px; padding: 3px 11px; white-space: nowrap; }
tr.ev-arch { opacity: .58; transition: opacity .15s; }
tr.ev-arch:hover { opacity: .9; }

/* ── Équipe & accès (T-01) ───────────────────────────────────────────────── */

/* Incarnation. Ambre = « à traiter » : un état temporaire dont il faut sortir,
   pas une erreur. Barre pleine largeur, elle ne se confond avec aucun contenu. */
.impersonate-bar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin: 0 0 14px; padding: 9px 14px; border-radius: 10px;
  background: var(--sem-attente-bg); color: var(--sem-attente-t);
  border: 1px solid var(--sem-attente);
  font-size: 13px;
}
.impersonate-bar form { margin: 0; }

/* Les identifiants tiennent sur UNE ligne : ils ne reviendront jamais, mais
   ils n'ont pas à occuper un quart de l'écran pour autant. */
.mdp-bar {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  margin: 0 0 12px; padding: 8px 14px; border-radius: 10px;
  background: var(--sem-facture-bg); border: 1px solid var(--sem-facture);
  font-size: 12.5px;
}
.mdp-who { font-weight: 650; color: var(--sem-facture-t); }
.mdp-l { font-size: 11px; text-transform: uppercase; letter-spacing: .04em;
         color: var(--ink-2); }
.mdp-v { font-size: 14px; font-weight: 650; user-select: all; color: var(--ink); }
.mdp-note { font-size: 11.5px; color: var(--sem-facture-t); font-style: italic; }

/* Tableau dense : cet écran se balaie (qui a un accès, qui n'en a pas), il ne
   se lit pas ligne à ligne. */
.table-compact th, .table-compact td { padding: 4px 9px; font-size: 12.5px; }
.table-compact code { font-size: 12px; }
.table-compact .td-mail {
  max-width: 210px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* L'état tient dans une pastille : la couleur le porte, le tooltip le nomme.
   Trois mots dans une colonne pour dire « actif » quinze fois, c'est du bruit. */
.dot-etat { display: inline-block; width: 9px; height: 9px; border-radius: 50%; }
.dot-etat.e-on   { background: var(--sem-facture); }
.dot-etat.e-off  { background: var(--muted); }
.dot-etat.e-none { background: var(--sem-attente); }

/* Actions : des icônes, pas des phrases. Le libellé vit dans le tooltip. */
/* La colonne d'actions reste une CELLULE de tableau.

   Elle portait `display: flex`, posé sur le <td> lui-même — ce qui le sort de
   la mise en page du tableau : il ne monte plus à la hauteur de la ligne, et
   son contenu se cale en haut. Invisible tant que toutes les lignes font la
   même hauteur ; dès qu'une ligne en porte davantage (l'équipe interne a un
   sous-titre sous son nom), les icônes se décalent vers le haut et l'écart
   grandit ligne après ligne.
   
   En restant une cellule, `vertical-align: middle` fait le centrage, et les
   enfants s'alignent en ligne. */
.row-actions { vertical-align: middle; text-align: right; white-space: nowrap; }
.row-actions > *, .row-actions form { display: inline-block; vertical-align: middle;
                                      margin: 0; }
.row-actions > * + * { margin-left: 3px; }
.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; padding: 0;
  border: 1px solid transparent; border-radius: 7px;
  background: none; color: var(--ink-2); cursor: pointer;
}
.icon-btn:hover { background: var(--page); border-color: var(--hairline); color: var(--ink); }
.icon-btn.act { color: var(--sem-vente-t); }
.icon-btn.danger:hover {
  color: var(--sem-defaut-t); border-color: var(--sem-defaut);
  background: var(--sem-defaut-bg);
}
.icon-btn[disabled] { opacity: .35; cursor: not-allowed; }

/* ── Les actions de la ligne d'équipe ────────────────────────────────────
   Les classes `ia-*` existaient dans le gabarit sans une ligne de CSS : les
   six boutons sortaient identiques et gris, et il fallait survoler chacun
   pour savoir lequel régénère un mot de passe et lequel suspend un accès.

   Le traitement est EXACTEMENT celui de `/adv/suivi-closing/` (`.pv-a-*`) :
   fond teinté au repos — pas seulement au survol, sinon on ne reconnaît rien
   sans viser — et au survol un assombrissement léger plus un filet de la
   même famille. Deux écrans de la même plateforme doivent se lire pareil.

   La couleur classe le geste, elle ne décore pas : gris = la fiche,
   bleu = ce qui ouvre, vert = ce qui crée l'accès, ambre = ce qui se refait
   avec précaution, rouge = ce qui referme. */
.row-actions .icon-btn { border-color: transparent; }
.ia-fiche      { color: var(--muted);           background: var(--page); }
.ia-compte     { color: var(--sem-facture-t);   background: var(--sem-facture-bg); }
.ia-mdp        { color: var(--sem-attente-t);   background: var(--sem-attente-bg); }
.ia-envoi      { color: var(--sem-acces-t);     background: var(--sem-acces-bg); }
.ia-incarner   { color: var(--sem-vente-t);     background: var(--sem-vente-bg); }
/* Le même bouton pour deux gestes opposés : rouge quand il ferme l'accès,
   neutre quand il le rouvre. Sans ça, « réactiver » criait au danger. */
.ia-suspendre         { color: var(--muted);          background: var(--page); }
.ia-suspendre.danger  { color: var(--sem-defaut-t);   background: var(--sem-defaut-bg); }

.row-actions .icon-btn:hover { filter: brightness(.94); }
.ia-fiche:hover            { border-color: var(--hairline); }
.ia-compte:hover           { border-color: #bfe4cd; }
.ia-mdp:hover              { border-color: #f0dcb4; }
.ia-envoi:hover            { border-color: var(--sem-acces-t); }
.ia-incarner:hover         { border-color: #cfe0f6; }
.ia-suspendre:hover        { border-color: var(--hairline); }
.ia-suspendre.danger:hover { border-color: #f2ccc4; }
.row-actions .icon-btn[disabled]:hover { filter: none; border-color: transparent; }

/* La recherche de /equipe/. Même allure que celle de l'en-tête — loupe dedans,
   pas de bouton à côté — parce que c'est le même geste. Elle prend la place
   qui reste dans la barre : on y tape « beatrice@wutao.fr », pas « be ». */
.eq-chercher {
  display: flex; align-items: center; gap: 7px;
  flex: 1 1 320px; min-width: 220px; max-width: 460px;
  height: 30px; padding: 0 11px;
  background: var(--page); border: 1px solid var(--hairline);
  border-radius: 8px; color: var(--muted);
  transition: border-color .15s, background .15s;
}
.eq-chercher:focus-within { border-color: var(--accent-soft); background: var(--surface); }
.eq-loupe { display: flex; flex: none; }
.eq-chercher input {
  flex: 1; min-width: 0; border: 0; background: none; outline: none;
  font: inherit; font-size: 13px; color: var(--ink);
}
.eq-chercher input::placeholder { color: var(--muted); }
/* La croix native de `type=search` : elle vide le champ d'un clic, et le
   filtre en direct suit tout seul puisqu'il écoute `input`. */
.eq-chercher input::-webkit-search-cancel-button { cursor: pointer; }
/* Le bouton « Filtrer » est caché par le script dès que le direct fonctionne ;
   il ne doit pas laisser un blanc dans la barre en attendant. */
.eq-chercher .btn[hidden] { display: none; }

.modal-intro { margin: 0 0 12px; font-size: 13px; color: var(--ink-2); }

/* Estado INTERMEDIO del sidebar: parte de la sección ya funciona y parte no.
   No puede ser el ámbar de « en dév. » (diría que no hay nada listo) ni la
   ausencia de badge (diría que está todo). Azul informativo, tercer estado. */
.nav-wip.partiel { color: #9fd2e8; background: rgba(14, 154, 167, .16);
                   border-color: rgba(14, 154, 167, .42); }

/* Badge de UNA entrada dentro de un grupo parcial: más pequeño, para que el
   del grupo siga mandando visualmente. */
.nav-sub .nav-wip.sub { flex: none; margin-left: 0; padding: 0 5px;
                        font-size: 8.5px; }

/* Champ éditable EN PLACE : il se lit comme du texte et se corrige d'un clic.
   Une bordure permanente ferait un formulaire d'un tableau ; elle n'apparaît
   qu'au survol et au focus, là où on a l'intention d'écrire. */
/* `input.inline-edit` et pas `.inline-edit` : la règle globale des formulaires
   est `input[type=text], …` (spécificité 0,1,1) et l'emporterait sur une simple
   classe (0,1,0) — elle rendait au champ ses 7px de padding et sa bordure, et
   le tableau reprenait la hauteur d'un formulaire. */
input.inline-edit {
  width: 100%; min-width: 0; padding: 1px 5px; font-size: 12px;
  color: var(--ink); background: none;
  border: 1px solid transparent; border-radius: 6px;
}
input.inline-edit:hover { border-color: var(--hairline); background: var(--surface); }
input.inline-edit:focus {
  outline: none; border-color: var(--accent); background: var(--surface);
  box-shadow: none;
}
input.inline-edit::placeholder { color: var(--muted); }

.td-cal { white-space: nowrap; }
/* Le préfixe est fixe et commun à tous : il s'affiche une fois, en gris, et
   n'occupe pas la place du champ. Le champ ne contient donc que ce qui
   distingue une agenda d'une autre — et cesse d'être tronqué. */
.td-cal form { display: inline-flex; align-items: center; margin: 0;
               vertical-align: middle; }
.cal-prefix { flex: none; font-size: 11.5px; color: var(--muted); }
.td-cal input.inline-edit { width: 178px; }
.td-cal .dot-etat { margin-left: 6px; vertical-align: middle; }

/* Un formulaire dans la barre d'actions ne doit pas casser l'alignement. */
.page-head .actions form { margin: 0; display: inline-block; }

/* ── Onglet « en travaux » ────────────────────────────────────────────────
   Un onglet non branché doit se reconnaître AVANT le clic. Deux signaux qui
   ne dépendent pas de la couleur seule : l'onglet est décoloré, et il porte un
   ruban rayé — la trame diagonale se lit comme un chantier même en niveaux de
   gris ou pour un daltonien. */
.tabstrip .tab.travaux { opacity: .45; }
.tabstrip .tab.travaux:hover { opacity: .7; color: var(--muted); }
.tab-travaux {
  display: inline-block; vertical-align: 1px; margin-left: 7px;
  padding: 1px 7px; border-radius: 999px;
  font-size: 9px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; line-height: 1.6; white-space: nowrap;
  color: var(--sem-attente-t);
  border: 1px solid rgba(198, 125, 16, .45);
  background: repeating-linear-gradient(45deg,
              rgba(198, 125, 16, .26) 0 4px,
              rgba(198, 125, 16, .05) 4px 8px);
}

/* ── Calendrier commun des closers ───────────────────────────────────────── */
.cal-head { display: flex; align-items: center; justify-content: space-between;
            gap: 12px; flex-wrap: wrap; margin-bottom: 10px; }
.cal-nav { display: flex; align-items: center; gap: 8px; }
.cal-mois { font-size: 14px; text-transform: capitalize; min-width: 130px; }
.cal-filtre { margin: 0; } .cal-filtre select { width: auto; min-width: 160px; }

.cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
            gap: 1px; background: var(--hairline); border: 1px solid var(--hairline);
            border-radius: 10px; overflow: hidden; }
.cal-dow { background: var(--page); padding: 3px 7px; font-size: 10px;
           text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
.cal-jour { background: var(--surface); min-height: 58px; padding: 3px 4px;
            display: flex; flex-direction: column; gap: 2px; }
.cal-jour.hors { background: var(--page); }
.cal-jour.hors .cal-num { opacity: .4; }
.cal-jour.today { box-shadow: inset 0 0 0 2px var(--accent); }
.cal-num { font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
.cal-jour.today .cal-num { color: var(--accent); font-weight: 700; }

/* Un rendez-vous : la pastille colorée situe le closer d'un coup d'œil, mais
   son nom est écrit — quinze teintes ne se distinguent pas de façon fiable. */
/* Une pastille de rendez-vous : deux lignes, pas trois. L'heure et le nom sur
   la même ligne — ils se lisent ensemble — et le closer dessous, en petit mais
   ÉCRIT : quinze teintes ne se distinguent pas, la couleur ne porte donc
   jamais l'identité toute seule. Le fond teinté remplace le filet latéral :
   plus doux, et la couleur reste lisible d'un coup d'œil. */
.cal-rdv {
  display: block; width: 100%; text-align: left; padding: 3px 7px;
  border-radius: 8px; cursor: pointer;
  background: color-mix(in srgb, var(--rdv) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--rdv) 24%, transparent);
  font-size: 10px; line-height: 1.25; color: var(--ink);
  text-decoration: none; overflow: hidden;
}
.cal-rdv:hover { background: color-mix(in srgb, var(--rdv) 20%, transparent);
                 border-color: var(--rdv); text-decoration: none; }
.cal-rdv.annule { opacity: .45; text-decoration: line-through; }
.cal-l1 { display: flex; align-items: baseline; gap: 5px; min-width: 0; }
.cal-h { font-weight: 700; flex: none; font-variant-numeric: tabular-nums; }
.cal-qui { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cal-closer { display: block; color: var(--rdv); font-weight: 600; font-size: 9px;
              overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.cal-legende { display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: 12px;
               font-size: 11.5px; color: var(--ink-2); }
.cal-lg { display: inline-flex; align-items: center; gap: 5px; }
.cal-lg i { width: 9px; height: 9px; border-radius: 2px; flex: none; }

/* Filtre multi-closers : liste à cocher avec recherche. */
.cal-filtre { position: relative; }
.multi-pop {
  position: absolute; right: 0; top: calc(100% + 5px); z-index: 20; width: 250px;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: 10px; box-shadow: var(--shadow-lift); padding: 8px;
}
.multi-pop .multi-q { width: 100%; margin-bottom: 6px; }
.multi-list { max-height: 232px; overflow-y: auto; }
.multi-it { display: flex; align-items: center; gap: 7px; padding: 3px 5px;
            border-radius: 6px; font-size: 12.5px; cursor: pointer; }
.multi-it:hover { background: var(--page); }
.multi-it input { width: auto; margin: 0; }
.multi-it i { width: 9px; height: 9px; border-radius: 2px; flex: none; }
.multi-foot { display: flex; justify-content: space-between; gap: 6px;
              margin-top: 7px; padding-top: 7px; border-top: 1px solid var(--hairline); }

/* Sélecteur d'échelle du calendrier (mois / semaine / jour). */
.vue-switch { display: inline-flex; margin-left: auto; border: 1px solid var(--hairline);
              border-radius: 8px; overflow: hidden; }
.vue-switch a { padding: 3px 11px; font-size: 12px; color: var(--ink-2);
                text-decoration: none; border-left: 1px solid var(--hairline); }
.vue-switch a:first-child { border-left: 0; }
.vue-switch a:hover { background: var(--page); text-decoration: none; }
.vue-switch a.on { background: var(--accent); color: #fff; font-weight: 600; }

/* En vue SEMAINE il n'y a qu'une rangée : les journées peuvent respirer et
   montrer tous leurs rendez-vous sans qu'on ait à survoler. */
.cal-grid.sem .cal-jour { min-height: 300px; }

/* Vue JOUR : une colonne chronologique. */
.cal-jourvue { display: flex; flex-direction: column; gap: 2px;
               border: 1px solid var(--hairline); border-radius: 10px; padding: 6px; }
.cal-jourvue.today { box-shadow: inset 0 0 0 2px var(--accent); }
.cal-ligne {
  display: grid; grid-template-columns: 52px minmax(0, 2fr) minmax(0, 1fr);
  gap: 10px; align-items: baseline;
  padding: 6px 9px; border-radius: 7px; text-decoration: none; color: var(--ink);
  border-left: 3px solid var(--rdv);
  background: color-mix(in srgb, var(--rdv) 7%, transparent);
  font-size: 12.5px;
}
.cal-ligne:hover { background: color-mix(in srgb, var(--rdv) 15%, transparent);
                   text-decoration: none; }
.cal-ligne.annule { opacity: .45; text-decoration: line-through; }
.cal-ligne .cal-closer { font-size: 12px; }
.cal-ligne .cal-rep { grid-column: 2 / -1; color: var(--ink-2); font-size: 11.5px; }

/* ── Tableau des rendez-vous : pleine largeur, dense, filtrable ──────────── */
.rdv-filtres { display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
               margin-bottom: 10px; }
.rdv-filtres select, .rdv-filtres input[type=date] { width: auto; min-width: 128px; }
.rdv-filtres .f-search { min-width: 230px; flex: 1 1 230px; }
.f-date { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px;
          color: var(--muted); }
.rdv-table .pastille { display: inline-block; width: 8px; height: 8px;
                       border-radius: 50%; margin-right: 6px; vertical-align: 1px; }
.rdv-table .td-rep { max-width: 320px; overflow: hidden; text-overflow: ellipsis;
                     white-space: nowrap; }
.rdv-table .sel-statut { width: 128px; font-size: 11.5px; padding: 2px 6px; }
.rdv-table tr.ligne-annulee td { opacity: .5; text-decoration: line-through; }
.pagin { display: flex; align-items: center; gap: 10px; justify-content: center;
         margin-top: 10px; }

/* Avertissement d'un geste qui sort de la plateforme (e-mail réel envoyé). */
.avertissement { margin: 6px 0 0; padding: 7px 10px; border-radius: 8px;
                 font-size: 12px; color: var(--sem-attente-t);
                 background: var(--sem-attente-bg);
                 border: 1px solid var(--sem-attente); }

/* Types d'input absents de la règle globale des formulaires : ils tombaient en
   rendu NATIF — sans bordure, sans largeur, alignés au fil du texte — et
   cassaient la mise en page des formulaires qui les utilisent (« Date et
   heure » du modal de rendez-vous). Même famille de bug que le type=url. */
input[type=datetime-local], input[type=time], input[type=url], input[type=tel] {
  font-family: inherit; font-size: 13.5px; color: var(--ink);
  border: 1px solid var(--hairline); border-radius: 9px; padding: 7px 10px;
  background: var(--surface); width: 100%;
  transition: border-color .15s, box-shadow .15s;
}
input[type=datetime-local]:hover, input[type=time]:hover,
input[type=url]:hover, input[type=tel]:hover { border-color: #b9b7ae; }

/* ── Modal « Nouveau rendez-vous » ───────────────────────────────────────── */
.rdv-form .form-row { gap: 12px; }
.rdv-form .form-row > label { flex: 1 1 0; min-width: 0; }
/* La case et son avertissement forment UN bloc : ce qu'on coche et ce que ça
   déclenche ne doivent pas se lire comme deux informations séparées. */
.rdv-envoi { margin-top: 4px; padding: 10px 12px; border-radius: 10px;
             background: var(--page); border: 1px solid var(--hairline); }
.rdv-envoi .check { margin: 0; font-weight: 600; font-size: 13px; }
.rdv-envoi .avertissement { margin-top: 8px; display: flex; gap: 8px;
                            align-items: flex-start; line-height: 1.45; }
.rdv-envoi .avertissement b { font-weight: 700; }
/* Règle GÉNÉRALE, pas réservée au formulaire de saisie : la fiche d'un
   rendez-vous utilise le même pied, et scoper sous `.rdv-form` la privait de
   sa marge — les boutons se collaient à la dernière réponse. */
.modal-actions { display: flex; gap: 8px; margin-top: 18px;
                 padding-top: 14px; border-top: 1px solid var(--hairline); }

/* ── Fiche d'un rendez-vous (modal du calendrier) ────────────────────────── */
.rf-bandeau { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
              padding: 9px 12px; border-radius: 9px; margin-bottom: 12px;
              border-left: 3px solid var(--rdv);
              background: color-mix(in srgb, var(--rdv) 9%, transparent); }
.rf-quand { font-weight: 650; font-size: 13.5px; text-transform: capitalize; }
.rf-badge { font-size: 10.5px; font-weight: 700; text-transform: uppercase;
            letter-spacing: .04em; padding: 1px 8px; border-radius: 999px;
            color: var(--sem-defaut-t); background: var(--sem-defaut-bg);
            border: 1px solid var(--sem-defaut); }
/* Deux colonnes : l'intitulé cadré à gauche, la valeur en face. Une fiche se
   parcourt du regard, elle ne se lit pas en phrases. */
.rf-liste { display: grid; grid-template-columns: 140px minmax(0, 1fr);
            gap: 7px 14px; margin: 0; font-size: 13px; }
.rf-liste dt { color: var(--ink-2); font-size: 12px; }
.rf-liste dd { margin: 0; min-width: 0; }
.rf-liste dd .pastille { display: inline-block; width: 9px; height: 9px;
                         border-radius: 50%; margin-right: 7px; vertical-align: 1px; }
.rf-rep { white-space: pre-line; color: var(--ink-2); }

/* ── Fiche client ────────────────────────────────────────────────────────── */
.fc-ident { display: flex; align-items: center; gap: 14px; }
.fc-ava { display: inline-flex; align-items: center; justify-content: center;
          width: 44px; height: 44px; flex: none; border-radius: 50%;
          background: var(--sem-vente-bg); color: var(--sem-vente-t);
          font-weight: 700; font-size: 15px; letter-spacing: .02em; }
.fc-coord { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }

/* La seule carte accentuée de la page : la mémoire historique. C'est ce que
   l'équipe sait et qui n'est écrit dans aucun autre système. */
.card-accent { border-color: var(--accent); }
.fc-note { padding: 7px 0; border-bottom: 1px solid var(--hairline); }
.fc-note:last-of-type { border-bottom: 0; }
.fc-note p { margin: 4px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--ink); }
.fc-form { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--hairline); }

/* Les réponses du prospect, sous son rendez-vous : c'est le contexte qu'on
   relit juste avant de rappeler. */
.fc-rep td { padding-top: 0 !important; font-size: 11.5px; color: var(--ink-2);
             white-space: pre-line; border-top: 0 !important; }

/* Réponses du formulaire, en paires question / réponse. Un pavé de texte où
   la question et la réponse se suivent au fil ne se lit pas : un closer doit
   pouvoir y trouver le budget d'un coup d'œil. */
.rf-rep-bloc { margin-top: 14px; padding-top: 12px;
               border-top: 1px solid var(--hairline); }
.rf-rep-titre { font-size: 11px; text-transform: uppercase; letter-spacing: .05em;
                color: var(--muted); margin-bottom: 8px; }
.rf-qa { margin: 0; display: flex; flex-direction: column; gap: 9px; }
.rf-qa dt { font-size: 11.5px; color: var(--ink-2); line-height: 1.4; }
.rf-qa dd { margin: 2px 0 0; font-size: 13px; font-weight: 600; color: var(--ink);
            white-space: pre-line; line-height: 1.45;
            padding-left: 10px; border-left: 2px solid var(--hairline); }

/* ── Sommaire du tutoriel (dès la deuxième visite) ───────────────────────── */
.tour-menu {
  position: fixed; z-index: 10001; left: 50%; top: 50%;
  transform: translate(-50%, -50%); width: min(430px, calc(100vw - 32px));
  background: var(--surface); border-radius: 14px; padding: 20px 22px;
  box-shadow: 0 18px 60px rgba(0, 0, 0, .28); display: none;
}
.tour-chaps { display: flex; flex-direction: column; gap: 5px; margin: 14px 0 4px;
              max-height: 46vh; overflow-y: auto; }
.tour-chap {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  width: 100%; text-align: left; padding: 9px 12px; border-radius: 9px;
  border: 1px solid var(--hairline); background: var(--surface);
  font: inherit; font-size: 13.5px; color: var(--ink); cursor: pointer;
}
.tour-chap:hover { border-color: var(--accent); background: var(--sem-vente-bg); }
.tour-chap small { flex: none; font-size: 11px; color: var(--muted); }
.tour-menu .tour-foot { justify-content: space-between; margin-top: 14px;
                        padding-top: 14px; border-top: 1px solid var(--hairline); }



/* ══════════════════════════════════════════ Suivi closing (préventes)
   L'écran qui remplace le tableau Nextcloud des closers.

   Le choix qui structure tout : ce que le prospect a écrit en réservant et ce
   que le closer saisit ne se ressemblent pas. La première moitié est posée sur
   un fond teinté, sans un seul champ ; la seconde est faite de champs. On voit
   donc, sans lire, ce qu'on n'a plus à retaper — c'est la promesse de l'écran.

   Les étapes suivent une PROGRESSION de teintes, pas dix couleurs au hasard :
   gris (rien encore) → bleu (en travail) → ambre (ça résiste) → violet
   (engagée) → turquoise (acompte) → vert (vendue), avec le rouge réservé au
   remboursement. Ce sont les jetons sémantiques de la plateforme, donc un
   « vendue » vert se lit comme le « encaissé » vert du registre. */

/* ── Le tableau : ce qui se balaie ──
   Une rangée = une ligne de texte, jamais deux. Le tableau doit tenir dans un
   écran : c'est ce qui permet de balayer quinze prospectes sans faire défiler,
   et c'est exactement ce que la feuille de calcul ne savait pas faire. */
.pv-table { table-layout: fixed; width: 100%; }
.pv-table th, .pv-table td { padding: 3px 9px; font-size: 12.5px;
                             vertical-align: middle; white-space: nowrap;
                             overflow: hidden; text-overflow: ellipsis; }
.pv-table th { font-size: 11px; }
/* La ligne n'est plus cliquable dans son ensemble : la fiche s'ouvre par le
   crayon. Un curseur en main sur une rangée qui ne fait rien promet un geste
   qui n'existe pas. */
.pv-ligne { cursor: default; }
/* Un rendez-vous à venir : la date est là, mais elle ne raconte pas la même
   chose qu'une rencontre passée. Discret — c'est une nuance, pas une alerte. */
.pv-d-venir { color: var(--accent-strong); font-weight: 600; }
/* Le temps de l'aller-retour : la ligne s'estompe légèrement. Assez pour dire
   « c'est parti », pas assez pour clignoter sur un réseau rapide. */
.pv-ligne.pv-envoi > td { opacity: .55; transition: opacity .12s; }
.pv-ligne:hover > td { background: var(--page); }

/* Largeurs déclarées PARTOUT SAUF sur « prochaine étape », qui absorbe le
   reste. Avec `table-layout: fixed`, si toutes les colonnes sont dimensionnées
   et que leur somme n'atteint pas la largeur du tableau, le navigateur étire
   la dernière : c'est ce qui laissait une bande vide traversée de filets à
   droite de la colonne RDV. Une seule colonne élastique, et le tableau se
   ferme sur son bord quel que soit l'écran. */
/* HH-2580 — la colonne élastique est « Prochaine étape », plus « Prospect ».
   Avec `table-layout: fixed`, la colonne SANS largeur absorbe ce qui reste —
   et quand il ne reste rien, elle tombe à zéro. Sur l'écran de Laure
   (MacBook Air, 1 150 px utiles), c'est le NOM du prospect qui disparaissait :
   « je ne vois plus les prénoms et noms ». Céline, sur un écran plus large,
   les voyait — d'où « étrange ».
   Le nom a donc sa largeur, garantie ; ce qui s'étire ou se tronque est la
   prochaine étape, qui se lit aussi dans la fiche. Et le tableau porte une
   largeur minimale : sous elle, il DÉFILE au lieu de s'écraser. */
.pv-table { min-width: 1240px; }
.pv-table .c-qui   { width: 220px; }
.pv-table .c-next  { width: auto; min-width: 150px; }
.pv-table .c-bud   { width: 140px; }
.pv-table .c-acc   { width: 140px; }
.pv-table .c-fat   { width: 170px; }
/* Une pastille d'initiales, pas un nom : 116 px pour afficher
   « Virginie Mo… » servaient surtout à tronquer. Le nom complet est au
   survol, et les pixels rendus vont à la colonne de l'appel. */
.pv-table .c-clo   { width: 58px; text-align: center; }
/* 132 px suffisent : l'étiquette la plus longue (« Annulé ou non honoré ») y
   tient à 11 px, et les vingt-six pixels rendus vont à la colonne « Appel »,
   où un lien tronqué ne se reconnaît plus. */
.pv-table .c-eta   { width: 132px; }
.pv-table .c-pro   { width: 64px; }
/* 76px coupaient « 13/09/26 » d'un cheveu. Les chiffres tabulaires
   alignent en plus les dates les unes sous les autres. */
.pv-table .c-rdv   { width: 92px; font-variant-numeric: tabular-nums; }
/* Quatre gestes sur une ligne signalée : 4 × 26 px + 3 écarts + le
   rembourrage. À 96 px ils débordaient et emportaient le tableau avec eux. */
.pv-table .c-act   { width: 124px; }
/* Écran étroit : on resserre ce qui peut l'être avant de faire défiler. Le
   nom, lui, ne bouge pas — c'est par lui qu'on reconnaît une ligne. */
@media (max-width: 1400px) {
  .pv-table { min-width: 1120px; }
  .pv-table th, .pv-table td { padding-left: 7px; padding-right: 7px; }
  .pv-table .c-eta { width: 120px; }
  .pv-table .c-acc { width: 124px; }
  .pv-table .c-fat { width: 140px; }
  .pv-table .c-bud { width: 118px; }
  .pv-table .c-qui { width: 196px; }
}

/* La pastille du closer : ses initiales sur SA teinte, celle qu'il porte déjà
   sur le calendrier. Une colonne de pastilles se balaie — « les trois bleues
   sont à Rémi » se voit sans lire —, ce qu'une colonne de noms tronqués au
   même endroit ne permettait pas. La teinte arrive en variable : le fond, le
   texte et le liseré en descendent tous les trois. */
.pv-ava {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 50%;
  font-size: 9.5px; font-weight: 700; letter-spacing: .02em;
  background: color-mix(in srgb, var(--cc) 16%, transparent);
  color: color-mix(in srgb, var(--cc) 72%, #000 28%);
  border: 1px solid color-mix(in srgb, var(--cc) 32%, transparent);
  cursor: default; transition: transform .12s, box-shadow .12s;
}
.pv-ligne:hover .pv-ava { transform: translateY(-1px);
  box-shadow: 0 2px 6px color-mix(in srgb, var(--cc) 30%, transparent); }
/* Sans closer : un tiret creux, qui se distingue d'une initiale sans crier. */
.pv-ava.sans { background: transparent; color: var(--muted);
  border: 1px dashed var(--hairline); font-weight: 400; font-size: 12px; }
.pv-ligne:hover .pv-ava.sans { transform: none; box-shadow: none; }

/* L'étape se change dans le tableau. La liste porte elle-même la couleur de
   l'étape : le badge et le contrôle sont le même objet, donc on lit et on
   modifie au même endroit, sans que la ligne grandisse. */
.pv-table .c-eta form { margin: 0; }
select.pv-etape {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 22px; padding: 0 20px 0 9px; margin: 0;
  border-radius: 999px; border: 1px solid transparent;
  font: inherit; font-size: 11px; font-weight: 600; letter-spacing: -.1px;
  line-height: 20px; cursor: pointer; text-overflow: ellipsis;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='9' height='6' viewBox='0 0 9 6'%3E%3Cpath d='M1 1l3.5 3.5L8 1' fill='none' stroke='%23000' stroke-opacity='.45' stroke-width='1.4' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 7px center;
}
select.pv-etape:hover { filter: brightness(.965); }
select.pv-etape:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
/* Le menu déroulant lui-même reste sur fond neutre : les options héritent
   sinon la teinte de l'étape courante et deviennent illisibles. */
select.pv-etape option { background: var(--surface); color: var(--ink);
                         font-weight: 400; }

/* Nom et e-mail sur la même ligne : le nom porte, l'adresse suit en retrait. */
/* Le voyant « sans nouvelles » porte le NOMBRE DE JOURS : « 40 j » se juge
   d'un coup d'œil, un simple triangle d'alerte ne se juge pas. Il précède le
   nom, là où l'œil descend la colonne. */
/* Les gestes de la ligne portent leur couleur AU REPOS, pas seulement au
   survol : dans une colonne de quatre icônes grises, on doit reconnaître
   « écarter » sans le viser. Les teintes sont celles de la plateforme — bleu
   pour ce qui ouvre, vert pour ce qui touche à l'argent, ambre pour ce qui
   reporte, rouge pour ce qui referme. */
.pv-table .icon-btn { border-color: transparent; }
.pv-table .icon-btn:hover { filter: none; }
.pv-a-suivi   { color: var(--sem-vente-t);   background: var(--sem-vente-bg); }
.pv-a-vente,
.pv-a-vendre  { color: var(--sem-facture-t); background: var(--sem-facture-bg); }
.pv-a-garder  { color: var(--sem-attente-t); background: var(--sem-attente-bg); }
.pv-a-ecarter { color: var(--sem-defaut-t);  background: var(--sem-defaut-bg); }
.pv-a-fiche   { color: var(--muted);         background: var(--page); }
.pv-table .icon-btn:hover  { filter: brightness(.94); }
.pv-a-suivi:hover   { border-color: #cfe0f6; }
.pv-a-vente:hover,
.pv-a-vendre:hover  { border-color: #bfe4cd; }
.pv-a-garder:hover  { border-color: #f0dcb4; }
.pv-a-ecarter:hover { border-color: #f2ccc4; }
.pv-a-fiche:hover   { border-color: var(--hairline); }

/* La date, à l'autre bout de la ligne, porte le même signal que le voyant. */
.pv-d-tard  { color: var(--sem-attente-t); font-weight: 650; }
.pv-d-grave { color: var(--sem-defaut-t);  font-weight: 650; }

.pv-alerte { display: inline-block; margin-right: 7px; padding: 0 6px;
             border-radius: 5px; background: var(--sem-attente-bg);
             border: 1px solid #f0dcb4; color: var(--sem-attente-t);
             font-size: 10.5px; font-weight: 700; line-height: 16px;
             font-variant-numeric: tabular-nums; vertical-align: 1px; }
/* Deux paliers : à trois semaines c'est un rappel (ambre), au-delà de quatre
   mois sur un dossier qui annonçait une action, c'est perdu (rouge). Une seule
   couleur pour les deux ne dirait ni l'un ni l'autre. */
.pv-alerte.grave { background: var(--sem-defaut-bg); border-color: #f2ccc4;
                   color: var(--sem-defaut-t); }
.btn.alerte b { margin-left: 5px; font-variant-numeric: tabular-nums; }
.pv-qui b { font-weight: 650; }
.pv-mail { margin-left: 7px; font-size: 11px; color: var(--muted); }
.pv-dot { display: inline-block; width: 8px; height: 8px; border-radius: 2.5px;
          margin-right: 6px; vertical-align: 0; flex: none; }
/* La colonne venue de Calendly : en italique et en retrait. Personne de
   l'équipe ne l'a tapée, et ça doit se voir sans explication. */
.pv-auto { font-style: italic; color: var(--ink-2); font-size: 12px; }

/* Jauge de probabilité : cinq segments. Dans une colonne, une jauge se compare
   d'un coup d'œil là où « 4/5 » doit être lu ligne par ligne. */
.pv-jauge { display: inline-flex; gap: 2px; }
.pv-jauge i { width: 4px; height: 11px; border-radius: 1.5px;
              background: var(--hairline); }
.pv-jauge i.on { background: var(--sem-vente); }

/* Onglets d'état : le tableau des lignes vives et celui de l'historique ne
   sont pas le même tableau. Posés au-dessus de la barre de filtres — on choisit
   d'abord DE QUOI on parle, on affine ensuite. */
.pv-onglets { display: flex; gap: 2px; margin-bottom: 12px;
              border-bottom: 1px solid var(--hairline); }
.pv-onglet { display: inline-flex; align-items: center; gap: 7px;
             padding: 6px 13px 8px; font-size: 13px; font-weight: 600;
             color: var(--muted); border-bottom: 2px solid transparent;
             margin-bottom: -1px; white-space: nowrap; }
.pv-onglet:hover { color: var(--ink); text-decoration: none; }
.pv-onglet.on { color: var(--ink); border-bottom-color: var(--accent); }
.pv-onglet-n { padding: 1px 7px; border-radius: 999px; background: var(--page);
               border: 1px solid var(--hairline); font-size: 11px;
               font-weight: 700; color: var(--muted);
               font-variant-numeric: tabular-nums; }
.pv-onglet.on .pv-onglet-n { background: var(--accent-soft);
                             border-color: var(--accent-soft);
                             color: var(--sem-vente-t); }

/* ── L'étape ── */
/* Dans la fiche, l'étape reste un <select> ordinaire du formulaire : c'est
   là qu'on prend le temps, pas là qu'on trie. */
.et-rdv_a_venir  .pv-etape { background-color: var(--sem-ops-bg);     color: var(--sem-ops-t);     border-color: #dbdfe5; }
.et-en_cours     .pv-etape { background-color: var(--sem-vente-bg);   color: var(--sem-vente-t);   border-color: #cfe0f6; }
.et-a_nurturer   .pv-etape { background-color: var(--sem-attente-bg); color: var(--sem-attente-t); border-color: #f0dcb4; }
.et-engagee      .pv-etape { background-color: var(--sem-care-bg);    color: var(--sem-care-t);    border-color: #ddd3f5; }
.et-acompte      .pv-etape { background-color: var(--sem-acces-bg);   color: var(--sem-acces-t);   border-color: #bfe4e8; }
.et-vendue       .pv-etape,
.et-vente_annexe .pv-etape { background-color: var(--sem-facture-bg); color: var(--sem-facture-t); border-color: #bfe4cd; }
.et-remboursee   .pv-etape { background-color: var(--sem-defaut-bg);  color: var(--sem-defaut-t);  border-color: #f2ccc4; }
/* Les deux sorties sans suite s'effacent : elles restent consultables mais ne
   doivent pas attirer l'œil dans une liste de travail. */
.et-non_close .pv-etape, .et-annule .pv-etape {
  background-color: var(--page); color: var(--muted); border-color: var(--hairline); }
.et-non_close > td, .et-annule > td { opacity: .62; }
.et-non_close:hover > td, .et-annule:hover > td { opacity: 1; }

.multi-wrap { position: relative; display: inline-block; }

/* ── La fiche : ce qui se remplit ──
   Trois zones, trois traitements, et on doit pouvoir les distinguer sans lire :
   le panneau bleuté (ce qui vient de Calendly, aucun champ), le bandeau de
   décision (l'étape et la probabilité, les deux seules choses qu'on change à
   chaque passage), et le formulaire proprement dit. Sans cette hiérarchie, les
   dix-huit champs se valaient tous et l'écran devenait un mur gris. */
.modal-box.pv-box { width: min(1060px, 96vw); max-height: 90vh;
                    display: flex; flex-direction: column; padding: 0;
                    overflow: hidden; }
.pv-head { flex: none; margin: 0; padding: 14px 18px;
           border-bottom: 1px solid var(--hairline); }
.pv-head .pv-titre { flex: 0 1 auto; font-size: 16.5px; font-weight: 650;
                     letter-spacing: -.01em; min-width: 0;
                     overflow: hidden; text-overflow: ellipsis;
                     white-space: nowrap; }
.pv-head-closer { display: inline-flex; align-items: center; gap: 6px;
                  margin-left: 12px; padding: 2px 10px 2px 8px;
                  border-radius: 999px; background: var(--page);
                  border: 1px solid var(--hairline);
                  font-size: 12px; font-weight: 500; color: var(--ink-2); }
.pv-head .modal-close { margin-left: auto; }
.pv-corps { flex: 1; min-height: 0; display: grid;
            grid-template-columns: 268px 1fr;
            grid-template-rows: 1fr auto; overflow: hidden; }

/* ── La moitié « déjà connue ». Fond teinté, aucun champ : on ne la saisit pas. */
.pv-calendly { grid-row: 1; display: flex; flex-direction: column;
               padding: 16px 18px; overflow-y: auto;
               background: var(--sem-vente-bg);
               border-right: 1px solid #cfe0f6; }
.pv-src { align-self: flex-start; margin-bottom: 13px; padding: 3px 10px;
          border-radius: 999px; background: var(--surface);
          border: 1px solid #cfe0f6; color: var(--sem-vente-t);
          font-size: 10px; font-weight: 700; letter-spacing: .07em;
          text-transform: uppercase; }
.pv-mail-l { display: block; font-size: 12.5px; word-break: break-word;
             color: var(--sem-vente-t); }

/* Le budget en grand : c'est le chiffre qu'on cherche en rouvrant un dossier. */
.pv-hero { margin: 14px 0; padding: 11px 13px; border-radius: 10px;
           background: var(--surface); border: 1px solid #d3e3f8; }
.pv-hero-l { display: block; font-size: 10px; font-weight: 700;
             letter-spacing: .07em; text-transform: uppercase;
             color: var(--sem-vente-t); opacity: .72; }
.pv-hero-v { display: block; margin-top: 3px; font-size: 17px; font-weight: 650;
             letter-spacing: -.015em; color: var(--ink); line-height: 1.25; }

.pv-bloc { padding-top: 12px; margin-top: 12px; border-top: 1px solid #d3e3f8; }
.pv-bloc:first-of-type { border-top: 0; }
.pv-bloc-t { font-size: 10px; font-weight: 700; letter-spacing: .07em;
             text-transform: uppercase; color: var(--sem-vente-t);
             opacity: .72; margin-bottom: 5px; }
.pv-bloc p { margin: 0; font-size: 12.5px; line-height: 1.5;
             white-space: pre-line; }

/* Les réponses du formulaire : chaque question porte son intitulé. Un pavé où
   l'on ne distingue plus la question de la réponse, c'est exactement ce qu'on
   relit mal juste avant d'appeler. */
.pv-qa { margin: 0; font-size: 12.5px; }
.pv-qa dt { font-size: 11px; line-height: 1.35; color: var(--sem-vente-t);
            opacity: .72; margin-top: 8px; }
.pv-qa dt:first-child { margin-top: 0; }
.pv-qa dd { margin: 1px 0 0; color: var(--ink); line-height: 1.45;
            white-space: pre-line; }
.pv-qa dd.seul { margin-top: 0; }
.pv-qa dd.seul + dd.seul { margin-top: 3px; }
.pv-rien { margin: 12px 0 0; font-size: 12px; line-height: 1.5;
           color: var(--sem-vente-t); opacity: .8; font-style: italic; }

.pv-rdv { list-style: none; margin: 0; padding: 0; font-size: 12.5px; }
.pv-rdv li { display: flex; justify-content: space-between; gap: 8px;
             align-items: baseline; padding: 4px 0; }
.pv-rdv li + li { border-top: 1px solid #dceaf9; }
.pv-rdv span { color: var(--sem-vente-t); opacity: .7; font-size: 11px;
               white-space: nowrap; }
.pv-rdv-import { margin: 0; font-size: 12.5px; line-height: 1.45;
                 color: var(--ink); }

/* Le journal : la date d'abord, l'action ensuite, l'auteur en dernier et en
   retrait. On y cherche « quand » et « quoi » — le « qui » ne compte que
   lorsqu'on a trouvé les deux autres. */
.pv-journal { list-style: none; margin: 0; padding: 0; font-size: 12px; }
.pv-journal li { padding: 5px 0; line-height: 1.4; }
.pv-journal li + li { border-top: 1px solid #dceaf9; }
.pv-journal span { display: block; font-size: 10.5px; color: var(--sem-vente-t);
                   opacity: .7; font-variant-numeric: tabular-nums; }
.pv-journal b { font-weight: 500; color: var(--ink); }
.pv-journal i { font-style: normal; color: var(--muted); font-size: 11px;
                margin-left: 5px; }
/* Le lien de sortie est poussé en bas du panneau : c'est une porte, pas une
   information, et il ne doit pas s'intercaler entre deux faits. */
.pv-lien { margin-top: auto; padding-top: 16px; font-size: 12px;
           color: var(--sem-vente-t); white-space: nowrap; }

/* ── La moitié qui se saisit ── */
.pv-saisie { grid-row: 1; padding: 16px 18px 6px; overflow-y: auto; }

/* Le bandeau de décision : l'acte, séparé de la documentation. */
.pv-etat { display: flex; gap: 16px; align-items: flex-start; flex-wrap: wrap;
           padding: 12px 14px; margin-bottom: 14px; border-radius: 11px;
           background: var(--page); border: 1px solid var(--hairline); }
.pv-etat-c { flex: 1; min-width: 190px; }
.pv-etat-l { display: block; margin-bottom: 5px; font-size: 10.5px;
             font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
             color: var(--muted); }
.pv-saisie select.pv-etat-sel { height: 34px; padding: 0 30px 0 11px;
                                font-size: 13.5px; font-weight: 600;
                                background-color: var(--surface); }

/* La probabilité est une échelle : on la montre, on ne la déroule pas. */
.pv-proba { display: inline-flex; border: 1px solid var(--hairline);
            border-radius: 9px; overflow: hidden; background: var(--surface);
            height: 34px; }
.pv-proba label { position: relative; display: block; cursor: pointer; }
.pv-proba label + label i { border-left: 1px solid var(--hairline); }
.pv-proba input { position: absolute; inset: 0; opacity: 0; margin: 0;
                  width: 100%; height: 100%; cursor: pointer; }
.pv-proba i { display: flex; align-items: center; justify-content: center;
              min-width: 34px; height: 32px; font-style: normal;
              font-size: 13px; font-weight: 600; color: var(--ink-2);
              font-variant-numeric: tabular-nums;
              transition: background-color .12s, color .12s; }
.pv-proba label:hover i { background: var(--page); }
.pv-proba input:checked + i { background: var(--sem-vente);
                              border-left-color: var(--sem-vente);
                              color: #fff; }
.pv-proba input:focus-visible + i { outline: 2px solid var(--accent);
                                    outline-offset: -2px; }

/* Les exemples doivent se distinguer d'une valeur AU PREMIER COUP D'ŒIL.
   « Rennes » ou « lundi 9 mars » en gris plein se lisent comme des données
   saisies : on croit l'écran rempli, puis cassé quand on comprend que non. */
.pv-saisie ::placeholder { color: var(--muted); opacity: .5; font-style: italic; }

.pv-neuf { margin: -4px 0 13px; padding: 8px 11px; border-radius: 9px;
           background: var(--sem-attente-bg); border: 1px solid #f0dcb4;
           color: var(--sem-attente-t); font-size: 12px; line-height: 1.5; }

.pv-suite { margin-bottom: 14px; }

/* Les groupes : un intitulé en petites capitales, et un filet qui s'arrête
   avant le texte au lieu de le traverser. */
.pv-grp { border: 0; margin: 0 0 14px; padding: 0; min-width: 0; }
.pv-grp > legend { display: flex; align-items: center; gap: 9px; width: 100%;
                   padding: 0 0 9px; font-size: 10.5px; font-weight: 700;
                   letter-spacing: .06em; text-transform: uppercase;
                   color: var(--muted); }
.pv-grp > legend::after { content: ""; flex: 1; height: 1px;
                          background: var(--hairline); }
.pv-grp .form-row { margin-bottom: 9px; }
.pv-grp .form-row:last-child { margin-bottom: 0; }

/* Les champs : plus bas, plus discrets, posés sur le fond de page. Le
   sélecteur doit battre `input[type=text]` (0,1,1) — d'où les deux classes. */
.pv-saisie .form-row > label { font-size: 11.5px; font-weight: 600;
                               color: var(--muted); }
.pv-saisie .form-row > label input,
.pv-saisie .form-row > label textarea,
.pv-saisie .form-row > label select {
  margin-top: 3px; padding: 6px 9px; font-size: 13px; border-radius: 8px;
  background-color: var(--page); }
.pv-saisie .form-row > label input:focus,
.pv-saisie .form-row > label textarea:focus,
.pv-saisie .form-row > label select:focus { background-color: var(--surface); }
.pv-saisie textarea { resize: vertical; min-height: 36px; line-height: 1.45; }

.pv-pied { grid-column: 1 / -1; grid-row: 2; display: flex; gap: 8px;
           align-items: center; padding: 12px 18px;
           border-top: 1px solid var(--hairline); background: var(--surface); }
.pv-devine { margin: 2px 0 0; }

@media (max-width: 860px) {
  .pv-corps { grid-template-columns: 1fr; grid-template-rows: auto 1fr auto; }
  .pv-calendly { grid-row: auto; border-right: 0;
                 border-bottom: 1px solid #cfe0f6; }
  .pv-saisie { grid-row: auto; }
}

/* ── Regroupement par closer ──
   Un bandeau DANS le tableau, pas un tableau par closer : une seule grille,
   donc les colonnes restent alignées d'un paquet à l'autre et l'en-tête reste
   collé en haut. C'est ce qui permet de comparer deux closers d'un coup d'œil
   — des tableaux séparés obligeraient à mesurer les colonnes de l'œil. */
.pv-grp-tete > td {
  /* Compact : c'est une étiquette, pas un titre de section. La respiration
     entre paquets vient de la bordure haute, pas du rembourrage — le cumul
     des deux donnait un bandeau plus épais que trois lignes du tableau. */
  padding: 6px 13px 5px !important;
  /* Repli d'abord, pour les navigateurs sans `color-mix` : ils gardent le
     bandeau gris d'avant plutôt qu'un fond transparent. */
  background: var(--page);
  background: linear-gradient(
      to right,
      color-mix(in srgb, var(--grp, var(--muted)) 11%, var(--surface)) 0%,
      color-mix(in srgb, var(--grp, var(--muted)) 4%, var(--surface)) 62%,
      var(--surface) 100%);
  /* Le liseré à gauche, pleine teinte : c'est lui qui identifie, la teinte de
     fond ne fait que le prolonger. Trois signaux (liseré, fond, nom) valent
     mieux qu'une bande saturée en travers du tableau — celle-ci entrerait en
     concurrence avec l'ambre et le rouge des alertes, qui doivent primer. */
  box-shadow: inset 3px 0 0 var(--grp, var(--muted));
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid color-mix(in srgb, var(--grp, var(--muted)) 22%,
                                     var(--hairline));
  white-space: nowrap; overflow: visible !important;
}
.pv-grp-tete:first-child > td { border-top: 0; }
.pv-grp-tete b {
  font-size: 13px; font-weight: 680; letter-spacing: -.015em;
  color: var(--ink);
  color: color-mix(in srgb, var(--grp, var(--ink)) 74%, var(--ink));
}
.pv-grp-n { margin-left: 10px; font-size: 11.5px; color: var(--muted);
            font-variant-numeric: tabular-nums; }
/* Les compteurs du bandeau portent les mêmes couleurs que les lignes qu'ils
   résument : vert pour ce qui est conclu, ambre pour ce qui dort. */
.pv-grp-tag { margin-left: 7px; padding: 0 7px; border-radius: 999px;
              font-size: 10px; font-weight: 700; line-height: 15px;
              display: inline-block; vertical-align: 1px;
              font-variant-numeric: tabular-nums; }
.pv-grp-tag.conclu { background: var(--sem-facture-bg); color: var(--sem-facture-t);
                     border: 1px solid #bfe4cd; }
.pv-grp-tag.alerte { background: var(--sem-attente-bg); color: var(--sem-attente-t);
                     border: 1px solid #f0dcb4; }

/* ── La recherche : à part, à droite, et reconnaissable ──
   Les filtres répondent à « quelles lignes ? », elle à « laquelle ? ». Dans la
   même rangée et de la même forme, on les prend pour la même chose. */
.pv-chercher { display: inline-flex; align-items: center; gap: 7px;
               margin-left: auto; height: 30px; padding: 0 11px;
               border: 1px solid var(--hairline); border-radius: 999px;
               background: var(--surface); color: var(--muted);
               transition: border-color .15s, box-shadow .15s; }
.pv-chercher:focus-within { border-color: var(--accent);
                            box-shadow: 0 0 0 3px var(--accent-soft); }
.pv-chercher input {
  width: 236px; height: 26px; padding: 0; margin: 0; font-size: 12.5px;
  border: 0; background: none; color: var(--ink); outline: none;
}
.pv-chercher input::-webkit-search-cancel-button { cursor: pointer; }
.pv-chercher-etat { font-size: 11px; color: var(--muted); min-width: 10px; }

/* ── Respiration entre closers ──
   Une ligne vide et transparente entre deux paquets : sans elle, le bandeau
   d'un closer se lit comme une ligne du précédent. Elle passe par une bordure
   haute épaisse et non par un `box-shadow` — celui-ci est déjà pris par le
   liseré de couleur, et l'un aurait effacé l'autre. */
.pv-table tr.pv-grp-tete:not(:nth-child(2)) > td {
  border-top: 8px solid var(--page);
}

/* ── Couleur dans les listes déroulantes ──
   Un champ rempli doit ressembler à ce qu'on verra dans le tableau une fois
   la vente enregistrée. Deux formes, parce que ce ne sont pas les mêmes
   choses : une PASTILLE pour ce qui EST une couleur (le closer, qui a la
   sienne sur le calendrier et le suivi closing), et la teinte de l'étiquette
   entière pour ce qui se lit comme une étiquette (le canal de vente, qui a
   déjà sa pastille colorée dans le registre). */
.sel-swatch { width: 9px; height: 9px; border-radius: 3px; flex: none;
              display: inline-block; margin-right: 8px; vertical-align: 0; }
.combo.sel-search { position: relative; }
.sel-swatch-cur { position: absolute; left: 11px; top: 50%; width: 9px;
                  height: 9px; border-radius: 3px; margin-top: -4.5px;
                  pointer-events: none; z-index: 1; }
.combo.sel-search.a-pastille .combo-input { padding-left: 28px; }

/* Le canal reprend exactement les teintes de sa pastille du registre. */
.combo-input.c-woo        { background: #f3e8fa; color: #6b2f8f; border-color: #ddc2ec; }
.combo-input.c-systemeio  { background: #e2f6ee; color: #0c6b4a; border-color: #b5e6d3; }
.combo-input.c-stripe_link{ background: #e9f1fc; color: #1c5cab; border-color: #c4dcf6; }
.combo-input.c-virement   { background: #fdf3dc; color: #8a5f00; border-color: #f3dda6; }
.combo-input.c-cheque     { background: var(--page); color: var(--ink-2); }
.combo-input[class*="c-"]:focus { background: var(--surface); }


/* ── Catalogue : la colonne « Où elle se vend » ──
   Calculée, jamais saisie. Elle peut porter deux boutiques à la fois — c'est
   précisément ce que l'ancien onglet « origine » ne savait pas dire. */
.prod-liste .prod-ou { width: 168px; white-space: nowrap; }
.prod-liste .prod-ou .canal { margin: 1px 3px 1px 0; vertical-align: middle; }
/* « Ce qu'elle déclenche » : pictogramme + mot, un seul gris, une ligne. */
.prod-effets { display: flex; flex-wrap: wrap; align-items: center; gap: 3px 12px; }
.prod-effet { display: inline-flex; align-items: center; gap: 4px; font-size: 11.5px;
              color: var(--ink-2); white-space: nowrap; }
.prod-effet svg { color: var(--muted); flex: none; }
.prod-effet.muette, .prod-effet.muette svg { color: var(--sem-attente-t); }
.prod-liste .prod-id { font-variant-numeric: tabular-nums; }

/* Le catalogue a SIX colonnes depuis qu'il dit aussi où chaque offre se vend :
   à 920 px (la largeur d'« Animateurs », dont il partage la classe) la
   colonne d'actions se faisait couper. Largeur propre, pour ne pas étirer un
   modal de trois lignes en même temps. */
.modal-box.prod-box { width: min(1240px, 96vw); }
.prod-box .prod-liste { table-layout: auto; width: 100%; }
.prod-box .prod-liste .ev-actions { white-space: nowrap; }

/* ── Choisir le fournisseur d'une offre ──
   On part de SON catalogue vers l'extérieur : « celle-ci se vend aussi sur
   WooCommerce, et c'est cette offre-là ». L'inverse — retrouver le produit
   derrière « OFFRE 997€ x 3 » — n'est pas une phrase qu'on peut dire.

   Deux temps dans la même boîte : d'abord OÙ, ensuite LAQUELLE. Le prix de
   NOTRE offre reste en tête pendant tout le second temps — c'est à lui qu'on
   compare les totaux, et le cacher obligerait à se souvenir d'un nombre. */
.modal-box.fr-box { width: min(760px, 95vw); max-height: 86vh;
                    display: flex; flex-direction: column; padding: 0;
                    overflow: hidden; }

.fr-tete { display: flex; align-items: flex-start; gap: 12px; flex: none;
           padding: 16px 20px 14px; border-bottom: 1px solid var(--hairline);
           background: var(--page); }
.fr-eyebrow { display: block; font-size: 10px; font-weight: 700;
              letter-spacing: .08em; text-transform: uppercase;
              color: var(--muted); }
.fr-titre-offre { display: block; margin-top: 3px; font-size: 16px;
                  font-weight: 650; letter-spacing: -.01em; line-height: 1.3; }
.fr-prix { display: flex; align-items: baseline; gap: 8px; margin-top: 4px;
           font-size: 12.5px; color: var(--muted); }
.fr-prix b { font-size: 14.5px; color: var(--ink); font-weight: 650;
             font-variant-numeric: tabular-nums; }

.fr-bloc { padding: 16px 20px; overflow-y: auto; }
.fr-bloc + .fr-bloc { padding-top: 0; }
/* « Elle se vend déjà ici » tient à sa taille : c'est un résumé de trois
   lignes. Avec `overflow-y: auto` hérité du bloc, il se partageait la hauteur
   avec la longue liste du dessous et se retrouvait haut de trente pixels,
   avec sa propre barre de défilement — on n'y voyait qu'un rattachement sur
   trois. Celle qui défile, c'est la liste des propositions. */
.fr-bloc[data-fr-deja] { flex: none; overflow: visible; }
.fr-titre { margin-bottom: 9px; font-size: 10.5px; font-weight: 700;
            letter-spacing: .06em; text-transform: uppercase;
            color: var(--muted); }
.fr-note { margin: 12px 0 0; padding: 10px 12px; border-radius: 9px;
           background: var(--page); font-size: 12px; line-height: 1.5;
           color: var(--muted); }

/* Premier temps : la boutique. Deux cartes qui se cliquent en entier — une
   cible de la taille d'un mot demande de viser. Celle sans clés reste
   VISIBLE mais éteinte : la faire disparaître ferait croire qu'elle
   n'existe pas. */
.fr-choix { display: flex; gap: 12px; flex-wrap: wrap; }
.fr-boutique { flex: 1; min-width: 160px; display: flex; align-items: center;
               justify-content: space-between;
               gap: 8px; padding: 9px 12px; border: 1px solid var(--hairline);
               border-radius: 10px; background: var(--surface); cursor: pointer;
               font: inherit; text-align: left;
               transition: border-color .15s, box-shadow .15s, transform .15s; }
.fr-boutique:hover { border-color: var(--accent); transform: translateY(-1px);
                     box-shadow: 0 4px 14px rgba(11, 11, 11, .08); }
.fr-b-haut { display: flex; align-items: center; justify-content: space-between; }
.fr-fleche { color: var(--muted); font-size: 15px; transition: transform .15s; }
.fr-boutique:hover .fr-fleche { transform: translateX(3px); color: var(--accent); }
.fr-boutique.off { opacity: .5; cursor: not-allowed; }
.fr-boutique.off:hover { border-color: var(--hairline); transform: none;
                         box-shadow: none; }
.fr-sous { font-size: 11.5px; line-height: 1.45; color: var(--muted); }

/* Ce qui est déjà rattaché : en tête, parce qu'on vient souvent retirer. */
.fr-liste { list-style: none; margin: 0; padding: 0; }
.fr-liste li { display: flex; align-items: center; gap: 9px; padding: 7px 0;
               font-size: 12.5px; }
.fr-liste li + li { border-top: 1px solid var(--hairline); }
.fr-liste form { margin: 0 0 0 auto; }
/* Le menu de la façon de payer : à côté du rattachement qu'il concerne, et
   pas poussé au bout de la ligne comme la croix. */
.fr-liste form.fr-plan-form { margin: 0 0 0 auto; }
.fr-liste form.fr-plan-form + form { margin-left: 9px; }
.fr-plan-form select { margin: 0; padding: 2px 22px 2px 8px; font-size: 11.5px;
                       min-width: 104px; }
/* Pas encore de façon de payer : le menu reste discret, il ne crie pas
   « — aucune — » comme une erreur sur chaque ligne. */
.fr-plan-form select:has(option[value=""]:checked) { color: var(--muted);
  border-color: transparent; background-color: transparent; }
.fr-plan-form select:has(option[value=""]:checked):hover,
.fr-plan-form select:focus { border-color: var(--hairline); }
.fr-info { display: inline-grid; place-items: center; width: 15px; height: 15px;
  margin-left: 5px; border-radius: 999px; border: 1px solid var(--hairline);
  font-size: 10px; text-transform: none; letter-spacing: 0; cursor: help;
  vertical-align: 1px; }
.fr-nom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
          max-width: 320px; }
.fr-meta { color: var(--muted); font-size: 11px; white-space: nowrap;
           font-variant-numeric: tabular-nums; }

/* Second temps : la liste, classée, avec la RAISON écrite sur chaque ligne —
   une proposition qu'on ne peut pas vérifier se valide au hasard. */
.fr-barre { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.fr-retour { font-size: 12px; font-weight: 600; color: var(--accent); }
.fr-retour:hover { text-decoration: none; opacity: .8; }
.fr-compte { margin-left: auto; font-size: 11.5px; color: var(--muted);
             font-variant-numeric: tabular-nums; }
.fr-chercher { display: flex; align-items: center; gap: 8px; height: 34px;
               padding: 0 12px; margin-bottom: 10px; border-radius: 999px;
               border: 1px solid var(--hairline); background: var(--surface);
               color: var(--muted); }
.fr-chercher:focus-within { border-color: var(--accent);
                            box-shadow: 0 0 0 3px var(--accent-soft); }
.fr-chercher input { flex: 1; height: 30px; padding: 0; margin: 0; border: 0;
                     background: none; font-size: 12.5px; color: var(--ink);
                     outline: none; }

.fr-props { list-style: none; margin: 0; padding: 0; }
/* ── Familles d'offres : une teinte par ligne (HH-2571) ──
   Onde, Wutao, Chant du Souffle, ATA… se reconnaissent à leur couleur, la
   même partout où une offre se range : le catalogue, le modal fournisseur.
   Catégoriel, donc hors de la palette sémantique — le vert reste à la
   facturation, l'ambre à l'attente. `--fam` est posé par la classe `fam-*`
   et lu par ce qui se colore. */
:root {
  --fam-onde: #2f6fb3; --fam-mouvement: #1f8a8a; --fam-chant: #7a4fb5;
  --fam-ata: #c2622e; --fam-voix: #b8407a; --fam-estudio: #d08a12;
  --fam-logistique: #6b7280; --fam-vide: #a8a49d;
}
.fam-onde { --fam: var(--fam-onde); }  .fam-mouvement { --fam: var(--fam-mouvement); }
.fam-chant { --fam: var(--fam-chant); } .fam-ata { --fam: var(--fam-ata); }
.fam-voix { --fam: var(--fam-voix); }   .fam-estudio { --fam: var(--fam-estudio); }
.fam-logistique { --fam: var(--fam-logistique); } .fam-vide { --fam: var(--fam-vide); }
.fr-fam-dot { flex: none; width: 10px; height: 10px; border-radius: 999px;
  background: var(--fam, var(--fam-vide));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--fam, var(--fam-vide)) 18%, transparent); }

/* Le tunnel en tête de chaque groupe : la couleur dit la ligne, le texte dit
   le tunnel (« Onde Wutao · Canada »), le chiffre dit combien il reste. */
.fr-props .fr-tunnel { display: flex; align-items: center; gap: 9px; margin: 18px 0 7px;
  padding: 0 2px; font-size: 12.5px; color: var(--ink); }
.fr-props .fr-tunnel:first-child { margin-top: 2px; }
.fr-props .fr-tunnel b { font-weight: 700; color: var(--fam, var(--ink)); }
.fr-tunnel-n { margin-left: auto; font-size: 11px; color: var(--muted);
  font-variant-numeric: tabular-nums; }

/* Une ligne rattachée : point de couleur, nom, tunnel dans la teinte de sa
   ligne. La croix n'arrive qu'au survol. */
.fr-liste li .fr-fam-dot { width: 8px; height: 8px; box-shadow: none; }
.fr-tunnel-nom { color: var(--muted); font-size: 11px; font-weight: 500;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 200px; }
.fr-liste li .sp-x { opacity: .3; }
.fr-liste li:hover .sp-x, .fr-liste li .sp-x:focus-visible { opacity: 1; }
.fr-prop form { margin: 0; }
.fr-prop + .fr-prop { margin-top: 4px; }
/* Le liseré à gauche est celui de la famille — même trait que le catalogue.
   En `box-shadow` et pas en `border-left` : la bordure change de couleur au
   survol et au coché, le liseré, lui, ne bouge pas. */
.fr-prop .fr-prop-btn { box-shadow: inset 3px 0 0 var(--fam, var(--fam-vide)); padding: 9px 12px 9px 36px; }
.fr-prop .fr-prop-btn > input[type=checkbox] { left: 13px; top: 12px; }
.fr-prop .fr-prop-meta { gap: 8px; margin-top: 4px; }
.fr-prop .fr-id { margin-left: auto; font-size: 10.5px; }
.fr-prop-btn { position: relative; display: block; width: 100%; text-align: left;
               font: inherit; padding: 11px 13px; border: 1px solid transparent;
               border-radius: 11px; background: var(--page); cursor: pointer;
               transition: border-color .15s, background .15s; }
.fr-prop-btn:hover { background: var(--surface); border-color: var(--accent); }
.fr-prop-nom { display: block; font-size: 13px; font-weight: 600;
               color: var(--ink); line-height: 1.35; padding-right: 84px; }
.fr-prop-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 7px;
                margin-top: 5px; font-size: 11px; color: var(--muted); }
.fr-montant { color: var(--ink-2); font-size: 12px;
              font-variant-numeric: tabular-nums; }
.fr-id { font-variant-numeric: tabular-nums; opacity: .75; }
.fr-raison { padding: 1px 8px; border-radius: 999px; background: var(--surface);
             border: 1px solid var(--hairline); }
/* La case à cocher, à gauche : c'est une LISTE OÙ L'ON COCHE, pas une suite
   de boutons. Une offre de WUTAO est trois produits de boutique ; le geste
   normal en désigne plusieurs, et le bouton unique est en bas.

   Elle est POSÉE sur la ligne, qui garde sa mise en page d'avant : en faire
   une colonne de flex rétrécissait l'intitulé, et « OFFRE 3497€ x 3 -
   Transmission MOUVEMENT WUTAO » se cassait en trois lignes. */
.fr-prop-btn { padding-left: 38px; }
.fr-prop-btn > input[type=checkbox] {
  position: absolute; left: 14px; top: 14px; margin: 0; cursor: pointer;
}
/* Cochée, la ligne se voit sans dépendre de la case : sur dix lignes on lit
   les fonds, pas les cases. */
.fr-prop:has(input:checked) .fr-prop-btn {
  background: var(--surface); border-color: var(--accent);
}
/* La phrase de l'IA : sur sa propre ligne, et à distance du galon
   « SUGGÉRÉE » qui flotte en haut à droite — sans cette marge, le texte
   passait dessous. */
.fr-motif-ia {
  display: block; margin-top: 6px; padding-right: 92px;
  font-size: 11.5px; line-height: 1.45; color: var(--sem-facture-t);
  font-style: italic;
}
/* Où ira la ligne : une constatation, en gris. Quand le plan manque, c'est
   une chose à faire, donc la couleur de l'attente — jamais du rouge : il ne
   s'est rien cassé. */
.fr-plan { padding: 1px 8px; border-radius: 999px; background: var(--surface);
           border: 1px solid var(--hairline); color: var(--ink-2);
           white-space: nowrap; }
.fr-plan.manque { background: var(--attention-bg); border-color: #efd9ad;
                  color: var(--sem-attente-t); }
.fr-creer { font-size: 12px; color: var(--ink-2); margin-right: auto;
            display: flex; align-items: center; gap: 6px; }
.fr-pied {
  display: flex; align-items: center; justify-content: flex-end; gap: 12px;
  margin-top: 12px; padding-top: 11px; border-top: 1px solid var(--hairline);
}
.fr-compte-choix { font-size: 12px; color: var(--muted);
                   font-variant-numeric: tabular-nums; }
/* La première quand le prix tombe juste : proposée, jamais appliquée. */
.fr-prop.suggeree .fr-prop-btn { background: var(--sem-facture-bg);
                                 border-color: #bfe4cd; }
.fr-prop.suggeree:has(input:checked) .fr-prop-btn { border-color: var(--sem-facture); }
.fr-prop.suggeree .fr-raison { background: var(--surface);
                               border-color: #bfe4cd;
                               color: var(--sem-facture-t); }
.fr-ruban { position: absolute; right: 13px; top: 11px; padding: 1px 9px;
            border-radius: 999px; background: var(--sem-facture);
            color: #fff; font-size: 9.5px; font-weight: 700;
            letter-spacing: .05em; text-transform: uppercase; }
.fr-vide { padding: 16px; font-size: 12.5px; color: var(--muted);
           line-height: 1.55; background: var(--page); border-radius: 10px; }

/* Le « + » qui rattache une boutique : un rond discret au bout de la ligne,
   pas un bouton pointillé sous la pastille. Il s'affirme au survol de la
   ligne — c'est là qu'on le cherche. */
.fr-ajouter { display: inline-flex; align-items: center; justify-content: center;
              width: 20px; height: 20px; margin-left: 2px; padding: 0; border-radius: 999px;
              border: 1px dashed var(--hairline); background: none; vertical-align: middle;
              color: var(--muted); font: inherit; font-size: 13px; line-height: 1;
              font-weight: 600; cursor: pointer; opacity: .55; transition: opacity .12s, border-color .12s, color .12s; }
tr:hover .fr-ajouter { opacity: 1; }
.fr-ajouter:hover, .fr-ajouter:focus-visible { border-style: solid; border-color: var(--accent);
                    color: var(--accent); opacity: 1; outline: none; }



/* ── Accès d'une personne ───────────────────────────────────────────────────
   Le modal fait quarante lignes s'il les ouvre toutes ; il en montre une. Le
   GROUPE règle 95 % des cas, les exceptions se déplient. C'est l'inverse de la
   première version, qui étalait tout et se lisait comme une console. */
.modal-box.acces-box { width: min(660px, 95vw); max-height: 88vh; }
.modal-chargement { padding: 34px; text-align: center; color: var(--muted);
  font-size: 12.5px; }

.acces-form { display: flex; flex-direction: column; gap: 12px; }
.acces-note { margin: 0 0 12px; padding: 9px 12px; border-radius: 9px;
  font-size: 11.5px; line-height: 1.45; color: var(--sem-vente-t);
  background: var(--sem-vente-bg); border: 1px solid #cfe0f6; }
.acces-sec > summary { font-size: 12.5px; }
.acces-sous { font-size: 10.5px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted); margin: 12px 0 4px; }

/* Une ligne = un droit. Le libellé, ce que ça donne aujourd'hui, et le choix.
   Sans le « aujourd'hui », « comme son groupe » ne répond pas à la question. */
.acces-ligne { display: flex; align-items: center; gap: 10px; padding: 4px 0;
  border-bottom: 1px solid var(--hairline); font-size: 12.5px; }
.acces-ligne:last-child { border-bottom: 0; }
.acces-lib { flex: 1; min-width: 0; }
.acces-etat { flex: none; font-size: 10.5px; padding: 1px 7px; border-radius: 999px;
  border: 1px solid var(--hairline); color: var(--muted); background: var(--page); }
.acces-etat.oui { color: var(--sem-facture-t); background: var(--sem-facture-bg);
  border-color: #bfe4cd; }
.acces-etat.non { color: var(--sem-attente-t); background: var(--sem-attente-bg);
  border-color: #f0dcb4; }

/* Trois états, pas deux : « comme son groupe » n'est pas « autorisé ». Les
   confondre empêche de rendre à quelqu'un ce que son groupe lui retire. */
.acces-trois { flex: none; display: inline-flex; border: 1px solid var(--hairline);
  border-radius: 8px; overflow: hidden; background: var(--surface); }
.acces-opt { font-size: 11px; padding: 3px 9px; cursor: pointer; color: var(--muted);
  border-right: 1px solid var(--hairline); white-space: nowrap;
  transition: background .12s, color .12s; }
.acces-opt:last-child { border-right: 0; }
.acces-opt:hover { background: var(--page); }
.acces-opt input { position: absolute; opacity: 0; width: 0; height: 0; }
.acces-opt.on { background: var(--accent); color: #fff; font-weight: 600; }
.acces-opt.on:hover { background: var(--accent-strong, var(--accent)); }

/* Les groupes : une liste courte qu'on ouvre deux fois par an. */
.grp-liste { display: flex; flex-direction: column; }
.grp { display: flex; align-items: center; gap: 10px; padding: 9px 0;
  border-bottom: 1px solid var(--hairline); }
.grp:last-child { border-bottom: 0; }
.grp-neuf { margin-top: 14px; border-top: 1px solid var(--hairline); padding-top: 14px; }


/* ── Groupes : une couleur, un pictogramme ──────────────────────────────────
   Un groupe se reconnaît d'abord à l'œil. « Gestionnaires » écrit quinze fois
   en gris dans le tableau ne distingue rien : on relit chaque ligne pour
   savoir qui est qui. La teinte vient de `--gc`, posée par le gabarit — un
   seul jeu de règles sert les huit couleurs, au lieu de huit classes. */
.grp-puce, .grp-filtre { --gc: var(--muted); }
.grp-puce { display: inline-flex; align-items: center; gap: 6px;
  font-size: 11.5px; font-weight: 600; padding: 2px 10px 2px 8px;
  border-radius: 999px; color: var(--gc);
  background: color-mix(in srgb, var(--gc) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--gc) 26%, transparent); }
.grp-puce.sans { color: var(--muted); background: var(--page);
  border-color: var(--hairline); }
.grp-puce svg { flex: none; }

/* La bande d'un paquet : elle range, elle ne crie pas. Un fond plein par
   groupe hacherait le tableau en sept blocs de couleur. */
.eq-bande td { background: var(--page); border-top: 1px solid var(--hairline);
  padding: 7px 10px !important; }

/* Le filtre par groupe porte sa couleur : c'est ce qui permet de retrouver le
   même groupe dans la barre, dans la colonne et dans le modal. */
.grp-filtre { display: inline-flex; align-items: center; gap: 5px; }
.grp-filtre svg { color: var(--gc); }
.grp-filtre.on { border-color: var(--gc); color: var(--gc);
  background: color-mix(in srgb, var(--gc) 8%, transparent); }

/* Le groupe se change dans la ligne. Le select porte la teinte du groupe :
   sans elle, la colonne redevient quinze mots gris. */
.grp-inline { display: inline-block; margin: 0; }
/* Plusieurs groupes sur une ligne (HH-2564) : les puces se suivent, et le
   menu d'ajout ferme la rangée, discret tant qu'on ne le cherche pas. */
/* Côte à côte, et TOUS à la même hauteur : la puce-formulaire, la puce
   « Sans groupe » et le menu d'ajout partagent 24 px, sans retour à la ligne
   — la table défile plutôt que la cellule ne s'empile. */
.td-groupe { white-space: nowrap; }
.grp-cell { display: flex; flex-wrap: nowrap; align-items: center; gap: 6px; }
.grp-cell .grp-puce, .grp-cell .grp-ajout { height: 24px; box-sizing: border-box;
  line-height: 1; padding-top: 0; padding-bottom: 0; }
form.grp-chip { margin: 0; padding-right: 5px; }
.grp-chip .sp-x { display: inline-flex; align-items: center; height: 18px; padding: 0 2px;
  margin-left: 2px; color: var(--gc); opacity: .45; font-size: 10px; }
.grp-chip .sp-x:hover { opacity: 1; color: var(--sem-defaut-t); }
.grp-select.grp-ajout { --gc: var(--muted); width: auto; max-width: 128px; font-size: 11.5px;
  padding-left: 9px; padding-right: 24px; border-radius: 999px; opacity: .8; }
.grp-select.grp-ajout:hover, .grp-select.grp-ajout:focus { opacity: 1; }
/* `background-color` et SURTOUT pas le raccourci `background`.
   La règle maison de `select` dessine son chevron en image de fond, avec son
   `no-repeat`, sa position et sa taille. Le raccourci remet ces trois-là à
   zéro : l'image disparaît — jusqu'au survol, où `select:hover` (plus
   spécifique) la remet… sans le `no-repeat` que je venais d'effacer. Le
   chevron se répétait alors en mosaïque sur toute la largeur, et le champ
   ressemblait à un ruban zébré. */
.grp-select { --gc: var(--muted); font-size: 11.5px; font-weight: 600;
  padding: 3px 26px 3px 10px; border-radius: 999px; cursor: pointer;
  max-width: 152px; color: var(--gc);
  border: 1px solid color-mix(in srgb, var(--gc) 30%, transparent);
  background-color: color-mix(in srgb, var(--gc) 9%, transparent);
  background-position: right 9px center; }
.grp-select:hover { border-color: var(--gc); transform: none;
  box-shadow: 0 1px 2px rgba(11, 11, 11, .05); }
.td-groupe { white-space: nowrap; }

/* Les cartes du modal : on choisit un groupe à l'œil, pas dans une liste. */
.grp-cartes { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 14px; }
.grp-carte { --gc: var(--muted); display: inline-flex; align-items: center;
  gap: 7px; padding: 7px 12px; border-radius: 10px; text-decoration: none;
  color: var(--ink); font-size: 12.5px; background: var(--surface);
  border: 1px solid var(--hairline); transition: border-color .12s, background .12s; }
.grp-carte:hover { border-color: var(--gc); }
.grp-carte.on { border-color: var(--gc);
  background: color-mix(in srgb, var(--gc) 9%, transparent); }
.grp-ico { display: grid; place-items: center; width: 26px; height: 26px;
  border-radius: 8px; color: #fff; background: var(--gc); flex: none; }
.grp-carte i { font-style: normal; font-size: 11px; color: var(--muted);
  font-variant-numeric: tabular-nums; }

.grp-form { display: flex; flex-direction: column; gap: 12px;
  border-top: 1px solid var(--hairline); padding-top: 14px; }
.grp-look { align-items: flex-start; }
.grp-teintes, .grp-icos { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 4px; }
.grp-teinte { --gc: #64748b; width: 26px; height: 26px; border-radius: 8px;
  background: var(--gc); cursor: pointer; border: 2px solid transparent;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.08); }
.grp-teinte.on { border-color: var(--ink); }
.grp-teinte input, .grp-ico-opt input { position: absolute; opacity: 0;
  width: 0; height: 0; }
.grp-ico-opt { display: grid; place-items: center; width: 28px; height: 28px;
  border-radius: 8px; cursor: pointer; color: var(--muted);
  border: 1px solid var(--hairline); background: var(--surface); }
.grp-ico-opt:hover { color: var(--gc); border-color: var(--gc); }
.grp-ico-opt.on { color: #fff; background: var(--gc); border-color: var(--gc); }

.grp-aide { margin: 4px 0 0; font-size: 11.5px; color: var(--muted); }
.grp-n { display: inline-block; margin-left: 6px; padding: 1px 8px;
  border-radius: 999px; font-weight: 600; color: var(--sem-attente-t);
  background: var(--sem-attente-bg); border: 1px solid #f0dcb4; }
.grp-sec > summary { font-size: 12.5px; }
.grp-ligne { display: flex; align-items: center; gap: 9px; padding: 4px 0;
  font-size: 12.5px; cursor: pointer; border-bottom: 1px solid var(--hairline); }
.grp-ligne:last-child { border-bottom: 0; }
.grp-ligne.coupe span { color: var(--sem-attente-t); font-weight: 600;
  text-decoration: line-through; text-decoration-color: #d9b478; }
.grp-neuf { margin-top: 14px; border-top: 1px solid var(--hairline); padding-top: 14px; }


/* La barre de la liste des droits : chercher, et régler en masse. */
.grp-barre { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin: 10px 0 4px; }
.grp-chercher { flex: 1; min-width: 180px; display: flex; align-items: center;
  gap: 7px; padding: 4px 10px; border: 1px solid var(--hairline);
  border-radius: 999px; background: var(--surface); color: var(--muted); }
.grp-chercher input { flex: 1; min-width: 0; border: 0; outline: 0;
  background: none; font: inherit; font-size: 12.5px; color: var(--ink); }
.grp-chercher:focus-within { border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft); }
.grp-bulk { display: flex; gap: 5px; }


/* ── La liste des droits : une page à la fois ───────────────────────────────
   Vingt-six lignes dans un modal qui coupe, et une barre de défilement qu'on
   ne voyait pas : on croyait avoir tout lu. Une hauteur FIXE et une pagination
   disent combien il reste — « 1 / 4 » est une information, un contenu coupé
   n'en est pas une.

   Les lignes des autres pages restent dans le formulaire, seulement cachées :
   n'envoyer que la page visible effacerait en silence les vingt autres
   décisions. */
.perm-boite { min-height: 268px; }
.perm-pied { display: flex; align-items: center; gap: 10px; margin-top: 8px;
  padding-top: 8px; border-top: 1px solid var(--hairline); }
.perm-compte { flex: 1; font-size: 11.5px; color: var(--muted);
  font-variant-numeric: tabular-nums; }
.perm-nav { display: flex; align-items: center; gap: 4px; }
.perm-nav button { width: 26px; height: 26px; display: grid; place-items: center;
  border: 1px solid var(--hairline); border-radius: 8px; background: var(--surface);
  cursor: pointer; color: var(--ink-2); font-size: 13px; line-height: 1; }
.perm-nav button:hover:not(:disabled) { border-color: var(--accent);
  color: var(--accent); }
.perm-nav button:disabled { opacity: .35; cursor: default; }
.perm-page { font-size: 11.5px; color: var(--ink-2); font-weight: 600;
  min-width: 46px; text-align: center; font-variant-numeric: tabular-nums; }


/* ── L'écran Équipe : neuf colonnes qui doivent tenir sans déborder ─────────
   Elle portait quinze closers ; elle porte maintenant toute l'équipe, avec une
   colonne de groupe en plus. Sans largeurs, l'e-mail prenait tout et les trois
   colonnes du closing se retrouvaient collées à droite avec un tiret chacune :
   ça se lisait comme un tableau cassé. */
/* Sur `.eq-table` et PAS sur `.table-compact` : la classe compacte est une
   utilitaire, portée par six tableaux de la plateforme. Ces quatre largeurs
   écrites pour Équipe s'appliquaient donc aussi au suivi de closing (0,2,1
   contre 0,2,0 pour `.pv-table .c-eta`, et plus bas dans la feuille) : la
   colonne « Étape » y prenait 11 % de l'écran au lieu de ses 158 px et
   « Proba » 18 % — d'où une colonne d'étape démesurée sans raison visible. */
.eq-table th:nth-child(1), .eq-table td:nth-child(1) { width: 18%; }
.eq-table th:nth-child(2), .eq-table td:nth-child(2) { width: 11%; }
.eq-table th:nth-child(3), .eq-table td:nth-child(3) { width: 11%; }
.eq-table th:nth-child(4), .eq-table td:nth-child(4) { width: 18%; }
.td-sansobjet { font-style: italic; opacity: .75; }

/* Supprimer est le seul geste dont on ne revient pas : il se distingue au
   survol, pas au repos — un rouge permanent au bout de vingt lignes fait un
   mur, et on cesse de le voir. */
.icon-btn.ia-suppr:hover { color: var(--sem-defaut-t);
  border-color: #f2ccc4; background: var(--sem-defaut-bg); }


/* ── Le catalogue : des onglets qui se reconnaissent ────────────────────────
   « Je ne comprends pas les onglets » — six mots gris d'affilée, et rien ne
   disait qu'ils rangeaient par LIGNE de produit. Une couleur et un signe
   donnent à chacun un visage : on retrouve « les ATA » sans relire. Même
   vocabulaire de teintes que les groupes d'accès — la plateforme n'en a
   qu'un. */
.prod-tab { --gc: var(--muted); display: inline-flex; align-items: center;
  gap: 6px; }
.prod-tab svg { color: var(--gc); opacity: .85; }
.prod-tab.actif { border-bottom-color: var(--gc); color: var(--gc); }
.prod-tab.actif svg { opacity: 1; }
.prod-tab.actif .tag { border-color: color-mix(in srgb, var(--gc) 30%, transparent);
  background: color-mix(in srgb, var(--gc) 10%, transparent); color: var(--gc); }
/* Un onglet sans résultat pendant une recherche : décoloré, pas caché. Le
   faire disparaître déplacerait les autres sous le curseur. */
.prod-tab.sans-resultat { opacity: .35; }

/* Chercher, dans l'en-tête, à la place de la ligne de prose qui était là. */
.prod-chercher { display: flex; align-items: center; gap: 7px; flex: none;
  width: 240px; padding: 5px 12px; border: 1px solid var(--hairline);
  border-radius: 999px; background: var(--surface); color: var(--muted); }
.prod-chercher input { flex: 1; min-width: 0; border: 0; outline: 0;
  background: none; font: inherit; font-size: 12.5px; color: var(--ink); }
.prod-chercher:focus-within { border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft); }
.anim-box .ev-head .prod-chercher { margin-right: 4px; }

/* Une offre archivée : lisible, mais visiblement hors service. */
.prod-liste tr.ev-passe td { opacity: .62; }
.prod-liste tr.ev-passe .prod-nom b { text-decoration: line-through;
  text-decoration-thickness: 1px; text-decoration-color: #c9c7bf; }


/* ── Les gestes d'une offre ─────────────────────────────────────────────── */
.modal-box.taches-box { width: min(560px, 95vw); }
.tach-note { margin: 0 0 14px; padding: 9px 12px; border-radius: 9px;
  font-size: 11.5px; line-height: 1.45; color: var(--sem-vente-t);
  background: var(--sem-vente-bg); border: 1px solid #cfe0f6; }

/* Ce qui ne se règle pas, montré quand même : une liste où « Paiement » et
   « Facture » manqueraient ferait croire qu'on les a oubliés. */
.tach-fixes { display: flex; align-items: center; flex-wrap: wrap; gap: 7px;
  padding-bottom: 12px; margin-bottom: 4px;
  border-bottom: 1px solid var(--hairline); }
.tach-fixe { display: inline-flex; align-items: center; gap: 5px;
  font-size: 11.5px; font-weight: 600; padding: 3px 10px; border-radius: 999px;
  color: var(--muted); background: var(--page); border: 1px solid var(--hairline); }
.tach-fixe[title] { cursor: help; }

.tach-liste { display: flex; flex-direction: column; }
.tach-ligne { display: flex; align-items: center; gap: 10px; padding: 9px 2px;
  border-bottom: 1px solid var(--hairline); cursor: pointer; font-size: 13px;
  transition: color .12s; }
.tach-ligne:last-child { border-bottom: 0; }
.tach-ligne input { position: absolute; opacity: 0; width: 0; height: 0; }
.tach-case { display: grid; place-items: center; width: 24px; height: 24px;
  flex: none; border-radius: 7px; border: 1px solid var(--hairline);
  background: var(--surface); color: transparent; transition: all .12s; }
.tach-ligne.on .tach-case { background: var(--sem-facture); color: #fff;
  border-color: var(--sem-facture); }
.tach-ligne.on .tach-lib { font-weight: 600; }
.tach-ligne:not(.on) .tach-lib { color: var(--muted); }
.tach-aide { margin: 12px 0 0; font-size: 11.5px; color: var(--muted);
  line-height: 1.45; }
/* Les gestes du catalogue portent leur couleur AU REPOS, pas seulement au
   survol. En gris uniforme, quarante lignes de quatre icônes font une grille
   indifférenciée où l'on vise à l'aveugle ; teintées, chaque colonne se
   reconnaît d'un coup d'œil et on ne se trompe pas de bouton.

   La teinte reste discrète tant qu'on ne survole pas — un mur de couleurs
   pleines fatiguerait autant que le gris. Elle se remplit au passage. */
.prod-liste .icon-btn { color: var(--gb, var(--ink-2)); }
.prod-liste .icon-btn:hover {
  color: #fff; background: var(--gb, var(--ink-2));
  border-color: var(--gb, var(--ink-2));
}
.icon-btn.ia-fiche      { --gb: var(--accent); }        /* corriger : bleu   */
.icon-btn.ia-gestes     { --gb: #7f54b3; }              /* régler  : violet  */
.icon-btn.ia-archiver   { --gb: var(--sem-attente-t); } /* ranger  : ambre   */
.icon-btn.ia-desarchiver{ --gb: var(--sem-facture-t); } /* remettre: vert    */
.prod-liste .icon-btn.ia-suppr { --gb: var(--sem-defaut-t); }


/* Les gestes propres à une offre : une ligne qu'on écrit, pas qu'on coche. */
.tach-propres { margin-top: 16px; padding-top: 14px;
  border-top: 1px solid var(--hairline); }
.tach-sous { font-size: 10.5px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 8px; }
.tach-propre { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.tach-propre input[type=text] { flex: 1; min-width: 0; font-size: 13px;
  padding: 5px 10px; border: 1px solid var(--hairline); border-radius: 8px;
  background: var(--surface); }
.tach-propre input[type=text]:focus { border-color: var(--accent); outline: 0;
  box-shadow: 0 0 0 3px var(--accent-soft); }
.tach-x { border: 0; background: none; cursor: pointer; color: var(--muted);
  font-size: 13px; line-height: 1; padding: 4px; flex: none; }
.tach-x:hover { color: var(--sem-defaut-t); }
.tach-case.on { background: var(--sem-facture); color: #fff;
  border-color: var(--sem-facture); }


/* Les pastilles de tâches après un réglage enregistré sans rechargement : la
   ligne du registre ne connaît pas encore le changement. Un point discret le
   dit, plutôt que de laisser croire que le chiffre est à jour. */
.tache-cell.a-rafraichir .tache-frac { position: relative; }
.tache-cell.a-rafraichir .tache-frac::after {
  content: ""; position: absolute; top: -2px; right: -6px;
  width: 5px; height: 5px; border-radius: 50%; background: var(--sem-attente);
}

/* ── HH-2521 · « Déjà au registre » dans le modal de conversion ───────────────
   La commande arrivée seule (Systeme.io, boutique) passe AVANT le formulaire
   de création : c'est elle qu'on doit voir en ouvrant le modal. Ambre, parce
   que c'est un « attention » — pas une erreur, pas encore. La ligne dont
   l'offre est celle choisie passe en rouge : là, c'est le doublon. */
.pv-jumelles { margin: 0 0 12px; padding: 9px 12px; border-radius: 10px;
  background: var(--sem-attente-bg); border: 1px solid #f0dcb4; }
.pv-jumelles-t { font-size: 10.5px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--sem-attente-t); margin-bottom: 4px; }
.pv-jumelle { display: flex; align-items: center; gap: 10px; padding: 6px 0; }
.pv-jumelle + .pv-jumelle { border-top: 1px solid #f0dcb4; }
.pv-jumelle-txt { flex: 1; min-width: 0; font-size: 12.5px; color: var(--ink); }
.pv-jumelle-txt .muted { display: block; margin-top: 1px; }
.pv-jumelle.meme .pv-jumelle-txt b { color: var(--sem-defaut-t); }
.pv-jumelle .btn { flex: none; }
.pv-forcer { margin: 6px 0 0; }

/* ── HH-2521 · « Vente détectée » ───────────────────────────────────────────
   Vert : c'est de l'argent entré, la teinte « encaissé » de la plateforme. Le
   point bat doucement — c'est la seule pastille du tableau qui attend un
   geste, et elle doit se voir dans soixante lignes sans crier. */
.pv-detectee {
  display: inline-flex; align-items: center; gap: 5px; margin-right: 7px;
  padding: 0 8px 0 6px; border-radius: 999px; border: 1px solid #bfe4cd;
  background: var(--sem-facture-bg); color: var(--sem-facture-t);
  font: inherit; font-size: 10.5px; font-weight: 700; line-height: 17px;
  cursor: pointer; vertical-align: 1px; transition: background .15s, color .15s;
}
.pv-detectee::before { content: ""; flex: none; width: 6px; height: 6px;
  border-radius: 50%; background: var(--sem-facture);
  animation: pvd-pouls 2.2s ease-in-out infinite; }
.pv-detectee:hover { background: var(--sem-facture); border-color: var(--sem-facture);
  color: #fff; }
.pv-detectee:hover::before { background: #fff; }
@keyframes pvd-pouls { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }
@media (prefers-reduced-motion: reduce) { .pv-detectee::before { animation: none; } }

/* Le modal : qui, quel achat, un bouton. */
.pvd-box { max-width: 440px; }
.pvd-qui { margin: 0 0 12px; font-size: 12.5px; color: var(--muted); }
.pvd-qui b { color: var(--ink); font-size: 14.5px; margin-right: 8px; }
.pvd-liste { display: grid; gap: 8px; }
.pvd-carte { display: flex; gap: 10px; align-items: flex-start; padding: 12px 14px;
  border: 1px solid var(--hairline); border-radius: 12px;
  background: var(--surface); cursor: pointer;
  transition: border-color .15s, background .15s, box-shadow .15s; }
.pvd-carte:has(input:checked) { border-color: var(--sem-facture);
  background: var(--sem-facture-bg);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--sem-facture) 14%, transparent); }
.pvd-carte input { margin-top: 3px; }
.pvd-corps { flex: 1; min-width: 0; display: grid; gap: 4px; }
.pvd-haut { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.pvd-haut b { font-size: 13.5px; color: var(--ink); }
.pvd-montant { font-size: 17px; font-weight: 750; white-space: nowrap;
  color: var(--sem-facture-t); font-variant-numeric: tabular-nums; }
.pvd-bas { font-size: 11.5px; color: var(--muted); }

/* La ligne clôturée s'allume un instant en vert : on voit OÙ elle est. */
.pv-ligne.pv-juste > td { animation: pv-juste 1.8s ease-out; }
@keyframes pv-juste { 0% { background: var(--sem-facture-bg); } 100% { background: transparent; } }

/* HH-2521 · « Ventes détectées » en tête de liste : le jumeau de « Sans
   nouvelles », en vert — c'est de l'argent entré, pas un retard. Actif, il
   prend le bleu des filtres comme tous les autres. */
.btn.detectee { color: var(--sem-facture-t); border-color: #bfe4cd;
  background: var(--sem-facture-bg); }
.btn.detectee:hover { border-color: var(--sem-facture); }
.btn.detectee b { margin-left: 5px; font-variant-numeric: tabular-nums; }
.btn.detectee.primary { color: #fff; background: var(--sem-facture);
  border-color: var(--sem-facture); }
.btn.detectee.primary .fdot { background: #fff; }

/* HH-2521 · « Associer une vente existante » en tête du modal de vente : la
   vente existe le plus souvent déjà. Le chercheur prend la largeur, le bouton
   se colle à sa droite ; « ou créer » sépare les deux chemins d'un filet. */
.pv-associer { display: flex; align-items: flex-end; gap: 8px; margin: 0 0 4px; }
.pv-associer > label { flex: 1; min-width: 0; font-size: 12px; font-weight: 600;
  color: var(--ink-2); }
.pv-associer > label select, .pv-associer > label .sel-search { margin-top: 4px; }
.pv-associer .btn { flex: none; }
.pv-ou { display: flex; align-items: center; gap: 10px; margin: 12px 0 10px;
  font-size: 11px; color: var(--muted); text-transform: uppercase;
  letter-spacing: .06em; }
.pv-ou::before, .pv-ou::after { content: ""; flex: 1; height: 1px;
  background: var(--hairline); }

/* Passage en « gagnée » suspendu : la question, en une ligne, avant les cartes. */
.pvd-avant { margin: -4px 0 10px; font-size: 12.5px; font-weight: 650;
  color: var(--sem-attente-t); }

/* ── HH-2521 · Le modal « Vente détectée », redessiné ──────────────────────
   Trois étages : QUI (en-tête, avec la pastille du closer à ses couleurs),
   QUOI (la question en bandeau, puis l'achat en carte), et la DÉCISION (le
   pied). Assez large pour que les trois boutons tiennent sur une ligne —
   à 440 px le dernier sortait du cadre et le modal défilait de côté. */
.modal-box.pvd-box { width: 500px; max-width: 94vw; padding: 0; overflow-x: hidden; }
.pvd-box .modal-head { align-items: flex-start; gap: 12px; margin: 0;
  padding: 18px 20px 14px; border-bottom: 1px solid var(--hairline); }
.pvd-ico { flex: none; display: grid; place-items: center; width: 38px; height: 38px;
  border-radius: 12px; color: var(--sem-facture); background: var(--sem-facture-bg);
  border: 1px solid #bfe4cd; }
.pvd-titre { flex: 1; min-width: 0; display: grid; gap: 5px; }
.pvd-box .modal-head .pvd-titre > b { flex: none; font-size: 15.5px; letter-spacing: -.15px; }
.pvd-box .pvd-qui { display: flex; align-items: center; gap: 6px; margin: 0;
  font-size: 12.5px; color: var(--muted); min-width: 0; }
.pvd-box .modal-head .pvd-qui b { flex: none; margin: 0; font-size: 13px;
  font-weight: 600; color: var(--ink); }
.pvd-sep { color: var(--hairline); }
.pvd-qui .pv-ava { width: 20px; height: 20px; font-size: 8.5px; }
.pvd-box .modal-close { margin-top: 2px; }

.pvd-corpsbox { padding: 16px 20px 2px; }
.pvd-box .pvd-avant { display: flex; align-items: center; gap: 8px; margin: 0 0 12px;
  padding: 8px 12px; border-radius: 10px; font-size: 12.5px; font-weight: 600;
  color: var(--sem-attente-t); background: var(--sem-attente-bg);
  border: 1px solid #f0dcb4; }
.pvd-box .pvd-avant::before { content: ""; flex: none; width: 7px; height: 7px;
  border-radius: 50%; background: var(--sem-attente); }

.pvd-box .pvd-carte { padding: 14px 16px; border-radius: 14px; gap: 12px; }
.pvd-box .pvd-carte:has(input:checked) {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--sem-facture) 12%, transparent),
              0 6px 18px color-mix(in srgb, var(--sem-facture) 12%, transparent); }
.pvd-box .pvd-haut { align-items: flex-start; }
.pvd-offre { font-size: 14px; font-weight: 700; color: var(--ink); line-height: 1.3; }
.pvd-box .pvd-montant { font-size: 21px; font-weight: 800; letter-spacing: -.3px;
  line-height: 1.1; }
/* LE BON DE COMMANDE. C'est la page où la cliente a payé : il ne
   s'interprète pas, il se reconnaît — et c'est précisément ce qui manquait à
   Béatrice le 15/09 pour ne pas écarter la bonne vente. Petites capitales,
   sous le nom de l'offre, avant tout le reste. */
.pvd-tunnel { display: block; margin-top: 3px; font-size: 11px; font-weight: 650;
  letter-spacing: .04em; color: var(--muted); text-transform: uppercase;
  line-height: 1.35; }
.pvd-mod { padding: 1px 8px; border-radius: 999px; font-size: 11px; font-weight: 650;
  color: var(--sem-vente-t); background: var(--sem-vente-bg);
  border: 1px solid var(--accent-soft); }
/* Une formation que le LMS ne peut plus ouvrir : rouge, parce qu'elle ne
   prévient de rien toute seule — l'élève ne reçoit simplement pas son cours. */
/* Ce qui vient d'un AUTRE achat : gris, sans croix, sans action. On le lit
   pour ne pas le refaire — et surtout pour ne pas le défaire. */
/* L'HISTORIQUE, en bas et discret. Il se lit, il ne s'actionne pas — d'où
   l'absence de croix, et un gris qui ne rivalise pas avec les pastilles
   vivantes juste au-dessus. Le trait plein sépare mieux que le pointillé :
   trois pointillés empilés (le trait, les pastilles, le menu) donnaient
   l'impression d'un bloc inachevé. */
.ge-autres { margin-top: 12px; padding-top: 10px;
  border-top: 1px solid var(--hairline); }
.ge-autres-t { font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted); margin-bottom: 6px; }
/* INCOMPLÈTE — ambre, pas rouge : rien n'est cassé, il manque un réglage, et
   c'est réparable en deux clics depuis cette même ligne. Le rouge reste pour
   ce qui bloque vraiment. */
.prod-effet.incomplete { color: var(--sem-attente-t); background: var(--sem-attente-bg);
  border-color: #ecd3a1; font-weight: 650; cursor: help; }

/* Ce qui manque à l'offre, au-dessus du bouton qui va ouvrir. Ambre : rien
   n'est cassé, il manque un réglage — mais on le lit AVANT d'agir. */
/* Le menu qui répare, collé au constat : on lit qu'il manque un courrier et
   on le pose, sans quitter la ligne. */
/* HH-2620 · le modal « Nouvelle ligne » dit ce qui l'empêche d'avancer. */
.n-erreur { margin: 0 0 10px; padding: 8px 12px; border-radius: 9px; font-size: 13px;
  color: var(--sem-defaut-t); background: var(--sem-defaut-bg);
  border: 1px solid var(--sem-defaut); }
.n-alerte { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px;
  margin: -4px 0 10px; padding: 7px 11px; border-radius: 9px; font-size: 12.5px;
  color: var(--sem-attente-t); background: var(--sem-attente-bg); border: 1px solid #ecd3a1; }
.n-passe { margin: -4px 0 10px; font-size: 12.5px; color: var(--muted); }

/* La recherche sort de l'onglet — et le dit. Bleu accent : c'est une
   information sur ce qu'on regarde, pas une alerte. */
.pv-recherche-globale { display: flex; align-items: center; gap: 8px;
  margin: 0 0 10px; padding: 8px 12px; border-radius: 9px;
  font-size: 12.5px; color: var(--sem-vente-t);
  background: var(--sem-vente-bg); border: 1px solid var(--accent-soft); }

/* Deux choses, deux blocs : le courrier d'identifiants ne se lit pas comme
   un cinquième onboarding. */
/* Le rattrapage : accès ouverts, courrier jamais parti. Bleu et pas ambre —
   ce n'est pas une alerte, c'est une action qui attend. */
.ge-rattrapage { display: flex; align-items: center; gap: 12px; margin: 0 0 12px;
  padding: 10px 13px; border-radius: 10px;
  border: 1px solid var(--accent-soft); background: var(--sem-vente-bg); }
.ge-rattrapage-txt { flex: 1; font-size: 13px; line-height: 1.5; }

.md-bloc { margin-bottom: 10px; }
.md-explique { font-size: 12px; color: var(--muted); line-height: 1.45;
  margin: -2px 0 7px; max-width: 62ch; }

.ge-modele { display: flex; flex-direction: column; gap: 3px; margin-top: 8px; }
.ge-modele select { max-width: 380px; }

.ge-manques { display: flex; gap: 10px; margin: 0 0 14px; padding: 11px 14px;
  border-radius: 10px; border: 1px solid #ecd3a1;
  background: var(--sem-attente-bg); }
.ge-manques-ico { font-size: 15px; line-height: 1.4; flex: 0 0 auto; }
.ge-manques-txt { font-size: 13px; line-height: 1.5; }
.ge-manques-txt ul { margin: 5px 0 5px 16px; padding: 0; }
.ge-manques-txt li { margin: 1px 0; }

.ge-achat { margin-bottom: 8px; }
.ge-achat:last-child { margin-bottom: 0; }
.ge-achat-t { display: flex; align-items: baseline; gap: 8px; margin-bottom: 3px; }
.ge-achat-t b { font-size: 12px; font-weight: 650; color: var(--ink-2); }
.ge-achat-d { font-size: 11px; color: var(--muted);
  font-variant-numeric: tabular-nums; }
/* `.ge-histo` et surtout PAS `.ge-autre` : cette classe-là existait déjà pour
   le menu « ＋ Autre liste… », qui héritait donc du pointillé et se lisait
   comme une pastille d'historique. */
.ge-histo { display: inline-flex; align-items: baseline; margin: 0 5px 4px 0;
  padding: 3px 10px; border-radius: 999px; background: var(--page);
  border: 1px solid var(--hairline); cursor: help;
  font-size: 12px; color: var(--muted); }

.lo-mort { color: var(--sem-defaut); font-weight: 700; cursor: help; }
/* La sortie est collée au problème : on lit l'alerte et la réparation d'un
   seul regard, au lieu d'aller chercher la bonne formation dans la liste. */
.lo-remplace { border-color: var(--sem-defaut); background: var(--sem-defaut-bg); }
.lo-remplace .lien-bouton { color: var(--sem-defaut-t); font-size: 11.5px;
  text-decoration: none; font-weight: 650; }
.lb-mort { padding: 1px 7px; border-radius: 999px; font-size: 11px; font-weight: 650;
  color: var(--sem-defaut-t); background: var(--sem-defaut-bg);
  border: 1px solid var(--sem-defaut); cursor: help; }

.pvd-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 8px; }
.pvd-canal { padding: 1px 8px; border-radius: 999px; font-size: 11px; font-weight: 650;
  color: var(--ink-2); background: var(--surface); border: 1px solid var(--hairline); }
.pvd-date { font-size: 11.5px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.pvd-meta .badge { font-size: 11px; }
.pvd-num { margin-left: auto; font-size: 11px; color: var(--muted);
  font-variant-numeric: tabular-nums; }

.pvd-box .modal-actions { align-items: center; margin: 16px 0 0; padding: 14px 20px 16px;
  background: var(--page); border-top: 1px solid var(--hairline); }
.pvd-box .modal-cancel { margin-right: auto; padding-left: 4px; padding-right: 4px;
  background: none; border-color: transparent; box-shadow: none; color: var(--muted); }
.pvd-box .modal-cancel:hover { color: var(--ink); background: none; }
/* Associer, c'est de l'argent qui entre : le vert du registre, pas le bleu. */
.pvd-box [data-pvd-go] { background: var(--sem-facture); border-color: var(--sem-facture);
  color: #fff; }
.pvd-box [data-pvd-go]:hover { filter: brightness(.94); }

/* HH-2521 · Ce que l'IA a trouvé : violet, la teinte « care » — ni une
   erreur ni de l'argent, une proposition à juger. */
.pvd-ia { padding: 1px 7px; border-radius: 999px; font-size: 10.5px; font-weight: 800;
  letter-spacing: .03em; color: var(--sem-care-t); background: var(--sem-care-bg);
  border: 1px solid color-mix(in srgb, var(--sem-care) 30%, transparent); }
.pvd-motif { display: block; margin-top: 8px; font-size: 11.5px; line-height: 1.4;
  color: var(--ink-2); font-style: italic; }
.statut-doublon { display: flex; align-items: center; gap: 3px; margin-top: 4px;
  font-size: 11px; font-weight: 650; }
.statut-doublon a { color: var(--sem-care-t); }
.statut-doublon form { margin: 0; }
.statut-doublon-x { border: 0; background: none; padding: 0 3px; cursor: pointer;
  font-size: 11px; color: var(--muted); }
.statut-doublon-x:hover { color: var(--sem-defaut-t); }

/* ── HH-2521 · Doublons, dans le registre ────────────────────────────────── */
.kpi-doublons { font: inherit; text-align: left; cursor: pointer;
  border: 1px solid var(--hairline); background: var(--surface); }
.kpi-doublons .l, .kpi-doublons .v { display: block; }
.kpi-doublons:hover { border-color: var(--sem-care); }
.kpi-doublons.a-trancher { border-color: color-mix(in srgb, var(--sem-care) 45%, transparent);
  background: var(--sem-care-bg); }
.kpi-doublons.a-trancher .v { color: var(--sem-care-t); }

.modal-box.db-box { width: 800px; max-width: 95vw; }
.db-paire { margin: 0 0 14px; padding: 12px 14px; border-radius: 14px;
  border: 1px solid var(--hairline); background: var(--page); }
.db-motif { display: flex; align-items: center; gap: 8px; margin-bottom: 10px;
  font-size: 12.5px; color: var(--ink-2); }
.db-cartes { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.db-carte { display: flex; gap: 10px; align-items: flex-start; padding: 12px 14px;
  border: 1px solid var(--hairline); border-radius: 12px; background: var(--surface);
  cursor: pointer; transition: border-color .15s, box-shadow .15s; }
.db-carte:has(input:checked) { border-color: var(--sem-facture);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--sem-facture) 14%, transparent); }
.db-carte.fixe { cursor: default; opacity: .9; }
.db-carte input { margin-top: 3px; }
.db-corps { flex: 1; min-width: 0; display: grid; gap: 3px; }
.db-haut { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.db-num { font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
.db-montant { font-size: 16px; font-weight: 800; color: var(--ink); font-variant-numeric: tabular-nums; }
.db-client { font-size: 13.5px; color: var(--ink); }
.db-mail, .db-meta { font-size: 11.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.db-offre { font-size: 12.5px; color: var(--ink-2); }
.db-bloque { margin-top: 4px; font-size: 11.5px; font-weight: 600; color: var(--sem-defaut-t); }
.db-actions { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
.db-aide, .db-impossible { margin-right: auto; font-size: 12px; color: var(--muted); }
.db-impossible { color: var(--sem-defaut-t); font-weight: 600; }
.db-vide { margin: 4px 0 12px; font-size: 13px; color: var(--muted); }
.db-manuel .form-row > label { flex: 1 1 0; min-width: 0; }
@media (max-width: 640px) { .db-cartes { grid-template-columns: 1fr; } }

/* ── HH-2521 · Options sur deux niveaux dans les listes filtrables ─────────
   Une vente se cherche des yeux par la cliente ; ce qui la distingue — numéro,
   offre, date — passe en dessous, en gris ; le montant s'aligne à droite pour
   se comparer d'une ligne à l'autre. Rien ne se coupe au milieu d'un mot. */
.sel-search .combo-item.riche { display: flex; align-items: center; gap: 12px;
  padding-top: 8px; padding-bottom: 8px; }
.ci-corps { flex: 1; min-width: 0; display: grid; gap: 2px; }
.ci-titre { font-size: 13px; font-weight: 600; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ci-sous { font-size: 11.5px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ci-droite { flex: none; font-size: 13px; font-weight: 700; color: var(--ink-2);
  font-variant-numeric: tabular-nums; }
.sel-search .combo-item.riche.chosen { font-weight: inherit; color: inherit; }
.sel-search .combo-item.riche.chosen .ci-titre { color: var(--accent-strong); }
.sel-search .combo-item.riche.chosen::before { top: 50%; transform: translateY(-50%); }
.sel-search .combo-item.riche:hover .ci-sous,
.sel-search .combo-item.riche.active .ci-sous { color: var(--ink-2); }

/* Doublons : ce qui arrive à chaque carte, sans alarme inutile. La vente qui
   ne peut pas disparaître dit POURQUOI on la garde, en vert ; celle qui n'est
   pas cochée annonce qu'elle partira — et le texte suit le choix. */
.pvd-ia { white-space: nowrap; flex: none; }
.db-garde { margin-top: 4px; font-size: 11.5px; font-weight: 600; color: var(--sem-facture-t); }
.db-sort { display: none; margin-top: 4px; font-size: 11.5px; font-weight: 600;
  color: var(--sem-defaut-t); }
.db-sort::after { content: "Sera supprimée à la fusion"; }
.db-carte:not(:has(input:checked)) .db-sort { display: block; }

/* ═══════════════════════════════════════════════════════════════════════════
   CARE CLIENT — trois écrans (HH-2549)

   Aucun vocabulaire nouveau : .page-head, .kpi-strip, .card, .filter-bar,
   table.data, .badge, .task-chip et les modals viennent tous du registre des
   ventes. Ce bloc ne fait qu'ajouter ce que le registre n'avait pas à dire —
   une file d'ouvertures, une conversation à côté de sa liste, et deux onglets
   dans une carte.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Le compteur dans l'onglet. Savoir s'il y a quelque chose derrière AVANT de
   cliquer : c'est ce qui évite d'ouvrir une file vide. Il vit dans le <b> du
   chip, pas dans un badge à part — deux boîtes pour deux mots feraient une
   barre de filtres deux fois plus haute. */
.filter-bar.onglets-compte .btn.xs > b {
  margin-left: 5px; padding: 0 5px; border-radius: 999px;
  background: var(--page); color: var(--muted);
  font-size: 10.5px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.filter-bar.onglets-compte .btn.xs.primary > b { background: rgba(255, 255, 255, .22); color: #fff; }

/* ---- 1. Accès à ouvrir ---------------------------------------------------- */
.acces-log .col-quand { width: 132px; }
.acces-log .col-gestes { width: 268px; }
/* L'adresse sert à créer le compte et à chercher la cliente dans Brevo : elle
   se prend d'un double-clic, entière, sans attraper la ligne d'à côté. */
.acces-mail { user-select: all; }
/* Pas encore soldée : la ligne existe, mais ce n'est pas encore le moment. Un
   gris franc plutôt qu'une couleur d'alerte — il n'y a rien d'anormal. */
.acces-log tr.row-attente td { background: color-mix(in srgb, var(--page) 62%, transparent); }
/* `table.data tr:hover td` repeint le fond : sans ces deux règles, survoler une
   ligne teintée la décolorait, et on croyait avoir changé de catégorie. */
.acces-log tr.row-attente:hover td { background: color-mix(in srgb, var(--page) 80%, transparent); }
.inbox-log tr.row-ouverte:hover td { background: var(--sem-care-bg); }
.acces-log tr.row-attente .acces-mail,
.acces-log tr.row-faite td { opacity: .78; }
.date-inline { display: block; margin: 0; }
.date-inline input[type="date"] {
  width: 122px; padding: 3px 6px; font-size: 12px;
  border: 1px solid transparent; background: transparent; border-radius: 7px;
  color: var(--ink); font-variant-numeric: tabular-nums;
}
/* Au repos, un champ vide ne doit pas ressembler à un formulaire : c'est une
   date facultative sur trois cents lignes. Elle s'annonce au survol. */
.date-inline input[type="date"]:hover { border-color: var(--hairline); background: var(--surface); }
.date-inline input[type="date"]:focus { border-color: var(--accent); background: var(--surface); outline: none; }
.acces-periode { margin-top: 2px; font-size: 11px; }
/* La note du closer : du texte libre, parfois une phrase entière (« prolonger
   accès de 3 mois avec son démarrage reporté »). Elle ne rentre pas dans une
   cellule — elle s'annonce, et se lit au survol. */
.acces-note {
  display: inline-block; margin-top: 3px; padding: 1px 7px; border-radius: 999px;
  background: var(--sem-attente-bg); color: var(--sem-attente-t);
  font-size: 10.5px; font-weight: 600; cursor: help;
}
.acces-log .task-chips { gap: 4px; }
/* Les trois gestes ne sont pas interchangeables : « Accès » est le seul qui
   ouvre vraiment quelque chose, et c'est celui qu'on cherche des yeux. */
.acces-log .task-chip { white-space: nowrap; }

/* ---- 2. Boîte de réception ------------------------------------------------ */
/* Le fond sur toute la ligne, le liseré sur la PREMIÈRE cellule seulement :
   posé sur chaque `td`, il redessinait une barre violette à l'entrée de chaque
   colonne — cinq traits au lieu d'un. */
.inbox-log tr.row-ouverte td { background: var(--sem-care-bg); }
.inbox-log tr.row-ouverte td:first-child { box-shadow: inset 3px 0 0 var(--sem-care); }
.canal-care {
  display: inline-block; padding: 1px 8px; border-radius: 999px;
  font-size: 10.5px; font-weight: 600; white-space: nowrap;
  background: var(--sem-ops-bg); color: var(--sem-ops-t);
}
/* Le portail élève est le SEUL canal réellement branché : il se distingue des
   quatre autres, qui attendent encore leur arrivée. */
.canal-care.c-formulario { background: var(--sem-acces-bg); color: var(--sem-acces-t); }
.canal-care.c-llamada { background: var(--sem-care-bg); color: var(--sem-care-t); }
/* La carte de démonstration s'annonce comme telle : elle disparaîtra le jour
   où la boîte wutaoteam@ sera branchée, et elle ne doit pas se lire comme un
   outil de travail entre-temps. */
.demo-card { border-style: dashed; }
.demo-card h3 { margin: 0 0 8px; color: var(--muted); }

/* ---- La base de connaissances, en modal ----------------------------------- */
.kb-liste { display: flex; flex-direction: column; gap: 6px; max-height: 46vh; overflow-y: auto; }
.kb-fiche { border: 1px solid var(--hairline); border-radius: 10px; background: var(--surface); }
.kb-fiche > summary {
  display: flex; align-items: center; gap: 10px; cursor: pointer;
  padding: 9px 12px; font-size: 13px; list-style: none;
}
.kb-fiche > summary::-webkit-details-marker { display: none; }
.kb-fiche > summary::before { content: "›"; color: var(--muted); transition: transform .12s; }
.kb-fiche[open] > summary::before { transform: rotate(90deg); }
.kb-fiche[open] { border-color: var(--accent-soft); }
.kb-fiche:hover { border-color: var(--accent-soft); }
.kb-q { flex: 1; min-width: 0; font-weight: 600; }
.kb-mots { font-size: 11px; color: var(--muted); white-space: nowrap; }
.kb-form { padding: 0 12px 12px; border-top: 1px solid var(--page); margin-top: 2px; }
.kb-neuve { border-style: dashed; }
.kb-neuve .kb-q { color: var(--accent); font-weight: 600; }

/* ---- 3. Appels & rappels -------------------------------------------------- */
.rappel-fait { display: inline-flex; align-items: center; gap: 6px; margin: 0; }
.rappel-fait input[type="number"] { width: 58px; padding: 3px 6px; font-size: 12px; }
.resume-appel { position: relative; }
.resume-appel > summary {
  cursor: pointer; font-size: 12px; color: var(--accent); list-style: none;
}
.resume-appel > summary::-webkit-details-marker { display: none; }
.resume-corps {
  margin-top: 6px; padding: 10px 12px; border-radius: 10px;
  background: var(--page); border: 1px solid var(--hairline);
  /* `position: absolute` et pas un min-width dans le flux : posé tel quel, il
     élargissait la cellule et poussait toute la table vers la droite. */
  position: absolute; right: 12px; z-index: 40;
  width: 360px; max-width: min(360px, 80vw); white-space: normal;
  box-shadow: var(--shadow-lift);
}
/* Le résumé est écrit en lignes : « Motif : … / À retenir : … / Actions
   suggérées : … ». `pre-line` garde ces retours sans transformer le texte en
   bloc de code. */
.resume-txt { font-size: 12px; line-height: 1.5; color: var(--ink-2); white-space: pre-line; margin-bottom: 8px; }

/* ---- Les listes Brevo (HH-2549) ------------------------------------------
   Une liste de diffusion, c'est des GENS. La première version en faisait une
   fiche de métadonnées qu'on dépliait pour éditer un numéro — ce n'est pas
   comme ça qu'on la pense, ni comme ça qu'on s'en sert. */

/* La cellule « Séquence » : une date de départ et une liste, empilées. Au
   repos, deux champs discrets — ce sont des cases facultatives sur trois cents
   lignes. Remplis, ils s'affirment : ce sont alors des informations. */
/* Assez large pour lire le NOM ENTIER d'une liste : « Inscrit.es Transmision
   ONDE & MOUVEMENTS - Bienvenue » fait cinquante-deux caractères, et tronqué il
   ne se distingue plus de « Inscrit.es Transmision ONDE - Bienvenue ». Choisir
   la mauvaise liste envoie le mauvais mail de bienvenue — Céline l'a noté :
   « va la confusionner ». La colonne coûte de la place ; se tromper coûte plus. */
.acces-log .col-seq { width: 320px; }
.seq-cell { display: flex; flex-direction: column; gap: 3px; align-items: stretch; }
.seq-champ { margin: 0; display: block; }
.seq-cell input[type="date"],
.seq-cell select {
  width: 100%; font-size: 11.5px; line-height: 1.5;
  padding: 3px 7px; border-radius: 7px;
  border: 1px dashed var(--hairline); background-color: transparent;
  color: var(--muted); font-variant-numeric: tabular-nums;
}
.seq-cell select { padding-right: 20px; }
.seq-cell input[type="date"]:hover,
.seq-cell select:hover { border-style: solid; border-color: var(--accent-soft); background-color: var(--surface); }
.seq-cell input[type="date"]:focus,
.seq-cell select:focus { border-style: solid; border-color: var(--accent); background-color: var(--surface); outline: none; }
/* Rempli : plein, teinté, lisible d'un coup d'œil. Le trait plein contre le
   pointillé dit « c'est fait » sans avoir besoin d'une couleur d'alerte. */
.seq-cell input[type="date"].rempli {
  border-style: solid; border-color: transparent;
  background-color: var(--sem-acces-bg); color: var(--sem-acces-t); font-weight: 600;
}
.seq-cell select.posee {
  border-style: solid; border-color: transparent;
  background-color: var(--sem-care-bg); color: var(--sem-care-t); font-weight: 600;
}
.seq-cell .sel-search { width: 100%; }
/* Aucune liste enregistrée : un <select> vide serait une porte fermée avec la
   poignée dessus. On montre le geste qui débloque, et rien d'autre. */
.seq-amorce {
  font: inherit; font-size: 11.5px; text-align: left; cursor: pointer;
  padding: 3px 7px; border-radius: 7px;
  border: 1px dashed var(--hairline); background: transparent; color: var(--muted);
}
.seq-amorce:hover { border-style: solid; border-color: var(--accent); color: var(--accent); }
.seq-cell.lecture { gap: 2px; font-size: 11.5px; }
.seq-cell .seq-date { color: var(--ink-2); font-variant-numeric: tabular-nums; }
.seq-cell .seq-liste { color: var(--sem-care-t); font-weight: 600; }

/* L'annuaire : des cartes cliquables, une par liste, avec son effectif. */
.lb-grille { display: flex; flex-direction: column; gap: 6px; max-height: 52vh; overflow-y: auto; }
.lb-carte {
  display: flex; align-items: center; gap: 11px; padding: 10px 12px;
  border: 1px solid var(--hairline); border-radius: 11px; background: var(--surface);
  color: var(--ink); text-decoration: none;
  transition: border-color .12s, box-shadow .12s, transform .12s;
}
.lb-carte:hover {
  border-color: var(--sem-care); box-shadow: var(--shadow);
  transform: translateY(-1px); text-decoration: none;
}
/* Une rangée : la carte qui ouvre, et la croix qui retire. */
.lb-rang { display: flex; align-items: center; gap: 4px; }
.lb-rang > .lb-carte { flex: 1; min-width: 0; }
.lb-rang.inactive { opacity: .55; }
.lb-retirer { margin: 0; flex: none; }
.lb-retirer .sp-x { opacity: 0; font-size: 12px; padding: 4px 6px; }
.lb-rang:hover .lb-retirer .sp-x, .lb-retirer .sp-x:focus-visible { opacity: .6; }
.lb-retirer .sp-x:hover { opacity: 1; }
.lb-num {
  flex: none; min-width: 40px; text-align: center; padding: 3px 8px; border-radius: 7px;
  background: var(--sem-care-bg); color: var(--sem-care-t);
  font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.lb-corps { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.lb-corps b { font-size: 13px; font-weight: 600; }
.lb-corps i { font-size: 11.5px; color: var(--muted); font-style: normal; }
.lb-compte { flex: none; text-align: right; line-height: 1.15; }
.lb-compte b { display: block; font-size: 17px; font-weight: 680; font-variant-numeric: tabular-nums; }
.lb-compte i { font-size: 10.5px; color: var(--muted); font-style: normal; }

/* Les personnes d'une liste. Ajouter est le geste principal : il est en haut. */
.lb-retour {
  flex: none; margin-right: 2px; width: 24px; height: 24px; border-radius: 7px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 18px; line-height: 1; color: var(--muted); background: var(--page);
}
.lb-retour:hover { color: var(--ink); text-decoration: none; }
.modal-head .lb-num { margin-left: 8px; }
.lb-ajout {
  display: flex; gap: 8px; align-items: center; margin: 0 0 12px;
  padding: 9px 11px; border-radius: 10px;
  background: var(--sem-care-bg); border: 1px solid transparent;
}
.lb-ajout select, .lb-ajout .sel-search { flex: 1; min-width: 0; background-color: var(--surface); }
.lb-membres td { vertical-align: top; }
.lb-sorties, .lb-reglage, .lb-neuve { margin-top: 8px; }
.lb-sorties > summary, .lb-reglage > summary, .lb-neuve > summary {
  cursor: pointer; font-size: 12px; color: var(--muted); list-style: none;
}
.lb-neuve > summary { color: var(--accent); font-weight: 600; }
.lb-sorties > summary::-webkit-details-marker,
.lb-reglage > summary::-webkit-details-marker,
.lb-neuve > summary::-webkit-details-marker { display: none; }
.lb-sorties > summary::before, .lb-reglage > summary::before { content: "› "; }
.lb-sorties[open] > summary::before, .lb-reglage[open] > summary::before { content: "⌄ "; }
.lb-form { margin-top: 10px; }
.lb-offres { width: 100%; padding: 6px; font-size: 12px; background-image: none; }
.lb-offres option { padding: 3px 5px; }
.lb-amorce { margin-top: 10px; text-align: center; }
.lb-amorce p { margin: 0 0 10px; line-height: 1.55; }

/* Le catalogue de Brevo, en lecture : 247 listes, on en coche quelques-unes.
   Une ligne par liste — case, numéro, nom, effectif — et un filtre au-dessus,
   parce que dérouler 247 lignes pour trouver « Séquence 90 mails » n'est pas
   une recherche, c'est une fouille. */
/* Le second temps de l'import : une ligne par liste, son rôle en trois
   pastilles — le choix se voit et se fait d'un clic, dans la couleur qu'il
   aura ensuite partout. */
.lo-box { width: 620px; max-width: 100%; }
.lo-roles { display: flex; flex-direction: column; gap: 6px; max-height: 50vh; overflow-y: auto;
  margin: 2px 0 14px; }
.lo-role { display: flex; align-items: center; gap: 10px; padding: 8px 10px;
  border: 1px solid var(--hairline); border-radius: 10px; background: var(--page); }
.lo-role-nom { flex: 1; min-width: 0; font-size: 12.5px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lo-choix { display: flex; flex: none; gap: 4px; }
.lo-opt { display: inline-flex; align-items: center; margin: 0; padding: 3px 11px;
  border-radius: 999px; cursor: pointer; font-size: 11.5px; font-weight: 600;
  color: var(--muted); background: var(--surface); border: 1px solid var(--hairline);
  transition: color .12s, background .12s, border-color .12s; }
.lo-opt input { position: absolute; opacity: 0; width: 0; height: 0; }
.lo-opt:hover { color: var(--lo, var(--ink-2)); border-color: color-mix(in srgb, var(--lo, var(--hairline)) 45%, transparent); }
.lo-opt:has(input:checked) { color: #fff; background: var(--lo, var(--ink-2)); border-color: transparent; }
.lo-opt:has(input:focus-visible) { box-shadow: 0 0 0 3px var(--accent-soft); }
.lo-autre { --lo: #8a5f00; }
.lo-pied { display: flex; align-items: center; gap: 10px; padding-top: 12px;
  border-top: 1px solid var(--hairline); }
.lo-pied .small { flex: 1; }
.lb-dispo.connue .tag { margin-left: auto; }
.lb-filtre { display: flex; width: 100%; margin-bottom: 8px; }
.lb-filtre input { flex: 1; min-width: 0; }
.lb-catalogue {
  display: flex; flex-direction: column; gap: 2px;
  max-height: 46vh; overflow-y: auto;
  border: 1px solid var(--hairline); border-radius: 10px; padding: 6px;
}
.lb-dispo {
  display: flex; align-items: center; gap: 10px; padding: 5px 8px;
  border-radius: 8px; cursor: pointer; font-size: 12.5px;
}
.lb-dispo:hover { background: var(--page); }
/* Déjà reprise : elle reste visible et cochée — savoir ce qu'on a déjà évite
   de la chercher deux fois. */
.lb-dispo.connue { background: var(--sem-care-bg); }
.lb-dispo .lb-num { min-width: 46px; font-size: 11px; }
.lb-dispo .lb-corps b { font-weight: 500; }
.lb-dispo .lb-compte b { font-size: 12.5px; font-weight: 600; color: var(--muted); }
/* HH-2596 — le nom d'un modèle Brevo peut être un seul mot interminable
   (« Vidéo quotidienne Onde Wutao_copy_copy_copy_copy… »). Sans coupure, il
   sortait de la boîte et fabriquait une barre de défilement horizontale sur
   tout le catalogue. On le coupe proprement ; le nom entier reste en
   infobulle. */
.lb-dispo .lb-corps b,
.lb-dispo .lb-corps i {
  display: block; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lb-catalogue { overflow-x: hidden; }

/* Le compte de duplications, discret : il qualifie le modèle, il ne le
   remplace pas. 3 888 des 4 215 modèles du compte sont des copies — s'il
   criait, tout l'écran crierait. */
.lb-copies { flex: none; opacity: .65; font-size: 10.5px; }

/* Le paginateur du catalogue : les modèles se parcourent page par page,
   chacune servie par notre copie locale. */
.lb-pages {
  display: flex; align-items: center; gap: 10px; margin-top: 8px;
  font-size: 12px; color: var(--muted);
}
.lb-pages .grow { flex: 1; text-align: center; }
/* Le bout de la course : on garde la place du bouton pour que « Page X sur Y »
   ne saute pas d'un bord à l'autre entre la première page et les suivantes. */
.lb-pages .muet { opacity: .38; pointer-events: none; }

/* HH-2596 — la porte de sortie quand le modèle cherché est trop ancien pour
   figurer dans la tranche rapatriée. Même dessin que `.lb-sync` : c'est le
   même registre, une action de service posée au-dessus de la liste. */
.lb-numero {
  display: flex; align-items: center; gap: 10px; margin: 0 0 8px;
  padding: 7px 11px; border-radius: 10px;
  background: var(--page); border: 1px dashed var(--hairline);
  font-size: 12px; color: var(--muted);
}
.lb-numero span { flex: 1; min-width: 0; }
.lb-numero input { width: 150px; font-size: 12.5px; }
@media (max-width: 760px) {
  .lb-numero { flex-wrap: wrap; }
  .lb-numero input { width: 100%; }
}

.lb-sync {
  display: flex; align-items: center; gap: 10px; margin: 0 0 12px;
  padding: 8px 11px; border-radius: 10px;
  background: var(--page); border: 1px dashed var(--hairline);
}
.transfert-qui, .transfert-qui + .sel-search { width: 230px; }
/* Une pastille qu'on ne peut pas cliquer ne doit pas s'allumer au survol :
   elle promettait un geste que le profil n'a pas. */
.task-chip.locked { cursor: default; }
.task-chip.locked:hover { border-color: var(--hairline); color: var(--muted); }
.task-chip.locked.done:hover { border-color: var(--good-tint-border); color: var(--good-text); }
/* Le cours choisi : vert d'accès ouvert, et non le violet des listes Brevo —
   ce sont deux services différents, et les confondre à l'œil ferait chercher
   un cours dans Brevo. */
.seq-cell select.acces-ok, .acces-log .col-gestes select.acces-ok {
  background-color: var(--sem-acces-bg); color: var(--sem-acces-t);
}
.acces-log .col-gestes select { width: 100%; max-width: 100%; }
/* « Quelle liste pour quelle offre » : quinze lignes, deux menus chacune.
   Le modal s'élargit pour que les noms de liste tiennent — les distinguer est
   tout l'intérêt de l'écran. */
.lb-par-offre td { vertical-align: middle; }
/* « Quelle liste pour quelle offre » : des puces par liste, dans la teinte de
   leur rôle, et « + Ajouter… » au bout (HH-2577). Le modal s'élargit : deux
   colonnes de puces ne tiennent pas dans 860 px. */
.modal-box.wide.lb-large { width: min(1120px, 96vw); }
.lo-cell { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; min-height: 26px; }
.lo-puce { display: inline-flex; align-items: center; gap: 5px; margin: 0; height: 24px;
  box-sizing: border-box; padding: 0 3px 0 8px; border-radius: 999px; max-width: 100%;
  font-size: 11.5px; font-weight: 600; color: var(--lo);
  background: color-mix(in srgb, var(--lo) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--lo) 28%, transparent); }
.lo-bienvenue { --lo: #1c5cab; }  .lo-sequence { --lo: #0c6b4a; }
.lo-num { font-size: 10px; opacity: .7; font-variant-numeric: tabular-nums; }
.lo-nom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 230px; }
.lo-puce .sp-x { color: var(--lo); opacity: .45; font-size: 10px; margin-left: 1px; }
.lo-ajout { margin: 0; }
.lb-par-offre .lo-select { width: auto; max-width: 128px; height: 24px; box-sizing: border-box;
  padding: 0 24px 0 9px !important; font-size: 11.5px; border-radius: 999px; opacity: .8;
  background-position: right 8px center; }
.lo-ajout .sel-search { width: 150px; }
.lo-ajout .sel-search .combo-list { min-width: 340px; }
.lb-par-offre td:first-child { max-width: 300px; }
/* Les deux onglets du modal des listes tiennent dans l'en-tête, à côté du
   titre — comme ceux du modal des relances. Le tableau « quelle liste pour
   quelle offre » défile tout seul : trente-quatre offres ne rentrent pas dans
   un modal, et faire défiler le modal entier perdrait le bouton d'envoi. */
#listes-modal .modal-head .modal-tabs { margin-left: 18px; flex: 1; }
.lb-po-scroll { max-height: 46vh; overflow-y: auto; }
.lb-po-scroll .data tr:first-child th { position: sticky; top: 0; z-index: 2;
  background: var(--surface); box-shadow: inset 0 -1px 0 var(--hairline); }
/* Les campagnes qui visent une liste : savoir quand le dernier mail de
   bienvenue est parti, c'est savoir si les personnes inscrites cette semaine
   l'attendent encore. */
.lb-campagnes { margin: 0 0 12px; padding: 9px 11px; border-radius: 10px;
  background: var(--page); border: 1px solid var(--hairline); }
.lb-campagnes .check-item { border-bottom-color: var(--surface); }
/* Une pastille par liste posée, parce qu'il peut y en avoir plusieurs :
   « inscription listes cds (276 et 298) ». Le menu en dessous en ajoute une
   autre ; la croix en retire une seule. */
.seq-pastille { display: flex; align-items: center; gap: 4px; margin: 0 0 2px;
  padding: 2px 4px 2px 8px; border-radius: 999px;
  background: var(--sem-care-bg); color: var(--sem-care-t); font-size: 11px; }
.seq-pastille .sp-nom { flex: 1; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
/* La croix qui défait — partout la même : pastille de liste, colonne
   « Bienvenue », gestes B-Sport. Elle n'était stylée QUE dans la pastille, et
   sortait ailleurs en bouton natif, avec sa boîte grise (vu le 15/09/2026). */
.sp-quand { flex: none; font-size: 10.5px; font-weight: 600; color: var(--sem-attente-t);
  background: var(--sem-attente-bg); border-radius: 999px; padding: 0 6px; margin-left: 4px;
  white-space: nowrap; }
.sp-x { flex: none; border: 0; background: transparent; cursor: pointer;
  padding: 0 3px; margin: 0; line-height: 1; font: inherit; font-size: 11px;
  color: var(--muted); opacity: .55; border-radius: 4px;
  transition: opacity .12s, color .12s; }
.sp-x:hover, .sp-x:focus-visible { opacity: 1; color: var(--sem-defaut-t); outline: none; }
/* Le menu redevient discret quand une liste est déjà posée : il n'est plus le
   sujet, il sert à en AJOUTER une autre. */
.seq-cell select.posee-vide { border-style: dashed; color: var(--muted);
  background-color: transparent; font-weight: 400; }
/* Le mail de bienvenue : à une personne, avec le modèle de son offre. Trois
   états, trois couleurs — parti, en file, raté — parce qu'un courrier parti ne
   se rattrape pas et qu'on doit le voir sans survoler. */
.acces-log .col-bienvenue { width: 104px; }
.bv-envoi { display: flex; flex-direction: column; gap: 3px; margin: 0; }
.bv-envoi input[type="date"] { width: 100%; font-size: 11.5px; padding: 3px 6px;
  border: 1px dashed var(--hairline); border-radius: 7px; background: transparent;
  color: var(--muted); }
.bv-envoi input[type="date"]:hover { border-style: solid; border-color: var(--accent-soft); background: var(--surface); }
/* « à l'ouverture » : le courrier de bienvenue suit l'ouverture des accès,
   il ne se propose pas avant. Discret, mais cliquable — il mène au geste. */
.bv-apres { font-size: 11.5px; color: var(--muted); border-bottom: 1px dotted var(--hairline); }
.bv-apres:hover { color: var(--accent); border-bottom-color: var(--accent); }
.bv-faite { display: inline-block; font-size: 11px; font-weight: 600;
  color: var(--sem-facture-t); cursor: help; }
.bv-ratee { display: inline-block; font-size: 11px; font-weight: 600;
  color: var(--sem-defaut-t); cursor: help; }
/* Le même état, mais cliquable : l'échec rouvre le choix du modèle. */
button.bv-ratee { background: none; border: 0; padding: 0; cursor: pointer;
  font-family: inherit; }
button.bv-ratee:hover { text-decoration: underline; }
.bv-file { display: flex; align-items: center; gap: 2px; margin: 0; }
.bv-box { width: 620px; }
.bv-liste { max-height: 260px; }
.bv-liste .lb-dispo { cursor: pointer; }
.bv-barre { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 10px; }
.bv-barre .grow { flex: 1; min-width: 120px; }
.bv-conseil { background: var(--good-tint); color: var(--good-text); }
.bv-prevue { flex: 1; font-size: 11px; font-weight: 600; color: var(--sem-attente-t); cursor: help; }

/* ---- Cartes B-Sport, le poste de Laure (HH-2564) --------------------------
   Même table que la file des accès (`.acces-log`) ; seules ses colonnes
   propres sont réglées ici. */
.bsport-log .col-geste { width: 118px; }
.bs-faite { display: inline-flex; align-items: center; gap: 4px; margin: 0; }
.bs-faite .bv-faite.muted { color: var(--muted); font-weight: 500; }

/* ---- La ligne DIT, le modal FAIT (HH-2549) --------------------------------
   Les trois gestes tenaient dans trois colonnes étroites, chacune avec ses
   menus et ses dates : illisible, et on l'a dit. La ligne ne porte plus que
   l'état ; tout ce qui se règle s'ouvre dans le modal de la ligne. */
.acces-log .col-accueil { width: 210px; }
.ac-etats { display: flex; flex-wrap: wrap; gap: 3px; }
.ac-e {
  padding: 2px 8px; border-radius: 999px; font-size: 10.5px; font-weight: 600;
  background: var(--page); color: var(--muted);
  box-shadow: inset 0 0 0 1px var(--hairline); cursor: help;
}
/* L'état EST le bouton : il n'y a plus de « Traiter » à côté de lui. */
a.ac-e { cursor: pointer; text-decoration: none; transition: box-shadow .12s, color .12s; }
a.ac-e:hover { color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
a.ac-e.ok:hover { box-shadow: inset 0 0 0 1px var(--good-text); color: var(--good-text); }
a.ac-e.en-attente { opacity: .55; }
.ac-e.ok { background: var(--good-tint); color: var(--good-text); box-shadow: none; }
.ac-e.file { background: var(--sem-attente-bg); color: var(--sem-attente-t); box-shadow: none; }
.ac-e.ko { background: var(--sem-defaut-bg); color: var(--sem-defaut-t); box-shadow: none; }

/* Le modal d'une ligne : trois sections, une par geste, chacune avec « le
   faire » et « c'est déjà fait ailleurs ». */
.ge-box { width: 720px; }
/* L'offre achetée : ce qui décide des cours, du courrier et des listes. Elle
   se lit donc comme une étiquette, pas comme une note de bas de page. */
.ge-offre { display: inline-flex; align-items: center; padding: 2px 10px; border-radius: 999px;
  font-size: 12.5px; font-weight: 600; color: var(--sem-acces-t);
  background: var(--sem-acces-bg); max-width: 100%; }
.ge-entete { display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  font-size: 12px; margin-bottom: 14px; }
.ge-bloc { border: 1px solid var(--hairline); border-radius: 12px;
  padding: 12px 14px; margin-bottom: 10px; background: var(--surface); }
.ge-titre { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; font-size: 13.5px; }
.ge-ligne { display: flex; align-items: center; gap: 8px; margin: 0 0 8px; flex-wrap: wrap; }
/* Où elle est déjà, en premier — puis le geste, puis le réglage. */
.ge-inscrite { display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  margin-bottom: 10px; }
.ge-pied { display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: wrap; margin-top: 10px; padding-top: 9px;
  border-top: 1px solid var(--hairline); }
.ge-pied .ge-quand { margin: 0; }
/* HH-2558 — les quatre étapes de l'ouverture, et le chercheur de cours. */
.ge-etapes { list-style: none; margin: 0 0 10px; padding: 0; display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 6px; }
.ge-etapes li { display: flex; flex-direction: column; gap: 2px; padding: 6px 9px;
  border-radius: 9px; background: var(--page); box-shadow: inset 0 0 0 1px var(--hairline);
  font-size: 11.5px; }
.ge-etapes li.ok { background: var(--good-tint); box-shadow: none; }
.ge-etapes li.ko { background: var(--sem-defaut-bg); box-shadow: none; }
.ge-etape-l { font-weight: 600; }
.ge-etapes li.ok .ge-etape-l::before { content: "✓ "; color: var(--good-text); }
.ge-etapes li.ko .ge-etape-l::before { content: "✕ "; color: var(--sem-defaut-t); }
.ge-etape-d { color: var(--muted); font-size: 11px; }
.ge-etape-d.ko { color: var(--sem-defaut-t); }
.ge-ouvrir { margin: 0; }
.ge-ouvrir .ge-ajout { flex: 1 0 100%; }
/* `.ge-ligne` pose `margin: 0 0 8px` APRÈS `.mt8` dans la feuille, et gagne :
   le bouton arrivait collé à la liste des cours. On le dit ici, plus précis. */
.ge-ouvrir .ge-ligne { margin-top: 12px; }
.ge-deja { margin-top: 12px; }
.ge-deja .ge-ouvrir { margin-top: 8px; }
/* Le choix des cours : une boîte, son filtre en tête, les cours dedans. Le
   NOM d'abord — le numéro Tutor le précédait en pastille violette et prenait
   la vedette sur ce qu'on cherche vraiment. */
.ge-picker { border: 1px solid var(--hairline); border-radius: 10px;
  background: var(--page); overflow: hidden; }
.ge-chercher { display: flex; align-items: center; gap: 7px; padding: 6px 10px;
  border-bottom: 1px solid var(--hairline); background: var(--surface); color: var(--muted); }
.ge-chercher input[type=search] { flex: 1; min-width: 0; border: 0; background: none;
  padding: 2px 0; font-size: 12.5px; box-shadow: none; }
.ge-chercher input[type=search]:focus { outline: none; box-shadow: none; border: 0; }
.ge-cours { display: flex; flex-direction: column; gap: 1px;
  max-height: 188px; overflow-y: auto; padding: 4px; }
.ge-cours-l { display: flex; align-items: center; gap: 9px; padding: 5px 8px;
  border-radius: 7px; cursor: pointer; font-size: 12.5px; }
.ge-cours-l:hover { background: var(--surface); }
.ge-cours-l input[type=checkbox] { flex: none; margin: 0; }
.ge-cours-nom { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; color: var(--ink-2); }
/* Le numéro Tutor garde sa pastille violette : c'est par lui qu'on retrouve
   un cours dans le LMS, et la couleur le rend cherchable à l'œil. */
.ge-cours-num { flex: none; min-width: 46px; text-align: center; padding: 2px 7px;
  border-radius: 7px; background: var(--sem-care-bg); color: var(--sem-care-t);
  font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums; }
.ge-cours-l:has(input:checked) { background: var(--accent-soft); }
.ge-cours-l:has(input:checked) .ge-cours-nom { color: var(--ink); font-weight: 600; }
/* Le compteur de cochés, à côté du titre : une pastille, pas une étiquette
   grise perdue dans un résumé de dépliant. */
/* Une formation que l'offre inclut : marquée dans la liste, et la ligne le
   dit d'un mot. Ce n'est pas une alerte — c'est un repère pour vérifier. */
.ge-cours-l.incluse { background: color-mix(in srgb, var(--sem-care) 9%, transparent); }
.ge-cours-l.incluse .ge-cours-nom { font-weight: 600; color: var(--ink); }
.ge-cours-inc { flex: none; font-size: 10px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--sem-care-t); }
.ge-incluses { font-size: 10.5px; font-weight: 700; letter-spacing: 0; text-transform: none;
  color: var(--sem-care-t); background: var(--sem-care-bg); border-radius: 999px; padding: 1px 8px; }
.ge-incluses.manque { color: var(--sem-attente-t); background: var(--sem-attente-bg); }
/* Les puces d'une formation, dans « Quelle formation pour quelle offre ». */
.lo-cours { --lo: #6b2f8f; }
.ge-choisis { font-size: 10.5px; font-weight: 700; letter-spacing: 0; text-transform: none;
  color: var(--accent-strong); background: var(--accent-soft); border-radius: 999px; padding: 1px 8px; }
.lb-usage select { font-size: 11px; padding: 2px 6px; max-width: 170px; }
/* L'aide, en info-bulle : un petit « ? » à côté de ce qu'il explique, et rien
   d'écrit sous les champs — un label et un placeholder suffisent. */
.aide-tip { display: inline-flex; align-items: center; justify-content: center;
  width: 15px; height: 15px; border-radius: 50%; font-size: 10px; font-weight: 700;
  line-height: 1; color: var(--muted); box-shadow: inset 0 0 0 1px var(--hairline);
  cursor: help; vertical-align: middle; margin-left: 5px; flex: none; }
.aide-tip:hover { color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.ge-ligne:last-child { margin-bottom: 0; }
/* Les listes conseillées d'une ligne (HH-2577) : une rangée par liste, le
   point de couleur pour le rôle, le nom entier, « Inscrire » petit à droite.
   Trois gros boutons bleus empilés disaient « fais-moi » trois fois. */
.ge-conseils-titre { display: flex; align-items: center; gap: 6px; margin: 8px 0 4px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
.ge-conseils { display: flex; flex-direction: column; gap: 4px; margin-bottom: 8px; }
.ge-conseil { display: flex; align-items: center; gap: 8px; margin: 0; padding: 5px 6px 5px 9px;
  border: 1px solid var(--hairline); border-radius: 9px; background: var(--page); font-size: 12.5px; }
.lo-dot { flex: none; width: 8px; height: 8px; border-radius: 999px; background: var(--lo, var(--muted)); }
.ge-conseil-role { flex: none; font-size: 10px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--lo, var(--muted)); width: 66px; }
.ge-conseil-nom { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); }
.ge-conseil .btn.xs { flex: none; }
.ge-autre { margin-bottom: 8px; }
/* Les listes DANS le geste d'ouverture : une case par liste, cochée d'office
   pour celles de l'offre, « + Autre liste… » pour en ajouter. */
.ge-listes { display: flex; flex-direction: column; gap: 4px; margin-top: 10px; }
.ge-case { display: flex; align-items: center; gap: 8px; margin: 0; padding: 5px 9px;
  border: 1px solid var(--hairline); border-radius: 9px; background: var(--page);
  font-size: 12.5px; cursor: pointer; }
.ge-case input[type=checkbox] { margin: 0; flex: none; }
.ge-case-quand { flex: none; font-size: 10.5px; color: var(--muted); white-space: nowrap; }
.ge-listes .lo-select, .ge-listes .sel-search { align-self: flex-start; margin-top: 2px; }
.ge-listes .sel-search { width: 180px; }
.ge-listes .sel-search .combo-list { min-width: 340px; }
.ge-note { font-size: 11.5px; color: var(--muted); margin-top: 2px; }
/* « Mettre les listes de son offre » : le geste qu'on vient faire. Assez
   visible pour qu'on le voie, pas un bouton primaire — le bouton primaire de
   ce bloc reste « Ouvrir ses accès ». */
.ge-defaut { display: inline-flex; align-items: center; gap: 7px; align-self: flex-start;
  font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer;
  padding: 6px 13px; border-radius: 9px; color: var(--accent-strong);
  background: var(--accent-soft); border: 1px dashed color-mix(in srgb, var(--accent) 45%, transparent);
  transition: background .12s, border-color .12s; }
.ge-defaut:hover, .ge-defaut:focus-visible { border-style: solid; border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 14%, transparent); outline: none; }
.ge-defaut svg { color: var(--accent); }
.ge-quand-choix { display: flex; align-items: center; gap: 8px; margin-top: 4px; }
.ge-quand-choix input[type=date] { width: auto; padding: 3px 8px; font-size: 12px; }
/* Ce qui manque à l'offre se lit en pastille, le détail en infobulle ; la
   date de la séquence n'apparaît que si on en veut une autre que demain 9 h. */
.ge-modele label .aide-tip { margin-left: 4px; }
.ge-incluses.attention { color: var(--sem-attente-t); background: var(--sem-attente-bg); }
.ge-quand-choix label, .ge-quand label { display: flex; align-items: center; gap: 8px; margin: 0; }
.ge-quand-choix label[hidden], .ge-quand label[hidden] { display: none; }
.ge-quand-btn { gap: 6px; color: var(--ink-2); }
.ge-quand-btn svg { color: var(--muted); }
.ge-quand-changer { color: var(--accent-strong); font-weight: 600; }
.ge-quand-changer::before { content: "·"; margin-right: 6px; color: var(--muted); font-weight: 400; }
.ge-sous { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--hairline); }
.ge-note.manque { color: var(--sem-attente-t); }
/* Deux chemins pour le même courrier : on le dit, on ne tranche pas. */
.ge-note.attention { color: var(--sem-attente-t); background: var(--sem-attente-bg);
  border-radius: 8px; padding: 5px 9px; cursor: help; font-weight: 600; }
/* « En ouvrant » : l'aperçu de la chaîne, sous le bouton, avant de cliquer. */
.ge-apercu { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; margin-top: 8px;
  font-size: 11.5px; color: var(--ink-2); }
.ge-apercu-t { flex: none; font-size: 10px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--muted); margin-right: 2px; }
.ge-apercu-item { display: inline-flex; align-items: center; gap: 5px; padding: 1px 8px;
  border-radius: 999px; background: var(--page); border: 1px solid var(--hairline); max-width: 100%; }
.ge-apercu-item.manque { color: var(--sem-attente-t); background: var(--sem-attente-bg); border-color: transparent; }
.ge-apercu-item .lo-dot { width: 6px; height: 6px; }
.ge-autre .lo-select { max-width: 160px; }
.ge-autre .sel-search { width: 180px; }
.ge-autre .sel-search .combo-list { min-width: 340px; }
.ge-ligne .grow { flex: 1; min-width: 140px; }
.ge-quand { display: inline-flex; align-items: center; gap: 5px; font-size: 12px;
  color: var(--ink-2); }
.ge-quand input[type="date"] { width: 132px; }
.ge-role { display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  padding: 6px 0; border-top: 1px solid var(--page); }
.ge-role-l { flex: 0 0 132px; font-size: 11.5px; color: var(--muted); }
.ge-role .seq-pastille { margin: 0; max-width: 260px; }
/* « ＋ ajouter » est un BOUTON, et le choix n'apparaît qu'après. Un menu
   déroulant posé en permanence sous chaque ligne, c'est ce qui rendait la
   cellule illisible. */
.ge-ajout > summary { cursor: pointer; font-size: 11.5px; font-weight: 600;
  color: var(--accent); list-style: none; padding: 2px 8px; border-radius: 999px;
  border: 1px dashed var(--hairline); }
.ge-ajout > summary::-webkit-details-marker { display: none; }
.ge-ajout > summary:hover { border-style: solid; border-color: var(--accent); }
.ge-ajout[open] { flex: 1 0 100%; margin-top: 6px; }
/* Le geste d'ouverture : déplié tant qu'il reste à faire, replié une fois les
   accès ouverts. Un seul exemplaire du formulaire — deux copies finiraient
   par diverger. */
/* ── Le modal d'une ligne, refondu (HH-2585) ────────────────────────────────
   Trois sections, un seul style de titre, et les gestes de second rang
   ensemble tout en bas. Avant : des titres de trois graisses différentes, des
   étapes en boîtes bordées qui répétaient la même heure quatre fois, et deux
   liens gris perdus entre les blocs. « Sale », et c'était vrai. */
.ge-sect-t { display: flex; align-items: center; gap: 8px; margin: 16px 0 7px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted); }
.ge-sect-t > span:first-child { color: var(--ink-2); }
.ge-sect-t::after { content: ""; flex: 1; height: 1px; background: var(--hairline); }
.ge-sect-t .badge { order: 1; }
.ge-sect-t2 { margin-top: 13px; }
.ge-bloc > .ge-sect-t:first-child { margin-top: 0; }

/* Les quatre étapes : une rangée de pastilles, le détail en infobulle. */
.ge-etapes { display: flex; flex-wrap: wrap; gap: 5px; margin: 0 0 4px; padding: 0; list-style: none; }
.ge-etapes > li { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px 3px 8px;
  border-radius: 999px; font-size: 12px; color: var(--muted);
  background: var(--page); border: 1px solid var(--hairline); cursor: help; }
.ge-etapes > li.ok { color: var(--good-text); background: var(--sem-facture-bg); border-color: transparent; }
.ge-etapes > li.ko { color: var(--sem-defaut-t); background: var(--sem-defaut-bg); border-color: transparent; }
.ge-etape-p { flex: none; font-weight: 700; font-size: 11px; }
.ge-etapes > li .ge-etape-l { font-weight: 600; }

/* HH-2642 — le cahier « déjà fait à la main », à l'écart du geste réel.
   Un cadre pointillé sur le fond de page, pas une carte de plus : on doit voir
   d'un coup d'œil que ce n'est pas l'endroit d'où l'on ENVOIE. Trois rangées,
   une par geste, l'état à droite, et le formulaire se déplie sous sa rangée. */
.ge-main { margin-top: 18px; padding: 0 14px; border-radius: 12px;
  border: 1px dashed color-mix(in srgb, var(--ink-2) 38%, transparent);
  background: var(--page); }
.ge-main > summary.ge-main-t { list-style: none; display: flex; align-items: center; gap: 10px;
  padding: 9px 0; margin: 0; cursor: pointer; font-size: 12.5px; font-weight: 600; color: var(--ink); }
.ge-main > summary::-webkit-details-marker { display: none; }
.ge-main > summary::before { content: none; }
.ge-main > summary::after { content: "›"; margin-left: auto; color: var(--muted);
  font-size: 15px; line-height: 1; transition: transform .15s ease; }
.ge-main[open] > summary::after { transform: rotate(90deg); }
.ge-main-ico { flex: none; width: 26px; height: 26px; border-radius: 50%;
  display: grid; place-items: center; background: var(--surface);
  box-shadow: inset 0 0 0 1px var(--hairline); color: var(--ink-2); }
.ge-main-releve { margin: 0 0 8px; }
.ge-main-releve .btn { gap: 5px; }
.ge-main[open] { padding-bottom: 4px; }
.ge-main-gestes { display: flex; flex-direction: column; }
.ge-main-g { border-top: 1px solid var(--hairline); }
.ge-main-g > summary { list-style: none; display: flex; align-items: center; gap: 9px;
  padding: 8px 6px; margin: 0; cursor: pointer; font-size: 12.5px; color: var(--ink-2);
  border-radius: 8px; }
.ge-main-g > summary::-webkit-details-marker { display: none; }
.ge-main-g > summary::before { content: none; }
.ge-main-g > summary:hover { background: var(--surface); }
.ge-main-g > summary > svg { flex: none; color: var(--muted); }
.ge-main-l { flex: 1; font-weight: 600; color: var(--ink); }
.ge-main-g > summary::after { content: "›"; flex: none; color: var(--muted);
  font-size: 15px; line-height: 1; transition: transform .15s ease; }
.ge-main-g[open] > summary::after { transform: rotate(90deg); }
.ge-main-etat { flex: none; font-size: 11px; padding: 2px 8px; border-radius: 999px;
  background: var(--surface); box-shadow: inset 0 0 0 1px var(--hairline); color: var(--muted); }
.ge-main-etat.ok { background: var(--good-tint); color: var(--good-text); box-shadow: none; }
.ge-main-f { margin: 2px 6px 14px 29px; }
.ge-main-f .ge-picker { background: var(--surface); }
.ge-picker-court .ge-cours { max-height: 150px; }
.ge-main-champs { display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-end; }
.ge-main-champ { display: flex; flex-direction: column; gap: 3px; }
.ge-main-champ.grow { flex: 1 1 220px; }
.ge-main-champ input[type=date] { width: auto; }
.ge-main-listes { display: flex; flex-direction: column; gap: 4px; margin-bottom: 10px; }
.ge-main-listes .ge-case { background: var(--surface); }
.ge-main-pied { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 10px; }
@media (prefers-reduced-motion: reduce) { .ge-main-g > summary::after { transition: none; } }
@media (max-width: 640px) { .ge-main-f { margin-left: 6px; } }

/* Les gestes de second rang, au pied du modal. */
.ge-pied-actions { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 6px 18px;
  margin-top: 16px; padding-top: 11px; border-top: 1px solid var(--hairline); }
.ge-pied-actions .ge-deja { flex: 1 0 auto; }
/* Le dépliant prend l'habit d'un bouton : un lien bleu souligné avec son
   chevron et son rond d'aide, posé à côté d'un vrai bouton, se lit comme deux
   familles de gestes alors que c'en est une. */
.ge-pied-actions .ge-deja > summary { margin: 0; list-style: none; width: auto;
  display: inline-flex; color: var(--ink-2); }
.ge-pied-actions .ge-deja > summary::-webkit-details-marker { display: none; }
.ge-pied-actions .ge-deja > summary::before { content: none; }
.ge-pied-actions .ge-deja[open] > summary { background: var(--page); }
.ge-quand { display: flex; align-items: center; gap: 8px; margin: 8px 0 0; }
.ge-quand input[type=date] { width: auto; }

/* L'option présentielle d'une offre : une rangée, pas un bloc. Elle dit ce
   que l'offre inclut et si la place est prise — le geste lui-même vit dans
   l'événement, où il y a la place pour le tarif et l'hébergement. */
.ge-presentiel { display: flex; align-items: center; gap: 9px; margin: 0;
  padding: 7px 11px; border-radius: 9px; font-size: 12.5px;
  background: var(--page); border: 1px solid var(--hairline); color: var(--ink-2); }
.ge-presentiel svg { flex: none; color: var(--sem-vente-t); }
.ge-pres-nom { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; font-weight: 600; color: var(--ink); }
.ge-pres-quand { flex: none; font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.ge-pres-etat { flex: none; font-size: 11.5px; font-weight: 700; color: var(--good-text); }
.ge-presentiel.manque { background: var(--sem-attente-bg); }
.ge-presentiel.manque .ge-pres-quand { color: var(--sem-attente-t); font-weight: 600; cursor: help; }
/* Le point qui dit « il y a à lire » sur une date : qui l'a posée, et la
   période enregistrée. Deux lignes de gris sous chaque champ pesaient plus
   que ce qu'elles apprenaient. */
.acces-detail { display: inline-block; margin-left: 6px; width: 14px; text-align: center;
  color: var(--muted); opacity: .5; cursor: help; font-weight: 700; line-height: 1; }
.acces-detail:hover { opacity: 1; color: var(--accent); }
.ge-refaire > summary { cursor: pointer; font-size: 12px; color: var(--accent);
  list-style: none; margin: 8px 0 2px; display: flex; align-items: center; gap: 6px; }
.ge-refaire > summary::-webkit-details-marker { display: none; }
.ge-refaire[data-toujours] > summary { display: none; }
.ge-deja > summary { cursor: pointer; font-size: 12px; color: var(--accent);
  list-style: none; margin-top: 4px; }
.ge-deja > summary::-webkit-details-marker { display: none; }
.ge-deja > summary::before { content: "› "; }
.ge-deja[open] > summary::before { content: "⌄ "; }
.lien-bouton { border: 0; background: none; padding: 0; cursor: pointer;
  color: var(--accent); font: inherit; text-decoration: underline; }

/* ══════════════ « Quelle offre a-t-elle achetée ? » ══════════════
   La question qui remplace les offres que la plateforme s'inventait.
   Ambre plutôt que rouge : ce n'est pas une panne, c'est une question dont
   la réponse tient en un clic. Le rouge est réservé à ce qui bloque. */
.oa-bande { display: flex; align-items: center; gap: 12px; margin: 0 0 14px;
  padding: 11px 14px; border-radius: 10px;
  border: 1px solid #ecd3a1;
  background: var(--sem-attente-bg); }
.oa-bande .oa-b-ico { font-size: 16px; line-height: 1; flex: 0 0 auto; }
.oa-bande .oa-b-txt { flex: 1; font-size: 13px; line-height: 1.5; }
/* L'attente d'une commande ne demande RIEN : elle se raconte plus bas. */
.oa-douce { border-color: var(--hairline); background: var(--page); }
/* Une décision de l'IA n'est pas une alerte : c'est une information, avec de
   quoi la défaire. Bleu accent, pas d'ambre — rien n'est en attente ici. */
.oa-bande.oa-ia { border-color: var(--accent-soft); background: var(--sem-vente-bg); }
.oa-bande.oa-ia .oa-b-ico { color: var(--accent); }

.oa-corps { padding: 14px 16px 16px; display: flex; flex-direction: column; gap: 10px; }
.oa-vendu { display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; }
.oa-v-nom { font-weight: 650; font-size: 14.5px; line-height: 1.35; }
.oa-v-meta { font-size: 12px; color: var(--muted); white-space: nowrap;
  font-variant-numeric: tabular-nums; }
.oa-cherche { width: 100%; }
.oa-corps .oa-liste { gap: 0; max-height: 46vh; border: 1px solid var(--hairline);
  border-radius: 9px; padding: 4px; }
.oa-groupe { font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted); padding: 8px 8px 4px; }
.oa-corps .oa-opt { position: relative; align-items: center; gap: 9px; padding: 7px 8px;
  border: 0; border-radius: 7px; background: none; }
.oa-corps .oa-opt:hover { background: var(--page); }
.oa-corps .oa-opt.choisie { background: var(--sem-vente-bg); box-shadow: none; }
.oa-corps .oa-opt input { position: absolute; opacity: 0; pointer-events: none; }
.oa-o-nom { flex: 1; min-width: 0; font-size: 13.5px; }
.oa-opt.choisie .oa-o-nom { font-weight: 600; }
.oa-o-prix { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums;
  white-space: nowrap; }
.oa-pourquoi { width: 16px; height: 16px; border-radius: 999px; font-size: 10.5px;
  display: inline-grid; place-items: center; color: var(--muted);
  border: 1px solid var(--hairline); cursor: help; }
.oa-vide { padding: 14px 8px; font-size: 13px; color: var(--muted); }
.oa-ecart { font-size: 12.5px; padding: 7px 10px; border-radius: 8px;
  border: 1px solid #ecd3a1; background: var(--sem-attente-bg); color: var(--sem-attente-t); }
.oa-modes { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.oa-mode { position: relative; display: flex; align-items: center; justify-content: center;
  text-align: center; min-height: 38px; padding: 6px 10px; border-radius: 9px; cursor: pointer;
  border: 1px solid var(--hairline); background: var(--surface); font-size: 13px; font-weight: 600;
  line-height: 1.25; }
.oa-mode:hover { border-color: var(--accent); }
.oa-mode.on { border-color: var(--accent); background: var(--sem-vente-bg); color: var(--accent-strong); }
.oa-mode input { position: absolute; opacity: 0; pointer-events: none; }
.oa-mode:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.oa-panneau { display: flex; flex-direction: column; gap: 8px; }
.oa-panneau[hidden] { display: none; }
.oa-prix-ko { font-size: 11px; font-weight: 700; padding: 1px 7px; border-radius: 999px;
  color: var(--sem-attente-t); background: var(--sem-attente-bg); border: 1px solid #ecd3a1; }
.oa-nouvelle { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 12px; }
.oa-nouvelle > label { display: flex; flex-direction: column; gap: 4px; font-size: 12px;
  color: var(--muted); }
.oa-nouvelle > label > input, .oa-nouvelle > label > select, .oa-nouvelle > label .fld-in { width: 100%; }
.oa-nouvelle .plans { margin: 2px 0 0; min-width: 0; }
.oa-n-large { grid-column: 1 / -1; }
.oa-par { font-size: 11.5px; color: var(--muted); min-height: 1em; }
@media (max-width: 560px) {
  .oa-modes { grid-template-columns: 1fr; }
  .oa-nouvelle { grid-template-columns: 1fr; }
}
.oa-plus { margin-left: 4px; padding: 0 6px; border-radius: 999px; font-size: 11px;
  background: color-mix(in srgb, #fff 25%, transparent); }
.oa-corps .modal-actions { margin-top: 2px; }
.oa-commande { padding: 10px 12px; border-radius: 9px; background: var(--page);
  border: 1px solid var(--hairline); margin-bottom: 14px; }
.oa-c-t { font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted); margin-bottom: 3px; }
.oa-c-nom { font-weight: 650; font-size: 14px; line-height: 1.35; }
.oa-c-meta { display: flex; flex-wrap: wrap; gap: 6px 10px; margin-top: 5px;
  font-size: 12px; color: var(--muted); }
.oa-c-meta .oa-tunnel { color: var(--ink); font-weight: 600; }

.oa-liste { display: flex; flex-direction: column; gap: 6px; max-height: 42vh;
  overflow: auto; }
.oa-opt { display: flex; align-items: flex-start; gap: 10px; cursor: pointer;
  padding: 9px 11px; border: 1px solid var(--hairline); border-radius: 9px;
  background: var(--surface); }
.oa-opt:hover { border-color: var(--accent); }
.oa-opt.choisie { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.oa-opt input { margin-top: 3px; flex: 0 0 auto; }
.oa-o-corps { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1; }
.oa-o-haut { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.oa-o-haut b { font-size: 13.5px; }
.oa-o-bas { display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  font-size: 11.5px; color: var(--muted); }
.oa-fam { display: inline-flex; align-items: center; gap: 4px; }
.oa-type, .oa-raison { padding: 1px 7px; border-radius: 999px;
  background: var(--page); border: 1px solid var(--hairline); }
.oa-pct { font-size: 11px; font-weight: 700; padding: 1px 7px; border-radius: 999px;
  color: #fff; background: var(--accent); }
.oa-motif { font-size: 11.5px; color: var(--muted); font-style: italic;
  line-height: 1.4; }
.oa-ia { border-color: var(--accent); }

.pv-quandmeme { display: block; margin-top: 9px; font-size: 12px; }

.oa-autre { display: block; margin-top: 12px; }
.oa-portee { margin: 10px 0 0; font-size: 12px; line-height: 1.5;
  color: var(--muted); }

/* Le registre : l'attente se dit en une pastille, pas en un paragraphe. */
.pu-attente { display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 7px; border-radius: 999px; font-size: 11px; font-weight: 600;
  border: 1px solid #ecd3a1;
  background: var(--sem-attente-bg); color: var(--sem-attente-t); white-space: nowrap; }

/* ═══════════════════════════════════════════════════════════════════════════
   HH-2588 — « Desde mi portátil se ve todo super apelotonado y agobiante »
   ═══════════════════════════════════════════════════════════════════════════
   Écran de la plainte : portable 1 440 × 900 logiques. Barre latérale
   déployée (240) + gouttières de `.content` (56) = il reste 1 144 px pour
   travailler. Deuxième cible 1 280 (≈ 984 px), troisième 1 100 (≈ 804 px).

   QUATRE PALIERS, et rien d'autre. Les quarante-six correctifs d'origine
   proposaient dix-sept seuils différents entre 1 280 et 1 700 px ; ils sont
   ramenés ici à quatre familles, une requête média chacune, dans l'ordre
   squelette → écrans :

     1600  « écran étroit »   — en dessous, un vis-à-vis dont un des deux
                                côtés a une largeur FIXE (diagramme de 1 002 px,
                                table de trésorerie de 300 px, panneau de
                                l'eshop de 320 px, donut de 146 px) n'a plus de
                                quoi loger l'autre côté. On empile.
     1520  « portable »       — le 1 440 de la plainte. Densité : gouttières,
                                rembourrages, planchers d'intitulés. Le seuil
                                est AU-DESSUS de 1 440 et pas à 1 400 : une
                                requête à 1 400 ne se déclenche jamais sur
                                l'écran qui se plaint, elle serait lettre morte
                                là où elle sert.
     1300  « petit portable » — la grille de douze colonnes retombe sur des
                                moitiés, les doubles colonnes sur une seule.
                                1 300 de fenêtre = ~1 000 px de grille, largeur
                                sous laquelle une carte `c3` cesse d'être
                                lisible. L'ancien repli était écrit à 1 000 px
                                de FENÊTRE : il mesurait l'écran au lieu de la
                                place et arrivait ~300 px trop tard.
     760   « tablette »       — palier existant (le rail y est déjà forcé).
                                Tout sur une colonne.

   Une seule mesure, celle de la FENÊTRE, et pas deux systèmes selon l'état du
   menu : sous 1 180 px `base.html` force le rail, donc les deux mesures se
   rejoignent d'elles-mêmes juste sous le palier 1300. Entre 1 181 et 1 300 un
   utilisateur en rail replie un peu tôt — ses cartes deviennent plus larges,
   jamais plus étroites. C'est la direction sûre, et ça vaut mieux que deux
   jeux de seuils à tenir.

   `screen and` sur les quatre : `@media print` (l. 2018) remet
   `.content { padding: 0 }` et une feuille A4 fait ~794 px. Sans le garde,
   ces requêtes arrivant APRÈS dans la source gagneraient sur le papier.
   ═════════════════════════════════════════════════════════════════════════ */


/* ───────────────────────────────────────────────────────────────────────────
   0. LE SOCLE — ce qui est faux à TOUTE largeur
   ───────────────────────────────────────────────────────────────────────────
   Hors requête média, donc oui : ces règles changent aussi le grand écran.
   C'est voulu, et c'est le seul endroit où ça l'est. Une colonne figée à
   124 px qui coupe son crayon le coupe aussi sur un 27 pouces ; une ligne de
   coordonnées masquée par un sélecteur est masquée partout ; une grille qui
   fabrique des pistes vides en fabrique DAVANTAGE quand l'écran grandit. Ce
   ne sont pas des défauts de densité, ce sont des défauts tout court. Tout
   ce qui n'est qu'une question de place vit dans un palier, plus bas.
   ─────────────────────────────────────────────────────────────────────────── */

/* ── Un bouton d'action n'est pas un onglet ─────────────────────────────────
   Le script de `base.html` dépose les boutons de la page DANS la tira, qui est
   en `flex-wrap: nowrap`. Les onglets y sont en `flex: none` ; le bloc
   d'actions, lui, garde le `flex-shrink` par défaut ET un `flex-wrap: wrap` :
   c'est donc LUI, et lui seul, qu'on écrase. Il n'attend même pas le
   débordement — il empile ses six boutons du registre des ventes sur deux
   rangs et fait grandir la barre, exactement ce que le commentaire de
   `.tabstrip` interdit (« la barre d'onglets ne doit jamais gagner en
   hauteur »).

   On lui rend sa taille et on lui interdit d'empiler. Ce qui déborde alors,
   ce sont les ONGLETS — et eux peuvent défiler sans rien perdre, puisqu'ils
   sont aussi dans le menu latéral. Le bouton principal, non : il n'existe
   nulle part ailleurs, et un bouton emporté par le défilement n'existe plus
   (sur macOS la barre ne se montre même pas pour dire qu'il y a une suite).
   D'où le `sticky` : les onglets glissent DESSOUS, « + Nouvelle vente » reste
   au bord droit. Le fond est celui du corps, sans quoi on verrait les onglets
   passer au travers. */
.tabstrip > .tab-actions {
  flex: none; flex-wrap: nowrap;
  position: sticky; right: 0; z-index: 3;
  background: var(--page);
  padding-left: 14px;
}

/* ── Fiche contact · la ligne de coordonnées n'est pas un sous-titre ────────
   `.page-head .sub` (0,2,0, l. 1344) masque les sous-titres de page et passe
   devant `.fc-coord` (0,1,0, l. 5044) : les deux règles sont hors requête
   média, donc la ligne est masquée à TOUTE largeur. Or ici `.sub` ne porte
   pas une phrase d'explication mais de la donnée — e-mail, téléphone, pays,
   ancienneté, repère Sellsy — et c'est le seul endroit de l'écran où elle est
   écrite. On ouvre la fiche d'une cliente et on ne peut pas lire son adresse.
   C'est le plus grave de tous les défauts relevés, et il n'a rien à voir avec
   la largeur. Trois classes suffisent à repasser devant, sans `!important`.

   La taille est posée explicitement : `.sub` n'a aucune règle de base dans
   cette feuille, la ligne hériterait des 14,5 px du corps de page — à deux
   doigts du h1 de 20 px juste au-dessus. */
.page-head .fc-ident .sub.fc-coord {
  display: flex;
  min-width: 0;
  margin-top: 3px;
  font-size: 12.5px;
  color: var(--muted);
}
/* PIÈGE — l'article flex de `.fc-ident` n'est pas la ligne de coordonnées,
   c'est le div anonyme qui empile le nom et elle. Tant qu'il garde son
   `min-width: auto`, il réclame la largeur min-content de l'adresse la plus
   longue et pousse la recherche de l'en-tête hors du portable : les
   `min-width: 0` posés PLUS BAS dans l'arbre n'y peuvent rien. On ouvre
   d'abord le maillon qui bloque. */
.page-head .fc-ident > div { min-width: 0; }
/* Une adresse longue se replie plutôt que de rogner le reste de l'en-tête.
   `anywhere` et non `break-word` : lui seul abaisse aussi la largeur
   min-content, celle que le calcul flex ci-dessus interroge. */
.page-head .fc-ident .sub.fc-coord > a { min-width: 0; overflow-wrap: anywhere; }

/* ── Calendrier éditorial · deux calendriers, un seul vocabulaire ───────────
   `.cal-grid` et `.cal-head` sont écrits DEUX fois dans cette feuille : pour
   le calendrier éditorial (l. 2591-2592), puis pour celui des closers
   (l. 4870-4876). À spécificité égale, le second gagne. L'éditorial hérite
   donc d'une gouttière de 1 px au lieu de 6, d'un fond de filet et d'un
   `overflow: hidden` : quarante-deux cases à bord arrondi soudées sur un
   aplat gris, et les jours hors mois — transparents par construction — virés
   en trous gris. C'est le « tassé et étouffant » dont la cliente parle, et
   c'est une collision, pas une largeur.

   Deuxième dégât du même choc : `.cal-head` devient un conteneur flex en
   `space-between`. Le `text-align: center` de la l. 2593 survit mais n'a plus
   prise — le texte devient un élément de flex anonyme ajusté au contenu, où
   centrer ne déplace rien : « Lun », « Mar »… se collent à gauche de colonnes
   centrées, avec 10 px de marge basse en trop.

   `:has(> .cal-cell)` désigne l'éditorial et lui seul : la grille des closers
   contient des `.cal-dow` / `.cal-jour`, et son `.cal-head` est la barre
   d'outils SŒUR de la grille, jamais son enfant — d'où le `>`. On rend ce qui
   a été écrasé, aux valeurs de la l. 2591 : rien de plus. */
.cal-grid:has(> .cal-cell) {
  gap: 6px;
  background: none;
  border: 0;
  border-radius: 0;
  overflow: visible;
}
.cal-grid:has(> .cal-cell) > .cal-head { display: block; margin-bottom: 0; }

/* ── Calendrier éditorial · le titre distingue deux publications ────────────
   La pastille était en nowrap + ellipse dans une grille de sept colonnes.
   Mesuré sur la cascade RÉELLE (la règle des closers écrase la gouttière de
   l'éditorial, corrigée juste au-dessus) : ~129 px de texte à 1 440 px,
   ~106 px à 1 280, ~81 px à 1 100. Or la ligne s'ouvre sur le réseau, et
   « Instagram · » pèse douze signes à elle seule : ce que l'ellipse emporte
   est précisément le TITRE. Il en reste huit signes à 1 280 px, trois à
   1 100 px, et deux publications du même jour sur le même réseau deviennent
   deux rectangles identiques — alors que le réseau est déjà porté par la
   couleur et répété dans la légende sous le calendrier.

   On ne coupe donc pas, on passe à la ligne : `.cal-cell` n'a qu'une hauteur
   MINIMALE (88 px), la case s'allonge sans rien recouvrir. On conserve
   l'`overflow: hidden` hérité — inoffensif puisque la case grandit — pour
   qu'un titre d'un seul tenant (une URL) ne déborde pas de la pastille
   arrondie, `break-word` se chargeant de le couper. */
.cal-cell .cal-post {
  white-space: normal;
  overflow-wrap: break-word;
  line-height: 1.3;
  padding-bottom: 4px;
}

/* ── Suivi closing · la colonne des gestes, et le nom qui la payait ─────────
   Deux défauts d'une même table, tous deux INDÉPENDANTS de la largeur : sous
   `table-layout: fixed` ces colonnes ont une largeur déclarée, elles sont
   donc aussi fausses sur un 27 pouces que sur un portable. On les corrige
   ici, et on paie la facture en défilement — jamais sur une autre colonne.

   1) LES GESTES. `.c-act` a été taillée pour QUATRE boutons de 26 px. Mais
   l'étape « Acompte versé » est à la fois gagnée (donc convertible) et active
   (donc signalable « sans nouvelles ») : cette ligne-là porte CINQ gestes —
   ouvrir, vendre, garder, écarter, fiche. Et comme la cellule aligne à droite
   sous `overflow: hidden`, ce qui dépasse est coupé à GAUCHE : ce n'est pas
   le dernier bouton qui disparaissait, c'est le CRAYON — le seul moyen
   d'ouvrir le suivi depuis que la rangée entière n'est plus cliquable.
   5 × 26 px + 4 gouttières de 3 px (`.row-actions > * + *` les donne aussi
   aux <form>, vérifié) = 142 px, + 18 px de rembourrage = 160. On déclare 162 :
   une colonne sans un cheveu de jeu déborde au premier arrondi.
   Les blancs du gabarit entre deux éléments en ligne s'ajoutaient à tout ça.
   `font-size: 0` sur la cellule les annule sans toucher au HTML : elle ne
   contient que des <svg> dimensionnés en attributs, des <form> et des champs
   masqués — aucun texte à perdre, et `.icon-btn` est dimensionné en pixels,
   pas en em.

   2) LE NOM. La cellule « Prospect » porte jusqu'à DEUX pastilles avant le
   nom : « 40 j » (sans nouvelles) et « Vente détectée ». Ensemble elles
   prennent près de 140 px des 202 px utiles de la colonne. Et comme la
   troncature est posée sur la cellule ENTIÈRE, ce n'est pas la fin de la
   ligne qui saute : c'est le NOM qui se fait couper à quatre ou six lettres,
   l'e-mail ayant déjà disparu. C'est exactement ce que HH-2580 refusait — une
   ligne qu'on ne reconnaît plus.

   Écrit sur `th.c-qui` / `th.c-act` et non `.c-qui` / `.c-act` : avec
   `table-layout: fixed` ce sont les cellules de la PREMIÈRE rangée qui fixent
   les colonnes, et le type en plus fait gagner la règle sur la requête à
   1 400 px de la l. 5164, où que ce bloc soit collé dans la feuille. */
.pv-table td.c-act { font-size: 0; }
.pv-table th.c-act { width: 162px; }
.pv-table th.c-qui { width: 264px; }
/* Les deux pastilles au même rembourrage, resserré : rien à lire n'est perdu,
   seulement de l'air qui manquait au nom posé juste à côté. */
.pv-table .pv-detectee { margin-right: 5px; padding: 0 6px 0 5px; gap: 4px; }
.pv-table .pv-alerte   { margin-right: 5px; }

/* Le plancher du tableau, CALCULÉ au lieu d'être promis. `min-width` sur la
   cellule `.c-next` ne garantit rien : en `table-layout: fixed` les colonnes
   sont dimensionnées par `width` sur la première rangée et la colonne sans
   largeur reçoit ce qui RESTE. Mesuré dans le moteur, « Prochaine étape »
   obtenait 100 px sur un portable 1 440 — pas les 150 px que la l. 5145 croit
   poser — et son propre en-tête (« PROCHAINE ÉTAPE », petites capitales
   espacées : 136 px) s'y tronquait. Une colonne dont le TITRE est coupé ne se
   reconnaît plus.
   La seule garantie tenable porte donc sur le TABLEAU : somme des colonnes
   fixes + les 150 px dus à l'élastique.
     264 + 58 + 132 + 64 + 140 + 92 + 170 + 140 + 162 = 1 222, + 150 = 1 372
   Les 82 px que les deux corrections ci-dessus reprennent à l'élastique lui
   sont donc RENDUS par le plancher : on défile un peu plus tôt, ce qui est
   honnête, plutôt que d'écraser « Prochaine étape » pour financer le crayon.
   Aucune autre colonne n'est touchée : reprendre des pixels sur « Closer »,
   « Proba » ou « Dernier RDV » couperait leur en-tête, qui réclame
   respectivement 66, 59 et 99 px rembourrage compris. */
table.pv-table { min-width: 1372px; }
/* Vue d'un closer : sa propre colonne n'est pas rendue (`{% if not es_closer %}`).
   Sans cette ligne on lui ferait défiler 58 px de plus que nécessaire. Un
   navigateur sans `:has()` retombe sur le plancher plein : il défile un peu,
   rien ne casse. */
table.pv-table:not(:has(.c-clo)) { min-width: 1314px; }

/* ── Registre des ventes · le NOM n'est plus la variable d'ajustement ───────
   Le défaut du suivi closing (HH-2580), pris par l'autre bout. `.sales-log`
   est en `table-layout: auto` : ce sont les colonnes SANS largeur qui
   absorbent le manque, et il n'y en a que deux — « Client·e » et « Offre ».
   Tout le reste est rigide : les cellules Date et Canal portent `.nowrap`,
   `td.num` en pose une sur Prix et Éch., la colonne Closer déclare 142 px, et
   le badge de statut est `nowrap` lui aussi. À 1 440 px les colonnes rigides
   prennent ~840 px des ~1 100 disponibles : il reste ~260 px à partager entre
   le nom ET l'offre, et le nom finit vers 115 px. `.nom-lu` étant un
   `inline-flex`, sa largeur minimale est celle du plus long MOT — « Marie-
   Christine » casse au trait d'union et la ligne fait trois étages. C'est la
   capture du client.

   On rend donc au nom un plancher garanti ; sous ce plancher le tableau
   défile dans `.table-scroll` (~45 px à 1 440, ~200 px à 1 280) et ses
   en-têtes restent collés en haut. Pas de requête média : un `min-width` est
   un plancher, jamais un plafond — au-delà de ~1 600 px les colonnes
   dépassent déjà ces valeurs et la règle ne s'applique pas. `nth-child` parce
   que Date, Client·e et Offre sont les trois seules colonnes dont le rang ne
   bouge jamais : Canal, Closer et Actions apparaissent selon les droits. */
.sales-log th:nth-child(2), .sales-log td:nth-child(2) { min-width: 172px; }
/* 172 px est le genou : le nom casse au plus une fois, à l'espace
   (« Marie-Christine » puis « Delaunay »). Le tenir sur une seule ligne
   demanderait ~215 px, donc 45 px de défilement de plus pour un pli. */
.sales-log th:nth-child(3), .sales-log td:nth-child(3) { min-width: 132px; }
/* L'offre est déjà coupée à 42 caractères et son nom entier vit dans
   l'infobulle : elle peut se replier sur deux lignes, pas tomber à un mot par
   ligne — sans quoi la ligne à trois étages se contente de changer de colonne. */

/* Le champ d'adresse ne redimensionne plus la table. `.adr-saisie > input`
   porte `min-width: 140px` ; dans une cellule en `table-layout: auto` ce
   plancher n'est pas une préférence, il remonte en contribution min-content
   de la COLONNE entière. Ouvert, le champ réclame 140 + 5 + 32 (le OK) + 20
   (rembourrage) ≈ 197 px là où la colonne ne demandait que la ligne du nom.
   Et comme le script masque « adresse manquante » au moment d'ouvrir, la
   cellule perd d'abord son bouton puis en exige 57 de plus : les lignes
   glissent sous le curseur à l'instant où l'on allait taper. Ce plancher ne
   protège rien — `flex: 1` donne déjà au champ tout ce que la colonne
   possède, et cette colonne est tenue par le nom, jamais par le champ. */
.sales-log .adr-saisie > input { min-width: 0; }

/* ── Fiche vente · le parcours, une grille plutôt qu'une file ───────────────
   `Sale.parcours()` rend jusqu'à SEPT pas. En flex, avec `.pas { flex: 1 1
   190px }`, il en tient cinq sur la première rangée à 1 150 px utiles ; les
   deux derniers tombent dessous et `flex-grow` les étire à ~570 px chacun.
   Le déséquilibre est double : la place manque en haut — le détail « 3/6
   réglées · 2 en défaut (J+14) », ce qu'on était précisément venu lire, part
   à l'ellipse — et se perd en bas. Et le défaut ne se répare pas en
   s'élargissant : tant que la base est nulle, l'écran gagné sert à aligner
   plus de pas, jamais à les lire. D'où le socle, pas un palier.

   La grille donne à tous les pas la même largeur quel que soit le reste de la
   division : plus de dernière rangée à rallonge. `auto-fit` plutôt
   qu'`auto-fill` parce que toutes les ventes n'ont pas sept pas — sans
   e-learning ni B-Sport il n'y en a que quatre, et les pistes vides se
   replient au lieu de laisser des colonnes creuses. Le `min()` garde la piste
   à l'intérieur du conteneur sur un écran plus étroit que la largeur
   plancher. */
.parcours { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(198px, 100%), 1fr)); }
/* TRANCHÉ — le pas qui porte ses boutons reste sur UNE colonne : ce sont les
   boutons qui passent à la ligne dans la carte. Un `grid-column: span 2`
   paraissait plus simple, mais le placement automatique ne revient jamais en
   arrière : à quatre colonnes — ≈1 280 px, notre deuxième cible — le pas
   « Envoi » ne trouve pas deux colonnes libres en fin de rangée, saute à la
   suivante et laisse un trou au milieu d'un parcours NUMÉROTÉ, où un trou se
   lit comme un pas manquant. Et sur une vente sans e-learning ni B-Sport, il
   cassait en deux rangées les quatre cartes qui tenaient sur une seule. */
.parcours .pas:has(.pas-actions) { flex-wrap: wrap; }
.parcours .pas-actions { flex-wrap: wrap; justify-content: flex-end; }
/* Le détail s'écrit en entier : une ligne de plus vaut mieux qu'une donnée en
   moins. `overflow-wrap` parce que le détail d'envoi contient une adresse
   e-mail — un seul mot, qui ne se coupe nulle part et sortirait de la carte. */
.parcours .pas-detail { white-space: normal; overflow: visible; overflow-wrap: anywhere; }

/* ── Suivi closing · la recherche ne réclame plus sa pleine largeur ─────────
   Les deux listes `data-search` deviennent des <input> au chargement : le cap
   `.filter-bar select { max-width: 116px }` ne les tient plus, chacune
   reprend sa largeur intrinsèque (~190 px), et la rangée réclame ~1 250 px
   quand le portable de référence n'en offre que 1 144. Elle se repliait, et
   `.pv-chercher` — seule sur la deuxième ligne avec son `margin-left: auto` —
   allait se coller au bord droit, à ~860 px des filtres qu'elle prolonge.

   On ne lui fait donc plus RÉCLAMER ses 281 px au moment où le navigateur
   décide des lignes : sa base flex est courte, donc elle reste sur la
   première ligne, puis `flex-grow` lui rend la place restante. Le plafond est
   ce qui garde l'`auto` utile sur grand écran : une fois la boîte figée à son
   maximum, le reste repasse à la marge et la plaque à droite, comme
   aujourd'hui. 298 px = les 281 actuels + les 17 px du témoin « … » affiché
   pendant la requête, sans quoi le champ rétrécissait à chaque frappe. */
.filter-bar .pv-chercher { flex: 1 1 112px; min-width: 112px; max-width: 298px; }
/* `min-width: 0` est indispensable : sans lui le minimum automatique d'un
   <input> est sa largeur par défaut (~144 px) et plus rien ne peut le
   comprimer. La loupe, elle, n'est pas élastique — sinon elle partage la
   compression avec le champ et se déforme d'un ou deux pixels. */
.filter-bar .pv-chercher input { flex: 1 1 auto; width: auto; min-width: 0; }
.filter-bar .pv-chercher > svg { flex: none; }

/* ── « Ce qui va coincer » · une phrase ne se lit pas en 19 caractères ──────
   Sur le tableau de bord des VENTES, `.al-who` porte une liste de noms suivie
   d'un « +3 » : l'ellipse y est honnête, on sait qu'on regarde un extrait.
   Ici elle porte LA phrase qui dit le problème — « aucune adresse pour
   l'animateur référent — la liste des régimes et allergies ne partira à
   personne », 98 caractères. `flex: 1` part d'une base nulle relevée à
   `min-width: 260px` : quatre alertes tiennent sur les 1 144 px du portable,
   le contenu d'une alerte tombe à 252 px et les 45 % de `.al-who` valent
   113 px, soit 19 caractères. Une alerte qu'il faut ouvrir pour comprendre
   n'est plus une alerte.

   Et le défaut EMPIRE en montant : à 1 920 px six alertes se rangent côte à
   côte, 106 px pour la phrase — pire qu'à 1 150. Tant que la base est nulle,
   l'écran gagné sert à en aligner davantage, jamais à les lire. C'est donc la
   base qui change, pas un palier. 380 px et non 420 : à 1 100 px utiles, 420
   ne laisse plus tenir qu'UNE alerte par rangée, étalée sur 776 px pour une
   phrase qui en occupe 586, et six alertes repoussent alors la bande KPI de
   six rangées.

   Tout est cloisonné à `.ev-alertes` : le bandeau de l'ADV et le `.al` de la
   fenêtre des animateurs gardent leur ellipse, justifiée chez eux. */
.ev-alertes .al { flex: 1 1 380px; flex-wrap: wrap; }
/* Sans cela le nom refuse de se réduire sous son mot le plus long et déborde
   du badge arrondi au lieu de se replier. */
.ev-alertes .al > b { min-width: 0; }
/* Le compte à rebours tenait la droite grâce au `margin-left: auto` de la
   phrase ; celle-ci descendant d'une ligne, c'est lui qui le reprend. */
.ev-alertes .al-jour { margin: 0 0 0 auto; }
.ev-alertes .al-who {
  flex: 1 0 100%; max-width: none; white-space: normal;
  margin-left: 0; text-align: left;
}

/* ── Registre des événements · le nom ne paie pas pour les autres ───────────
   Quatre des sept colonnes refusent de rétrécir — la date, « Paiements »
   (trois pastilles côte à côte), « Animateur » et les actions portent toutes
   la classe `nowrap` — et « Remplissage » est figée à 190 px par un style en
   ligne. En disposition automatique le déficit retombe donc entièrement sur
   « Événement » et « Lieu », et une colonne compressible descend jusqu'à la
   largeur de son mot le plus long : une centaine de pixels ici, où un nom de
   44 caractères s'empile sur quatre lignes. Or c'est le nom qui identifie la
   ligne — le défaut corrigé sur « Suivi closing », transposé. La somme des
   minima (~1 128 px) dépasse déjà la place réelle du portable (1 062 px) :
   le nom est écrasé dès 1 440, pas seulement plus bas. */
.ev-table td:nth-child(2) { min-width: 220px; }
/* Chaque pastille garde son propre `nowrap` : elles ne se coupent pas, elles
   passent à la ligne entières. `inline-block` est indispensable — en
   `inline`, leur rembourrage vertical déborde du bloc de ligne et les
   pastilles empilées se chevauchent. */
.ev-table td:nth-child(5) { white-space: normal; }
.ev-table td:nth-child(5) .pastille { display: inline-block; margin-bottom: 2px; }
/* « Marie-Christine Dupont » sur deux lignes vaut mieux qu'un nom de session
   sur quatre. */
.ev-table td:nth-child(6) { white-space: normal; }
/* Les gestes se rangent en colonne à droite quand la ligne se resserre : tous
   visibles, tous atteignables. Chaque bouton reste insécable de lui-même, et
   les 3 px de marge restent sous la hauteur de la cellule du nom. */
.ev-table .ev-actions { white-space: normal; }
.ev-table .ev-actions .btn { margin-bottom: 3px; }
/* Un nom de ville sans espace — « Saint-Rémy-de-Provence » — n'a aucun point
   de coupe et débordait par-dessus la jauge voisine. `break-word` plutôt
   qu'`anywhere` : il ne casse qu'en dernier recours et ne modifie pas la
   largeur minimale de la colonne, qui reste celle du mot entier. */
.ev-table td:nth-child(2), .ev-table td:nth-child(3) { overflow-wrap: break-word; }
/* Sous ce plancher la table DÉFILE dans `.table-scroll`. 900 px et non 940 :
   la place réelle vaut la fenêtre moins la barre (240), le rembourrage de
   `.content` (56) et celui de `.card` (32) — soit 912 px sur une fenêtre de
   1 280. À 940 px la deuxième cible se serait mise à défiler pour 28 px. */
.ev-table { min-width: 900px; }

/* ── Équipe · le nom cesse d'être la variable d'ajustement ──────────────────
   Huit des neuf colonnes refusent de rétrécir : `.td-groupe`, `.td-cal` et
   `.row-actions` sont en `nowrap`, les deux colonnes de chiffres aussi,
   l'e-mail est plafonné et l'identifiant est un mot d'un seul tenant. La
   table n'étant pas en `table-layout: fixed`, le navigateur ramène tout le
   monde à son contenu minimal dès que la place manque — et le seul contenu
   qui accepte de se couper, c'est le nom. Il retombait à la largeur de son
   mot le plus long (« Marie-Aliette de La Tour » sur trois lignes) pendant
   que la table débordait de toute façon : on perdait l'identité de la ligne
   sans gagner un pixel.
   Le `18 %` de la l. 6031 ne protège rien — un pourcentage n'est qu'une
   préférence, ignorée dès que la somme des minima dépasse la carte. Il faut
   un plancher en pixels. `:not([colspan])` par prudence : les bandes de
   groupe portent `colspan="9"` et n'ont rien à dire de la première colonne. */
.eq-table th:nth-child(1),
.eq-table td:nth-child(1):not([colspan]) { min-width: 168px; }
/* Si une personne porte un nom plus long que le plancher, c'est la table qui
   s'élargit et défile, pas le nom qui s'empile. */
.eq-table td:nth-child(1) > b { white-space: nowrap; }

/* ── Agendas des closers · le tableau des rendez-vous ───────────────────────
   Le motif du « Suivi closing », encore lui : toutes les colonnes ont leur
   place sauf celle qui porte l'identité.

   `.rdv-table .td-rep` est en `nowrap` sur un texte coupé à 70 signes : sa
   largeur MINIMALE vaut donc ses 70 signes, ~440 px, et rien ne peut la
   réduire — en disposition automatique une cellule de tableau ignore
   `max-width`. La somme des minima des huit colonnes dépasse 1 350 px alors
   qu'il reste ~1 100 px dans la carte sur un portable. Le tableau part donc à
   son minimum absolu : « Réponses » garde ses 440 px, « Prospect » tombe à un
   mot par ligne (« Marie- / Claire / Dubois »), et la liste « Résultat » — le
   SEUL champ qu'on vienne saisir ici — démarre hors du bord droit.

   Même remède que `.pv-table`, et la même leçon : avec `table-layout: fixed`,
   la colonne SANS largeur absorbe ce qui reste, donc ce n'est JAMAIS le nom
   qu'on laisse élastique. Le prospect a sa largeur, garantie ; ce qui s'étire
   ou se tronque, ce sont les réponses — dont le texte entier vit déjà dans le
   `title` de la cellule. Le budget est calé pour que le portable de référence
   NE DÉFILE PAS : 930 px de colonnes fixes + 140 px d'élastique = 1 070, sous
   les ~1 100 disponibles. */
.rdv-table { table-layout: fixed; min-width: 1070px; }
.rdv-table th:nth-child(1) { width: 140px; }  /* Date + heure, insécable      */
.rdv-table th:nth-child(2) { width: 130px; }  /* Closer                        */
.rdv-table th:nth-child(3) { width: 164px; }  /* Prospect — garanti            */
.rdv-table th:nth-child(4) { width: 150px; }  /* E-mail                        */
/* « Vente conclue » est un badge insécable : sous ~115 px il déborde sur la
   colonne voisine, c'est-à-dire qu'il recrée le défaut qu'on corrige. */
.rdv-table th:nth-child(5) { width: 118px; }  /* Statut                        */
.rdv-table th:nth-child(6) { width: 86px;  }  /* Origine                       */
.rdv-table th:nth-child(7) { width: auto; min-width: 140px; }  /* Réponses     */
.rdv-table th:nth-child(8) { width: 140px; }  /* Résultat — la saisie          */
/* Le cap annoncé à la l. 4975 devient enfin vrai : en disposition fixe la
   cellule a une largeur définie, donc `overflow` et les points de suspension
   fonctionnent. Rien n'est perdu, le texte intégral est dans le `title`.
   Sélecteur qualifié : à égalité de spécificité avec la règle d'origine, seul
   l'ordre du fichier départageait. */
table.data.rdv-table .td-rep { max-width: none; }
/* L'adresse n'a PAS de `title` : la tronquer, ce serait cacher une donnée. On
   empile, on ne coupe pas. Même remarque pour le nom du closer, insécable par
   `.nowrap` et qui sinon déborderait sur la colonne du prospect. */
.rdv-table td:nth-child(2) { white-space: normal; }
table.data.rdv-table .td-mail {
  max-width: none; white-space: normal; overflow: visible; overflow-wrap: anywhere;
}
/* La liste « Résultat » suit sa colonne au lieu de la faire déborder. */
table.data.rdv-table .sel-statut { width: 100%; }

/* ── Agendas des closers · la barre de filtres, à une seule hauteur ─────────
   Neuf commandes réclament ~1 315 px là où il en reste 1 112 sur un portable :
   la barre passe à deux rangées. Et comme `.rdv-filtres` n'est pas une
   `.filter-bar`, rien ne l'a jamais mise au pas : le champ de recherche est un
   `type=search`, absent de la règle globale des formulaires (l. 1631, qui
   n'énumère que text/number/date/email/password/select/textarea) — il tombe en
   rendu NATIF, ~24 px, sans arrondi et dans la police du navigateur ; les
   listes en font 32 et les `.btn.xs` 21. Deux rangées en escalier, à TOUTE
   largeur : c'est le défaut que la barre du registre avait déjà corrigé pour
   elle-même (l. 1189-1200), et il n'attend pas le portable pour exister.

   On écrit `background-color` et NON le raccourci `background` : le raccourci
   effacerait le chevron des `select`, précisément l'accident dont souffre
   déjà `.filter-bar`. Le rembourrage droit des selects ne bouge pas, il est
   en `!important` (l. 2625). */
.rdv-filtres { gap: 5px; }
.rdv-filtres input,
.rdv-filtres select,
.rdv-filtres .combo-input {
  font: inherit; font-size: 12.5px; height: 30px; padding: 3px 7px;
  border: 1px solid var(--hairline); border-radius: 8px;
  background-color: var(--surface); color: var(--ink);
}
/* Le chevron du champ filtrable garde sa place : la règle ci-dessus vient
   d'écraser le `padding-right: 28px` de `.sel-search .combo-input` (l. 2268),
   et sans lui le nom du closer passerait dessous. On rend le rembourrage, pas
   la position de l'image : celle d'origine est bonne. */
.rdv-filtres .combo-input { padding-right: 28px; }
/* La recherche est le SEUL élément élastique de la rangée : c'est elle qui
   absorbe le reste sur grand écran et qui cède les derniers pixels sur un
   portable. D'où `min-width: 0` — avec le plancher de 230 px de la l. 4970
   elle ne pouvait pas céder, et la barre repassait à deux rangées malgré
   tout. Même remède que la barre des encaissements (l. 3125). */
.rdv-filtres .f-search { flex: 1 1 176px; min-width: 0; }
.rdv-filtres select { width: auto; min-width: 112px; max-width: 152px; }
.rdv-filtres .combo { min-width: 112px; max-width: 152px; }
/* La liste est en `left: 0; right: 0` et le script lui pose la largeur du
   champ en style en ligne ; bornée à 152 px comme sa boîte, elle coupait
   « Marie-Charlotte (ext.) » sur deux lignes. Un `min-width` passe devant une
   largeur, en ligne comprise : on ne resserre que le champ fermé, jamais le
   choix qu'il propose — comme l. 474 et l. 6700. */
.rdv-filtres .combo-list { min-width: 210px; }
.rdv-filtres input[type=date] { width: 106px; min-width: 0; }
/* Les boutons à la hauteur des champs : côte à côte, la rangée était en
   escalier — 21 px contre 32. */
.rdv-filtres .btn { height: 30px; padding: 0 11px; font-size: 12.5px; border-radius: 8px; }
.rdv-filtres .btn:hover { transform: none; box-shadow: none; }

/* ── Care · Boîte de réception — un plancher sous l'identité ────────────────
   La file a CINQ colonnes dont TROIS rigides : la pastille de canal, la date
   de réception collée à son badge « >24 h », et le statut suivi du
   « → Delphine » sont tous en `nowrap` — ~460 px figés. « De » et « Objet »,
   les deux seules qui disent de QUI et de QUOI il s'agit, héritent du reste,
   c'est-à-dire de rien dès qu'une conversation est ouverte à côté : l'objet
   tombe à la largeur de son mot le plus long et s'enroule sur sept lignes.
   L'identité n'est jamais la variable d'ajustement — quand la place manque,
   c'est la table qui défile. 136 px tiennent un prénom-nom sur une ligne,
   216 px le plus long sujet réel sur deux ; sans effet dès que la place est
   là, la répartition naturelle dépassant déjà ces valeurs. */
.inbox-log th:nth-child(2), .inbox-log td:nth-child(2) { min-width: 136px; }
.inbox-log th:nth-child(3), .inbox-log td:nth-child(3) { min-width: 216px; }

/* ── Care · Accès à ouvrir — la file DÉFILE, elle ne s'écrase pas ───────────
   `col-quand` et `col-accueil` portent une largeur, mais la table est en
   `table-layout: auto` : une largeur y est un souhait, pas un plancher. La
   carte offre (fenêtre − 240 − 56 − 32) px, soit 1 112 à 1 440 (ça tient),
   952 à 1 280 (tout juste), 772 à 1 100 — pour ~894 px de besoin une fois
   l'offre posée sur une ligne. Les ~120 px manquants, le navigateur les prend
   sur « Offre achetée », qui part en quatre lignes pour un nom déjà tronqué à
   46 caractères, et sur « Accueil », dont les trois pastilles se cassent en
   deux rangs — sur toutes les lignes à la fois, donc la file double de
   hauteur.
   PORTÉE — `.acces-log` habille AUSSI la file B-Sport (`ops/bsport.html`),
   sept colonnes et son propre équilibre. Elle n'a pas été mesurée ici, on la
   laisse tranquille. */
.acces-log:not(.bsport-log) { min-width: 900px; }
/* Les trois gestes se lisent en UNE rangée ou ne se lisent pas. Plutôt qu'une
   largeur devinée — qui se démentirait au premier changement de police, et
   qui avec `box-sizing: border-box` (l. 83) se fait manger par le rembourrage
   — on interdit le retour à la ligne : la colonne réclame alors d'elle-même
   la largeur exacte des trois pastilles, et le plancher ci-dessus la lui
   garantit. */
.acces-log:not(.bsport-log) .ac-etats { flex-wrap: nowrap; }
/* Le nom ET l'adresse sont l'identité de la ligne : c'est avec l'adresse
   qu'on crée le compte dans le LMS et qu'on retrouve la cliente dans Brevo.
   200 px = une adresse de trente-trois signes à 12 px, gouttières comprises. */
.acces-log:not(.bsport-log) th:first-child,
.acces-log:not(.bsport-log) td:first-child { min-width: 200px; }

/* ── Care · Appels & rappels — la raison du rappel garde sa place ───────────
   Les deux tables de cet écran n'ont pas de classe à elles. Ce qui est
   partagé s'attrape par `#appel-modal`, qui n'existe que sur cette page ; ce
   qui vise une seule des deux tables s'attrape par `.rappel-fait`, présent
   uniquement dans la file « À rappeler ». Les deux onglets ne s'accordent PAS
   sur le sens des colonnes — la 4e est « Objet » côté rappels mais « Durée »
   côté journal — donc aucune règle de colonne ne doit passer par le seul
   `#appel-modal`.

   Quatre colonnes sur six sont rigides : l'attente (~86 px), le téléphone
   (17 caractères insécables, ~135 px), la date de demande (~92 px) et la
   rangée d'action (~215 px : un champ de 58 px, « min », et un bouton qui ne
   se replie jamais). Soit ~528 px figés. À 1 440 px il reste 584 px pour la
   cliente et l'objet : rien à signaler. À 1 100 px il n'en reste que 244 pour
   les deux, et c'est « Objet » qui paie — la raison du rappel, celle qui
   décide de l'ordre des appels, tombe vers 120 px et s'enroule.
   900 px et non 840 : à 7 px de rembourrage les colonnes rigides coûtent
   encore ~500 px, et un plancher de 840 ne laisserait que ~186 px à l'objet,
   à peine mieux que le mal qu'on soigne. */
.content:has(#appel-modal) .card table.data { min-width: 900px; }
/* Le plancher du tableau ne dit pas QUI reçoit les pixels rendus : en largeur
   automatique, le navigateur les répartit au prorata de l'appétit de chaque
   colonne. On l'écrit donc noir sur blanc, et seulement sur la file des
   rappels — dans le journal, ces mêmes rangs sont « Durée » et « Traité par ». */
.content:has(#appel-modal) table.data:has(.rappel-fait) th:nth-child(4),
.content:has(#appel-modal) table.data:has(.rappel-fait) td:nth-child(4) { min-width: 240px; }
.content:has(#appel-modal) table.data:has(.rappel-fait) th:nth-child(2),
.content:has(#appel-modal) table.data:has(.rappel-fait) td:nth-child(2) { min-width: 150px; }

/* ── Fiche contact · tableau « Rendez-vous de closing » ─────────────────────
   Les trois colonnes sont en `nowrap` (date + heure, pastille + closer,
   badge) : aucune n'est élastique, donc rien ne peut céder quand la carte
   rétrécit. La carte défile déjà (le filet `.card:has(> table.data)`
   du socle s'en charge) : ce qu'on corrige ici, c'est qu'elle défile TROP TÔT
   — la colonne du nom cède avant que le tableau ne dépasse. Le badge de
   statut sort alors du cadre et se peint sur la carte voisine.
   Le créneau est étroit mais réel : sous ~990 px de fenêtre `.grid-2` retombe
   seule sur une colonne, au-dessus de ~1 190 px la carte offre déjà plus que
   les ~410 px réclamés. Entre les deux — le portable à 1 100 px — il manque
   une cinquantaine de pixels.
   On rend leur souplesse aux DEUX colonnes de texte : la date passe à la
   ligne après le « · » et un nom composé se coupe au trait d'union. Le badge
   reste d'un seul tenant : c'est le résultat du rendez-vous, il ne se lit pas
   en deux morceaux.
   La table des achats, juste au-dessus, partage ces classes et ne bouge pas :
   sa 1re cellule (« 15/09/2025 ») ne contient aucune espace et sa 2e n'est pas
   en `nowrap`. Une seule exclusion, parce qu'une seule est utile :
   `.rdv-table` est la seule autre table `.table-compact` de l'application à
   porter des cellules `.nowrap` (vérifié au grep), et on ne la touche pas
   d'ici — `team.html` et les préventes n'en ont aucune. */
table.data.table-compact:not(.rdv-table) td.nowrap:nth-child(-n + 2) { white-space: normal; }
/* La pastille du closer redevient un POINT. Vide de texte, elle hérite de
   `.pastille` — une gélule à 9 px de rembourrage horizontal — et occupe 20 px
   pour ne rien dire, dans la colonne la plus serrée de la fiche. C'est déjà
   le dessin retenu sur l'écran des closers (l. 4973), où la couleur porte
   seule l'identité : les deux écrans se rejoignent. `:empty` garantit qu'on
   ne touche qu'aux pastilles sans texte ; celles qui portent un mot
   (« inactif », « Barème standard ») restent des gélules. */
table.data.table-compact:not(.rdv-table) .pastille:empty {
  display: inline-block;
  width: 8px; height: 8px; padding: 0;
  border-radius: 50%;
  margin-right: 6px;
  vertical-align: 1px;
}

/* ── KPIs · « Répartition par canal » : ~70 px gelés à gauche de chaque barre ─
   `.hbar` réserve 170 px au libellé alors que le plus long des six canaux,
   « Lien Stripe direct », mesure ~101 px à 12,5 px. Ces ~70 px sont pris à la
   barre, la seule chose qu'on regarde ici : à 1 440 px la carte offre 532 px
   de contenu et il ne reste que 278 px de piste ; 198 px à 1 280, 108 px à
   1 100. On ramène le libellé à sa largeur réelle et la piste récupère 50 px
   à toutes les largeurs — le gaspillage n'attend pas le portable.

   TRANCHÉ — les deux colonnes extrêmes RESTENT fixes. `.hbars` est un flex en
   colonne, donc chaque `.hbar` est une grille INDÉPENDANTE et rien n'aligne
   les colonnes d'une ligne à l'autre : une piste dimensionnée sur son contenu
   se mesurerait ligne par ligne — « 0 € » ici, « 12 480 € » là — et deux
   canaux au même pourcentage dessineraient deux barres de longueurs
   différentes. Un graphique de comparaison ne survit pas à ça.
   Les 64 px du montant ne bougent pas non plus : le gabarit passe par
   `euros`, qui écrit sans centimes (« 12 480 € », ~49 px en chiffres
   tabulaires), donc la piste est déjà large et rien ne déborde. */
.hbar { grid-template-columns: 120px 1fr 64px; }
/* Filet pour un futur canal : un nom en plusieurs mots passe à la ligne tout
   seul, mais un mot unique trop long sortirait de sa colonne et se peindrait
   par-dessus la barre. */
.hbar > span:first-child { overflow-wrap: break-word; }

/* ── Pédagogie · `auto-fill` conserve les pistes vides ──────────────────────
   Avec les deux promotions et les deux séquences réelles, un portable
   (1 144 px utiles) fabrique quatre pistes de 277 px, coince les cartes dans
   la moitié gauche et laisse l'autre moitié blanche : tassé d'un côté, vide
   juste à côté. Et le défaut GRANDIT avec l'écran — en rail sur un 1 920, six
   pistes pour deux cartes. `auto-fit` efface les pistes vides ; c'est déjà ce
   que fait `.grid-2` deux lignes plus haut dans la feuille.
   Le plancher passe à 300 px parce qu'à 277 px la carte n'offre que 243 px
   utiles, alors que les deux étiquettes de `promotions.html`
   (« 01/09/2025 → 30/06/2026 » et « 24 participants », toutes deux
   insécables) en réclament ~250 : elles retombaient l'une sous l'autre pour
   rien. Le plafond de 420 px est l'autre moitié du remède : sans lui,
   `auto-fit` donne TOUTE la largeur aux deux seules cartes présentes et une
   fiche de séquence s'étale sur 900 px. Bornées, elles restent des cartes et
   se rangent à gauche.
   `min(100%, …)` garde le plancher sous la largeur du conteneur : sous 760 px
   la grille doit pouvoir descendre à une colonne sans pousser la page. */
.grid.grid-3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 420px)); }
/* Exception pour le mur d'élèves : la fiche n'y porte qu'un avatar et un nom.
   Surtout, son filtre instantané masque les fiches en `display: none` — avec
   `auto-fit`, une recherche qui ne laisse qu'un résultat verrait sa carte
   changer de largeur à chaque frappe. On lui laisse des pistes stables. */
#student-cards.grid-3 { grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr)); }

/* ── « Participants à relancer » · la ligne apprend à passer à la ligne ─────
   La ligne met bout à bout le nom (130 px garantis par un style en ligne), un
   commentaire élastique et un bouton que `.btn` interdit de couper — environ
   420 px de minimum, pour une carte de `.grid-2` qui en offre 339 sur un
   portable. Le bouton sortait par la droite, par-dessus la carte voisine. Le
   geste descend seul sous le texte, le nom garde sa place en tête — c'est par
   lui qu'on reconnaît une ligne, ce n'est jamais lui qu'on sacrifie.
   Borné aux lignes qui portent un formulaire, et c'est volontaire : ailleurs
   (la fiche du cercle, libellé de 130 px + valeur), l'élément élastique n'a
   pas de base nulle, donc flex le mesure à son max-content et `wrap` le
   renverrait à la ligne alors qu'il s'enroulait très bien à côté de son
   libellé. Vérifié : `promotion_detail.html` est le seul gabarit à poser un
   <form> en enfant direct d'un `.check-item`. */
.card > .check-item:has(> form) {
  flex-wrap: wrap;
  /* la retombée reste collée à son texte : on empile, on n'aère pas */
  row-gap: 4px;
}
/* Le bouton retombe sous le commentaire mais garde son bord droit : la
   colonne des gestes reste lisible de haut en bas, qu'elle ait replié ou non. */
.card > .check-item:has(> form) > form:last-child { margin-left: auto; }

/* ── « Suivi pédagogique » · la jauge cesse de manger le nom ────────────────
   Le motif corrigé sur « Suivi closing » est revenu ici : toutes les colonnes
   sont bornées sauf celle qui porte l'identité de la ligne, le Participant,
   qui encaisse ce qui reste. Et il reste peu : 160 px de jauge + un `.badge`
   d'accès insécable (~90 px) + 60 px de rembourrages = 310 px pris sur les
   452 px d'une carte à 1 280 px. Le nom reçoit 142 px pour un
   « Marie-Aliette Delacroix » qui en demande 165.
   PAS de requête média, et c'est le point : `auto-fit` resserre les cartes à
   mesure que la fenêtre s'ÉLARGIT (quatre pistes vers 1 800 px, carte à
   333 px), donc une borne haute laisserait justement le cas le plus serré
   sans correctif.
   La jauge est le seul élément élastique de la ligne : 70 px de barre, 6 px
   d'écart et le pourcentage lui suffisent — ~129 px, trente de moins que les
   160 imposés. `width: 1%` la ramène à sa largeur de contenu et rend le solde
   au nom. Rien n'est masqué : la barre reste une barre, le chiffre reste à
   côté.
   Le `!important` n'est pas un raccourci : les 160 px sont écrits en style EN
   LIGNE dans le gabarit, aucune règle de feuille ne peut les reprendre
   autrement. Le sélecteur d'attribut vise cette colonne et elle seule — c'est
   l'unique `style="width:160px"` de tout `templates/`. Le jour où le gabarit
   gagne une vraie classe de colonne, cette règle s'en va avec lui. */
table.data th.num[style*="width:160px"] { width: 1% !important; }

/* ── Une table dense a le droit de défiler ; pas de SORTIR de sa carte ──────
   FUSION de cinq correctifs qui décrivaient le même défaut sur cinq écrans
   (échéancier de la fiche vente, campagnes, factures fournisseurs, planning
   des coachings, historique des versions) : ces gabarits posent `table.data`
   en enfant DIRECT de `.card`, sans `.table-scroll` autour. Or `.card` n'a
   aucune règle d'`overflow`, et une table ne se comprime jamais sous la
   largeur minimale de ses colonnes : quand ça ne rentre pas, elle ne se tasse
   pas, elle SORT — et comme les fonds de bloc se peignent avant les textes,
   elle passe sous la carte voisine, où on ne la lit plus du tout.
   C'est donc la carte qui devient le conteneur de défilement. `auto` ne se
   déclenche que s'il manque vraiment de la place : sur un écran large où tout
   tient, rien ne change — d'où le socle plutôt qu'un palier.
   Vérifié : aucune des ~20 cartes visées ne contient de liste flottante
   (`.combo-list`, `.multi-pop`) qu'un conteneur de défilement viendrait
   rogner, et `invoice_print.html` ne pose aucune table dans une carte.

   À NOTER — le `min-width: 0` que plusieurs correctifs réclamaient sur les
   enfants de `.grid-2` est ici INUTILE : la taille minimale automatique d'un
   élément de grille ne s'applique QU'AUX éléments dont l'`overflow` est
   `visible`. En posant `overflow-x: auto` on a déjà ramené ce minimum à zéro.
   Une règle de moins, et aucune autre grille perturbée. */
.card:has(> table.data) {
  overflow-x: auto;
  /* Le geste latéral au trackpad — celui du portable qui a motivé la plainte
     — ne doit pas déborder sur l'historique : on défile la table, on ne
     recule pas d'une page. */
  overscroll-behavior-x: contain;
  /* Le même rail visible que `.table-scroll`, et pour la même raison (l. 2660) :
     une barre qu'on ne voit pas laisse croire qu'on a déjà tout lu. */
  scrollbar-color: #a8a69c #eceae4;
}
/* Le titre, le compteur « 2/3 réglées » et les phrases qui encadrent la table
   restent collés à gauche : sinon ils s'en vont avec elle et on ne sait plus
   quel tableau on est en train de faire défiler. Tout ce qui n'est pas la
   table, pour que l'ajout d'une barre de filtres dans l'un de ces gabarits
   n'ait pas à repasser par ici. */
.card:has(> table.data) > :not(table) { position: sticky; left: 0; }
/* Segments & campagnes : la carte de droite est prise dans une grille
   « 2fr 3fr » figée en style en ligne. 600 px et non le minimum absolu du
   tableau (~536) : sous 600 il rendrait au NOM de la campagne des confettis
   plutôt qu'une part réelle. */
.content > .grid[style*="2fr 3fr"] > .card > table.data { min-width: 600px; }


/* ── La grille à deux cartes ne compte pas jusqu'à deux ─────────────────────
   `.grid-2` réclame autant de pistes de 340 px (l. 1558) que la place en
   permet : trois cartes là où le gabarit en dessine deux, cinq sur un 1 920.
   Le planning des coachings en réclame ~520 (cinq colonnes, lien Zoom sans
   espace, tag et badge insécables) ; 540 px de plancher = ces ~520 plus les
   32 px de rembourrage de la carte.

   Au SOCLE et pas dans un palier : un plancher ne dépend pas de la fenêtre —
   la carte la plus exigeante en réclame autant à 1 900 qu'à 1 600. Enfermé
   dans le palier 1600, il fabriquait une MARCHE d'un pixel : deux colonnes à
   1 600, quatre à 1 601, quand le plancher de 340 px reprenait la main. Et un
   plancher n'est pas un plafond : au-delà de ~1 760 px il laisse repasser
   trois cartes tout seul, sans qu'on ait à l'écrire. */
.grid.grid-2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 540px), 1fr)); }

/* ───────────────────────────────────────────────────────────────────────────
   1. PALIER « ÉCRAN ÉTROIT » — 1600 px
   ───────────────────────────────────────────────────────────────────────────
   Un seul motif, cinq écrans : un vis-à-vis dont l'un des deux côtés a une
   largeur FIXE. Tant que la fenêtre est large, le côté élastique encaisse
   sans se plaindre ; en dessous, c'est toujours lui qui paie — et c'est
   toujours lui qui porte l'information. On empile. Rien n'est caché : le
   second bloc descend d'un cran et le premier récupère toute la largeur.
   ─────────────────────────────────────────────────────────────────────────── */
@media screen and (max-width: 1600px) {

  /* Care · la boîte de réception : le vis-à-vis coûte plus qu'il ne rapporte.
     La file n'a plus que ~530 px, où ni ses cinq colonnes ni sa barre de
     filtres (cinq chips + recherche + select + OK ≈ 814 px) ne tiennent sur
     un rang. PAS d'exception pour la barre en rail : elle est l'état PAR
     DÉFAUT de cet écran (base.html applique `nav-rail` hors de « / »), et
     même à 62 px elle ne rend que ~613 px à la carte de gauche. Une exception
     ici désactiverait le correctif sur le portable qu'il vise.
     Le `:has()` vise CETTE file : `.grid-2` sert dix autres écrans. */
  .grid.grid-2:has(.inbox-log) { grid-template-columns: minmax(0, 1fr); }
  /* Empilée, la file gardait ses 72 vh et poussait le champ de réponse deux
     écrans plus bas : elle défile dans son cadre, comme ailleurs. */
  .grid.grid-2:has(.inbox-log) > .card .table-scroll { max-height: 42vh; }

  /* Segments & campagnes : côte à côte, le NOM de la campagne n'obtient une
     largeur décente qu'au-delà de ~1 600 px. Six colonnes dont quatre
     incompressibles — date en `nowrap`, badge de statut, en-tête
     « OUVERTURE » en majuscules interlettrées, bouton « Envoyer → » —
     mangent ~380 px avant d'écrire une seule lettre ; il reste ~260 px pour
     le nom ET son segment, et le nom retombe à ~150 px. Le sélecteur
     d'attribut et le `!important` sont le seul moyen de passer devant un
     style en ligne, et ils citent la valeur corrigée pour qu'on retrouve la
     règle le jour où le gabarit changera — ce jour-là elle devient inerte,
     elle ne casse rien. Empilé, l'ordre de lecture reste segments →
     assistant → campagnes, l'ordre logique de l'écran. */
  .content > .grid[style*="2fr 3fr"] { grid-template-columns: minmax(0, 1fr) !important; }
  /* Une fois empilée, la dernière carte de la colonne de gauche ajoutait sa
     propre marge basse à la gouttière de la grille : deux écarts au lieu
     d'un, juste au-dessus du tableau. */
  .content > .grid[style*="2fr 3fr"] > div > .card:last-child { margin-bottom: 0; }

  /* Prévision trésorerie : la table passe SOUS la frise. `.tr-table` fait
     300 px et ne rétrécit pas (`flex-shrink: 0`) : toute la compression de la
     carte `c8` tombe sur `.tr-chart`, seul élastique de la rangée — le motif
     qui faisait disparaître le nom dans « Suivi closing ». À 1 440 px la
     carte n'a que 727 px de dedans, la frise 405, et chaque mois 26 px —
     quand « sept. 26 » en mesure 38 au corps 10. Le libellé déborde alors les
     8 px de gouttière et percute son voisin ; à 1 280 il reste 17 px par
     mois, à 1 100 sept. La frise n'est plus qu'un peigne.
     Le seuil se calcule : un mois doit être au moins aussi large que son
     libellé (38 px), ce qui demande une frise de 544 px, donc une carte de
     898, donc une fenêtre d'environ 1 650. Rangé dans le palier 1600 — à
     1 601-1 650 le mois est à un pixel de son libellé, on ne crée pas un
     cinquième seuil pour ça.
     Ce bloc REMPLACE l'ancien repli écrit à 900 px de FENÊTRE (l. 327), qui
     oubliait les 240 px de la barre latérale et ne se déclenchait sur aucun
     portable. */
  .tr-wrap { flex-direction: column; }
  .tr-table { width: auto; max-height: 240px; }
  /* Sous ~1 240 px de fenêtre, même empilée la frise manque de place : elle
     DÉFILE plutôt que de rogner un mois. On ne sacrifie pas une donnée pour
     économiser une barre de défilement. */
  .tr-chart { overflow-x: auto; padding-bottom: 3px; }
  .tr-month { flex: 1 0 42px; }

  /* Légende du donut « Hébergement » : le libellé avant la décoration.
     `.offre-legend li` réserve cinq pistes : 11 px de pastille, le libellé,
     deux `auto`, 44 px pour une colonne de MONTANTS — plus quatre gouttières
     de 9 px. Dans la carte `c4` du tableau de bord des événements, à 1 440 px,
     la carte fait 373 px, le donut de 146 px (`flex-shrink: 0`) et sa
     gouttière en prennent 166, et il ne reste que 163 px à la ligne : 91 px
     de pistes fixes, ~42 px pour le nombre et le pourcentage, ~30 px au
     libellé. « Chambre individuelle » et « Chambre partagée » s'affichent
     tous deux « C… » : on ne sait plus quelle chambre réserver, c'est-à-dire
     la seule chose que la carte ait à dire.
     La cinquième piste n'existe que s'il y a un montant à y mettre : le donut
     du tableau de bord ADV en a un (`.lg-eur`), celui de l'hébergement non —
     il payait 53 px pour une colonne vide. Le `:not(.empty)` laisse de côté
     le « Aucune vente. » de l'ADV, qui est un paragraphe et non une ligne de
     légende. */
  .offre-legend li:not(.empty):not(:has(.lg-eur)) {
    grid-template-columns: 11px minmax(0, 1fr) auto auto;
  }
  /* Et dans une carte étroite, le donut passe AU-DESSUS de la légende au lieu
     de lui disputer la largeur : on empile, on ne rogne pas. */
  .dg .c4 .offre-wrap { flex-direction: column; align-items: stretch; gap: 12px; }
  .dg .c4 .offre-wrap .donut-chart { margin-inline: auto; }

  /* Eshop · le schéma du parcours et son panneau. Le diagramme mesure
     1 002 px de large (5 colonnes × 196 + la boîte de 170 + les marges, cf.
     `eshop/workflow_spec.py`) et le panneau réclame 320 px fermes. Les deux
     ne cohabitent pas sur un portable : à 1 440 px il ne reste que ~795 px de
     piste et « Ajuster » — qui s'exécute seul à la première visite — pose le
     diagramme à 76 %. Les libellés, dessinés en 10,5 px, se lisent alors à
     8 px ; à 1 280 px, à 6,3 px ; à 1 100 px, à 4,6 px. Le diagramme est là,
     entier, et illisible. La requête existante (l. 3375) parle de 920 px de
     FENÊTRE : la barre latérale gardant ses 240 px jusqu'à 760, elle ne se
     déclenche jamais sur un portable.
     Au-delà de 1 600 px « Ajuster » retombe sur 92 % ou mieux ; en deçà il
     faut choisir, et on choisit le schéma.
     Le panneau se range dessous EN LIGNE, pas en pile : légende, couverture
     et texte côte à côte tiennent en ~180 px de haut au lieu de 400. Et la
     carte du schéma rend la hauteur correspondante, car le panneau est la
     zone de lecture du survol : s'il sort de l'écran, survoler une case ne
     sert plus à rien — c'était tout l'intérêt de le coller, on ne le perd pas
     en le déplaçant. */
  .wf-wrap { grid-template-columns: minmax(0, 1fr); }
  .wf-canvas { max-height: calc(100vh - 340px); margin-bottom: 0; }
  .wf-side { position: static; flex-direction: row; flex-wrap: wrap; }
  .wf-side > .card { flex: 1 1 330px; margin-bottom: 0; }
  /* Étalé sur toute la largeur, le paragraphe d'explication ferait 150
     caractères de long. On borne la LIGNE, pas la carte : les pastilles de
     légende, elles, gagnent à s'étendre. */
  #wf-panel-text { max-width: 78ch; }
}


/* ───────────────────────────────────────────────────────────────────────────
   2. PALIER « PORTABLE » — 1520 px  ·  l'écran de la plainte
   ───────────────────────────────────────────────────────────────────────────
   Ici on ne replie rien : on RESSERRE. La moitié de la sensation « agobiante »
   n'est pas que le texte soit trop gros, c'est que chaque bloc est entouré de
   vide pendant que son contenu se serre. Squelette d'abord (gouttières,
   cartes, tableaux), puis les écrans.
   1520 et non 1400 : l'écran qui se plaint fait 1 440 de large. Une requête à
   1 400 ne s'y déclencherait jamais et le correctif serait lettre morte là où
   il sert.
   ─────────────────────────────────────────────────────────────────────────── */
@media screen and (max-width: 1520px) {

  /* ── Squelette ──────────────────────────────────────────────────────────
     La gouttière coûte une colonne de tableau. Le menu prend 240 px et les
     28 px de gouttière 56 de plus : on travaille sur 1 144 px pour une
     fenêtre de 1 440. L'en-tête, lui, sort de la gouttière par une marge
     négative puis la repaie intégralement dans son propre rembourrage — le
     vide est compté deux fois. À 18 px la page ne touche toujours pas le bord
     et rend 20 px à chaque écran. */
  .content { padding-top: 18px; padding-left: 18px; padding-right: 18px; }
  /* Propriété par propriété, jamais en raccourci : le `margin-bottom` de
     l'en-tête appartient à `.content:has(> .tabstrip) > .page-head` (6 px
     quand il y a des onglets, 18 px sinon). Un `margin` raccourci l'écraserait
     et décollerait la tira d'onglets de son titre. Les marges négatives
     doivent suivre au pixel, sinon la barre collante se décale du reste de la
     page. */
  .content > .page-head {
    margin-top: -18px; margin-left: -18px; margin-right: -18px;
    padding-left: 18px; padding-right: 18px;
  }
  /* Sur un portable, une carte `c3` de l'aperçu tombe autour de 240 px : ses
     32 px de rembourrage horizontal, c'est 14 % de la carte donnés au vide
     pendant que les chiffres se serrent. Rien dans une carte ne déborde par
     marge négative (les seuls débords de la feuille sont ceux des modals,
     calés sur leurs propres 22 px), donc la resserrer ne fait rien sortir. */
  .card { padding: 12px 13px; }

  /* Avant d'en arriver au défilement de la tira d'onglets, on resserre : même
     hauteur de bouton, moins de gras autour du texte. ~80 px rendus sur le
     registre des ventes — ses six boutons et ses trois onglets repassent
     ainsi sous les 1 144 px utiles, donc sans rien à faire défiler du tout. */
  .tabstrip > .tab-actions { gap: 6px; padding-left: 10px; }
  .tabstrip > .tab-actions .btn { padding: 4px 9px; font-size: 12.5px; }

  /* Un tableau dense rend ses marges au texte. `table.data th, td` porte
     7px 10px, soit 20 px de rembourrage PAR COLONNE : le registre des ventes
     a neuf colonnes, donc 180 px des ~1 112 de la carte dépensés en vide
     avant la première lettre. Comme la table est en `width: 100%` et en
     disposition automatique, ce sont « Client·e » et « Offre » qui paient —
     un nom passe à la ligne deux ou trois fois et une rangée qui devrait
     faire une ligne en fait quatre.
     `padding-left` / `padding-right` et non le raccourci, pour ne pas toucher
     à la hauteur de ligne que certains écrans ont déjà réglée.
     Les tableaux déjà compactés sont exclus : `.compact` (4/8) et
     `.table-compact` (4/9) ont chacun leur densité choisie à la main, et une
     règle générale posée ici l'emporterait sur eux par spécificité —
     (0,3,2) contre (0,1,1) — et déferait ce travail. `.pv-table`,
     `.eq-table` et `.rdv-table` sont dans ce cas : elles portent
     `.table-compact` et ont leur propre réglage plus bas. */
  .table-scroll table.data:not(.compact):not(.table-compact) th,
  .table-scroll table.data:not(.compact):not(.table-compact) td {
    padding-left: 7px;
    padding-right: 7px;
  }

  /* Un intitulé entier vaut mieux qu'un rang gagné. `.kpi-s .l` tronque à
     l'ellipse ; quand la tuile descend à son plancher de 112 px il ne reste
     que 88 px de texte, et « Remises accordées » (≈ 98 px en Inter 11 px)
     devient « Remises accord… » — un chiffre dont l'intitulé est amputé ne
     dit plus ce qu'il compte, et posé à côté de « Commissions » il se lit
     même de travers. Le plancher passe à 128 px : les 98 px du plus long
     intitulé plus les 22 px de rembourrage et les 2 px de filet, et rien de
     plus — au-delà, le bandeau partirait sur deux rangs à des largeurs où il
     se lit parfaitement sur un seul.
     `:not(.kpi-tight)` et pas seulement `.content` : le bandeau compact
     (l. 1207) a la même spécificité et perdrait par simple ordre de fichier.
     Or à son plancher de 108 px il reste 86 px de texte pour « RDV
     programmés » qui en demande 85 : rien n'y est coupé, et l'élargir
     casserait en deux le bandeau à sept tuiles du registre des ventes. */
  .content .kpi-strip:not(.kpi-tight) {
    grid-template-columns: repeat(auto-fit, minmax(128px, 1fr));
  }

  /* ── Accueil ────────────────────────────────────────────────────────────
     L'aperçu passe en trois tiers égaux. Accueil est à « / », le seul chemin
     où le script d'en-tête laisse la barre DÉPLOYÉE : le calcul y est donc le
     plus serré de toute la plateforme, et une carte `c3` n'y garde que
     ~245 px utiles à 1 440 px — alors qu'une ligne de « Suivi des paiements »
     demande ~215 px pour poser « Échéances à venir (7 j) » en face de son
     montant. On lit la rangée au millimètre, et un montant à six chiffres la
     fait déjà passer à la ligne.
     On re-proportionne au lieu d'empiler : 4/4/4 rend ~300 px utiles, la
     rangée 2 est déjà en tiers, et l'aperçu devient une planche à trois
     colonnes régulière — sans coûter une rangée de hauteur sur un écran de
     900 px, là où le client regarde en premier. Le graphe de CA suit sans
     casse : ses barres sont en `flex: 1` sous un `max-width` de 30 px.
     TRANCHÉ — cette règle (0,3,0) passe DEVANT le repli en moitiés du palier
     suivant (0,2,0), et c'est voulu : Accueil garde ses trois tiers jusqu'à
     la tablette. Retomber en moitiés y donnerait une `c6` pleine largeur,
     puis deux `c3` côte à côte, puis trois `c4` sur deux rangs dont une
     orpheline — quatre rangées et un trou, là où trois colonnes tiennent.
     `:has(> .c6)` ne vise que ce gabarit : seul `my_day.html` pose une carte
     `c6`, les autres tableaux de bord tiennent leur rangée en `c8`. */
  .dg:has(> .c6) > .c6,
  .dg:has(> .c6) > .c4,
  .dg:has(> .c6) > .c3 { grid-column: span 4; }

  /* ── Registre des ventes ────────────────────────────────────────────────
     SPÉCIFICITÉ — `table.data th` vaut (0,1,2) et `.sales-log th` (0,1,1) :
     la seconde ne l'emporte JAMAIS, requête média ou pas. C'est déjà pour ça
     que `.sales-log td { padding: 4px 10px }` (l. 1179) n'a jamais rien fait
     et que le registre s'affiche en 7/10. On double la classe sur le <table>,
     qui porte bien `class="data sales-log"` — et on en profite pour rendre
     enfin la hauteur de ligne resserrée que cette ligne morte promettait. */
  table.data.sales-log th { padding: 6px 7px; }
  table.data.sales-log td { padding: 4px 7px; }

  /* Le statut s'écrit sur deux lignes plutôt que de manger la colonne du nom.
     `.badge { white-space: nowrap }` est juste partout ailleurs : une
     pastille coupée en deux dans une fiche ne veut rien dire. Ici c'est
     l'inverse — la table est en `table-layout: auto`, donc le `nowrap` fait
     de la largeur maximale de « Paiement échelonné en cours › » la largeur
     MINIMALE de la colonne : ~227 px que Statut garde quelle que soit la
     place, et que Client·e finançait. Deux lignes de badge coûtent 16 px de
     hauteur, et seulement sur les lignes concernées. On n'a rien tronqué,
     rien caché : on a empilé. */
  .sales-log td > .badge {
    white-space: normal;
    /* Deux des trois branches du gabarit sont des <button> : leur feuille de
       style native centre le texte, et sur deux lignes le badge-bouton ne se
       lisait plus comme le badge-span d'à côté. */
    text-align: left;
    align-items: flex-start;
    /* Hauteur de ligne en PIXELS, pas en nombre : la puce `::before` l'hérite
       alors telle quelle au lieu de la recalculer sur ses 8 px. Les deux
       éléments du flex partagent la même boîte de ligne, donc la puce se cale
       toute seule sur la PREMIÈRE ligne du texte — c'est une puce, pas une
       décoration latérale. */
    line-height: 16px;
    /* Une pilule de 99 px sur un cartouche de deux lignes devient un ovale. */
    border-radius: 10px;
  }
  /* Le plancher vient avec : une fois qu'elle a le droit de se replier, la
     colonne tomberait à un mot par ligne, et « Paiement / échelonné / en
     cours » ne se lit pas mieux que la version qui écrasait le nom. 170 px
     laissent ~117 px de texte, de quoi tenir « Paiement échelonné » sur la
     première ligne ; 150 px en laissaient 97 et forçaient trois lignes.
     Scopé au registre : dix-huit autres tableaux posent un badge directement
     dans un <td> avec des libellés courts (« Faite », « Payée »), et leur
     imposer ce plancher élargirait leur colonne de statut aux dépens de leur
     propre colonne de noms — le défaut qu'on corrige, recopié ailleurs. */
  .sales-log td:has(> .badge) { min-width: 170px; }

  /* Le closer tient en 120 px : la pastille d'initiales, un nom rogné par
     `text-overflow` — son entier reste dans l'infobulle `data-tip` du
     fragment — et la croix. 120 et non 118 : l'état « à assigner » mesure
     20 (pastille) + 6 (gap) + 78 (champ) + 14 (cellule) = 118 au pixel près,
     et une colonne sans un cheveu de jeu déborde au premier arrondi. */
  .sales-log .col-closer, .sales-log .col-closer-cell { width: 120px; }
  .sales-log .closer-input, .sales-log .closer-edit .sel-search { width: 78px; }

  /* La barre de filtres tiendra de toute façon sur deux rangs ici ; on lui en
     évite un troisième.
     `.enc-filtres` est exclue et la cible est `input.f-date` : dans le modal
     Encaissements, `.f-date` est un <label> qui contient « du » ET son champ
     de 132 px. Lui imposer une largeur fixe est exactement ce qui faisait se
     chevaucher les dates (voir le commentaire l. 3110) ; un <label> ne matche
     pas `input.f-date`, et le `:not()` protège aussi ses <select>. */
  .filter-bar:not(.enc-filtres) input.f-search { width: 128px; }
  .filter-bar:not(.enc-filtres) input.f-date { width: 102px; }
  .filter-bar:not(.enc-filtres) select { max-width: 104px; }
  .filter-bar .btn { padding: 0 9px; }

  /* ── Suivi closing ──────────────────────────────────────────────────────
     Le rembourrage tombe à 7 px dans ce palier : quatre pixels de moins
     suffisent alors pour les mêmes contenus. Les largeurs et le plancher
     suivent, recalculés sur les corrections du socle :
       236 + 58 + 120 + 64 + 124 + 92 + 140 + 118 + 158 = 1 110, + 150 = 1 260
     (Ces déclarations REMPLACENT celles de la requête à 1 400 px, l. 5164 :
     même spécificité, ce bloc arrive après. Le rembourrage y est répété pour
     que la bande 1 400-1 520 ne garde pas les anciens 9 px avec les nouvelles
     largeurs.) */
  .pv-table th, .pv-table td { padding-left: 7px; padding-right: 7px; }
  .pv-table th.c-qui { width: 236px; }
  .pv-table th.c-act { width: 158px; }
  .pv-table .c-eta { width: 120px; }
  .pv-table .c-acc { width: 124px; }
  .pv-table .c-fat { width: 140px; }
  .pv-table .c-bud { width: 118px; }
  table.pv-table { min-width: 1260px; }
  table.pv-table:not(:has(.c-clo)) { min-width: 1202px; }

  /* ── Tableaux de bord ───────────────────────────────────────────────────
     Remplissage : le nom ne se replie pas, c'est la jauge qui cède. Les deux
     pistes sont en proportion pure (1.1fr / 2fr) : la jauge grandit avec la
     carte alors qu'elle se lit entière à 150 px, et le nom rétrécit avec elle
     alors que lui a une longueur PLANCHER — 30 caractères imposés par le
     gabarit, soit environ 200 px. À 1 280 px il ne reste que 184 px au nom, à
     1 100 px 141 : il se replie sur deux lignes, et comme la date est déjà un
     bloc en dessous la ligne monte à trois niveaux pendant que la barre
     continue de s'étaler. Pas d'inversion du rapport : au-delà du plancher le
     nom ne saurait rien faire de la place en plus, la vignette étant tronquée
     à 30 signes. */
  .rmp-row { grid-template-columns: minmax(200px, 1.1fr) minmax(0, 2fr) 64px; gap: 10px; }

  /* ── Gains & critères de succès ─────────────────────────────────────────
     Six tuiles sur une grille dont le plancher est 150 px. Mesuré en Inter
     12 px, la plus longue légende (« ≈ 12 min gagnées chacune », 149 px) et
     le plus long libellé (« Notifications (ex-Signal) », 134 px) tiennent
     encore dans les 153 px utiles d'une tuile à 1 440 px — mais la tuile
     tombe à 141 px de texte à 1 366 px puis 127 px à 1 280, et deux puis cinq
     chaînes passent à deux lignes : la rangée prend la hauteur de la pire et
     l'écran vitrine du cahier des charges devient une bande de pavés
     irréguliers.
     On ne remonte PAS le plancher de l'`auto-fit` : c'est lui qui choisit le
     nombre de colonnes, et à 1 440 comme à 1 500 px un plancher de 200 px en
     retient CINQ — la sixième tuile se retrouve seule sur une rangée à quatre
     cases vides, précisément sur l'écran de référence. On impose donc le
     repli 3+3 : deux rangées pleines, aucune orpheline, et 232 px de texte
     même à 1 100 px. Oui, ça coûte une rangée dès 1 440 : c'est justement
     l'écran qui étouffe, et deux rangées aérées s'y lisent mieux qu'une
     rangée de six pavés à deux étages.
     Le `:has` limite la correction aux bandes de SIX tuiles ; celles de trois
     (onboarding/accesses) et de cinq (contacts/kpis) tiennent déjà.
     `minmax(0, …)` et non `1fr` seul : un libellé long ne peut pas forcer la
     piste au-delà de sa part et faire déborder la bande. */
  .kpis:has(> .kpi:nth-child(6)) { grid-template-columns: repeat(3, minmax(0, 1fr)); }

  /* ── Équipe ─────────────────────────────────────────────────────────────
     Le défilement est permis, mais il ne doit pas COMMENCER avant la colonne
     « Accès » : neuf colonnes réclament ~1 390 px quand un portable en offre
     1 112, et la pastille d'état et les six gestes de la ligne naissaient donc
     hors cadre — pour suspendre un compte il fallait pousser la table vers la
     droite, ligne après ligne. On reprend la place là où elle ne porte aucune
     information : deux pixels de rembourrage par bord, et un champ d'agenda
     taillé pour un slug de douze caractères (« celine-wutao ») plutôt que
     pour vingt-huit. Rien n'est caché : le champ reste éditable, défile sous
     le curseur, et son `title` porte l'URL entière.
     La spécificité est montée à (0,2,1) et (0,3,1) pour l'emporter où qu'on
     colle ce bloc : `.table-compact th/td` et `.td-cal input.inline-edit` ont
     exactement la même que les sélecteurs naïfs, et un `@media` n'en ajoute
     pas. `.eq-bande td` garde son rembourrage propre (il est en !important),
     et les autres tableaux `.table-compact` ne bougent pas.
     L'e-mail n'est volontairement PAS resserré : sa cellule n'a ni `title` ni
     `data-tip` (team.html:162), une adresse coupée y serait irrécupérable ;
     et `.eq-table` n'ayant pas `table-layout: fixed`, un `max-width` sur le
     <td> n'y mord pas de façon fiable.
     NOTE pour la suite : le vrai gaspillage n'est pas l'e-mail mais la
     colonne « Groupe » (~338 px, plus qu'Agenda et E-mail réunis), gonflée
     par `.td-groupe{nowrap}` + `.grp-cell{flex-wrap:nowrap}` + un select
     « ＋ Ajouter… » de 128 px sur chaque ligne. On n'y touche pas ici : c'est
     un choix délibéré et commenté (l. 5909-5910). */
  .eq-table.table-compact th,
  .eq-table.table-compact td { padding-left: 7px; padding-right: 7px; }
  .eq-table .td-cal input.inline-edit { width: 118px; }

  /* ── Agendas des closers ────────────────────────────────────────────────
     Le rembourrage compact s'applique enfin vraiment : `.table-compact th`
     (0,1,1) perd contre `table.data th` (0,1,2), donc la classe compacte ne
     réduisait rien du tout sur ce tableau. Le seuil de défilement descend
     vers 1 350 px. */
  table.data.rdv-table th, table.data.rdv-table td { padding-left: 7px; padding-right: 7px; }
  .rdv-table { min-width: 1024px; }
  .rdv-table th:nth-child(1) { width: 134px; }
  .rdv-table th:nth-child(2) { width: 124px; }
  .rdv-table th:nth-child(4) { width: 140px; }
  .rdv-table th:nth-child(5) { width: 112px; }
  .rdv-table th:nth-child(7) { min-width: 130px; }
  .rdv-table th:nth-child(8) { width: 134px; }

  /* Le calendrier commun : le nom du prospect ne se tronque plus. La grille à
     sept colonnes donne 157 px par jour à 1 440 px, et la pastille n'a plus
     que 133 px à l'intérieur ; l'heure et sa gouttière en prennent 33, il
     reste une vingtaine de signes. À 1 280 px le nom tombe à 78 px, à 1 100 à
     52 — dix signes, « Marie-Clai… ». Or le nom du prospect EST l'identité du
     rendez-vous : la teinte `--rdv` ne nomme que le closer, et le nom du
     closer est déjà écrit dessous précisément parce que quinze teintes ne se
     distinguent pas à l'œil. Quand il ne tient pas à côté de l'heure, il
     passe DESSOUS et la case s'allonge — `.cal-jour` est une colonne flexible
     à hauteur MINIMALE, sans plafond. Vaut pour la vue mois comme pour la vue
     semaine : c'est la même pastille. */
  .cal-rdv { padding-left: 5px; padding-right: 5px; }
  /* SANS gouttière verticale : `gap` s'applique aussi entre les lignes d'un
     flex replié, et chaque pastille repliée gonflerait de 5 px pour rien.
     C'est la hauteur des cases qu'on paie ici, autant ne payer que le texte. */
  .cal-l1 { flex-wrap: wrap; column-gap: 5px; row-gap: 0; }
  /* `.cal-rdv` est en `overflow: hidden` : sans coupure de dernier recours,
     un nom composé plus large que la pastille serait COUPÉ net — pire que les
     points de suspension qu'on vient d'enlever. `anywhere` ne coupe que
     lorsqu'aucune espace ne se présente. */
  .cal-qui {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    overflow-wrap: anywhere;
  }

  /* ── Care · Appels ──────────────────────────────────────────────────────
     Le bouton cède le peu qu'il peut céder sans qu'on touche à son libellé :
     des écarts plus serrés. On ne masque ni « min » ni le texte du bouton. */
  .content:has(#appel-modal) .rappel-fait { gap: 4px; }

  /* ── Fournisseurs ───────────────────────────────────────────────────────
     `.grid-32` ne sert que sur `ops/suppliers.html` : son seuil se calcule
     donc sur ce contenu-là. Celui de la l. 1561 mesurait la FENÊTRE — le rail
     en prend 240 et le rembourrage 56, si bien qu'il ne restait que 804 px de
     contenu quand le repli se déclenchait enfin, trois cents pixels trop
     tard. Le tableau a six colonnes dont aucune ne se comprime sous son mot
     le plus long : l'étiquette de pièce jointe, les deux pastilles et le
     bouton sont tous en `nowrap` — plancher mesuré ~630 px. Sur le portable
     de référence la colonne « 3fr » n'en laisse que ~659 dans la carte : on
     est déjà au contact, et c'est le fournisseur et l'objet, le QUI et le
     QUOI de la facture, qui se cassent en escalier. On empile tant que le
     tableau n'a pas confortablement ses ~680 px. */
  .grid-32 { grid-template-columns: 1fr; }
  /* Une fois empilé, le formulaire hérite des ~1 110 px du tableau : sans
     bride, « Montant TTC » devient un champ de 545 px. On le ramène à une
     largeur de formulaire, en une seule règle pour que les champs gardent
     entre eux leurs proportions. */
  .grid-32 > .card:last-child form { max-width: 720px; }
}


/* ───────────────────────────────────────────────────────────────────────────
   3. PALIER « PETIT PORTABLE » — 1300 px
   ───────────────────────────────────────────────────────────────────────────
   Resserrer ne suffit plus : on REPLIE. Une grille à trois ou quatre colonnes
   doit retomber sur deux, puis sur une — jamais se serrer.
   ─────────────────────────────────────────────────────────────────────────── */
@media screen and (max-width: 1300px) {

  /* La grille de douze colonnes retombe sur des moitiés. Le repli existant
     (l. 2926) est écrit à 1 000 px de FENÊTRE alors que la grille vit dans
     `.content`, plus étroit de 276 px : à 1 280 px menu ouvert elle dispose
     de 1 004 px, soit douze colonnes de 73 px, donc une carte `c3` de 242 px
     et une `c4` de 327. À 1 100 px la `c3` tombe à 192 px — 166 px de contenu
     une fois le rembourrage et le filet déduits — pour y loger un donut de
     112 px et deux lignes de légende. Quatre cartes côte à côte là où il en
     faudrait deux, et le repli n'arrivait qu'une fois la zone de travail
     descendue à 704 px. C'est exactement le « ça se serre au lieu de retomber
     sur deux colonnes ».
     1 300 de fenêtre = ~1 000 px de grille, largeur en dessous de laquelle
     une `c3` cesse d'être lisible. Sous 1 180 px `base.html` force le rail et
     les deux mesures se rejoignent ; entre 1 181 et 1 300 un utilisateur en
     rail replie ~120 px trop tôt — ses cartes deviennent plus LARGES, jamais
     plus étroites, et c'est le prix d'un seul système de seuils au lieu de
     deux.
     Ces sélecteurs (0,2,0) pèsent autant que le repli mobile de la l. 2930 et
     gagneraient par simple position : le palier tablette, plus bas, les
     reprend explicitement. */
  .dg .c3, .dg .c4, .dg .c5 { grid-column: span 6; }
  .dg .c6, .dg .c7, .dg .c8 { grid-column: span 12; }

  /* Espace élève : les deux colonnes se replient. L'ancien seuil (l. 2800) se
     lisait lui aussi sur la fenêtre : le rail (240), les rembourrages du
     contenu (56), la gouttière (14) et la carte (32 + 2 de liseré) en
     prennent 344, si bien que la colonne principale ne vaut que ~505 px de
     carte à 1 280 px. Or « Mes factures & paiements » a un plancher
     incompressible d'environ 465 px — la pastille « Partiellement encaissée »
     est en `nowrap` (~165 px), le montant aussi (~90), la colonne Facture est
     figée à 64, et il reste le mot le plus long du nom d'offre
     (« accompagnement », ~105). Sous ~1 205 px ce plancher dépasse la carte,
     et ce tableau n'est PAS dans un `.table-scroll` : il sortait du bord
     arrondi et mordait sur la colonne de droite (le filet du socle l'attrape
     désormais, mais mieux vaut lui rendre la place). À 1 440 px rien ne
     bouge : deux colonnes, 628 / 502. Séances et événements passent sous les
     formations : on empile, on ne cache rien.
     Cette règle REMPLACE la l. 2800, qui devient morte — 1 300 englobe
     1 100 ; ne pas laisser les deux, la spécificité est identique et seule la
     position déciderait. */
  .portal-cols { grid-template-columns: 1fr; }

  /* Fiche d'un événement : le nom de l'élève ne quitte pas l'écran. Le
     tableau des inscrits porte neuf colonnes dont cinq refusent de se
     comprimer (« Chambre individuelle », « Client depuis 12 ans », les badges
     et le bouton, tous en `nowrap`) : son plancher avoisine 1 040 px quand un
     portable de 1 280 n'offre que ~950 px dans la carte. Il déborde donc et
     défile — c'est le bon comportement, la maison l'assume — mais le
     défilement emporte la première colonne, donc l'identité de la ligne : on
     se retrouve à lire un régime alimentaire sans savoir de qui il est. La
     colonne du nom s'ancre à gauche, comme l'en-tête s'ancre déjà en haut.
     Rangé ici et non plus haut : au-dessus de 1 300 px la table ne défile pas,
     et l'ancrage n'aurait dessiné qu'un filet vertical gratuit.
     `:has(> .ed-tete)` désigne la fiche d'un événement et elle seule — même
     tournure que `.content:has(> .tabstrip)` plus haut dans la feuille, et
     c'est le seul `.table-scroll` de la page. `:not(.empty)` écarte la
     cellule « Aucun inscrit » : elle porte un `colspan` de neuf, l'ancrer la
     ferait glisser par-dessus le tableau. */
  .content:has(> .ed-tete) .table-scroll td:first-child:not(.empty) {
    position: sticky; left: 0; z-index: 1; background: var(--surface);
    /* `border-collapse: collapse` fait peindre les filets par le TABLEAU,
       donc SOUS les cellules positionnées : ancrée, cette cellule effacerait
       le filet de sa propre rangée et les séparateurs sembleraient ne
       commencer qu'à la deuxième colonne. On le rend en ombre — le même
       remède que l'en-tête ancré emploie déjà (l. 2697). Le second filet
       marque le bord de la colonne gelée, sans quoi les colonnes suivantes
       s'évanouiraient sous une arête invisible. */
    box-shadow: 0 1px 0 #eceae4, 1px 0 0 var(--hairline);
  }
  /* La dernière rangée n'a pas de filet bas : lui en rendre un ne laisserait
     qu'un moignon d'un centimètre sous la seule première colonne. */
  .content:has(> .ed-tete) .table-scroll tr:last-child td:first-child {
    box-shadow: 1px 0 0 var(--hairline);
  }
  /* L'angle haut-gauche est ancré dans les deux sens : il doit passer devant
     l'en-tête ancré (z-index 2) comme devant les cellules ancrées (1). */
  .content:has(> .ed-tete) .table-scroll th:first-child {
    position: sticky; left: 0; z-index: 3;
    box-shadow: 0 1px 0 var(--hairline), 1px 0 0 var(--hairline);
  }
  /* Une inscription annulée porte ses hachures sur la RANGÉE ; un fond opaque
     posé sur la première cellule les effacerait juste là où se lit « annulée
     le… » — l'ancrage aurait sauvé le nom en perdant son statut. On repose le
     même motif sur la cellule ancrée, par-dessus son fond opaque. */
  .content:has(> .ed-tete) .table-scroll .reg-annulee td:first-child {
    background:
      repeating-linear-gradient(-45deg, transparent, transparent 7px,
                                rgba(11, 11, 11, .018) 7px, rgba(11, 11, 11, .018) 14px),
      linear-gradient(var(--surface), var(--surface));
  }
  /* Le survol repeint la rangée entière : sans cette règle, la colonne ancrée
     serait la seule à ne pas s'allumer avec elle. En dernier, pour l'emporter
     aussi sur une rangée annulée survolée, comme partout ailleurs. */
  .content:has(> .ed-tete) .table-scroll tr:hover td:first-child { background: #f5f8fd; }

  /* Suivi closing : à cette largeur la rangée de filtres finit par se replier
     pour de bon, malgré la base flex courte posée dans le socle. La recherche
     rend alors sa marge automatique : si elle descend, elle descend SOUS les
     filtres, pas à l'autre bout de l'écran, à 860 px du reste de la barre. */
  .filter-bar .pv-chercher { margin-left: 0; }
}


/* ───────────────────────────────────────────────────────────────────────────
   4. PALIER « TABLETTE PORTRAIT » — 760 px  ·  palier existant
   ───────────────────────────────────────────────────────────────────────────
   Le rail y est déjà imposé (l. 281). Tout ce qui restait en colonnes y passe
   sur une seule.
   ─────────────────────────────────────────────────────────────────────────── */
@media screen and (max-width: 760px) {

  /* Reprise EXPLICITE du repli mobile de la l. 2930. Les règles des deux
     paliers précédents pèsent (0,2,0) et (0,3,0) et sont écrites après lui :
     sans cette reprise, un téléphone garderait deux cartes de front, et
     Accueil ses trois tiers à 200 px. Le second sélecteur vise ce cas-là. */
  .dg > .card,
  .dg:has(> .c6) > .card { grid-column: span 12; }

  /* La bande des six gains repasse la main à son `auto-fit`, qui converge de
     lui-même vers deux colonnes puis une — meilleur qu'un 3 forcé sur un
     écran étroit. */
  .kpis:has(> .kpi:nth-child(6)) {
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr));
  }
}


/* ───────────────────────────────────────────────────────────────────────────
   5. HORS PALIERS — la HAUTEUR, pour les modals de Care
   ───────────────────────────────────────────────────────────────────────────
   Le seuil est posé en hauteur parce que le défaut est vertical : une fenêtre
   large mais haute n'a rien à corriger, une fenêtre large et basse l'a
   entièrement. C'est le cas de tous les portables.

   TRANCHÉ — le diagnostic d'ensemble qui circulait (« chaque cadre porte sa
   borne en vh, additionnées elles débordent ») ne se vérifie pas : dans
   `#listes-modal`, le catalogue (46vh) et l'annuaire (52vh) sont les deux
   branches d'un même test de gabarit, et « quelle liste pour quelle offre »
   vit dans un onglet masqué — jamais deux cadres à l'écran en même temps.
   Idem pour `#cours-modal` et `#modeles-modal`. On ne rogne donc rien là où
   rien ne se chevauche : un catalogue de 247 listes a besoin de ses lignes.

   Restent deux choses vraies. L'overlay garde 24 px de gouttière pendant que
   la boîte s'arrête à 88vh : sur 900 px logiques, 60 px inutilisés. Et
   `#liste-modal`, où la table des membres est bornée à 72vh SOUS l'en-tête,
   le champ d'ajout, le bandeau de synchronisation et les campagnes — environ
   200 px. 200 + 72vh dépasse 88vh tant que la fenêtre fait moins de 1 250 px
   de haut, c'est-à-dire toujours sur un portable : deux barres de défilement
   empilées, et la molette pousse la mauvaise.
   ─────────────────────────────────────────────────────────────────────────── */
@media screen and (max-height: 1250px) {
  #geste-modal, #listes-modal, #liste-modal, #listes-roles-modal,
  #cours-modal, #modeles-modal, #kb-modal, #lms-modal { padding: 14px; }
  #geste-modal > .modal-box, #listes-modal > .modal-box,
  #liste-modal > .modal-box, #listes-roles-modal > .modal-box,
  #cours-modal > .modal-box, #modeles-modal > .modal-box,
  #kb-modal > .modal-box, #lms-modal > .modal-box {
    max-height: calc(100vh - 28px);
  }
  /* La table prend ce qui reste sous le chrome qui la précède — mesuré, pas
     une fraction devinée de la fenêtre, sinon le rapport se déforme à chaque
     hauteur. Le plancher garde des lignes lisibles sur une fenêtre très
     basse : là seulement, la boîte reprend son défilement, ce qui reste
     honnête puisque rien n'est masqué. */
  #liste-modal .table-scroll {
    max-height: calc(100vh - 243px);
    min-height: 200px;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   6. LES TROIS MANQUES — relevés par la relecture finale
   ═══════════════════════════════════════════════════════════════════════════
   Trois écrans denses qu'aucun relevé n'avait mesurés, ajoutés après coup.
   ═════════════════════════════════════════════════════════════════════════ */

/* ── Dé-marquer une échéance, et sa trace (HH-2586) ────────────────────────
   Le lien est discret : c'est un geste rare et lourd, il ne doit pas se
   cliquer par erreur à côté d'« Encaisser ». Il se teinte au survol, quand on
   l'a visé exprès. */
/* Un vrai bouton, pas un mot gris : écrit « non réglée ? » en 11 px pâles, il
   ne se lisait pas comme un geste — « je ne vois pas où décocher ». Il reste
   sobre (c'est rare et lourd), mais il a une bordure et un fond au survol. */
.ech-devalider { margin-left: 8px; padding: 2px 9px; border-radius: 7px;
  font: inherit; font-size: 11.5px; font-weight: 600; cursor: pointer;
  color: var(--sem-defaut-t); background: var(--sem-defaut-bg);
  border: 1px solid transparent; transition: border-color .12s, filter .12s; }
.ech-devalider:hover, .ech-devalider:focus-visible { border-color: #f2ccc4;
  filter: brightness(.97); outline: none; }
/* Le même geste depuis le popover du registre : un lien, il change d'écran. */
.ei-dev { margin-left: 8px; font-size: 10.5px; font-weight: 600;
  color: var(--sem-defaut-t); white-space: nowrap; }
.ei-dev:hover { text-decoration: underline; }
/* Le journal : une trace se lit, elle ne se survole pas. Tout est écrit. */
.dev-journal { display: flex; flex-direction: column; gap: 8px; }
.dev-ligne { padding: 10px 12px; border-radius: 10px; background: var(--page);
  border: 1px solid var(--hairline); border-left: 3px solid var(--sem-defaut); }
.dev-tete { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.dev-tete b { font-size: 13px; }
.dev-motif { margin: 4px 0 6px; font-size: 12.5px; color: var(--ink); line-height: 1.5; }
.dev-meta { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: 11px; color: var(--muted); }
.dev-meta .dev-compta { color: var(--sem-attente-t); font-weight: 600; }

/* ── Les types de rendez-vous Calendly (HH-2583) ───────────────────────────
   Une ligne par type, son volume au bout : c'est le chiffre qui fait décider.
   Même grammaire que les listes Brevo — on coche, on enregistre. */
.tr-liste { display: flex; flex-direction: column; gap: 4px;
  max-height: 52vh; overflow-y: auto; margin-bottom: 4px; }
.tr-ligne { display: flex; align-items: center; gap: 11px; margin: 0; padding: 8px 11px;
  border: 1px solid var(--hairline); border-radius: 10px; background: var(--surface);
  cursor: pointer; transition: border-color .12s, background .12s; }
.tr-ligne:hover { border-color: var(--sem-care); }
.tr-ligne:has(input:checked) { background: var(--sem-care-bg); border-color: var(--sem-care); }
.tr-ligne input[type=checkbox] { flex: none; margin: 0; }
.tr-corps { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.tr-corps b { font-size: 13px; font-weight: 600; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.tr-corps i { font-size: 11.5px; font-style: normal; color: var(--muted); }
.tr-vus { flex: none; min-width: 52px; text-align: right; font-size: 13px; font-weight: 650;
  color: var(--ink-2); font-variant-numeric: tabular-nums; }
.tr-ligne.inactif { opacity: .6; }
.tr-compte { font-size: 12.5px; color: var(--muted); }

/* ── Un plancher d'identité pour les tables denses ──────────────────────────
   Le filet du socle fait défiler une carte dont la table déborde. Mais en
   disposition automatique une colonne cède AVANT que la table ne dépasse :
   elle se replie sur son mot le plus long, et le défilement n'arrive jamais.
   La colonne qui cède est toujours la même — la première, celle qui porte
   l'identité de la ligne — parce que les autres sont des pastilles, des dates
   ou des états, tous insécables.

   Cinq écrans dans ce cas, marqués `t-id` dans leur gabarit : la logistique
   (tâche), les accès e-learning et les cohortes (élève), le tableau de bord
   de la boutique (numéro de commande) et les sept tables de la recherche, où
   l'identité EST le résultat. On leur donne un plancher, et on donne un
   plancher à la table pour que ce soit elle qui défile. */
table.data.t-id { min-width: 760px; }
table.data.t-id th:first-child,
table.data.t-id td:first-child:not([colspan]) { min-width: 190px; }

/* ── Contacts · le nom n'est pas la variable d'ajustement ───────────────────
   Cinq colonnes sur six refusent de céder : l'e-mail est un mot d'un seul
   tenant, « Pays » est court, et « Ancienneté », « Tags comportementaux »
   (jusqu'à quatre pastilles) et « Sellsy » sont insécables. La seule
   compressible est « Contact » — l'identité, sur l'écran où vivent les cent
   vingt et une clientes. */
.ct-table { min-width: 940px; }
.ct-table th:nth-child(1), .ct-table td:nth-child(1):not([colspan]) { min-width: 190px; }
.ct-table td:nth-child(1) > b { white-space: nowrap; }
/* Quatre pastilles côte à côte sur une ligne, ou elles ne se lisent pas. */
.ct-table td:nth-child(5) { min-width: 200px; }

/* ── Cartes B-Sport · le poste de Laure ─────────────────────────────────────
   Sept colonnes, dont deux de gestes à bouton. Même règle que ses sœurs : la
   cliente d'abord, et la table défile plutôt que de replier son nom. */
.bsport-log { min-width: 900px; }
.bsport-log th:first-child,
.bsport-log td:first-child:not([colspan]) { min-width: 180px; }

/* ── « Retards & relances » · trois cadres dans UN seul volet ───────────────
   Le palier en hauteur plus haut ne vaut que pour Care : là-bas, les cadres
   défilants sont les branches d'un même test de gabarit, jamais deux à
   l'écran en même temps. Ici si. `#rl-pilotage` montre SIMULTANÉMENT la file
   des impayés (42vh) et les deux panneaux appels / escalades (36vh chacun) :
   78vh de cadres dans une boîte plafonnée à 88vh, en-tête et tuiles en plus.
   Sur un portable de 900 px, quatre barres de défilement emboîtées et la
   molette pousse la mauvaise. Rien n'est masqué : ce qui dépasse défile,
   mais dans UN cadre à la fois. */
@media screen and (max-height: 1250px) {
  #relance-modal { padding: 14px; }
  #relance-modal > .modal-box { max-height: calc(100vh - 28px); }
  #relance-modal .rl-table-wrap { max-height: 34vh; }
  #relance-modal .rl-panel { max-height: 30vh; }
}

/* HH-2619 — une pastille d'accueil sans objet pour cette offre : elle garde sa
   place dans la rangée (les trois s'alignent d'une ligne à l'autre), mais ne
   se lit plus comme un geste en retard. */
.ac-e.na { opacity: .35; }

/* HH-2619 — « Retirer de la file », en bout de pied de modal : un geste rare,
   qui ne doit pas se lire comme le travail du jour. */
.ge-retrait { display: inline-flex; align-items: center; gap: 8px; margin-left: auto; }

/* HH-2616 — le virement qui paie la vente qu'on saisit : rattaché d'office
   (« Créer la vente » depuis Encaissements) ou signalé quand la cliente
   choisie en a un qui n'est rattaché à rien. */
.vt-virement {
  display: flex; align-items: flex-start; gap: 10px; margin: 10px 0 2px;
  padding: 9px 12px; border-radius: 10px; font-size: 12.5px;
  background: var(--good-tint); color: var(--ink);
}
.vt-virement.vt-propose { background: var(--sem-attente-bg); }
.vt-ico {
  flex: none; width: 22px; height: 22px; border-radius: 50%;
  display: grid; place-items: center; font-weight: 700; font-size: 12px;
  background: var(--good-text); color: #fff;
}
.vt-propose .vt-ico { background: var(--sem-attente-t); }
.vt-choix { display: flex; flex-direction: column; gap: 4px; margin-top: 6px; }
.vt-ligne { font-weight: 400; align-items: flex-start; }
@media (max-width: 760px) { .vt-virement { flex-wrap: wrap; } }

/* `.clamp-1` est un `display: block` : posé sur un <td>, il sortait la cellule
   du tableau et ses traits de séparation ne tombaient plus en face de ceux de
   la ligne (Encaissements, colonne « Saisi par »). On rend à toute cellule son
   rôle de cellule, quelle que soit la classe qu'on lui met — pour que l'erreur
   ne puisse plus casser un tableau, où qu'elle revienne. Le recadrage se fait
   dans un bloc intérieur (`.cel-tronquee`). */
table td.clamp-1, table th.clamp-1 { display: table-cell; }
.cel-tronquee { max-width: 260px; }

/* HH-2616 — associer une vente depuis sa ligne d'Encaissements.
   `.enc-cel-vente` et pas `.enc-vente` : ce nom-là est déjà le bloc des
   ventes proposées dans la saisie, et il grisait toute la colonne. */
.enc-cel-vente { white-space: nowrap; }
.enc-associer {
  display: inline-flex; align-items: center; gap: 5px; vertical-align: middle;
  border: 1px dashed var(--hairline); border-radius: 8px; padding: 2px 8px;
  background: var(--surface); margin-right: 4px;
}
.enc-associer:focus-within { border-style: solid; border-color: var(--accent); }
.enc-associer-ico { color: var(--ink-2); display: inline-flex; }
/* Spécificité relevée exprès : le style global des champs texte (bordure,
   fond, ombre au focus) dessinait une seconde boîte DANS le contour. */
.enc-associer input.enc-associer-champ,
.enc-associer input.enc-associer-champ:focus {
  border: 0; border-radius: 0; background: transparent; box-shadow: none;
  outline: none; padding: 3px 0; width: 150px; font-size: 12.5px;
}
/* La liste flotte hors du tableau : dans `.table-scroll` elle serait coupée. */
.encp-liste {
  position: fixed; z-index: 160; width: 400px; max-height: 360px; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--hairline); border-radius: 12px;
  box-shadow: 0 16px 40px rgba(21, 26, 43, .16), 0 2px 6px rgba(21, 26, 43, .06);
  padding: 6px;
}
/* `encp-` et pas `enc-prop` : ce nom-là est déjà la ligne de proposition
   de la saisie (bordure et marge en haut), et il décalait cette liste. */
.encp-tete { padding: 6px 8px 8px; font-size: 10.5px; font-weight: 600; letter-spacing: .05em;
             text-transform: uppercase; color: var(--muted); }
.encp-item {
  display: flex; align-items: flex-start; gap: 11px; width: 100%; text-align: left;
  border: 1px solid transparent; background: transparent; padding: 9px 10px;
  border-radius: 9px; cursor: pointer; font: inherit;
}
.encp-item + .encp-item { margin-top: 2px; }
.encp-item.actif, .encp-item:focus-visible { background: var(--page); border-color: var(--hairline);
                                             outline: none; }
.encp-ini { flex: none; width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center;
            font-size: 11.5px; font-weight: 600; letter-spacing: .02em;
            background: var(--sem-vente-bg); color: var(--sem-vente-t); }
.encp-item.colle .encp-ini { background: var(--sem-facture-bg); color: var(--sem-facture-t); }
.encp-corps { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1; }
.encp-haut { display: flex; align-items: baseline; gap: 8px; }
.encp-nom { font-size: 13px; font-weight: 600; color: var(--ink); white-space: nowrap;
            overflow: hidden; text-overflow: ellipsis; }
.encp-sienne { flex: none; font-size: 10.5px; padding: 1px 6px; border-radius: 999px;
               background: var(--sem-vente-bg); color: var(--sem-vente-t); }
.encp-montant { margin-left: auto; flex: none; font-size: 13px; font-weight: 600;
                font-variant-numeric: tabular-nums; color: var(--ink); }
.encp-offre { font-size: 12px; color: var(--ink-2); white-space: nowrap; overflow: hidden;
              text-overflow: ellipsis; }
.encp-bas { display: flex; align-items: center; gap: 8px; margin-top: 2px; }
.encp-motif { font-size: 11.5px; padding: 2px 8px; border-radius: 999px;
              background: var(--page); color: var(--ink-2); border: 1px solid var(--hairline); }
.encp-motif.ok { background: var(--sem-facture-bg); color: var(--sem-facture-t); border-color: transparent;
                 font-weight: 500; }
.encp-num { margin-left: auto; font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums;
            white-space: nowrap; }
.encp-vide { padding: 10px 10px 12px; display: flex; flex-direction: column; gap: 3px; }
.encp-vide b { font-size: 12.5px; color: var(--ink); font-weight: 600; }
.encp-vide span { font-size: 12px; color: var(--muted); }
.encp-pied { padding: 8px 8px 4px; margin-top: 4px; border-top: 1px solid var(--hairline);
             font-size: 11px; color: var(--muted); }
.icon-btn-danger:hover { color: var(--sem-defaut-t); }

/* Questions du type Calendly dans le modal de rendez-vous (HH-2620) */
.rdv-envoi .cq { margin-top: 10px; display: grid; gap: 10px; }
.rdv-envoi .cq-question { display: grid; gap: 4px; }
.rdv-envoi .cq-titre { font-size: 13px; font-weight: 600; }
.rdv-envoi .cq-choix { font-weight: 400; font-size: 13px; }
.rdv-envoi .cq textarea, .rdv-envoi .cq input[type=text],
.rdv-envoi .cq input[type=tel] { width: 100%; }
.rdv-envoi .cq[hidden] { display: none; }
.rdv-envoi .cq-erreur { margin: 0; font-size: 13px; color: var(--sem-defaut-t); }

/* HH-2616 — modifier un paiement. Un champ verrouillé doit se VOIR verrouillé :
   blanc et net, il se lisait éditable et le refus à l'envoi surprenait. */
#enc-edit-modal input:disabled, #enc-edit-modal select:disabled {
  background: var(--page); color: var(--ink-2); cursor: not-allowed;
}
.enc-verrou {
  display: flex; align-items: center; gap: 8px; margin: 0 0 12px;
  padding: 8px 11px; border-radius: 9px; font-size: 12.5px;
  background: var(--sem-attente-bg); color: var(--sem-attente-t);
}
.enc-verrou svg { flex: none; }
.enc-piece { display: flex; align-items: center; gap: 10px; margin-top: 6px; font-size: 12.5px; }
.enc-piece-l { font-weight: 600; }
.enc-piece-nom { flex: 1; min-width: 0; color: var(--ink-2); overflow: hidden;
                 text-overflow: ellipsis; white-space: nowrap; }
.enc-piece label.btn { cursor: pointer; }

/* HH-2616 — un paiement reçu qui correspond à une vente en attente. À voix
   basse : une ligne discrète au-dessus des chiffres, pas un bandeau d'alarme.
   Il n'apparaît que lorsqu'un clic suffit à rapprocher. */
.enc-coincide {
  display: inline-flex; align-items: center; gap: 8px; max-width: 100%;
  align-self: flex-start; width: fit-content;
  margin: 0 0 12px; padding: 5px 11px; border-radius: 999px;
  border: 1px solid var(--hairline); background: var(--surface);
  font: inherit; font-size: 12.5px; color: var(--ink-2); cursor: pointer; text-align: left;
}
.enc-coincide svg { flex: none; color: var(--accent); }
.enc-coincide b { color: var(--ink); font-weight: 600; }
.enc-coincide span:first-of-type { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.enc-coincide-go { flex: none; color: var(--accent); font-weight: 600; }
.enc-coincide:hover { border-color: var(--accent); }
.rdv-envoi .cq-type { display: grid; gap: 4px; font-size: 13px; font-weight: 600; }
.rdv-envoi .cq-type select { font-weight: 400; }
.rdv-envoi .cq-charge { margin: 0; font-size: 13px; color: var(--muted, inherit); }

/* HH-2616 — les rapprochements sûrs, en tête d'Encaissements : des lignes
   discrètes, pas un panneau. Rien quand il n'y a rien de sûr. */
.enc-coincides { display: flex; flex-direction: column; gap: 6px; margin: 0 0 12px; }
.enc-coincide-l {
  display: flex; align-items: center; gap: 9px; padding: 6px 8px 6px 12px;
  border: 1px solid var(--hairline); border-radius: 10px; background: var(--surface);
  font-size: 12.5px; color: var(--ink-2);
}
.enc-coincide-l > svg { flex: none; color: var(--accent); }
.enc-coincide-l b { color: var(--ink); font-weight: 600; }
.enc-coincide-l .grow { flex: 1; min-width: 0; }

/* ── Calendrier de rendez-vous (HH-2620) ─────────────────────────────────
   Le type d'abord, puis le mois : points bleus = créneaux libres du type,
   gris chaud = jours passés (appel déjà eu, noté ici), barré = fermé. */
.modal-box.rc-box { width: min(760px, 96vw); }
.form-section { margin: 16px 0 8px; padding-top: 12px; border-top: 1px solid var(--hairline);
  font-size: 12px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-2); }
.form-section .muted { text-transform: none; letter-spacing: 0; font-weight: 500; }
.rc { display: grid; gap: 12px; }
.rc-type { display: grid; gap: 4px; font-size: 13px; font-weight: 600; }
.rc-type select { font-weight: 400; }
.rc-corps { display: grid; grid-template-columns: minmax(0, 300px) minmax(0, 1fr); gap: 14px;
  padding: 12px; border: 1px solid var(--hairline); border-radius: var(--radius); background: var(--surface); }
@media (max-width: 640px) { .rc-corps { grid-template-columns: 1fr; } }
.rc-tete { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
.rc-tete b { font-size: 14px; text-transform: capitalize; }
.rc-nav { width: 28px; height: 28px; border-radius: 8px; border: 1px solid var(--hairline);
  background: var(--surface); color: var(--ink); font-size: 16px; line-height: 1; cursor: pointer; }
.rc-nav:hover:not(:disabled) { background: var(--sem-vente-bg); border-color: var(--accent-soft); }
.rc-nav:disabled { opacity: .35; cursor: default; }
.rc-semaine, .rc-grille { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; }
.rc-semaine span { text-align: center; font-size: 11px; font-weight: 600; color: var(--muted); padding: 2px 0; }
.rc-j { position: relative; aspect-ratio: 1; min-height: 32px; border: 0; border-radius: 9px;
  background: transparent; color: var(--ink); font: inherit; font-size: 13px;
  font-variant-numeric: tabular-nums; cursor: pointer; transition: background .12s, color .12s; }
.rc-j i { position: absolute; left: 50%; bottom: 4px; width: 4px; height: 4px; margin-left: -2px;
  border-radius: 50%; background: var(--accent); }
.rc-j.libre { background: var(--sem-vente-bg); color: var(--accent-strong); font-weight: 600; }
.rc-j.libre:hover { background: var(--accent-soft); }
.rc-j.libre-manuel:hover, .rc-j.passe:hover { background: var(--page); }
.rc-j.passe { color: var(--ink-2); }
.rc-j.ferme { color: var(--muted); opacity: .45; cursor: default; }
.rc-j.attente { background: linear-gradient(90deg, var(--page), var(--hairline), var(--page));
  background-size: 200% 100%; animation: rc-lueur 1.2s linear infinite; color: var(--muted); cursor: progress; }
@keyframes rc-lueur { to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) { .rc-j.attente { animation: none; } }
.rc-j.auj { box-shadow: inset 0 0 0 1.5px var(--ink-2); }
.rc-j.choisi, .rc-j.choisi:hover { background: var(--accent); color: #fff; }
.rc-j.choisi i { background: #fff; }
.rc-j:focus-visible, .rc-h:focus-visible, .rc-nav:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.rc-legende { display: flex; gap: 14px; margin-top: 8px; font-size: 11px; color: var(--muted); }
.rc-legende span { display: inline-flex; align-items: center; gap: 5px; }
.rc-pt { width: 8px; height: 8px; border-radius: 3px; display: inline-block; }
.rc-pt.libre { background: var(--sem-vente-bg); box-shadow: inset 0 0 0 1.5px var(--accent); }
.rc-pt.passe { background: var(--page); box-shadow: inset 0 0 0 1.5px var(--muted); }
.rc-heures { display: flex; flex-direction: column; gap: 10px; min-height: 120px;
  border-left: 1px solid var(--hairline); padding-left: 14px; }
@media (max-width: 640px) { .rc-heures { border-left: 0; padding-left: 0; border-top: 1px solid var(--hairline); padding-top: 12px; } }
.rc-vide { margin: auto; font-size: 13px; color: var(--muted); }
.rc-sous { margin: 0; font-size: 13px; font-weight: 600; }
.rc-sous::first-letter { text-transform: uppercase; }
.rc-hs { display: grid; grid-template-columns: repeat(auto-fill, minmax(62px, 1fr)); gap: 6px;
  max-height: 230px; overflow-y: auto; padding-right: 2px; }
.rc-h { padding: 7px 0; border-radius: 8px; border: 1px solid var(--accent-soft); background: var(--surface);
  color: var(--accent-strong); font: inherit; font-size: 13px; font-weight: 600;
  font-variant-numeric: tabular-nums; cursor: pointer; }
.rc-h:hover { background: var(--sem-vente-bg); }
.rc-h.choisi { background: var(--accent); border-color: var(--accent); color: #fff; }
.rc-heure-libre { display: grid; gap: 4px; font-size: 13px; font-weight: 600; max-width: 160px; }
.rc-deja { align-self: flex-start; font-size: 12px; }
.rc-choix { display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 12px; border-radius: 9px; background: var(--sem-vente-bg); color: var(--accent-strong);
  font-size: 13px; font-weight: 600; }
.rc-choix[hidden], .rc .cq[hidden], .rc-avert[hidden] { display: none; }
.rc-avert { margin: 0; display: flex; gap: 8px; }
.rc .cq { display: grid; gap: 10px; }
.rc .cq-question { display: grid; gap: 4px; }
.rc .cq-titre { font-size: 13px; font-weight: 600; }
.rc .cq-choix { font-weight: 400; font-size: 13px; margin: 0; }
.rc .cq textarea, .rc .cq input[type=text], .rc .cq input[type=tel] { width: 100%; }
.rc .cq-erreur { margin: 0; font-size: 13px; color: var(--sem-defaut-t); }

/* Pas à pas (HH-2620) : chaque étape du modal apparaît quand la précédente est
   faite, en glissant doucement plutôt qu'en surgissant. */
/* ⚠ Jamais sur un bloc qui contient un `select[data-search]`. Sa liste est en
   `position: fixed` pour sortir du modal ; sous une étape animée — `transform`
   ou même simple opacité, dans Chrome — elle restait prisonnière du modal et
   s'y faisait couper (la liste des closers). Mesuré, pas supposé. */
[data-apparait]:not([hidden]) { animation: apparait .2s ease-out; }
@keyframes apparait { from { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { [data-apparait]:not([hidden]) { animation: none; } }
.rc[hidden], .n-suite[hidden], .rc-corps[hidden], .rc-heures[hidden], .rc [data-rc-erreur][hidden] { display: none; }
.rc-corps { grid-template-columns: minmax(0, 300px); }
.rc-corps.avec-heures { grid-template-columns: minmax(0, 300px) minmax(0, 1fr); }
@media (max-width: 640px) { .rc-corps.avec-heures { grid-template-columns: 1fr; } }
.rc .form-section { margin-top: 4px; }

/* Dépôt seul (Al) : un titre à la place des filtres de tout le compte. */
.enc-mes-depots { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; margin: 4px 0 10px; }

/* Encaissements sur téléphone (Al dépose depuis le sien) : le bouton passait
   PAR-DESSUS le titre, « Encaissemen… » à moitié caché. Le titre et la croix
   restent en haut, le bouton descend sur sa propre ligne, pleine largeur. */
@media (max-width: 760px) {
  .enc-head { flex-wrap: wrap; row-gap: 10px; }
  .enc-head > .grow { flex: 1 1 calc(100% - 48px); min-width: 0; order: 0; }
  .enc-head > .modal-close { order: 1; }
  .enc-head > [data-modal="saisie-modal"] { order: 2; flex: 1 1 100%; margin-right: 0 !important;
                                            justify-content: center; text-align: center; }
  .enc-head > .enc-count { order: 3; }
}

/* Tutoriel — « Le parcours d'une vente » (HH-2629). Les statuts portent la
   couleur de leur badge ; le geste à faire est mis en avant. */
.tour-body p { margin: 0 0 9px; }
.tour-body p:last-child { margin-bottom: 0; }
.tour-etats { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 4px 0 10px; }
.tour-etats .fleche { color: var(--muted); }
.tour-body .etat {
  display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: 12px;
  font-weight: 700; white-space: nowrap; border: 1px solid transparent;
}
.tour-body .e-valider { background: var(--sem-defaut-bg); color: var(--sem-defaut-t); border-color: #f2bcbc; }
.tour-body .e-checker { background: var(--sem-attente-bg); color: var(--sem-attente-t); border-color: #f3dda6; }
.tour-body .e-traiter { background: var(--accent-soft); color: var(--accent-strong); border-color: #c4dcf6; }
.tour-body .e-complet { background: var(--good-tint); color: var(--good-text); border-color: #cfe8db; }
.tour-geste { padding: 8px 11px; border-radius: 9px; background: var(--accent-soft); color: var(--accent-strong); }
.tour-geste b { color: inherit; }
.tour-note { font-size: 12.5px; color: var(--muted); }

/* Cases de la file B-Sport (HH-2649) : un geste fait à la main dans B-Sport,
   coché ici. Une case, pas un bouton — un bouton « Créditée » se lisait comme
   un état déjà acquis. */
.bs-case { display: inline-flex; align-items: center; gap: 7px; padding: 4px 9px 4px 6px; border-radius: 8px;
  border: 1px solid var(--hairline); background: var(--surface); color: var(--ink-2); font: inherit; font-size: 12px;
  cursor: pointer; white-space: nowrap; }
.bs-case i { width: 14px; height: 14px; border-radius: 4px; border: 1.5px solid var(--muted); background: var(--surface); flex: none; }
.bs-case:hover { border-color: var(--accent); color: var(--accent-strong); }
.bs-case:hover i { border-color: var(--accent); }
.bs-case-2 { color: var(--accent-strong); border-color: var(--accent-soft); }
.bs-case-2 i { border-color: var(--accent); }

/* Le bilan du geste (HH-2642) : ce qui est en place, ce qui manque, et un
   bouton qui ne fait QUE ce qui manque. Au-dessus du cahier « Fait ailleurs »,
   pour qu'on ne cherche plus le manque dans l'absence d'une mention. */
.ge-bilan { margin-top: 18px; padding: 11px 14px; border-radius: 10px; font-size: 13px; line-height: 1.5; }
.ge-bilan.manque { border: 1px solid #ecd3a1; background: var(--sem-attente-bg); }
.ge-bilan.ok { display: flex; align-items: center; gap: 8px; border: 1px solid var(--good-tint-border);
  background: var(--good-tint); color: var(--good-text); }
.ge-bilan-t { display: flex; align-items: center; gap: 7px; color: var(--sem-attente-t); }
.ge-bilan-l { margin: 5px 0 10px 20px; padding: 0; }
.ge-bilan-l li { margin: 1px 0; }
.ge-bilan form { display: flex; justify-content: flex-end; }
.ge-main input[type=checkbox]:disabled + * { opacity: .75; }

/* « Où en est-elle ? » (HH-2642) : vérifier, lire le compte rendu, faire ce
   qui manque — sans quitter le modal. */
.ge-etat { margin-top: 18px; padding: 12px 14px; border: 1px solid var(--hairline); border-radius: 12px;
  background: var(--surface); display: grid; gap: 10px; }
.ge-etat-t { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.ge-etat-t b { font-size: 13px; }
.ge-etat-vide { margin: 0; font-size: 13px; color: var(--ink-2); }
.ge-etat .ge-bilan { margin-top: 0; }
.ge-etat-flash { animation: ge-flash 1.2s ease-out; }
@keyframes ge-flash { from { box-shadow: 0 0 0 3px var(--accent-soft); } }
@media (prefers-reduced-motion: reduce) { .ge-etat-flash { animation: none; } }
.ge-rapport { display: grid; gap: 6px; padding: 10px 12px; border-radius: 10px; background: var(--page); font-size: 13px; }
.ge-rapport-q { font-size: 11px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase; color: var(--muted); }
.ge-rapport-l { display: flex; gap: 8px; align-items: flex-start; }
.ge-rapport-ico { width: 16px; flex: none; font-weight: 700; text-align: center; }
.ge-rapport-l.ok .ge-rapport-ico { color: var(--good-text); }
.ge-rapport-l.ko .ge-rapport-ico { color: var(--sem-attente-t); }
.ge-rapport-l.souci { color: var(--sem-defaut-t); }
.ge-puces { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 3px; }
.ge-puce { padding: 2px 8px; border-radius: 999px; font-size: 12px; }
.ge-puce.ok { background: var(--good-tint); color: var(--good-text); }
.ge-puce.ko { background: var(--sem-attente-bg); color: var(--sem-attente-t); }
.ge-resultat { padding: 8px 12px; border-radius: 9px; font-size: 13px; background: var(--good-tint); color: var(--good-text); }
.ge-resultat.error { background: var(--sem-defaut-bg); color: var(--sem-defaut-t); }
.ge-resultat.warning { background: var(--sem-attente-bg); color: var(--sem-attente-t); }
.ge-afaire { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 6px; counter-reset: etape; }
.ge-afaire-l { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 9px;
  background: var(--surface); border: 1px solid #ecd3a1; counter-increment: etape; }
.ge-afaire-l::before { content: counter(etape); flex: none; width: 20px; height: 20px; border-radius: 50%;
  background: var(--sem-attente-bg); color: var(--sem-attente-t); font-size: 12px; font-weight: 700;
  display: grid; place-items: center; }
.ge-afaire-txt { flex: 1; display: grid; gap: 1px; font-size: 13px; }
.ge-afaire-txt span { font-size: 12px; color: var(--ink-2); }
.ge-bilan .ge-tout { margin-top: 10px; display: flex; justify-content: flex-end; }
/* Listes filtrables en direct (HH-2642) */
.live-onglets { display: contents; }
[data-live-liste].live-charge [data-live-corps] { opacity: .55; transition: opacity .15s; }
/* Modal épuré (HH-2642) */
.ge-place { display: grid; gap: 5px; }
.ge-place-t { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; color: var(--good-text); }
.ge-verif-cours { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--muted); }
.ge-cours-l.fait { opacity: .7; }
.ge-cours-fait { flex: none; font-size: 10px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--good-text); }
/* Étapes de l'ouverture : une pastille d'une ligne, « ✓ Compte boutique ».
   Deux règles anciennes se superposaient et doublaient la coche (HH-2642). */
.ge-etapes { display: flex; flex-wrap: wrap; gap: 5px; margin: 0 0 6px; }
.ge-etapes > li { flex-direction: row; align-items: center; padding: 3px 10px; border-radius: 999px; font-size: 12px; }
.ge-etapes > li .ge-etape-p { display: none; }
/* Le modal d'accès pendant sa vérification (HH-2642) : l'en-tête et un
   spinner, rien d'autre — pas de boutons qui vont disparaître. */
.ge-box.ge-verifie > *:not(.modal-head):not(.ge-attente) { display: none !important; }
.ge-attente { display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px; min-height: 260px; color: var(--muted); font-size: 13px; }
.ge-attente .spinner { width: 28px; height: 28px; }

/* ── HH-2647 : onglets Compte bancaire / Stripe dans Encaissements ───────── */
.enc-onglets { display: flex; gap: 4px; border-bottom: 1px solid var(--border);
               margin: 4px 0 12px; }
.enc-onglet { background: none; border: 0; border-bottom: 2px solid transparent;
              padding: 8px 14px; font: inherit; font-size: 13px; color: var(--muted);
              cursor: pointer; margin-bottom: -1px; display: inline-flex;
              align-items: center; gap: 6px; }
.enc-onglet:hover { color: var(--ink); }
.enc-onglet.actif { color: var(--sem-facture-t); border-bottom-color: var(--sem-facture);
                    font-weight: 600; }
.enc-onglet:focus-visible { outline: 2px solid var(--sem-facture); outline-offset: -2px; }
.st-corps .enc-totaux { align-items: flex-end; }
.st-synchro { display: flex; align-items: center; gap: 10px; font-size: 12px;
              color: var(--muted); }
.st-propose { display: inline-flex; align-items: center; gap: 6px; margin: 0 6px 0 0; vertical-align: middle; }
/* Rattachée : pastille pleine, verte, cochée. Rien d'autre n'a cette forme. */
.st-lie {
  display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; font-weight: 700;
  padding: 3px 9px; border-radius: 99px; text-decoration: none; font-variant-numeric: tabular-nums;
  background: var(--sem-facture-bg); color: var(--sem-facture-t); border: 1px solid var(--sem-facture);
}
.st-lie span { font-weight: 500; }
.st-lie:hover { text-decoration: underline; }
/* Proposée : même pastille, en POINTILLÉ et sans couleur d'état — une
   suggestion, pas un fait. Le mot « Suggérée » le dit en plus de la forme. */
.st-suggere {
  display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600;
  padding: 3px 9px; border-radius: 99px; text-decoration: none; font-variant-numeric: tabular-nums;
  color: var(--ink); border: 1.5px dashed var(--sem-attente); background: var(--surface);
}
.st-suggere span {
  font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em;
  color: var(--sem-attente-t);
}
.st-suggere:hover { background: var(--sem-attente-bg); }
/* Refusé : la vente qu'il visait, contour neutre (ni rattachée ni
   suggérée), et l'état de l'échéance à côté — rouge si toujours due. */
.st-echec-vente {
  display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; font-weight: 600;
  padding: 3px 9px; border-radius: 99px; text-decoration: none; font-variant-numeric: tabular-nums;
  color: var(--ink); border: 1px solid var(--hairline); background: var(--surface);
}
.st-echec-vente span { font-weight: 500; color: var(--muted); }
.st-echec-vente:hover { text-decoration: underline; }
.st-echec-etat { font-size: 11.5px; font-weight: 700; margin-left: 6px; cursor: help; }
.st-echec-etat.du { color: var(--sem-defaut-t); }
.st-echec-etat.regle { color: var(--sem-facture-t); font-weight: 500; }
/* « Autre… » : discret tant qu'on ne s'en sert pas, s'ouvre au clic. */
.enc-associer.st-autre input.enc-associer-champ { width: 52px; transition: width .15s; }
.enc-associer.st-autre:focus-within input.enc-associer-champ { width: 170px; }
/* Le statut porte le motif : un pointillé dit « survolez-moi ». */
.badge.st-motif { cursor: help; text-decoration: underline dotted; text-underline-offset: 3px; }
@media (prefers-reduced-motion: reduce) { .enc-associer.st-autre input.enc-associer-champ { transition: none; } }
.st-pied { display: flex; align-items: center; justify-content: space-between;
           gap: 12px; flex-wrap: wrap; margin-top: 10px; }
.st-historique { display: inline-flex; align-items: center; gap: 8px; margin-left: auto; }
.st-historique input { width: 140px; }
.chip.st-o-systemeio { background: var(--sem-vente-bg); color: var(--sem-vente-t); border-color: #cbdff8; }
.chip.st-o-woo       { background: var(--sem-care-bg);  color: var(--sem-care-t);  border-color: #ddd3f5; }
.chip.st-o-direct    { background: var(--sem-attente-bg); color: var(--sem-attente-t); border-color: #f1ddb8; }
.chip.st-o-autre     { background: var(--sem-ops-bg);   color: var(--sem-ops-t);   border-color: #d9dee4; }

/* ── HH-2638 : plan de paiement personnalisé ─────────────────────────────── */
.pp { display: flex; flex-direction: column; gap: 10px; background: var(--page);
      border-radius: 10px; padding: 12px 14px; margin: 8px 0 4px; }
.pp-bloc, .pp-figees { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.pp-t { width: 64px; flex: 0 0 64px; font-size: 11px; font-weight: 600; letter-spacing: .04em;
        text-transform: uppercase; color: var(--ink-2); }
.pp-champs { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; flex: 1; min-width: 0; }
.pp-champs input[type=number] { width: 104px; }
.pp-champs input.pp-n { width: 64px; }
.pp-champs input[type=date] { width: 148px; }
.pp-champs select { width: auto; min-width: 140px; flex: 0 0 auto; }
.pp-mot { font-size: 12.5px; color: var(--muted); }
.pp-case { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--ink-2); }
.pp-figees-l { display: flex; gap: 6px; flex-wrap: wrap; }
.pp-fige { font-size: 12px; padding: 3px 8px; border-radius: 999px; background: var(--sem-facture-bg);
           color: var(--sem-facture-t); font-variant-numeric: tabular-nums; }
.pp-resume { border-top: 1px solid var(--hairline); padding-top: 10px; display: flex;
             flex-direction: column; gap: 8px; }
.pp-total { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; font-size: 13px; }
.pp-total > span:first-child { color: var(--muted); font-size: 12px; }
.pp-total b { font-size: 17px; font-variant-numeric: tabular-nums; }
.pp-compare { font-size: 12.5px; }
.pp-compare.ok { color: var(--sem-facture-t); }
.pp-compare.remise { color: var(--sem-attente-t); }
.pp-compare.plus { color: var(--sem-vente-t); }
.pp-cal { display: flex; gap: 6px; flex-wrap: wrap; }
.pp-puce { font-size: 12px; padding: 3px 9px; border-radius: 999px; background: var(--surface);
           border: 1px solid var(--hairline); font-variant-numeric: tabular-nums; color: var(--ink-2); }
.pp-puce.acompte { background: var(--sem-facture-bg); border-color: transparent; color: var(--sem-facture-t); }
.pp-puce.trou { border-style: dashed; color: var(--muted); }
.modal-box.pp-box { width: min(760px, 96vw); }
@media (max-width: 640px) { .pp-t { width: 100%; flex-basis: 100%; } }

/* HH-2638 — la façon de payer « Personnalisé », à côté de celles de l'offre. */
.sale-plan.sale-plan-perso { border-style: dashed; }
.sale-plan.sale-plan-perso:has(input:checked) { border-style: solid; }

/* ── Filtres du registre des ventes : une ligne, compacte, en direct ─────── */
.vf { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 12px; }
.vf-seg { display: inline-flex; align-items: center; gap: 2px; padding: 3px; border-radius: 10px;
          background: var(--page); border: 1px solid var(--hairline); flex-wrap: wrap; }
.vf-pill { display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 10px;
           border-radius: 7px; font-size: 12.5px; font-weight: 500; color: var(--ink-2);
           text-decoration: none; white-space: nowrap; }
.vf-pill:hover { color: var(--ink); background: var(--surface); text-decoration: none; }
.vf-pill.on { background: var(--surface); color: var(--ink); font-weight: 600;
              box-shadow: 0 1px 2px rgba(21, 26, 43, .08), 0 0 0 1px var(--hairline); }
.vf-pill .fdot { margin: 0; }
.vf-form { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; flex: 1; min-width: 0; }
.vf-search { position: relative; display: inline-flex; align-items: center; flex: 1 1 180px;
             max-width: 240px; min-width: 150px; }
.vf-search svg { position: absolute; left: 9px; color: var(--muted); pointer-events: none; }
.vf-search input { width: 100%; height: 32px; padding: 0 28px 0 30px; font-size: 12.5px; }
.vf-search .f-etat { position: absolute; right: 9px; }
.vf-sel { width: auto; height: 32px; padding: 0 26px 0 10px; font-size: 12.5px; max-width: 150px;
          color: var(--ink-2); }
.vf-sel.actif { color: var(--sem-vente-t); border-color: var(--sem-vente); background-color: var(--sem-vente-bg); }
.vf-per { position: relative; }
.vf-per > summary { list-style: none; display: inline-flex; align-items: center; gap: 6px; height: 32px;
                    padding: 0 26px 0 10px; border: 1px solid var(--hairline); border-radius: 8px;
                    background: var(--surface); font-size: 12.5px; color: var(--ink-2); cursor: pointer;
                    white-space: nowrap; position: relative; font-variant-numeric: tabular-nums; }
.vf-per > summary::-webkit-details-marker { display: none; }
.vf-per > summary::after { content: ""; position: absolute; right: 10px; top: 50%; width: 6px; height: 6px;
                           border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
                           transform: translateY(-70%) rotate(45deg); opacity: .6; }
.vf-per.actif > summary { color: var(--sem-vente-t); border-color: var(--sem-vente); background: var(--sem-vente-bg); }
.vf-per-pop { position: absolute; z-index: 40; top: calc(100% + 6px); right: 0; width: 300px;
              background: var(--surface); border: 1px solid var(--hairline); border-radius: 12px;
              box-shadow: 0 16px 40px rgba(21, 26, 43, .16); padding: 12px; display: flex;
              flex-direction: column; gap: 10px; }
.vf-per-dates { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.vf-per-dates label { display: flex; flex-direction: column; gap: 4px; font-size: 11.5px; color: var(--muted); }
.vf-per-dates input { width: 100%; height: 32px; font-size: 12.5px; }
.vf-per-raccourcis { display: flex; flex-wrap: wrap; gap: 6px; }
.vf-mini { border: 1px solid var(--hairline); background: var(--page); border-radius: 999px; padding: 4px 10px;
           font: inherit; font-size: 12px; color: var(--ink-2); cursor: pointer; }
.vf-mini:hover { color: var(--ink); border-color: var(--ink-2); }
.vf-effacer { font-size: 12.5px; color: var(--muted); padding: 0 4px; text-decoration: underline;
              text-underline-offset: 2px; }
.vf-effacer:hover { color: var(--ink); }

/* HH-2638 — un échéancier négocié se dit dans l'infobulle du registre. */
.ech-tip-special { margin: -2px 0 8px; padding: 5px 8px; border-radius: 7px; font-size: 11.5px;
                   background: var(--sem-care-bg); color: var(--sem-care-t); font-weight: 500; }

/* ---------- Historique d'une vente : genres, pastilles, pages ----------
   Les couleurs sont celles du système sémantique (`--sem-*`) : vert pour
   l'argent et la facture, bleu pour la vente, turquoise pour les accès,
   ambre pour ce qui a été corrigé, rouge pour ce qui demande qu'on regarde. */
.historique li { --h: var(--sem-ops); --h-t: var(--sem-ops-t); --h-bg: var(--sem-ops-bg); }
.historique li.h-vente, .h-filtre.h-vente { --h: var(--sem-vente); --h-t: var(--sem-vente-t); --h-bg: var(--sem-vente-bg); }
.historique li.h-paiement, .h-filtre.h-paiement,
.historique li.h-facture, .h-filtre.h-facture { --h: var(--sem-facture); --h-t: var(--sem-facture-t); --h-bg: var(--sem-facture-bg); }
.historique li.h-acces, .h-filtre.h-acces { --h: var(--sem-acces); --h-t: var(--sem-acces-t); --h-bg: var(--sem-acces-bg); }
.historique li.h-correction, .h-filtre.h-correction { --h: var(--sem-attente); --h-t: var(--sem-attente-t); --h-bg: var(--sem-attente-bg); }
.historique li.h-alerte, .h-filtre.h-alerte { --h: var(--sem-defaut); --h-t: var(--sem-defaut-t); --h-bg: var(--sem-defaut-bg); }
.historique li.h-note, .h-filtre.h-note { --h: var(--sem-care); --h-t: var(--sem-care-t); --h-bg: var(--sem-care-bg); }

.historique .t-ico { background: var(--h-bg); border-color: transparent; color: var(--h-t); }
.historique li.h-alerte { background: var(--sem-defaut-bg); border-radius: 8px; padding-left: 6px; padding-right: 6px; }
.historique .h-corps { min-width: 0; flex: 1; }
.historique .t-date { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: 2px; }
.historique .h-genre {
  font-size: 10.5px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
  color: var(--h-t); background: var(--h-bg); border-radius: 99px; padding: 1px 7px;
}
.historique .h-auto {
  font-size: 10.5px; font-weight: 600; color: var(--ink-2); border: 1px dashed var(--hairline);
  border-radius: 99px; padding: 0 6px;
}
.historique .h-texte { font-size: 13px; line-height: 1.55; color: var(--ink); overflow-wrap: anywhere; }
.historique .h-montant { font-variant-numeric: tabular-nums; color: var(--sem-facture-t); font-weight: 700; white-space: nowrap; }
.historique .h-cite { font-weight: 600; }
.historique .h-non { color: var(--sem-defaut-t); }
.historique .h-chip {
  display: inline-block; font-size: 11.5px; font-weight: 600; border-radius: 6px;
  padding: 0 6px; white-space: nowrap; font-variant-numeric: tabular-nums;
}
.historique .h-facture { background: var(--sem-facture-bg); color: var(--sem-facture-t); }
.historique a.h-vente { background: var(--sem-vente-bg); color: var(--sem-vente-t); text-decoration: none; }
.historique a.h-vente:hover { text-decoration: underline; }
.historique .h-outil {
  display: inline-block; font-size: 11px; font-weight: 600; border-radius: 99px; padding: 0 6px;
  background: var(--page); border: 1px solid var(--hairline); color: var(--ink-2);
}
.historique .h-ref { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; color: var(--muted); }
.historique .h-ticket { font-size: 11px; color: var(--muted); }
.historique li[hidden] { display: none; }

.h-filtres { display: flex; flex-wrap: wrap; gap: 6px; margin: 2px 0 8px; }
.h-filtre {
  --h: var(--ink-2); --h-t: var(--ink-2); --h-bg: var(--page);
  font: inherit; font-size: 12px; font-weight: 600; cursor: pointer; border-radius: 99px;
  padding: 3px 10px; border: 1px solid var(--hairline); background: var(--surface); color: var(--h-t);
}
.h-filtre span { opacity: .6; font-weight: 500; margin-left: 2px; }
.h-filtre:hover { background: var(--h-bg); }
.h-filtre.on { background: var(--h-bg); border-color: var(--h); }
.h-filtre:focus-visible, .h-page:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.h-pages { display: flex; justify-content: center; gap: 4px; margin-top: 8px; }
.h-pages[hidden] { display: none; }
.h-page {
  font: inherit; font-size: 12px; min-width: 28px; height: 28px; border-radius: 8px; cursor: pointer;
  border: 1px solid var(--hairline); background: var(--surface); color: var(--ink-2);
}
.h-page.on { background: var(--sem-vente-bg); border-color: var(--sem-vente); color: var(--sem-vente-t); font-weight: 700; }
.h-page:disabled { opacity: .4; cursor: default; }
.historique li.h-alerte .h-genre,
.historique li.h-alerte .t-ico { background: var(--surface); border: 1px solid var(--sem-defaut); }

/* ---------- Vente suggérée pour un paiement Stripe (modal) ---------- */
.st-suggere { cursor: pointer; font-family: inherit; }
.sta-box { width: min(860px, calc(100vw - 32px)); }
.sta-grille { display: grid; grid-template-columns: 1fr 1.5fr; gap: 14px; }
@media (max-width: 720px) { .sta-grille { grid-template-columns: 1fr; } }
.sta-bloc { border: 1px solid var(--hairline); border-radius: 12px; padding: 14px 16px; background: var(--surface); }
.sta-bloc h3 {
  display: flex; align-items: center; gap: 8px; margin: 0 0 8px; font-size: 11px;
  letter-spacing: .05em; text-transform: uppercase; color: var(--muted);
}
.sta-vente { border: 1.5px dashed var(--sem-attente); }
.sta-suggere { color: var(--sem-attente-t); }
.sta-num { font-size: 13px; letter-spacing: 0; text-transform: none; color: var(--ink); font-variant-numeric: tabular-nums; }
.sta-montant { font-size: 26px; font-weight: 700; color: var(--sem-facture-t); font-variant-numeric: tabular-nums; margin-bottom: 8px; }
.sta-offre { font-size: 15px; font-weight: 700; margin-bottom: 8px; }
.sta-dl { display: grid; grid-template-columns: 88px 1fr; gap: 6px 10px; margin: 0; font-size: 13px; }
.sta-dl dt { color: var(--muted); font-size: 12px; }
.sta-dl dd { margin: 0; }
.sta-ech { width: 100%; border-collapse: collapse; margin-top: 12px; font-size: 12.5px; font-variant-numeric: tabular-nums; }
.sta-ech th { text-align: left; font-size: 11px; color: var(--muted); font-weight: 600; padding: 4px 6px; border-bottom: 1px solid var(--hairline); }
.sta-ech td { padding: 5px 6px; border-bottom: 1px solid var(--hairline); }
.sta-ech .num { text-align: right; }
.sta-ech tr.sta-egal td { background: var(--sem-attente-bg); }
.sta-motif {
  display: flex; gap: 8px; align-items: flex-start; margin-top: 12px; padding: 9px 12px;
  border-radius: 10px; background: var(--page); font-size: 12.5px; color: var(--ink-2);
}
.sta-motif svg { flex: none; margin-top: 2px; }
.sta-pied { display: flex; align-items: center; gap: 8px; margin-top: 14px; }
.sta-pied .grow { flex: 1; }
.sta-pied form { margin: 0; }
.sta-alerte {
  display: flex; gap: 8px; align-items: flex-start; margin-top: 10px; padding: 8px 10px; border-radius: 9px;
  background: var(--sem-attente-bg); color: var(--sem-attente-t); font-size: 12.5px;
}
.sta-alerte svg { flex: none; margin-top: 2px; }

/* ---------- Ajouter plusieurs éléments d'un coup (liste à cocher) ---------- */
.lo-ajout-btn {
  font: inherit; font-size: 12.5px; cursor: pointer; padding: 3px 10px; border-radius: 99px;
  border: 1px dashed var(--hairline); background: var(--surface); color: var(--ink-2);
}
.lo-ajout-btn:hover { border-color: var(--accent); color: var(--accent-strong); }
.lo-ajout-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.multi-panneau {
  position: fixed; z-index: 200; width: 420px; max-width: calc(100vw - 16px);
  display: flex; flex-direction: column; background: var(--surface);
  border: 1px solid var(--hairline); border-radius: 12px; box-shadow: var(--shadow-lift);
}
.multi-titre { padding: 10px 12px 6px; font-size: 12.5px; font-weight: 700; color: var(--ink); }
.multi-cherche { margin: 0 12px 8px; }
.multi-liste { max-height: 300px; overflow-y: auto; border-top: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline); }
.multi-ligne {
  display: flex; align-items: center; gap: 10px; padding: 7px 12px; cursor: pointer; font-size: 13px;
}
.multi-ligne:hover { background: var(--page); }
.multi-ligne:has(input:checked) { background: var(--sem-vente-bg); }
.multi-ligne[hidden] { display: none; }
.multi-ligne input { flex: none; }
.multi-nom { flex: 1; min-width: 0; }
.multi-vide { padding: 14px 12px; color: var(--muted); font-size: 12.5px; }
.multi-pied { display: flex; align-items: center; gap: 8px; padding: 8px 12px; }
.multi-compte { flex: 1; font-size: 12px; color: var(--muted); }
.multi-panneau input.multi-cherche {
  font: inherit; font-size: 13px; padding: 6px 10px; border: 1px solid var(--hairline);
  border-radius: 8px; background: var(--surface); color: var(--ink);
}
.multi-panneau input.multi-cherche:focus { outline: 2px solid var(--accent-soft); border-color: var(--accent); }

/* Le récapitulatif avant de relier : une page par ligne, sa façon de payer,
   son nom chez Systeme.io, et l'offre qu'elle recevra. */
.sio-recap { list-style: none; margin: 4px 0 10px; padding: 0; text-align: left;
             max-height: 320px; overflow-y: auto; }
.sio-recap li { display: grid; grid-template-columns: 110px 1fr; gap: 1px 10px;
                padding: 7px 2px; border-top: 1px solid var(--hairline); font-size: 13px; }
.sio-recap li:first-child { border-top: none; }
.sio-recap li b { grid-row: span 2; font-variant-numeric: tabular-nums; color: var(--ink); }
.sio-recap li span { color: var(--muted); font-size: 12px; }
.sio-recap .sio-recap-vers { color: var(--sem-vente-t); font-weight: 600; font-size: 12.5px; }
.sio-recap .sio-recap-ecart { grid-column: 2; color: var(--sem-attente-t); }
.sio-recap-avant { text-align: left; font-size: 12.5px; color: var(--sem-defaut-t); margin: 0 0 6px; }
.sio-recap-note { text-align: left; font-size: 12px; color: var(--muted); margin: 6px 0 0; }

/* « + fournisseur » → Systeme.io : les pages de l'offre, par tunnel. Une
   pastille par façon de payer ; verte ✓ = reliée, cochée = à relier. */
.frs-tunnel { padding: 10px 0; border-top: 1px solid var(--hairline); }
.frs-tunnel:first-of-type { border-top: none; }
.frs-t-nom { display: block; font-size: 13px; font-weight: 620; margin-bottom: 7px; }
.frs-pages { display: flex; flex-wrap: wrap; gap: 6px; }
.frs-page { position: relative; display: inline-flex; align-items: center; gap: 6px;
            padding: 5px 10px; border-radius: 8px; font-size: 12.5px; cursor: pointer;
            font-variant-numeric: tabular-nums; border: 1.5px solid var(--hairline);
            background: var(--surface); }
.frs-page input { margin: 0; }
.frs-page b { font-weight: 700; }
.frs-page i { font-style: normal; font-weight: 700; }
.frs-page:has(input:checked) { border-color: var(--sem-vente); color: var(--sem-vente-t); }
.frs-page.ecart i { color: var(--sem-attente-t); }
.frs-page.reliee { cursor: default; border-color: color-mix(in srgb, var(--sem-facture) 55%, transparent);
                   background: var(--sem-facture-bg); color: var(--sem-facture-t); }
.frs-x { display: none; position: absolute; top: -7px; right: -7px; width: 17px; height: 17px;
         border-radius: 999px; border: 1px solid var(--hairline); background: var(--surface);
         color: var(--muted); font-size: 9px; line-height: 1; cursor: pointer; padding: 0; }
.frs-page:hover .frs-x, .frs-x:focus-visible { display: block; }
.frs-x:hover { color: var(--sem-defaut-t); border-color: var(--sem-defaut); }
.frs-autres { margin-top: 12px; border-top: 1px solid var(--hairline); padding-top: 10px; }
.frs-autres summary { cursor: pointer; font-size: 12.5px; color: var(--muted); }
.frs-autres .fr-chercher { margin: 8px 0; }
.frs-a-tunnel { margin-top: 8px; display: flex; flex-direction: column; gap: 2px; }
.frs-a-nom { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
             color: var(--muted); }
.frs-a-page { display: flex; align-items: center; gap: 8px; font-size: 12.5px; padding: 3px 0; cursor: pointer; }
.frs-completer { font-size: 12px; color: var(--muted); }
.sio-recap li { display: block; }
.frs-page.reliee.doute { border-color: var(--sem-attente); background: var(--sem-attente-bg);
                         color: var(--sem-attente-t); }

/* ── Cartes B-Sport : le référentiel (HH-2740) ─────────────────────────────
   Une ligne = un formulaire, en grille pour que les colonnes tombent juste
   sans <table> (un <form> ne peut pas couvrir une ligne de tableau). */
.cartes-box { width: min(920px, calc(100vw - 32px)); }
.cartes-grille {
  display: grid; grid-template-columns: 1.1fr 1.7fr 1.2fr 52px 52px 128px;
  gap: 8px; align-items: center; padding: 6px 0; margin: 0;
  border-bottom: 1px solid var(--hairline);
}
.cartes-grille input[type=text] { width: 100%; min-width: 0; }
.cartes-tete { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
               color: var(--muted); padding-top: 0; }
.cartes-tete span:nth-child(4), .cartes-tete span:nth-child(5) { text-align: center; }
.cartes-active { display: flex; justify-content: center; cursor: help; }
.cartes-usage { text-align: center; font-variant-numeric: tabular-nums; font-weight: 600; cursor: help; }
.cartes-gestes { display: flex; gap: 6px; justify-content: flex-end; align-items: center; }
.cartes-grille.retiree input[type=text] { color: var(--muted); }
.cartes-nouvelle { border-bottom: 0; padding-top: 12px; }
@media (max-width: 720px) {
  .cartes-grille { grid-template-columns: 1fr 1fr; }
  .cartes-tete { display: none; }
  .cartes-gestes { grid-column: 1 / -1; }
}

/* Échéancier modifiable dans la ligne (Q88) : un champ qui se lit comme du
   texte, et qui se révèle au survol et au focus. `ech-inline` et pas
   `ech-edit` : ce nom-là est déjà la GRILLE de l'échéancier du modal de
   facture, et la grille s'appliquait aux champs (la date n'affichait que « 1 »). */
input.ech-inline {
  border: 1px solid transparent; background: transparent; font: inherit; color: inherit;
  padding: 3px 6px; border-radius: 6px; font-variant-numeric: tabular-nums;
}
input.ech-inline[type=number] { width: 74px; text-align: right; font-weight: 700; }
input.ech-inline[type=date] { width: 11.5em; min-width: 150px; }
input.ech-inline:hover { border-color: var(--hairline); background: var(--surface); }
input.ech-inline:focus { border-color: var(--sem-vente); background: #fff; outline: none; }
.ech-inline-wrap { display: inline-flex; align-items: center; gap: 2px; }
.ech-inline-wrap i { font-style: normal; font-weight: 700; }
tr.ech-ok > td { animation: ech-flash-ok 1.2s ease-out; }
tr.ech-ko > td { animation: ech-flash-ko 1.2s ease-out; }
@keyframes ech-flash-ok { from { background: var(--sem-facture-bg); } to { background: transparent; } }
@keyframes ech-flash-ko { from { background: var(--sem-defaut-bg); } to { background: transparent; } }
@media (prefers-reduced-motion: reduce) { tr.ech-ok > td, tr.ech-ko > td { animation: none; } }

/* HH-2762 — le produit d'une offre, dans la liste du catalogue : discret, sur la même ligne. */
.pastille.gamme { background: var(--page); color: var(--muted); border: 1px solid var(--border); font-weight: 500; }

/* ── « Où cette offre se vend » : en-tête sobre et pages Systeme.io en lignes ── */
.fr-titre-offre .fr-prix-ligne { font-weight: 500; color: var(--muted); font-size: 13.5px; margin-left: 6px; }
.fr-ou { display: block; margin-top: 3px; font-size: 12.5px; color: var(--muted); }
.fr-ou a { font-weight: 600; }
.frs-t-nom { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 6px; }
.frs-lignes { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.frs-ligne { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 7px 10px;
  border: 1px solid var(--hairline); border-radius: 8px; font-size: 13px; }
.frs-ligne.reliee { background: var(--sem-facture-bg); border-color: color-mix(in srgb, var(--sem-facture) 35%, transparent); }
.frs-ligne.doute { background: var(--sem-attente-bg); border-color: var(--sem-attente); }
.frs-etat { font-size: 11px; font-weight: 700; color: var(--sem-facture-t); min-width: 64px; }
.frs-ligne.doute .frs-etat { color: var(--sem-attente-t); }
.frs-choix { display: flex; align-items: center; gap: 10px; flex: 1; cursor: pointer; }
.frs-choix input { margin: 0; }
.frs-nom { font-weight: 600; }
.frs-paie { color: var(--muted); font-size: 12px; }
.frs-note { flex-basis: 100%; font-size: 12px; color: var(--sem-attente-t); padding-left: 74px; }
.frs-delier { margin-left: auto; border: 0; background: none; padding: 2px 4px; font: inherit;
  font-size: 12px; color: var(--muted); cursor: pointer; }
.frs-delier:hover { color: var(--sem-defaut-t); text-decoration: underline; }
[data-fr-sio]:not(:has(input[name=external_id]:checked)) .frs-pied { display: none; }

/* « changer » l'offre d'une vente, à côté de son nom (29/09). */
.changer-offre { display: inline-block; font-size: 12px; font-weight: 500; }
.changer-offre > summary { cursor: pointer; color: var(--accent); list-style: none; }
.changer-offre > summary::-webkit-details-marker { display: none; }
.changer-offre[open] > summary { color: var(--muted); }
.changer-offre form { display: flex; gap: 6px; align-items: center; margin-top: 6px; flex-wrap: wrap; }
.changer-offre select { max-width: 420px; font-size: 12.5px; }

/* E2 — la masterclass d'une offre « avec Masterclass », sous l'offre. */
.mc-choix { margin-top: 3px; max-width: 260px; }
.mc-choix select, .mc-choix .combo-input { font-size: 11px; padding: 2px 6px; min-height: 0; }
.mc-choix.mc-vide .combo-input, .mc-choix.mc-vide select { border-color: var(--sem-attente); color: var(--sem-attente-t); }

/* Colonne « Offres » des événements (01/10). */
.evo { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; max-width: 300px; }
.evo-chip { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; padding: 2px 4px 2px 8px;
  border-radius: 12px; background: var(--sem-vente-bg); color: var(--sem-vente-t); }
.evo-chip button { border: 0; background: none; color: inherit; cursor: pointer; font-size: 10px; opacity: .55; padding: 0 2px; }
.evo-chip button:hover { opacity: 1; }
.evo-ajout select, .evo-ajout .combo-input { font-size: 11px; padding: 2px 6px; min-height: 0; width: 120px; }
.evo-filtre { width: 100%; margin-bottom: 6px; }
.evo-liste { max-height: 210px; overflow-y: auto; border: 1px solid var(--hairline); border-radius: 8px; padding: 4px; }
.evo-item { display: flex; align-items: center; gap: 8px; padding: 4px 6px; border-radius: 6px; font-size: 13px; cursor: pointer; }
.evo-item:hover { background: var(--surface); }
.evo-item.sug span { font-weight: 600; }
.evo-titre { display: flex; align-items: center; gap: 6px; font-size: 10px; font-weight: 650; letter-spacing: .05em;
  text-transform: uppercase; color: var(--muted); padding: 8px 6px 2px; }
.evo-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; display: inline-block; }

/* Le menu « + Offre » : le bouton est petit, la liste ne l'est pas. */
.evo-ajout .combo { position: relative; }
.evo-ajout .combo-list { width: 340px !important; max-width: 80vw; overflow-x: hidden; }
.evo-ajout .combo-item { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 12px; padding: 6px 10px; }
.evo-ajout .combo-groupe { font-size: 10px; padding: 6px 10px 2px; }
.rl-echs { display: inline-block; vertical-align: top; }
.rl-echs summary { cursor: pointer; }
.rl-ech { display: flex; align-items: center; gap: 6px; margin-top: 3px; white-space: nowrap; }
.rb-ligne { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 6px 0; border-bottom: 1px solid var(--hairline); }
/* P0 de Céline : « + Offre » à côté du produit, « + Boutique » nommé. */
.prod-plus-offre { margin-left: 6px; padding: 1px 8px; font-size: 11px; }
.fr-ajouter { width: auto !important; padding: 1px 8px !important; font-size: 11px; white-space: nowrap; }
.periode-choix { display: inline-block; margin-right: 8px; }
.periode-choix select { font-size: 13px; padding: 6px 10px; }

/* Registre des événements (05/10) : animateur sur la ligne, boutons plus doux. */
td.col-anim { width: 180px; min-width: 180px; max-width: 180px; }
.anim-choix { display: flex; align-items: center; gap: 4px; width: 172px; position: relative; }
.anim-choix .combo { width: 100%; position: relative; }
.anim-choix select, .anim-choix .combo-input { width: 100%; box-sizing: border-box; font-size: 12px; padding: 3px 8px; border-radius: 8px; }
.anim-choix .combo-list { position: absolute; left: 0; top: 100%; width: 240px; z-index: 30; }
.anim-choix.anim-vide .combo-input, .anim-choix.anim-vide select { color: var(--muted); border-style: dashed; }
td.col-ev-actions { width: 1%; }
div.ev-actions { display: flex; gap: 6px; justify-content: flex-end; align-items: center; }
.ev-bouton { display: inline-flex; align-items: center; gap: 5px; padding: 5px 10px; border-radius: 999px;
  border: 1px solid var(--hairline); background: var(--surface); color: var(--ink-2); font: inherit;
  font-size: 12px; font-weight: 550; cursor: pointer; text-decoration: none; transition: background .15s, border-color .15s; }
.ev-bouton:hover { background: var(--sem-vente-bg); border-color: var(--sem-vente); color: var(--sem-vente-t); }
.ev-bouton-fort { background: var(--sem-vente-bg); border-color: transparent; color: var(--sem-vente-t); }
.ev-bouton-fort:hover { background: var(--sem-vente); color: #fff; }
.ev-lieu { cursor: default; border-bottom: 1px dotted var(--hairline); }
tr.ev-groupe { cursor: pointer; background: var(--page); }
tr.ev-groupe:hover { background: var(--sem-vente-bg); }
tr.ev-groupe .ev-chevron { display: inline-flex; transition: transform .15s; transform: rotate(-90deg); color: var(--muted); }
tr.ev-groupe[aria-expanded="true"] .ev-chevron { transform: none; }
tr.ev-session > td:first-child { padding-left: 26px; }
tr.ev-session { background: var(--surface); }

/* Registre des événements, compact (05/10). */
.ev-table td { vertical-align: middle; }
.evo-pop { position: relative; display: inline-block; }
.evo-pop > summary { list-style: none; cursor: pointer; }
.evo-pop > summary::-webkit-details-marker { display: none; }
.evo-resume { display: inline-flex; align-items: center; gap: 4px; padding: 3px 10px; border-radius: 999px;
  background: var(--sem-vente-bg); color: var(--sem-vente-t); font-size: 12px; font-weight: 550; white-space: nowrap; }
.evo-resume::after { content: "▾"; font-size: 10px; opacity: .7; }
.evo-resume.evo-aucune { background: var(--sem-attente-bg); color: var(--sem-attente-t); }
.evo-pop[open] > .evo-panneau { position: absolute; z-index: 40; top: calc(100% + 4px); left: 0; width: 300px;
  background: var(--surface); border: 1px solid var(--hairline); border-radius: 12px; padding: 8px;
  box-shadow: 0 10px 30px rgba(0,0,0,.12); }
.ev-nb { margin-left: 6px; font-size: 11.5px; color: var(--muted); }
.ev-groupe-nom { font-weight: 650; }
tr.ev-groupe td { padding-top: 10px; padding-bottom: 10px; }

/* Choix de la session d'une vente (05/10) : une pastille, et une liste à taille humaine. */
.mc-choix { max-width: 280px; }
.mc-choix .combo-input { border-radius: 999px; padding: 3px 12px; font-size: 11.5px; font-weight: 550;
  background: var(--sem-vente-bg); color: var(--sem-vente-t); border: 1px solid transparent; }
.mc-choix.mc-vide .combo-input { background: var(--sem-attente-bg); color: var(--sem-attente-t); border-style: solid; }
.mc-choix .combo-list { width: 440px; max-width: 80vw; max-height: 320px; overflow-y: auto; border-radius: 12px;
  box-shadow: 0 12px 32px rgba(0,0,0,.14); padding: 4px; }
.mc-choix .combo-item { border-radius: 8px; padding: 7px 10px; }
.mc-choix .combo-item .ci-titre { font-size: 12.5px; font-weight: 600; white-space: normal; line-height: 1.3; }
.mc-choix .combo-item .ci-sous { font-size: 11px; }
.mc-choix .combo-item .ci-droite { font-size: 11px; font-variant-numeric: tabular-nums; color: var(--muted);
  background: var(--page); border-radius: 999px; padding: 2px 8px; align-self: center; }
.av-onglets { margin: 0 0 10px; }
.rb-form { display: grid; gap: 10px; }
.rb-form select { width: 100%; }

/* Session publiée dans la fiche boutique (adv.boutique_sessions) */
.boutique-ok { display: inline-flex; align-items: center; margin-left: 4px; white-space: nowrap; color: var(--sem-facture); vertical-align: -1px; opacity: .85; }
.boutique-ko { display: inline-flex; align-items: center; gap: 4px; margin-left: 6px; padding: 1px 8px; border-radius: 999px;
  border: 1px solid var(--sem-attente); background: var(--sem-attente-bg); color: var(--sem-attente-t);
  font-size: 11px; font-weight: 600; cursor: pointer; }
.boutique-ko:hover { filter: brightness(.97); }
.ev-chiffres { white-space: nowrap; }
td.col-lieu { min-width: 112px; }

/* Rattachement Systeme.io : une ligne par façon de payer (06/10) */
.frs-plans { display: flex; flex-direction: column; gap: 6px; }
.frs-plan { display: grid; grid-template-columns: 120px 1fr; gap: 12px; align-items: start;
  padding: 8px 10px; border: 1px solid var(--hairline); border-radius: 10px; background: var(--surface); }
.frs-plan.vide { background: var(--sem-attente-bg); border-color: color-mix(in srgb, var(--sem-attente) 45%, transparent); }
.frs-plan-g { display: flex; flex-direction: column; gap: 1px; padding-top: 3px; }
.frs-plan-g b { font-size: 13px; font-weight: 650; }
.frs-plan-g span { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.frs-plan-d { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.frs-bon { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 4px 8px; border-radius: 8px; cursor: pointer; }
.frs-bon:hover { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.frs-bon input { margin: 0; }
.frs-bon .frs-nom { font-size: 12.5px; font-weight: 600; }
.frs-bon .frs-tun { font-size: 10.5px; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.frs-encaisse { margin-left: auto; font-size: 12px; font-weight: 650; font-variant-numeric: tabular-nums; color: var(--ink-2); }
.frs-bon.reliee { cursor: default; background: var(--sem-facture-bg); }
.frs-bon.reliee .frs-etat { display: inline-flex; align-items: center; gap: 4px; min-width: 0; }
.frs-bon.doute { background: var(--sem-attente-bg); }
.frs-bon .frs-delier { margin-left: auto; }
.frs-bon .frs-note { flex-basis: 100%; font-size: 11.5px; color: var(--sem-attente-t); padding-left: 24px; }
.frs-aucun { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600;
  color: var(--sem-attente-t); padding: 4px 8px; }
.frs-orph { margin-top: 10px; padding-top: 8px; border-top: 1px dashed var(--hairline); }
.frs-orph-t { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); margin-bottom: 4px; }
.frs-bon { flex-wrap: nowrap; min-width: 0; }
.frs-bon .frs-nom { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.frs-bon .frs-tun, .frs-bon .frs-etat, .frs-encaisse, .frs-bon .frs-delier { flex-shrink: 0; white-space: nowrap; }
.frs-bon.doute, .frs-bon:has(.frs-note) { flex-wrap: wrap; }
.frs-bon .frs-note { order: 5; padding-left: 0; }
.frs-bon .frs-nom { flex: 0 1 auto; }
.frs-bon .frs-tun { flex: 0 20 auto; min-width: 30px; overflow: hidden; text-overflow: ellipsis; }
/* « + Autre bon… » dans chaque façon de payer */
.frs-autre { position: relative; }
.frs-autre-btn { border: 1px dashed var(--hairline); background: transparent; color: var(--accent-strong);
  font-size: 12px; font-weight: 600; padding: 3px 10px; border-radius: 999px; cursor: pointer; margin: 2px 0 0 8px; }
.frs-autre-btn:hover { border-color: var(--accent); background: var(--sem-vente-bg); }
.frs-autre-pop { margin: 6px 0 2px 8px; padding: 8px; border: 1px solid var(--hairline); border-radius: 10px;
  background: var(--surface); box-shadow: var(--shadow); }
.frs-autre-pop .fr-chercher { margin: 0 0 6px; }
.frs-autre-liste { max-height: 220px; overflow-y: auto; display: flex; flex-direction: column; gap: 1px; }
.frs-autre-choix { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left; border: 0;
  background: transparent; padding: 5px 8px; border-radius: 7px; cursor: pointer; font: inherit; color: var(--ink); }
.frs-autre-choix:hover { background: var(--sem-vente-bg); }
.frs-autre-choix .frs-nom { font-size: 12.5px; flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.frs-autre-choix .frs-tun { font-size: 10.5px; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; white-space: nowrap; }
.frs-autre-choix .frs-n { margin-left: auto; font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
.frs-autre-choix.meme .frs-n { color: var(--sem-vente-t); font-weight: 700; }
.frs-bon.frs-ajoute { background: var(--sem-vente-bg); }
.frs-choisi { color: var(--sem-vente-t); font-weight: 600; font-size: 11px; }
/* Écart d'un bon avec sa façon de payer : sur le bon, pas sur la ligne */
.frs-badge { display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0; white-space: nowrap;
  font-size: 11px; font-weight: 650; padding: 2px 4px 2px 9px; border-radius: 999px; }
.frs-badge.prix { background: var(--sem-attente-bg); color: var(--sem-attente-t); border: 1px solid var(--sem-attente); }
.frs-badge.arrondi { background: var(--page); color: var(--ink-2); border: 1px solid var(--hairline); }
.frs-aligner { border: 0; border-radius: 999px; padding: 2px 8px; font: inherit; font-size: 10.5px; font-weight: 700;
  cursor: pointer; background: var(--surface); color: var(--accent-strong); box-shadow: 0 0 0 1px var(--hairline); }
.frs-aligner:hover { background: var(--sem-vente-bg); }
.frs-encaisse.ecart-prix { color: var(--sem-attente-t); }
.frs-bon .frs-encaisse { margin-left: auto; }
.frs-bon .frs-encaisse + .frs-badge { margin-left: 0; }
.frs-badge.ancien { background: var(--page); color: var(--muted); border: 1px dashed var(--hairline); padding-right: 9px; }

/* ── Rattachement Systeme.io : tableau des façons de payer (06/10, v2) ── */
.modal-box.fr-box:has(.frt) { width: min(1180px, 96vw); max-height: 92vh; }
.frt { --frt-g: 190px; --frt-enc: 150px; --frt-ver: 250px; display: flex; flex-direction: column; gap: 8px; }
.frt-tete { display: grid; grid-template-columns: var(--frt-g) 1fr var(--frt-enc) var(--frt-ver); gap: 14px;
  padding: 0 12px 2px; font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.frt-ligne { display: grid; grid-template-columns: var(--frt-g) 1fr; gap: 14px; padding: 10px 12px;
  border: 1px solid var(--hairline); border-radius: 12px; background: var(--surface); }
.frt-ligne.vide { background: var(--sem-attente-bg); border-color: color-mix(in srgb, var(--sem-attente) 45%, transparent); }
.frt-ligne.orph { border-style: dashed; }
.frt-plan { display: flex; flex-direction: column; gap: 2px; padding-top: 2px; }
.frt-plan b { font-size: 14px; font-weight: 650; }
.frt-prix { font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; }
.frt-detail { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.frt-bons { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.frt-bon { display: grid; grid-template-columns: 1fr var(--frt-enc) var(--frt-ver); gap: 14px; align-items: start;
  padding: 8px 10px; border-radius: 9px; background: var(--page); }
.frt-bon.reliee { background: var(--sem-facture-bg); }
.frt-bon.doute { background: var(--sem-attente-bg); }
.frt-bon.ancien { opacity: .85; }
.frt-bon.frs-ajoute { background: var(--sem-vente-bg); }
.frt-c-bon { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.frt-etat { display: inline-flex; align-items: center; gap: 5px; align-self: flex-start; font-size: 11px; font-weight: 700;
  padding: 1px 8px; border-radius: 999px; margin-bottom: 2px; }
.frt-etat.ok { color: var(--sem-facture-t); background: color-mix(in srgb, var(--sem-facture) 14%, transparent); }
.frt-etat.choix { color: var(--sem-vente-t); background: color-mix(in srgb, var(--accent) 12%, transparent); cursor: pointer; }
.frt-etat.choix input { margin: 0; }
.frt-nom { font-size: 13px; font-weight: 600; line-height: 1.35; overflow-wrap: anywhere; }
.frt-tun { font-size: 11px; color: var(--muted); }
.frt-alerte { font-size: 11.5px; color: var(--sem-attente-t); margin-top: 2px; }
.frt-c-enc { display: flex; flex-direction: column; gap: 1px; font-variant-numeric: tabular-nums; }
.frt-c-enc b { font-size: 14px; font-weight: 700; }
.frt-c-enc span { font-size: 12px; color: var(--muted); }
.frt-c-verif { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
.frt-ok { display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; font-weight: 650; color: var(--sem-facture-t); }
.frt-ecart { display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; font-weight: 700; color: var(--sem-attente-t); }
.frt-ecart.arrondi { color: var(--ink-2); }
.frt-ancien { font-size: 12px; color: var(--muted); }
.frt-aligner { border: 1px solid var(--accent); background: var(--surface); color: var(--accent-strong); font: inherit;
  font-size: 12px; font-weight: 650; padding: 4px 10px; border-radius: 8px; cursor: pointer; }
.frt-aligner:hover { background: var(--sem-vente-bg); }
.frt-delier { border: 0; background: none; padding: 0; font: inherit; font-size: 11.5px; color: var(--muted); cursor: pointer; text-decoration: underline; }
.frt-delier:hover { color: var(--sem-defaut-t); }
.frt-aucun { display: flex; align-items: center; gap: 7px; font-size: 13px; font-weight: 600; color: var(--sem-attente-t); padding: 6px 2px; }
.frt .frs-autre-btn { margin-left: 0; }
.frt .frs-autre-pop { margin-left: 0; }
@media (max-width: 900px) {
  .frt-tete { display: none; }
  .frt-ligne { grid-template-columns: 1fr; }
  .frt-bon { grid-template-columns: 1fr; }
}
.frt-tete { padding-right: 34px; }
.frt-tete span:nth-child(2) { padding-left: 10px; }

/* Réattribuer une ligne de closing (07/10) */
.pv-ava-btn { border: 0; background: none; padding: 0; cursor: pointer; border-radius: 50%; }
.pv-ava-btn:hover .pv-ava, .pv-ava-btn:focus-visible .pv-ava { box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--accent); }
.modal-box.ra-box { width: min(720px, 95vw); }
.ra-form { display: flex; flex-direction: column; gap: 12px; padding: 4px 2px 0; }
.ra-de { font-size: 13px; color: var(--ink-2); }
.ra-champ { display: flex; flex-direction: column; gap: 4px; font-size: 12.5px; font-weight: 600; }
.ra-modes { border: 1px solid var(--hairline); border-radius: 10px; padding: 8px 12px 10px; display: flex; flex-direction: column; gap: 6px; }
.ra-modes legend { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); padding: 0 4px; }
.ra-mode { display: flex; align-items: flex-start; gap: 8px; font-size: 13px; cursor: pointer; padding: 4px 2px; }
.ra-mode input { margin-top: 3px; }
.ra-mode:has(input:disabled) { opacity: .55; cursor: not-allowed; }
.ra-dispo { display: block; font-style: normal; font-size: 12px; color: var(--muted); margin-top: 1px; }
.ra-dispo.ok { color: var(--sem-facture-t); font-weight: 600; }
.ra-dispo.non { color: var(--sem-attente-t); }
.ra-avert { margin: 0; }
.ra-cal .rc > .form-section, .ra-cal [data-rc-avert] { display: none !important; }
.ra-questions { margin: 2px 0 4px 26px; padding: 8px 10px; border-radius: 8px; background: var(--page); display: flex; flex-direction: column; gap: 8px; }
.ra-q-titre { font-size: 12px; color: var(--muted); }
.ra-q-nom { font-size: 12.5px; font-weight: 600; margin-bottom: 2px; }
.ra-q .check { display: flex; gap: 6px; font-size: 12.5px; padding: 1px 0; }
.ra-q input[type=text] { width: 100%; }

/* 07/10 — une personne attendue chez plusieurs closers. */
/* Une insignia sur l'angle de la pastille : la colonne est étroite et coupe
   tout ce qui viendrait à côté (07/10). */
td.c-clo { position: relative; overflow: visible; }
.pv-doublon { position: absolute; top: 2px; left: calc(50% + 6px); z-index: 2; font-size: 9px; font-weight: 700; line-height: 1;
  padding: 2px 4px; border-radius: 8px; border: 1.5px solid var(--surface, #fff); cursor: pointer;
  background: var(--sem-attente); color: #fff; }
.pv-doublon:hover { filter: brightness(.9); }
.db-liste { display: flex; flex-direction: column; gap: 6px; }
.db-rdv { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border: 1px solid var(--hairline);
  border-radius: 10px; cursor: pointer; font-size: 13.5px; }
.db-rdv:has(input:checked) { border-color: var(--accent, #2f6fde); background: var(--surface); }
.db-nom { font-weight: 600; flex: 1; }
.db-quand { color: var(--muted); font-size: 12.5px; font-variant-numeric: tabular-nums; }
.db-annuler { font-size: 13px; }

/* Réattribuer — épuré (07/10) : « actuelle → nouvelle » sur une ligne. */
.ra-flux { display: flex; align-items: center; gap: 12px; }
.ra-actuelle { display: inline-flex; align-items: center; gap: 8px; font-size: 13.5px; font-weight: 600; white-space: nowrap; }
.ra-fleche { color: var(--muted); font-size: 16px; }
.ra-nouvelle { flex: 1; min-width: 0; }
.ra-nouvelle select, .ra-nouvelle .combo { width: 100%; }
.ra-rdv { font-size: 12.5px; color: var(--muted); }
.ra-pied { justify-content: flex-end; }
.stripe-lien-bloc .fld.grow { flex: 1; }
.stripe-lien-bloc .fld { position: relative; min-width: 0; }
.stripe-lien-bloc .combo-list { max-width: min(600px, calc(100vw - 32px)); }
.stripe-lien-bloc .combo-list * { white-space: normal !important; overflow-wrap: anywhere; }

/* Registre : options sous leur vente principale (07/10) */
.opt-toggle { display: inline-flex; align-items: center; gap: 4px; margin-left: 6px; padding: 1px 9px; border-radius: 999px;
  border: 1px solid var(--hairline); background: var(--page); color: var(--ink-2); font: inherit; font-size: 11.5px; font-weight: 600; cursor: pointer; white-space: nowrap; }
.opt-toggle::after { content: "▾"; font-size: 10px; transition: transform .15s; }
.opt-toggle.ouvert::after { transform: rotate(180deg); }
.opt-toggle:hover, .opt-toggle.ouvert { border-color: var(--accent); color: var(--accent-strong); background: var(--sem-vente-bg); }
tr.vente-option > td { background: color-mix(in srgb, var(--sem-vente-bg) 45%, transparent); }
tr.vente-option > td:nth-child(2), tr.vente-option > td:nth-child(3) { padding-left: 22px; }
.opt-fleche { color: var(--muted); margin-right: 5px; }
.opt-de { display: block; }
.opt-closer { font-size: 12.5px; color: var(--muted); }
.opt-bande { margin: 0 0 10px; padding: 8px 12px; border-radius: 10px; background: var(--sem-vente-bg); color: var(--ink-2); font-size: 13px; }
.opt-bande a { font-weight: 600; }

/* ══ Fiche d'un événement — repas et chambres (07/10) ═══════════════════════
   Quatre chiffres en tête, une ligne de pastilles pour le « sur place », puis
   les onglets Inscrits / Chambres. Couleurs : vert = argent, ambre = à
   préciser / à placer, violet = individuelle, turquoise = partagée. */
.evx-kpis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; margin-bottom: 10px; }
@media (max-width: 900px) { .evx-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.evx-k { background: var(--surface); border: 1px solid var(--hairline); border-radius: 12px;
  padding: 11px 14px 12px; display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.evx-kl { font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); font-weight: 600; }
.evx-kv { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
.evx-kv b { font-size: 22px; line-height: 1; font-variant-numeric: tabular-nums; }
.evx-kv > span { color: var(--muted); font-size: 13px; }
.evx-kv i { font-style: normal; }
.evx-bar { height: 5px; border-radius: 99px; background: var(--page); overflow: hidden; margin-top: auto; }
.evx-bar i { display: block; height: 100%; border-radius: inherit; background: var(--sem-vente); max-width: 100%; }
.evx-bar.vert i { background: var(--sem-facture); }
.evx-bar.teal i { background: var(--sem-acces); }
.j-plein .evx-bar i, .j-complet .evx-bar i { background: var(--sem-facture); }
.evx-krepas { display: flex; flex-wrap: wrap; gap: 4px; }
.evx-kr { display: inline-flex; align-items: baseline; gap: 4px; padding: 2px 8px 2px 3px; border-radius: 99px;
  background: var(--sem-peda-bg); color: var(--sem-peda-t); font-size: 11.5px; white-space: nowrap; }
.evx-kr b { background: var(--sem-peda); color: #fff; border-radius: 99px; padding: 0 6px; font-size: 11px;
  font-variant-numeric: tabular-nums; }
.evx-klink { all: unset; cursor: pointer; font-size: 12px; color: var(--accent); margin-top: auto; }
.evx-klink:hover { text-decoration: underline; }
.evx-badge { display: inline-flex; align-items: center; gap: 4px; padding: 1px 8px; border-radius: 99px; font-size: 11.5px;
  font-weight: 600; background: var(--page); color: var(--muted); white-space: nowrap; }
.evx-badge.ambre { background: var(--sem-attente-bg); color: var(--sem-attente-t); }
.evx-badge.rouge { background: var(--sem-defaut-bg); color: var(--sem-defaut-t); }
.evx-badge.vert { background: var(--sem-facture-bg); color: var(--sem-facture-t); }

.evx-infos { display: flex; flex-wrap: wrap; gap: 8px 22px; align-items: center; background: var(--surface);
  border: 1px solid var(--hairline); border-radius: 12px; padding: 10px 14px; margin-bottom: 12px; }
.evx-i { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; min-width: 0; }
.evx-il { font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); font-weight: 600; margin-right: 2px; }
.evx-pill { display: inline-flex; align-items: center; gap: 4px; padding: 2px 9px; border-radius: 99px; font-size: 12px;
  background: var(--page); color: var(--ink); white-space: nowrap; border: 1px solid transparent; }
.evx-pill b { font-variant-numeric: tabular-nums; }
.evx-pill em { font-style: normal; font-size: 11px; color: var(--sem-facture-t); }
.evx-pill em.rouge { color: var(--sem-defaut-t); }
.evx-pill.lien { color: var(--accent); text-decoration: none; }
.evx-pill.alg { background: var(--sem-defaut-bg); color: var(--sem-defaut-t); }
.evx-pill.reg { background: var(--sem-vente-bg); color: var(--sem-vente-t); }
.evx-pill.woo { background: var(--orig-boutique-bg); color: var(--orig-boutique-t); }
.evx-pill.sm { font-size: 11px; padding: 1px 7px; margin: 1px 2px 1px 0; }
.evx-pers { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; padding: 2px 9px 2px 2px;
  border-radius: 99px; background: var(--page); white-space: nowrap; }
.evx-pers i { font-style: normal; width: 19px; height: 19px; border-radius: 50%; display: grid; place-items: center;
  font-size: 10px; font-weight: 700; background: var(--sem-care-bg); color: var(--sem-care-t); }
.evx-pers.ref { background: var(--sem-care-bg); color: var(--sem-care-t); font-weight: 600; }
.evx-pers.ref i { background: var(--sem-care); color: #fff; }
.evx-pers.info { opacity: .7; }

.evx-main { padding-top: 6px; }
.evx-tabbar { display: flex; align-items: flex-end; justify-content: space-between; gap: 10px; flex-wrap: wrap;
  border-bottom: 1px solid var(--hairline); margin-bottom: 10px; }
.evx-onglets { margin-bottom: -1px; }
.pv-onglet-n.ambre { background: var(--sem-attente-bg); color: var(--sem-attente-t); }
.evx-tabact { display: flex; gap: 6px; align-items: center; padding-bottom: 8px; flex-wrap: wrap; }
.evx-tabact[hidden] { display: none; }
.evx-table td { vertical-align: middle; }
.evx-nom { font-weight: 600; color: var(--ink); text-decoration: none; }
.evx-nom:hover { color: var(--accent); }
.evx-mail { display: block; font-size: 11.5px; color: var(--muted); max-width: 240px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.evx-note { font-size: 10.5px; font-weight: 600; color: var(--sem-attente-t); background: var(--sem-attente-bg); padding: 0 6px; border-radius: 99px; margin-left: 5px; cursor: help; vertical-align: 1px; }
.evx-lg { display: inline-block; font-size: 11.5px; font-weight: 600; padding: 1px 8px; border-radius: 6px;
  background: var(--page); color: var(--muted); }
.evx-lg.l-individual { background: var(--sem-care-bg); color: var(--sem-care-t); }
.evx-lg.l-compartida { background: var(--sem-acces-bg); color: var(--sem-acces-t); }
.evx-chip-ch { display: inline-block; margin-left: 4px; font-size: 11.5px; padding: 1px 8px; border-radius: 99px;
  border: 1px solid var(--hairline); cursor: pointer; white-space: nowrap; }
.evx-chip-ch.ambre { border-color: transparent; background: var(--sem-attente-bg); color: var(--sem-attente-t); font-weight: 600; }
.evx-anc { font-size: 11.5px; padding: 1px 8px; border-radius: 99px; background: var(--page); color: var(--muted); }
.evx-anc.nouveau { background: var(--sem-facture-bg); color: var(--sem-facture-t); font-weight: 600; }
.evx-ach { font-size: 11.5px; padding: 1px 8px; border-radius: 99px; background: var(--sem-vente-bg); color: var(--sem-vente-t); cursor: help; }
.evx-annul { all: unset; cursor: pointer; font-size: 12px; color: var(--muted); padding: 3px 8px; border-radius: 6px; }
.evx-annul:hover { color: var(--sem-defaut-t); background: var(--sem-defaut-bg); }

/* Les pastilles de repas : un clic = pris / pas pris. */
.evx-rps { display: flex; flex-wrap: wrap; gap: 3px; align-items: center; }
.evx-rp { all: unset; cursor: pointer; font-size: 11px; line-height: 1; padding: 4px 8px; border-radius: 99px;
  border: 1px solid var(--border); color: var(--muted); white-space: nowrap; transition: background .12s, color .12s, border-color .12s; }
.evx-rp:hover { border-color: var(--sem-peda); color: var(--sem-peda-t); }
.evx-rp.on { background: var(--sem-peda); border-color: var(--sem-peda); color: #fff; }
.evx-rp:focus-visible, .evx-rp-all:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.evx-rp[disabled] { cursor: default; }
.evx-rps.apreciser .evx-rp { border-style: dashed; border-color: var(--sem-attente); color: var(--sem-attente-t); }
.evx-rp-all { all: unset; cursor: pointer; font-size: 11px; width: 20px; height: 20px; display: grid; place-items: center;
  border-radius: 50%; color: var(--muted); opacity: 0; transition: opacity .12s; }
tr:hover .evx-rp-all, .evx-rp-all:focus-visible { opacity: 1; }
.evx-rp-all:hover { background: var(--sem-peda-bg); color: var(--sem-peda-t); }
.evx-rps.busy { opacity: .55; pointer-events: none; }
.evx-rp-chk input { position: absolute; opacity: 0; width: 0; height: 0; }
.evx-rp-chk span { display: inline-block; cursor: pointer; font-size: 12px; padding: 4px 10px; border-radius: 99px; border: 1px solid var(--border); color: var(--muted); }
.evx-rp-chk input:checked + span { background: var(--sem-peda); border-color: var(--sem-peda); color: #fff; }
.evx-rp-chk input:focus-visible + span { outline: 2px solid var(--accent); }

/* Le plan des chambres */
.evx-ch { display: flex; flex-direction: column; gap: 14px; padding-bottom: 6px; }
.evx-tray { border: 1.5px dashed var(--sem-attente); background: var(--sem-attente-bg); border-radius: 12px; padding: 10px 12px; }
.evx-tray.vide { border-color: var(--sem-facture); background: var(--sem-facture-bg); }
.evx-tray-t { font-size: 11px; letter-spacing: .06em; text-transform: uppercase; font-weight: 700; color: var(--sem-attente-t); }
.evx-tray.vide .evx-tray-t { color: var(--sem-facture-t); }
.evx-tray-t b { margin-left: 4px; }
.evx-tray-p { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; min-height: 30px; }
.evx-ok { font-size: 12.5px; color: var(--sem-facture-t); font-weight: 600; align-self: center; }
.evx-sans { margin-top: 8px; }
.evx-sans summary { cursor: pointer; font-size: 12px; color: var(--muted); }
.evx-p { display: inline-flex; align-items: center; gap: 6px; padding: 3px 9px 3px 3px; border-radius: 99px;
  background: var(--surface); border: 1px solid var(--hairline); box-shadow: 0 1px 2px rgba(0,0,0,.05);
  cursor: grab; user-select: none; font-size: 12.5px; max-width: 100%; }
.evx-p:active { cursor: grabbing; }
.evx-p.dragging { opacity: .4; }
.evx-p.choisie { outline: 2px solid var(--accent); }
.evx-av { width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center; font-size: 10px; font-weight: 700;
  background: var(--page); color: var(--muted); flex: none; }
.evx-p.l-individual .evx-av { background: var(--sem-care); color: #fff; }
.evx-p.l-compartida .evx-av { background: var(--sem-acces); color: #fff; }
.evx-pn { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.evx-pt { font-size: 10.5px; color: var(--muted); }
.evx-p.ecart { border-color: var(--sem-attente); background: var(--sem-attente-bg); }
.evx-mas-h { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.evx-mas-h b { font-size: 14px; }
.evx-mas-ico { width: 24px; height: 24px; border-radius: 7px; display: grid; place-items: center; background: var(--sem-acces-bg); color: var(--sem-acces-t); }
.evx-mas-n { font-size: 12px; color: var(--muted); }
.evx-mas-h .btn { margin-left: auto; }
.evx-rooms { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 10px; }
.evx-room { border: 1px solid var(--hairline); border-top: 3px solid var(--sem-ops); border-radius: 10px; background: var(--surface);
  padding: 9px 10px 10px; transition: box-shadow .12s, border-color .12s, background .12s; }
.evx-room.t-indiv { border-top-color: var(--sem-care); }
.evx-room.t-part { border-top-color: var(--sem-acces); }
.evx-room.over { background: var(--accent-soft); box-shadow: 0 0 0 2px var(--accent); }
.evx-room.full.over { background: var(--sem-defaut-bg); box-shadow: 0 0 0 2px var(--sem-defaut); }
.evx-room.trop { border-color: var(--sem-defaut); }
.evx-room-h { display: flex; align-items: center; gap: 6px; margin-bottom: 8px; }
.evx-room-h b { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.evx-rtype { font-size: 10.5px; padding: 1px 7px; border-radius: 99px; background: var(--page); color: var(--muted); white-space: nowrap; }
.t-indiv .evx-rtype { background: var(--sem-care-bg); color: var(--sem-care-t); }
.t-part .evx-rtype { background: var(--sem-acces-bg); color: var(--sem-acces-t); }
.evx-cap { margin-left: auto; font-size: 11.5px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--muted); }
.full .evx-cap { color: var(--sem-facture-t); }
.trop .evx-cap { color: var(--sem-defaut-t); }
.evx-edit { all: unset; cursor: pointer; font-size: 12px; color: var(--muted); padding: 0 4px; border-radius: 5px; opacity: 0; }
.evx-room:hover .evx-edit, .evx-edit:focus-visible { opacity: 1; }
.evx-edit:hover { background: var(--page); color: var(--ink); }
.evx-slots { display: flex; flex-direction: column; gap: 5px; }
.evx-slots .evx-p { width: 100%; box-sizing: border-box; }
.evx-slot { border: 1.5px dashed var(--border); border-radius: 99px; padding: 4px 10px; font-size: 11.5px; color: var(--muted); text-align: center; }
.evx-ch-pied { display: flex; gap: 8px; }
.evx-vide { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 34px 10px; text-align: center; }
.evx-vide-ico { font-size: 30px; }
.evx-vide-a { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; align-items: center; }
.evx-import { display: flex; gap: 6px; align-items: center; }
.evx-import select { max-width: 280px; }

/* Les modals repas / chambre */
.modal-box.evx-box { width: min(540px, 94vw); overflow-x: hidden; }
.evx-mhead { display: flex; align-items: center; gap: 12px; margin: -20px -22px 0; padding: 16px 22px; border-bottom: 1px solid var(--hairline); }
.evx-mhead b { font-size: 15px; }
.evx-mhead .grow { flex: 1; display: flex; flex-direction: column; }
.evx-mico { width: 32px; height: 32px; border-radius: 9px; display: grid; place-items: center; font-size: 16px; }
.evx-mico.rp { background: var(--sem-peda-bg); }
.evx-mico.ch { background: var(--sem-acces-bg); }
.evx-msub { font-size: 12px; color: var(--muted); }
.evx-mbody { padding: 18px 0 6px; display: flex; flex-direction: column; gap: 12px; }
.evx-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px 14px; }
.evx-span2 { grid-column: 1 / -1; }
.evx-grid2 .fld { display: flex; flex-direction: column; gap: 6px; font-size: 12px; color: var(--muted); font-weight: 600; margin: 0; }
.evx-grid2 .fld input[type=text] { width: 100%; box-sizing: border-box; }
.evx-rp-liste { display: flex; flex-direction: column; gap: 6px; }
.evx-rp-ligne { display: flex; gap: 6px; align-items: center; }
.evx-rp-ligne .input { flex: 1; }
.evx-x { all: unset; cursor: pointer; width: 26px; height: 26px; display: grid; place-items: center; border-radius: 7px; color: var(--muted); }
.evx-x:hover { background: var(--sem-defaut-bg); color: var(--sem-defaut-t); }
.evx-sugg { display: flex; flex-direction: column; gap: 5px; padding-top: 8px; border-top: 1px dashed var(--hairline); }
.evx-sugg-j { display: flex; align-items: center; gap: 5px; }
.evx-sugg-j > span { width: 40px; font-size: 12px; font-weight: 600; color: var(--muted); }
.evx-chip { all: unset; cursor: pointer; font-size: 11.5px; padding: 3px 9px; border-radius: 99px; border: 1px solid var(--border); color: var(--muted); }
.evx-chip:hover { border-color: var(--sem-peda); color: var(--sem-peda-t); }
.evx-chip.pris { background: var(--sem-peda); border-color: var(--sem-peda); color: #fff; }
.evx-types { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; }
.evx-type input { position: absolute; opacity: 0; width: 0; height: 0; }
.evx-type span { display: inline-block; cursor: pointer; font-size: 12px; font-weight: 500; padding: 5px 12px; border-radius: 99px; border: 1px solid var(--border); color: var(--ink); }
.evx-type input:checked + span { background: var(--sem-acces); border-color: var(--sem-acces); color: #fff; }
.evx-type input:focus-visible + span { outline: 2px solid var(--accent); }
.evx-box .evx-type-libre { width: 110px; font-size: 12px; padding: 5px 10px; border-radius: 99px; height: auto; }
.evx-stepper { display: flex; align-items: center; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; width: max-content; }
.evx-stepper button { all: unset; cursor: pointer; width: 30px; text-align: center; font-size: 15px; color: var(--muted); }
.evx-stepper button:hover { background: var(--page); color: var(--ink); }
.evx-stepper { height: 36px; background: var(--surface); }
.evx-stepper button { height: 100%; display: grid; place-items: center; }
.evx-box .evx-stepper input[type=number] { width: 44px; height: 100%; border: 0; border-left: 1px solid var(--hairline); border-right: 1px solid var(--hairline); border-radius: 0; box-shadow: none; padding: 0; text-align: center; font-weight: 600; color: var(--ink); -moz-appearance: textfield; }
.evx-stepper input::-webkit-inner-spin-button { -webkit-appearance: none; }
.evx-err { background: var(--sem-defaut-bg); color: var(--sem-defaut-t); border-radius: 8px; padding: 7px 10px; font-size: 12.5px; }
.evx-box .av-pied { display: flex; gap: 8px; align-items: center; }
.evx-box .av-pied .grow { flex: 1; }
.evx-pill.nul { background: transparent; color: var(--muted); padding-left: 2px; padding-right: 2px; }
.evx-i { line-height: 20px; }
.evx-il { line-height: 20px; }
.evx-il { display: inline-flex; align-items: center; height: 24px; padding-top: 2px; box-sizing: border-box; }
.evx-infos .evx-pill, .evx-infos .evx-pers { height: 24px; box-sizing: border-box; }
.evx-mbody > [data-evx-rp-ajout] { align-self: flex-start; }
.evx-box .evx-type-libre { border: 1px solid var(--border); box-shadow: none; outline: 0; }
.evx-box .evx-type-libre:focus { border-color: var(--accent); }
.evx-type input:checked + span { background: var(--accent); border-color: var(--accent); }
.evx-k > .evx-badge { align-self: flex-start; }
.evx-onglets .pv-onglet .pv-onglet-n.ambre { background: var(--sem-attente-bg); color: var(--sem-attente-t); }
.evx-kv [hidden] { display: none; }
/* Binôme, demande pour l'hôtel, équipe (07/10) */
.evx-bin { font-size: 10.5px; padding: 0 6px; border-radius: 99px; background: var(--sem-acces-bg); color: var(--sem-acces-t); white-space: nowrap; }
.evx-bin.ailleurs { background: var(--sem-attente-bg); color: var(--sem-attente-t); }
td .evx-bin { display: inline-block; margin-left: 4px; font-size: 11px; padding: 1px 8px; }
.evx-nh { width: 15px; height: 15px; border-radius: 50%; display: grid; place-items: center; font-size: 10px; font-weight: 800;
  background: var(--sem-attente); color: #fff; flex: none; }
.evx-pmore { all: unset; cursor: pointer; margin-left: auto; padding: 0 5px; border-radius: 6px; color: var(--muted); font-size: 13px; line-height: 18px; opacity: .45; }
.evx-p:hover .evx-pmore, .evx-pmore:focus-visible { opacity: 1; }
.evx-pmore:hover { background: var(--page); color: var(--ink); }
.evx-p.staff { border-style: dashed; }
.evx-p.staff .evx-av { background: var(--sem-ops); color: #fff; }
.evx-tray-eq { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 8px; }
.evx-tray-st { font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase; font-weight: 700; color: var(--sem-ops-t); margin-right: 2px; }
.evx-box select { width: 100%; }

/* ══ Places & chambres — pour les closers (07/10) ═══════════════════════ */
.modal-box.dsp-box { width: min(980px, 96vw); max-height: 90vh; display: flex; flex-direction: column; overflow: hidden; }
.dsp-head { display: flex; align-items: center; gap: 12px; margin: -20px -22px 0; padding: 16px 22px; border-bottom: 1px solid var(--hairline); }
.dsp-head .grow { flex: 1; display: flex; flex-direction: column; }
.dsp-head b { font-size: 15px; }
.dsp-rouge { color: var(--sem-defaut-t); font-weight: 600; }
.dsp-box input.dsp-q { width: 230px; border-radius: 99px; padding: 6px 14px; font-size: 13px; }
.dsp-leg { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--muted); padding: 10px 0 2px; }
.dsp-dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; margin-left: 8px; }
.dsp-dot:first-child { margin-left: 0; }
.dsp-dot.ok { background: var(--sem-facture); } .dsp-dot.juste { background: var(--sem-attente); }
.dsp-dot.complet { background: var(--sem-defaut); } .dsp-dot.inconnu { background: var(--border); }
.dsp-body { overflow-y: auto; padding: 4px 2px 8px; margin: 0 -4px; }
.dsp-mois h3 { font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); margin: 14px 4px 8px; font-weight: 700; }
.dsp-mois[hidden], .dsp-ev[hidden] { display: none; }
.dsp-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); gap: 10px; padding: 0 4px; }
.dsp-ev { background: var(--surface); border: 1px solid var(--hairline); border-radius: 12px; padding: 11px 12px 12px; display: flex; flex-direction: column; gap: 9px; }
.dsp-ev.e-complet { background: var(--sem-defaut-bg); border-color: transparent; }
.dsp-ev-h { display: flex; gap: 10px; align-items: center; min-width: 0; }
.dsp-date { width: 40px; flex: none; text-align: center; border-radius: 9px; background: var(--page); padding: 4px 0; line-height: 1.05; }
.dsp-date b { display: block; font-size: 17px; }
.dsp-date span { font-size: 10px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
.dsp-ev-t { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.dsp-nom { font-weight: 600; font-size: 12.5px; line-height: 1.3; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.dsp-ou { font-size: 11.5px; color: var(--muted); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dsp-places { flex: none; text-align: right; line-height: 1.05; }
.dsp-places b { display: block; font-size: 20px; font-variant-numeric: tabular-nums; }
.dsp-places span { font-size: 10.5px; color: var(--muted); }
.dsp-places.pl-ok b { color: var(--sem-facture-t); }
.dsp-places.pl-juste b { color: var(--sem-attente-t); }
.dsp-places.pl-complet b, .dsp-places.pl-complet span { color: var(--sem-defaut-t); }
.dsp-bar { height: 4px; border-radius: 99px; background: var(--page); overflow: hidden; }
.dsp-bar i { display: block; height: 100%; background: var(--sem-facture); border-radius: inherit; }
.dsp-bar.pl-juste i { background: var(--sem-attente); } .dsp-bar.pl-complet i { background: var(--sem-defaut); }
.dsp-f { display: flex; flex-wrap: wrap; gap: 5px; }
.dsp-chip { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; padding: 2px 4px 2px 9px; border-radius: 99px; background: var(--page); color: var(--ink); }
.dsp-chip b { font-size: 11px; padding: 1px 7px; border-radius: 99px; background: var(--surface); }
.dsp-chip.f-ok b { background: var(--sem-facture); color: #fff; }
.dsp-chip.f-juste b { background: var(--sem-attente); color: #fff; }
.dsp-chip.f-complet b { background: var(--sem-defaut); color: #fff; }
.dsp-chip.f-inconnu b { color: var(--muted); }
.dsp-chip.f-sans { padding-right: 9px; color: var(--muted); }

.dsp-places { background: none; }
.dsp-ev-h { align-items: flex-start; }
.dsp-ev[data-dsp-detail] { cursor: pointer; transition: box-shadow .15s, transform .15s, border-color .15s; }
.dsp-ev[data-dsp-detail]:hover { border-color: var(--border); box-shadow: var(--shadow-lift); transform: translateY(-1px); }
.dsp-ev[data-dsp-detail]:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.dsp-leg[hidden], .dsp-body[hidden] { display: none; }
.dsp-fiche { display: flex; flex-direction: column; gap: 14px; padding: 12px 4px 6px; }
.dsp-retour { all: unset; cursor: pointer; font-size: 12.5px; color: var(--accent); align-self: flex-start; }
.dsp-retour:hover { text-decoration: underline; }
.dsp-fh { display: flex; gap: 12px; align-items: center; }
.dsp-date.big { width: 52px; padding: 7px 0; }
.dsp-date.big b { font-size: 22px; }
.dsp-ftitre { font-size: 15px; line-height: 1.3; }
.dsp-kpis { display: flex; flex-wrap: wrap; gap: 10px; }
.dsp-k { display: flex; align-items: center; gap: 10px; padding: 10px 14px; border-radius: 12px; background: var(--surface); border: 1px solid var(--hairline); min-width: 170px; }
.dsp-k b { font-size: 26px; font-variant-numeric: tabular-nums; line-height: 1; }
.dsp-k span { font-size: 12.5px; color: var(--ink); line-height: 1.3; }
.dsp-k em { font-style: normal; font-size: 11px; color: var(--muted); }
.dsp-k.pl-ok b { color: var(--sem-facture-t); }
.dsp-k.pl-juste { background: var(--sem-attente-bg); border-color: transparent; } .dsp-k.pl-juste b { color: var(--sem-attente-t); }
.dsp-k.pl-complet { background: var(--sem-defaut-bg); border-color: transparent; } .dsp-k.pl-complet b { color: var(--sem-defaut-t); }
.dsp-k.pl-inconnu b { color: var(--muted); }
.dsp-mas h4 { display: flex; align-items: center; gap: 8px; font-size: 14px; margin: 4px 0 8px; }
.dsp-mas-l { font-size: 11.5px; font-weight: 600; padding: 1px 9px; border-radius: 99px; }
.dsp-mas-l.ok { background: var(--sem-facture-bg); color: var(--sem-facture-t); }
.dsp-mas-l.complet { background: var(--sem-defaut-bg); color: var(--sem-defaut-t); }
.dsp-rooms { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 8px; }
.dsp-room { border: 1px solid var(--hairline); border-left: 4px solid var(--sem-ops); border-radius: 10px; background: var(--surface); padding: 9px 11px; display: flex; flex-direction: column; gap: 7px; }
.dsp-room.t-indiv { border-left-color: var(--sem-care); }
.dsp-room.t-part { border-left-color: var(--sem-acces); }
.dsp-room.pleine { opacity: .6; background: var(--page); }
.dsp-room-h { display: flex; align-items: center; gap: 6px; }
.dsp-room-h b { font-size: 13px; }
.dsp-lits { display: flex; gap: 5px; }
.lit { display: inline-block; width: 14px; height: 14px; border-radius: 4px; }
.lit.pris { background: var(--sem-vente); }
.lit.equipe { background: var(--sem-ops); }
.lit.libre { border: 2px dashed var(--sem-facture); box-sizing: border-box; background: var(--sem-facture-bg); }
.dsp-room-s { font-size: 11.5px; font-weight: 600; color: var(--sem-facture-t); }
.dsp-room.pleine .dsp-room-s { color: var(--muted); }
.dsp-leg2 { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--muted); }
.dsp-leg2 .lit { margin-left: 8px; } .dsp-leg2 .lit:first-child { margin-left: 0; }
.dsp-rien { display: flex; flex-direction: column; gap: 4px; padding: 22px; border-radius: 12px; background: var(--page); text-align: center; }
.dsp-rien span { font-size: 12.5px; color: var(--muted); }
.dsp-box input.dsp-q { border: 1px solid var(--border); box-shadow: none; outline: 0; background: var(--surface); }
.dsp-box input.dsp-q:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
/* Détail d'une session, v2 : dispo à gauche, infos de vente à droite */
.dsp-cols { display: grid; grid-template-columns: minmax(250px, 320px) 1fr; gap: 16px; align-items: start; }
@media (max-width: 760px) { .dsp-cols { grid-template-columns: 1fr; } }
.dsp-dispo { display: flex; flex-direction: column; gap: 8px; }
.dsp-jauge { border-radius: 14px; padding: 14px 16px; background: var(--sem-facture-bg); display: flex; flex-direction: column; gap: 8px; }
.dsp-jauge.pl-juste { background: var(--sem-attente-bg); }
.dsp-jauge.pl-complet { background: var(--sem-defaut-bg); }
.dsp-jauge-n { display: flex; align-items: baseline; gap: 8px; }
.dsp-jauge-n b { font-size: 38px; line-height: 1; font-variant-numeric: tabular-nums; color: var(--sem-facture-t); }
.dsp-jauge.pl-juste b { color: var(--sem-attente-t); } .dsp-jauge.pl-complet b { color: var(--sem-defaut-t); }
.dsp-jauge-n span { font-size: 14px; font-weight: 600; }
.dsp-jauge .dsp-bar { height: 6px; background: rgba(255,255,255,.7); }
.dsp-jauge-s { font-size: 12px; color: var(--muted); }
.dsp-frm { display: grid; grid-template-columns: 1fr auto; grid-template-rows: auto auto; column-gap: 10px; align-items: center;
  padding: 9px 12px; border-radius: 10px; background: var(--surface); border: 1px solid var(--hairline); }
.dsp-frm-l { font-size: 13px; font-weight: 600; }
.dsp-frm-s { font-size: 11.5px; color: var(--muted); grid-column: 1; }
.dsp-frm b { grid-column: 2; grid-row: 1 / span 2; font-size: 12px; padding: 3px 10px; border-radius: 99px; background: var(--sem-facture); color: #fff; white-space: nowrap; }
.dsp-frm.pl-juste b { background: var(--sem-attente); } .dsp-frm.pl-complet b { background: var(--sem-defaut); }
.dsp-frm.pl-inconnu b, .dsp-frm.neutre b { background: var(--page); color: var(--muted); }
.dsp-infos { margin: 0; display: grid; grid-template-columns: 70px 1fr; gap: 12px 12px; padding: 14px 16px; border-radius: 14px;
  background: var(--surface); border: 1px solid var(--hairline); }
.dsp-infos dt { font-size: 10.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); font-weight: 700; padding-top: 3px; }
.dsp-infos dd { margin: 0; font-size: 13px; display: flex; flex-wrap: wrap; align-items: center; gap: 5px 8px; min-width: 0; }
.dsp-adr { flex-basis: 100%; font-size: 12px; color: var(--muted); }
.dsp-lien { font-size: 12px; color: var(--accent); }
.dsp-copie { flex-wrap: nowrap !important; }
.dsp-url { flex: 1; min-width: 0; font-size: 12px; color: var(--muted); background: var(--page); padding: 4px 10px; border-radius: 8px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-family: ui-monospace, monospace; }
.dsp-note { font-size: 12.5px; color: var(--sem-attente-t); background: var(--sem-attente-bg); padding: 10px 14px; border-radius: 10px; }

/* La carte remplit sa carte du tableau de bord (07/10). */
.card.c4:has(> .carte-google) { display: flex; flex-direction: column; }
.card.c4 > .carte-google { height: auto; }
/* Une vente d'hébergement : un badge, pas de tâches (07/10). */
.badge.b-heb { background: var(--sem-acces-bg); color: var(--sem-acces-t); cursor: help; }
.badge.b-heb::before { content: none; }
.badge.b-heb.attente { background: var(--sem-attente-bg); color: var(--sem-attente-t); }

/* ══ Setting (08/10) ══════════════════════════════════════════════════════ */
.st-k-s { font-size: 12px; color: var(--sem-facture-t); font-weight: 600; }
.st-filtres { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.st-filtres select, .st-filtres .st-q { max-width: 240px; }
.st-table td { vertical-align: middle; }
.st-table tr.st-ok td { background: color-mix(in srgb, var(--sem-facture-bg) 60%, transparent); }
.st-table tr.st-non td { opacity: .55; }
.st-table tr.st-busy { opacity: .5; pointer-events: none; }
.st-table tr.st-flash td { animation: st-flash 1.2s ease; }
@keyframes st-flash { from { background: var(--accent-soft); } to { background: transparent; } }
@media (prefers-reduced-motion: reduce) { .st-table tr.st-flash td { animation: none; } }
.st-tel { font-weight: 600; font-variant-numeric: tabular-nums; color: var(--ink); text-decoration: none; padding: 2px 8px;
  border-radius: 99px; background: var(--sem-vente-bg); }
.st-tel:hover { background: var(--sem-vente); color: #fff; }
.st-live { all: unset; cursor: pointer; display: inline-flex; align-items: center; gap: 3px; padding: 2px 4px; border-radius: 8px; }
.st-live:hover { background: var(--page); }
.st-live:focus-visible { outline: 2px solid var(--accent); }
.st-j { font-style: normal; font-size: 10px; font-weight: 700; width: 20px; height: 20px; display: inline-grid; place-items: center;
  border-radius: 6px; background: var(--page); color: var(--muted); }
.st-j.on { background: var(--sem-peda); color: #fff; }
.st-j.big { width: 30px; height: 26px; font-size: 12px; }
.st-clic { font-size: 10.5px; padding: 2px 7px; border-radius: 99px; background: var(--sem-attente-bg); color: var(--sem-attente-t); margin-left: 2px; }
.st-score { font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; margin-left: 2px; }
.st-pill { font-size: 12px; padding: 2px 9px; border-radius: 99px; background: var(--page); }
.st-pill.moi { background: var(--sem-care-bg); color: var(--sem-care-t); font-weight: 600; }
.st-table select.st-sel { font-size: 12.5px; padding: 3px 26px 3px 8px; height: auto; min-width: 0; }
.st-etat.e-a_appeler { color: var(--sem-vente-t); }
.st-etat.e-a_rappeler { color: var(--sem-attente-t); }
.st-etat.e-injoignable { color: var(--muted); }
.st-etat.e-pas_interessee { color: var(--sem-defaut-t); }
.st-table input.st-date { font-size: 12.5px; padding: 3px 6px; width: 130px; }
.st-table input.st-date.du { border-color: var(--sem-attente); background: var(--sem-attente-bg); }
.st-table input.st-note { font-size: 12.5px; padding: 4px 8px; width: 100%; min-width: 160px; border-color: transparent; background: transparent; }
.st-table input.st-note:hover, .st-table input.st-note:focus { border-color: var(--border); background: var(--surface); }
.st-setter { display: flex; align-items: center; gap: 8px; padding: 6px 0; border-bottom: 1px solid var(--hairline); }
.st-av { background: var(--sem-care); color: #fff; }
.st-setter-form { display: grid; grid-template-columns: 1fr 1fr 70px auto; gap: 8px; align-items: end; padding-top: 10px; }
.st-setter-form .fld { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--muted); font-weight: 600; margin: 0; }
.st-setter-form input, .st-setter-form select { width: 100%; box-sizing: border-box; }
.modal-box.st-rdv-box { width: min(720px, 96vw); }
.st-rdv-box .fld { display: flex; flex-direction: column; gap: 5px; font-size: 12px; color: var(--muted); font-weight: 600; }
.modal-box.st-live-box { width: min(640px, 96vw); }
.st-live-k { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.st-bloc h4 { font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); margin: 6px 0; }
.st-rep, .st-log { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 4px; font-size: 13px; }
.st-chat { font-size: 13px; line-height: 1.5; background: var(--page); border-radius: 10px; padding: 10px 12px; max-height: 260px; overflow-y: auto; }
.st-apercu-k { font-size: 14px; }
.st-choix { display: flex; gap: 10px; align-items: flex-start; padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px; cursor: pointer; font-size: 13px; }
.st-choix:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); }
.st-choix b { font-size: 15px; }
.st-cell { margin: 0; }
.st-cell-sel { font-size: 12px; padding: 2px 22px 2px 6px; border-color: transparent; background-color: transparent; color: var(--muted); max-width: 140px; }
.st-cell-sel:hover { border-color: var(--border); }
.st-cell-sel.pris { color: var(--sem-care-t); font-weight: 600; background-color: var(--sem-care-bg); border-radius: 99px; }
.st-filtres select { min-width: 170px; }
/* Une vente qui n'attend que son règlement (08/10). */
.inv-alert.warn { background: var(--sem-attente-bg); border-color: color-mix(in srgb, var(--sem-attente) 35%, transparent); color: var(--sem-attente-t); }
.badge.b-attente-regl { cursor: help; }
.badge.b-attente-regl::before { content: none; }
.st-setter .grow { flex: 1; display: flex; flex-direction: column; }
.st-setter.inactive { opacity: .55; }
.st-taux-form { display: flex; align-items: center; gap: 3px; margin: 0; }
.st-taux-form input { width: 58px; text-align: right; padding: 3px 6px; }
/* Une CELLULE, pas une boîte flex : en `display: flex` la case ne suivait plus
   la hauteur de la ligne, et son trait du bas décrochait de 10 px (14/10). */
.st-act { white-space: nowrap; }
.st-act > * { vertical-align: middle; }
.st-act form.inline { display: inline-block; margin: 0 0 0 4px; }
.st-table .st-act .evx-x { opacity: 0; }
.st-table tr:hover .st-act .evx-x, .st-act .evx-x:focus-visible { opacity: 1; }

/* Suivi closing — les chiffres d'une closer (08/10). */
.kpi-strip.kpi-tight:has(.kpi-closer) { display: flex; flex-wrap: wrap; align-items: stretch; }
.kpi-strip.kpi-tight:has(.kpi-closer) .kpi-s { flex: 0 1 152px; min-width: 108px; }
.kpi-closer { margin-left: auto; align-self: center; min-width: 210px; }
.kpi-closer select, .kpi-closer .combo { width: 100%; }

/* ---- Les adresses e-mail de la fiche (09/10) ----
   Le crayon sort au survol des coordonnées, comme celui du nom. La fenêtre :
   la principale en haut (★), les outils qui suivent n'apparaissent que si
   elle change, les autres adresses en pastilles. */
.fc-mail { display: inline-flex; align-items: center; gap: 3px; }
.fc-mail-crayon {
  border: 0; background: none; padding: 0 2px; cursor: pointer; font: inherit;
  font-size: 11px; line-height: 1; color: var(--muted); opacity: 0; transition: opacity .12s;
}
.fc-coord:hover .fc-mail-crayon, .fc-mail-crayon:focus-visible { opacity: 1; }
.fc-mail-crayon:hover { color: var(--ink-2); }
.fc-mail-plus {
  border: 1px solid var(--hairline); background: var(--page); color: var(--ink-2);
  border-radius: 999px; font: inherit; font-size: 11px; padding: 1px 8px; cursor: pointer;
}
.fc-mail-plus:hover { border-color: var(--accent); color: var(--accent-strong); }

.em-box { width: min(520px, 94vw); }
.em-l {
  display: block; font-size: 11px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 6px;
}
.em-l-autres { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--hairline); }
.em-form { margin: 0; }
.em-champ {
  display: flex; align-items: center; gap: 8px; padding: 0 10px;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface);
}
.em-champ:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.em-champ input {
  flex: 1; margin: 0; padding: 9px 0; border: 0; box-shadow: none;
  background: transparent; outline: none;
}
.em-etoile { color: var(--warning); font-size: 13px; }
.em-suivent { margin-top: 12px; padding: 12px; border-radius: var(--radius); background: var(--page); }
.em-cibles { display: flex; flex-wrap: wrap; gap: 6px; }
.em-cible {
  display: inline-flex; align-items: center; gap: 6px; margin: 0; padding: 4px 10px;
  border: 1px solid var(--hairline); border-radius: 999px; background: var(--surface);
  font-size: 12.5px; cursor: pointer;
}
.em-cible input { margin: 0; }
.em-cible:has(input:checked) {
  border-color: var(--good-tint-border); background: var(--good-tint); color: var(--good-text);
}
.em-main { cursor: default; color: var(--muted); border-style: dashed; background: transparent; }
.em-pied { display: flex; justify-content: flex-end; gap: 8px; margin-top: 12px; }
.em-autres { list-style: none; margin: 0 0 10px; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.em-pastille {
  display: flex; align-items: center; gap: 8px; padding: 5px 6px 5px 12px;
  border: 1px solid var(--hairline); border-radius: var(--radius); background: var(--surface);
}
.em-adr { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.em-src { font-size: 11px; color: var(--muted); white-space: nowrap; }
.em-pastille form { display: contents; }
.em-geste {
  width: 26px; height: 26px; border: 0; border-radius: 6px; background: none;
  color: var(--muted); font-size: 13px; line-height: 1; cursor: pointer;
}
.em-geste:hover { background: var(--page); color: var(--ink); }
.em-x:hover { color: var(--critical); }
.em-vide { color: var(--muted); font-size: 12.5px; padding: 4px 0; }
.em-ajout { display: flex; gap: 8px; margin: 0; }
.em-ajout input { flex: 1; margin: 0; }

/* ---- Filtres à cases du registre (12/10) ----
   Même habit que « Période » : un bouton qui se résume, un panneau qui
   s'ouvre dessous. Les cases cochées prennent la couleur des ventes. */
.vf-multi { position: relative; }
.vf-multi > summary { list-style: none; display: inline-flex; align-items: center; height: 32px;
                      padding: 0 26px 0 10px; border: 1px solid var(--hairline); border-radius: 8px;
                      background: var(--surface); font-size: 12.5px; color: var(--ink-2); cursor: pointer;
                      white-space: nowrap; position: relative; max-width: 190px; overflow: hidden;
                      text-overflow: ellipsis; }
.vf-multi > summary::-webkit-details-marker { display: none; }
.vf-multi > summary::after { content: ""; position: absolute; right: 10px; top: 50%; width: 6px; height: 6px;
                             border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
                             transform: translateY(-70%) rotate(45deg); opacity: .6; }
.vf-multi.actif > summary { color: var(--sem-vente-t); border-color: var(--sem-vente); background: var(--sem-vente-bg);
                            font-weight: 600; }
.vf-multi-pop { position: absolute; z-index: 40; top: calc(100% + 6px); left: 0; min-width: 220px;
                max-height: 320px; overflow-y: auto; background: var(--surface); border: 1px solid var(--hairline);
                border-radius: 12px; box-shadow: 0 16px 40px rgba(21, 26, 43, .16); padding: 6px;
                display: flex; flex-direction: column; gap: 1px; }
.vf-opt { display: flex; align-items: center; gap: 9px; margin: 0; padding: 7px 10px; border-radius: 8px;
          font-size: 13px; color: var(--ink); cursor: pointer; white-space: nowrap; }
.vf-opt:hover { background: var(--page); }
.vf-opt input { margin: 0; width: 15px; height: 15px; accent-color: var(--sem-vente); }
.vf-opt:has(input:checked) { background: var(--sem-vente-bg); color: var(--sem-vente-t); font-weight: 500; }

/* ---- La même personne sous deux fiches (12/10) ----
   Sur la fiche : une carte ambrée, une ligne par fiche proposée. Sur la page
   des doublons : les deux fiches côte à côte, « Garder celle-ci » sous chacune. */
.fu-carte { border-color: var(--sem-attente); background: var(--sem-attente-bg); }
.fu-tete { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.fu-tete b { color: var(--sem-attente-t); font-size: 14px; }
.fu-ligne { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 10px 12px;
            background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--radius); }
.fu-ligne + .fu-ligne { margin-top: 8px; }
.fu-ligne form { margin: 0; }
.fu-ava { width: 34px; height: 34px; font-size: 12px; }
.fu-qui { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 160px; }
.fu-btn { border-color: var(--sem-attente); color: var(--sem-attente-t); }
.fu-n { display: inline-flex; align-items: center; justify-content: center; min-width: 20px; height: 20px;
        padding: 0 6px; margin-left: 4px; border-radius: 999px; background: var(--sem-attente);
        color: #fff; font-size: 11px; font-weight: 700; }
.fu-paire { position: relative; padding-top: 30px; }
.fu-motif { position: absolute; top: 10px; left: 14px; }
.fu-cotes { display: grid; grid-template-columns: 1fr auto 1fr; gap: 12px; align-items: stretch; }
.fu-vs { align-self: center; font-size: 20px; color: var(--muted); }
.fu-fiche { display: flex; flex-direction: column; justify-content: space-between; gap: 10px; padding: 12px;
            border: 1px solid var(--hairline); border-radius: var(--radius); background: var(--surface); }
.fu-fiche-tete { display: flex; gap: 10px; align-items: flex-start; }
.fu-fiche-pied { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.fu-fiche-pied form { margin: 0; }
.fu-pas { margin: 10px 0 0; display: flex; justify-content: center; }
@media (max-width: 720px) { .fu-cotes { grid-template-columns: 1fr; } .fu-vs { display: none; } }

/* ---- Supprimer une vente depuis le registre (12/10) ----
   Sur la même ligne que les tâches, une petite corbeille sans cadre : grise,
   rouge au survol. Éteinte (très pâle, raison au survol) quand la vente ne
   peut pas partir. */
.tache-cell { white-space: nowrap; }
.tache-cell .tache-mini { display: inline-flex; vertical-align: middle; }
.sl-suppr { display: inline-flex; margin: 0; vertical-align: middle; }
.sl-suppr-btn { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px;
                margin-left: 6px; border: 0; border-radius: 6px; background: none; padding: 0;
                color: var(--muted); cursor: pointer; vertical-align: middle; opacity: 0;
                transition: opacity .12s, color .12s, background .12s; }
.sl-suppr .sl-suppr-btn { margin-left: 6px; }
/* Invisible tant qu'on n'est pas sur SA ligne (Adrián, 12/10). */
tr:hover .sl-suppr-btn, .sl-suppr-btn:focus-visible { opacity: .7; }
tr:hover .sl-suppr-btn.off { opacity: .25; }
.sl-suppr-btn:hover { opacity: 1 !important; color: var(--critical); background: var(--page); }
.sl-suppr-btn.off { cursor: not-allowed; }
.sl-suppr-btn.off:hover { opacity: .4 !important; color: var(--muted); background: none; }

/* HH-2855 — un souci de delivery là où on règle listes et modèles :
   la même terre cuite que l'alerte, en petit. */
.souci-pill { display: inline-flex; align-items: center; gap: 5px; align-self: center; white-space: nowrap;
              font-size: 11px; font-weight: 650; font-style: normal; line-height: 1.5;
              color: #8f2020; background: #fbe4e4; border: 1px solid #f2bcbc;
              border-radius: 999px; padding: 1px 8px; }
.souci-pill::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.lb-corps .souci-pill { margin-top: 4px; align-self: flex-start; }
.souci-point { display: inline-flex; align-items: center; justify-content: center; flex: none;
               min-width: 16px; height: 16px; padding: 0 4px; border-radius: 999px;
               font-size: 10px; font-weight: 700; color: #fff; background: #c0392b; }

/* Rembourser un paiement — le récapitulatif avant de retaper le montant (13/10). */
.rb-recap { border: 1px solid var(--hairline); border-radius: 12px; padding: 16px 18px; background: var(--page); }
.rb-recap-titre { font-size: 12px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.rb-recap-montant { font-size: 30px; font-weight: 650; font-variant-numeric: tabular-nums; margin: 2px 0 10px; color: var(--critical); }
.rb-recap dl { display: grid; grid-template-columns: max-content 1fr; gap: 4px 14px; margin: 0; font-size: 13.5px; }
.rb-recap dt { color: var(--muted); }
.rb-recap dd { margin: 0; }
.rb-recap-avert { margin: 12px 0 0; font-size: 13px; color: var(--critical); }
.rb-confirmer .rb-retape { margin-top: 14px; width: 260px; max-width: 100%; }
.rb-confirmer .av-pied { margin-top: 14px; }

/* Fiche d'une personne suivie par quelqu'un d'autre (HH-2841, 14/10). */
.hp-carte { max-width: 460px; margin: 64px auto; text-align: center; background: var(--surface, #fff);
            border: 1px solid var(--hairline); border-radius: 16px; padding: 36px 40px; box-shadow: var(--shadow); }
.hp-ico { font-size: 28px; margin-bottom: 8px; }
.hp-carte h1 { font-size: 19px; margin: 0 0 8px; text-wrap: balance; }
.hp-carte p { color: var(--muted); font-size: 13.5px; margin: 0 0 20px; }

/* Fiche d'une offre : les sessions qu'elle comprend (15/10). */
.prod-sessions { display: grid; gap: 6px; margin-top: 4px; padding-top: 10px; border-top: 1px dashed var(--hairline); }
.prod-sessions-t { font-size: 13px; font-weight: 600; }
.prod-sessions .evo-filtre { margin-bottom: 0; }
.prod-sessions .evo-liste { max-height: 180px; }
/* Le filtre des listes d'offres / de sessions : un champ comme les autres. */
.evo-filtre {
  font-family: inherit; font-size: 13.5px; color: var(--ink);
  border: 1px solid var(--hairline); border-radius: 9px; padding: 7px 10px;
  background: var(--surface); transition: border-color .15s, box-shadow .15s;
}

/* Fenêtre de facture : à qui l'adresser, quand une structure apparaît (16/10). */
.inv-dest { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; margin: 4px 0 10px; font-size: 13px; }
.inv-dest-t { font-size: 12px; font-weight: 600; color: var(--ink-2); }
.inv-dest-o { display: inline-flex; align-items: center; gap: 5px; padding: 4px 9px; border: 1px solid var(--hairline); border-radius: 999px; cursor: pointer; }
.inv-dest-o:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); }
