/* ============================================================
   Acordo — design system (handoff « Acordo Redesign »)
   Tokens dans css/tokens/*.css (chargés via css/styles.css AVANT ce fichier).
   Shell : sidebar 248px + topbar 60px. Fonts self-hostées.
   ============================================================ */

/* ---------- Fonts (self-hosted, wwwroot/fonts) ---------- */
@font-face {
    font-family: 'Archivo';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('fonts/archivo-v25-latin_latin-ext-600.woff2') format('woff2');
}

@font-face {
    font-family: 'Archivo';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('fonts/archivo-v25-latin_latin-ext-700.woff2') format('woff2');
}

@font-face {
    font-family: 'Archivo';
    font-style: normal;
    font-weight: 800;
    font-display: swap;
    src: url('fonts/archivo-v25-latin_latin-ext-800.woff2') format('woff2');
}

@font-face {
    font-family: 'IBM Plex Sans';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('fonts/ibm-plex-sans-v23-latin_latin-ext-regular.woff2') format('woff2');
}

@font-face {
    font-family: 'IBM Plex Sans';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('fonts/ibm-plex-sans-v23-latin_latin-ext-500.woff2') format('woff2');
}

@font-face {
    font-family: 'IBM Plex Sans';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('fonts/ibm-plex-sans-v23-latin_latin-ext-600.woff2') format('woff2');
}

@font-face {
    font-family: 'IBM Plex Sans';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('fonts/ibm-plex-sans-v23-latin_latin-ext-700.woff2') format('woff2');
}

@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('fonts/ibm-plex-mono-v20-latin_latin-ext-regular.woff2') format('woff2');
}

@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('fonts/ibm-plex-mono-v20-latin_latin-ext-500.woff2') format('woff2');
}

@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('fonts/ibm-plex-mono-v20-latin_latin-ext-600.woff2') format('woff2');
}

/* ---------- Base ---------- */
* { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--surface-page);
    color: var(--text-body);
    font-family: var(--font-sans);
    font-size: var(--text-md);
    line-height: var(--lh-normal);
}

h1:focus { outline: none; }

h1, h2, h3 { font-family: var(--font-display); color: var(--text-strong); letter-spacing: var(--ls-snug); }

a { color: var(--text-link); }

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { transition: none !important; animation: none !important; }
}

/* ---------- Shell : sidebar + topbar ---------- */
.shell { display: flex; min-height: 100vh; }

.sidebar {
    width: var(--sidebar-w);
    flex: none;
    background: var(--white);
    border-right: 1px solid var(--border-subtle);
    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
}

.brand {
    display: flex;
    align-items: center;
    gap: 10px;
    height: var(--topbar-h);
    flex: none;
    padding: 0 18px;
    border-bottom: 1px solid var(--border-subtle);
    text-decoration: none;
    color: inherit;
}

.brand-mark {
    width: 30px;
    height: 30px;
    border-radius: var(--radius-sm);
    background: var(--ink-950);
    color: var(--white);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-mono);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.02em;
    flex: none;
}

.brand-text h1 {
    margin: 0;
    font-family: var(--font-display);
    font-size: 21px;
    font-weight: 800;
    letter-spacing: var(--ls-tight);
    color: var(--ink-950);
    line-height: 1;
}

.brand-text h1 .brand-dot { color: var(--orange-600); }

.tenant-box {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin: 10px 12px 6px;
    padding: 8px 10px;
    background: var(--slate-50);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
}

.tenant-box .t-name { display: block; font-size: var(--text-sm); font-weight: var(--fw-semibold); color: var(--text-strong); line-height: 1.25; }
.tenant-box .t-sub { display: block; font-size: var(--text-2xs); color: var(--text-muted); line-height: 1.25; }

.side-nav { display: flex; flex-direction: column; gap: 2px; padding: 4px 12px 12px; flex: 1; }

.side-nav a {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 10px;
    border-radius: var(--radius-sm);
    color: var(--slate-600);
    font-size: var(--text-md);
    font-weight: var(--fw-medium);
    text-decoration: none;
    transition: background 130ms ease-out, color 130ms ease-out;
}

.side-nav a svg { flex: none; }
.side-nav a .nav-label { flex: 1; min-width: 0; }
.side-nav a .nav-plus { color: var(--text-subtle); display: inline-flex; }
.side-nav a:hover:not(.active) { background: var(--surface-hover); color: var(--text-strong); }
.side-nav a.active { background: var(--surface-brand-soft); color: var(--orange-700); font-weight: var(--fw-semibold); }
.side-nav a.active .nav-plus { display: none; }
.side-nav .nav-spacer { flex: 1; min-height: 24px; }
.side-nav .nav-divider { height: 1px; background: var(--border-subtle); margin: 8px 4px; }

.main-col { flex: 1; display: flex; flex-direction: column; min-width: 0; }

.topbar {
    display: flex;
    align-items: center;
    gap: 14px;
    height: var(--topbar-h);
    flex: none;
    padding: 0 24px 0 30px;
    background: var(--white);
    border-bottom: 1px solid var(--border-subtle);
    position: sticky;
    top: 0;
    z-index: 50;
}

.searchbox {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1;
    max-width: 380px;
    height: 34px;
    padding: 0 12px;
    background: var(--slate-50);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    color: var(--text-subtle);
}

.searchbox input {
    flex: 1;
    min-width: 0;
    border: none;
    outline: none;
    background: transparent;
    font-family: inherit;
    font-size: var(--text-sm);
    color: var(--text-strong);
}

.searchbox input::placeholder { color: var(--text-subtle); }
.searchbox:focus-within { border-color: var(--border-focus); box-shadow: var(--ring); }

.topbar-spacer { flex: 1; }
.topbar-sep { width: 1px; height: 24px; background: var(--border-subtle); flex: none; }

.bell {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    height: 32px;
    padding: 0 12px;
    background: var(--white);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-pill);
    font-size: var(--text-sm);
    font-weight: var(--fw-semibold);
    color: var(--text-body);
    text-decoration: none;
    white-space: nowrap;
    transition: border-color 130ms ease-out, color 130ms ease-out;
}

.bell:hover { border-color: var(--border-strong); color: var(--text-strong); }

.bell .count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: var(--radius-pill);
    background: var(--orange-600);
    color: #fff;
    font-size: 10px;
    font-weight: var(--fw-bold);
}

.user-area { display: flex; align-items: center; gap: 9px; }

.avatar {
    width: 32px;
    height: 32px;
    flex: none;
    border-radius: 50%;
    background: var(--blue-600);
    color: #fff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    font-weight: var(--fw-semibold);
}

.user-meta { display: flex; flex-direction: column; align-items: flex-start; line-height: 1.2; }
.user-meta .u-name { font-size: var(--text-sm); font-weight: var(--fw-semibold); color: var(--text-strong); }
.user-meta .u-role { font-size: var(--text-2xs); color: var(--text-muted); }

.role-chip {
    font-size: var(--text-2xs);
    font-weight: var(--fw-bold);
    background: var(--surface-brand-soft);
    color: var(--orange-700);
    padding: 4px 10px;
    border-radius: var(--radius-pill);
    white-space: nowrap;
}

.logout {
    background: none;
    border: none;
    color: var(--text-link);
    font-size: var(--text-sm);
    font-weight: var(--fw-medium);
    cursor: pointer;
    text-decoration: none;
    padding: 0;
    margin-left: 6px;
    font-family: var(--font-sans);
}

.logout:hover { color: var(--blue-700); text-decoration: underline; }

/* Aucun plafond de largeur : toutes les pages occupent l'écran. Deux gabarits
   différents selon la page (liste large / fiche bornée) donnaient une appli qui
   change de largeur à chaque navigation, ce qui se voit plus que le confort de
   lecture que le plafond apportait. */
/* `flex: 1` et non une hauteur : le contenu absorbe la place restante de la
   colonne (`.shell` fait 100vh au minimum), ce qui pousse le pied de page au
   BAS DE L'ÉCRAN sur une page courte — sans lui, CGU et mentions légales se
   posaient juste sous la dernière carte, au milieu du vide. Base `auto` et
   `flex-shrink: 0` : le pied reste en FLUX, il n'est pas collé en `fixed`, donc
   sur une page longue il redescend sous le contenu au lieu de manger une bande
   de l'écran à chaque défilement. */
.content { padding: 26px 30px 34px; min-width: 0; width: 100%; flex: 1 0 auto; }

/* Layout non authentifié (Login, erreurs) : contenu centré sans sidebar */
.shell-plain { max-width: 560px; margin: 0 auto; padding: 40px 20px 80px; }

/* ---------- En-tête de page ---------- */
.page-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 22px;
    flex-wrap: wrap;
}

.page-head h1 {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--text-3xl);
    font-weight: var(--fw-black);
    letter-spacing: var(--ls-tight);
    color: var(--text-strong);
}

/* Variante compacte, pour une page dont le contenu se présente tout seul
   (liste avec bandeau de synthèse) : titre d'un cran plus bas, sans sous-titre,
   actions centrées sur le titre. Gagne ~35 px de haut de page. */
.page-head--tight { align-items: center; margin-bottom: 14px; }
.page-head--tight h1 { font-size: var(--text-2xl); }

.page-head .sub { margin: 5px 0 0; font-size: var(--text-md); color: var(--text-muted); }

/* Tête d'une fiche à recherche : grille 2 × 2 — titre / actions, puis
   sous-titre / recherche. La recherche s'aligne sur le bord droit des boutons
   et non dans leur rangée : elle ne modifie rien et n'a pas à se lire comme
   une action. En dessous de 900 px la grille passe en colonne — deux colonnes
   sur un téléphone rognent le titre pour un champ de 260 px. */
.page-head--split {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: start;
    column-gap: 16px;
    row-gap: 8px;
}
.page-head--split h1 { grid-area: 1 / 1; }
.page-head--split .actions { grid-area: 1 / 2; justify-self: end; }
.page-head--split .sub { grid-area: 2 / 1; margin: 0; align-self: center; }
.page-head--split .scoped-search { grid-area: 2 / 2; justify-self: end; }
@media (max-width: 900px) {
    .page-head--split { grid-template-columns: minmax(0, 1fr); }
    .page-head--split h1, .page-head--split .actions,
    .page-head--split .sub, .page-head--split .scoped-search {
        grid-area: auto; justify-self: start;
    }
    /* En colonne, les boutons remontent au-dessus de la recherche : ils
       appartiennent au titre, elle est un outil de lecture. */
    .page-head--split .actions { order: 3; }
    .page-head--split .scoped-search { order: 4; }
    /* Champ revenu à gauche ⇒ popover ouvert vers la droite, sinon il sort
       de la fenêtre du côté opposé. */
    .page-head--split .scoped-search__pop { left: 0; right: auto; }
}

.page-head .actions { flex: none; display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }

.eyebrow {
    font-size: var(--text-2xs);
    font-weight: var(--fw-semibold);
    text-transform: uppercase;
    letter-spacing: var(--ls-caps);
    color: var(--text-subtle);
}

/* ---------- Cards ---------- */
.card {
    display: block;
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
    padding: 20px;
    margin-bottom: 18px;
    overflow: hidden;
}

/* Carte qui contient une liste déroulante (SearchSelect) devant déborder :
   overflow visible pour ne pas clipper le menu (cf. IntervenantsRattaches). */
.card.card--pop { overflow: visible; }

/* Compteur d'une section, dans son titre : même pastille que sur un onglet de
   liste — c'est le même objet (un nombre d'éléments), il n'a pas à changer de
   forme selon l'écran. */
.card h2 .count {
    margin-left: 6px;
    vertical-align: 2px;
    font-family: var(--font-sans);
    font-size: var(--text-2xs);
    font-weight: var(--fw-semibold);
    line-height: 1;
    padding: 2px 6px;
    border-radius: var(--radius-pill);
    background: var(--slate-100);
    color: var(--text-muted);
}
.card h2 {
    font-family: var(--font-display);
    font-size: var(--text-lg);
    font-weight: var(--fw-bold);
    letter-spacing: var(--ls-snug);
    color: var(--text-strong);
    margin: 0 0 2px;
}

.card .sub { color: var(--text-muted); font-size: var(--text-sm); margin: 0 0 18px; }
.card .card-body { padding: 0; }

/* Carte avec en-tête bordé + corps sans padding (listes, tables) */
.card.flush { padding: 0; }
.card-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    padding: 14px 20px;
    border-bottom: 1px solid var(--border-subtle);
}
.card-head h2 { margin: 0; }
.card-head .sub { margin: 2px 0 0; }
.card-head .head-actions { display: flex; gap: 8px; flex: none; align-items: center; }

/* Titre + action (ou champ) à droite DANS une carte à padding standard — à ne
   pas confondre avec `.card-head`, qui appartient aux cartes `flush` : celui-ci
   porte son propre padding et un filet bas, et posé dans une carte ordinaire il
   décale le titre et trace une barre au milieu de rien. */
.card-title-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 14px;
}
.card-title-row h2 { margin: 0; }
.card-title-row .sub { margin: 2px 0 0; }
.card-foot {
    padding: 11px 18px;
    border-top: 1px solid var(--border-subtle);
    text-align: center;
    font-size: var(--text-sm);
}
.card-foot a { font-weight: var(--fw-semibold); text-decoration: none; }
.card.flush .card-pad { padding: 20px; }

/* ---------- Barre d'action d'un formulaire ----------
   Le pied de page d'un formulaire est le MÊME partout : bandeau bordé sur fond
   gris en bas de la carte, action principale en bout à droite, « Annuler »
   juste avant, aides éventuelles à gauche. Portée de la page « Nouveau devis »,
   où elle a été dessinée, et globalisée pour que les fiches et les autres
   formulaires de création ne redessinent pas chacun un rang de boutons nus. */
.form-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 10px;
    margin-top: 22px;
    padding: 16px 22px;
    border-top: 1px solid var(--border-subtle);
    background: var(--slate-50);
}
.form-actions .btn { white-space: nowrap; }
/* Aide (raccourcis clavier, rappel) : à gauche, elle pousse les boutons. */
.form-actions__hint {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-right: auto;
    font-size: var(--text-2xs);
    color: var(--text-subtle);
    white-space: nowrap;
}
/* Dans une carte à padding standard, la barre file jusqu'aux bords : des marges
   négatives valent mieux qu'une carte `flush` par formulaire, qui obligerait à
   repadder tout le reste de son contenu. Le rayon bas est repris pour les
   cartes `card--pop`, qui ne clippent pas (overflow visible). */
.card > .form-actions {
    margin: 22px -20px -20px;
    border-radius: 0 0 var(--radius-md) var(--radius-md);
}

/* ---------- KPI / dashboard ---------- */
.dash-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 14px; margin-bottom: 20px; }
/* Grille de métriques à nombre variable de tuiles (fiche société plateforme). */
.metric-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 14px; margin-bottom: 20px; }

/* Liste clé/valeur (fiches de supervision plateforme). */
.kv-list { list-style: none; margin: 0; padding: 0; }
.kv-list li { display: flex; justify-content: space-between; gap: 16px; padding: 6px 0; border-bottom: 1px solid var(--border); }
.kv-list li:last-child { border-bottom: 0; }
.kv-list li > span:first-child { color: var(--text-subtle); flex: none; }
/* La valeur se coupe plutôt que de sortir de la carte : un sha de build de
   40 caractères débordait de 65 px sur un téléphone. */
.kv-list li > span:last-child { min-width: 0; overflow-wrap: anywhere; text-align: right; }

.stat-card {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-top: 3px solid var(--slate-400);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
    padding: 16px 18px;
    color: inherit;
    text-decoration: none;
    display: block;
    transition: border-color 130ms ease-out;
}

a.stat-card:hover { border-color: var(--border-strong); border-top-color: var(--slate-400); }

.stat-card .l {
    color: var(--text-muted);
    font-size: var(--text-sm);
    font-weight: var(--fw-medium);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.stat-card .l svg { color: var(--text-subtle); flex: none; }

.stat-card .n {
    font-family: var(--font-display);
    font-size: var(--text-3xl);
    font-weight: var(--fw-bold);
    letter-spacing: var(--ls-tight);
    line-height: 1;
    color: var(--text-strong);
    margin-top: 8px;
}

.stat-card.acc-pending { border-top-color: var(--amber-600); }
.stat-card.acc-info { border-top-color: var(--blue-600); }
.stat-card.acc-brand { border-top-color: var(--orange-600); }
.stat-card.acc-confirmed { border-top-color: var(--green-600); }
.stat-card.acc-dispute { border-top-color: var(--red-600); }
a.stat-card.acc-pending:hover { border-top-color: var(--amber-600); }
a.stat-card.acc-info:hover { border-top-color: var(--blue-600); }
a.stat-card.acc-brand:hover { border-top-color: var(--orange-600); }
a.stat-card.acc-confirmed:hover { border-top-color: var(--green-600); }

/* Barre + hero d'avancement (suivi de chantier) */
.progress {
    height: 10px;
    border-radius: var(--radius-pill);
    background: var(--surface-hover);
    overflow: hidden;
}
.progress > span {
    display: block;
    height: 100%;
    background: var(--green-600);
    border-radius: var(--radius-pill);
    transition: width 200ms ease-out;
}
.avct-mini { display: flex; align-items: center; gap: 8px; }
.avct-mini .progress { flex: 1; min-width: 60px; }
.avct-mini .pct { font-family: var(--font-mono); font-size: var(--text-sm); color: var(--text-strong); min-width: 46px; text-align: right; white-space: nowrap; }

.two-col { display: grid; grid-template-columns: 1fr 360px; gap: 18px; align-items: start; }
.col-stack { display: flex; flex-direction: column; gap: 18px; min-width: 0; }

.cta-row { display: flex; gap: 10px; margin: 22px 0 20px; flex-wrap: wrap; }

/* ---------- Boutons ---------- */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    height: var(--control-h-md);
    padding: 0 16px;
    font-family: var(--font-sans);
    font-weight: var(--fw-semibold);
    font-size: var(--text-md);
    line-height: 1;
    letter-spacing: var(--ls-snug);
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    transition: background 130ms ease-out, border-color 130ms ease-out, color 130ms ease-out;
}

.btn svg { flex: none; }

.btn-primary { background: var(--action-primary-bg); color: var(--action-primary-fg); }
.btn-primary:hover, .btn-primary:focus, .btn-primary:active { background: var(--action-primary-bg-hover); color: var(--action-primary-fg); }

.btn-ghost, .btn-secondary {
    background: var(--action-secondary-bg);
    color: var(--action-secondary-fg);
    border-color: var(--action-secondary-border);
    box-shadow: var(--shadow-xs);
}

.btn-ghost:hover, .btn-secondary:hover { background: var(--action-secondary-bg-hover); color: var(--text-strong); }

.btn-plain { background: transparent; color: var(--action-ghost-fg); }
.btn-plain:hover { background: var(--action-ghost-bg-hover); color: var(--text-strong); }

.btn-dark { background: var(--ink-950); color: #fff; }
.btn-dark:hover { background: var(--slate-800); color: #fff; }

.btn-danger { background: var(--action-danger-bg); color: #fff; }
.btn-danger:hover { background: var(--action-danger-bg-hover); color: #fff; }

/* Teintes d'un bouton secondaire : dans une cellule d'actions, tous les boutons
   sont du MÊME type (btn-ghost) et c'est la couleur qui porte le sens. Mélanger
   btn-plain et btn-ghost sur un même rang donnait des boutons qui n'ont pas
   l'air d'appartenir à la même ligne. Déclarées après .btn-ghost:hover, qui
   repose la couleur. */
.btn-ghost.tint-accent { color: var(--action-primary-bg); }
.btn-ghost.tint-accent:hover { color: var(--action-primary-bg-hover); }
.btn-ghost.tint-danger { color: var(--action-danger-bg); }
.btn-ghost.tint-danger:hover { color: var(--action-danger-bg-hover); }

.btn:disabled, .btn.disabled { opacity: 0.55; cursor: not-allowed; }
.btn-sm { height: var(--control-h-sm); padding: 0 12px; font-size: var(--text-sm); gap: 6px; }

.btn:focus-visible, .icon-btn:focus-visible, a:focus-visible { outline: none; box-shadow: var(--ring); }

.icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    padding: 0;
    background: var(--white);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    color: var(--slate-600);
    cursor: pointer;
    transition: background 130ms ease-out, border-color 130ms ease-out;
}

.icon-btn:hover { background: var(--surface-hover); border-color: var(--border-strong); }
.icon-btn.danger { color: var(--red-600); }

.row-actions { display: inline-flex; gap: 6px; align-items: center; justify-content: flex-end; }

/* ---------- Listes ---------- */
.list-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 4px;
    border-bottom: 1px solid var(--border-subtle);
    gap: 12px;
}

.list-item:last-child { border-bottom: none; }

/* dans une carte "flush", la liste colle aux bords */
.card.flush .list-item { padding: 12px 18px; }

.li-icon {
    width: 30px;
    height: 30px;
    flex: none;
    border-radius: var(--radius-sm);
    background: var(--slate-100);
    color: var(--slate-500);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.li-icon.round { border-radius: 50%; width: 28px; height: 28px; }
.li-main { min-width: 0; flex: 1; }
.li-title { font-weight: var(--fw-semibold); font-size: var(--text-md); color: var(--text-strong); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.li-sub { color: var(--text-subtle); font-size: var(--text-2xs); margin-top: 1px; }
.li-actions { display: flex; gap: 6px; flex-shrink: 0; align-items: center; }
.empty { text-align: center; padding: 30px 10px; color: var(--text-muted); font-size: var(--text-sm); }

.empty-illu {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 30px 0;
    text-align: center;
    color: var(--text-muted);
    font-size: var(--text-sm);
}

.empty-illu .ico {
    width: 40px;
    height: 40px;
    border-radius: var(--radius-md);
    background: var(--slate-100);
    color: var(--slate-400);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* ---------- Badges & pills ---------- */
.badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: var(--text-xs);
    font-weight: var(--fw-semibold);
    line-height: 1.4;
    padding: 3px 10px;
    border-radius: var(--radius-pill);
    white-space: nowrap;
}

.badge-draft { background: var(--status-neutral-bg); color: var(--status-neutral-fg); }
.badge-archive { background: var(--status-confirmed-bg); color: var(--status-confirmed-fg); }
.badge-brand { background: var(--orange-100); color: var(--orange-700); }

.badge-status {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: var(--text-xs);
    font-weight: var(--fw-semibold);
    line-height: 1.4;
    padding: 3px 10px 3px 8px;
    border-radius: var(--radius-pill);
    white-space: nowrap;
}

.badge-status svg { flex: none; }
.badge-status.badge-icon-only { gap: 0; padding: 5px; border-radius: 50%; cursor: default; }
.st-brouillon { background: var(--status-neutral-bg); color: var(--status-neutral-fg); }
.st-attente { background: var(--status-pending-bg); color: var(--status-pending-fg); }
.st-valide { background: var(--status-confirmed-bg); color: var(--status-confirmed-fg); }
.st-transmis { background: var(--status-info-bg); color: var(--status-info-fg); }
.st-refuse { background: var(--status-dispute-bg); color: var(--status-dispute-fg); }
/* États de devis (les autres réutilisent st-attente / st-valide / st-refuse) */
.st-devis-encours { background: var(--status-info-bg); color: var(--status-info-fg); }
.st-devis-repondu { background: var(--surface-brand-soft); color: var(--orange-700); }
.st-devis-infructueux { background: var(--status-neutral-bg); color: var(--status-neutral-fg); }
.st-devis-termine { background: var(--green-600); color: #fff; }

.pill-actif {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 10px;
    border-radius: var(--radius-pill);
    background: var(--status-confirmed-bg);
    color: var(--status-confirmed-fg);
    font-size: var(--text-xs);
    font-weight: var(--fw-semibold);
}

.pill-actif::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

/* ---------- Tabs ---------- */
.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border-subtle); margin-bottom: 16px; }

.tab {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 9px 12px;
    border: none;
    background: transparent;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    cursor: pointer;
    font-family: var(--font-sans);
    font-size: var(--text-md);
    font-weight: var(--fw-semibold);
    color: var(--text-muted);
    text-decoration: none;
    transition: color 120ms ease-out, border-color 120ms ease-out;
}

.tab:hover { color: var(--text-strong); }
.tab.active { border-bottom-color: var(--orange-600); color: var(--text-strong); }

.tab .count {
    font-size: var(--text-2xs);
    font-weight: var(--fw-semibold);
    line-height: 1;
    padding: 2px 6px;
    border-radius: var(--radius-pill);
    background: var(--slate-100);
    color: var(--text-muted);
}

.tab.active .count { background: var(--orange-100); color: var(--orange-700); }

/* ---------- Segmented control ---------- */
.segmented {
    display: inline-flex;
    padding: 3px;
    gap: 2px;
    background: var(--slate-100);
    border-radius: var(--radius-sm);
}

.segmented button {
    border: none;
    cursor: pointer;
    padding: 5px 12px;
    border-radius: var(--radius-xs);
    font-family: var(--font-sans);
    font-size: var(--text-sm);
    font-weight: var(--fw-semibold);
    background: transparent;
    color: var(--text-muted);
    transition: background 120ms ease-out, color 120ms ease-out;
}

.segmented button.on { background: var(--white); color: var(--text-strong); box-shadow: var(--shadow-xs); }

/* ---------- Wizard : stepper ---------- */
.steps-rail { display: flex; gap: 8px; margin-bottom: 22px; overflow-x: auto; padding-bottom: 2px; }

.step-pill {
    flex: 1 1 0;
    min-width: 86px;
    min-height: 56px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    padding: 11px 8px;
    border-radius: var(--radius-sm);
    background: var(--white);
    border: 1px solid var(--border-subtle);
    box-shadow: var(--shadow-xs);
    cursor: pointer;
    font-family: var(--font-sans);
    transition: border-color 130ms ease-out;
}

.step-pill .num {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-family: var(--font-mono);
    font-size: var(--text-2xs);
    font-weight: 600;
    letter-spacing: var(--ls-wide);
    color: var(--text-subtle);
}

.step-pill .lab { font-size: var(--text-sm); font-weight: var(--fw-semibold); color: var(--text-muted); white-space: nowrap; max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.step-pill:hover:not(.current) { border-color: var(--border-strong); }
.step-pill.current { background: var(--ink-950); border-color: var(--ink-950); box-shadow: none; }
.step-pill.current .num { color: var(--slate-300); }
.step-pill.current .lab { color: var(--white); font-weight: var(--fw-bold); }
.step-pill.done { border-color: var(--green-100); }
.step-pill.done .num { color: var(--green-600); }
.step-pill.done .lab { color: var(--text-strong); }
.step-pill.invalid .lab::after { content: " •"; color: var(--red-600); }

/* ---------- Formulaires ---------- */
.field { margin-bottom: 16px; }
.field label { display: block; font-weight: var(--fw-medium); font-size: var(--text-sm); color: var(--text-body); margin-bottom: 6px; }
.field label .req { color: var(--red-600); margin-left: 2px; }
.field .hint { color: var(--text-muted); font-size: var(--text-xs); margin-top: 4px; }

.field input:not([type=checkbox]):not([type=radio]):not([type=file]), .field select, .field textarea {
    width: 100%;
    height: var(--control-h-md);
    padding: 0 12px;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    font-family: var(--font-sans);
    font-size: var(--text-md);
    background: var(--white);
    color: var(--text-strong);
    transition: border-color 120ms ease-out, box-shadow 120ms ease-out;
}

.field textarea { resize: vertical; min-height: 74px; height: auto; padding: 10px 12px; line-height: var(--lh-snug); }

.field input:focus, .field select:focus, .field textarea:focus {
    outline: none;
    border-color: var(--border-focus);
    box-shadow: var(--ring);
}

.field.error input, .field.error select, .field.error textarea { border-color: var(--red-600); background: var(--red-50); }
.field input[readonly] { background: var(--slate-50); color: var(--text-muted); cursor: not-allowed; }

/* Sélecteur filtrable (SearchSelect) : <input> + liste déroulante filtrée. */
.search-select { position: relative; }
.search-select > input { padding-right: 34px; }
.search-select > svg {
    position: absolute; right: 11px; top: 50%; transform: translateY(-50%);
    color: var(--text-subtle); pointer-events: none;
}
.search-select-list {
    position: absolute; z-index: 30; top: calc(100% + 4px); left: 0; right: 0;
    max-height: 260px; overflow-y: auto;
    background: var(--surface-card); border: 1px solid var(--border-default);
    border-radius: var(--radius-sm); box-shadow: var(--shadow-lg); padding: 4px;
}
.search-select-opt {
    padding: 8px 10px; border-radius: var(--radius-sm);
    font-size: var(--text-md); color: var(--text-strong); cursor: pointer;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.search-select-opt:hover { background: var(--surface-hover); }
.search-select-opt.sel { background: var(--surface-brand-soft); color: var(--orange-700); font-weight: var(--fw-semibold); }
.search-select-empty { padding: 8px 10px; font-size: var(--text-sm); color: var(--text-muted); }

/* Sélecteur d'intervenants (staged) — cartes des sélections + champ de recherche. */
.ipk-list { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }

/* Cartes d'intervenants rattachés — variante B du design (rail d'accent +
   avatar, fond BLANC : l'orange reste la couleur d'action, il ne teinte pas
   un bloc entier). Partagées par le sélecteur du devis (édition) et la fiche
   devis en lecture. */
.iv-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 14px; align-items: start; margin-bottom: 12px;
}
.iv-c {
    background: var(--white); border: 1px solid var(--border-default);
    border-top: 3px solid var(--orange-600); border-radius: var(--radius-md);
    box-shadow: var(--shadow-xs); overflow: hidden;
}
.iv-c__h {
    display: flex; align-items: center; gap: 10px;
    padding: 12px 12px 10px 14px; border-bottom: 1px solid var(--border-subtle);
}
.iv-c__ttl { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.iv-soc {
    font-size: var(--text-md); font-weight: var(--fw-semibold);
    color: var(--text-strong); line-height: var(--lh-snug);
}
a.iv-soc { color: var(--text-strong); text-decoration: none; }
a.iv-soc:hover { color: var(--orange-700); text-decoration: underline; }
.iv-role { font-size: var(--text-2xs); color: var(--text-muted); }
.iv-av {
    width: 34px; height: 34px; flex: none; border-radius: 50%;
    background: var(--slate-100); border: 1px solid var(--border-subtle);
    color: var(--slate-600); display: inline-flex; align-items: center;
    justify-content: center; font-size: var(--text-xs); font-weight: var(--fw-semibold);
}
/* Actions d'une carte de contact, dans son en-tête : le tableau qu'elle
   remplace avait une colonne pour elles. Serrées et sans fond, pour ne pas
   concurrencer le nom. */
.iv-c__act { flex: none; display: flex; gap: 2px; }
.iv-c__b { display: flex; flex-direction: column; gap: 12px; padding: 14px 16px 16px; }
.iv-f label {
    display: block; font-size: var(--text-sm); font-weight: var(--fw-medium);
    color: var(--text-body); margin-bottom: 6px;
}
/* Cible de 40 px pour le retrait (une croix de 14 px se rate au doigt). */
.iv-x {
    width: 40px; height: 40px; flex: none; display: inline-flex;
    align-items: center; justify-content: center; border: none;
    background: transparent; border-radius: var(--radius-sm);
    color: var(--text-muted); cursor: pointer;
}
.iv-x:hover { background: var(--surface-hover); color: var(--red-600); }
.iv-x:focus-visible { outline: none; box-shadow: var(--ring); }

/* Coordonnées du contact d'un intervenant (carte, tableau de la fiche affaire). */
.iv-lines { display: flex; flex-direction: column; gap: 7px; }
.iv-line { display: flex; align-items: center; gap: 8px; min-width: 0; font-size: var(--text-sm); color: var(--text-body); }
.iv-line > svg { flex: none; color: var(--text-subtle); }
.iv-line > span, .iv-line > a { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.iv-contact { font-weight: var(--fw-medium); color: var(--text-strong); }
.iv-fn { color: var(--text-muted); font-weight: var(--fw-regular); }
.iv-empty-c { font-size: var(--text-sm); color: var(--text-muted); font-style: italic; }
/* Coordonnées sur une rangée : pastille compacte, où la hauteur compte plus
   que l'alignement des icônes. */
.iv-lines--row { flex-direction: row; flex-wrap: wrap; gap: 4px 16px; }

/* Contact sélectionné sous une liste déroulante (facturation d'un AR, contact
   d'un devis ou d'une affaire) — variante D du design « Cartes Intervenants » :
   la personne choisie s'affiche en pastille, avatar + identité + coordonnées,
   sur un fond sourd (l'orange reste la couleur d'action). */
.ct-person {
    display: flex; align-items: flex-start; gap: 10px;
    margin-top: 8px; padding: 10px 12px;
    background: var(--surface-page); border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
}
.iv-av--sm { width: 28px; height: 28px; font-size: var(--text-2xs); }
.ct-person__m { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.ct-person__t {
    display: flex; align-items: center; flex-wrap: wrap; gap: 4px 8px;
    line-height: var(--lh-snug);
}
.ct-tag {
    font-size: var(--text-2xs); font-weight: var(--fw-semibold);
    text-transform: uppercase; letter-spacing: var(--ls-caps);
    background: var(--status-neutral-bg); color: var(--status-neutral-fg);
    padding: 2px 7px; border-radius: var(--radius-pill);
}
.ct-empty {
    display: flex; align-items: center; gap: 8px;
    margin-top: 8px; padding: 10px 12px;
    background: var(--surface-page); border: 1px dashed var(--border-default);
    border-radius: var(--radius-sm);
    font-size: var(--text-sm); color: var(--text-muted);
}
.ct-empty > svg { flex: none; color: var(--text-subtle); }

/* Le picker et les sélecteurs de contact ne sont pas toujours posés dans un
   .field (fiche devis, fiche affaire) : sans ça leurs contrôles natifs sortent
   sans bordure ni hauteur. Mêmes valeurs que « .field input » — c'est ce que
   /nouveau-devis obtient déjà via ses styles scoped. */
.ipk .search-select > input,
.contact-select {
    width: 100%;
    height: var(--control-h-md);
    padding: 0 12px;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    font-family: var(--font-sans);
    font-size: var(--text-md);
    background: var(--white);
    color: var(--text-strong);
    transition: border-color 120ms ease-out, box-shadow 120ms ease-out;
}
/* Pas de chevrons ↕ ici — comme sur /nouveau-devis. */
.ipk .search-select > svg { display: none; }
.ipk .search-select > input:focus,
.contact-select:focus { outline: none; border-color: var(--border-focus); box-shadow: var(--ring); }
.ipk .search-select > input::placeholder { color: var(--text-subtle); }
/* Dans un tableau (fiche affaire), le sélecteur ne mange pas toute la colonne. */
.db-table .contact-select { max-width: 300px; margin-bottom: 8px; }

/* Liste des PJ bufferisées (avant enregistrement) dans DevisForm. */
.pending-files { list-style: none; margin: 0 0 8px; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.pending-files li { display: flex; align-items: center; gap: 8px; font-size: var(--text-sm); color: var(--text-strong); }
.pending-files .linklike {
    border: none; background: none; padding: 0 4px; cursor: pointer;
    font-size: var(--text-md); line-height: 1; color: var(--text-subtle);
}
.pending-files .linklike.danger:hover { color: var(--red-600); }
.field-error-msg { color: var(--red-600); font-size: var(--text-xs); margin-top: 4px; font-weight: var(--fw-semibold); }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.field-row.narrow { grid-template-columns: 2fr 1fr; }

/* Saisie d'avancement (% cumulé) du suivi de chantier : input-group compact
   avec suffixe « % » intégré, focus ring du design system, spinners masqués. */
.pct-field {
    display: inline-flex;
    align-items: baseline;
    gap: 3px;
    width: 104px;
    height: var(--control-h-sm);
    padding: 0 10px;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    background: var(--white);
    transition: border-color 120ms ease-out, box-shadow 120ms ease-out;
}
.pct-field:focus-within { border-color: var(--border-focus); box-shadow: var(--ring); }
.pct-field input {
    width: 100%;
    height: 100%;
    border: 0;
    padding: 0;
    background: transparent;
    text-align: right;
    font-family: var(--font-mono);
    font-size: var(--text-md);
    color: var(--text-strong);
    -moz-appearance: textfield;
    appearance: textfield;
}
.pct-field input:focus { outline: none; }
.pct-field input::-webkit-outer-spin-button,
.pct-field input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.pct-field .suffix { color: var(--text-muted); font-size: var(--text-sm); font-weight: var(--fw-medium); user-select: none; }

.radio-group, .check-group { display: flex; flex-wrap: wrap; gap: 8px; }

.chip {
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    padding: 8px 14px;
    font-size: var(--text-sm);
    font-weight: var(--fw-semibold);
    cursor: pointer;
    background: var(--white);
    color: var(--text-body);
    font-family: var(--font-sans);
    box-shadow: var(--shadow-xs);
    transition: background 130ms ease-out, border-color 130ms ease-out, color 130ms ease-out;
}

.chip:hover:not(.selected) { border-color: var(--border-strong); }
.chip.selected { background: var(--surface-brand-soft); border-color: var(--orange-600); color: var(--orange-700); box-shadow: none; }

.section-title {
    font-family: var(--font-sans);
    font-weight: var(--fw-semibold);
    font-size: var(--text-2xs);
    text-transform: uppercase;
    letter-spacing: var(--ls-caps);
    color: var(--text-subtle);
    margin: 26px 0 14px;
    padding-top: 14px;
    border-top: 1px solid var(--border-subtle);
}

.section-title:first-child { margin-top: 0; padding-top: 0; border-top: none; }

.wizard-footer { display: flex; justify-content: space-between; align-items: center; margin-top: 22px; gap: 8px; flex-wrap: wrap; }
.wizard-footer .right { display: flex; gap: 10px; }
.autosave-note { font-size: var(--text-sm); color: var(--text-muted); display: flex; align-items: center; gap: 7px; }
.dot { width: 7px; height: 7px; border-radius: 50%; background: var(--green-600); }

.banner {
    padding: 11px 14px;
    border-radius: var(--radius-sm);
    font-size: var(--text-sm);
    font-weight: var(--fw-medium);
    margin-bottom: 16px;
    display: block;
    line-height: var(--lh-normal);
}

.banner-danger { background: var(--red-50); border: 1px solid var(--red-100); color: var(--red-600); }
.banner-info { background: var(--blue-50); border: 1px solid var(--blue-100); color: var(--text-body); }
.banner-warning { background: var(--amber-50); border: 1px solid var(--amber-100); color: var(--amber-600); }
/* Variante appuyée : une liste à corriger, qui doit se voir au premier coup d'œil. */
.banner-warning--strong { border: 1.5px solid var(--orange-600); color: var(--text-body); }
.banner-warning--strong strong { color: var(--orange-700); }

/* ---------- Consultation « voir en tant que » (ViewAsBanner) ----------
   Bandeau du super-admin en train de consulter une société en lecture seule.
   Volontairement plus voyant que les autres bandeaux et non masquable : il ne
   signale pas une information, il signale un ÉTAT anormal de la session — on
   regarde la donnée réelle d'un client. Pleine largeur, en tête de contenu,
   au-dessus de l'annonce plateforme. */
.viewas-bar {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 16px;
    margin-bottom: 16px;
    border-radius: var(--radius-md, 8px);
    background: var(--red-50);
    border: 1px solid var(--red-100);
    border-left: 4px solid var(--red-600);
    color: var(--text-body);
    font-size: var(--text-sm);
    line-height: var(--lh-normal);
}
.viewas-bar .va-dot {
    flex: none;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--red-600);
}
.viewas-bar .va-text { flex: 1 1 auto; min-width: 0; }
.viewas-bar .va-text strong { color: var(--red-600); }
.viewas-bar .va-meta {
    display: block;
    color: var(--text-muted);
    font-size: var(--text-xs);
}
.viewas-bar form { flex: none; margin: 0; }
/* ---------- Annonce plateforme (AnnouncementBox) ----------
   Bandeau posé par le super-admin, en tête d'application pour tous. Doit se voir
   sans hurler : filet d'accent à gauche + pastille d'icône + eyebrow de niveau.
   Réutilisé tel quel en aperçu dans /plateforme/systeme. */
.app-announcement { margin: 16px 28px 0; }

.announce {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 12px 16px;
    border: 1px solid var(--ann-border);
    border-left: 4px solid var(--ann-accent);
    border-radius: var(--radius-md);
    background: var(--ann-bg);
    box-shadow: var(--shadow-sm);
    animation: announce-in 220ms ease-out;
}

@keyframes announce-in {
    from { opacity: 0; transform: translateY(-6px); }
    to { opacity: 1; transform: none; }
}

.announce-icon {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border-radius: var(--radius-pill);
    background: var(--ann-chip);
    color: var(--ann-accent-strong);
}

.announce-body { min-width: 0; display: flex; flex-direction: column; gap: 1px; }

.announce-tag {
    font-size: var(--text-2xs);
    font-weight: var(--fw-semibold);
    text-transform: uppercase;
    letter-spacing: var(--ls-caps);
    color: var(--ann-accent-strong);
}

/* pre-line : un message multi-lignes saisi dans le textarea garde ses retours. */
.announce-msg {
    font-size: var(--text-md);
    font-weight: var(--fw-medium);
    line-height: var(--lh-normal);
    color: var(--text-body);
    white-space: pre-line;
    overflow-wrap: anywhere;
}

.announce--info {
    --ann-bg: var(--blue-50);
    --ann-border: var(--blue-100);
    --ann-accent: var(--blue-500);
    --ann-accent-strong: var(--blue-700);
    --ann-chip: var(--blue-100);
}

.announce--warning {
    --ann-bg: var(--amber-50);
    --ann-border: var(--amber-100);
    --ann-accent: var(--amber-600);
    --ann-accent-strong: var(--amber-600);
    --ann-chip: var(--amber-100);
}

.announce--danger {
    --ann-bg: var(--red-50);
    --ann-border: var(--red-100);
    --ann-accent: var(--red-600);
    --ann-accent-strong: var(--red-600);
    --ann-chip: var(--red-100);
}

@media (max-width: 960px) {
    .app-announcement { margin: 12px 16px 0; }
}

/* Panneau d'alertes du tableau de bord plateforme. */
.alert-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.alert-list li { display: flex; align-items: center; gap: 8px; padding: 9px 12px; border-radius: var(--radius-sm); font-size: var(--text-sm); }
.alert-list li svg { flex: none; }
.alert-list .al-danger { background: var(--red-50); color: var(--red-600); }
.alert-list .al-warning { background: var(--amber-50); color: var(--amber-600); }
.alert-list .al-info { background: var(--blue-50); color: var(--text-body); }
.alert-list a { color: inherit; text-decoration: underline; }
.banner ul { margin: 6px 0 0; padding-left: 18px; font-weight: var(--fw-regular); }

.info-note {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    padding: 11px 13px;
    background: var(--blue-50);
    border: 1px solid var(--blue-100);
    border-radius: var(--radius-sm);
    font-size: var(--text-xs);
    color: var(--text-body);
    line-height: var(--lh-normal);
}

.info-note svg { color: var(--blue-600); flex: none; margin-top: 1px; }

.siret-row { display: flex; gap: 8px; align-items: stretch; }
.siret-row input { flex: 1; }
.multi-field { display: flex; flex-direction: column; gap: 8px; }
.multi-row { display: flex; gap: 8px; align-items: center; }
.multi-row input { flex: 1; }
.devis-field { display: flex; flex-direction: column; gap: 8px; }
/* Devis rattachés (étape Commande du wizard) : colonnes alignées d'une ligne
   à l'autre — n° / nom (ellipse) / montant / bouton détacher. */
.devis-linked { display: grid; grid-template-columns: 110px minmax(0, 1fr) 120px 32px; gap: 8px; align-items: center; }
.devis-linked .devis-nom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.devis-linked .devis-montant { text-align: right; }
/* Total de la commande (sous les boutons de rattachement) : mis en valeur,
   même langage visuel que les stat-cards (liseré brand). */
.devis-total-box {
    margin-top: 12px;
    padding: 12px 16px;
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-left: 3px solid var(--orange-600);
    border-radius: var(--radius-md);
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
}
.devis-total-box .l { color: var(--text-muted); font-size: var(--text-sm); font-weight: var(--fw-medium); }
.devis-total-box .n {
    font-family: var(--font-display);
    font-size: var(--text-xl);
    font-weight: var(--fw-bold);
    color: var(--text-strong);
}
.devis-row { display: flex; gap: 8px; align-items: center; }
.devis-row .devis-num { flex: 2; }
.devis-row .devis-montant { flex: 1; min-width: 110px; }

/* Inputs hors .field (lignes de devis) : même style que .field input */
.devis-row input {
    height: var(--control-h-md);
    padding: 0 12px;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    font-family: var(--font-sans);
    font-size: var(--text-md);
    background: var(--white);
    color: var(--text-strong);
    transition: border-color 120ms ease-out, box-shadow 120ms ease-out;
}

.devis-row input:focus {
    outline: none;
    border-color: var(--border-focus);
    box-shadow: var(--ring);
}
.money-input { position: relative; display: flex; align-items: center; }
/* :not() répétés = spécificité alignée sur .field input pour gagner dedans */
.money-input input:not([type=checkbox]):not([type=radio]):not([type=file]) {
    width: 100%;
    padding-right: 28px;
    text-align: right;
    font-family: var(--font-mono);
    appearance: textfield;
    -moz-appearance: textfield;
}
.money-input input::-webkit-outer-spin-button,
.money-input input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
/* Montant dérivé (ligne de devis : quantité × PU) : il reste lisible, mais se
   voit non saisissable — sans ce fond, un champ verrouillé passe pour un champ
   vide qu'on n'arrive pas à remplir. */
.money-input input:disabled { background: var(--surface-hover); cursor: not-allowed; }
.money-input .unit {
    position: absolute;
    right: 10px;
    color: var(--text-muted);
    font-size: var(--text-sm);
    pointer-events: none;
}
.devis-foot { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 8px; }
.devis-total { font-family: var(--font-mono); font-size: var(--text-md); font-weight: 600; color: var(--text-brand); }

.file-field { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.file-name { font-size: var(--text-sm); font-weight: var(--fw-semibold); color: var(--text-strong); }
.file-none { font-size: var(--text-sm); color: var(--text-muted); }

.certify {
    display: flex;
    gap: 10px;
    align-items: flex-start;
    background: var(--slate-50);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    padding: 13px 16px;
    margin-top: 6px;
}

.certify input { margin-top: 3px; }

.computed-val {
    padding: 9px 12px;
    border: 1px dashed var(--border-default);
    border-radius: var(--radius-sm);
    background: var(--slate-50);
    font-family: var(--font-mono);
    font-weight: 600;
    color: var(--text-brand);
}

/* ---------- Dépôt de fichiers (composant DropZone) ----------
   La zone unique du produit : clic partout dans le cadre, glisser-déposer,
   Ctrl+V. L'input fichier la recouvre en transparence (voir DropZone.razor). */
.drop-zone {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    margin-top: 4px;
    padding: 18px;
    border: 1.5px dashed var(--border-default);
    border-radius: var(--radius-md);
    text-align: center;
    color: var(--text-muted);
    background: var(--white);
    transition: border-color 130ms ease-out, background 130ms ease-out, color 130ms ease-out;
}
.drop-zone:hover { border-color: var(--slate-400); background: var(--slate-50); }
.drop-zone:has(input:focus-visible),
.drop-zone.drag { border-color: var(--border-focus); box-shadow: var(--ring); color: var(--text-body); }
.drop-zone.drag { background: var(--surface-raised, var(--slate-50)); }
.drop-zone__t { font-size: var(--text-sm); color: var(--text-muted); }
.drop-zone__h { font-size: var(--text-2xs); color: var(--text-subtle); max-width: 52ch; }
.drop-zone__kbd { display: inline-flex; align-items: center; gap: 4px; font-size: var(--text-2xs); color: var(--text-subtle); }
.drop-zone__kbd kbd {
    font-family: var(--font-mono); font-size: 10px; line-height: 1; padding: 2px 4px;
    background: var(--white); border: 1px solid var(--border-default); border-bottom-width: 2px;
    border-radius: 4px; color: var(--text-body);
}
/* Spécificité volontairement haute (classe + attribut) : le CSS isolé d'une
   page qui habille ses inputs (« .dv-f ::deep input » sur /nouveau-devis)
   pèse autant qu'une règle « .drop-zone input », et sa hauteur de contrôle
   réduirait la surface cliquable à une bande en haut du cadre. */
.drop-zone .drop-zone__input[type=file] {
    position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; padding: 0;
    border: 0; opacity: 0; cursor: pointer;
}
.drop-zone.is-disabled { opacity: .6; }
.drop-zone.is-disabled:hover { border-color: var(--border-default); background: var(--white); }
.drop-zone.is-disabled .drop-zone__input[type=file] { cursor: default; }
.drop-zone__err { list-style: none; margin: 6px 0 0; padding: 0; color: var(--red-600); font-size: var(--text-xs); font-weight: var(--fw-semibold); }

.review-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 18px; margin: 10px 0; }
.review-grid .rk { font-size: var(--text-2xs); color: var(--text-subtle); text-transform: uppercase; letter-spacing: var(--ls-caps); font-weight: var(--fw-semibold); }
.review-grid .rv { font-size: var(--text-sm); font-weight: var(--fw-semibold); color: var(--text-strong); overflow-wrap: anywhere; }

/* ---------- Tables ---------- */
.db-table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); margin: 0; font-family: var(--font-sans); background: var(--surface-card); }

.db-table th, .db-table td { border-bottom: 1px solid var(--border-subtle); padding: 12px 14px; text-align: left; vertical-align: middle; }

.db-table th {
    background: var(--slate-50);
    font-weight: var(--fw-semibold);
    font-size: var(--text-2xs);
    text-transform: uppercase;
    letter-spacing: var(--ls-caps);
    color: var(--text-muted);
    position: sticky;
    top: 0;
    white-space: nowrap;
}

.db-table tbody tr:last-child td { border-bottom: none; }
.db-table tbody tr[role=button], .db-table tbody tr.clickable { transition: background 100ms ease-out; }
.db-table tbody tr[role=button]:hover, .db-table tbody tr.clickable:hover { background: var(--surface-hover); cursor: pointer; }
.db-table .mono, .db-table td.num { font-family: var(--font-mono); }
.db-table td.right, .db-table th.right { text-align: right; }
.db-table .cell-strong { color: var(--text-strong); font-weight: var(--fw-medium); }
.db-table .cell-dash { color: var(--text-subtle); }
.db-table .cell-late { color: var(--status-dispute-fg); font-weight: var(--fw-semibold); }
.db-table tfoot tr.row-total td { border-top: 2px solid var(--border-subtle); border-bottom: none; background: var(--surface-hover); color: var(--text-strong); }
.db-table a.cell-link { color: inherit; text-decoration: none; }
.db-table a.cell-link:hover { color: var(--orange-700); text-decoration: underline; }

.db-scroll {
    overflow: auto;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--surface-card);
    box-shadow: var(--shadow-sm);
}

.table-note { margin-top: 12px; font-size: var(--text-sm); color: var(--text-muted); }

.wf-trail { margin-top: 6px; font-size: var(--text-xs); color: var(--text-muted); padding-left: 18px; }
.wf-trail li { margin: 3px 0; }

.archives-toolbar { display: flex; gap: 12px; margin-bottom: 14px; flex-wrap: wrap; align-items: flex-end; }

.archives-toolbar input, .archives-toolbar select {
    flex: 1;
    min-width: 160px;
    height: var(--control-h-md);
    padding: 0 12px;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    font-size: var(--text-md);
    font-family: var(--font-sans);
    background: var(--white);
    color: var(--text-strong);
    transition: border-color 120ms ease-out, box-shadow 120ms ease-out;
}

.archives-toolbar input:focus, .archives-toolbar select:focus { outline: none; border-color: var(--border-focus); box-shadow: var(--ring); }

/* ---------- Ligne d'onglets + recherche en ligne ---------- */
/* Le filet du bas passe sur la ligne entière, pas sur les seuls onglets, pour
   que la recherche s'y aligne au lieu de flotter à côté. */
.tabs-row {
    display: flex; align-items: flex-end; flex-wrap: wrap; gap: 16px;
    border-bottom: 1px solid var(--border-subtle); margin-bottom: 16px;
}
/* Pas d'overflow ici : une barre de défilement se glisserait entre les onglets
   et le champ de recherche. À l'étroit, c'est la ligne entière qui passe en
   colonne (media query plus bas). */
.tabs-row .tabs { flex: 1 1 auto; border-bottom: none; margin-bottom: 0; }

.inline-search {
    flex: none; display: flex; align-items: center; gap: 6px; margin-bottom: 6px;
    width: 230px; height: var(--control-h-sm); padding: 0 8px;
    border: 1px solid var(--border-default); border-radius: var(--radius-pill);
    background: var(--white); color: var(--text-subtle);
    transition: border-color 120ms ease-out, box-shadow 120ms ease-out;
}
.inline-search:focus-within { border-color: var(--border-focus); box-shadow: var(--ring); }
.inline-search.filled { border-color: var(--orange-600); color: var(--orange-700); }
.inline-search input {
    flex: 1; min-width: 0; height: 100%; padding: 0; border: none; outline: none;
    background: transparent; font-family: var(--font-sans); font-size: var(--text-sm);
    color: var(--text-strong);
}
.inline-search button {
    flex: none; display: inline-flex; border: none; background: transparent;
    color: inherit; cursor: pointer; padding: 2px; border-radius: 50%;
}
.inline-search button:hover { background: var(--surface-hover); }

/* Recherche restreinte à une fiche (client, chantier) : le champ des listes,
   posé en tête de fiche, et ses résultats en popover ancré dessous. La nappe
   ferme au clic extérieur (même mécanique que le popover de filtre d'une
   colonne). Largeur du popover supérieure à celle du champ : un hit porte un
   titre, un badge et un sous-titre, pas un mot. */
.scoped-search { position: relative; }
.scoped-search .inline-search { margin-bottom: 0; width: 260px; }
.scoped-search__veil { position: fixed; inset: 0; z-index: 40; }
.scoped-search__pop {
    /* Ancré sur le bord DROIT du champ, qui est lui-même au bord droit de la
       tête de page : ouvert vers la gauche, le popover reste dans la fenêtre
       (l'inverse le poussait dehors, moitié des résultats inatteignable). */
    position: absolute; z-index: 41; top: calc(100% + 6px); right: 0; width: 440px;
    max-width: calc(100vw - 48px);
    background: var(--surface-card); border: 1px solid var(--border-default);
    border-radius: var(--radius-md); box-shadow: var(--shadow-lg);
    text-align: left; cursor: default;
}
.scoped-search__pop .ss-head {
    padding: 10px 12px 0; font-size: var(--text-2xs); text-transform: uppercase;
    letter-spacing: var(--ls-caps); color: var(--text-subtle); font-weight: var(--fw-semibold);
}
/* Le popover défile, la page non : dix AR sur un chantier sortiraient de
   l'écran et le pied de la liste serait inatteignable. */
.scoped-search__pop .ss-body { padding: 8px 10px 10px; max-height: min(60vh, 520px); overflow-y: auto; }
.scoped-search__pop .section-title:first-child { margin-top: 4px; }
.scoped-search__pop .empty { margin: 6px 0 2px; }

/* Lignes filles d'une table (les devis sous l'AR qui les commande) et
   intertitre de groupe. Le décrochement se lit à trois signes cumulés — un
   filet vertical, un retrait, une teinte de fond — parce qu'un seul suffit à
   se perdre dès qu'on défile : le retrait seul se confond avec une colonne
   étroite, la teinte seule avec un survol. */
/* La ligne d'AR est l'EN-TÊTE de son groupe : c'est elle qui est teintée, pas
   ses devis — l'inverse (parent blanc, enfants gris) faisait lire les devis
   comme la matière secondaire d'une table dont on ne savait plus où commençait
   le groupe suivant. Filet haut de 2 px : il OUVRE le groupe. */
.db-table tbody tr.row-ar { background: var(--surface-sunken); }
.db-table tbody tr.row-ar.clickable:hover { background: var(--surface-hover); }
.db-table tbody tr.row-ar > td { border-top: 2px solid var(--border-default); }
.db-table tbody tr.row-ar:first-child > td { border-top: none; }

/* Devis d'un AR : fond de table, retrait et rail à la couleur d'accent —
   « rattaché à la ligne du dessus ». */
.db-table tr.row-sub > td:first-child {
    padding-left: 34px;
    box-shadow: inset 3px 0 0 var(--orange-200);
}

/* Trois crans (fiche client) : le CHANTIER ouvre le groupe, l'AR s'y range, le
   devis se range sous l'AR. La règle « le parent est teinté » ne change pas,
   c'est le parent qui change : la teinte et le filet d'ouverture passent de
   l'AR à l'affaire, et l'AR prend à son tour un retrait et un rail — gris, là
   où celui du devis est à la couleur d'accent, pour que les deux crans ne se
   confondent pas au défilement. */
.db-table--chantiers tbody tr.row-affaire { background: var(--surface-sunken); }
.db-table--chantiers tbody tr.row-affaire.clickable:hover { background: var(--surface-hover); }
.db-table--chantiers tbody tr.row-affaire > td { border-top: 2px solid var(--border-strong); }
.db-table--chantiers tbody tr.row-affaire:first-child > td { border-top: none; }
.db-table--chantiers tbody tr.row-ar { background: transparent; }
.db-table--chantiers tbody tr.row-ar.clickable:hover { background: var(--surface-hover); }
.db-table--chantiers tbody tr.row-ar > td { border-top: none; }
.db-table--chantiers tr.row-ar > td:first-child {
    padding-left: 22px;
    box-shadow: inset 3px 0 0 var(--border-default);
}
.db-table--chantiers tr.row-sub > td:first-child { padding-left: 46px; }

/* Étiquette de nature (AR · Devis) devant le numéro. Trois signes cumulés
   distinguent les deux natures — teinte de ligne, retrait, mot — parce que
   deux numéros mono côte à côte se confondent au défilement. */
.rt {
    display: inline-block;
    margin-right: 8px;
    padding: 1px 5px;
    border-radius: var(--radius-sm);
    font-family: var(--font-sans);
    font-size: 10px;
    font-weight: var(--fw-bold);
    letter-spacing: .06em;
    text-transform: uppercase;
    vertical-align: 1px;
}
.rt-ar { background: var(--orange-100); color: var(--orange-700); }
.rt-devis { background: var(--slate-100); color: var(--slate-600); }
.db-table tr.row-head > td {
    padding-top: 14px;
    font-size: var(--text-2xs);
    font-weight: var(--fw-semibold);
    text-transform: uppercase;
    letter-spacing: var(--ls-caps);
    color: var(--text-subtle);
    background: var(--surface-card);
}
/* La pastille de compteur n'a pas de style de base — chaque contexte la
   redéfinit (onglet, titre de carte, cloche). Ici comme dans un titre. */
.db-table tr.row-head .count {
    margin-left: 6px;
    padding: 2px 6px;
    border-radius: var(--radius-pill);
    background: var(--slate-100);
    color: var(--text-muted);
    letter-spacing: normal;
}

/* ---------- Bandeau de synthèse d'une liste ---------- */
.list-summary {
    display: flex; align-items: center; flex-wrap: wrap; gap: 28px;
    margin-bottom: 16px; padding: 12px 18px;
    background: var(--surface-card); border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md); box-shadow: var(--shadow-sm);
}
/* Posé DANS une carte (fiche client), le bandeau ne redessine pas une boîte :
   une carte dans une carte se lit comme un encadré à part, alors que ces
   chiffres sont la première ligne de la synthèse. Il ne garde que son rythme. */
.card > .list-summary {
    margin-bottom: 4px;
    padding: 0;
    background: none;
    border: none;
    box-shadow: none;
}
.ls-stat { display: flex; align-items: baseline; gap: 10px; }
.ls-stat .k {
    font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--ls-caps);
    color: var(--text-muted); font-weight: var(--fw-semibold);
}
.ls-stat .v {
    font-family: var(--font-mono); font-size: var(--text-lg);
    font-weight: var(--fw-semibold); color: var(--text-strong);
}
.ls-view { display: flex; align-items: center; gap: 8px; margin-left: auto; }
/* Le même sélecteur vit aussi dans la barre d'avancement de /affaires
   (.ch-actions), qui remplace le bandeau de synthèse dès qu'il y a un
   marché : même habillage, pour qu'il ne change pas de tête d'un onglet à
   l'autre. */
.ls-view label, .ch-actions label {
    font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--ls-caps);
    color: var(--text-muted); font-weight: var(--fw-semibold);
}
.ls-view select, .ch-actions select {
    height: var(--control-h-sm); padding: 0 9px; min-width: 190px;
    border: 1px solid var(--border-default); border-radius: var(--radius-sm);
    font-size: var(--text-sm); font-family: var(--font-sans);
    background: var(--white); color: var(--text-strong);
}
.ls-view select:focus, .ch-actions select:focus { outline: none; border-color: var(--border-focus); box-shadow: var(--ring); }
/* Deux sélecteurs côte à côte (« CA » + « Chiffreur » sur /devis) : un
   peu d'air entre le premier champ et le libellé du second. */
.ls-view select + label { margin-left: 10px; }
.ch-actions label + select { margin-left: 8px; }

/* ---------- Tri + filtre par colonne (ColumnHead, FilterChecklist) ---------- */
.db-table th.col-head { padding: 0; }
.db-table th.col-head .ch { display: flex; align-items: center; padding: 4px 8px 4px 10px; }
.db-table th.col-head.right .ch { justify-content: flex-end; }
.db-table th.col-head.filtered { background: var(--surface-brand-soft); }

/* La colonne filtrée réserve la place de l'entonnoir, qui reste alors visible ;
   les autres non — un bouton par colonne élargirait la table de ~20 px chacun
   et la ferait déborder de son conteneur. */
.db-table th.col-head.filtered .ch { padding-right: 28px; }

.ch-sort {
    display: inline-flex; align-items: center; gap: 4px;
    border: none; background: transparent; cursor: pointer;
    font: inherit; color: inherit;
    text-transform: inherit; letter-spacing: inherit;
    padding: 6px 4px; border-radius: var(--radius-sm);
    transition: color 120ms ease-out, background 120ms ease-out;
}
.ch-sort:hover { color: var(--text-strong); background: var(--surface-hover); }
.ch-sort.on { color: var(--orange-700); }

/* Colonne calculée (avancement) : libellé seul, aligné sur les autres. */
.ch-static { padding: 6px 4px; }

/* Entonnoir en superposition (aucune largeur consommée), révélé au survol. */
.ch-filter {
    position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
    display: inline-flex; border: none; background: transparent; cursor: pointer;
    color: var(--text-subtle); padding: 5px; border-radius: var(--radius-sm);
    opacity: 0; transition: opacity 120ms ease-out, color 120ms ease-out;
}
.db-table th.col-head:hover .ch-filter, .ch-filter.on { opacity: 1; }
.ch-filter:hover { background: var(--surface-hover); color: var(--text-strong); }
.ch-filter.on { color: var(--orange-600); }

/* Popover de filtre, ancré sous l'en-tête. `.db-scroll.pop` relâche l'overflow
   pendant l'ouverture, sinon le conteneur scrollable clipperait le popover
   (même piège que `.card--pop` avec SearchSelect). */
.db-scroll.pop { overflow: visible; }

.col-pop-backdrop { position: fixed; inset: 0; z-index: 40; }

.col-pop {
    position: absolute; z-index: 41; top: 100%; left: 6px; width: 262px;
    background: var(--surface-card); border: 1px solid var(--border-default);
    border-radius: var(--radius-md); box-shadow: var(--shadow-lg);
    text-transform: none; letter-spacing: normal;
    font-weight: var(--fw-regular); color: var(--text-body); cursor: default;
}
.col-pop.right { left: auto; right: 6px; }
.col-pop-head {
    padding: 10px 12px 0; font-size: var(--text-2xs); text-transform: uppercase;
    letter-spacing: var(--ls-caps); color: var(--text-subtle); font-weight: var(--fw-semibold);
}
.col-pop-body { padding: 10px 12px; display: flex; flex-direction: column; gap: 8px; }
.col-pop-foot {
    display: flex; justify-content: space-between; gap: 8px;
    padding: 8px 12px; border-top: 1px solid var(--border-subtle);
}

.fpop-search, .fpop-row input {
    height: var(--control-h-sm); padding: 0 9px;
    border: 1px solid var(--border-default); border-radius: var(--radius-sm);
    font-size: var(--text-sm); font-family: var(--font-sans);
    background: var(--white); color: var(--text-strong);
}
.fpop-search { width: 100%; }
.fpop-search:focus, .fpop-row input:focus { outline: none; border-color: var(--border-focus); box-shadow: var(--ring); }

.fpop-actions { display: flex; gap: 12px; }
.fpop-actions .btn-link { font-size: var(--text-xs); }

.fpop-list { max-height: 244px; overflow-y: auto; display: flex; flex-direction: column; }
.fpop-opt {
    display: flex; align-items: center; gap: 8px; padding: 5px 4px;
    border-radius: var(--radius-sm); cursor: pointer; font-size: var(--text-sm);
}
.fpop-opt:hover { background: var(--surface-hover); }
.fpop-lbl { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-strong); }
.fpop-count { font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--text-muted); }
.fpop-empty { padding: 6px 2px; font-size: var(--text-sm); color: var(--text-muted); }

.fpop-row { display: flex; align-items: center; gap: 8px; }
.fpop-row label { flex: none; width: 66px; font-size: var(--text-xs); color: var(--text-muted); }
.fpop-row input { flex: 1; min-width: 0; }

/* Filtre composite (le « contient » ET le format, sur la colonne Document). */
.fpop-stack { display: flex; flex-direction: column; gap: 8px; }
.fpop-sub {
    font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--ls-caps);
    color: var(--text-subtle); font-weight: var(--fw-semibold);
    border-top: 1px solid var(--border-subtle); padding-top: 8px;
}

.fpop-shortcuts { display: flex; flex-wrap: wrap; gap: 6px; }
.fpop-shortcuts .chip { padding: 4px 9px; font-size: var(--text-xs); }

/* Puces des filtres actifs : sans elles, un filtre posé puis oublié se lit
   comme une liste vide. */
.filter-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 14px; }

.fchip {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 6px 4px 10px; border-radius: var(--radius-pill);
    background: var(--surface-brand-soft); border: 1px solid var(--orange-200);
    color: var(--orange-700); font-size: var(--text-xs); font-weight: var(--fw-semibold);
}
.fchip button {
    display: inline-flex; border: none; background: transparent; color: inherit;
    cursor: pointer; padding: 2px; border-radius: 50%;
}
.fchip button:hover { background: rgba(20, 26, 33, .10); }

/* ---------- Utilisateurs : stats par rôle, avatars ---------- */
.role-stats { display: flex; gap: 14px; margin-bottom: 20px; flex-wrap: wrap; }

.role-stat {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 16px;
    background: var(--white);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
    flex: 1;
    min-width: 150px;
}

.role-stat .rs-ico {
    width: 32px;
    height: 32px;
    flex: none;
    border-radius: var(--radius-sm);
    background: var(--slate-50);
    border: 1px solid var(--border-subtle);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.role-stat .rs-n { display: block; font-family: var(--font-display); font-size: var(--text-xl); font-weight: var(--fw-bold); color: var(--text-strong); line-height: 1; }
.role-stat .rs-l { display: block; font-size: var(--text-xs); color: var(--text-muted); margin-top: 3px; }

/* Les tuiles par rôle servent d'onglets à la liste : mêmes chiffres qu'avant,
   plus le clic qui filtre. Posées dans la ligne d'onglets, elles s'alignent sur
   son filet et laissent la recherche à droite. */
.tabs-row .role-stats { flex: 1 1 auto; margin-bottom: 8px; }
/* Tuiles à la taille de leur contenu (et non étirées comme sur une rangée de
   stats) : c'est ce qui laisse la recherche sur la même ligne, à droite. */
.tabs-row .role-stat { flex: 0 1 auto; min-width: 0; padding: 10px 12px; }

button.role-stat { font: inherit; text-align: left; cursor: pointer; }
button.role-stat:hover { border-color: var(--border-default); box-shadow: var(--shadow-md); }
button.role-stat:focus-visible { outline: none; box-shadow: var(--ring); }
.role-stat.on { border-color: var(--orange-600); background: var(--surface-brand-soft); }
.role-stat.on .rs-l { color: var(--orange-700); }

.avatar-sm {
    width: 34px;
    height: 34px;
    flex: none;
    border-radius: 50%;
    color: #fff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    font-weight: var(--fw-semibold);
    background: var(--slate-500);
}

.avatar-admin { background: var(--orange-600); }
.avatar-dir { background: var(--slate-700); }
.avatar-ca { background: var(--blue-600); }
.avatar-chiffreur { background: var(--amber-600); }
.avatar-assist { background: var(--slate-500); }
.avatar-conducteur { background: var(--green-600); }
/* Rôle sans couleur attitrée : un avatar neutre plutôt qu'un avatar nu. */
.avatar-default { background: var(--slate-500); }

.user-cell { display: inline-flex; align-items: center; gap: 11px; }
.user-cell .uc-name { font-weight: var(--fw-semibold); color: var(--text-strong); line-height: 1.3; display: block; }
.user-cell .uc-mail { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-muted); line-height: 1.3; display: block; }

.role-select {
    width: 100%;
    height: var(--control-h-sm);
    padding: 0 8px;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    font-family: var(--font-sans);
    font-size: var(--text-sm);
    background: var(--white);
    color: var(--text-strong);
}

.role-select:focus { outline: none; border-color: var(--border-focus); box-shadow: var(--ring); }

/* Édition inline de l'email (tables Équipe et Plateforme). */
.row-edit-input {
    height: var(--control-h-sm);
    min-width: 220px;
    padding: 0 8px;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    background: var(--white);
    color: var(--text-strong);
}

.row-edit-input:focus { outline: none; border-color: var(--border-focus); box-shadow: var(--ring); }

/* Nom de famille (PersonNameFields) : en capitales dès la frappe, pour voir
   ce qui sera enregistré — la vraie mise en forme se fait côté serveur. */
.input-nom { text-transform: uppercase; }
.input-nom::placeholder { text-transform: none; }
/* En ligne, Prénom et Nom côte à côte : deux champs de 220 px ne tiennent pas. */
.row-edit-input.row-edit-input--nom { min-width: 120px; width: 140px; font-family: inherit; }

.role-segment { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }

.role-segment button {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 64px;
    gap: 4px;
    padding: 10px 6px;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    background: var(--white);
    cursor: pointer;
    box-shadow: var(--shadow-xs);
    font-family: var(--font-sans);
    font-size: var(--text-xs);
    font-weight: var(--fw-semibold);
    color: var(--text-body);
    text-align: center;
    transition: background 130ms ease-out, border-color 130ms ease-out, color 130ms ease-out;
}

.role-segment button:hover:not(.on) { border-color: var(--border-strong); }
.role-segment button.on { border-color: var(--orange-600); background: var(--surface-brand-soft); color: var(--orange-700); box-shadow: none; }

/* ---------- Toast ---------- */
/* Succès et erreur partagent la même grammaire : surface claire teintée,
   filet d'accent à gauche, icône, texte sombre. Seule la teinte change (et
   l'erreur ajoute une croix, puisqu'elle est persistante). */
#toast {
    position: fixed;
    left: 50%;
    bottom: 26px;
    transform: translateX(-50%);
    display: flex;
    align-items: flex-start;
    gap: 10px;
    max-width: min(560px, calc(100vw - 32px));
    padding: 12px 16px;
    border-radius: var(--radius-md);
    text-align: left;
    font-size: var(--text-sm);
    font-weight: var(--fw-regular);
    color: var(--text-body);
    background: var(--white);
    border: 1px solid var(--border-subtle);
    opacity: 0;
    transition: opacity .2s ease-out;
    /* Au-dessus des modales (.modal-overlay = 10000) : un toast déclenché
       depuis une modale doit rester visible. */
    z-index: 10001;
    box-shadow: var(--shadow-lg);
    pointer-events: none;
}

#toast.show { opacity: 1; }
#toast .toast-ic { flex: none; margin-top: 1px; }
#toast .toast-body { flex: 1; min-width: 0; padding-top: 1px; }
#toast .toast-body > span { color: var(--text-strong); font-weight: var(--fw-semibold); }
#toast .toast-list { margin: 0; padding-left: 16px; display: flex; flex-direction: column; gap: 3px; }
#toast .toast-list li { list-style: disc; color: var(--text-body); }

#toast.ok {
    background: var(--green-50);
    border-color: var(--green-100);
    border-left: 3px solid var(--green-600);
}
#toast.ok .toast-ic { color: var(--green-600); }

/* Erreur : persistante, donc interactive (croix pour fermer). */
#toast.err {
    pointer-events: auto;
    background: var(--red-50);
    border-color: var(--red-100);
    border-left: 3px solid var(--red-600);
}
#toast.err .toast-ic { color: var(--red-600); }
#toast.err .toast-x {
    flex: none;
    display: inline-flex;
    border: none;
    background: transparent;
    color: var(--text-subtle);
    cursor: pointer;
    line-height: 1;
    padding: 2px;
    border-radius: var(--radius-sm);
}
#toast.err .toast-x:hover { background: var(--red-100); color: var(--red-600); }

/* ---------- Modale pièce jointe ---------- */
/* Modale générique (formulaire) — overlay scrollable, boîte centrée en haut. */
.modal-overlay { position: fixed; inset: 0; background: rgba(14, 17, 22, .5); z-index: 10000; display: flex; align-items: flex-start; justify-content: center; padding: 40px 20px; overflow-y: auto; }
.modal-box { background: var(--surface-card); border-radius: var(--radius-lg); width: min(680px, 96vw); box-shadow: var(--shadow-lg); padding: 22px; }
.modal-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 14px; }
.modal-head h2 { margin: 0; }

#att-modal { position: fixed; inset: 0; background: rgba(14, 17, 22, .5); z-index: 10000; display: flex; align-items: center; justify-content: center; padding: 20px; }
.att-box { background: var(--white); border-radius: var(--radius-lg); width: min(900px, 96vw); height: min(90vh, 900px); display: flex; flex-direction: column; overflow: hidden; box-shadow: var(--shadow-lg); }
.att-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 12px 16px; border-bottom: 1px solid var(--border-subtle); }
.att-name { font-weight: var(--fw-bold); font-size: var(--text-md); color: var(--text-strong); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.att-body { flex: 1; overflow: auto; background: var(--slate-100); }
.att-body img { max-width: 100%; display: block; margin: auto; }
.att-body iframe { width: 100%; height: 100%; border: none; }

/* Fiche document : aperçu à gauche, métadonnées à droite. La colonne de droite
   scrolle seule — sur un PDF long, les informations restent atteignables. */
.att-box--doc { width: min(1180px, 96vw); }
.att-split { flex: 1; display: grid; grid-template-columns: minmax(0, 1fr) 340px; min-height: 0; }
.att-split .att-body { border-right: 1px solid var(--border-subtle); }
.att-meta { overflow: auto; padding: 14px 18px 20px; background: var(--surface-card); }
.att-meta .meta-line { display: grid; grid-template-columns: 108px minmax(0, 1fr); gap: 8px; padding: 5px 0; align-items: baseline; }
.att-meta .rk { font-size: var(--text-xs); color: var(--text-muted); text-transform: uppercase; letter-spacing: .02em; }
.att-meta .rv { font-size: var(--text-sm); color: var(--text-body); overflow-wrap: anywhere; }

@media (max-width: 900px) {
    .att-split { grid-template-columns: 1fr; grid-template-rows: minmax(0, 1fr) auto; }
    .att-split .att-body { border-right: none; border-bottom: 1px solid var(--border-subtle); }
    .att-meta { max-height: 45vh; }
}

/* Base documentaire : la taille ne se coupe jamais en deux lignes (« 38,5 / Ko »). */
.db-table td.size { white-space: nowrap; }

/* ---------- Résultats de recherche globale ---------- */
.search-group + .search-group { margin-top: 18px; }
.search-group-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.search-hits { display: flex; flex-direction: column; gap: 2px; }

.search-hit {
    display: block;
    width: 100%;
    text-align: left;
    padding: 9px 10px;
    border: none;
    border-radius: var(--radius-sm);
    background: transparent;
    color: inherit;
    font: inherit;
    cursor: pointer;
    text-decoration: none;
}

.search-hit:hover { background: var(--surface-hover); }
.search-hit:focus-visible { outline: none; box-shadow: var(--ring); }
.hit-body { display: flex; flex-direction: column; gap: 2px; }
.hit-title { display: flex; align-items: center; gap: 8px; font-weight: var(--fw-medium); color: var(--text-strong); }
.hit-sub { font-size: var(--text-sm); color: var(--text-body); }
.hit-context { font-size: var(--text-xs); color: var(--text-muted); }

/* Modale de confirmation générique (actions destructrices) */
.confirm-modal { position: fixed; inset: 0; background: rgba(14, 17, 22, .5); z-index: 10000; display: flex; align-items: center; justify-content: center; padding: 20px; }
/* La boîte ne dépasse JAMAIS de l'écran. Sans ce plafond, une modale plus haute
   que la fenêtre débordait en haut ET en bas : le fond est en position fixed,
   il n'y a donc rien à faire défiler, et les boutons devenaient inatteignables.
   dvh (et non vh) pour que la barre d'adresse mobile ne rogne pas le pied. */
.confirm-box {
    background: var(--white); border-radius: var(--radius-lg);
    width: min(420px, 96vw); max-height: calc(100dvh - 40px);
    padding: 22px 22px 18px; box-shadow: var(--shadow-lg);
    overflow: auto;
}
.confirm-box h3 { margin: 0 0 8px; font-size: var(--text-md); color: var(--text-strong); }
.confirm-box p { margin: 0 0 18px; color: var(--text-body); font-size: var(--text-sm); }
.confirm-box .confirm-actions { display: flex; justify-content: flex-end; gap: 10px; }

/* Modales larges (aperçu d'import, édition d'une ligne). `width` et non
   `max-width` : la règle de base fixe déjà une largeur, un max-width seul ne
   l'élargirait pas. */
.confirm-box--md { width: min(660px, 96vw); }
.confirm-box--lg { width: min(920px, 96vw); }

/* Modale à en-tête et pied FIXES, corps défilant : sur un aperçu de plusieurs
   centaines de lignes, faire défiler toute la boîte éloignerait le bouton
   « Créer le devis » de plusieurs écrans. */
.confirm-box--flow { display: flex; flex-direction: column; overflow: hidden; padding-bottom: 0; }
.confirm-box--flow > h3 { flex: none; }
.confirm-box__body { flex: 1 1 auto; overflow-y: auto; overflow-x: hidden; min-height: 0; margin: 0 -22px; padding: 0 22px 4px; }
.confirm-box--flow > .confirm-actions {
    flex: none; margin: 0 -22px; padding: 14px 22px;
    border-top: 1px solid var(--border-subtle); background: var(--white);
}

/* ---------- Pages Identity (sans Bootstrap : classes réimplémentées) ---------- */
.form-label { display: block; font-weight: var(--fw-medium); font-size: var(--text-sm); color: var(--text-body); margin-bottom: 6px; }

.form-control, .form-select {
    display: block;
    width: 100%;
    height: var(--control-h-md);
    padding: 0 12px;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    font-family: var(--font-sans);
    font-size: var(--text-md);
    background: var(--white);
    color: var(--text-strong);
    transition: border-color 120ms ease-out, box-shadow 120ms ease-out;
}

textarea.form-control { height: auto; min-height: 74px; padding: 10px 12px; }
.form-control:focus, .form-select:focus { outline: none; border-color: var(--border-focus); box-shadow: var(--ring); }
.form-control::placeholder { color: var(--text-subtle); }

/* form-floating (markup Identity : input puis label) → label affiché au-dessus */
.form-floating { display: flex; flex-direction: column-reverse; }
.form-floating > label { font-weight: var(--fw-medium); font-size: var(--text-sm); color: var(--text-body); margin-bottom: 6px; }
.form-floating > .form-control::placeholder { color: transparent; }
.form-floating > .form-control:focus::placeholder { color: var(--text-subtle); }

.form-check { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.form-check-input { width: 16px; height: 16px; accent-color: var(--orange-600); margin: 0; }
.form-check-label { font-size: var(--text-md); color: var(--text-body); }

.valid.modified:not([type=checkbox]) { outline: none; border-color: var(--green-600); }
.invalid { outline: none; border-color: var(--red-600); }
.validation-message { color: var(--red-600); font-size: var(--text-xs); font-weight: var(--fw-semibold); display: block; margin-top: 4px; }

.alert { padding: 11px 14px; border-radius: var(--radius-sm); font-size: var(--text-sm); font-weight: var(--fw-medium); margin-bottom: 16px; border: 1px solid transparent; }
.alert-danger { background: var(--red-50); border-color: var(--red-100); color: var(--red-600); }
.alert-success { background: var(--green-50); border-color: var(--green-100); color: var(--green-600); }
.alert-info { background: var(--blue-50); border-color: var(--blue-100); color: var(--text-body); }
.alert-warning { background: var(--amber-50); border-color: var(--amber-100); color: var(--amber-600); }

/* Navigation de SECTION (Annuaire : clients / intervenants) — à ne pas
   confondre avec `.tabs`, qui filtre le contenu d'une liste. D'où des pastilles
   pleines plutôt que des onglets soulignés : sur la liste des intervenants, les
   deux rangées se suivent et doivent se distinguer au premier coup d'œil. */
.subnav { display: flex; gap: 6px; margin: 0 0 16px; }
.subnav-item {
    display: inline-flex; align-items: center; gap: 6px;
    height: var(--control-h-sm); padding: 0 14px;
    border: 1px solid var(--border-default); border-radius: var(--radius-pill);
    background: var(--white); color: var(--text-subtle);
    font-size: var(--text-sm); font-weight: var(--fw-medium); text-decoration: none;
    transition: border-color 120ms ease-out, color 120ms ease-out, background 120ms ease-out;
}
.subnav-item:hover { color: var(--text-strong); border-color: var(--border-strong); }
.subnav-item.is-on {
    background: var(--text-strong); border-color: var(--text-strong); color: var(--white);
}

/* N° d'affaire pas encore attribué par l'ERP du client : une étape du
   processus, pas une donnée manquante — d'où un libellé lisible plutôt qu'une
   cellule vide, en retrait pour ne pas se confondre avec un vrai numéro. */
.num-attente {
    color: var(--text-muted);
    font-style: italic;
    font-family: var(--font-sans);
    font-size: .92em;
    white-space: nowrap;
}

.text-danger { color: var(--red-600); }
.text-secondary { color: var(--text-muted); }
.text-muted { color: var(--text-muted); }
.text-info { color: var(--blue-600); }
.text-success { color: var(--green-600); }
.font-weight-bold { font-weight: var(--fw-bold); }

/* grille Bootstrap minimale (pages Account) */
.row { display: flex; flex-wrap: wrap; gap: 20px; }
.row > * { min-width: 0; }
.col, .col-md-4, .col-md-6, .col-lg-4, .col-lg-5, .col-lg-6, .col-xl-6 { flex: 1 1 320px; }
.col-md-2, .col-md-3, .col-lg-3 { flex: 0 0 220px; }
.col-md-8, .col-md-9, .col-md-12, .col-lg-8, .col-lg-9 { flex: 1 1 460px; }
.col-12 { flex: 0 0 100%; }

.input-group { display: flex; align-items: stretch; }
.input-group .form-control { flex: 1; border-radius: var(--radius-sm) 0 0 var(--radius-sm); }
.input-group-append { display: flex; }
.input-group-text {
    display: inline-flex;
    align-items: center;
    padding: 0 12px;
    border: 1px solid var(--border-default);
    border-left: none;
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    background: var(--slate-50);
    font-size: var(--text-sm);
    color: var(--text-muted);
}

.recovery-code { font-family: var(--font-mono); font-size: var(--text-md); color: var(--text-strong); }

/* QR code TOTP : le SVG généré par le serveur porte sa propre taille en
   modules — on la neutralise et on borne l'affichage. */
.qr-code {
    display: inline-block;
    padding: 12px;
    background: #fff;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
}
.qr-code svg { display: block; width: 200px; height: 200px; }

table:not(.db-table) { border-collapse: collapse; }
table:not(.db-table) th, table:not(.db-table) td { padding: 8px 12px; border-bottom: 1px solid var(--border-subtle); text-align: left; font-size: var(--text-sm); }

.w-100 { width: 100%; }
.mb-0 { margin-bottom: 0; }
.mb-2 { margin-bottom: 8px; }
.mb-3 { margin-bottom: 14px; }
.mt-3 { margin-top: 14px; }
.btn-lg { height: var(--control-h-lg); padding: 0 22px; font-size: var(--text-lg); }
.btn-link { background: none; border: none; color: var(--text-link); font-size: var(--text-md); cursor: pointer; padding: 0; text-decoration: underline; font-family: var(--font-sans); }
hr { border: none; border-top: 1px solid var(--border-subtle); margin: 18px 0; }

/* ---------- Connexion (layout auth plein écran) ---------- */
.auth { display: grid; grid-template-columns: 44% 1fr; min-height: 100vh; }

.auth-brand {
    background: var(--ink-950);
    color: var(--white);
    padding: 44px 48px;
    display: flex;
    flex-direction: column;
}

.auth-wordmark {
    font-family: var(--font-display);
    font-size: 26px;
    font-weight: var(--fw-black);
    letter-spacing: var(--ls-tight);
    color: var(--white);
}

.auth-wordmark .brand-dot { color: var(--orange-500); }

.auth-pitch { flex: 1; display: flex; flex-direction: column; justify-content: center; max-width: 420px; }

.auth-pitch h2 {
    margin: 0;
    font-family: var(--font-display);
    font-size: 36px;
    font-weight: var(--fw-black);
    line-height: var(--lh-tight);
    letter-spacing: var(--ls-tight);
    color: var(--white);
}

.auth-pitch p { margin: 18px 0 0; font-size: 15px; line-height: 1.6; color: var(--slate-300); }

.auth-copy { font-size: var(--text-xs); color: var(--slate-500); }

.auth-panel {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 40px;
    background: var(--surface-page);
}

.auth-card { width: 100%; max-width: 380px; }

.auth-title {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--text-2xl);
    font-weight: var(--fw-bold);
    color: var(--text-strong);
    letter-spacing: var(--ls-snug);
}

.auth-sub { margin: 6px 0 26px; font-size: var(--text-md); color: var(--text-muted); }

.input-icon {
    display: flex;
    align-items: center;
    gap: 8px;
    height: var(--control-h-md);
    padding: 0 12px;
    background: var(--white);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    color: var(--text-subtle);
    transition: border-color 120ms ease-out, box-shadow 120ms ease-out;
}

.input-icon:focus-within { border-color: var(--border-focus); box-shadow: var(--ring); }
.input-icon svg { flex: none; }

/* prime sur .field input (l'enveloppe .input-icon porte bordure et focus) */
.field .input-icon input:not([type=checkbox]):not([type=radio]):not([type=file]),
.input-icon input {
    flex: 1;
    width: auto;
    min-width: 0;
    height: 100%;
    padding: 0;
    border: none;
    outline: none;
    box-shadow: none;
    background: transparent;
    font-family: var(--font-sans);
    font-size: var(--text-md);
    color: var(--text-strong);
}

.input-icon input::placeholder { color: var(--text-subtle); }
.input-icon:has(input.invalid) { border-color: var(--red-600); }

.auth-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; }

.auth-remember {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: var(--text-md);
    color: var(--text-body);
    cursor: pointer;
}

.auth-foot {
    margin-top: 22px;
    padding-top: 18px;
    border-top: 1px solid var(--border-subtle);
    font-size: var(--text-sm);
    color: var(--text-muted);
    text-align: center;
    line-height: var(--lh-normal);
}

.auth-foot a { font-weight: var(--fw-semibold); text-decoration: none; }

@media (max-width: 840px) {
    .auth { grid-template-columns: 1fr; }
    .auth-brand { display: none; }
    .auth-panel { padding: 24px 16px; align-items: flex-start; padding-top: 48px; }
}

/* ---------- Mon compte (pages Identity Manage) ---------- */
.manage-grid { display: grid; grid-template-columns: 220px 1fr; gap: 24px; align-items: start; }

.manage-nav { display: flex; flex-direction: column; gap: 2px; }

.manage-nav a {
    display: block;
    padding: 9px 10px;
    border-radius: var(--radius-sm);
    color: var(--slate-600);
    font-size: var(--text-md);
    font-weight: var(--fw-medium);
    text-decoration: none;
    transition: background 130ms ease-out, color 130ms ease-out;
}

.manage-nav a:hover:not(.active) { background: var(--surface-hover); color: var(--text-strong); }
.manage-nav a.active { background: var(--surface-brand-soft); color: var(--orange-700); font-weight: var(--fw-semibold); }

.manage-body {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
    padding: 20px;
    min-width: 0;
}

.manage-body h3 { font-family: var(--font-display); font-size: var(--text-lg); font-weight: var(--fw-bold); color: var(--text-strong); margin: 0 0 14px; }

@media (max-width: 960px) {
    .manage-grid { grid-template-columns: 1fr; }
    .manage-nav { flex-direction: row; flex-wrap: wrap; }
}

/* ---------- Blazor error UI ---------- */
#blazor-error-ui {
    color-scheme: light only;
    background: var(--red-600);
    color: #fff;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 100000;
    font-size: var(--text-sm);
    font-weight: var(--fw-semibold);
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 0.75rem;
    top: 0.5rem;
}

#blazor-error-ui a { color: #fff; }
#blazor-error-ui a.signaler { margin-left: 14px; font-weight: 600; }

.blazor-error-boundary {
    background: var(--red-600);
    border-radius: var(--radius-md);
    padding: 1rem;
    color: white;
}

.blazor-error-boundary::after { content: "Une erreur est survenue."; }

/* ---------- Tiroir de navigation (≤ 960 px) ----------
   Sous 960 px la sidebar sort de l'écran et s'ouvre par le burger de la
   topbar (js/nav-drawer.js pose `nav-open` sur <html>). Ces éléments n'existent
   qu'à cette taille : en large, la sidebar fixe les rend inutiles. */
.nav-burger, .topbar-brand, .nav-backdrop, .drawer-only { display: none; }

.nav-burger {
    order: -1;
    flex: none;
    width: 40px;
    height: 40px;
    margin-left: -8px;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    border-radius: var(--radius-sm);
    color: var(--text-strong);
    cursor: pointer;
}
.nav-burger:hover { background: var(--surface-hover); }

.topbar-brand { align-items: center; gap: 8px; flex: none; text-decoration: none; color: var(--ink-950); }
.topbar-brand__name {
    font-family: var(--font-display);
    font-size: 19px;
    font-weight: 800;
    letter-spacing: var(--ls-tight);
    line-height: 1;
}
.topbar-brand__name .brand-dot { color: var(--orange-600); }

.drawer-user {
    align-items: center;
    gap: 10px;
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid var(--border-subtle);
}
.drawer-user .user-meta { flex: 1; min-width: 0; }
.drawer-user .logout { margin-left: 0; }

/* ---------- Tableau en CARTES (≤ 640 px) ----------
   `db-table--cards` sur la table, `data-label` sur chaque cellule : sur un
   téléphone une ligne devient une carte « libellé · valeur ». Le défilement
   horizontal cachait justement ce qu'on vient faire sur la ligne — rôle,
   statut et boutons étaient à droite, hors de l'écran, sans rien pour dire
   qu'ils existaient. `cell-card-title` remonte en tête de carte (ordre flex,
   la colonne n'a pas à être la première), `cell-card-actions` ferme la carte,
   `cell-card-block` met un texte long sous son libellé, `cell-card-skip` cache
   une cellule sans objet sur cette ligne. */
@media (max-width: 640px) {
    .db-scroll:has(> .db-table--cards),
    .card.flush:has(> .db-scroll > .db-table--cards) { overflow: visible; border: none; border-radius: 0; background: none; box-shadow: none; }
    .db-table--cards, .db-table--cards tbody { display: block; background: none; }
    .db-table--cards thead { display: none; }
    .db-table--cards tbody tr {
        display: flex;
        flex-direction: column;
        margin-bottom: 10px;
        padding: 12px 14px;
        background: var(--surface-card);
        border: 1px solid var(--border-subtle);
        border-radius: var(--radius-md);
        box-shadow: var(--shadow-sm);
    }
    .db-table--cards tbody td {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
        min-width: 0;
        max-width: none !important;
        padding: 5px 0;
        border: none;
        text-align: right !important;
        overflow-wrap: anywhere;
    }
    .db-table--cards tbody td[data-label]::before {
        content: attr(data-label);
        flex: none;
        color: var(--text-muted);
        font-family: var(--font-sans);
        font-size: var(--text-xs);
        text-align: left;
    }
    .db-table--cards tbody td.cell-card-title {
        order: -1;
        display: block;
        padding: 0 0 6px;
        font-size: var(--text-md);
        text-align: left !important;
    }
    .db-table--cards tbody td.cell-card-block { display: block; text-align: left !important; }
    .db-table--cards tbody td.cell-card-block::before { display: block; margin-bottom: 2px; }
    .db-table--cards tbody td.cell-card-actions {
        justify-content: flex-end;
        margin-top: 6px;
        padding-top: 10px;
        border-top: 1px solid var(--border-subtle);
    }
    .db-table--cards tbody td.cell-card-skip { display: none; }
}

/* ---------- Responsive ---------- */

/* Écrans tactiles : cibles ≥ 40px (recommandation ~44px) */
@media (pointer: coarse) {
    .btn-sm { height: 38px; padding: 0 14px; }
    .icon-btn { width: 40px; height: 40px; }
    .tab { padding: 12px 14px; }
    .side-nav a, .manage-nav a { padding: 12px 10px; }
    .segmented button { padding: 9px 14px; }
}

/* Tablette : sidebar en tiroir, grilles à 1 colonne */
@media (max-width: 960px) {
    /* Étroit : la recherche repasse sous les onglets, pleine largeur. */
    .tabs-row { flex-direction: column; align-items: stretch; gap: 8px; padding-bottom: 8px; }
    .inline-search { width: 100%; margin-bottom: 0; }

    .shell { display: block; }
    .main-col { min-height: 100vh; }
    .sidebar {
        position: fixed;
        inset: 0 auto 0 0;
        z-index: 900;
        width: min(300px, 86vw);
        height: 100%;
        box-shadow: var(--shadow-lg);
        transform: translateX(-100%);
        /* `visibility` retardée : fermé, le tiroir sort de l'ordre de
           tabulation — mais seulement une fois l'animation finie. */
        visibility: hidden;
        transition: transform 200ms ease-out, visibility 0s linear 200ms;
    }
    .nav-open .sidebar { transform: none; visibility: visible; transition: transform 200ms ease-out; }
    .nav-backdrop {
        display: block;
        position: fixed;
        inset: 0;
        z-index: 899;
        background: rgba(14, 17, 22, 0.45);
        opacity: 0;
        pointer-events: none;
        transition: opacity 200ms ease-out;
    }
    .nav-open .nav-backdrop { opacity: 1; pointer-events: auto; }
    .nav-open body { overflow: hidden; }

    .drawer-only { display: flex; }
    .sidebar .searchbox { flex: none; max-width: none; height: 40px; margin: 4px 12px 8px; }
    .nav-burger, .topbar-brand { display: inline-flex; }
    .topbar .searchbox, .topbar .topbar-sep, .topbar .user-area { display: none; }
    .topbar { padding: 0 16px; gap: 10px; }
    .content { padding: 20px 16px 34px; }
    .two-col { grid-template-columns: 1fr; }
    .dash-grid { grid-template-columns: 1fr 1fr; }
    .role-stats { display: grid; grid-template-columns: 1fr 1fr; }
    .tabs { overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
    .tabs::-webkit-scrollbar { display: none; }
    .tab { flex: none; white-space: nowrap; }
    .db-scroll { -webkit-overflow-scrolling: touch; }

    /* Étroit : l'aide passe sur sa propre ligne au lieu d'écraser les boutons. */
    .form-actions__hint { width: 100%; margin: 0 0 4px; }
}

/* Téléphone étroit (360 px) : le logo seul, sans le nom — cloche et bouée
   sortaient de la barre. */
@media (max-width: 400px) {
    .topbar-brand__name { display: none; }
}

/* Mobile */
@media (max-width: 640px) {
    .field-row { grid-template-columns: 1fr; }
    .field-row.narrow { grid-template-columns: 1fr; }
    .dash-grid { grid-template-columns: 1fr; }
    .review-grid { grid-template-columns: 1fr; }
    .topbar .user-meta { display: none; }

    /* iOS zoome sur les champs < 16px : forcer 16px au focus */
    .field input:not([type=checkbox]):not([type=radio]):not([type=file]),
    .field select, .field textarea,
    .archives-toolbar input, .archives-toolbar select,
    .form-control, .form-select, .role-select, .row-edit-input,
    .sidebar .searchbox input, .filters select, .filters input:not([type=checkbox]) { font-size: 16px; }

    /* Filtres : un par ligne, pleine largeur. */
    .filters label:not(.filters__check) { flex: 1 1 100%; }

    /* Pied de page : liens sur une ligne, mention en dessous. */
    .app-footer { flex-wrap: wrap; justify-content: center; padding: 12px 16px 18px; }
    .app-footer .footer-note { margin-left: 0; flex-basis: 100%; text-align: center; }

    .page-head { flex-direction: column; align-items: stretch; }
    .page-head h1 { font-size: var(--text-2xl); }

    .page-head .actions { justify-content: stretch; }
    .page-head .actions .btn { flex: 1; }

    /* Stepper compact : numéros seuls, libellé sur l'étape courante */
    .steps-rail { gap: 5px; }
    .step-pill { min-width: 0; min-height: 44px; padding: 8px 6px; }
    .step-pill:not(.current) .lab { display: none; }
    .step-pill.current { flex: 2 1 auto; }

    /* Footer wizard empilé, boutons pleine largeur */
    .wizard-footer { flex-direction: column-reverse; align-items: stretch; }
    .wizard-footer .right { flex-direction: column; }
    .wizard-footer .right .btn, .wizard-footer > .btn { width: 100%; justify-content: center; }
    .autosave-note { justify-content: center; }

    /* Toolbars et actions de liste empilées */
    .archives-toolbar { flex-direction: column; align-items: stretch; }
    .archives-toolbar input, .archives-toolbar select { max-width: none !important; flex: 1 1 auto; }
    .archives-toolbar > * { width: 100%; }
    .cta-row .btn { flex: 1 1 auto; justify-content: center; }
    .list-item { flex-wrap: wrap; }
    .list-item .li-actions { width: 100%; justify-content: flex-end; }
    .role-stats { grid-template-columns: 1fr; }
    .role-segment { grid-template-columns: 1fr 1fr; }
    .two-col { gap: 14px; }
    .card, .manage-body { padding: 16px; }
    .card.flush { padding: 0; }
    .card-head { padding: 12px 16px; }
    .card.flush .card-pad { padding: 16px; }
    .card.flush .list-item { padding: 12px 16px; }

    /* Modale pièce jointe plein écran */
    #att-modal { padding: 0; }
    .att-box { width: 100vw; height: 100vh; border-radius: 0; }

    #toast { left: 16px; right: 16px; transform: none; text-align: center; }
    #toast.err { max-width: none; text-align: left; }

    .bell { padding: 0 10px; }
}

/* ---------- Légal : badge bêta, footers, pages CGU ---------- */
.badge-beta {
    display: inline-block;
    margin-left: 8px;
    padding: 2px 7px;
    border-radius: var(--radius-pill);
    background: var(--orange-100);
    color: var(--orange-700);
    font-family: var(--font-sans);
    font-size: 10px;
    font-weight: var(--fw-bold);
    letter-spacing: 0.06em;
    vertical-align: middle;
    line-height: 1.4;
}

.auth-wordmark .badge-beta { background: var(--orange-500); color: var(--white); }

.app-footer {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 28px 16px;
    font-size: var(--text-xs);
    color: var(--slate-400);
}

.app-footer a { color: var(--slate-500); text-decoration: none; }
.app-footer a:hover { color: var(--text-strong); text-decoration: underline; }
.app-footer .footer-note { margin-left: auto; }

.auth-panel { flex-direction: column; gap: 18px; }

.auth-footer {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: var(--text-xs);
    color: var(--slate-400);
}

.auth-footer a { color: var(--slate-500); text-decoration: none; }
.auth-footer a:hover { color: var(--text-strong); text-decoration: underline; }

/* Page d'acceptation : carte élargie + texte CGU scrollable */
.auth-card:has(.cgu-scroll) { max-width: 640px; }

.cgu-scroll {
    max-height: 46vh;
    overflow-y: auto;
    margin: 16px 0;
    padding: 14px 16px;
    border: 1px solid var(--border-default, var(--slate-200));
    border-radius: var(--radius-md);
    background: var(--white);
}

/* Contenu des documents légaux */
.legal-page { max-width: 860px; }
.legal-page h2 { margin-top: 0; }

.legal-doc h4 { margin: 18px 0 6px; font-size: var(--text-md); color: var(--text-strong); }
.legal-doc p, .legal-doc li { font-size: var(--text-sm); line-height: 1.65; color: var(--slate-600); }
.legal-doc ul { margin: 6px 0 10px; padding-left: 20px; }
.legal-doc .legal-meta { font-size: var(--text-xs); color: var(--slate-400); margin: 0 0 4px; }

/* ============================================================
   Tableau de bord « Vue d'ensemble » (handoff design, classes ac-*)
   ============================================================ */
.ac-eyebrow { font-size: var(--text-2xs); font-weight: var(--fw-semibold); text-transform: uppercase; letter-spacing: var(--ls-caps); color: var(--text-subtle); }
.ac-eyebrow--sec { margin: 0 0 10px; }
.ac-link { font-size: var(--text-sm); font-weight: 600; color: var(--text-link); }

.ac-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 24px; }
.ac-head h1 { margin: 0; font-family: var(--font-display); font-size: var(--text-3xl); font-weight: 800; letter-spacing: -.02em; color: var(--text-strong); }
.ac-head .sub { margin: 5px 0 0; font-size: var(--text-md); color: var(--text-muted); }
.ac-head .actions { display: flex; gap: 10px; flex: none; }

/* Bandeau KPI — une seule ligne desktop (StatCard réutilisé) */
.ac-kpis { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 14px; margin-bottom: 26px; }
.ac-kpis .stat-card { height: 100%; transition: box-shadow 140ms ease-out, transform 140ms ease-out; }
.ac-kpis a.stat-card:hover { box-shadow: var(--shadow-lg); transform: translateY(-1px); }

/* Grilles thématiques */
.ac-g2 { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; margin-bottom: 18px; align-items: start; }
.ac-g3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; align-items: start; }

/* Tuiles de stats dans les cartes */
.ac-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.ac-stats--2 { grid-template-columns: 1fr 1fr; align-items: stretch; }
.ac-stat { display: flex; flex-direction: column; gap: 3px; min-height: 40px; padding: 12px 14px; background: var(--slate-50); border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); transition: background 140ms ease-out, border-color 140ms ease-out; }
a.ac-stat:hover { background: var(--white); border-color: var(--border-default); box-shadow: var(--shadow-sm); }
.ac-stat__l { font-size: var(--text-xs); font-weight: 500; color: var(--text-muted); }
.ac-stat__v { font-family: var(--font-mono); font-size: var(--text-xl); font-weight: 600; color: var(--text-strong); letter-spacing: -.01em; }
.ac-stat__s { font-size: var(--text-2xs); color: var(--text-subtle); }
.ac-finaliser { display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 8px; padding: 12px 14px; background: var(--amber-50); border: 1px solid var(--amber-100); border-radius: var(--radius-sm); }
.ac-chart { overflow-x: auto; padding-bottom: 2px; }

/* Tendance */
.ac-trend { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.ac-trend__i { display: flex; flex-direction: column; gap: 6px; padding: 16px 18px; background: var(--slate-50); border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); }
a.ac-trend__i:hover { background: var(--white); border-color: var(--border-default); box-shadow: var(--shadow-sm); }
.ac-trend__l { font-size: var(--text-sm); font-weight: 500; color: var(--text-muted); }
.ac-trend__v { font-family: var(--font-mono); font-size: var(--text-2xl); font-weight: 600; color: var(--text-strong); letter-spacing: -.01em; }
.ac-trend__p { display: flex; align-items: center; gap: 10px; font-size: var(--text-xs); color: var(--text-subtle); }
.ac-delta { font-weight: 600; font-size: var(--text-sm); }
.ac-delta.up { color: var(--green-600); }
.ac-delta.down { color: var(--red-600); }
.ac-delta.flat { color: var(--text-subtle); }

/* Listes (à traiter / brouillons / activité) */
.ac-list { display: flex; flex-direction: column; }
.ac-row { display: flex; align-items: center; gap: 11px; min-height: 56px; padding: 11px 18px; border-bottom: 1px solid var(--border-subtle); color: inherit; }
.ac-row:last-child { border-bottom: none; }
.ac-row:hover { background: var(--surface-hover); color: inherit; }
.ac-row__ic { width: 28px; height: 28px; flex: none; border-radius: 50%; background: var(--slate-100); color: var(--slate-500); display: inline-flex; align-items: center; justify-content: center; }
.ac-row__tx { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ac-row__t { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; font-size: var(--text-md); font-weight: 600; color: var(--text-strong); min-width: 0; }
.ac-row__n { font-size: var(--text-2xs); color: var(--text-muted); }
.ac-row__r { flex: none; }
.ac-ref { font-family: var(--font-mono); font-size: var(--text-sm); font-weight: 600; color: var(--text-strong); }
.ac-sep { font-size: var(--text-sm); font-weight: 500; color: var(--text-body); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.ac-go { color: var(--text-subtle); display: inline-flex; }
.ac-more { display: block; padding: 12px 18px; border-top: 1px solid var(--border-subtle); text-align: center; font-size: var(--text-sm); font-weight: 600; color: var(--text-link); }

.badge-warning { background: var(--status-pending-bg); color: var(--status-pending-fg); }

@media (max-width: 1280px) {
    .ac-kpis { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .ac-g2, .ac-g3 { grid-template-columns: 1fr; }
}
@media (max-width: 720px) {
    .ac-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .ac-trend, .ac-stats { grid-template-columns: 1fr; }
    .ac-head { flex-direction: column; }
}

/* Barre de filtres du journal des sociétés : libellé au-dessus du champ,
   les champs se répartissent la largeur et repassent à la ligne au besoin. */
.filters { display: flex; flex-wrap: wrap; gap: 12px; }
.filters label {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex: 1 1 180px;
    font-size: var(--text-sm);
    color: var(--text-muted);
}

/* ── Tête du suivi de chantier : avancement + chiffres dans UNE carte ───────
   Le pourcentage à gauche, les montants à droite, sur une seule ligne. En deux
   blocs séparés (hero d'avancement + quatre tuiles), le haut de page occupait
   un écran entier avant la première ligne de saisie, et le montant réalisé
   apparaissait deux fois. */
/* ── Tête de la page chantier : UNE barre, pas une rangée de tuiles ─────────

   Les trois montants du chantier sont EMBOÎTÉS — sur relevé ⊆ réalisé ⊆
   marché —, donc une seule barre les porte tous, et chaque chiffre est écrit
   SUR la part qu'il décrit : le pourcentage dans le segment, le montant juste
   dessous, aux mêmes largeurs. Une légende à part imposait l'aller-retour
   couleur → ligne → chiffre. Les trois parts se distinguent aussi par leur
   TRAME (plein / hachuré / vide), jamais par la seule teinte : la carte reste
   lisible en noir et blanc, à l'impression comme en daltonisme. */
.chantier-head {
    padding: 16px 20px 14px;
    margin-bottom: 18px;
}
.chantier-head .ch-top {
    display: flex;
    align-items: baseline;
    gap: 10px;
    flex-wrap: wrap;
}
.chantier-head .ch-top .l {
    font-size: var(--text-xs);
    font-weight: var(--fw-semibold);
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.chantier-head .ch-top .pct {
    font-family: var(--font-display);
    font-size: var(--text-3xl);
    font-weight: var(--fw-bold);
    letter-spacing: var(--ls-tight);
    line-height: 1;
    color: var(--text-strong);
}
.chantier-head .ch-top .sfx { font-size: var(--text-sm); color: var(--text-muted); }
.chantier-head .ch-top .marche {
    margin-left: auto;
    font-size: var(--text-sm);
    color: var(--text-muted);
    white-space: nowrap;
}
/* Le marché est le DÉNOMINATEUR : tout le reste de la carte en est une
   fraction, il mérite donc mieux qu'une note de bas de ligne. Mais il n'est
   pas une nouveauté — il se redéduit des trois montants —, et deux nombres de
   29 px aux deux bouts de la même ligne privent l'œil de point d'entrée. D'où
   la hiérarchie : 29 px pour la réponse (l'avancement), 19 pour le cadre, 16
   pour les trois parts. */
/* Le bouton ne s'aligne pas sur la ligne de base des chiffres (une bordure
   n'a pas de baseline utile) : centré sur la hauteur de la ligne. */
.chantier-head .ch-top .ch-actions { align-self: center; margin-left: 14px; }
.chantier-head .ch-top .marche b {
    font-family: var(--font-display);
    font-size: var(--text-xl);
    font-weight: var(--fw-bold);
    letter-spacing: var(--ls-tight);
    color: var(--text-strong);
}

/* La marge haute réserve la place du libellé du repère « prévu », qui vit
   AU-DESSUS de la barre : posé dedans, il masquerait un pourcentage. */
.chantier-head .ch-bar-wrap { position: relative; margin: 24px 0 8px; }
.chantier-head .ch-bar {
    display: flex;
    height: 26px;
    border-radius: var(--radius-pill);
    background: var(--surface-sunken);
    overflow: hidden;
}
.chantier-head .ch-bar .seg {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    min-width: 0;
    overflow: hidden;
    transition: width 200ms ease-out;
}
.chantier-head .ch-bar .seg b {
    font-family: var(--font-display);
    font-size: var(--text-2xs);
    font-weight: var(--fw-bold);
    letter-spacing: .01em;
    white-space: nowrap;
}
/* Un filet blanc sépare les segments : deux aplats jointifs se lisent comme un
   dégradé, et la frontière — ce qui est acquis contre ce qui ne l'est pas —
   est justement l'information. Posé en bordure interne pour ne pas décaler les
   largeurs, qui doivent rester celles des pourcentages. */
.chantier-head .seg-releve {
    background: var(--green-600);
    box-shadow: inset -2px 0 0 var(--surface-card);
}
.chantier-head .seg-releve b { color: var(--white); }
/* Trame CLAIRE à rayures foncées, et non l'inverse : sur l'ambre plein, un
   pourcentage blanc tombe à 2,4:1 de contraste. Ici l'encre sombre tient
   8,4:1 sur le fond comme 5,7:1 sur les rayures. */
.chantier-head .seg-porter {
    background: repeating-linear-gradient(135deg,
        var(--amber-400) 0 5px, var(--amber-600) 5px 10px);
    box-shadow: inset -2px 0 0 var(--surface-card);
}
.chantier-head .seg-porter b { color: var(--ink-950); }
.chantier-head .seg-reste b { color: var(--text-muted); }

/* Repère « prévu à ce jour » : un trait qui traverse la barre, pas un chiffre
   de plus à comparer — l'avance et le retard se lisent à la position. */
.chantier-head .ch-mark {
    position: absolute;
    top: -20px;
    bottom: -4px;
    width: 0;
    pointer-events: none;
    z-index: 1;
}
.chantier-head .ch-mark i {
    position: absolute;
    top: 17px;
    bottom: 0;
    left: -1px;
    width: 2px;
    background: var(--ink-950);
    border-radius: 1px;
}
.chantier-head .ch-mark .lbl {
    position: absolute;
    top: 0;
    left: 0;
    transform: translateX(-50%);
    white-space: nowrap;
    font-size: var(--text-2xs);
    font-weight: var(--fw-semibold);
    color: var(--text-body);
}
/* Aux extrémités, un libellé centré sortirait de la carte (.card est en
   overflow: hidden) : il s'aligne alors sur le bord intérieur. */
.chantier-head .ch-mark.start .lbl { transform: none; }
.chantier-head .ch-mark.end .lbl { transform: translateX(-100%); }

/* Les montants reprennent les largeurs des segments (flex-basis posé en
   ligne). `flex-shrink` sans `flex-grow` + `min-width: max-content` : un
   segment étroit garde son montant entier et mord sur la place du voisin, qui
   est large par construction — un montant tronqué serait un mensonge, un
   montant décalé de vingt pixels reste lisible. */
.chantier-head .ch-legend { display: flex; align-items: flex-start; }
.chantier-head .ch-legend .i {
    flex: 0 1 auto;
    min-width: max-content;
    padding: 8px 14px 0 0;
    position: relative;
}
/* Le trait vertical relie le montant à son segment : c'est lui qui remplace la
   pastille de légende, en disant EN PLUS d'où vient le chiffre. */
.chantier-head .ch-legend .i::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    width: 2px;
    height: 6px;
}
.chantier-head .i-releve::before { background: var(--green-600); }
.chantier-head .i-porter::before { background: var(--amber-600); }
.chantier-head .i-reste::before { background: var(--border-default); }
.chantier-head .ch-legend .k {
    display: block;
    font-size: var(--text-2xs);
    font-weight: var(--fw-semibold);
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.chantier-head .ch-legend .v {
    font-family: var(--font-display);
    font-size: var(--text-lg);
    font-weight: var(--fw-bold);
    letter-spacing: var(--ls-tight);
    color: var(--text-strong);
    white-space: nowrap;
}
.chantier-head .ch-legend .p {
    margin-left: 6px;
    font-size: var(--text-2xs);
    color: var(--text-subtle);
}

/* Variante DENSE : la même barre en tête d'une LISTE, où elle n'est pas la
   réponse de la page mais son cadre — la réponse est le tableau en dessous.
   Rien ne disparaît (mêmes segments, mêmes montants, mêmes règles de largeur
   et d'écriture du pourcentage) : seules la hauteur et la graisse cèdent, pour
   que la première ligne du tableau reste au-dessus du pli. */
.chantier-head--dense { padding: 11px 16px 12px; margin-bottom: 14px; }
.chantier-head--dense .ch-top { gap: 8px; }
.chantier-head--dense .ch-top .pct { font-size: var(--text-xl); }
.chantier-head--dense .ch-top .marche b { font-size: var(--text-lg); }
.chantier-head--dense .ch-bar-wrap { margin: 10px 0 6px; }
/* Le repère « prévu » écrit son libellé AU-DESSUS de la barre : là où il est
   rendu, la marge haute doit lui rester, sinon il sort de la carte. */
.chantier-head--dense .ch-bar-wrap:has(.ch-mark) { margin-top: 22px; }
.chantier-head--dense .ch-bar { height: 18px; }
/* Libellé et montant sur UNE ligne : c'est la moitié de la hauteur gagnée, et
   à cette taille le montant n'a plus besoin d'une ligne à lui. Contrepartie
   assumée : chaque bloc est plus LARGE, donc mord davantage sur son voisin —
   `min-width: max-content` tient toujours, et les listes sont en plein écran. */
.chantier-head--dense .ch-legend .i { padding-top: 6px; }
.chantier-head--dense .ch-legend .k { display: inline; margin-right: 6px; }
.chantier-head--dense .ch-legend .v { font-size: var(--text-md); }

/* Précédente / suivante entre situations, dans la tête de page. Le rang au
   milieu répond à « où suis-je dans le chantier » sans revenir à la liste —
   deux flèches nues n'en disent rien. */
.sit-nav {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 2px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--surface-card);
}
.sit-nav .rang {
    font-family: var(--font-mono);
    font-size: var(--text-2xs);
    color: var(--text-muted);
    padding: 0 6px;
    white-space: nowrap;
}

/* Sous ~560 px, trois montants côte à côte ne tiennent plus : ils passent en
   colonne et la correspondance avec la barre est portée par le seul trait. */
@media (max-width: 560px) {
    .chantier-head .ch-top .marche { margin-left: 0; flex: 1 1 100%; }
    .chantier-head .ch-legend { flex-wrap: wrap; gap: 0 18px; }
    .chantier-head .ch-legend .i { flex: 1 1 auto; }
}

/* ── Saisie des situations de chantier (page /affaire/{id}/situations) ──────

   L'ÉQUATION, au-dessus du tableau : déjà réalisé + cette situation = nouveau
   cumul. Tous les chiffres saisis sont des cumuls, un seul est un montant de
   période — la confusion se règle ici, en écrivant l'opération en toutes
   lettres, plutôt qu'en espérant qu'un intitulé de colonne suffise. */
.sit-eq { display: flex; align-items: stretch; flex-wrap: wrap; margin: 4px 0 18px; }
.sit-eq .box {
    flex: 1 1 200px;
    padding: 12px 16px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--surface-card);
}
.sit-eq .box .l {
    font-size: var(--text-xs);
    font-weight: var(--fw-semibold);
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 6px;
}
.sit-eq .box .n {
    font-size: 22px;
    font-weight: var(--fw-semibold);
    color: var(--text-strong);
    font-variant-numeric: tabular-nums;
}
.sit-eq .box .x { font-size: var(--text-xs); color: var(--text-muted); margin-top: 3px; }
.sit-eq .op { display: flex; align-items: center; padding: 0 12px; font-size: 20px; color: var(--text-subtle); }
/* Le terme du milieu est le seul qui compte au moment de facturer : il est le
   seul en couleur d'action. */
.sit-eq .box.now { border: 2px solid var(--action-primary-bg); background: var(--surface-brand-soft); }
.sit-eq .box.now .l, .sit-eq .box.now .n { color: var(--text-brand); }

@media (max-width: 900px) {
    .sit-eq { flex-direction: column; }
    .sit-eq .op { padding: 4px 0; }
}

/* Le tableau porte deux colonnes de saisie (le cumul, en % ou en €) et une
   colonne calculée (le montant de la période) : sans séparateur visuel, l'œil
   ne sait plus dans quelle série il tape.

   Ces champs vivent DANS un tableau, donc hors d'un `.field` : ils n'héritent
   d'aucun style de contrôle et sortiraient nus (bordure du navigateur, hauteur
   différente de celle du champ % voisin). On rejoue donc ici le style de
   contrôle du design system, calé sur `.pct-field` pour que les deux colonnes
   d'une même série s'alignent au pixel. */
.sit-table th.sep, .sit-table td.sep { border-left: 2px solid var(--border-subtle); }

/* L'en-tête est collant (`.db-table th`), mais sans z-index il reste dans la
   même couche que les cellules positionnées — et `.money-input` / `.pct-field`
   le sont. Sur un bordereau qui défile, les champs de saisie passaient DEVANT
   le nom de leur colonne. Posé ici et pas sur `.db-table th` : les listes ont
   un popover de filtre dans leur en-tête, dont l'empilement dépend de ces
   th-là. */
.sit-table th { z-index: 2; }

/* Deux zones nommées par un en-tête à deux niveaux : le cumul, et la période.
   Le fond porte le groupe sur toute la hauteur — c'est lui qui dit « ces deux
   colonnes-là parlent de la même chose », ce qu'un intitulé ne fait pas. La
   sélection de ligne et la ligne de total ont leur propre fond : les sélecteurs
   sont donc plus spécifiques. */
.sit-table tr.grp th {
    text-align: center;
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: .05em;
    padding-bottom: 2px;
    border-bottom: none;
}
.sit-table th.sub { font-size: var(--text-xs); font-weight: var(--fw-medium); color: var(--text-muted); }
.db-table.sit-table th.zn,
.db-table.sit-table tbody td.zn,
.db-table.sit-table tfoot tr.row-total td.zn,
.db-table.sit-table tbody tr.row-selected > td.zn { background: var(--surface-brand-soft); }
.sit-table th.zn, .sit-table td.zn { color: var(--text-brand); }
.sit-table tbody td.zn { font-size: var(--text-md); }
/* Prévisionnel non posé : le montant affiché vient du réalisé (règle de
   SituationService.PrevuPeriode). Il est juste, mais il n'a été décidé par
   personne — d'où le ton effacé. */
.sit-table tbody td.zn.herite { color: var(--text-muted); font-weight: var(--fw-regular); }
/* D'où part le cumul, et ce qui avait été prévu : en filigrane sous le champ,
   parce que la colonne qui portait ces valeurs n'est plus à l'écran. */
.sit-was {
    display: block;
    margin-top: 3px;
    font-size: var(--text-xs);
    color: var(--text-muted);
    text-align: right;
}

/* Ligne soldée avant cette situation : elle affiche son 100 % et rend sa place
   plutôt que deux champs qui ne peuvent plus rien recevoir. La marque est
   discrète — c'est un état, pas une action. */
.sit-done {
    display: block;
    margin-top: 3px;
    font-size: var(--text-2xs);
    font-weight: var(--fw-semibold);
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--green-600);
    text-align: right;
}

/* Conséquence de la saisie, en une phrase, juste avant les boutons. */
.sit-phrase {
    margin: 16px 0 0;
    padding: 10px 14px;
    border-left: 3px solid var(--action-primary-bg);
    background: var(--surface-brand-soft);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    font-size: var(--text-sm);
    color: var(--text-body);
}

.sit-table .pct-field { width: 96px; margin-left: auto; }
.sit-table .money-input { width: 118px; margin-left: auto; }
.sit-table .money-input input,
.sit-comment input {
    height: var(--control-h-sm);
    padding: 0 10px;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    background: var(--white);
    color: var(--text-strong);
    font-size: var(--text-md);
    transition: border-color 120ms ease-out, box-shadow 120ms ease-out;
}
.sit-table .money-input input {
    width: 100%;
    padding-right: 26px;
    text-align: right;
    font-family: var(--font-mono);
}
.sit-table .money-input .unit { font-size: var(--text-sm); }
.sit-table .money-input input:focus,
.sit-comment input:focus {
    outline: none;
    border-color: var(--border-focus);
    box-shadow: var(--ring);
}
.sit-table .money-input input:disabled { background: var(--surface-hover); }
.sit-table td { vertical-align: middle; }
.sit-trace { font-size: var(--text-xs); color: var(--text-muted); margin-top: 2px; }
.db-table tr.row-group td {
    background: var(--surface-hover);
    font-size: var(--text-sm);
    font-weight: var(--fw-medium);
    color: var(--text-muted);
}
/* Chapitre DANS le panneau détaillé d'une situation : c'est une ligne de
   structure (fond du groupe), mais elle porte des chiffres et deux champs de
   saisie — le gris effacé de `.row-group` la rendrait moins lisible que les
   postes qu'elle totalise. */
.sit-table tr.row-chap td { color: var(--text-strong); font-weight: var(--fw-semibold); }
.sit-table tr.row-chap td .hint { font-weight: var(--fw-regular); }
/* Chevron de repli : un bouton nu, à la ligne de base du titre. */
.sit-chap__x {
    border: 0;
    background: none;
    padding: 0 6px 0 0;
    margin: 0;
    color: var(--text-muted);
    cursor: pointer;
    vertical-align: -2px;
}
.sit-chap__x:hover { color: var(--text-strong); }
/* Place du chevron sur les lignes qui n'en ont pas : sans elle, les repères
   des postes ne s'alignent plus sur ceux des chapitres. */
.sit-chap__v { display: inline-block; width: 20px; }
/* Ligne du bordereau sans avancement : un commentaire, ou un poste ajouté
   après le passage en saisie détaillée. Elle est là pour la lecture. */
.sit-table tr.row-libre td { color: var(--text-subtle); }

/* Ligne de remise d'un bordereau : déduite du total, jamais saisie dans
   les situations. En italique pour se distinguer d'un poste. */
.db-table tr.row-remise td { font-style: italic; color: var(--text-muted); }
.db-table tr.row-remise td.mono { color: var(--text-strong); }
.db-table tr.row-selected > td { background: var(--surface-hover); }
.db-table td.neg, .db-table td .neg { color: var(--red-600); }
.nowrap { white-space: nowrap; }
/* Ligne verrouillée (validée ou partie au client) : lisible, mais visiblement
   inerte — sans ça, un champ désactivé garde l'air d'un champ où l'on peut taper. */
.money-input--off { opacity: .55; }
.money-input--off input { pointer-events: none; }
.pct-field:has(input:disabled) { opacity: .55; background: var(--surface-hover); }

/* Commentaire d'une ligne de situation : il part sur le relevé du client, donc
   il est visible en permanence, pas caché derrière une icône à déplier. Le
   libellé en petites capitales reprend celui des clés de fiche (.rk) — c'est
   ce qui le rattache visuellement au reste du site plutôt qu'à un champ isolé. */
/* La ligne de commentaire prolonge celle du devis : le trait qui les séparait
   faisait lire le commentaire comme celui du devis SUIVANT. Il tombe donc, et
   la cellule garde l'espace vertical d'une cellule normale — sans lui, le
   champ vient toucher la ligne du dessus. */
.sit-table tr:has(+ tr.row-comment) > td { border-bottom: none; }
.db-table tr.row-comment > td { border-top: none; padding-top: 10px; padding-bottom: 12px; }
.sit-comment { display: flex; align-items: center; gap: 10px; }
.sit-comment .lbl {
    font-size: var(--text-xs);
    font-weight: var(--fw-semibold);
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--text-muted);
    white-space: nowrap;
}
.sit-comment input { flex: 1; min-width: 0; }
.sit-comment-ro { color: var(--text-muted); font-style: italic; font-size: var(--text-sm); }
/* Suite donnée à un relevé (accord ou annulation) : le motif compte autant que
   le statut — un « Annulé » sans raison oblige à aller chercher ailleurs. Sur
   UNE ligne, tronqué : en pile, trois relevés annulés doublaient la hauteur du
   tableau pour des phrases qu'on ne relit jamais en entier. */
.db-table td.sit-suite {
    font-size: var(--text-sm);
    max-width: 240px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.sit-suite .d { color: var(--text-body); font-weight: var(--fw-medium); }
.sit-suite .m { color: var(--text-muted); }
.sit-suite .d + .m::before { content: " — "; }
.sit-suite .m.todo { font-style: italic; }

/* Barre de génération d'un relevé : fenêtre de dates, commentaire, aperçu du
   montant et bouton sur une seule ligne. */
.releve-bar {
    display: flex;
    align-items: flex-end;
    flex-wrap: wrap;
    gap: 10px 14px;
    margin-bottom: 4px;
}
.releve-bar > label { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.releve-bar > label.grow { flex: 1 1 240px; }
.releve-bar > label > span,
.sit-entete > label > span {
    font-size: var(--text-xs);
    font-weight: var(--fw-semibold);
    letter-spacing: .03em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.releve-bar input, .releve-bar select,
.sit-entete input {
    height: var(--control-h-sm);
    padding: 0 10px;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    background: var(--white);
    color: var(--text-strong);
    font-size: var(--text-md);
    width: 100%;
    transition: border-color 120ms ease-out, box-shadow 120ms ease-out;
}
.releve-bar input:focus, .releve-bar select:focus,
.sit-entete input:focus {
    outline: none;
    border-color: var(--border-focus);
    box-shadow: var(--ring);
}
.releve-bar .rb-apercu { display: flex; flex-direction: column; gap: 1px; padding-bottom: 2px; }
.releve-bar .rb-apercu .n {
    font-size: var(--text-lg);
    font-weight: var(--fw-semibold);
    color: var(--text-brand);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.releve-bar .rb-apercu .x { font-size: var(--text-xs); color: var(--text-muted); white-space: nowrap; }
.releve-bar .rb-apercu .vide { font-size: var(--text-sm); color: var(--text-muted); font-style: italic; }

/* En-tête d'une situation : date, libellé, commentaire interne sur une ligne,
   sans bouton à eux — ils partent avec « Tout enregistrer ». */
.sit-entete {
    display: flex;
    align-items: flex-end;
    flex-wrap: wrap;
    gap: 10px 14px;
    margin: 12px 0 14px;
}
.sit-entete > label { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.sit-entete > label.grow { flex: 1 1 200px; }
.sit-entete > label.grow2 { flex: 2 1 280px; }

/* ---------- Bordereau d'un devis (lignes) ---------- */
/* Le code article vit sous la désignation, en second plan : il sert à retrouver
   un poste dans le fichier d'origine, pas à être lu à chaque ligne. */
.dl-code { font-size: var(--text-xs); color: var(--text-subtle); margin-top: 2px; }

/* Aperçu d'import : le défilement vertical est celui du corps de la modale
   (.confirm-box__body) — deux ascenseurs imbriqués rendraient la lecture
   pénible. Ici, seul le débordement horizontal est pris en charge. */
.import-preview { overflow-x: auto; }

/* Bilan de réconciliation d'un import : deux totaux face à face. Le vert ou le
   rouge portent l'information, le chiffre la confirme. */
.import-check { display: flex; flex-wrap: wrap; gap: 22px; align-items: baseline; margin: 10px 0 4px; }
.import-check .k { font-size: var(--text-2xs); color: var(--text-subtle); text-transform: uppercase; letter-spacing: var(--ls-caps); font-weight: var(--fw-semibold); }
.import-check .v { font-family: var(--font-mono); font-size: var(--text-md); color: var(--text-strong); font-weight: var(--fw-semibold); }
.import-check.ok .v { color: var(--status-ok-fg, var(--text-strong)); }
.import-check.ko .v { color: var(--red-600); }

/* Ouvrages repris sans n° de bordereau : un par ligne, chapitre · libellé · montant. */
.import-sans-numero { margin: 12px 0 4px; }
/* Bornée en hauteur : un gros devis peut en aligner cent, la modale ne doit
   pas devenir une page de liste. */
.import-sans-numero ul { list-style: none; padding-left: 0; margin-top: 8px; max-height: 260px; overflow: auto; }
.import-sans-numero li { display: flex; gap: 12px; align-items: baseline; padding: 3px 0; border-top: 1px solid var(--amber-100); }
.import-sans-numero li .mono:first-child { min-width: 56px; color: var(--text-strong); }
.import-sans-numero__d { flex: 1; min-width: 0; }
.import-sans-numero li .mono:last-child { white-space: nowrap; }

/* Fichiers reconnus de l'export de chiffrage, sous la DropZone. */
.import-files { list-style: none; margin: 10px 0 0; padding: 0; font-size: var(--text-sm); }
.import-files li { display: flex; align-items: center; gap: 8px; padding: 4px 0; }
.import-files .role { font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--ls-caps); color: var(--text-subtle); font-weight: var(--fw-semibold); }

/* ---------- Saisie d'une situation poste par poste ---------- */
/* Le chevron ouvre le détail d'un devis. Il est là même quand le détail n'est
   pas activé : c'est par lui qu'on découvre que la saisie fine existe. */
.sit-expand {
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 22px; margin-right: 6px; vertical-align: middle;
    border: none; background: transparent; color: var(--text-subtle);
    border-radius: var(--radius-sm); cursor: pointer;
    transition: transform 120ms ease-out, color 120ms ease-out, background 120ms ease-out;
}
.sit-expand:hover { background: var(--surface-hover); color: var(--text-strong); }
.sit-expand.on { transform: rotate(90deg); color: var(--orange-700); }

/* Un devis suivi poste par poste : le dire sur la ligne, sinon on cherche
   pourquoi ses champs ne se laissent pas taper. */
.sit-badge-detail {
    margin-left: 8px; padding: 1px 7px; border-radius: var(--radius-pill);
    font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--ls-caps);
    font-weight: var(--fw-semibold); color: var(--orange-700);
    background: var(--orange-50, var(--surface-hover));
}

.db-table tr.row-detail > td { background: var(--surface-hover); padding: 0; }
.sit-detail { padding: 14px 16px 16px; }
.sit-detail__off { display: flex; gap: 16px; align-items: flex-start; justify-content: space-between; flex-wrap: wrap; }
.sit-detail__off .hint { margin: 4px 0 0; max-width: 70ch; }
.sit-detail__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 10px; flex-wrap: wrap; }
.sit-detail__t { font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--ls-caps); font-weight: var(--fw-semibold); color: var(--text-subtle); }
.sit-detail__a { display: flex; gap: 8px; }
/* Le panneau n'a pas de bouton d'enregistrement : le dire, sinon on cherche
   celui qui a disparu. */
.sit-detail__x { margin-left: 10px; text-transform: none; letter-spacing: normal; font-weight: var(--fw-regular); color: var(--text-muted); }
/* Un bordereau fait couramment cent postes : il défile dans sa boîte, sinon la
   ligne du devis suivant se retrouve à deux écrans de la précédente. */
.sit-detail__scroll { max-height: 52vh; }

/* N° de devis + version : deux champs de saisie, un seul numéro. Les séparer
   dans la grille ferait oublier qu'ils vont ensemble — le client, lui, lit
   « 2210447/00 » d'un seul tenant. Le séparateur affiché entre les deux dit
   qu'il n'est pas à saisir. */
.num-ver { display: flex; align-items: center; gap: 6px; }
.num-ver > input { flex: 1 1 auto; min-width: 0; }
.num-ver__sep { flex: none; color: var(--text-muted); }
/* Deux chiffres : la largeur du champ le dit avant même qu'on essaie. Elle est
   posée sur un CONTENEUR et non sur l'input — la règle générale des champs de
   formulaire (`.field input:not(…)`, width 100 %) est plus spécifique que
   n'importe quelle classe posée directement dessus, et l'emporterait. */
.num-ver__v { flex: none; width: 3.6em; }
.num-ver__v input { text-align: center; }

/* ── Droits par rôle (/utilisateurs) ─────────────────────────────────────
   Matrice dérivée de RoleMatrix : rôles en colonnes, droits en lignes. */
.droits-head {
    display: flex; align-items: flex-start; gap: 10px; width: 100%;
    border: none; background: none; padding: 0; cursor: pointer;
    text-align: left; color: var(--text-strong); font-family: inherit;
}
.droits-head:hover { color: var(--blue-600); }
.droits-head .sub { display: block; font-size: var(--text-xs); color: var(--text-muted); font-weight: 400; }

/* Colonnes de rôle serrées : la lisibilité tient à la colonne « Droit »,
   qui doit garder la place d'une phrase entière. */
.droits-table th.dr-role {
    text-align: center; white-space: nowrap; width: 1%; padding: 10px 12px;
}
.droits-table th.dr-role .rs-ico { display: block; margin: 0 auto 2px; }
.droits-table td.dr-cell { text-align: center; width: 1%; }
.droits-table .dr-oui { color: var(--green-600); display: inline-flex; }
/* Le refus se lit comme une absence, pas comme une alerte : un tiret gris,
   jamais une croix rouge — la moitié de la matrice serait en rouge. */
.droits-table .dr-non { color: var(--slate-300); }
.droits-table tr.dr-groupe td {
    background: var(--slate-50); font-size: var(--text-xs); font-weight: var(--fw-semibold);
    text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted);
    padding: 8px 14px;
}

/* ---------- Retours à l'éditeur (améliorations, bugs) ---------- */
/* Bouton « Signaler un problème » de la barre du haut : même gabarit que la
   cloche, le libellé disparaît sur écran étroit. */
.retour-menu { position: relative; }
.retour-btn { border: 1px solid var(--border-subtle); background: transparent; cursor: pointer; font-family: var(--font-sans); }
.retour-btn.is-open { border-color: var(--border-strong); color: var(--text-strong); }
@media (max-width: 1100px) { .retour-btn__label { display: none; } }
/* Menu de la bouée : même gabarit que les popovers de l'app, ancré à droite
   pour rester dans la fenêtre. Le fond transparent ferme au clic ailleurs
   sans JS. */
.retour-menu__backdrop { position: fixed; inset: 0; z-index: 40; }
.retour-menu__pop {
    position: absolute; z-index: 41; top: calc(100% + 6px); right: 0; width: 300px;
    background: var(--surface-card); border: 1px solid var(--border-default);
    border-radius: var(--radius-md); box-shadow: var(--shadow-lg); padding: 6px;
    display: flex; flex-direction: column; gap: 2px;
}
.retour-menu__pop > button, .retour-menu__pop > a {
    display: flex; align-items: center; gap: 10px; padding: 8px 10px; border: none; border-radius: var(--radius-sm);
    background: transparent; color: var(--text-strong); text-align: left; text-decoration: none; cursor: pointer;
    font-family: var(--font-sans); font-size: var(--text-sm);
}
.retour-menu__pop > button:hover, .retour-menu__pop > a:hover { background: var(--surface-hover); }
.retour-menu__pop svg { flex: none; color: var(--text-muted); }
.retour-menu__pop span { display: flex; flex-direction: column; }
.retour-menu__pop small { color: var(--text-muted); font-size: var(--text-2xs); }

.modal-box--retour { width: min(720px, 96vw); max-height: 94vh; overflow: auto; }
/* Modale de dépôt de document : quatre sélecteurs filtrables — l'overlay
   défile (overflow-y: auto sur .modal-overlay), la boîte reste en overflow
   visible pour que les listes déroulantes des SearchSelect sortent du cadre. */
.modal-box--depot { width: min(760px, 96vw); overflow: visible; }
/* Reclassement dans la fiche document : la cascade sur une colonne, dans le
   panneau latéral (étroit), et les listes des SearchSelect doivent pouvoir
   déborder du panneau. */
.att-move { margin: 6px 0 12px; padding: 12px; border: 1px solid var(--border-subtle); border-radius: var(--radius-md); background: var(--slate-50); }
.att-move .field-row { grid-template-columns: 1fr; gap: 0; }
.retour-aide { display: block; margin-top: 4px; color: var(--text-muted); font-size: var(--text-xs); }
.retour-contexte { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin: 6px 0 0; color: var(--text-muted); font-size: var(--text-xs); }
.retour-contexte code { font-size: var(--text-2xs); }
.retour-capture { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.retour-capture small { color: var(--text-muted); font-size: var(--text-xs); }
.retour-fichiers { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; gap: 4px; font-size: var(--text-sm); }
.retour-fichiers li { display: flex; align-items: center; gap: 6px; }
.retour-fichiers .muted { color: var(--text-muted); }

/* Guide de capture : replié par défaut, une étape par ligne, les touches en
   <kbd> comme dans le reste de l'app. */
.retour-guide { margin-top: 8px; font-size: var(--text-sm); color: var(--text-muted); }
.retour-guide summary { cursor: pointer; color: var(--action-primary-bg); font-weight: var(--fw-semibold); }
.retour-guide ol { margin: 8px 0 4px; padding-left: 20px; }
.retour-guide li { margin-bottom: 6px; }
.retour-guide li small { display: block; color: var(--text-subtle); }
.retour-guide p { margin: 4px 0 0; }
.retour-guide kbd, .drop-zone__kbd kbd { font-family: var(--font-mono); font-size: var(--text-2xs); padding: 1px 5px; border: 1px solid var(--border-strong); border-bottom-width: 2px; border-radius: 4px; background: var(--surface-card); color: var(--text-strong); margin: 0 1px; }

/* Doublons proposés à la saisie du titre. */
.retour-similaires { border: 1px solid var(--amber-300, #f6d28b); background: var(--amber-50, #fff8e6); border-radius: var(--radius-md); padding: 10px 12px; margin: -6px 0 12px; }
.retour-similaires__t { display: flex; align-items: center; gap: 6px; font-size: var(--text-sm); font-weight: var(--fw-semibold); color: var(--text-strong); margin-bottom: 6px; }
.retour-similaires__row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 6px 0; border-top: 1px solid rgba(0,0,0,.06); }
.retour-similaires__tx { display: flex; flex-direction: column; min-width: 0; }
.retour-similaires__tx small { color: var(--text-muted); }

/* Liste : le geste de soutien à gauche, comme un board. */
.retour-row { align-items: center; }
.retour-row.is-attente { background: var(--amber-50, #fff8e6); }
.retour-row.is-nonlu .li-title a { font-weight: var(--fw-bold); }
.retour-nonlu { display: inline-flex; align-items: center; gap: 5px; font-size: var(--text-2xs); font-weight: var(--fw-semibold); color: var(--orange-700); background: var(--orange-100); padding: 2px 8px; border-radius: var(--radius-pill); }
.retour-nonlu::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--orange-600); }
.retour-btn .count { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 5px; border-radius: var(--radius-pill); background: var(--orange-600); color: #fff; font-size: var(--text-2xs); font-weight: var(--fw-bold); }
.retour-row__vote { flex: none; width: 150px; display: flex; justify-content: center; }
.retour-row .li-title { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.retour-extrait { color: var(--text-subtle); }
.retour-reponse-court { color: var(--action-primary-bg); }
.retour-etat { flex: none; margin-bottom: 8px; }
.retour-etat .count { font-size: var(--text-2xs); margin-left: 4px; color: var(--text-muted); }
.retour-etat button.on .count { color: var(--text-strong); }
.retour-clos-note { display: flex; align-items: center; gap: 8px; padding: 10px 16px; font-size: var(--text-sm); color: var(--text-muted); background: var(--slate-100); border-bottom: 1px solid var(--border-subtle); }
.retour-budget { display: inline-flex; align-items: center; gap: 6px; font-size: var(--text-sm); color: var(--text-muted); padding: 0 4px; margin-bottom: 14px; white-space: nowrap; }
.retour-budget strong { color: var(--text-strong); }
.retour-moderation { margin-bottom: 14px; border-color: var(--amber-300, #f6d28b); }

.retour-vote { display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 10px; border: 1px solid var(--border-strong); border-radius: var(--radius-pill); background: var(--surface-card); color: var(--text-muted); font-family: var(--font-sans); font-size: var(--text-sm); cursor: pointer; }
.retour-vote strong { color: var(--text-strong); font-size: var(--text-md); }
.retour-vote.is-on { border-color: var(--orange-600); color: var(--orange-700); background: var(--orange-100); }
.retour-vote.is-on strong { color: var(--orange-700); }
.retour-vote:disabled { cursor: default; opacity: .6; }
.retour-vote__l { font-size: var(--text-2xs); white-space: nowrap; }
.retour-vote--pts { cursor: default; padding: 0 4px; }
.retour-vote__b { width: 22px; height: 22px; border: none; border-radius: 50%; background: var(--slate-100); color: var(--text-strong); font-weight: var(--fw-bold); cursor: pointer; line-height: 1; }
.retour-vote__b:hover:not(:disabled) { background: var(--orange-100); color: var(--orange-700); }
.retour-vote__b:disabled { opacity: .35; cursor: default; }

/* Fiche : contenu à gauche, contexte / soutiens / décisions à droite. */
.retour-grid { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 16px; align-items: start; }
@media (max-width: 1000px) { .retour-grid { grid-template-columns: 1fr; } }
.retour-col { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.retour-objet { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.retour-head-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.retour-texte { white-space: pre-wrap; margin: 0; line-height: 1.5; }
.retour-editeur { border-left: 3px solid var(--action-primary-bg); }
.retour-dl { display: grid; grid-template-columns: auto 1fr; gap: 6px 12px; margin: 0; font-size: var(--text-sm); }
.retour-dl dt { color: var(--text-muted); }
.retour-dl dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.retour-pre { margin: 0; padding: 8px 10px; background: var(--slate-100); border-radius: var(--radius-sm); font-family: var(--font-mono); font-size: var(--text-2xs); white-space: pre-wrap; overflow-wrap: anywhere; max-height: 240px; overflow: auto; }
.retour-diag details { margin-top: 8px; }
.retour-diag summary { cursor: pointer; font-size: var(--text-sm); color: var(--text-muted); }
.retour-pieces { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 12px; }
.retour-piece { margin: 0; width: 160px; }
.retour-piece a { display: block; height: 110px; border: 1px solid var(--border-subtle); border-radius: var(--radius-md); overflow: hidden; background: var(--slate-100); display: flex; align-items: center; justify-content: center; }
.retour-piece img { width: 100%; height: 100%; object-fit: cover; }
.retour-piece__doc { color: var(--text-muted); }
.retour-piece figcaption { display: flex; flex-direction: column; font-size: var(--text-xs); margin-top: 4px; overflow: hidden; }
.retour-piece figcaption span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.retour-piece figcaption small { color: var(--text-muted); }
.retour-messages { display: flex; flex-direction: column; gap: 10px; margin-bottom: 12px; }
.retour-message { padding: 10px 12px; border-radius: var(--radius-md); background: var(--slate-100); }
.retour-message.is-editeur { background: var(--orange-100); }
.retour-message__h { display: flex; justify-content: space-between; gap: 8px; margin-bottom: 4px; font-size: var(--text-sm); }
.retour-message__h small { color: var(--text-muted); }
.retour-soutiens { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; font-size: var(--text-sm); }
.retour-soutiens li { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.retour-soutiens li small { color: var(--text-muted); flex-basis: 100%; }
.retour-soutiens li p { flex-basis: 100%; font-size: var(--text-sm); color: var(--text-muted); }
.filters__check { flex-direction: row !important; align-items: center; gap: 6px; }
/* Contrôles des filtres au gabarit des champs du design system : ils
   sortaient au style du navigateur, petits et gris. */
.filters label:not(.filters__check) { font-size: var(--text-xs); font-weight: var(--fw-medium); color: var(--text-muted); }
.filters select, .filters input:not([type=checkbox]) {
    height: var(--control-h-md);
    padding: 0 10px;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    background: var(--white);
    color: var(--text-strong);
    font-family: var(--font-sans);
    font-size: var(--text-sm);
}
.filters select:focus, .filters input:not([type=checkbox]):focus { outline: none; border-color: var(--border-focus); box-shadow: var(--ring); }

/* ---------- Éditeur d'annotation d'une capture (retour-annoter.js) ---------- */
/* Au-dessus de la modale (10000) et du toast (10001). Sombre : l'image doit
   être la seule chose claire à l'écran. */
.annot { position: fixed; inset: 0; z-index: 10002; background: rgba(14, 17, 22, .92); display: flex; flex-direction: column; color: var(--white); font-family: var(--font-sans); }
.annot__bar { display: flex; align-items: center; gap: 16px; padding: 10px 16px; background: rgba(0,0,0,.35); flex-wrap: wrap; }
.annot__titre { font-weight: var(--fw-semibold); margin-right: auto; }
.annot__outils, .annot__actions { display: flex; gap: 6px; }
.annot__bar button { height: 32px; padding: 0 12px; border-radius: var(--radius-sm); border: 1px solid rgba(255,255,255,.25); background: transparent; color: var(--white); font-family: var(--font-sans); font-size: var(--text-sm); cursor: pointer; }
.annot__bar button:hover { background: rgba(255,255,255,.12); }
.annot__bar button.on { background: var(--white); color: var(--text-strong); border-color: var(--white); }
.annot__bar button.annot__ok { background: var(--orange-600); border-color: var(--orange-600); font-weight: var(--fw-semibold); }
.annot__bar button.annot__ok:hover { background: var(--orange-700); }
.annot__scene { flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center; padding: 12px; }
.annot__scene canvas { max-width: 100%; max-height: 100%; object-fit: contain; box-shadow: var(--shadow-lg); cursor: crosshair; touch-action: none; background: var(--white); }
.annot__aide { margin: 0; padding: 8px 16px 12px; font-size: var(--text-xs); color: rgba(255,255,255,.7); text-align: center; }

/* ---------- Nouveautés (retours livrés) ---------- */
.nouveaute { display: flex; align-items: center; gap: 12px; padding: 10px 14px; border-radius: var(--radius-sm); background: var(--orange-50, #fff7ed); border: 1px solid var(--orange-200, #fed7aa); color: var(--text-body); font-size: var(--text-sm); }
.nouveaute__tag { flex: none; font-size: var(--text-2xs); font-weight: var(--fw-bold); letter-spacing: var(--ls-caps); padding: 3px 7px; border-radius: var(--radius-pill); background: var(--orange-600); color: #fff; }
.nouveaute.is-bug .nouveaute__tag { background: var(--green-600, #16a34a); }
.nouveaute__tx { flex: 1; min-width: 0; }
.nouveaute__tx a { color: var(--orange-700); }
.nouveaute__rep { display: block; color: var(--text-muted); font-size: var(--text-xs); margin-top: 2px; }
.nouveaute__lien { flex: none; color: var(--orange-700); font-weight: var(--fw-semibold); white-space: nowrap; }
.nouveaute__x { flex: none; border: none; background: transparent; color: var(--text-subtle); cursor: pointer; padding: 4px; display: inline-flex; }
.nouveaute__x:hover { color: var(--text-strong); }
