  /* ============================================================
     FICHE PROJET
     ============================================================

     UNE SEULE FEUILLE POUR LES 7 ONGLETS · tranché le 2026-07-22 après
     mesure (ménage de fin du Chantier 3). Les onglets de la fiche sont des
     modules autonomes (fiche-tabs/), mais leur CSS reste ICI.

     Pourquoi pas une feuille par onglet · une feuille chargée avec son onglet
     DISPARAÎT avec lui, et 18 classes sont posées par plusieurs onglets :
     `.suivi-list` / `.suivi-card` / `.panel-grid-2` (Suivi + Sous-traitants),
     les `.livr-comment*` (Suivi + Documents), `.ident-grid` / `.ident-label`
     (Suivi + Infos client). Éteindre Suivi aurait déshabillé Sous-traitants.
     Et là où les 5 feuilles de tableau se battaient vraiment (22 sélecteurs en
     conflit, deux tableaux qui vivaient d'une fuite), il n'y a ici qu'UNE
     feuille · aucune guerre de cascade n'existe. Découper l'aurait créée.

     LA CONVENTION · l'isolation passe par un PRÉFIXE DE CLASSE, pas par un
     fichier. Une classe qui appartient à un onglet porte son préfixe :

       documents     doc- docs- permis- photo- upload- heic- pdf-
       history       hist- history- timeline-
       infos-client  ic- infos- client- billing-
       production    prod- facture- kpi-prod
       soustraitants st- sst- soustrait
       suivi         suivi- wf- livr- etiq- check- stage- day- preset-
       updates       upd- update- mention-

     Une classe posée par PLUSIEURS onglets appartient au socle de la fiche ·
     c'est une décision à assumer, pas un accident : elle se déclare dans
     `SOCLE_PARTAGE` de fiche-tabs/verifier-modules.mjs.

     JAMAIS DE NOM NU (règle CLAUDE.md) · `.card`, `.modal`, `.btn-primary`
     existent déjà dans assets/styles.css, un nom nu les écrase. 49 classes
     nues traînent encore ici : elles NE se renomment PAS en bloc (mesuré, une
     seule se cogne aujourd'hui avec le design system, et payer un coût réel
     contre un risque hypothétique est un mauvais marché). On les préfixe AU
     PASSAGE · quand on touche l'une d'elles pour une autre raison, on la
     préfixe et on la retire de `NUES_CONNUES`. Le compte baisse tout seul,
     sans big-bang et sans preuve de non-régression à refaire.

     Le contrôle : `node fiche-tabs/verifier-modules.mjs`
       ÉCHEC         une classe devient partagée sans passer par le socle
       AVERTISSEMENT une classe NUE neuve entre dans le fichier
     ============================================================ */

  .content { background: var(--surface-soft); padding: 0 !important; }
  .fiche-wrap { max-width: none; margin: 0 auto; padding: var(--space-lg) var(--space-xl) var(--space-xxl); }

  /* ---------- Header de la fiche ---------- */
  .back-link {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: 13px; color: var(--muted);
    margin-bottom: var(--space-base);
    cursor: pointer;
  }
  .back-link:hover { color: var(--ink); }

  .header-card {
    background: var(--canvas);
    border: 1px solid var(--hairline);
    border-radius: var(--r-xl);
    padding: var(--space-lg) var(--space-xl);
    margin-bottom: var(--space-base);
  }
  .title-row {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: var(--space-base); flex-wrap: wrap;
  }
  .meta-line {
    display: flex; align-items: center; gap: var(--space-sm);
    margin-bottom: var(--space-xs);
    font-size: 12px; color: var(--muted);
  }
  .project-number { font-family: var(--font-mono); font-weight: 600; color: var(--ink); letter-spacing: 0.02em; }
  /* LE NUMÉRO DE DOSSIER · un CHAMP, dessiné comme le texte qu'il remplace
     (db/194). Il s'affichait en lecture seule et n'était saisissable nulle
     part · « ça prend une place pour écrire un numéro ». La case reste
     invisible tant qu'on n'y touche pas : elle ne doit pas ressembler à un
     formulaire posé dans un en-tête. */
  .project-number-input {
    font-family: var(--font-mono); font-weight: 600; color: var(--ink);
    letter-spacing: 0.02em; font-size: inherit;
    background: transparent; border: 1px solid transparent;
    /* ⚠ PAS DE LARGEUR FIXE · elle était de 14ch, donc « + N° de soumission »
       sortait coupé (« + N° de soumissi »). La largeur se règle en JS avec
       l'attribut `size`, sur le plus long du repère ou de la valeur · un mot
       choisi par le client n'a pas de longueur prévisible. */
    border-radius: var(--r-sm); padding: 2px 6px; min-width: 0;
  }
  /* ⚠ LE VIDE NE DOIT PAS RESSEMBLER À UNE VALEUR. Le repère était en mono,
     même taille, même graisse que le numéro · un client a tapé un chiffre dans
     le champ du MOT (côté admin) et toutes ses fiches se sont mises à afficher
     ce chiffre en gris. Elles n'en portaient aucun · c'était le repère.
     Il prend donc la police du CORPS, jamais la mono. Le numéro est en mono,
     l'invitation ne l'est pas · on les distingue sans les lire. */
  .project-number-input::placeholder {
    color: var(--muted); font-weight: 400;
    font-family: var(--font-body); letter-spacing: 0;
  }
  .project-number-input:hover { border-color: var(--hairline); }
  .project-number-input:focus {
    outline: none; border-color: var(--ink); background: var(--canvas);
  }
  .project-title { font-size: var(--text-h1); font-weight: var(--weight-semibold); line-height: 1.1; letter-spacing: -0.5px; margin-bottom: 4px; }
  .project-address { font-size: 14px; color: var(--body); }



  /* Statut pill */
  .status-pill {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: 11px; font-weight: 600;
    padding: 4px 10px; border-radius: var(--r-pill);
    text-transform: uppercase; letter-spacing: 0.05em;
    background: var(--surface-strong);
    color: var(--ink);
  }
  .status-pill .dot { width: 6px; height: 6px; border-radius: var(--r-full); background: var(--muted); }
  .status-pill.production .dot { background: var(--semantic-up); }
  .status-pill.production { color: var(--semantic-up); }
  .status-pill.warning    .dot { background: var(--accent-yellow); }
  .status-pill.warning    { color: var(--accent-yellow); }

  /* Secteur · pill éditable inline dans le header, à côté du PO.
     Auto-saved via data-field="sector". 3 états visuels : vide (gris,
     warning), Commercial (bleu doux), Résidentiel (jaune doux). */
  /* ---------- La pastille d'ÉTIQUETTE (db/193) ----------
     Elle s'appelait .sector-header-pill et portait DEUX couleurs en dur, une
     par valeur de CAM, plus un chevron SVG dont la couleur était écrite dans
     l'URL encodée. Impossible d'ajouter une valeur sans écrire du CSS.

     ⚠ ET AUCUNE COULEUR NE L'A REMPLACÉE. Un jet intermédiaire donnait une
     teinte à choisir par étiquette · refusé : « je ne veux pas de couleurs, je
     veux que ça reste dans mon thème ». Le design system est quasi-monochrome,
     le contraste noir/blanc EST l'accent. La pastille prend donc les mêmes
     tokens que le reste · une étiquette se lit par son MOT, pas par sa teinte.

     Le chevron prend `currentColor` · il suit le thème tout seul, au lieu
     d'être un SVG par couleur. */
  .etiquette-pill {
    display: inline-flex; align-items: center;
    font-family: var(--font-body);
    font-size: 11px; font-weight: 600;
    padding: 4px 24px 4px 10px;
    border-radius: var(--r-pill);
    border: none; outline: none;
    text-transform: uppercase; letter-spacing: 0.05em;
    appearance: none;
    background: var(--surface-strong) no-repeat right 8px center;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10'><path d='M2 3.5l3 3 3-3' stroke='currentColor' stroke-width='1.4' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>");
    background-size: 10px;
    color: var(--ink);
    cursor: pointer;
    max-width: 220px;
  }
  /* Sans étiquette · en retrait, pour ne pas peser autant qu'une vraie valeur. */
  .etiquette-pill:not([data-pose]) { background-color: transparent; color: var(--muted); }
  .etiquette-pill:hover { color: var(--ink); }

  .header-actions { display: flex; gap: var(--space-xs); flex-shrink: 0; }
  .header-actions .btn { height: 38px; padding: 0 16px; font-size: 13px; }

  /* Page actions · barre au-dessus du header-card. Back-link a gauche, actions a droite.
     Toujours sur sa propre ligne, ne wrap jamais avec le titre / adresse. */
  .page-actions {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--space-base);
    margin-bottom: var(--space-base);
    flex-wrap: wrap;
  }
  .page-actions-right {
    display: flex; gap: var(--space-xs); flex-shrink: 0;
    flex-wrap: wrap;
  }
  .page-actions-right .btn { height: 36px; padding: 0 14px; font-size: 13px; }
  /* Bouton retour · rond noir avec chevron blanc vers la gauche (matche le
     systeme de pills noir). Le label (vers quel tableau) est dans le title. */
  .page-back-link {
    display: inline-flex; align-items: center; justify-content: center;
    width: 36px; height: 36px; padding: 0;
    border-radius: var(--r-full);
    background: var(--ink); color: var(--canvas);
    border: none;
    text-decoration: none; cursor: pointer;
    transition: opacity 0.15s, transform 0.08s;
    flex-shrink: 0;
  }
  .page-back-link:hover { opacity: 0.88; }
  .page-back-link:active { transform: scale(0.95); }
  .page-back-link svg { width: 16px; height: 16px; }

  /* Rangee localisation (header) · chip temps de trajet + bouton Street View */
  .fiche-loc-row {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    margin-top: 10px;
  }
  /* Chip · temps de trajet bureau -> chantier (header, toutes les phases) */
  .office-drive-chip {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 10px;
    background: var(--surface-soft);
    border: 1px solid var(--hairline);
    border-radius: var(--r-pill);
    font-size: 12px; color: var(--body);
    width: fit-content;
  }
  /* Bouton immeuble · ouvre la facade dans Google Street View · meme hauteur
     que le chip de trajet (~24px), un peu plus petit qu avant */
  .streetview-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 24px; height: 24px;
    background: var(--surface-soft);
    border: 1px solid var(--hairline);
    border-radius: var(--r-full);
    color: var(--muted);
    cursor: pointer; flex-shrink: 0; text-decoration: none;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
  }
  .streetview-btn:hover { background: var(--primary-soft); color: var(--primary); border-color: var(--primary); }
  .streetview-btn svg { width: 13px; height: 13px; }
  .office-drive-chip svg { width: 14px; height: 14px; color: var(--muted); flex-shrink: 0; }
  .office-drive-chip .odc-val { font-family: var(--font-mono); font-weight: 600; color: var(--ink); }
  .office-drive-chip .odc-sep,
  .office-drive-chip .odc-muted { color: var(--muted-soft); }

  /* ---------- KPI Strip (cockpit) ---------- */
  .kpi-strip {
    /* UNE colonne par carte RÉELLEMENT présente · pas quatre en dur.
       Le nombre de cartes est de la DONNÉE depuis db/192 (tableaux.kpis · le
       client coche ce qu'il veut, tableau par tableau) et se réduit encore
       selon les modules achetés. Avec repeat(4, 1fr), les pistes vides
       laissaient un grand bloc gris (le fond du bandeau qui transparaît) · un
       trou, exactement ce qu'on voulait éviter. grid-auto-flow ne crée de
       piste que pour les enfants affichés · le bandeau se reforme tout seul,
       de 1 à N cartes. */
    display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
    gap: 1px;
    background: var(--hairline);
    border: 1px solid var(--hairline);
    border-radius: var(--r-lg);
    margin-top: var(--space-lg);
    overflow: hidden;
  }
  .kpi-card {
    background: var(--canvas);
    padding: var(--space-base) var(--space-lg);
    display: flex; flex-direction: column; gap: 2px;
  }
  .kpi-label { font-size: var(--text-caption); font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; }
  .kpi-value { font-family: var(--font-mono); font-size: var(--text-display); font-weight: 600; color: var(--ink); letter-spacing: -0.01em; }
  .kpi-sub   { font-family: var(--font-mono); font-size: 11px; color: var(--muted); margin-top: 2px; }
  .kpi-bar {
    height: 4px; background: var(--surface-strong); border-radius: var(--r-full);
    margin-top: var(--space-xs); overflow: hidden;
  }
  /* ⚠ `display: block` N'EST PAS DÉCORATIF · sans lui, un élément inline ignore
     `width` et `height`, et la barre se rend en 0x0. La couleur est calculée,
     la largeur est posée en style inline, la console est muette · et rien ne
     s'affiche. La règle a été écrite pour un `<div>` puis jamais exercée (elle
     dormait dans la feuille sans que rien ne la pose) ; le jour où on l'a
     branchée sur un `<span>`, elle est morte en silence. */
  .kpi-bar-fill { display: block; height: 100%; background: var(--primary); border-radius: var(--r-full); transition: width 0.2s; }
  .kpi-bar-fill.warn { background: var(--accent-yellow); }
  .kpi-bar-fill.down { background: var(--semantic-down); }
  .kpi-card.up   .kpi-value { color: var(--semantic-up); }
  .kpi-card.down .kpi-value { color: var(--semantic-down); }
  .kpi-card.warn .kpi-value { color: var(--accent-yellow); }

  /* ---------- Tabs ---------- */
  .tabs {
    display: flex; gap: 2px;
    background: var(--canvas);
    border: 1px solid var(--hairline);
    border-radius: var(--r-pill);
    padding: 4px;
    margin-bottom: var(--space-lg);
    overflow-x: auto;
    scrollbar-width: none;
  }
  .tabs::-webkit-scrollbar { display: none; }
  .tab-btn {
    flex-shrink: 0;
    background: transparent; border: none;
    font-family: var(--font-body); font-size: 13px; font-weight: 600;
    color: var(--muted);
    padding: 8px 16px; border-radius: var(--r-pill);
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
    white-space: nowrap;
  }
  .tab-btn:hover { color: var(--ink); }
  .tab-btn.active { background: var(--ink); color: var(--canvas); }
  .tab-btn .count {
    display: inline-block;
    margin-left: 6px;
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--muted-soft);
  }
  .tab-btn.active .count { color: var(--on-dark-soft); }
  /* Onglet pousse a droite (Mises a jour) · separer du reste */
  .tab-btn-right { margin-left: auto; }
  /* Look distinct pour signaler qu il y a des updates recents · bleu primary */
  .tab-btn-right.has-recent {
    background: var(--primary-soft);
    color: var(--primary);
  }
  .tab-btn-right.has-recent:hover { color: var(--primary); }
  .tab-btn-right.has-recent .count { color: var(--primary); }
  .tab-btn-right.has-recent.active { background: var(--primary); color: var(--on-primary); }
  .tab-btn-right.has-recent.active .count { color: var(--on-primary); opacity: 0.85; }
  /* Bulle SVG pleine rouge quand il y a des mentions non lues sur cette fiche.
     Une fois lues, la classe disparait · la bulle revient en outline blanc/gris (defaut). */
  #tab-btn-updates.has-unread-mentions .tab-updates-icon {
    color: var(--semantic-down);
    stroke: var(--semantic-down);
    fill: var(--semantic-down);
    fill-opacity: 1;
  }
  /* Onglet actif (selectionne, fond fonce) · garder la bulle visible en blanc. */
  #tab-btn-updates.has-unread-mentions.active .tab-updates-icon {
    color: var(--canvas);
    stroke: var(--canvas);
    fill: var(--canvas);
    fill-opacity: 1;
  }
  /* Sur mobile, retire margin-left:auto · les onglets scrollent horizontalement deja */
  @media (max-width: 640px) {
    .tab-btn-right { margin-left: 0; }
  }

  /* ---------- Panels ---------- */
  .tab-panel { display: none; }
  .tab-panel.active { display: block; }

  /* ---------- Grids communes ---------- */
  /* Onglet Suivi · 2 colonnes egales (avant: 2fr 1fr). Donne plus de place a la colonne
     de droite (client + description) pour que la description soit moins haute. */
  .panel-grid-2 {
    display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-base);
    align-items: start;
  }
  @media (max-width: 900px) {
    .panel-grid-2 { grid-template-columns: 1fr; }
  }

  /* ---------- Section card ---------- */
  .card {
    background: var(--canvas);
    border: 1px solid var(--hairline);
    border-radius: var(--r-xl);
    padding: var(--space-lg);
    margin-bottom: var(--space-base);
  }
  .card-head {
    display: flex; align-items: center; justify-content: space-between;
    margin-bottom: var(--space-base);
  }
  .card-title { font-size: var(--text-caption); font-weight: var(--weight-semibold); color: var(--ink); letter-spacing: -0.01em;  text-transform: uppercase;}
  .card-action {
    background: none; border: none;
    font-size: 12px; font-weight: 600;
    color: var(--primary); cursor: pointer;
    padding: 0;
  }
  .card-action:hover { color: var(--primary-active); }

  /* ---------- Calculator picker (Soumission tab) ---------- */
  .calc-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: var(--space-base);
    margin-top: var(--space-base);
  }
  .calc-card {
    display: block;
    background: var(--canvas);
    border: 1px solid var(--hairline);
    border-radius: var(--r-xl);
    padding: var(--space-lg);
    text-decoration: none;
    color: inherit;
    transition: border-color 0.15s, box-shadow 0.15s, transform 0.1s;
    position: relative;
  }
  a.calc-card { cursor: pointer; }
  /* Bouton 'Retour aux calculateurs' · au-dessus du calculateur actif. Style
     discret pill avec icone chevron, aligne a gauche. */
  .calc-back-btn {
    display: inline-flex; align-items: center; gap: 6px;
    margin-bottom: 12px;
    padding: 6px 14px;
    background: var(--surface-soft);
    border: 1px solid var(--hairline);
    color: var(--body);
    border-radius: var(--r-pill);
    font-family: inherit; font-size: 12px; font-weight: 600;
    cursor: pointer;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
  }
  .calc-back-btn:hover {
    background: var(--canvas);
    color: var(--primary);
    border-color: var(--primary);
  }
  a.calc-card:hover {
    border-color: var(--ink);
    box-shadow: var(--shadow-hover);
    transform: translateY(-1px);
  }
  .calc-card.disabled { opacity: 0.55; cursor: default; }
  .calc-card.disabled:hover { border-color: var(--hairline); box-shadow: none; transform: none; }
  /* Point bleu en haut a droite · indique qu un brouillon existe pour ce calculateur */
  .calc-dot {
    position: absolute;
    top: 12px; right: 12px;
    width: 10px; height: 10px;
    border-radius: var(--r-full);
    background: var(--primary);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 20%, transparent);
  }
  /* Variante bleue du status pill pour les calc avec brouillon */
  .calc-status.draft {
    color: var(--primary);
    background: var(--primary-soft);
  }
  .calc-icon {
    width: 40px; height: 40px;
    display: flex; align-items: center; justify-content: center;
    background: var(--surface-soft);
    border-radius: var(--r-md);
    margin-bottom: var(--space-sm);
  }
  .calc-icon svg { width: 20px; height: 20px; stroke: var(--ink); }
  .calc-card.disabled .calc-icon svg { stroke: var(--muted); }
  .calc-name {
    font-size: 14px; font-weight: 600;
    color: var(--ink);
    margin-bottom: 4px;
  }
  .calc-desc {
    font-size: 12px; line-height: 1.45;
    color: var(--muted);
  }
  .calc-status {
    display: inline-block;
    margin-top: var(--space-sm);
    font-size: var(--text-caption); font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.07em;
    color: var(--muted);
    padding: 3px 8px;
    background: var(--surface-soft);
    border-radius: var(--r-pill);
  }
  .calc-status.live {
    color: var(--semantic-up);
    background: color-mix(in srgb, var(--semantic-up) 12%, transparent);
  }

  /* ---------- Mises a jour (Updates style Monday) ---------- */
  .upd-composer {
    display: flex; gap: 12px;
    padding: var(--space-base);
  }
  .upd-avatar {
    position: relative;
    width: 36px; height: 36px;
    border-radius: var(--r-full);
    background: var(--surface-dark); color: var(--on-dark);
    font-size: 13px; font-weight: 600;
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
  }
  .upd-avatar.empty {
    background: var(--surface-soft);
    color: var(--muted);
  }
  .upd-composer-body {
    flex: 1;
    display: flex; flex-direction: column;
    gap: 8px;
  }
  .upd-textarea-wrap {
    position: relative;
  }
  .upd-textarea-wrap textarea {
    width: 100%;
    min-height: 60px;
    max-height: 240px;
    padding: 10px 14px;
    background: var(--input-bg);
    color: var(--ink);
    border: 1px solid var(--hairline);
    border-radius: var(--r-md);
    font-family: var(--font-body);
    font-size: 14px; line-height: 1.5;
    resize: vertical;
    outline: none;
    transition: border-color 0.15s;
  }
  .upd-textarea-wrap textarea:focus { border-color: var(--primary); }
  .upd-mention-dropdown {
    display: none;
    position: absolute;
    background: var(--canvas);
    border: 1px solid var(--hairline);
    border-radius: var(--r-md);
    box-shadow: var(--shadow-hover);
    min-width: 220px;
    max-height: 240px;
    overflow-y: auto;
    z-index: 100;
    padding: 4px 0;
  }
  .upd-mention-dropdown.open { display: block; }
  .upd-mention-item {
    display: flex; align-items: center; gap: 10px;
    padding: 8px 12px;
    cursor: pointer;
    font-size: 13px;
    transition: background 0.1s;
  }
  .upd-mention-item:hover, .upd-mention-item.active { background: var(--surface-soft); }
  .upd-mention-item .mini-avatar {
    width: 24px; height: 24px;
    border-radius: var(--r-full);
    background: var(--surface-dark); color: var(--on-dark);
    font-size: var(--text-caption); font-weight: 600;
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
  }
  .upd-composer-foot {
    display: flex; align-items: center; justify-content: space-between;
    gap: 8px;
  }
  .upd-toolbar {
    display: flex; gap: 4px;
  }
  .upd-toolbar-btn {
    width: 32px; height: 32px;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--r-full);
    cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    color: var(--muted);
    transition: background 0.12s, color 0.12s;
  }
  .upd-toolbar-btn:hover {
    background: var(--surface-soft);
    color: var(--ink);
  }
  .upd-toolbar-btn svg {
    width: 16px; height: 16px;
  }

  /* Chips de pièces jointes en attente (avant publication) */
  .upd-attachments-preview {
    display: none;
    flex-wrap: wrap;
    gap: 6px;
  }
  .upd-attachments-preview:not(:empty) { display: flex; }
  .upd-att-chip {
    display: inline-flex; align-items: center; gap: 8px;
    padding: 6px 10px 6px 8px;
    background: var(--surface-soft);
    border: 1px solid var(--hairline);
    border-radius: var(--r-pill);
    font-size: 12px; color: var(--ink);
    max-width: 240px;
  }
  .upd-att-chip.uploading {
    background: var(--primary-soft);
    border-color: var(--primary);
    color: var(--primary);
  }
  .upd-att-chip svg { width: 14px; height: 14px; flex-shrink: 0; color: var(--muted); }
  .upd-att-chip .name {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    max-width: 160px;
  }
  .upd-att-chip .remove {
    background: transparent; border: none;
    width: 16px; height: 16px;
    border-radius: var(--r-full);
    color: var(--muted);
    cursor: pointer; line-height: 1;
    display: flex; align-items: center; justify-content: center;
    font-size: 14px;
  }
  .upd-att-chip .remove:hover { background: var(--hairline); color: var(--semantic-down); }

  /* Pieces jointes affichees dans un commentaire publie */
  .upd-item-attachments {
    display: flex; flex-wrap: wrap; gap: 6px;
    margin-top: 8px;
  }
  .upd-item-attachments a {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 10px 4px 8px;
    background: var(--surface-soft);
    border: 1px solid var(--hairline);
    border-radius: var(--r-pill);
    font-size: 12px;
    color: var(--ink);
    text-decoration: none;
    transition: border-color 0.12s, background 0.12s;
  }
  .upd-item-attachments a:hover {
    border-color: var(--primary);
    background: var(--primary-soft);
  }
  .upd-item-attachments a svg {
    width: 13px; height: 13px;
    color: var(--muted);
  }
  .upd-item-attachments a:hover svg { color: var(--primary); }
  .upd-btn-post {
    height: 36px; padding: 0 18px;
    background: var(--primary); color: var(--on-primary);
    border: none; border-radius: var(--r-pill);
    font-size: 13px; font-weight: 600;
    cursor: pointer; transition: background 0.15s;
  }
  .upd-btn-post:hover { background: var(--primary-active); }
  .upd-btn-post:disabled {
    background: var(--primary-disabled);
    cursor: not-allowed;
  }

  /* Liste des mises a jour */
  .upd-item {
    background: var(--canvas);
    border: 1px solid var(--hairline);
    border-radius: var(--r-xl);
    padding: var(--space-base);
    margin-bottom: var(--space-sm);
    display: flex; gap: 12px;
  }
  .upd-item.mentioned-me {
    border-left: 3px solid var(--primary);
  }
  .upd-item-body {
    flex: 1;
    display: flex; flex-direction: column;
    gap: 4px;
    min-width: 0;
  }
  .upd-item-head {
    display: flex; align-items: baseline; gap: 8px;
    flex-wrap: wrap;
  }
  .upd-item-author {
    font-size: var(--text-body); font-weight: var(--weight-semibold);
    color: var(--ink);
  }
  .upd-item-time {
    font-size: 11px; color: var(--muted);
    font-family: var(--font-mono);
  }
  .upd-item-edited {
    font-size: 11px; color: var(--muted);
    font-style: italic;
  }
  .upd-item-content {
    font-size: 13px; line-height: 1.55;
    color: var(--ink);
    white-space: pre-wrap;
    word-wrap: break-word;
  }
  .upd-item-content .mention {
    color: var(--primary);
    font-weight: 600;
    background: var(--primary-soft);
    padding: 1px 6px;
    border-radius: var(--r-xs);
    text-decoration: none;
  }
  .upd-item-actions {
    display: flex; gap: 4px;
    margin-top: 4px;
  }
  .upd-item-action {
    background: transparent; border: none;
    color: var(--muted);
    font-size: 11px; font-weight: 500;
    cursor: pointer;
    padding: 2px 6px;
    border-radius: var(--r-sm);
  }
  .upd-item-action:hover { color: var(--ink); background: var(--surface-soft); }
  .upd-item-action.danger:hover { color: var(--semantic-down); }

  /* ---------- Threading (parent + réponses imbriquées) ----------
     Chaque niveau de .upd-replies ajoute sa propre indentation (margin-left).
     Donc une réponse à une réponse est plus indentée que sa réponse parente.
     Cap visuel implicite via le MAX_DEPTH = 3 dans le JS. */
  .upd-thread { margin-bottom: var(--space-base); }
  .upd-thread > .upd-item { margin-bottom: 0; }
  .upd-replies {
    margin-left: 20px; padding-left: 14px;
    border-left: 2px solid var(--hairline);
    margin-top: 6px;
    display: flex; flex-direction: column; gap: 6px;
  }
  .upd-replies .upd-item {
    border-radius: var(--r-lg);
    padding: 10px 12px;
    margin-bottom: 0;
    background: var(--surface-soft);
  }
  /* Réponses imbriquées (depth 2+) · fond légèrement différent pour distinguer */
  .upd-replies .upd-replies .upd-item {
    background: var(--canvas);
  }
  .upd-replies .upd-item .upd-avatar {
    width: 28px; height: 28px;
    font-size: 11px;
  }
  .upd-reply-composer {
    display: flex; gap: 10px;
    margin-left: 28px; padding-left: 16px;
    border-left: 2px solid var(--hairline);
    margin-top: 6px;
  }
  .upd-reply-composer-body { flex: 1; display: flex; flex-direction: column; gap: 6px; }
  .upd-reply-input {
    width: 100%;
    border: 1px solid var(--hairline);
    background: var(--input-bg);
    border-radius: var(--r-md);
    padding: 8px 12px;
    font-size: 13px; font-family: var(--font-body); color: var(--ink);
    outline: none; resize: none;
    transition: border-color 0.15s;
  }
  .upd-reply-input:focus { border-color: var(--primary); }
  .upd-reply-actions { display: flex; gap: 8px; justify-content: flex-end; }
  .upd-reply-cancel, .upd-reply-send {
    font-family: inherit; font-size: 12px; font-weight: 600;
    padding: 6px 14px; border-radius: var(--r-pill);
    border: 1px solid var(--hairline);
    background: transparent; color: var(--body);
    cursor: pointer;
    transition: all 0.15s;
  }
  .upd-reply-cancel:hover { border-color: var(--ink); color: var(--ink); }
  .upd-reply-send {
    background: var(--primary); color: var(--on-primary); border-color: var(--primary);
  }
  .upd-reply-send:hover { background: var(--primary-active); }
  .upd-reply-send:disabled { opacity: 0.5; cursor: not-allowed; }

  /* ---------- Modal generique Gestion ----------
     Suit DESIGN.md : carte canvas, hairline, rounded-xl, pas d'ombres,
     titres weight 400 avec letter-spacing negatif sur display, boutons pill. */
  .app-modal {
    position: fixed; inset: 0;
    background: color-mix(in srgb, var(--ink) 55%, transparent);
    z-index: 1000;
    align-items: center; justify-content: center;
    padding: var(--space-lg);
  }
  .app-modal[style*="display:none"] { display: none !important; }
  .app-modal[style*="display:flex"] { display: flex !important; }

  .app-modal-card {
    background: var(--canvas);
    border: 1px solid var(--hairline);
    border-radius: var(--r-xl);
    width: 100%; max-width: 480px;
    max-height: 90vh;
    display: flex; flex-direction: column;
    overflow: hidden;
  }
  .app-modal-head {
    padding: var(--space-xl) var(--space-xl) var(--space-base);
  }
  .app-modal-title {
    font-family: var(--font-display);
    font-size: var(--text-h2); font-weight: var(--weight-semibold);
    letter-spacing: -0.4px;
    color: var(--ink);
    line-height: 1.2;
    margin-bottom: var(--space-sm);
  }
  .app-modal-filename {
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--muted);
    word-break: break-all;
  }
  .app-modal-body {
    padding: 0 var(--space-xl) var(--space-base);
    overflow-y: auto;
  }
  .app-modal-foot {
    padding: var(--space-base) var(--space-xl) var(--space-xl);
    display: flex; justify-content: flex-end; gap: 8px;
  }

  /* Liste de categories : rangees minimales avec hairline-soft entre chacune,
     hover surface-soft, pas de bordures lourdes. */
  .app-cat-list {
    display: flex; flex-direction: column;
    border-top: 1px solid var(--hairline-soft);
  }
  .app-cat-row {
    display: flex; align-items: center; gap: var(--space-base);
    padding: 14px 6px;
    background: transparent;
    border: none;
    border-bottom: 1px solid var(--hairline-soft);
    cursor: pointer;
    text-align: left;
    width: 100%;
    transition: background 0.12s;
    font-family: var(--font-body);
    color: var(--ink);
  }
  .app-cat-row:hover { background: var(--surface-soft); }
  .app-cat-row svg {
    width: 18px; height: 18px;
    stroke: var(--muted);
    flex-shrink: 0;
  }
  .app-cat-row .app-cat-label {
    flex: 1;
    font-size: 14px; font-weight: 500;
  }
  .app-cat-row .app-cat-tag {
    font-family: var(--font-mono);
    font-size: var(--text-caption); font-weight: 600;
    color: var(--primary);
    text-transform: uppercase; letter-spacing: 0.08em;
  }
  .app-cat-row.suggested svg { stroke: var(--primary); }
  .app-cat-row.suggested .app-cat-label { color: var(--primary); font-weight: 600; }

  /* Bouton primary pill (suit DESIGN.md ds-btn-primary) */
  .app-btn-primary {
    display: inline-flex; align-items: center; justify-content: center;
    height: 44px; padding: 0 20px;
    background: var(--primary); color: var(--on-primary);
    border: none; border-radius: var(--r-pill);
    font-family: var(--font-body); font-size: 14px; font-weight: 600;
    cursor: pointer; transition: background 0.15s;
  }
  .app-btn-primary:hover { background: var(--primary-active); }

  .app-btn-secondary {
    display: inline-flex; align-items: center; justify-content: center;
    height: 44px; padding: 0 20px;
    background: var(--surface-strong); color: var(--ink);
    border: none; border-radius: var(--r-pill);
    font-family: var(--font-body); font-size: 14px; font-weight: 600;
    cursor: pointer; transition: background 0.15s;
  }
  .app-btn-secondary:hover { background: var(--hairline); }

  /* Force #app a occuper au moins la hauteur du viewport (moins la topbar et l espace
     reserve a la danger-card). Resultat: la danger-card qui suit est toujours collee en
     bas du viewport meme si l onglet actif a peu de contenu, sans toucher au layout des
     enfants de #app (ce qui casserait certains onglets). */
  #app { min-height: calc(100vh - var(--topbar-h) - 180px); }

  /* ---------- Zone danger (carte toujours en bas de page) ---------- */
  .danger-card {
    margin-top: var(--space-xxl);
    background: var(--canvas);
    border: 1px solid var(--hairline);
    border-radius: var(--r-xl);
    padding: var(--space-lg) var(--space-xl);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-lg);
  }
  .danger-card-title {
    font-size: var(--text-caption); font-weight: var(--weight-semibold);
    color: var(--ink);
    margin-bottom: 4px;
    display: flex; align-items: center; gap: 8px;
   text-transform: uppercase; letter-spacing: 0.08em;}
  .danger-card-title svg {
    width: 14px; height: 14px;
    stroke: var(--semantic-down);
  }
  .danger-card-desc {
    font-size: 12px; line-height: 1.5;
    color: var(--muted);
    max-width: 480px;
  }
  .btn-danger {
    flex-shrink: 0;
    font-size: 13px; font-weight: 500;
    color: var(--semantic-down);
    background: var(--canvas);
    border: 1px solid var(--semantic-down);
    border-radius: var(--r-pill);
    padding: 8px 18px;
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
  }
  .btn-danger:hover {
    background: var(--semantic-down);
    color: var(--canvas);
  }

  /* ---------- Team strip dans le header (rangee inline d avatars · pas d encadre) ---------- */
  .team-strip { margin-top: var(--space-base); }
  .team-strip-row {
    display: flex; align-items: center; gap: var(--space-lg);
    flex-wrap: wrap;
  }
  .team-role-group {
    display: flex; align-items: center; gap: 10px;
    position: relative;
  }
  .role-avatars {
    display: flex; align-items: center;
    flex-shrink: 0;
  }
  .role-avatars .mini-avatar {
    width: 28px; height: 28px;
    border-radius: var(--r-full);
    background: var(--surface-dark);
    color: var(--on-dark);
    font-size: 11px; font-weight: 600;
    display: inline-flex; align-items: center; justify-content: center;
    border: 2px solid var(--canvas);
    margin-left: -8px;
    flex-shrink: 0;
    cursor: default;
    transition: transform 0.12s;
  }
  .role-avatars .mini-avatar:first-child { margin-left: 0; }
  .role-avatars .mini-avatar:hover { z-index: 2; transform: translateY(-1px); }
  .role-avatars .mini-avatar.empty,
  .role-avatars .mini-avatar.plus {
    background: var(--primary-soft);
    color: var(--primary);
    border-style: dashed;
    cursor: pointer;
  }
  .role-avatars .mini-avatar.plus:hover {
    background: var(--primary-soft);
    color: var(--primary);
    border-color: var(--primary);
    border-style: solid;
  }
  .role-meta {
    display: flex; flex-direction: column;
    line-height: 1.2;
    min-width: 0;
  }
  .role-label {
    font-size: var(--text-caption); font-weight: 600;
    color: var(--muted);
    text-transform: uppercase; letter-spacing: 0.06em;
  }
  .role-status {
    font-size: 13px; color: var(--ink);
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 160px;
  }
  /* Icone camion (utilisee dans le picker) */

  /* Picker · popover ancre au bouton "+" (pas un overlay full-screen) */
  .team-picker-overlay {
    position: fixed; inset: 0;
    background: transparent;
    z-index: 1000;
  }
  .team-picker {
    position: absolute;
    background: var(--canvas);
    border: 1px solid var(--hairline);
    border-radius: var(--r-md);
    box-shadow: var(--shadow-hover);
    width: 240px;
    max-height: 50vh;
    display: flex; flex-direction: column;
    overflow: hidden;
  }
  .team-picker-head {
    padding: 10px 14px 8px;
    border-bottom: 1px solid var(--hairline-soft);
    font-size: 11px; font-weight: 600;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
  }
  .team-picker-list {
    flex: 1; overflow-y: auto;
    padding: 4px 0;
  }
  .team-picker-row {
    display: flex; align-items: center; gap: 10px;
    padding: 8px 14px;
    cursor: pointer;
    font-size: 13px; color: var(--ink);
    transition: background 0.1s;
    background: none; border: none;
    width: 100%; text-align: left;
    font-family: inherit;
  }
  .team-picker-row:hover { background: var(--surface-soft); }
  /* Sur mobile : popover devient une bottom-sheet (plus pratique au pouce) */
  @media (max-width: 640px) {
    .team-picker-overlay { background: color-mix(in srgb, var(--ink) 30%, transparent); }
    .team-picker {
      position: fixed !important;
      left: 12px !important; right: 12px !important;
      bottom: 12px !important; top: auto !important;
      width: auto !important;
      max-height: 60vh;
    }
  }
  /* team-avatar · utilise dans le picker (cercles avec initiales) */
  .team-avatar {
    width: 22px; height: 22px;
    border-radius: var(--r-full);
    background: var(--primary);
    color: var(--on-primary);
    display: flex; align-items: center; justify-content: center;
    font-size: var(--text-caption); font-weight: 600;
    flex-shrink: 0;
  }

  /* ---------- Timeline ---------- */
  .timeline-item {
    display: flex; gap: var(--space-sm);
    padding: var(--space-sm) 0;
    border-bottom: 1px solid var(--hairline-soft);
  }
  .timeline-item:last-child { border-bottom: none; }
  .timeline-icon {
    width: 28px; height: 28px;
    border-radius: var(--r-full);
    background: var(--primary-soft);
    color: var(--primary);
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
    font-size: 13px;
  }
  .timeline-icon svg { width: 14px; height: 14px; }
  .alert-icon svg { width: 16px; height: 16px; flex-shrink: 0; }
  .timeline-content { flex: 1; min-width: 0; }
  .timeline-text { font-size: 13px; color: var(--ink); margin-bottom: 2px; }
  .timeline-meta {
    font-size: 11px; color: var(--muted);
    display: flex; gap: 8px;
  }
  .timeline-meta .mono { font-family: var(--font-mono); }

  /* ---------- Alertes ---------- */
  .alert-item {
    display: flex; gap: var(--space-sm); align-items: flex-start;
    padding: var(--space-sm);
    border-radius: var(--r-md);
    margin-bottom: var(--space-xs);
    background: var(--surface-soft);
    border-left: 3px solid var(--accent-yellow);
  }
  .alert-item:last-child { margin-bottom: 0; }
  .alert-item.danger { border-left-color: var(--semantic-down); }
  .alert-item.info   { border-left-color: var(--primary); }
  .alert-icon { font-size: 16px; flex-shrink: 0; }
  .alert-text { font-size: 12px; color: var(--ink); line-height: 1.4; }
  .alert-meta { font-size: 11px; color: var(--muted); margin-top: 2px; }

  /* ---------- Tables réutilisables ---------- */
  .data-table { width: 100%; border-collapse: collapse; font-size: 13px; }
  .data-table th {
    font-size: var(--text-caption); font-weight: 600;
    color: var(--muted);
    text-transform: uppercase; letter-spacing: 0.07em;
    padding: 10px 12px;
    text-align: left;
    border-bottom: 1px solid var(--hairline);
  }
  .data-table td {
    padding: 12px;
    border-bottom: 1px solid var(--hairline-soft);
    color: var(--body);
    vertical-align: middle;
  }
  .data-table tbody tr:last-child td { border-bottom: none; }
  .data-table tbody tr:hover { background: var(--surface-soft); }
  .data-table .num { text-align: right; font-family: var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink); }
  .data-table .strong { font-weight: 600; color: var(--ink); }

  /* Soumission lignes */
  .quote-summary {
    display: grid; grid-template-columns: 1fr 1fr 1fr 1fr;
    gap: 1px;
    background: var(--hairline-soft);
    border: 1px solid var(--hairline);
    border-radius: var(--r-md);
    overflow: hidden;
    margin-bottom: var(--space-base);
  }
  .quote-summary > div {
    background: var(--canvas);
    padding: var(--space-sm) var(--space-base);
  }
  .quote-summary .label { font-size: var(--text-caption); font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; }
  .quote-summary .value { font-family: var(--font-mono); font-size: var(--text-h2); font-weight: 600; color: var(--ink); margin-top: 2px; }

  /* Production · badge de statut sur les lignes du sub-tab Heures */
  .prod-status-badge {
    display: inline-block;
    padding: 2px 8px;
    border-radius: var(--r-pill);
    font-size: var(--text-caption);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
  }
  .prod-status-badge.confirmed {
    background: var(--semantic-up);
    color: var(--canvas);
  }
  .prod-status-badge.approved {
    background: rgba(244, 176, 0, 0.18);
    color: #b07b00;
    border: 1px solid rgba(244, 176, 0, 0.5);
  }
  .prod-status-badge.pending {
    background: var(--surface-soft);
    color: var(--muted);
    border: 1px solid var(--hairline);
  }
  /* Ligne pending_approval · grisée pour montrer 'pas encore validé' */
  .data-table tr.is-pending-foreman td {
    background: var(--surface-soft);
    color: var(--muted);
  }
  .data-table tr.is-pending-foreman td.strong {
    color: var(--body);
  }
  /* Ligne approved · normal mais subtile bordure pour distinction */
  .data-table tr.is-pending-admin td {
    background: rgba(244, 176, 0, 0.04);
  }
  .prod-pending-note {
    padding: 8px 14px;
    margin-bottom: 10px;
    background: var(--surface-soft);
    border: 1px solid var(--hairline-soft);
    border-radius: var(--r-md);
    font-size: 11px;
    color: var(--muted);
  }

  /* Location · bouton crayon pour éditer la date de SORTIE */
  .loc-start-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 22px;
    margin-left: 6px;
    padding: 0;
    background: transparent;
    border: none;
    border-radius: var(--r-sm);
    color: var(--muted-soft);
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.15s, background 0.15s, color 0.15s;
    vertical-align: middle;
  }
  .mat-day-row:hover .loc-start-btn { opacity: 1; }
  .loc-start-btn:hover {
    background: var(--surface-soft);
    color: var(--primary);
  }
  .loc-start-btn svg { width: 12px; height: 12px; }

  /* Location · bouton date picker · style cohérent avec suivi-date-btn */
  .loc-end-btn {
    display: inline-flex; align-items: center; gap: 6px;
    height: 28px;
    padding: 0 10px;
    background: var(--surface-soft);
    border: 1px solid var(--hairline);
    border-radius: var(--r-pill);
    font-family: inherit;
    font-size: 12px;
    color: var(--muted);
    cursor: pointer;
    transition: all 0.15s;
  }
  .loc-end-btn:hover {
    background: var(--canvas);
    border-color: var(--primary);
    color: var(--primary);
  }
  .loc-end-btn.has-date {
    background: var(--primary-soft);
    border-color: var(--primary);
    color: var(--primary);
    font-weight: 500;
  }
  .loc-end-btn svg { width: 12px; height: 12px; }

  /* Matériaux · groupage par jour avec dépliage */
  .data-table tr.mat-day-row { transition: background 0.1s; }
  .data-table tr.mat-day-row:hover { background: var(--surface-soft); }
  .data-table tr.mat-detail-row td {
    background: var(--surface-soft);
    border-top: 1px solid var(--hairline-soft);
    font-size: 12px;
    color: var(--body);
  }
  .data-table tr.mat-detail-row td.strong { color: var(--ink); }
  .mat-chevron {
    font-size: var(--text-caption);
    user-select: none;
  }

  /* ── LE SOUS-ONGLET LOCATION (db/200) ──────────────────────────────
     Préfixe `loc-` · règle du dépôt, une feuille unique pour les sept onglets
     avec isolation par préfixe de classe (voir CLAUDE.md). */
  .loc-table-wrap { overflow-x: auto; }
  .loc-table { width: 100%; border-collapse: collapse; font-size: var(--text-label); }
  .loc-table th {
    text-align: left; padding: 8px 10px;
    font-size: 10px; text-transform: uppercase; letter-spacing: .06em;
    font-weight: var(--weight-semibold); color: var(--muted);
    border-bottom: 1px solid var(--hairline); white-space: nowrap;
  }
  .loc-table td { padding: 10px; border-bottom: 1px solid var(--hairline-soft); color: var(--body); }
  .loc-table .r { text-align: right; }
  /* Chiffres en mono · prix, durées et totaux se comparent d'une ligne à
     l'autre (DESIGN.md). */
  .loc-table .num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
  .loc-quoi { color: var(--ink); font-weight: var(--weight-semibold); }
  .loc-muet { color: var(--muted-soft); }
  .loc-rabais { color: var(--semantic-up); font-size: var(--text-caption); }
  .loc-table tfoot td { border-bottom: none; padding-top: 12px; color: var(--muted); }
  .loc-total { color: var(--ink); font-weight: var(--weight-semibold); font-family: var(--font-mono); }
  .loc-del {
    background: none; border: none; cursor: pointer;
    color: var(--muted-soft); font-size: 16px; line-height: 1; padding: 2px 6px;
  }
  .loc-del:hover { color: var(--semantic-down); }

  .loc-vide { padding: var(--space-xl); text-align: center; color: var(--muted); font-size: var(--text-label); }
  .loc-vide-titre { color: var(--ink); font-weight: var(--weight-semibold); margin-bottom: 4px; }
  .loc-ajouter { margin-top: var(--space-base); font-size: var(--text-caption); padding: 7px 14px; }

  .loc-form {
    margin-top: var(--space-base); padding: var(--space-base);
    border: 1px solid var(--hairline); border-radius: var(--r-md);
    background: var(--surface-soft);
  }
  /* `auto-fill` et non un nombre de colonnes figé · le panneau vit dans un
     onglet dont la largeur change avec la fenêtre, et une grille figée
     débordait sur portable. */
  .loc-form-grille {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: var(--space-sm);
  }
  .loc-form-grille label { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
  .loc-form-grille label > span {
    font-size: 10px; text-transform: uppercase; letter-spacing: .06em;
    font-weight: var(--weight-semibold); color: var(--muted);
  }
  .loc-inp {
    height: 38px; box-sizing: border-box; width: 100%;
    background: var(--input-bg); border: 1px solid var(--hairline);
    border-radius: var(--r-md); padding: 0 12px;
    font-family: var(--font-body); font-size: var(--text-label); color: var(--ink);
  }
  .loc-inp:focus { outline: none; border-color: var(--ink); }
  .loc-inp.loc-num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; text-align: right; }
  .loc-form-pied {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--space-base); flex-wrap: wrap; margin-top: var(--space-base);
  }
  /* L'aperçu du coût, en direct · le seul moyen de voir qu'on s'est trompé de
     mode de facturation AVANT d'enregistrer. */
  .loc-apercu {
    font-family: var(--font-mono); font-variant-numeric: tabular-nums;
    font-size: var(--text-label); color: var(--ink);
  }
  .loc-form-btns { display: flex; gap: var(--space-xs); }

  /* Production sub-tabs */
  .sub-tabs {
    display: flex; gap: 2px;
    border-bottom: 1px solid var(--hairline);
    margin-bottom: var(--space-base);
  }
  .sub-tab {
    background: none; border: none;
    font-size: 13px; font-weight: 600;
    color: var(--muted);
    padding: 10px 16px;
    cursor: pointer;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
  }
  .sub-tab:hover { color: var(--ink); }
  .sub-tab.active { color: var(--ink); border-bottom-color: var(--primary); }

  .sub-panel { display: none; }
  .sub-panel.active { display: block; }

  /* Photos grid */
  .photos-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: var(--space-xs);
  }
  .photo-tile {
    aspect-ratio: 1;
    background: var(--surface-strong);
    border-radius: var(--r-md);
    border: 1px solid var(--hairline);
    display: flex; align-items: center; justify-content: center;
    font-size: 11px; color: var(--muted);
    cursor: pointer;
    transition: transform 0.15s;
  }
  .photo-tile:hover { transform: scale(1.02); }
  .photo-tile.upload {
    border: 1px dashed var(--hairline);
    color: var(--muted);
    background: var(--surface-soft);
  }
  .photo-tile.photo-real { padding: 0; overflow: hidden; }
  .photo-tile.photo-real img {
    width: 100%; height: 100%;
    object-fit: cover; display: block;
  }

  /* ---------- Grille de tuiles unifiee (Documents tab, toutes categories) ---------- */
  .doc-tiles-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: var(--space-xs);
  }
  /* Section card · header avec bouton 'Ajouter' a droite */
  .doc-section-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-base);
  }
  .doc-add-btn {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 30px;
    padding: 0 12px;
    background: var(--canvas);
    color: var(--primary);
    border: 1px solid var(--primary);
    border-radius: var(--r-pill);
    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
    flex-shrink: 0;
  }
  .doc-add-btn:hover {
    background: var(--primary);
    color: var(--on-primary);
  }
  .doc-add-btn svg { width: 13px; height: 13px; }
  /* Variante 'primary' · fond rempli, pour l action principale 'Doc visite' */
  .doc-add-btn-primary {
    background: var(--primary);
    color: var(--on-primary);
  }
  .doc-add-btn-primary:hover {
    background: var(--ink);
    color: var(--canvas);
  }
  /* Container des actions dans le head de section · 2 boutons (Doc visite + Ajouter) */
  .doc-section-head-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
  }
  /* Sous-sections de la categorie Contremaitre · 5 sous-cats fixes empilees
     dans une seule carte. Chaque sous-section a son propre header + bouton Ajouter. */
  .doc-subsections {
    display: flex;
    flex-direction: column;
    gap: var(--space-base);
  }
  .doc-subsection {
    border-top: 1px solid var(--hairline-soft);
    padding-top: var(--space-base);
  }
  .doc-subsection:first-child {
    border-top: none;
    padding-top: 0;
  }
  .doc-subsection-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-base);
    margin-bottom: var(--space-sm);
  }
  .doc-subsection-title {
    font-size: var(--text-caption);
    font-weight: var(--weight-semibold);
    color: var(--ink);
   text-transform: uppercase; letter-spacing: 0.08em;}
  .doc-subsection-title .doc-subsection-count {
    color: var(--muted-soft);
    font-family: var(--font-mono);
    font-weight: 400;
    margin-left: 6px;
  }
  .doc-subsection-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
  }
  /* Tuile · doc de visite chantier (texte riche · Quill) · visuel dedie sans
     thumbnail, avec titre + meta template + auteur + date */
  .doc-tile-visit {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: var(--space-sm) var(--space-base);
    background: var(--canvas);
    border: 1px solid var(--hairline);
    border-radius: var(--r-md);
    min-height: 100px;
    cursor: pointer;
    transition: border-color 0.15s, transform 0.15s, box-shadow 0.15s;
    position: relative;
  }
  .doc-tile-visit:hover {
    border-color: var(--primary);
    transform: translateY(-1px);
    box-shadow: var(--shadow-hover);
  }
  .doc-tile-visit-head {
    display: flex;
    align-items: center;
    gap: 8px;
  }
  .doc-tile-visit-title {
    font-size: var(--text-body);
    font-weight: var(--weight-semibold);
    color: var(--ink);
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
  }
  .doc-tile-visit-meta {
    font-size: 11px;
    color: var(--primary);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
  }
  .doc-tile-visit-foot {
    margin-top: auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    font-size: 11px;
    color: var(--muted);
  }
  .doc-tile-visit-author {
    font-weight: 600;
    color: var(--body);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .doc-tile-visit-date {
    font-family: var(--font-mono);
    color: var(--muted-soft);
    white-space: nowrap;
  }
  /* Placeholder pour les sections vides · invite l user a ajouter */
  .doc-section-empty {
    padding: var(--space-lg);
    text-align: center;
    font-size: 12px;
    color: var(--muted-soft);
    font-style: italic;
    background: var(--surface-soft);
    border: 1px dashed var(--hairline);
    border-radius: var(--r-md);
    transition: border-color 0.15s, background 0.15s, color 0.15s;
  }
  /* Etat visuel · drag d'un fichier au-dessus d'une section */
  .doc-section-card.dragover {
    border-color: var(--primary);
    background: var(--primary-soft);
    box-shadow: 0 0 0 2px var(--primary-soft);
  }
  .doc-section-card.dragover .doc-section-empty {
    border-color: var(--primary);
    background: transparent;
    color: var(--primary);
  }
  /* Sous-section Contremaitre · meme effet, isole a la sous-section */
  .doc-subsection.dragover {
    background: var(--primary-soft);
    border-radius: var(--r-md);
    box-shadow: inset 0 0 0 2px var(--primary);
  }
  .doc-subsection.dragover .doc-section-empty {
    border-color: var(--primary);
    background: transparent;
    color: var(--primary);
  }
  .doc-tile {
    position: relative;
    aspect-ratio: 1;
    background: var(--surface-strong);
    border: 1px solid var(--hairline);
    border-radius: var(--r-md);
    overflow: hidden;
    cursor: pointer;
    transition: border-color 0.15s, transform 0.15s;
  }
  .doc-tile:hover {
    border-color: var(--ink);
    transform: scale(1.02);
  }
  /* Tuile image : juste la photo en cover */
  .doc-tile-img img {
    width: 100%; height: 100%;
    object-fit: cover; display: block;
  }
  /* Tuile fichier non-image : icone centree + nom + taille */
  .doc-tile-file {
    background: var(--canvas);
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    padding: 12px 10px;
    gap: 6px;
    text-align: center;
  }
  .doc-tile-file .doc-tile-icon {
    width: 32px; height: 32px;
    flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    background: var(--surface-soft);
    border-radius: var(--r-sm);
  }
  .doc-tile-file .doc-tile-icon svg {
    width: 18px; height: 18px;
    stroke: var(--muted);
  }
  .doc-tile-file .doc-tile-name {
    font-size: 11px; font-weight: 500;
    color: var(--ink);
    line-height: 1.3;
    width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    word-break: break-all;
  }
  .doc-tile-file .doc-tile-meta {
    font-family: var(--font-mono);
    font-size: var(--text-caption); color: var(--muted);
  }
  /* HEIC : placeholder le temps de la conversion JPEG cote client */
  .doc-tile-heic-placeholder {
    width: 100%; height: 100%;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    gap: 8px;
    background: var(--surface-soft);
    color: var(--muted);
  }
  .doc-tile-heic-spinner {
    width: 18px; height: 18px;
    border: 2px solid var(--hairline);
    border-top-color: var(--primary);
    border-radius: var(--r-full);
    animation: heic-spin 0.7s linear infinite;
  }
  @keyframes heic-spin { to { transform: rotate(360deg); } }
  .doc-tile-heic-label {
    font-family: var(--font-mono);
    font-size: var(--text-caption); font-weight: 600;
    letter-spacing: 0.08em;
  }
  .doc-tile-heic.converted .doc-tile-heic-placeholder { display: none; }
  .doc-tile-heic.failed .doc-tile-heic-spinner { display: none; }
  .doc-tile-heic.failed .doc-tile-heic-label {
    color: var(--semantic-down);
  }
  .doc-tile-heic.failed .doc-tile-heic-label::after {
    content: ' · échec';
    text-transform: lowercase;
    font-weight: 400;
  }
  .doc-tile-heic img {
    width: 100%; height: 100%;
    object-fit: cover; display: block;
  }

  /* PDF : placeholder + nom du fichier en bas, image apparait apres conversion */
  .doc-tile-pdf {
    background: var(--canvas);
    display: flex; flex-direction: column;
    overflow: hidden;
  }
  .doc-tile-pdf-placeholder {
    flex: 1;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    gap: 8px;
    background: var(--surface-soft);
    color: var(--muted);
  }
  .doc-tile-pdf-label {
    font-family: var(--font-mono);
    font-size: var(--text-caption); font-weight: 600;
    letter-spacing: 0.08em;
    color: var(--semantic-down);
  }
  .doc-tile-pdf canvas, .doc-tile-pdf img {
    width: 100%;
    flex: 1; min-height: 0;
    object-fit: cover;
    object-position: top;
    display: block;
  }
  .doc-tile-pdf-name {
    font-size: var(--text-caption); font-weight: 500;
    color: var(--ink);
    background: var(--canvas);
    border-top: 1px solid var(--hairline-soft);
    padding: 6px 8px;
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .doc-tile-pdf.converted .doc-tile-pdf-placeholder { display: none; }
  .doc-tile-pdf.failed .doc-tile-heic-spinner { display: none; }
  .doc-tile-pdf.failed .doc-tile-pdf-label::after {
    content: ' · échec';
    text-transform: lowercase; font-weight: 400;
    color: var(--semantic-down);
  }

  /* Bouton supprimer · toujours visible mais discret, plus marque au hover */
  .doc-tile-del {
    position: absolute;
    top: 6px; right: 6px;
    width: 24px; height: 24px;
    border: none;
    background: rgba(0,0,0,0.55);
    color: #fff;
    font-size: 16px; line-height: 1;
    border-radius: var(--r-full);
    cursor: pointer;
    opacity: 0.85;
    transition: opacity 0.15s, background 0.15s, transform 0.15s;
    display: flex; align-items: center; justify-content: center;
    z-index: 2;
  }
  .doc-tile:hover .doc-tile-del { opacity: 1; }
  .doc-tile-del:hover {
    background: var(--semantic-down);
    transform: scale(1.1);
  }

  /* Documents */
  .doc-item {
    display: flex; align-items: center; gap: var(--space-sm);
    padding: var(--space-sm);
    border-bottom: 1px solid var(--hairline-soft);
    cursor: pointer;
  }
  .doc-item:hover { background: var(--surface-soft); }
  .doc-item:last-child { border-bottom: none; }
  .doc-icon {
    width: 36px; height: 36px;
    background: var(--surface-strong);
    border-radius: var(--r-sm);
    display: flex; align-items: center; justify-content: center;
    font-size: 14px;
    flex-shrink: 0;
  }
  .doc-info { flex: 1; min-width: 0; }
  .doc-name { font-size: var(--text-body); font-weight: var(--weight-semibold); color: var(--ink); }
  .doc-meta { font-size: 11px; color: var(--muted); margin-top: 2px; }

  /* ---------- Identification block ---------- */
  .ident-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-sm) var(--space-base);
    font-size: 13px;
  }
  .ident-grid .full { grid-column: 1 / -1; }
  /* Variante 1 colonne · utilisee dans les cartes etroites (layout 2 cols Infos client) */
  .ident-grid.ident-grid-col1 {
    grid-template-columns: 1fr;
  }
  /* Rangee 2 colonnes pour l onglet Infos client · Client (avec adresses) a gauche, Infos complementaires a droite */
  .infos-client-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-base);
    margin-bottom: var(--space-base);
    align-items: start;
  }
  @media (max-width: 900px) {
    .infos-client-row { grid-template-columns: 1fr; }
  }
  /* Titre de sous-section principal a l interieur d une carte (ex: 'Adresse' qui regroupe travaux + facturation)
     · meme poids que .card-title (15px bold) mais separe visuellement avec une ligne au-dessus */
  .card-section-title {
    font-size: var(--text-caption); font-weight: var(--weight-semibold);
    color: var(--ink);
    letter-spacing: -0.2px;
    margin-top: var(--space-lg);
    padding-top: var(--space-lg);
    border-top: 1px solid var(--hairline);
   text-transform: uppercase;}
  /* Pills onglets pour les co-clients · Client 1 / 2 / 3 / 4 / 5 + bouton +Ajouter */
  .clients-tabs {
    display: flex; flex-wrap: wrap; gap: 4px;
    margin-bottom: var(--space-base);
    padding-bottom: var(--space-sm);
    border-bottom: 1px solid var(--hairline-soft);
  }
  .client-tab {
    background: transparent;
    border: 1px solid var(--hairline);
    color: var(--muted);
    padding: 5px 12px;
    border-radius: var(--r-pill);
    font-family: inherit; font-size: 12px; font-weight: 600;
    cursor: pointer;
    transition: all 0.15s;
    display: inline-flex; align-items: center; gap: 6px;
  }
  .client-tab:hover { color: var(--ink); border-color: var(--ink); }
  .client-tab.active {
    background: var(--ink); color: var(--canvas);
    border-color: var(--ink);
  }
  .client-tab-remove {
    background: none; border: none;
    color: inherit; opacity: 0.6;
    cursor: pointer; padding: 0; margin: 0;
    font-size: 14px; line-height: 1;
  }
  .client-tab-remove:hover { opacity: 1; }
  .client-add-btn {
    background: transparent;
    border: 1px dashed var(--hairline);
    color: var(--primary);
    padding: 5px 12px;
    border-radius: var(--r-pill);
    font-family: inherit; font-size: 12px; font-weight: 600;
    cursor: pointer;
    transition: all 0.15s;
  }
  .client-add-btn:hover {
    background: var(--primary-soft);
    border-color: var(--primary);
    border-style: solid;
  }
  /* Panel client · seul l actif est visible */
  .client-panel { display: none; }
  .client-panel.active { display: block; }

  /* Mini-label de sous-section a l interieur d une carte (ex: 'Adresse des travaux', 'Autre adresse de facturation')
     · separation legere via hairline-soft. La premiere sous-section apres un card-section-title n a pas de border-top. */
  .card-subsection-label {
    font-size: 11px; font-weight: 600;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-top: var(--space-lg);
    margin-bottom: 8px;
    padding-top: var(--space-base);
    border-top: 1px solid var(--hairline-soft);
  }
  .card-subsection-label.first-subsection {
    /* Pas de border ni padding-top si c est le premier · le card-section-title fait deja la separation */
    margin-top: var(--space-base);
    padding-top: 0;
    border-top: none;
  }
  .ident-label {
    font-size: var(--text-caption); font-weight: 600;
    color: var(--muted); text-transform: uppercase; letter-spacing: 0.07em;
    margin-bottom: 2px;
  }
  .ident-value { color: var(--ink); font-size: 13px; line-height: 1.4; }
  .ident-value.muted { color: var(--muted); font-style: italic; }

  /* ---------- Contact links ---------- */
  .inp-with-action { position: relative; display: flex; align-items: center; gap: 6px; }
  .inp-with-action .fiche-inp { flex: 1; }
  .contact-icon-link {
    flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
    width: 28px; height: 28px; border-radius: var(--r-full);
    color: var(--muted); background: var(--surface-soft);
    border: 1px solid var(--hairline); text-decoration: none;
    transition: all 0.15s;
  }
  .contact-icon-link:hover { color: var(--primary); border-color: var(--primary); background: var(--primary-soft); }
  .contact-icon-link svg { width: 13px; height: 13px; }
  .fiche-contact-link { color: inherit; text-decoration: none; }
  .fiche-contact-link:hover { color: var(--primary); }
  .ident-value .pill-mini {
    display: inline-block;
    background: var(--surface-strong);
    color: var(--ink);
    font-size: 11px;
    padding: 2px 8px;
    border-radius: var(--r-pill);
    margin-right: 4px; margin-bottom: 2px;
  }

  /* ---------- Filter bar Documents ---------- */
  .filter-bar {
    display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
    margin-bottom: var(--space-base);
  }
  .filter-chip {
    background: var(--canvas);
    border: 1px solid var(--hairline);
    border-radius: var(--r-pill);
    padding: 6px 14px;
    font-family: inherit;
    font-size: 12px; font-weight: 600;
    color: var(--body);
    cursor: pointer;
    transition: all 0.15s;
  }
  .filter-chip:hover { border-color: var(--primary); color: var(--primary); }
  .filter-chip.active {
    background: var(--ink); border-color: var(--ink); color: var(--canvas);
  }
  .filter-chip .count {
    margin-left: 4px;
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--muted);
  }
  .filter-chip.active .count { color: var(--on-dark-soft); }

  /* ---------- Photo groups ---------- */
  .photo-group { margin-bottom: var(--space-base); }
  .photo-group:last-child { margin-bottom: 0; }
  .photo-group-head {
    display: flex; justify-content: space-between; align-items: center;
    margin-bottom: var(--space-xs);
  }
  .photo-group-label {
    font-size: 11px; font-weight: 600;
    color: var(--muted);
    text-transform: uppercase; letter-spacing: 0.07em;
  }

  /* ---------- Upload zone (drag&drop) ---------- */
  .upload-zone {
    border: 2px dashed var(--hairline);
    border-radius: var(--r-md);
    padding: var(--space-base);
    text-align: center;
    background: var(--surface-soft);
    margin-bottom: var(--space-base);
    cursor: pointer;
    transition: all 0.15s;
  }
  .upload-zone:hover {
    border-color: var(--primary);
    background: var(--primary-soft);
    color: var(--primary);
  }
  .upload-zone .upload-text { font-size: 13px; font-weight: 600; color: var(--ink); }
  .upload-zone .upload-sub  { font-size: 11px; color: var(--muted); margin-top: 2px; }

  /* Notice de mockup */
  .mockup-notice {
    background: var(--primary-soft);
    border: 1px solid var(--primary);
    border-radius: var(--r-md);
    padding: var(--space-sm) var(--space-base);
    margin-bottom: var(--space-base);
    font-size: 12px;
    color: var(--primary);
  }
  .mockup-notice strong { font-weight: 600; }
  .stage-switcher {
    margin-top: 8px;
    display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  }
  .stage-switcher .label {
    font-size: 11px; font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.06em;
    color: var(--primary);
    margin-right: 4px;
  }
  .stage-switcher a {
    text-decoration: none;
    padding: 4px 10px;
    border-radius: var(--r-pill);
    font-size: 11px; font-weight: 600;
    background: var(--canvas);
    border: 1px solid var(--primary);
    color: var(--primary);
    transition: all 0.15s;
  }
  .stage-switcher a:hover { background: var(--primary); color: var(--on-primary); }
  .stage-switcher a.current { background: var(--primary); color: var(--on-primary); }

  /* ---------- Lifecycle bar dans le header ---------- */
  .lifecycle-bar {
    display: flex; align-items: center; gap: 4px;
    overflow-x: auto;
    padding: var(--space-sm) 0 4px;
    margin: var(--space-base) 0 0;
    border-top: 1px solid var(--hairline-soft);
    scrollbar-width: thin;
  }
  .stage-pill {
    flex-shrink: 0;
    display: inline-flex; align-items: center; gap: 6px;
    padding: 6px 12px;
    border-radius: var(--r-pill);
    font-size: 11px; font-weight: 600;
    background: var(--surface-soft);
    color: var(--muted);
    border: 1px solid var(--hairline-soft);
  }
  .stage-pill.done {
    background: var(--surface-strong);
    color: var(--ink);
  }
  .stage-pill.done::before { content: '✓'; color: var(--semantic-up); font-weight: var(--weight-semibold); }
  .stage-pill.current {
    background: var(--primary);
    color: var(--on-primary);
    border-color: var(--primary);
  }
  .stage-pill.current::before { content: '●'; }
  .stage-pill.future { opacity: 0.5; }
  .stage-arrow {
    flex-shrink: 0;
    color: var(--muted-soft);
    font-size: 11px;
  }

  /* ---------- Mode lecture seule (fiche-readonly) ----------
     Activé via html[data-fiche-readonly] pour les rôles sans fiches.edit
     ni fiches.change_status (ex. contremaître). Cache tous les boutons
     d'action sauf le bouton Doc Visite et l'upload Documents Contre-maître. */
  html[data-fiche-readonly] #btn-transfer-nc              { display: none !important; }
  html[data-fiche-readonly] .suivi-add-btn                { display: none !important; }
  html[data-fiche-readonly] #etiq-add-btn                 { display: none !important; }
  html[data-fiche-readonly] #livr-add-btn                 { display: none !important; }
  html[data-fiche-readonly] #st-lie-add-btn               { display: none !important; }
  html[data-fiche-readonly] #st-detache-add-btn           { display: none !important; }
  /* Sous-traitants · cache seulement le bouton "+" vide (pas l'avatar tagué).
     Mathieu doit voir le rond avec ses initiales sur le sous-traitant qui lui
     est assigné · sinon il ne sait pas que c'est lui le responsable. */
  html[data-fiche-readonly] .suivi-item .st-cm-btn-empty  { display: none !important; }
  html[data-fiche-readonly] .suivi-item .st-cm-btn-active { pointer-events: none; cursor: default; }
  /* Composer de commentaires sur les livrables · cache (le contremaitre peut
     lire les commentaires existants mais pas en ajouter). */
  html[data-fiche-readonly] .livr-comments-section .livr-comment-composer { display: none !important; }
  html[data-fiche-readonly] .suivi-date-btn               { pointer-events: none; opacity: 0.5; }
  html[data-fiche-readonly] .suivi-note-btn               { pointer-events: none; opacity: 0.5; }
  html[data-fiche-readonly] [contenteditable]             { pointer-events: none; cursor: default; }
  html[data-fiche-readonly] .inp-client,
  html[data-fiche-readonly] .inp-ident                    { pointer-events: none; background: var(--surface-soft); }
  /* Pill secteur (résidentiel / commercial) dans le header de la fiche · pas
     modifiable en mode lecture seule. Le contremaitre voit la valeur mais ne
     peut pas la changer · ce choix relève du chargé de projet / admin. */
  html[data-fiche-readonly] #sel-sector                   { pointer-events: none; opacity: 0.8; }
  html[data-fiche-readonly] #danger-zone                  { display: none !important; }
  /* Onglets entiers cachés : Cost (Budget est le résumé lecture-seule),
     PandaDoc, Calculateur. Le contremaître consulte Budget pour voir
     les heures par section (menuiserie, maçonnerie, soudure) sans
     accéder au Cost éditable. */
  html[data-fiche-readonly] .tab-btn[data-tab="cost"]        { display: none !important; }
  html[data-fiche-readonly] .tab-btn[data-tab="pandadoc"]    { display: none !important; }
  html[data-fiche-readonly] .tab-btn[data-tab="calculateur"] { display: none !important; }
  html[data-fiche-readonly] .tab-btn[data-tab="history"]     { display: none !important; }
  html[data-fiche-readonly] .tab-btn[data-tab="infos-client"] { display: none !important; }
  /* Suivi · caché uniquement en stade Nouveau contrat (le contremaitre n'a pas
     besoin de la checklist commerciale). En Production, Suivi reste visible
     pour les étapes/milestones de chantier. */
  html[data-fiche-readonly][data-stage="nouveau-contrat"] .tab-btn[data-tab="suivi"] { display: none !important; }
  /* Boutons "+" de la carte Équipe (Chargé, Contremaître). Camion reste
     éditable car le contremaître doit pouvoir choisir le cube qui va sur la job.
     Slot Administration retire (2026-06-04) · denylist model. */
  html[data-fiche-readonly] .mini-avatar.plus[data-add-inline="charge"],
  html[data-fiche-readonly] .mini-avatar.plus[data-add-inline="contremaitre"] { display: none !important; }
  html[data-fiche-readonly] [data-add-inline="charge"],
  html[data-fiche-readonly] [data-add-inline="contremaitre"] { pointer-events: none; cursor: default; }
  /* Onglet Documents : afficher SEULEMENT la section Contremaître.
     Toutes les autres sections (client, contrat, fichier, commande, soumission,
     permis, vidéo, photo_chantier) sont cachées en mode lecture seule.
     Les chips de filtre en haut sont cachées aussi (une seule section visible
     · le filtre n'a plus de raison d'être). */
  /* En readonly (contremaitre), seules les sections Contremaitre + Photo chantier
     sont visibles. La filter-bar reste cachee (juste 2 sections, scroll suffit). */
  html[data-fiche-readonly] .doc-section-card:not([data-section="contremaitre"]):not([data-section="photo_chantier"]) { display: none !important; }
  html[data-fiche-readonly] #docs-filter-bar                                     { display: none !important; }

  /* ---------- Visibilité par statut · DES BLOCS, PAS DES ONGLETS ----------
     4 stages : demande / nouveau-contrat / production / archive.
     data-stage est posé sur <html> par le head-script avant parsing,
     puis re-synchronisé par le module JS après chargement de la fiche.

     PÉRIMÈTRE (tranché au ménage de fin du Chantier 3) · ces règles gouvernent
     des BLOCS de la fiche : le numéro de PO et le sélecteur de secteur dans
     l'en-tête, la pastille de statut, le bouton « Mettre à l'horaire », le
     bandeau KPI Production, les groupes d'équipe, la carte Client et le bloc
     Étiquettes/Livrables de l'onglet Suivi.

     Elles ne gouvernent PLUS AUCUN ONGLET · c'est `tableaux.fiche_tabs`
     (db/172) qui décide quels onglets composent la fiche, et lui seul. Les
     deux mécanismes se recouvraient sur les boutons « Sous-traitants » et
     « Production », et le CSS gagnait : un client qui ajoutait « production »
     au fiche_tabs d'un tableau au stage « demande » ne voyait pas son onglet.
     Un bouton d'onglet ne doit donc jamais porter .hide-in-demande /
     .only-prod / .only-demande · c'est vérifié par
     fiche-tabs/verifier-seed-onglets.mjs.

     `.only-nc` n'existe plus : la classe était déclarée ici (4 règles) mais
     posée sur AUCUN élément, ni dans fiche.html, ni dans fiche.js, ni dans les
     sept onglets-modules. */
  /* Sélecteurs sur <html> pour que data-stage posé en head-script
     (avant parsing du body) s'applique sans FOUC. */
  html[data-stage="demande"]         .only-prod    { display: none !important; }
  html[data-stage="demande"]         .hide-in-demande { display: none !important; }
  html[data-stage="nouveau-contrat"] .only-demande, html[data-stage="nouveau-contrat"] .only-prod    { display: none !important; }
  html[data-stage="production"]      .only-demande { display: none !important; }
  html[data-stage="archive"]         .only-demande, html[data-stage="archive"] .only-prod { display: none !important; }

  /* Stage « custom » · un tableau créé par le client (tb_<base36>), dont le
     stage n'est aucun des quatre systèmes. AVANT (Chantier 3, Phase 1), sa
     fiche retombait en silence sur la mise en page « demande ». Maintenant
     elle prend une mise en page NEUTRE : on cache tout ce qui appartient à un
     stage système précis, on garde le générique. Les blocs .hide-in-demande
     restent visibles · ce sont les blocs « partout sauf en demande ». */
  html[data-stage="custom"] .only-demande,
  html[data-stage="custom"] .only-prod { display: none !important; }

  /* Onglet ÉTEINT PAR CONFIGURATION (tableaux.fiche_tabs, db/172). À ne pas
     confondre avec les règles de stage ci-dessus : ici c'est le client qui a
     décidé que cet onglet ne fait pas partie de sa fiche. Posé par applyTabs()
     dans fiche.js · réversible, le tableau peut changer sans rechargement. */
  .tabs .tab-btn.tab-off { display: none !important; }

  /* ---------- Visibilité par SUIVI (workflow) ----------
     Le bloc workflow ne dépend PLUS du stage (ancien câblage « Leads seulement »)
     mais du réglage du tableau : tableaux.suivi_actif → html[data-suivi="on|off"],
     posé par fiche.js. Un tableau dont le Suivi est allumé montre son workflow,
     et il COHABITE avec le suivi interne (Étiquettes/Livrables) le cas échéant. */
  .only-suivi  { display: none; }
  .only-manuel { display: none; }
  html[data-suivi="on"]  .only-suivi  { display: block; }
  /* Pas de workflow → le déplacement manuel prend la place du workflow.
     ⚠ IL ÉTAIT RESTREINT AU STAGE « demande », parce qu'ailleurs la carte Suivi
     (.hide-in-demande) rendait déjà la même liste. Cette carte est partie dans
     le module Tâches le 2026-07-25 · et les listes de tâches ne déplacent
     aucune fiche. La restriction laissait donc l'onglet Suivi COMPLÈTEMENT VIDE
     sur Projets, Production, Terminé et Annulés : pas de workflow, pas de
     déplacement, pas de carte Client. Un onglet vide et zéro erreur. */
  html[data-suivi="off"] .only-manuel { display: block; }
  /* UNE SEULE COLONNE QUAND LA DROITE EST VIDE · la grille était figée à
     `1fr 1fr`. Dès que la carte Client ne paraissait pas (tout stade autre que
     « demande », ou bloc masqué par le client), la moitié droite restait
     blanche et la colonne de gauche flottait dans un demi-écran de vide.
     La classe est posée par le module, qui seul sait ce qu'il a rendu. */
  #suivi-top-grid.suivi-une-colonne { grid-template-columns: 1fr; }

  /* #suivi-top-grid garde les 2 colonnes de .panel-grid-2 : le bloc du haut
     (workflow ou déplacement manuel) occupe une DEMI-colonne, aligné avec les
     cartes Suivi/Tâches en dessous. Le média 900px le replie sur mobile. */

  /* #manual-move-list réutilise .suivi-list / .suivi-item · aucun style propre,
     c'est volontaire : même rendu que la carte Suivi des autres fiches. */

  /* ---------- Cartes Suivi NC (Etiquettes + Livrables) ----------
     Onglet Suivi en stage NC+. 2 cartes cote a cote.
     Chaque item : badge d etat clickable (cycle), label editable inline,
     date optionnelle, bouton supprimer. Etat 'fait' barre le texte. */
  .suivi-card .card-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
  .suivi-add-btn {
    display: inline-flex; align-items: center; gap: 4px;
    height: 28px; padding: 0 10px;
    background: var(--primary-soft); color: var(--primary);
    border: none; border-radius: var(--r-pill);
    font-size: 11px; font-weight: 600; letter-spacing: 0.02em;
    cursor: pointer; transition: filter 0.15s;
  }
  .suivi-add-btn:hover { filter: brightness(0.95); }

  /* Popover qui apparait au click sur +Ajouter · liste des templates dispos
     en boutons cliquables + option 'Autre...' pour custom. */
  .suivi-picker {
    background: var(--canvas);
    border: 1px solid var(--hairline);
    border-radius: var(--r-md);
    box-shadow: var(--shadow-hover, 0 8px 24px rgba(0,0,0,0.12));
    padding: 8px;
    z-index: 1000;
    max-height: 320px;
    overflow-y: auto;
  }
  .suivi-picker-head {
    font-size: var(--text-caption); font-weight: 600; color: var(--muted);
    text-transform: uppercase; letter-spacing: 0.06em;
    padding: 4px 8px 6px;
  }
  .suivi-picker-list { display: flex; flex-direction: column; gap: 2px; }
  .suivi-picker-empty {
    padding: 12px 8px; font-size: 12px; color: var(--muted-soft);
    text-align: center;
  }
  .suivi-picker-item {
    width: 100%; text-align: left;
    padding: 8px 10px;
    background: transparent; border: none;
    border-radius: var(--r-sm);
    font-size: 13px; color: var(--ink);
    cursor: pointer;
    transition: background 0.12s;
  }
  .suivi-picker-item:hover { background: var(--primary-soft); color: var(--primary); }
  .suivi-picker-custom {
    width: 100%; margin-top: 6px;
    padding: 8px 10px;
    background: transparent; border: 1px dashed var(--hairline);
    border-radius: var(--r-sm);
    font-size: 12px; color: var(--muted);
    cursor: pointer;
    transition: all 0.12s;
  }
  .suivi-picker-custom:hover { color: var(--primary); border-color: var(--primary); }
  .suivi-add-btn svg { width: 12px; height: 12px; }

  .suivi-list { display: flex; flex-direction: column; gap: 4px; margin-top: 4px; }
  .suivi-empty {
    padding: 24px 12px; text-align: center;
    font-size: 12px; color: var(--muted-soft);
  }

  /* Section historique livrables · entête plié, click pour déplier */
  .livr-history-toggle {
    display: flex; align-items: center; gap: 8px;
    width: 100%;
    margin-top: 12px;
    padding: 10px 12px;
    background: var(--surface-soft);
    border: 1px solid var(--hairline-soft);
    border-radius: var(--r-md);
    font-family: inherit;
    font-size: 12px; color: var(--body); font-weight: 500;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
    text-align: left;
  }
  .livr-history-toggle:hover {
    background: var(--canvas);
    border-color: var(--hairline);
  }
  .livr-history-chevron {
    width: 14px; height: 14px;
    color: var(--muted);
    flex-shrink: 0;
    transition: transform 0.15s;
  }
  .livr-history-toggle.expanded .livr-history-chevron {
    transform: rotate(90deg);
  }
  .livr-history-count {
    margin-left: auto;
    padding: 2px 8px;
    background: var(--canvas);
    border: 1px solid var(--hairline);
    border-radius: var(--r-pill);
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 11px; color: var(--muted);
  }
  .livr-history-list {
    margin-top: 6px;
    padding: 8px;
    background: var(--surface-soft);
    border-radius: var(--r-md);
    opacity: 0.92;
  }
  .livr-history-list .suivi-item { background: var(--canvas); }

  .suivi-item {
    display: flex; align-items: center; gap: 8px;
    padding: 8px 4px;
    border-bottom: 1px solid var(--hairline-soft);
    transition: background 0.12s;
  }
  .suivi-item:last-child { border-bottom: none; }
  .suivi-item:hover { background: var(--surface-soft); }

  /* Items sous-traitants · input nom (large) + dropdown contremaitre (lie
     uniquement) + bouton supprimer. */
  .suivi-item.st-item .st-name-input {
    flex: 1; min-width: 0;
    padding: 6px 10px;
    border: 1px solid var(--hairline);
    border-radius: var(--r-sm);
    background: var(--canvas);
    font-family: var(--font-body); font-size: 13px;
    color: var(--ink); outline: none;
    transition: border-color 0.15s;
  }
  .suivi-item.st-item .st-name-input:focus { border-color: var(--primary); }
  .suivi-item.st-item .st-name-input::placeholder { color: var(--muted-soft); font-style: italic; }
  /* Bouton 'Tag contremaitre' style team-picker · pill rond. Visible avec
     l avatar + initiales si un contremaitre est tag, sinon vide avec un '+'. */
  .suivi-item.st-item .st-cm-btn {
    flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
    width: 30px; height: 30px;
    padding: 0;
    border: 1px dashed var(--hairline);
    border-radius: var(--r-full);
    background: transparent;
    cursor: pointer;
    transition: border-color 0.15s, background 0.15s;
  }
  .suivi-item.st-item .st-cm-btn:hover {
    border-color: var(--primary);
    background: var(--primary-soft);
  }
  .suivi-item.st-item .st-cm-btn-active {
    border: none;
    background: transparent;
  }
  .suivi-item.st-item .st-cm-avatar {
    width: 28px; height: 28px; font-size: 11px;
  }
  .suivi-item.st-item .st-cm-plus {
    font-size: 16px; font-weight: 400;
    color: var(--muted-soft);
    line-height: 1;
  }
  .suivi-item.st-item .st-cm-btn:hover .st-cm-plus {
    color: var(--primary);
  }

  /* Badge d etat · pill cliquable qui cycle les etats */
  .suivi-state-badge {
    flex-shrink: 0;
    min-width: 70px; height: 22px; padding: 0 10px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: var(--r-pill);
    font-size: var(--text-caption); font-weight: 600; letter-spacing: 0.04em;
    text-transform: uppercase;
    cursor: pointer; user-select: none;
    border: 1px solid transparent;
    transition: filter 0.15s;
  }
  .suivi-state-badge:hover { filter: brightness(0.95); }
  .suivi-state-badge[data-state="a_faire"], .suivi-state-badge[data-state="a_preparer"] {
    background: var(--surface-soft); color: var(--muted);
    border-color: var(--hairline);
  }
  .suivi-state-badge[data-state="en_cours"], .suivi-state-badge[data-state="envoye"] {
    background: rgba(244,176,0,0.15); color: #b88500;
  }
  .suivi-state-badge[data-state="recu"] {
    background: var(--primary-soft); color: var(--primary);
  }
  .suivi-state-badge[data-state="fait"], .suivi-state-badge[data-state="signe"] {
    background: var(--surface-strong); color: var(--semantic-up);
  }
  .suivi-state-badge[data-state="bloque"] {
    background: rgba(220,53,69,0.15); color: #b02a37;
  }
  /* Etiquettes (Suivi) liees a un statut · badge devient un bouton 'Aller'
     / 'Actuel' pour deplacer la fiche dans une colonne du kanban. */
  .suivi-state-badge[data-state="current"] {
    background: var(--primary); color: var(--canvas);
    border-color: var(--primary);
  }
  .suivi-state-badge[data-state="move"] {
    background: transparent; color: var(--primary);
    border-color: var(--primary);
  }
  .suivi-state-badge[data-state="move"]:hover {
    background: var(--primary-soft);
  }
  /* Ligne 'actuelle' · bordure gauche + leger fond pour reperer la colonne en cours */
  .suivi-item.is-current-col {
    border-left: 3px solid var(--primary);
    background: var(--primary-soft);
    padding-left: 8px;
  }
  .suivi-item.is-current-col:hover { background: var(--primary-soft); }
  /* Libellé NON éditable · le déplacement manuel liste les colonnes du tableau,
     qui se renomment sur le tableau, pas ici. Sans ça le curseur promettait une
     saisie qui n'arrive jamais. */
  .suivi-label.suivi-fige { cursor: default; }

  /* LE DOSSIER EN BREF · une liste étiquette / valeur, en lecture.
     Pas de cadre par ligne, pas de case : ce n'est pas un formulaire, et il ne
     doit surtout pas en avoir l'air (c'est la confusion qu'on vient de
     retirer). Les valeurs en `--ink`, les étiquettes en `--muted`. */
  .suivi-resume-corps { display: flex; flex-direction: column; gap: var(--space-sm); }
  .suivi-resume-ligne { display: flex; flex-direction: column; gap: 1px; }
  .suivi-resume-label {
    font-size: var(--text-caption); color: var(--muted);
    text-transform: uppercase; letter-spacing: 0.05em;
  }
  .suivi-resume-valeur {
    font-size: var(--text-body); color: var(--ink); line-height: 1.5;
    word-break: break-word;
  }
  .suivi-resume-tel { color: var(--ink); text-decoration: underline; text-underline-offset: 2px; }
  .suivi-resume-tel:hover { text-decoration-thickness: 2px; }

  /* Journal · la boîte de note rapide, au-dessus du fil.

     ⚠ ELLE N'EST PAS UNE `.fiche-ta`, ET C'EST VOULU. Cette classe désigne les
     zones de texte qui doivent s'afficher AU COMPLET sans défiler (la
     description des travaux) : elle porte `field-sizing: content`, et fiche.js
     recalcule en plus leur hauteur en dur à chaque ouverture d'onglet. Une note
     rapide de deux lignes héritait donc d'une boîte de 544px. Elle emprunte
     l'apparence (elle est jointe aux sélecteurs de base plus bas) mais pas ce
     comportement. */
  .wf-note-add { display: flex; gap: 8px; align-items: flex-start; margin-bottom: 8px; }
  .wf-note-input {
    flex: 1; min-width: 0;
    height: 62px; resize: vertical;
    padding: 8px 12px; line-height: 1.5;
  }
  .wf-note-add .btn { flex-shrink: 0; }

  /* Label · editable inline (contenteditable) */
  .suivi-label {
    flex: 1; min-width: 0;
    font-size: 13px; color: var(--body);
    padding: 4px 6px;
    border-radius: var(--r-sm);
    cursor: text;
    word-break: break-word;
  }
  .suivi-label:hover { background: var(--surface-soft); }
  .suivi-label:focus { background: var(--canvas); outline: 1px solid var(--primary); }
  /* Item 'fait' · traitement visuel net (au-dela du petit badge vert) · la
     rangee entiere se teinte en vert + accent a gauche, le label est barre.
     Combine avec le tri (les faits descendent en bas de liste). */
  .suivi-item.done {
    background: color-mix(in srgb, var(--semantic-up) 9%, transparent);
    border-left: 3px solid var(--semantic-up);
    padding-left: 8px;
    border-radius: var(--r-md);
  }
  .suivi-item.done .suivi-label { text-decoration: line-through; color: var(--muted-soft); }
  /* Petit ✓ devant le libelle du badge 'Fait' · renforce le signal visuel. */
  .suivi-state-badge[data-state="fait"]::before,
  .suivi-state-badge[data-state="signe"]::before {
    content: "\2713";
    margin-right: 4px;
    font-weight: var(--weight-semibold);
  }

  /* Date · juste l icone calendrier + chip a cote si une date est selectionnee.
     Click sur l icone ouvre le calendrier custom partage (assets/date-picker.js,
     meme look que l Inventaire) en mode range. */
  .suivi-date-btn {
    flex-shrink: 0;
    width: 26px; height: 22px;
    display: inline-flex; align-items: center; justify-content: center;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--r-sm);
    color: var(--muted-soft);
    cursor: pointer;
    padding: 0;
    transition: color 0.15s, background 0.15s, border-color 0.15s;
  }
  .suivi-date-btn:hover {
    border-color: var(--hairline); background: var(--canvas); color: var(--ink);
  }
  .suivi-date-btn svg { width: 14px; height: 14px; }
  .suivi-date-btn.has-date { color: var(--primary); }
  .suivi-date-btn.has-date:hover { color: var(--primary); }
  .suivi-date-chip {
    flex-shrink: 0;
    font-size: 11px;
    color: var(--primary);
    font-family: var(--font-mono);
    white-space: nowrap;
    padding: 0 2px;
  }
  /* Labels d etiquettes liees a un statut · non editables (curseur normal,
     pas de bg/outline au hover · le label affecte le mapping avec la colonne). */
  .suivi-label[data-readonly] {
    cursor: default;
  }
  .suivi-label[data-readonly]:hover,
  .suivi-label[data-readonly]:focus {
    background: transparent;
    outline: none;
  }

  /* Bouton supprimer · apparait au hover */
  .suivi-del {
    flex-shrink: 0;
    width: 22px; height: 22px;
    display: inline-flex; align-items: center; justify-content: center;
    background: transparent; border: none;
    color: var(--muted-soft);
    cursor: pointer; opacity: 0;
    transition: opacity 0.12s, color 0.12s;
    border-radius: var(--r-full);
  }
  .suivi-item:hover .suivi-del { opacity: 1; }
  /* Highlight temporaire quand on arrive via deep-link de notif · le row
     pulse en Bleu primaire 2s puis retourne a normal. */
  @keyframes suivi-focus-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(10, 11, 13, 0.3); background: var(--primary-soft); }
    50%  { box-shadow: 0 0 0 6px rgba(10, 11, 13, 0); }
    100% { box-shadow: 0 0 0 0 rgba(10, 11, 13, 0); background: transparent; }
  }
  .suivi-item.focus-highlight {
    animation: suivi-focus-pulse 2.2s ease-out;
    border-radius: var(--r-md);
  }
  .suivi-del:hover { color: var(--semantic-down); background: rgba(220,53,69,0.1); }
  .suivi-del svg { width: 14px; height: 14px; }

  /* Bouton 'Note' · toujours visible (au lieu de seulement au hover). Couleur
     muted-soft si pas de note, primary si l item a une note (indicateur visuel). */
  .suivi-note-btn {
    flex-shrink: 0;
    width: 22px; height: 22px;
    display: inline-flex; align-items: center; justify-content: center;
    background: transparent; border: none;
    color: var(--muted-soft);
    cursor: pointer;
    transition: color 0.12s, background 0.12s;
    border-radius: var(--r-full);
  }
  .suivi-note-btn:hover { color: var(--primary); background: var(--primary-soft); }
  .suivi-note-btn.has-note { color: var(--primary); }
  .suivi-note-btn svg { width: 14px; height: 14px; }

  /* Zone expansible · note sous l item. Le save se fait au blur de la
     textarea. Pas de checkbox · si une assignee existe, elle est notifiee
     automatiquement quand la note a du contenu. */
  .suivi-note-panel {
    display: none;
    padding: 10px 8px 12px;
    margin-bottom: 4px;
    background: var(--surface-soft);
    border: 1px solid var(--hairline-soft);
    border-radius: var(--r-md);
  }
  .suivi-note-panel.open { display: block; }
  .suivi-note-panel textarea {
    width: 100%; min-height: 60px;
    padding: 8px 10px;
    background: var(--canvas);
    border: 1px solid var(--hairline);
    border-radius: var(--r-sm);
    font-family: var(--font-body);
    font-size: 13px; color: var(--ink);
    resize: vertical;
    transition: border-color 0.15s;
  }
  .suivi-note-panel textarea:focus { outline: none; border-color: var(--primary); }
  .suivi-note-panel textarea::placeholder { color: var(--muted-soft); }

  /* Fil de commentaires sur un livrable · pattern thread compact */
  .livr-comments-section {
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid var(--hairline-soft);
  }
  .livr-comments-list { display: flex; flex-direction: column; gap: 8px; }
  .livr-comments-list:empty { display: none; }
  .livr-comments-loading {
    font-size: 11px; color: var(--muted-soft); padding: 6px 0;
    font-style: italic;
  }
  .livr-comment {
    display: flex; align-items: flex-start; gap: 8px;
  }
  .livr-comment-avatar {
    flex-shrink: 0;
    width: 26px; height: 26px; border-radius: var(--r-full);
    background: var(--primary-soft); color: var(--primary);
    display: inline-flex; align-items: center; justify-content: center;
    font-size: var(--text-caption); font-weight: var(--weight-semibold);
    margin-top: 2px;
  }
  .livr-comment-body { flex: 1; min-width: 0; }
  .livr-comment-head {
    display: flex; align-items: baseline; gap: 8px;
    font-size: 11px;
  }
  .livr-comment-author { font-weight: 600; color: var(--ink); }
  .livr-comment-time { color: var(--muted-soft); font-family: var(--font-mono); }
  .livr-comment-content {
    margin-top: 2px; font-size: 13px; color: var(--body);
    line-height: 1.4; word-wrap: break-word;
  }
  .livr-comment-composer {
    display: flex; gap: 6px; align-items: flex-end;
    margin-top: 8px;
  }
  .livr-comment-input {
    flex: 1; min-height: 32px; max-height: 120px;
    padding: 7px 10px;
    background: var(--canvas);
    border: 1px solid var(--hairline);
    border-radius: var(--r-md);
    font-family: var(--font-body);
    font-size: 13px; color: var(--ink);
    resize: none;
    transition: border-color 0.15s;
  }
  .livr-comment-input:focus {
    outline: none; border-color: var(--primary);
  }
  .livr-comment-send {
    flex-shrink: 0;
    width: 34px; height: 34px;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--primary); color: var(--on-primary);
    border: none; border-radius: var(--r-full);
    cursor: pointer;
    transition: background 0.12s, transform 0.12s;
  }
  .livr-comment-send:hover {
    background: var(--ink); transform: scale(1.05);
  }
  .livr-comment-send svg { width: 14px; height: 14px; }

  /* Section Permis · fil de communication. Reutilise les classes livr-comment-*
     pour les messages + le composer; ce bloc ajoute le conteneur, l entete et le hint. */
  .permis-chat {
    margin-top: var(--space-base);
    padding-top: var(--space-base);
    border-top: 1px solid var(--hairline);
  }
  .permis-chat-head {
    display: flex; align-items: center; gap: 8px;
    font-size: 13px; font-weight: 600; color: var(--ink);
    margin-bottom: 10px;
  }
  .permis-chat-head svg { width: 16px; height: 16px; color: var(--muted); flex-shrink: 0; }
  .permis-chat-empty {
    font-size: 12px; color: var(--muted-soft); font-style: italic;
    padding: 2px 0 4px;
  }
  .permis-chat-hint {
    margin-top: 8px; font-size: 11px; color: var(--muted-soft);
    display: flex; align-items: center; gap: 5px;
  }
  .permis-chat-hint svg { width: 12px; height: 12px; flex-shrink: 0; }

  /* Hint sous la textarea · info uniquement, aucune action. Apparait avec
     un petit icone bell pour signaler la notification automatique. */
  .suivi-note-hint {
    display: flex; align-items: center; gap: 6px;
    margin-top: 8px;
    font-size: 11px; color: var(--muted);
    user-select: none;
  }
  .suivi-note-hint svg { width: 12px; height: 12px; flex-shrink: 0; color: var(--muted-soft); }
  .suivi-note-hint .name { color: var(--ink); font-weight: 500; }
  .suivi-note-hint .saved-hint {
    margin-left: auto; font-size: var(--text-caption); color: var(--semantic-up);
    opacity: 0; transition: opacity 0.2s;
  }
  .suivi-note-hint .saved-hint.show { opacity: 1; }

  /* ---------- Checklist nouveau contrat ---------- */
  .check-list { display: flex; flex-direction: column; gap: var(--space-xs); }
  .check-item {
    display: flex; align-items: flex-start; gap: 10px;
    padding: 10px 12px;
    background: var(--surface-soft);
    border: 1px solid var(--hairline-soft);
    border-radius: var(--r-md);
    transition: all 0.15s;
  }
  .check-item.done {
    background: var(--canvas);
    border-color: var(--semantic-up);
  }
  .check-item.done .check-circle {
    background: var(--semantic-up);
    border-color: var(--semantic-up);
    color: var(--canvas);
  }
  .check-circle {
    width: 22px; height: 22px;
    border-radius: var(--r-full);
    border: 2px solid var(--hairline);
    background: var(--canvas);
    flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    cursor: pointer;
    margin-top: 1px;
  }
  .check-circle svg { width: 12px; height: 12px; }
  .check-content { flex: 1; min-width: 0; }
  .check-title { font-size: 13px; font-weight: 600; color: var(--ink); margin-bottom: 2px; }
  .check-item.done .check-title { color: var(--semantic-up); }
  .check-meta { font-size: 11px; color: var(--muted); }
  .check-action {
    background: none; border: none;
    color: var(--primary); font-weight: 600; font-size: 11px;
    cursor: pointer; padding: 0;
    text-decoration: underline;
  }

  /* ---------- Bouton transition principal (Lancer production, etc.) ---------- */
  .stage-transition {
    background: var(--primary);
    color: var(--on-primary);
    border-radius: var(--r-xl);
    padding: var(--space-base) var(--space-lg);
    margin-bottom: var(--space-base);
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--space-base);
  }
  .stage-transition .text { font-size: 13px; }
  .stage-transition .text strong { display: block; font-size: 16px; margin-bottom: 2px; }
  .stage-transition .btn {
    background: var(--canvas);
    color: var(--primary);
    border: none;
    height: 40px; padding: 0 20px;
    border-radius: var(--r-pill);
    font-weight: 600; font-size: 13px;
    cursor: pointer;
    display: inline-flex; align-items: center; gap: 6px;
  }
  .stage-transition .btn:hover { background: var(--surface-soft); }
  .stage-transition .btn svg { width: 14px; height: 14px; }
  .stage-transition.disabled {
    background: var(--surface-strong);
    color: var(--muted);
  }
  .stage-transition.disabled .btn {
    background: var(--canvas);
    color: var(--muted);
    cursor: not-allowed;
    opacity: 0.6;
  }

  /* ---------- Données de vente (track 2) ---------- */
  .sales-grid {
    display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-sm) var(--space-base);
  }
  .sales-grid > div { font-size: 13px; }
  .sales-label {
    font-size: var(--text-caption); font-weight: 600;
    color: var(--muted); text-transform: uppercase; letter-spacing: 0.07em;
    margin-bottom: 2px;
  }
  .sales-value { color: var(--ink); font-family: var(--font-mono); font-weight: 600; }
  .sales-value.muted { color: var(--muted); font-style: italic; font-weight: 400; }

  /* ═══════════════════════════════════════════════════════
     WORKFLOW PROCESSUS · suit DESIGN.md
     Cartes canvas + hairline + r-xl, header sobre sans fond.
     Boutons pill 100px avec hauteur reduite (36-40px).
     ═══════════════════════════════════════════════════════ */
  .wf-step {
    display: flex; flex-direction: column;
    border: 1px solid var(--hairline);
    border-radius: var(--r-xl);
    background: var(--canvas);
    margin-bottom: var(--space-sm);
    overflow: hidden;
  }
  .wf-step-done   { opacity: 0.7; }
  .wf-step-closed { opacity: 0.7; }

  .wf-step-header {
    display: flex; align-items: center; gap: 12px;
    padding: 14px 18px;
    border-bottom: 1px solid var(--hairline-soft);
  }
  .wf-step-done .wf-step-header { border-bottom-color: transparent; }

  .wf-badge {
    width: 22px; height: 22px; border-radius: var(--r-full);
    display: flex; align-items: center; justify-content: center;
    font-size: 11px; font-weight: var(--weight-semibold); flex-shrink: 0;
  }
  .wf-badge-done    { background: var(--semantic-up);   color: #fff; }
  .wf-badge-current { background: var(--ink);            color: var(--canvas); }
  .wf-badge-closed  { background: var(--semantic-down);  color: #fff; }
  .wf-badge-future  { background: transparent; color: var(--muted); border: 1px solid var(--hairline); }

  .wf-step-meta { flex: 1; min-width: 0; }
  /* `.wf-step-num` retiré le 2026-07-30 avec le « ETAPE 1 » qu'il habillait ·
     la carte porte déjà le nom de l'étape. */
  .wf-step-label{ font-size: var(--text-body); font-weight: var(--weight-semibold); color: var(--ink); }
  .wf-step-date { font-size: 11px; color: var(--muted); font-family: var(--font-mono); flex-shrink: 0; }
  .wf-step-right {
    flex-shrink: 0;
    font-size: 11px;
    color: var(--muted);
    font-family: var(--font-mono);
  }

  .wf-step-body { padding: 16px 18px 18px 52px; }

  .wf-check-line {
    font-size: 12px; color: var(--body); line-height: 1.5;
  }
  .wf-result-pill {
    display: inline-block;
    font-size: 11px; font-weight: 500;
    padding: 1px 8px;
    border-radius: var(--r-pill);
    background: rgba(207, 32, 47, 0.10);
    color: var(--semantic-down);
    line-height: 1.5;
    vertical-align: baseline;
  }
  .wf-result-pill.ok {
    background: var(--surface-strong);
    color: var(--semantic-up);
  }

  /* Bandeau historique des tentatives precedentes · meme langage que .wf-step
     mais en muted/grisé pour signaler que c est secondaire (historique).
     S affiche au-dessus de l Etape 1 quand workflow_state.previous_attempts non vide. */
  .wf-history-card {
    border: 1px solid var(--hairline);
    border-radius: var(--r-xl);
    background: var(--canvas);
    margin-bottom: var(--space-sm);
    overflow: hidden;
  }
  .wf-history-head {
    display: flex; align-items: center; gap: 12px;
    padding: 14px 18px;
    cursor: pointer;
    transition: background 0.12s;
    user-select: none;
  }
  .wf-history-head:hover { background: var(--surface-soft); }
  .wf-history-card.expanded .wf-history-head { border-bottom: 1px solid var(--hairline-soft); }
  .wf-history-icon {
    width: 22px; height: 22px; border-radius: var(--r-full);
    background: var(--surface-strong); color: var(--muted);
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
  }
  .wf-history-icon svg { width: 12px; height: 12px; }
  .wf-history-meta { flex: 1; min-width: 0; }
  .wf-history-num {
    font-size: var(--text-caption); font-weight: 600; color: var(--muted);
    text-transform: uppercase; letter-spacing: 0.08em;
    margin-bottom: 1px;
  }
  .wf-history-summary {
    font-size: 13px; font-weight: 500; color: var(--ink);
  }
  .wf-history-chevron {
    width: 14px; height: 14px; color: var(--muted);
    flex-shrink: 0;
    transition: transform 0.2s;
  }
  .wf-history-card.expanded .wf-history-chevron { transform: rotate(180deg); }
  .wf-history-detail {
    display: none;
    padding: var(--space-base) var(--space-lg) var(--space-lg);
    background: var(--surface-soft);
  }
  .wf-history-card.expanded .wf-history-detail { display: block; }

  .wf-history-attempt + .wf-history-attempt {
    margin-top: var(--space-base);
    padding-top: var(--space-base);
    border-top: 1px solid var(--hairline-soft);
  }
  .wf-history-attempt-label {
    font-size: var(--text-caption); font-weight: 600; color: var(--muted);
    text-transform: uppercase; letter-spacing: 0.08em;
    margin-bottom: 8px;
  }
  .wf-history-events {
    display: flex; flex-direction: column; gap: 6px;
  }
  .wf-history-event {
    font-size: 12px; color: var(--body); line-height: 1.5;
    padding-left: 14px;
    position: relative;
  }
  .wf-history-event::before {
    content: "";
    position: absolute;
    left: 0; top: 7px;
    width: 4px; height: 4px;
    border-radius: var(--r-full);
    background: var(--muted);
  }
  .wf-history-close {
    margin-top: 8px;
    padding-left: 14px;
    font-size: 12px; line-height: 1.5;
    color: var(--semantic-down); font-weight: 500;
  }
  .wf-history-empty {
    font-size: 12px; color: var(--muted-soft);
    font-style: italic;
    padding-left: 14px;
  }

  /* Boutons workflow · suivent le pattern pill du design system,
     mais a echelle reduite pour les actions contextuelles (36px). */
  .wf-btn-group {
    display: flex; gap: 6px; flex-wrap: wrap;
    margin-top: 4px;
  }
  .wf-btn {
    display: inline-flex; align-items: center; justify-content: center;
    height: 36px; padding: 0 16px;
    border: 1px solid var(--hairline);
    border-radius: var(--r-pill);
    background: var(--canvas);
    color: var(--ink);
    font-family: var(--font-body);
    font-size: 13px; font-weight: 500;
    cursor: pointer;
    transition: background 0.12s, border-color 0.12s, color 0.12s;
  }
  .wf-btn:hover { background: var(--surface-soft); border-color: var(--ink); }
  .wf-btn-primary {
    background: var(--primary); color: var(--on-primary);
    border-color: transparent; font-weight: 600;
  }
  .wf-btn-primary:hover { background: var(--primary-active); border-color: transparent; }
  .wf-btn-danger {
    background: var(--canvas);
    color: var(--semantic-down);
    border-color: var(--hairline);
    font-weight: 500;
  }
  .wf-btn-danger:hover {
    background: var(--canvas);
    border-color: var(--semantic-down);
    color: var(--semantic-down);
  }

  .wf-scenario-grid {
    display: grid; grid-template-columns: 1fr 1fr; gap: 6px;
    margin-bottom: 8px;
  }
  .wf-scenario-btn {
    display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
    padding: 12px 14px;
    border: 1px solid var(--hairline); border-radius: var(--r-md);
    background: var(--canvas);
    cursor: pointer; transition: border-color 0.12s;
    text-align: left;
    font-family: var(--font-body);
  }
  .wf-scenario-btn:hover { border-color: var(--ink); }
  .wf-scenario-btn strong { font-size: 13px; font-weight: 600; color: var(--ink); }
  .wf-scenario-btn span   { font-size: 11px; color: var(--muted); }

  /* Outcomes (résultat de l'appel) · liste epuree */
  .wf-outcome-list {
    display: flex; flex-direction: column; gap: 4px;
    margin-bottom: 4px;
  }
  .wf-outcome-row {
    display: flex; align-items: center; justify-content: space-between;
    padding: 12px 14px; gap: 12px;
    border: 1px solid var(--hairline); border-radius: var(--r-md);
    background: var(--canvas);
    cursor: pointer; transition: border-color 0.12s, background 0.12s;
    font-family: var(--font-body);
  }
  .wf-outcome-row:hover {
    border-color: var(--ink);
    background: var(--surface-soft);
  }
  .wf-outcome-row > span:first-child { font-size: 13px; font-weight: 500; color: var(--ink); }
  .wf-outcome-row .meta { font-size: 11px; color: var(--muted); flex-shrink: 0; font-family: var(--font-mono); }
  .wf-outcome-row.close > span:first-child { color: var(--semantic-down); }
  .wf-outcome-row.close:hover { border-color: var(--semantic-down); }
  .wf-outcome-form {
    padding-top: 12px; margin-top: 8px;
    border-top: 1px solid var(--hairline-soft);
  }

  /* Picker de jours custom · cellules sobres, hover discret */
  .day-picker {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(56px, 1fr));
    gap: 4px;
    margin-bottom: 4px;
  }
  .day-cell {
    display: flex; flex-direction: column; align-items: center; gap: 1px;
    padding: 8px 4px;
    border: 1px solid var(--hairline); border-radius: var(--r-md);
    background: var(--canvas);
    cursor: pointer;
    font-family: var(--font-body);
    transition: border-color 0.12s, background 0.12s, color 0.12s;
    min-width: 0;
  }
  .day-cell:hover { border-color: var(--ink); }
  .day-cell.selected {
    border-color: var(--primary); background: var(--primary);
  }
  .day-cell .dow {
    font-size: var(--text-caption); text-transform: uppercase;
    color: var(--muted); letter-spacing: 0.04em;
  }
  .day-cell .dnum {
    font-size: 15px; font-weight: 500; color: var(--ink);
    font-family: var(--font-mono); line-height: 1.1;
    font-variant-numeric: tabular-nums;
  }
  .day-cell .dmon { font-size: var(--text-caption); color: var(--muted); }
  .day-cell.selected .dow,
  .day-cell.selected .dmon { color: rgba(255,255,255,0.75); }
  .day-cell.selected .dnum { color: #fff; }

  /* Picker de presets · chips pill */
  .preset-picker {
    display: flex; flex-wrap: wrap; gap: 6px;
    margin-bottom: 4px;
  }
  .preset-cell {
    padding: 7px 14px;
    border: 1px solid var(--hairline); border-radius: var(--r-pill);
    background: var(--canvas);
    cursor: pointer; font-family: var(--font-body); font-size: 12px; font-weight: 500;
    color: var(--ink);
    transition: border-color 0.12s, background 0.12s, color 0.12s;
  }
  .preset-cell:hover { border-color: var(--ink); }
  .preset-cell.selected {
    border-color: var(--primary); background: var(--primary); color: #fff;
  }

  /* Galerie photos jointes a la fiche (uploadees depuis le formulaire web) */
  .fiche-photos-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: 8px;
    margin-top: var(--space-xs);
  }
  .fiche-photo {
    position: relative; aspect-ratio: 1; overflow: hidden;
    border-radius: var(--r-md); border: 1px solid var(--hairline);
    background: var(--surface-soft);
    cursor: pointer; transition: border-color 0.15s, transform 0.15s;
  }
  .fiche-photo:hover { border-color: var(--primary); transform: scale(1.02); }
  .fiche-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }

  /* Visionneuse photos · plein ecran avec navigation */
  .photo-viewer {
    position: fixed; inset: 0; z-index: 9999;
    background: rgba(0,0,0,0.94);
    display: flex; flex-direction: column;
    user-select: none;
  }
  .photo-viewer-topbar {
    display: flex; align-items: center; justify-content: space-between;
    padding: var(--space-sm) var(--space-base);
    color: rgba(255,255,255,0.85);
    font-size: 13px; font-family: var(--font-mono);
  }
  .photo-viewer-counter { color: rgba(255,255,255,0.7); }
  .photo-viewer-close {
    background: rgba(255,255,255,0.1); border: none;
    color: #fff; font-size: 18px; line-height: 1;
    width: 36px; height: 36px; border-radius: var(--r-full);
    cursor: pointer; transition: background 0.15s;
    display: flex; align-items: center; justify-content: center;
  }
  .photo-viewer-close:hover { background: rgba(255,255,255,0.2); }
  .photo-viewer-stage {
    flex: 1; min-height: 0;
    display: flex; align-items: center; justify-content: center;
    position: relative;
    padding: 0 56px var(--space-base);
  }
  .photo-viewer-stage img {
    max-width: 100%; max-height: 100%;
    object-fit: contain;
    box-shadow: 0 10px 40px rgba(0,0,0,0.5);
    border-radius: var(--r-sm);
  }
  .photo-viewer-nav {
    position: absolute; top: 50%; transform: translateY(-50%);
    background: rgba(255,255,255,0.1); border: none;
    color: #fff; font-size: 24px; line-height: 1;
    width: 44px; height: 44px; border-radius: var(--r-full);
    cursor: pointer; transition: background 0.15s;
    display: flex; align-items: center; justify-content: center;
  }
  .photo-viewer-nav:hover { background: rgba(255,255,255,0.25); }
  .photo-viewer-nav:disabled { opacity: 0.25; cursor: default; }
  .photo-viewer-nav.prev { left: 8px; }
  .photo-viewer-nav.next { right: 8px; }
  .photo-viewer-thumbs {
    display: flex; gap: 6px; overflow-x: auto;
    padding: var(--space-sm) var(--space-base) var(--space-base);
    scrollbar-width: thin;
    justify-content: center;
  }
  .photo-viewer-thumb {
    width: 56px; height: 56px; flex-shrink: 0;
    border-radius: var(--r-sm); overflow: hidden;
    border: 2px solid transparent;
    cursor: pointer; transition: border-color 0.15s, opacity 0.15s;
    opacity: 0.5;
  }
  .photo-viewer-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
  .photo-viewer-thumb:hover { opacity: 1; }
  .photo-viewer-thumb.active { border-color: var(--primary); opacity: 1; }

  /* Visionneuse · variantes pour PDF et autres documents */
  .photo-viewer-stage iframe {
    width: 100%; height: 100%;
    border: none;
    background: var(--canvas);
    border-radius: var(--r-sm);
    box-shadow: 0 10px 40px rgba(0,0,0,0.5);
  }
  .photo-viewer-fallback {
    background: var(--canvas);
    border-radius: var(--r-xl);
    padding: var(--space-xxl) var(--space-xl);
    max-width: 480px;
    text-align: center;
    color: var(--ink);
  }
  .photo-viewer-fallback svg {
    width: 56px; height: 56px;
    stroke: var(--muted);
    margin-bottom: var(--space-base);
  }
  .photo-viewer-fallback .vf-name {
    font-family: var(--font-mono);
    font-size: 13px; font-weight: 500;
    color: var(--ink);
    word-break: break-all;
    margin-bottom: var(--space-sm);
  }
  .photo-viewer-fallback .vf-meta {
    font-size: 12px; color: var(--muted);
    margin-bottom: var(--space-lg);
  }
  .photo-viewer-fallback .vf-actions {
    display: flex; gap: 8px; justify-content: center;
  }

  /* Vignettes (thumb) sans image · placeholder pour PDF/autres */
  .photo-viewer-thumb.no-image {
    background: var(--surface-strong);
    display: flex; align-items: center; justify-content: center;
    color: var(--muted);
  }
  .photo-viewer-thumb.no-image svg { width: 18px; height: 18px; stroke: currentColor; }

  /* Titre du fichier en haut */
  .photo-viewer-name {
    color: var(--on-dark);
    font-size: 13px; font-weight: 500;
    flex: 1; text-align: center;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    padding: 0 var(--space-base);
  }

  .wf-form-row { margin-bottom: 12px; }
  .wf-form-row .ident-label {
    display: block;
    font-size: 11px; font-weight: 600;
    color: var(--muted);
    text-transform: uppercase; letter-spacing: 0.07em;
    margin-bottom: 6px;
  }

  /* Banner d'etat ferme · sobre, juste un avis */
  .wf-closed-banner {
    background: var(--canvas);
    border: 1px solid var(--hairline);
    border-radius: var(--r-xl);
    padding: var(--space-lg);
    text-align: center;
    font-size: 13px; color: var(--muted);
    line-height: 1.6;
    margin-bottom: var(--space-base);
  }
  .wf-closed-not-qualified {
    border-color: var(--hairline);
    color: var(--semantic-down);
    background: var(--canvas);
  }

  /* Journal des appels · header text-only sans fond */
  .wf-log-wrap {
    background: var(--canvas);
    border: 1px solid var(--hairline);
    border-radius: var(--r-xl);
    overflow: hidden;
    margin-top: var(--space-base);
  }
  .wf-log-head {
    font-size: 11px; font-weight: 600; color: var(--muted);
    text-transform: uppercase; letter-spacing: 0.08em;
    padding: 12px 16px 10px;
    border-bottom: 1px solid var(--hairline-soft);
  }
  .wf-log-entry {
    display: flex; gap: 12px; align-items: flex-start;
    padding: 12px 16px;
    border-bottom: 1px solid var(--hairline-soft);
    font-size: 13px;
  }
  .wf-log-entry:last-child { border-bottom: none; }
  .wf-log-icon {
    flex-shrink: 0; margin-top: 2px;
    color: var(--muted);
  }
  /* Le `font-size` ci-dessus dimensionnait un EMOJI · il ne dimensionne pas un
     SVG, qui prendrait sa taille intrinsèque et écraserait la ligne. */
  .wf-log-icon svg { width: 14px; height: 14px; display: block; }
  .wf-log-text { color: var(--ink); line-height: 1.5; margin-bottom: 2px; font-size: 13px; }
  .wf-log-meta { font-size: 11px; color: var(--muted); font-family: var(--font-mono); }

  /* Note ajout rapide */
  .wf-quick-note {
    display: flex; gap: 8px; align-items: flex-start;
    padding: 12px 16px;
    border-top: 1px solid var(--hairline-soft);
  }
  .wf-quick-note textarea {
    flex: 1;
    border: 1px solid var(--hairline); border-radius: var(--r-md);
    background: var(--canvas); color: var(--ink);
    font-family: inherit; font-size: 12px;
    padding: 7px 10px; resize: none; min-height: 36px;
    outline: none;
  }
  .wf-quick-note textarea:focus { border-color: var(--primary); }
  .wf-quick-note .btn { height: 36px; font-size: 12px; padding: 0 12px; flex-shrink: 0; }

  /* ---------- Champs éditables dans les cartes ---------- */
  .fiche-inp, .fiche-sel, .fiche-ta, .wf-note-input {
    width: 100%; box-sizing: border-box;
    border: 1px solid var(--hairline);
    border-radius: var(--r-sm);
    background: var(--canvas);
    color: var(--ink);
    font-family: inherit;
    font-size: 13px;
    padding: 6px 10px;
    outline: none;
    transition: border-color 0.15s, box-shadow 0.15s;
  }
  .fiche-inp:focus, .fiche-sel:focus, .fiche-ta:focus, .wf-note-input:focus {
    border-color: var(--primary);
    box-shadow: 0 0 0 3px var(--primary-soft);
  }
  .fiche-ta {
    resize: none;
    min-height: 80px;
    padding: 10px 12px;
    line-height: 1.55;
    /* Grandit automatiquement pour afficher tout le texte sans scroller
       (Chrome/Edge moderne). Fallback JS pour Firefox plus bas. */
    field-sizing: content;
    /* La textarea s'auto-redimensionne · pas besoin de scrollbar interne.
       Evite le glitch d'affichage qui apparait quand l'arrondi de hauteur
       provoque un scroll de quelques pixels. */
    overflow: hidden;
  }

  /* Photos client dans le Suivi : miniatures plus petites que dans Documents
     pour rester compactes a cote de la description. */
  #suivi-photos-grid {
    grid-template-columns: repeat(auto-fill, minmax(90px, 1fr)) !important;
    gap: 4px !important;
  }
  .fiche-sel { cursor: pointer; }

  /* Chips types de travaux éditables */
  .type-chip {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 4px 10px;
    border-radius: var(--r-pill);
    font-size: 11px;
    border: 1px solid var(--hairline);
    background: var(--surface-soft);
    color: var(--body);
    cursor: pointer;
    user-select: none;
    transition: all 0.12s;
  }
  .type-chip.selected {
    background: var(--primary);
    border-color: var(--primary);
    color: #fff;
  }
  .type-chip.selected:hover { opacity: 0.85; }
  /* Variante '+ Ajouter' · style plus discret, dashed, mute */
  .type-chip.type-chip-add {
    background: transparent;
    border-style: dashed;
    border-color: var(--hairline);
    color: var(--muted);
    font-weight: 500;
  }
  .type-chip.type-chip-add:hover {
    background: var(--primary-soft);
    border-color: var(--primary);
    border-style: solid;
    color: var(--primary);
  }
  .type-chips-wrap { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; }

  /* Save indicator */
  .save-dot {
    width: 7px; height: 7px; border-radius: var(--r-full);
    display: inline-block; background: var(--muted-soft);
    transition: background 0.3s;
  }
  .save-dot.saving { background: var(--accent-yellow); }
  .save-dot.saved  { background: var(--semantic-up); }
  .save-dot.error  { background: var(--semantic-down); }

  /* Mobile */
  @media (max-width: 768px) {
    .fiche-wrap { padding: var(--space-base); }
    .header-card { padding: var(--space-base); }
    .project-title { font-size: 24px; }
    /* Sur mobile on repasse en 2 colonnes qui s'empilent · il faut donc
       REMETTRE grid-auto-flow: row, sinon la règle de colonnes ci-dessus est
       ignorée (le flux « column » de la règle de base primerait). */
    .kpi-strip { grid-auto-flow: row; grid-template-columns: repeat(2, 1fr); }
    .quote-summary { grid-template-columns: repeat(2, 1fr); }
    .header-actions { width: 100%; }
  }

/* ============================================================
   Module SOUMISSION · préfixe `soum-` (isolation par préfixe · une seule
   fiche.css). Tout en tokens du design system.
   ============================================================ */
.soum-wrap { max-width: 760px; }
.soum-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: var(--space-base);
}
.soum-title { font-size: var(--text-h2); font-weight: var(--weight-semibold); color: var(--ink); }
.soum-saved { font-size: var(--text-caption); color: var(--semantic-success, #2e7d32); opacity: 0; transition: opacity 0.2s; }
.soum-saved.show { opacity: 1; }

.soum-card {
  background: var(--canvas);
  border: 1px solid var(--hairline);
  border-radius: var(--r-xl);
  padding: var(--space-base);
  margin-bottom: var(--space-base);
}
/* La carte qui accueille les champs CRÉÉS PAR LE CLIENT, posés dans une des
   parties de la soumission (db/186). Elle emprunte le rendu des champs de la
   fiche (`.ident-label` + contrôle) · un champ personnalisé doit se dessiner
   comme les autres, où qu'il soit posé. */
.soum-perso { display: grid; gap: var(--space-sm); }

.soum-sec-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: var(--space-sm);
}
.soum-sec-title, .soum-label {
  font-size: var(--text-caption); font-weight: var(--weight-semibold);
  color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em;
}
.soum-label { display: block; margin-bottom: 6px; }
.soum-total { font-size: var(--text-body); color: var(--body); }
.soum-total b { font-family: var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink); margin-left: 6px; }

.soum-input {
  width: 100%; box-sizing: border-box;
  background: var(--input-bg);
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
  padding: 8px 11px;
  font-family: var(--font-body); font-size: var(--text-body); color: var(--ink);
  transition: border-color 0.12s;
}
.soum-input:focus { outline: none; border-color: var(--ink); }
.soum-area { resize: vertical; line-height: 1.5; }
.soum-desc { resize: vertical; line-height: 1.5; }
.soum-prix {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums; text-align: right;
}

.soum-line, .soum-pay-line {
  display: grid; align-items: start; gap: 8px;
  margin-bottom: 8px;
}
.soum-line { grid-template-columns: 1fr 140px auto; }
.soum-pay-line { grid-template-columns: 1fr 120px auto; align-items: center; }

.soum-del {
  background: none; border: none; cursor: pointer;
  color: var(--muted); font-size: 20px; line-height: 1;
  padding: 4px 6px; border-radius: var(--r-md);
}
.soum-del:hover { color: var(--semantic-danger, #c0392b); background: var(--surface-soft); }

.soum-add {
  background: none; border: 1px dashed var(--hairline);
  border-radius: var(--r-md); cursor: pointer;
  padding: 7px 12px; font-family: var(--font-body); font-size: var(--text-caption);
  color: var(--muted); width: 100%; margin-top: 2px;
}
.soum-add:hover { border-color: var(--ink); color: var(--ink); }

.soum-ro-note { font-size: var(--text-caption); color: var(--muted); font-style: italic; }

/* Bas de soumission · sous-total, rabais, taxes, total. */
.soum-tot-ligne {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-base);
  padding: 7px 0;
  font-size: var(--text-body); color: var(--body);
}
.soum-tot-ligne b {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  color: var(--ink); font-weight: 400;
}
.soum-tot-final {
  border-top: 1px solid var(--hairline);
  margin-top: 4px; padding-top: 11px;
  font-weight: var(--weight-semibold); color: var(--ink);
}
.soum-tot-final b { font-size: var(--text-h2); font-weight: var(--weight-semibold); }

.soum-rabais-l { display: flex; align-items: center; gap: 8px; }
.soum-rabais-inp {
  width: 72px; text-align: right; padding: 5px 8px;
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
}
.soum-rabais-pct { color: var(--muted); font-size: var(--text-caption); }

.soum-tax-nums {
  margin-top: var(--space-sm); padding-top: var(--space-sm);
  border-top: 1px solid var(--hairline);
  font-size: var(--text-caption); color: var(--muted);
  font-family: var(--font-mono);
}
.soum-tax-vide {
  margin-top: var(--space-sm);
  font-size: var(--text-caption); color: var(--muted); font-style: italic;
}

/* ============================================================
   Module BUDGET · préfixe `bud-`. Tout en tokens.
   ============================================================ */
.bud-wrap { max-width: 680px; }
.bud-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: var(--space-base);
}
.bud-title { font-size: var(--text-h2); font-weight: var(--weight-semibold); color: var(--ink); }
.bud-saved { font-size: var(--text-caption); color: var(--semantic-success, #2e7d32); opacity: 0; transition: opacity 0.2s; }
.bud-saved.show { opacity: 1; }

.bud-card {
  background: var(--canvas);
  border: 1px solid var(--hairline);
  border-radius: var(--r-xl);
  padding: var(--space-base);
  margin-bottom: var(--space-base);
}
.bud-sec-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-sm); }
.bud-sec-title {
  font-size: var(--text-caption); font-weight: var(--weight-semibold);
  color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em;
  margin-bottom: var(--space-sm); display: block;
}
.bud-sec-head .bud-sec-title { margin-bottom: 0; }
.bud-total { font-size: var(--text-body); color: var(--body); }
.bud-total b { font-family: var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink); margin-left: 6px; }

.bud-line { display: flex; align-items: center; justify-content: space-between; gap: var(--space-base); margin-bottom: 8px; }
.bud-line:last-child { margin-bottom: 0; }
.bud-label { font-size: var(--text-body); color: var(--body); }
.bud-input-wrap { display: flex; align-items: center; gap: 6px; flex: none; }
.bud-input {
  width: 130px; box-sizing: border-box; text-align: right;
  background: var(--input-bg);
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
  padding: 8px 11px;
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--text-body); color: var(--ink);
}
.bud-input:focus { outline: none; border-color: var(--ink); }
.bud-suffixe { font-size: var(--text-caption); color: var(--muted); width: 14px; }

/* Prévu contre réel · le coeur du module. */
.bud-vide { font-size: var(--text-caption); color: var(--muted); line-height: 1.55; }
.bud-vide b { font-family: var(--font-mono); color: var(--body); }
.bud-compare { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-sm); }
.bud-kpi {
  background: var(--surface-soft); border-radius: var(--r-md);
  padding: 10px 12px; display: flex; flex-direction: column; gap: 2px;
}
.bud-kpi-l { font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
.bud-kpi b { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--text-h2); font-weight: var(--weight-semibold); color: var(--ink); }
/* ⚠ `--semantic-danger` N'EXISTE PAS · les deux règles ci-dessus le lisaient
   derrière un repli, donc le contrôle des tokens ne pouvait rien voir (un repli
   est un choix assumé) et l'écran affichait un rouge #c0392b qui n'est celui
   d'aucun autre retard de la plateforme. Les vrais jetons sont ceux-ci. */
.bud-kpi-depasse b   { color: var(--semantic-down); }
.bud-kpi-attention b { color: var(--semantic-warn-ink); }
.bud-kpi-ok b        { color: var(--semantic-success); }

.bud-jauge {
  grid-column: 1 / -1;
  height: 6px; border-radius: var(--r-pill);
  background: var(--surface-strong); overflow: hidden;
}
.bud-jauge span { display: block; height: 100%; background: var(--ink); transition: width 0.2s; }
/* LES TROIS ÉTATS · le seuil qui les sépare est réglé par le client
   (module_settings du module Budget). La couleur ne décide de rien · elle
   REND une décision prise dans `etatDeBarre`, un seul endroit, pour que la
   fiche et la carte ne puissent pas se contredire. */
.bud-jauge-ok span        { background: var(--semantic-success); }
.bud-jauge-attention span { background: var(--semantic-warn-ink); }
.bud-jauge-depasse span   { background: var(--semantic-down); }
.bud-pct { grid-column: 1 / -1; font-size: var(--text-caption); color: var(--muted); }

/* Les TROIS mesures comparées · heures, main-d'oeuvre, matériaux. Empilées et
   séparées par un filet · trois grilles collées se lisaient comme une seule. */
.bud-mesures { display: flex; flex-direction: column; }
.bud-mesure { padding: var(--space-base) 0; }
.bud-mesure:first-child { padding-top: 0; }
.bud-mesure:last-child { padding-bottom: 0; }
.bud-mesure + .bud-mesure { border-top: 1px solid var(--hairline); }
.bud-mesure-t {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--muted); font-weight: var(--weight-semibold);
  margin-bottom: var(--space-xs);
}
/* Une mesure sans source ou sans prévu ne montre PAS de barre · une barre à
   zéro se lirait « rien consommé », ce qui est exactement le contresens qu'on
   veut éviter sur un chantier. */
.bud-mesure-vide .bud-vide { margin: 0; }

.bud-ro-note { font-size: var(--text-caption); color: var(--muted); font-style: italic; }

/* Champs personnalisés · types chiffrés (montant, pourcentage, mesure).
   Le suffixe dit l'unité · elle est une propriété du champ, pas un mot collé
   dans son nom. Préfixe `cfp-` (assets/custom-fields.js). */
.cfp-mesure { display: flex; align-items: center; gap: 6px; }
.cfp-mesure .cfp-num { flex: 1; min-width: 0; text-align: right;
  font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.cfp-unite { font-size: var(--text-caption); color: var(--muted); white-space: nowrap; min-width: 18px; }
.cfp-area { resize: vertical; min-height: 64px; line-height: 1.5; }
.cfp-multi { display: flex; flex-wrap: wrap; gap: 6px 14px; padding: 6px 0; }
.cfp-case { display: flex; align-items: center; gap: 5px; font-size: var(--text-body); color: var(--body); cursor: pointer; }
.cfp-calcul {
  display: inline-block; padding: 8px 0;
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--text-body); color: var(--ink);
}
.cfp-calcul.is-vide { color: var(--muted); }

/* ============================================================
   Module TÂCHES · préfixe `tk-`. Sorti du module Suivi, qui portait deux
   listes figées. Tout en tokens.
   ============================================================ */
.tk-wrap { max-width: 900px; }
.tk-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-base); }
.tk-title { font-size: var(--text-h2); font-weight: var(--weight-semibold); color: var(--ink); }
.tk-saved { font-size: var(--text-caption); color: var(--semantic-success, #2e7d32); opacity: 0; transition: opacity .2s; }
.tk-saved.show { opacity: 1; }
.tk-vide { font-size: var(--text-caption); color: var(--muted); font-style: italic; }

.tk-card {
  background: var(--canvas); border: 1px solid var(--hairline);
  border-radius: var(--r-xl); padding: var(--space-base); margin-bottom: var(--space-base);
}
.tk-card-head { display: flex; align-items: center; gap: var(--space-sm); margin-bottom: var(--space-sm); }
.tk-card-head .tk-compte { margin-left: auto; }
.tk-card-title { font-size: var(--text-body); font-weight: var(--weight-semibold); color: var(--ink); }
.tk-tag {
  font-size: 11px; color: var(--muted); border: 1px solid var(--hairline);
  border-radius: var(--r-pill); padding: 1px 8px; margin-left: 8px; font-weight: 400;
}
.tk-compte { font-size: var(--text-caption); color: var(--muted); }

.tk-list { display: flex; flex-direction: column; gap: 4px; }
.tk-empty { font-size: var(--text-caption); color: var(--muted); font-style: italic; padding: 4px 0; }

.tk-item {
  display: flex; align-items: flex-start; gap: var(--space-xs);
  padding: 3px 8px;
  transition: background .12s;
}
/* UN FILET ENTRE LES TÂCHES · sans lui, « on dirait juste du texte qui se
   pitche dans un fond blanc ». Une liste a besoin de ses lignes pour se lire
   comme une liste. Pas sur la première · un filet en haut de carte doublerait
   le trait de l'en-tête. */
.tk-item + .tk-item { border-top: 1px solid var(--hairline-soft); }
/* `.tk-main` REDEVIENT une colonne · la rangée du libellé, puis les réglages
   dessous. C'est `.tk-ligne` qui met le libellé et les icônes côte à côte. */
.tk-ligne {
  display: flex; align-items: center; gap: var(--space-xs);
  width: 100%; min-height: 34px;
}
.tk-ligne > .tk-label { flex: 1; min-width: 0; }
.tk-item:hover { background: var(--surface-soft); }
.tk-list { display: flex; flex-direction: column; }
.tk-item.is-fait .tk-label { text-decoration: line-through; color: var(--muted); }
/* ═══ LA PASTILLE D'ÉTAT · l'interrupteur de la tâche ══════════════
   Elle remplace la case à cocher. Une case à cocher est petite, muette, et
   ne dit pas dans quel état on est · une pastille écrit « À faire » ou
   « Fait », et c'est elle qu'on clique. Même largeur dans les deux états,
   sinon les libellés de la liste dansent d'un cran à chaque clic. */
.tk-etat {
  flex: none; margin-top: 2px;
  display: inline-flex; align-items: center; justify-content: center; gap: 4px;
  min-width: 76px; padding: 4px 10px;
  border: none; border-radius: var(--r-pill);
  background: var(--surface-strong); color: var(--muted);
  font-family: var(--font-body); font-size: var(--text-caption); font-weight: 600;
  text-transform: uppercase; letter-spacing: .04em;
  cursor: pointer; transition: background .12s, color .12s;
}
.tk-etat svg { width: 12px; height: 12px; }
.tk-etat:hover:not(:disabled) { background: var(--hairline); color: var(--ink); }
.tk-etat.est-fait { background: var(--semantic-success-soft); color: var(--semantic-success); }
.tk-etat:disabled { cursor: default; }

/* Les réglages en ICÔNES · discrets, et ils disent s'ils portent une valeur. */
/* Les icônes se tiennent EN BOUT DE LIGNE, toutes à la même abscisse d'une
   tâche à l'autre · c'est l'alignement qui fait qu'une liste se lit comme une
   liste. `margin-left: auto` les pousse à droite quel que soit le libellé. */
.tk-outils {
  display: flex; align-items: center; gap: 0;
  flex: none; margin-left: auto;
}
.tk-outil {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 5px; border: none; border-radius: var(--r-md);
  background: transparent; color: var(--muted-soft); cursor: pointer;
  transition: background .12s, color .12s, opacity .12s;
}
.tk-outil svg { width: 13px; height: 13px; }
/* TRÈS discrètes au repos, franches au survol · quatre icônes à pleine force
   sur chaque tâche font un mur de gris qui concurrence le texte, alors que le
   texte est ce qu'on vient lire. Celles qui portent une valeur restent
   visibles en permanence (`.a-valeur`) · c'est de l'information, pas un outil. */
.tk-outil { opacity: .35; }
.tk-item:hover .tk-outil { opacity: .8; }
.tk-outil:hover { opacity: 1 !important; }
.tk-outil:hover { background: var(--surface-strong); color: var(--ink); }
.tk-outil.a-valeur { color: var(--ink); opacity: 1; }
.tk-outil-val { font-family: var(--font-mono); font-size: var(--text-caption); }

/* Le champ date est INVISIBLE mais présent, collé sous son icône · c'est sa
   position qui décide où le calendrier natif s'ouvre. `display:none` le
   rendrait inutilisable (showPicker refuse un champ non rendu), d'où la taille
   nulle plutôt qu'un masquage. */
.tk-outil-wrap { position: relative; display: inline-flex; }
.tk-date-cache {
  position: absolute; left: 0; bottom: 0;
  width: 1px; height: 1px; padding: 0; border: 0;
  opacity: 0; pointer-events: none;
}
.tk-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }

.tk-label {
  width: 100%; box-sizing: border-box;
  background: transparent; border: 1px solid transparent; border-radius: var(--r-md);
  padding: 3px 8px; font-family: var(--font-body); font-size: var(--text-body); color: var(--ink);
}
.tk-label:hover { border-color: var(--hairline); }
.tk-label:focus { outline: none; border-color: var(--ink); background: var(--canvas); }

.tk-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 4px 8px 2px; }
.tk-date, .tk-resp {
  background: var(--input-bg); border: 1px solid var(--hairline); border-radius: var(--r-md);
  padding: 3px 8px; font-family: var(--font-body); font-size: var(--text-caption); color: var(--body);
}
.tk-date { font-family: var(--font-mono); }
.tk-doc-add, .tk-notes-btn, .tk-doc-del {
  background: none; border: 1px solid var(--hairline); border-radius: var(--r-pill);
  padding: 3px 10px; cursor: pointer;
  font-family: var(--font-body); font-size: var(--text-caption); color: var(--muted);
}
.tk-doc-add:hover, .tk-notes-btn:hover { border-color: var(--ink); color: var(--ink); }
.tk-doc { display: inline-flex; align-items: center; gap: 4px; font-size: var(--text-caption); }
.tk-doc a { color: var(--ink); text-decoration: underline; text-underline-offset: 2px; }
.tk-doc-del { border: none; padding: 0 4px; font-size: 15px; }
.tk-doc-del:hover { color: var(--semantic-danger, #c0392b); }

.tk-notes {
  width: 100%; box-sizing: border-box; margin-left: 8px;
  background: var(--input-bg); border: 1px solid var(--hairline); border-radius: var(--r-md);
  padding: 6px 9px; font-family: var(--font-body); font-size: var(--text-caption);
  color: var(--body); resize: vertical; line-height: 1.5;
}
.tk-notes:focus { outline: none; border-color: var(--ink); }

.tk-resp-pastille {
  flex: none; width: 24px; height: 24px; border-radius: var(--r-full);
  background: var(--surface-strong); color: var(--body);
  display: flex; align-items: center; justify-content: center;
  font-size: 10px; font-weight: var(--weight-semibold); margin-top: 6px;
}
.tk-del {
  flex: none; background: none; border: none; cursor: pointer;
  color: var(--muted); font-size: 18px; line-height: 1; padding: 6px; border-radius: var(--r-md);
}
.tk-del:hover { color: var(--semantic-danger, #c0392b); }

/* Le ROND du responsable · initiales ou « + ». On clique dessus, une liste
   s'ouvre. Un menu déroulant natif prenait la largeur d'un champ pour une
   information qui tient dans un rond, et répétait le nom deux fois. */
.tk-rond {
  flex: none; width: 24px; height: 24px; border-radius: var(--r-full);
  display: inline-flex; align-items: center; justify-content: center;
  margin-left: 4px; border: none; cursor: pointer;
  background: var(--primary); color: var(--canvas);
  font-family: var(--font-body); font-size: 10px; font-weight: 600;
  letter-spacing: .02em;
}
.tk-rond.est-vide {
  background: transparent; color: var(--muted-soft);
  border: 1px dashed var(--hairline); font-size: var(--text-caption); font-weight: 400;
}
.tk-rond:hover { opacity: .85; }
.tk-rond.est-vide:hover { border-color: var(--ink); color: var(--ink); opacity: 1; }

/* La liste des personnes · posée sur le document pour ne pas être coupée par
   le débordement de la carte. */
.tk-menu {
  position: absolute; z-index: 60; min-width: 220px; max-height: 280px; overflow-y: auto;
  background: var(--canvas); border: 1px solid var(--hairline);
  border-radius: var(--r-lg); box-shadow: var(--shadow-hover); padding: 6px;
}
.tk-menu-titre {
  font-size: var(--text-caption); font-weight: 600; color: var(--muted);
  text-transform: uppercase; letter-spacing: .05em; padding: 6px 8px 8px;
}
.tk-menu-item {
  display: flex; align-items: center; gap: var(--space-xs); width: 100%;
  padding: 7px 8px; border: none; border-radius: var(--r-md);
  background: transparent; color: var(--ink); cursor: pointer;
  font-family: var(--font-body); font-size: var(--text-label); text-align: left;
}
.tk-menu-item:hover { background: var(--surface-soft); }
.tk-menu-item.est-choisi { background: var(--primary-soft); font-weight: 600; }
.tk-menu-rond {
  flex: none; width: 22px; height: 22px; border-radius: var(--r-full);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface-strong); color: var(--body);
  font-size: 10px; font-weight: 600;
}

/* « + Ajouter » vit DANS L'EN-TÊTE de la liste, à droite · c'est là qu'on le
   cherche, et ça évite une bande pointillée pleine largeur au bas de chaque
   carte. Il était en bas, sur toute la largeur, avec le texte « + Ajouter une
   tâche » · la carte se terminait par un bouton plus visible que son contenu. */
.tk-add {
  flex: none;
  background: var(--primary-soft); border: none; border-radius: var(--r-pill);
  padding: 5px 12px; cursor: pointer;
  font-family: var(--font-body); font-size: var(--text-caption); font-weight: 600;
  color: var(--ink);
}
.tk-add:hover { background: var(--surface-strong); }
/* Les tâches HABITUELLES d'une liste · proposées tant qu'elle est vide. */
.tk-defauts {
  width: 100%; margin-top: 6px; text-align: left;
  background: var(--surface-soft); border: 1px solid var(--hairline);
  border-radius: var(--r-md); padding: 9px 12px; cursor: pointer;
  font-family: var(--font-body); font-size: var(--text-caption); color: var(--ink);
  display: flex; flex-direction: column; gap: 2px;
}
.tk-defauts:hover { border-color: var(--ink); }
.tk-defauts-liste { color: var(--muted); font-size: 11px; }
