  /* ── Page layout ─────────────────────────────────────────── */
  .content { background: var(--surface-soft); padding: 0 !important; }
  /* Fond de la page · réglage commun, remonté ici depuis projets.css où il
     s'appliquait déjà à tous les tableaux sans le dire. */
  body.has-layout { background: var(--surface-soft); }

  /* Contient le débordement horizontal de `.kanban-scroll`, qui déborde
     volontairement de 32px de chaque côté (marge négative + padding) pour que
     les cartes puissent défiler bord à bord. Sans ça, ce débordement élargit le
     document et fait apparaître une barre horizontale sur la PAGE.
     Vérifié : #kanban-area a bien un scrollWidth supérieur à son clientWidth.

     Le commentaire d'origine (dans projets.css) parlait d'une hauteur posée par
     JS (`sizeBoard`) et d'un défilement DANS chaque colonne · les deux ont été
     retirés par d33ebb0, la zone garde sa hauteur naturelle et c'est la PAGE
     qui défile. Ne PAS y remettre de hauteur ni d'overflow-y : les cartes du
     bas d'une colonne redeviendraient inatteignables. */
  #kanban-area { overflow: hidden; }
  .pipeline-wrap { padding: var(--space-lg) var(--space-xl) var(--space-xxl); }

  /* ── Header ──────────────────────────────────────────────── */
  .page-header {
    display: flex; align-items: center; justify-content: space-between;
    flex-wrap: wrap; gap: var(--space-base);
    margin-bottom: var(--space-lg);
  }
  .page-header h1 {
    font-size: var(--text-h1); font-weight: var(--weight-semibold); letter-spacing: -0.3px;
    color: var(--ink); margin: 0;
  }
  .header-right { display: flex; align-items: center; gap: var(--space-xs); }

  /* ── Navigation pills (5 sections) ──────────────────────── */
  .stage-nav {
    display: flex; gap: 6px; flex-wrap: wrap;
    margin-bottom: var(--space-lg);
  }
  .stage-nav a {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 8px 16px; border-radius: var(--r-pill);
    font-size: 13px; font-weight: 500; text-decoration: none;
    border: 1px solid var(--hairline);
    background: var(--canvas); color: var(--body);
    transition: all 0.15s;
  }
  .stage-nav a:hover { border-color: var(--primary); color: var(--primary); }
  .stage-nav a.active {
    background: var(--primary); border-color: var(--primary);
    color: #fff; font-weight: 600;
  }
  .stage-nav a .count {
    background: rgba(255,255,255,0.25); border-radius: var(--r-pill);
    padding: 1px 7px; font-size: 11px; font-family: var(--font-display);
    font-variant-numeric: tabular-nums;
    min-width: 20px; text-align: center;
  }
  .stage-nav a:not(.active) .count {
    background: var(--surface-strong); color: var(--muted);
  }

  /* ── Filtres ─────────────────────────────────────────────── */
  .filters-bar {
    display: flex; align-items: center; gap: var(--space-xs);
    flex-wrap: wrap; margin-bottom: var(--space-base);
  }
  .filters-bar input, .filters-bar select {
    height: 36px; padding: 0 12px; border-radius: var(--r-pill);
    border: 1px solid var(--hairline); background: var(--canvas);
    font-size: 13px; font-family: inherit; color: var(--ink);
    outline: none; transition: border-color 0.15s;
  }
  .filters-bar input { min-width: 220px; }
  .filters-bar input:focus,
  .filters-bar select:focus { border-color: var(--primary); }
  .filters-bar select { cursor: pointer; }
  /* Pattern unifie · recherche dans un pill (meme look que tous les
     autres tableaux · projets, production, termine, annulees). */
  .search-group {
    display: flex; align-items: center;
    flex: 1; max-width: 560px;
    height: 47px; padding-right: 5px;
    border: 1px solid var(--hairline); border-radius: var(--r-pill);
    background: var(--canvas);
    transition: border-color 0.15s;
  }
  .search-group:focus-within { border-color: var(--primary); }

  /* CRÉER · un objet À PART de la recherche, et qui se voit comme l'action
     principale du tableau (l'action principale est le noir · DESIGN.md).
     La marge le décolle franchement de la pastille de recherche : les mettre
     côte à côte sans respiration les faisait lire comme un seul outil. */
  .btn-nouvelle-fiche {
    display: inline-flex; align-items: center; gap: 6px;
    height: 40px; padding: 0 16px;
    margin-left: var(--space-base);
    border-radius: var(--r-pill);
    background: var(--primary); color: var(--canvas);
    border: 1px solid var(--primary);
    font-size: var(--text-caption); font-weight: var(--weight-semibold);
    text-decoration: none; white-space: nowrap;
    transition: opacity 0.15s;
  }
  .btn-nouvelle-fiche:hover { opacity: 0.85; }
  .btn-nouvelle-fiche svg { width: 14px; height: 14px; flex-shrink: 0; }
  .search-group input[type="search"] {
    flex: 1; min-width: 0; height: 100%;
    border: none; background: transparent; outline: none;
    padding: 0 14px; font-size: 13px; font-family: inherit; color: var(--ink);
    border-radius: var(--r-pill);
  }

  /* ── État de chargement ──────────────────────────────────── */
  .loading-state {
    display: flex; align-items: center; gap: 10px;
    padding: var(--space-xl); color: var(--muted); font-size: 14px;
  }
  .loading-state svg { width: 18px; height: 18px; animation: spin 1s linear infinite; }
  @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }

  .empty-state {
    padding: var(--space-xxl) var(--space-xl);
    text-align: center; color: var(--muted);
  }
  .empty-state svg { width: 40px; height: 40px; opacity: 0.3; margin-bottom: var(--space-base); }
  .empty-state p { font-size: 14px; margin: 0 0 var(--space-base); }

  /* ── Kanban ──────────────────────────────────────────────── */
  /* La zone scroll horizontalement (entre les colonnes) tout en restant
     dans la fenetre · evite que la scrollbar se retrouve cachee tout en bas. */
  .kanban-scroll {
    overflow-x: auto;
    overflow-y: hidden;
    /* Drag-to-pan : on indique a l'user qu'il peut "saisir" le tableau */
    cursor: grab;
    user-select: none;
    /* Scrollbar masquee · navigation se fait au drag */
    scrollbar-width: none;          /* Firefox */
    -ms-overflow-style: none;       /* IE/Edge */
  }
  .kanban-scroll::-webkit-scrollbar { display: none; }   /* Chrome/Safari */
  .kanban-scroll.dragging {
    cursor: grabbing;
    scroll-behavior: auto;
  }
  .kanban-scroll.dragging .fiche-card {
    pointer-events: none;
  }

  .kanban-board {
    display: flex; gap: 20px;
    min-width: max-content;
    align-items: flex-start;
  }

  /* Groupes de colonnes */
  .col-group { display: flex; flex-direction: column; gap: 8px; }
  .col-group-label {
    font-size: 13px; font-weight: 500;
    color: var(--muted); padding: 0 4px;
  }
  .col-group-cols { display: flex; gap: 10px; align-items: flex-start; }
  .col-group-divider {
    width: 1px; background: var(--hairline); align-self: stretch;
    margin: 20px 0; flex-shrink: 0;
  }
  .col-group-ferme .col-group-label { color: var(--muted-soft); }
  .col-group-ferme .kanban-col { opacity: 0.7; }
  .col-group-ferme .kanban-col:hover { opacity: 1; }

  /* Colonnes sans fond/bordure · juste un header texte au-dessus des cartes.
     Les cartes elles-memes gardent leur surface canvas + hairline. */
  .kanban-col {
    width: 300px; flex-shrink: 0;
    background: transparent;
    border: 0;
    border-radius: 0;
    overflow: visible;
  }
  .col-header {
    display: flex; align-items: center; justify-content: space-between;
    padding: 4px 4px 10px;
    border-bottom: 0;
  }
  .col-header-left { display: flex; align-items: center; gap: 8px; }
  .col-dot {
    width: 8px; height: 8px; border-radius: var(--r-full);
    flex-shrink: 0;
  }
  .col-label {
    font-size: 13px; font-weight: 500; color: var(--muted);
  }
  .col-count {
    font-size: 11px; font-family: var(--font-display);
    font-variant-numeric: tabular-nums;
    color: var(--muted); background: var(--surface-soft);
    border-radius: var(--r-pill); padding: 1px 7px;
  }
  .col-cards { padding: 0; display: flex; flex-direction: column; gap: 8px; min-height: 60px; }

  /* ── Carte COMPOSÉE · le socle partagé ──────────────────────
     Le look de `.demande-card` (renderer `default` du constructeur de carte)
     vivait jusqu'ici PAR FUITE : projets.css donnait la boîte, termine.css le
     padding, production.css la police des lignes, annulees.css la taille du
     titre. Un tableau composé héritait donc d'un patchwork de 4 feuilles, et
     la moindre retouche dans l'une d'elles le déplaçait ailleurs.

     Ces valeurs sont maintenant DÉCLARÉES ici, dans la feuille partagée. Elles
     reproduisent exactement ce que la cascade produisait avant (relevé au
     computed style, pas réécrit à vue), pour que rien ne bouge.
     Un tableau qui veut s'en écarter le fait sous `.board-<card>`. */
  .demande-card {
    background: var(--canvas);
    border: none;
    box-shadow: var(--shadow);
    border-radius: var(--r-lg);
    padding: var(--space-base);
    cursor: pointer;
    transition: box-shadow 0.15s, border-color 0.15s, transform 0.15s;
    text-decoration: none;
    color: inherit;
    display: block;
  }
  .demande-card:hover {
    box-shadow: var(--shadow-hover);
    border-color: var(--primary);
    transform: translateY(-1px);
  }
  /* Titre de la carte · l'ellipsis venait de projets.css, la taille et la
     hauteur de ligne d'annulees.css. Fusionné ici. */
  .card-name {
    font-size: var(--text-body); font-weight: 600; color: var(--ink);
    line-height: 1.3; margin-bottom: 2px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  /* Lignes sous le titre · taille et couleur d'annulees.css, marge de
     termine.css, police tabulaire de production.css. Fusionné ici. */
  .card-sub {
    font-size: 12px; color: var(--muted); margin-bottom: 12px;
    font-family: var(--font-display); font-variant-numeric: tabular-nums;
  }
  /* Mise en forme des lignes · pilotée par le CHAMP (assets/fiche-fields.js),
     jamais par un réglage de carte. */
  .card-sub-label { color: var(--muted-soft); margin-right: 4px; }
  /* Chiffres en JetBrains Mono + tabulaires · règle du design system
     (DESIGN.md « JetBrains Mono sur chaque chiffre »). `tabular-nums` seul ne
     suffit pas, il faut aussi la police mono. */
  .card-sub.is-num .card-sub-val {
    font-family: var(--font-mono); font-variant-numeric: tabular-nums;
    color: var(--body);
  }
  /* Ligne avec pictogramme · le texte s'aligne sur l'icône, pas sous elle. */
  .card-sub.has-icon { display: flex; align-items: center; gap: 6px; }
  .card-sub-icon {
    display: inline-flex; flex-shrink: 0;
    color: var(--muted-soft);
  }
  .card-sub-icon svg { width: 12px; height: 12px; display: block; }
  .card-sub.has-icon .card-sub-val { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* ── Carte fiche ─────────────────────────────────────────── */
  .fiche-card {
    background: var(--canvas);
    border: none;
    box-shadow: var(--shadow);
    border-radius: var(--r-lg);
    padding: 18px;
    cursor: pointer;
    transition: box-shadow 0.15s, border-color 0.15s;
    text-decoration: none;
    display: block;
  }
  .fiche-card:hover {
    box-shadow: var(--shadow-hover);
    border-color: var(--primary);
  }
  .card-address {
    font-size: var(--text-body); font-weight: 600; color: var(--ink);
    line-height: 1.3; margin-bottom: 8px; letter-spacing: -0.2px;
  }
  .card-client {
    font-size: 13px; color: var(--body); margin-bottom: 12px;
    display: flex; align-items: center; gap: 6px;
  }
  .card-client svg { width: 13px; height: 13px; color: var(--muted); flex-shrink: 0; }
  .card-chips { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 8px; }
  .chip-mini {
    font-size: var(--text-caption); padding: 2px 8px;
    border-radius: var(--r-pill);
    background: var(--surface-soft);
    color: var(--body);
    border: 1px solid var(--hairline-soft);
    white-space: nowrap;
  }
  .card-footer {
    display: flex; align-items: center; justify-content: space-between;
    font-size: 12px; color: var(--muted);
    border-top: 1px solid var(--hairline-soft);
    padding-top: 12px; margin-top: 12px;
  }
  .card-footer svg { width: 11px; height: 11px; }
  /* Badge bulle de commentaires (style Monday) sur les cartes du tableau */
  .card-updates {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 2px 6px;
    border-radius: var(--r-pill);
    font-size: var(--text-caption);
    font-weight: 600;
    line-height: 1;
    transition: background 0.15s;
  }
  .card-updates svg { width: 11px; height: 11px; flex-shrink: 0; }
  .card-updates-count { font-family: var(--font-display); font-variant-numeric: tabular-nums; }
  /* Variante recent · plus visible, primary bleue */
  .card-updates.recent {
    background: var(--primary);
    color: var(--on-primary);
  }
  /* Variante old · existe mais pas de nouveau · grise discrete */
  .card-updates.old {
    background: var(--surface-strong);
    color: var(--muted);
  }
  .card-age { font-family: var(--font-display); font-variant-numeric: tabular-nums; }
  .card-attach {
    width: 12px; height: 12px;
    color: var(--muted);
    flex-shrink: 0;
  }

  /* Ligne de détail dans la carte */
  .card-row {
    display: flex; align-items: flex-start; gap: 8px;
    font-size: 13px; color: var(--body);
    margin-bottom: 6px; line-height: 1.45;
  }
  .card-row svg { width: 13px; height: 13px; color: var(--muted); flex-shrink: 0; margin-top: 2px; }
  .card-row .mono { font-family: var(--font-mono); }

  /* Avatar rep */
  /* ===== QUI EST ASSIGNÉ · UN SEUL RENDU POUR LES TROIS TABLEAUX =====
     Voir `assigneHTML()` dans board/shared.js. Avant, chaque tableau avait sa
     propre pastille (ou pas de pastille du tout), sa propre couleur de nom, et
     son propre « Non assigné ». Une classe, une réponse.
     Les couleurs viennent des TOKENS · l'ancienne version codait #e3e5e8 et
     #5c616b en dur, donc elle ne suivait pas le mode sombre. */
  .card-assignee {
    display: inline-flex; align-items: center; gap: 6px;
    min-width: 0;
  }
  .card-assignee-pastille {
    position: relative;
    display: inline-flex; align-items: center; justify-content: center;
    width: 18px; height: 18px; border-radius: var(--r-full);
    background: var(--surface-strong); color: var(--body);
    font-size: var(--text-caption); font-weight: var(--weight-semibold);
    flex-shrink: 0;
  }
  /* Point vert plus petit pour ce mini-avatar */
  .card-assignee-pastille .presence-dot {
    width: 7px; height: 7px;
    border-width: 1.5px;
    bottom: -1px; right: -1px;
  }
  .card-assignee-nom {
    color: var(--ink); font-weight: 500;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .card-assignee-extra { color: var(--muted); flex-shrink: 0; }

  /* PERSONNE · le rond en pointillé dit « place à prendre », et le nom passe
     en gris italique. C'était le rendu des Leads · c'est maintenant celui de
     tout le monde. */
  .card-assignee.is-vide .card-assignee-pastille {
    background: none;
    border: 1px dashed var(--hairline);
  }
  .card-assignee.is-vide .card-assignee-nom {
    color: var(--muted-soft); font-weight: 400; font-style: italic;
  }

  /* Badge "Doublon" en haut a droite des cartes flaggees */
  .card-dup-badge {
    position: absolute;
    top: 8px; right: 8px;
    font-size: var(--text-caption); font-weight: 600;
    padding: 2px 8px;
    border-radius: var(--r-pill);
    background: rgba(244, 176, 0, 0.15);
    color: #b07a00;
    border: 1px solid rgba(244, 176, 0, 0.4);
    z-index: 1;
    white-space: nowrap;
  }
  .fiche-card.has-duplicate {
    border-left: 3px solid #f4b000;
  }
  .fiche-card.has-duplicate:hover .card-dup-badge {
    background: #fff8e6;
  }

  /* Bouton supprimer sur la carte */
  .fiche-card { position: relative; }
  .card-delete {
    position: absolute; top: 8px; right: 8px;
    width: 26px; height: 26px;
    border-radius: var(--r-full);
    border: none;
    background: transparent;
    color: var(--muted);
    display: flex; align-items: center; justify-content: center;
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.15s, background 0.15s, color 0.15s;
    z-index: 2;
  }
  .card-delete svg { width: 13px; height: 13px; pointer-events: none; }
  .fiche-card:hover .card-delete { opacity: 1; }
  .card-delete:hover { background: var(--semantic-down); color: #fff; opacity: 1 !important; }

  /* Colonne vide */
  .col-empty {
    padding: 16px 12px; text-align: center;
    font-size: 11px; color: var(--muted-soft);
  }

  /* ── Quick-add dans "À traiter" ──────────────────────────── */
  .quick-add-wrap {
    padding: 6px 8px 2px;
    border-bottom: 1px solid var(--hairline-soft);
  }
  .quick-add-input {
    width: 100%; box-sizing: border-box;
    background: var(--surface-soft);
    border: 1px solid var(--hairline);
    border-radius: var(--r-md);
    padding: 7px 10px;
    font-size: 12px; font-family: inherit; color: var(--ink);
    outline: none; transition: border-color 0.15s;
  }
  .quick-add-input:focus { border-color: var(--primary); background: var(--canvas); }
  .quick-add-input::placeholder { color: var(--muted-soft); }

  /* ── Col header : bouton + dans "À traiter" ─────────────── */
  .col-add-btn {
    width: 22px; height: 22px;
    border: none; background: transparent;
    color: var(--muted); cursor: pointer;
    border-radius: var(--r-full);
    display: flex; align-items: center; justify-content: center;
    transition: background 0.15s, color 0.15s;
    flex-shrink: 0;
  }
  .col-add-btn:hover { background: var(--primary); color: #fff; }
  .col-add-btn svg { width: 13px; height: 13px; pointer-events: none; }

  /* ── Toggle vue liste / kanban ───────────────────────────── */
  /* Toggle de vue (.view-toggle / .view-btn) · maintenant dans assets/styles.css (partagé) */

  /* ── Vue liste (table) ───────────────────────────────────── */
  .list-view { background: var(--canvas); border: none; box-shadow: var(--shadow); border-radius: var(--r-xl); overflow: hidden; }
  /* table-layout: fixed force chaque groupe a respecter les memes largeurs
     de colonnes · sinon chaque table calcule ses colonnes selon son contenu
     local et les colonnes ne s'alignent pas entre les groupes (Nouvelle
     demande vs 2e appel a faire, etc.) */
  .list-table { width: 100%; border-collapse: collapse; font-size: 13px; table-layout: fixed; }
  .list-table col.col-adresse { width: 22%; }
  .list-table col.col-client  { width: 14%; }
  .list-table col.col-tel     { width: 12%; }
  .list-table col.col-email   { width: 18%; }
  .list-table col.col-suivi   { width: 16%; }
  .list-table col.col-rep     { width: 12%; }
  .list-table col.col-date    { width:  6%; }
  /* En-têtes et cellules · valeurs EFFECTIVES consolidées ici (2026-07-22).
     Elles venaient d'annulees.css, qui les déclarait en `.list-table thead th`
     et `.list-table tbody td` · plus spécifique que le `.list-table th` écrit
     ici, donc c'est la feuille du tableau Annulés qui habillait la vue liste de
     TOUS les tableaux. Les trois copies identiques de projets/production/termine
     ne gagnaient jamais. Une seule source désormais. */
  .list-table th {
    font-size: 12px; font-weight: 500; color: var(--muted);
    padding: 10px var(--space-lg); text-align: left;
    border-bottom: 1px solid var(--hairline);
    white-space: nowrap;
    /* Fond blanc · annulees.css (le gagnant sur les autres propriétés) ne le
       déclarait PAS : il venait des copies `.list-table th` de
       projets/production/termine. La cascade se fait propriété par propriété,
       un « perdant » peut donc rester porteur sur une propriété que le gagnant
       ignore. Écart attrapé par la comparaison avant/après. */
    background: var(--canvas);
  }
  .list-table td {
    padding: 12px var(--space-lg);
    border-bottom: 1px solid var(--hairline-soft);
    color: var(--body);
    vertical-align: middle;
  }
  /* Chiffres des tableaux · mono + tabulaire (règle du design system).
     Composite de DEUX feuilles : termine.css gagnait la police, la taille et la
     couleur, mais ne déclarait pas `font-variant-numeric` · c'est
     production.css (perdante sur le reste) qui fournissait le tabulaire. */
  .list-table .td-mono {
    font-family: var(--font-mono); font-size: 12px; color: var(--muted);
    font-variant-numeric: tabular-nums;
  }
  /* Cellules tronquées · va de pair avec `table-layout: fixed`. Venait aussi de
     projets.css, où cette règle habillait la liste de tous les tableaux. */
  .list-table th, .list-table td {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .list-table tbody tr:last-child td { border-bottom: none; }
  .list-table tbody tr { cursor: pointer; transition: background 0.1s; }
  .list-table tbody tr:hover { background: var(--surface-soft); }
  /* Survol posé aussi sur la CELLULE · venait de projets.css et s'appliquait à
     tous les tableaux. Conservé tel quel : le survol n'est pas mesurable par la
     sonde, on ne parie pas sur son équivalence avec la règle de rangée. */
  .list-table tbody tr:hover td { background: var(--surface-soft); }
  .list-table .td-adresse { font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .list-table .td-client { color: var(--ink); font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .list-table .td-tel    { color: var(--body); font-family: var(--font-mono); font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .list-table .td-email  { color: var(--body); font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .list-table .td-status { white-space: nowrap; }
  .list-table .td-age { font-family: var(--font-display); font-variant-numeric: tabular-nums; color: var(--muted); white-space: nowrap; }
  .list-status-dot { width: 7px; height: 7px; border-radius: var(--r-full); display: inline-block; margin-right: 6px; vertical-align: middle; }
  .list-chips { display: flex; flex-wrap: wrap; gap: 3px; }

  /* Drag & drop retiré · le statut suit uniquement le workflow. */
  .fiche-card.dragging { opacity: 0.35; pointer-events: none; }
  .kanban-col.drag-over { outline: 2px solid var(--primary); outline-offset: -2px; background: var(--primary-soft); }

  /* ── Groupes dans la vue liste ───────────────────────────── */
  .list-group {
    border: none;
    box-shadow: var(--shadow);
    border-radius: var(--r-xl);
    overflow: hidden;
    margin-bottom: var(--space-base);
    background: var(--canvas);
  }
  /* Wrapper qui permet le scroll horizontal sur mobile pour voir
     toutes les colonnes du tableau · sinon les cellules se compriment
     et tout devient illisible. Scrollbar masquee pour rester epure. */
  .list-table-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;          /* Firefox */
    -ms-overflow-style: none;       /* IE/Edge legacy */
  }
  .list-table-scroll::-webkit-scrollbar { display: none; } /* Chrome/Safari/Edge */
  /* Sur mobile : taille minimum de la table pour preserver la lisibilite
     des colonnes · l'user scrolle horizontalement avec le doigt. */
  @media (max-width: 768px) {
    .list-table { min-width: 900px; }
  }
  .list-group:last-child { margin-bottom: 0; }
  .list-group-head {
    display: flex; align-items: center; gap: 8px;
    padding: 10px 14px 8px;
    border-bottom: 1px solid var(--hairline-soft);
    background: var(--surface-soft);
  }
  .list-group-dot { width: 7px; height: 7px; border-radius: var(--r-full); flex-shrink: 0; }
  .list-group-label { font-size: 13px; font-weight: 500; color: var(--ink); }
  .list-group-count { font-size: 11px; font-family: var(--font-display); font-variant-numeric: tabular-nums; color: var(--muted); margin-left: auto; }

  /* Liens téléphone / courriel */
  /* Tel + courriel · simple texte (non cliquables). Le clic sur la carte
     ou la rangee ouvre la fiche · plus de href tel:/mailto: qui
     intercepteraient. Pas de hover · ce sont juste des libelles. */
  .card-contact-link, .contact-link {
    color: inherit; text-decoration: none;
  }

  /* ═══ LA PASTILLE DE CARTE · une seule, pour tout ce qu'une carte annonce ══
     Il y en avait DEUX (`.card-wf` et `.card-reminder`) qui portaient la même
     sorte d'information sans se ressembler : 4px contre 7px de hauteur
     intérieure, 11px contre 12px de texte, --r-sm contre --r-md, avec bordure
     contre sans, un EMOJI en couleur contre une icône dessinée au trait, et
     un délai à droite d'un côté seulement.
     Sur une même colonne, une carte montrait donc un téléphone au trait et sa
     voisine un téléphone en couleur, dans deux boîtes de hauteurs différentes.

     Il n'en reste qu'une, faite de trois morceaux TOUJOURS les mêmes :
     [icône au trait] [libellé] [délai facultatif, à droite].
     Une pastille sans délai a exactement la hauteur d'une pastille qui en a. */
  .card-pill {
    display: flex; align-items: center; gap: 6px;
    margin-top: 8px;
    padding: 7px 11px;
    border-radius: var(--r-md);
    background: var(--surface-soft);
    font-size: var(--text-caption);
    line-height: 1.3;
    color: var(--body);
  }
  .card-pill svg { width: 13px; height: 13px; color: var(--muted); flex-shrink: 0; }
  .card-pill-label {
    font-weight: 600; min-width: 0;
    /* UNE SEULE LIGNE, TOUJOURS · c'est ce qui garantit que deux
       pastilles voisines ont la même hauteur quoi qu'on écrive dedans.
       Sans ça, un libellé un peu long repassait à la ligne et cette
       carte-là devenait plus haute que ses voisines. */
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .card-pill .when {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: var(--text-caption);
    color: var(--muted);
    margin-left: auto;
    padding-left: var(--space-xs);
    flex-shrink: 0;
  }

  /* ── Les degrés d'urgence ─────────────────────────────────────
     ⚠ Les teintes étaient écrites EN DUR (#fff1f0, #fffbeb, #b07a00) et l'une
     appelait un token inexistant derrière un repli, `var(--err-soft, #fde8e8)`,
     ce qui la rendait invisible au contrôle des tokens. Tout passe par les
     tokens sémantiques · ils portent le SENS (retard, attention), jamais la
     marque, et ils suivent le mode sombre. */
  .card-pill.overdue,
  .card-pill.urgent {
    background: var(--semantic-down-soft);
    color: var(--semantic-down);
  }
  .card-pill.overdue svg, .card-pill.overdue .when,
  .card-pill.urgent  svg, .card-pill.urgent  .when { color: var(--semantic-down); }

  .card-pill.today,
  .card-pill.warn { background: var(--semantic-warn-soft); }
  .card-pill.today svg, .card-pill.today .when,
  .card-pill.warn  svg, .card-pill.warn  .when { color: var(--semantic-warn-ink); }

  .card-pill.ok { background: var(--primary-soft); }
  .card-pill.ok svg { color: var(--primary); }

  .card-pill.upcoming svg { color: var(--primary); }
  .card-pill.closed { opacity: 0.55; }

  @media (max-width: 768px) {
    .pipeline-wrap { padding: var(--space-base); }
    .filters-bar input { min-width: 160px; }
  }

/* ============================================================
   Édition de colonnes EN CONTEXTE (admin) · mécanisme partagé
   assets/board-columns.js. Poignée de glissement, renommage en place,
   réordonnancement fluide (SortableJS), bouton « + colonne ».
   ============================================================ */
.col-label-editable { cursor: pointer; border-radius: var(--r-md); padding: 3px 8px; margin: -3px -8px; }
.col-label-editable:hover { background: var(--surface-strong); }
.col-label-editing {
  cursor: text; color: var(--ink);
  background: var(--canvas);
  outline: none;
  box-shadow: 0 0 0 1px var(--hairline);
}
.col-grip {
  cursor: grab; color: var(--muted-soft);
  font-size: 14px; line-height: 1; letter-spacing: -2px;
  padding-right: 2px; user-select: none;
  opacity: 0.5; transition: opacity 0.15s, color 0.15s;
}
.col-grip:hover { opacity: 1; color: var(--ink); }
.kanban-col.col-ghost { opacity: 0.35; background: var(--surface-strong); border-radius: var(--r-lg); }
.kanban-col.col-ghost > * { visibility: hidden; }
.kanban-col.col-chosen { cursor: grabbing; }
.btn-add-col {
  flex-shrink: 0; margin-left: var(--space-xs);
  display: inline-flex; align-items: center; gap: 5px;
  height: 44px; padding: 0 16px;
  background: var(--canvas); color: var(--body);
  border: 1px solid var(--hairline); border-radius: var(--r-pill);
  font-size: var(--text-label); white-space: nowrap;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}
.btn-add-col:hover { border-color: var(--ink); color: var(--ink); }
.btn-add-col-plus { font-size: 16px; line-height: 1; }
