/* ============================================================
   Proxima design system — application stylesheet (starter kit)
   Brand accent lives in the --accent* tokens below — change them in ONE place.
   ============================================================ */

:root {
    /* Surfaces */
    --bg-primary:    #f8f9fc;
    --bg-secondary:  #ffffff;
    --bg-tertiary:   #f0f1f5;
    --bg-elevated:   #ffffff;
    --bg-glass:       rgba(0, 0, 0, 0.02);
    --bg-glass-hover: rgba(0, 0, 0, 0.04);
    --bg-primary-rgb: 248, 249, 252;

    /* Text — les trois niveaux respectent le contraste WCAG AA (4,5:1 pour du texte
       courant) sur les TROIS surfaces de l'app : --bg-secondary (#ffffff, les cartes),
       --bg-primary (#f8f9fc, la page) et --bg-tertiary (#f0f1f5, les entêtes de table).
       C'est la surface la plus claire qui commande — un gris qui passe sur la page
       échoue souvent sur une carte blanche.
         primary   17,1:1  ·  secondary  7,1:1  ·  muted  5,6:1  (mesuré sur #ffffff)
       Avant ce réglage, « muted » tombait à 2,2:1 : les entêtes de colonnes, les
       libellés de KPI et les aides de formulaire étaient en dessous de la norme. */
    --text-primary:   #1a1a2e;
    --text-secondary: #52586a;
    --text-muted:     #646873;

    /* Accent. --accent porte le TEXTE (liens, onglet actif) ; --accent-fill porte les
       FONDS PLEINS sous du blanc (chip actif, pastille d'identité). Les deux divergent en
       thème sombre : le texte doit s'éclaircir là où le fond doit rester foncé. */
    --accent:         #003ee9;
    --accent-fill:    #003ee9;
    --accent-soft:    rgba(0, 62, 233, 0.10);
    --accent-glow:    rgba(0, 62, 233, 0.16);
    --accent-gradient: linear-gradient(135deg, #003ee9, #3366ff);

    /* Borders */
    --border:        rgba(0, 0, 0, 0.08);
    --border-subtle: rgba(0, 0, 0, 0.04);

    /* Scrollbar */
    --scrollbar-thumb:       rgba(0, 0, 0, 0.18);
    --scrollbar-thumb-hover: rgba(0, 0, 0, 0.32);

    /* Radii */
    --radius-sm:   8px;
    --radius-md:  12px;
    --radius-lg:  16px;
    --radius-xl:  24px;
    --radius-full: 9999px;

    /* Shadows */
    --shadow-sm:   0 1px 2px  rgba(0, 0, 0, 0.05);
    --shadow-md:   0 4px 16px rgba(0, 0, 0, 0.06);
    --shadow-lg:   0 8px 32px rgba(0, 0, 0, 0.08);
    --shadow-glow: 0 0 30px var(--accent-glow);

    --transition: 200ms cubic-bezier(0.4, 0, 0.2, 1);

    /* Tokens additionnels utilisés par la zone « Rapports » — couleur de marque (voir --accent). */
    --accent-wash: radial-gradient(120% 100% at 0% 0%, rgba(0, 62, 233, 0.10) 0%, rgba(0, 62, 233, 0.00) 60%);
    --shimmer: linear-gradient(90deg, var(--bg-tertiary) 0%, var(--bg-glass-hover) 50%, var(--bg-tertiary) 100%);
    --status-success: #22c55e;
    --status-warning: #f59e0b;
    --status-danger:  #ef4444;
    /* Le rouge de REMPLISSAGE ci-dessus porte du blanc et convient très bien à un
       bouton. Écrit en TEXTE sur une surface claire, il ne donne que 3,8:1 : d'où ce
       second jeton, réservé aux libellés (même rouge que la pastille « Refusée »). */
    --status-danger-texte: #b91c1c;

    /* Surlignage de la vue 3D du configurateur. Orange franc : c'est la couleur
       COMPLÉMENTAIRE du bleu de l'acier, donc la pièce visée ne peut pas se confondre
       avec le rayonnage — même en survolant une zone dense de montants. */
    --surligne: #f2600c;
}

[data-theme="dark"] {
    --bg-primary:    #0f1419;
    --bg-secondary:  #161b22;
    --bg-tertiary:   #1e242c;
    --bg-elevated:   #1a2028;
    --bg-glass:       rgba(255, 255, 255, 0.03);
    --bg-glass-hover: rgba(255, 255, 255, 0.06);
    --bg-primary-rgb: 15, 20, 25;

    /* Même exigence qu'en thème clair, la surface la plus SOMBRE en moins : ici c'est
       la plus claire (--bg-tertiary #1e242c) qui commande.
         primary  15,7:1  ·  secondary  7,3:1  ·  muted  5,6:1  (mesuré sur #0f1419)
       « muted » était à 3,2:1 sur les entêtes de table — sous la norme lui aussi. */
    --text-primary:   #e6edf3;
    --text-secondary: #9aa4b1;
    --text-muted:     #858d9f;

    --status-danger-texte: #f87171;

    /* Bleu CamRack éclairci pour le fond sombre — même marque qu'en thème clair,
       juste assez relevée pour que liens et boutons primaires restent lisibles. */
    --accent:      #6b93ff;
    --accent-fill: #2f5ee0;
    --accent-glow: rgba(0, 62, 233, 0.32);
    --accent-soft: rgba(107, 147, 255, 0.16);

    /* Sur fond sombre l'orange doit s'éclaircir, comme l'accent — même rôle, même écart. */
    --surligne: #ffa14a;

    --border:        rgba(255, 255, 255, 0.08);
    --border-subtle: rgba(255, 255, 255, 0.04);

    --scrollbar-thumb:       rgba(255, 255, 255, 0.18);
    --scrollbar-thumb-hover: rgba(255, 255, 255, 0.32);

    --shadow-sm: 0 1px 2px  rgba(0, 0, 0, 0.4);
    --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.45);
    --shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.55);

    color-scheme: dark;
}

/* ---- Reset ---- */
*, *::before, *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

html, body {
    height: 100%;
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
    font-size: 15px;
    line-height: 1.6;
    color: var(--text-primary);
    background: var(--bg-primary);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

a { color: inherit; text-decoration: none; }

/* ---- Scrollbars ---- */
* {
    scrollbar-width: thin;
    scrollbar-color: var(--scrollbar-thumb) transparent;
}
*::-webkit-scrollbar          { width: 10px; height: 10px; }
*::-webkit-scrollbar-track    { background: transparent; }
*::-webkit-scrollbar-thumb {
    background: var(--scrollbar-thumb);
    border: 2px solid transparent;
    background-clip: padding-box;
    border-radius: 8px;
    transition: background-color 0.15s ease;
}
*::-webkit-scrollbar-thumb:hover {
    background: var(--scrollbar-thumb-hover);
    background-clip: padding-box;
}
*::-webkit-scrollbar-corner   { background: transparent; }

/* ============================================================
   App shell
   ============================================================ */
.app-shell {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

/* L'entête tient sur DEUX rangées par défaut : marque, recherche et outils en haut,
   navigation dessous, sur toute la largeur.

   Pourquoi par défaut et pas seulement sur téléphone : le contenu de l'entête mesure
   ~1980 px (135 de marque + 1073 de navigation + 691 d'outils + marges). Aucun portable
   n'a cette largeur. Tant que la barre gardait `height: 56px`, la navigation se repliait
   sur trois rangées DANS une boîte de 56 px centrée — « Accueil » et « Configurateur »
   passaient au-dessus du haut de la fenêtre, hors d'atteinte à la souris. D'où la règle :
   la hauteur SUIT le contenu (`min-height`, jamais `height`), et la navigation prend sa
   propre rangée dès qu'elle ne rentre pas à côté du reste. */
.appbar {
    position: sticky;
    top: 0;
    z-index: 50;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px 16px;
    /* min-height, PAS height : une rangée qui se replie doit agrandir la barre, pas
       déborder par-dessus (ou au-dessus de) la page. */
    min-height: 56px;
    padding: 6px 24px;
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--border);
    backdrop-filter: blur(20px);
}
.appbar-leading,
.appbar-trailing { display: flex; align-items: center; gap: 12px; }
.appbar-leading  { flex: 1 1 auto; min-width: 0; }
.appbar-trailing { flex: 0 0 auto; }
/* La navigation passe en dernier (order) et occupe toute la largeur : sa rangée à elle. */
.appbar-center   { flex: 1 0 100%; min-width: 0; order: 3; }

/* Très grand écran seulement : tout rentre sur une seule rangée, on y revient. */
@media (min-width: 2000px) {
    .appbar { flex-wrap: nowrap; height: 56px; padding: 0 24px; gap: 16px; }
    .appbar-center { flex: 1 1 auto; order: 0; }
}

/* La hauteur de la barre collante, en jeton : tout ce qui se colle SOUS elle (menu de
   configuration, ancres) doit s'en écarter, sinon la barre lui passe par-dessus. Valeur
   volontairement généreuse — trop d'air ne casse rien, pas assez cache le contenu.
   L'ordre compte : le défaut d'abord, les media queries ensuite (même spécificité). */
:root { --appbar-h: 96px; }
@media (min-width: 2000px) { :root { --appbar-h: 56px; } }
@media (max-width: 820px)  { :root { --appbar-h: 140px; } }

.brand-lockup      { display: inline-flex; align-items: center; gap: 12px; }
.brand-lockup-name { font-weight: 600; font-size: 18px; font-family: inherit; letter-spacing: -0.015em; color: var(--text-primary); }
.app-icon { display: inline-block; flex-shrink: 0; }
.app-icon-md { width: 32px; height: 32px; }

.appbar-badge {
    font-weight: 500; font-size: 9.5px; font-family: inherit;
    color: var(--accent);
    background: var(--accent-soft);
    padding: 2px 8px;
    border-radius: var(--radius-full);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    line-height: 1.6;
}
/* Pastille « Dev » (BadgeEnvironnement.razor) : ambre plutôt que l'accent — l'accent dit
   « c'est la marque », l'ambre dit « attention, pas la production ». Teintes de .tag.warn.
   La pastille « Démo » garde la teinte neutre de .appbar-badge : rien à craindre, c'est fictif. */
.appbar-badge.badge-dev { color: #b45309; background: rgba(245, 158, 11, 0.16); }
[data-theme="dark"] .appbar-badge.badge-dev { color: #fbbf24; }
@media (max-width: 560px) {
    /* Sur téléphone, la phrase entière pousserait la navigation : le titre (survol, lecteur
       d'écran) garde l'explication. */
    .appbar-badge.badge-dev, .appbar-badge.badge-demo {
        max-width: 9.5em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
}

.status-row {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-weight: 500; font-size: 11px; font-family: inherit;
    letter-spacing: 0.02em;
    color: var(--text-secondary);
}
.status-dot {
    width: 7px;
    height: 7px;
    border-radius: var(--radius-full);
    background: #22c55e;
    box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.18);
}

.btn-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    background: transparent;
    border: none;
    border-radius: var(--radius-full);
    color: var(--text-secondary);
    cursor: pointer;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.btn-icon:hover { background: var(--bg-glass-hover); color: var(--accent); }
.btn-icon.is-active { color: var(--accent); background: var(--accent-soft); }
a.btn-icon { text-decoration: none; }
/* Variante resserrée : dans une ligne de tableau, 34px casserait la hauteur de ligne. */
.btn-icon.compact { width: 26px; height: 26px; font-size: 13px; }
/* Variante destructive : le survol vire au rouge, pas à l'accent — supprimer n'est
   pas une action de marque. */
.btn-icon.danger:hover { color: #dc2626; background: var(--bg-glass-hover); }
[data-theme="dark"] .btn-icon.danger:hover { color: #f87171; }

/* ---- Mobile ----
   Sur petit écran, tout débordement horizontal fait « dézoomer » le navigateur, ce qui casse
   toute la mise en page (grilles qui repassent en 2 colonnes, champs coupés). On réduit donc le
   padding de la barre du haut et du contenu pour tout faire tenir dans la largeur de l'écran. */
/* ---- Entête sur petit écran (tablette, téléphone) ----
   Les deux rangées sont déjà la règle par défaut (voir `.appbar` plus haut). Ici, on
   resserre : sur un téléphone, le moindre débordement horizontal fait dézoomer TOUTE la
   page, et l'app devient illisible. La rangée du haut doit donc pouvoir se comprimer —
   la recherche prend ce qui reste au lieu d'imposer sa largeur ; la navigation, elle,
   défile horizontalement (voir MainLayout.razor.css). */
@media (max-width: 820px) {
    .appbar { padding: 8px 14px; gap: 8px 10px; }
    /* La rangée du haut doit pouvoir se comprimer : à 390 px, ses outils mesurent ~590 px
       à leur taille naturelle. Sans `min-width: 0`, un conteneur flex refuse de descendre
       sous son contenu et c'est la PAGE qui s'élargit — le navigateur dézoome alors tout. */
    .appbar-leading  { flex: 0 1 auto; }
    .appbar-trailing { flex: 1 1 auto; min-width: 0; justify-content: flex-end; }
    .appbar .search-field,
    .appbar .recherche-globale { flex: 1 1 90px; min-width: 0; }
    .appbar .recherche-champ { width: 100%; min-width: 0; }
    .appbar .personnification { min-width: 0; }
    .appbar .personnification-select { max-width: 110px; }
}

@media (max-width: 640px) {
    .appbar { padding: 8px 12px; gap: 8px; }
}

/* Très petit écran (iPhone SE) : la rangée du haut ne rentre plus au mot près.
   On garde l'icône de marque — qui reste le lien vers l'accueil — et on laisse
   tomber le mot, plutôt que de laisser le navigateur dézoomer toute la page. */
@media (max-width: 400px) {
    .appbar .brand-lockup-name { display: none; }
}

.app-main {
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;
    /* Utilise l'essentiel de la largeur de l'écran (≈ 95 % sur écran standard, plafonné sur
       très grand écran) au lieu de l'ancien 1320px qui laissait de larges marges vides. */
    max-width: min(2000px, 95vw);
    margin: 0 auto;
    padding: 28px 28px;
}

/* Sur téléphone, on récupère les marges : elles coûtaient 28 px de chaque côté au
   contenu. Cette règle DOIT rester après `.app-main` ci-dessus — à spécificité égale,
   c'est la dernière qui gagne, et écrite avant elle n'avait jamais rien fait. */
@media (max-width: 640px) {
    .app-main { padding: 18px 14px; }
}

/* ---- Footer ---- */
.footer {
    background: var(--bg-secondary);
    border-top: 1px solid var(--border);
    color: var(--text-secondary);
    font-size: 13px;
}
.footer-minimal {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 14px 24px;
}
.footer-copy strong { color: var(--text-primary); font-weight: 600; }
.footer-meta { color: var(--text-muted); font-variant-numeric: tabular-nums; }
@media (max-width: 720px) {
    .footer-minimal { flex-direction: column; align-items: flex-start; gap: 6px; }
}

/* ============================================================
   Page
   ============================================================ */
.page { display: flex; flex-direction: column; gap: 20px; }

.page-header {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
}
.page-title    { font-weight: 600; font-size: 28px; font-family: inherit; letter-spacing: -0.02em; color: var(--text-primary); }
.page-subtitle { font-size: 13px; color: var(--text-muted); margin-top: 2px; }

/* ---- Search ---- */
.search-field { position: relative; min-width: 280px; }
.search-icon {
    position: absolute;
    left: 12px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--text-muted);
    display: inline-flex;
    pointer-events: none;
}
.input.search-input { padding-left: 36px; }

.input {
    width: 100%;
    padding: 9px 12px;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    /* IMPORTANT : hériter la police du body (Inter). Le raccourci « font: … inherit » est
       invalide et était ignoré → les <input>/<select> tombaient en Arial et les <textarea>
       en monospace. On déclare donc les propriétés séparément. */
    font-family: inherit;
    font-size: 14px;
    line-height: 1.5;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.input:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-soft);
}

/* ============================================================
   Sélecteurs de date — STYLE_GUIDE §5.8
   Le calendrier est DESSINÉ par nous (composant SelecteurDate.razor) : la fenêtre
   native ne se thème pas, change d'un navigateur à l'autre et parle la langue du
   système. Les règles « input[type=date] » plus bas ne servent que de filet de
   sécurité pour un champ natif résiduel.
   ============================================================ */
.date-field {
    position: relative;
    display: inline-block;
    min-width: 220px;
}
/* Dans une grille de formulaire, le champ suit la colonne — sinon le min-width
   ci-dessus ferait déborder `.form-grid.tight` (colonnes de 155px). */
.form-field .date-field { display: block; width: 100%; min-width: 0; }

.date-field-trigger {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 9px 12px;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-family: inherit;
    font-size: 14px;
    line-height: 1.5;
    cursor: pointer;
    text-align: left;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.date-field-trigger:hover:not(:disabled) { border-color: var(--text-secondary); }
.date-field.open .date-field-trigger,
.date-field-trigger:focus-visible {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-soft);
    outline: none;
}
.date-field-trigger:disabled {
    cursor: not-allowed;
    opacity: 0.5;
    pointer-events: none;
}
.date-field-icon  { color: var(--text-muted); flex-shrink: 0; }
.date-field-value { flex: 1; min-width: 0; font-variant-numeric: tabular-nums; }
.date-field-value.empty { color: var(--text-muted); }
.date-field.open .date-field-icon { color: var(--accent); }

.date-picker {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    z-index: 30;
    width: 280px;
    padding: 12px;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    box-shadow: 0 12px 24px rgba(0, 0, 0, 0.12),
                0 2px 6px  rgba(0, 0, 0, 0.06);
    animation: date-picker-in 0.14s ease-out;
}
@keyframes date-picker-in {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: translateY(0);    }
}
/* Près du bord droit, la fenêtre s'aligne sur la droite du champ pour ne pas sortir
   de l'écran (dernière colonne d'une grille de formulaire). */
.date-field.align-right .date-picker { left: auto; right: 0; }

/* Sur téléphone, une fenêtre de 280px accrochée à gauche d'un champ déjà décalé fait
   déborder la page — et le navigateur dézoome alors TOUTE l'interface. On l'accroche
   donc à droite du champ et on la plafonne à la largeur de l'écran. */
@media (max-width: 720px) {
    .date-picker {
        left: auto;
        right: 0;
        width: min(280px, calc(100vw - 28px));
    }
}

.date-picker-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 2px 2px 10px;
}
.date-picker-title {
    font-weight: 600;
    font-size: 14px;
    color: var(--text-primary);
    letter-spacing: -0.01em;
    text-transform: capitalize;
}
.date-picker-nav {
    width: 28px;
    height: 28px;
    background: transparent;
    border: none;
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background-color var(--transition), color var(--transition);
}
.date-picker-nav:hover { background: var(--accent-soft); color: var(--accent); }

.date-picker-weekdays {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 2px;
    padding-bottom: 6px;
    margin-bottom: 4px;
    border-bottom: 1px solid var(--border-subtle);
}
.date-picker-weekdays span {
    text-align: center;
    font-weight: 500;
    font-size: 10.5px;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    padding: 4px 0;
}

.date-picker-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 2px;
}
.date-picker-day {
    aspect-ratio: 1;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-family: inherit;
    font-weight: 500;
    font-size: 13px;
    font-variant-numeric: tabular-nums;
    cursor: pointer;
    transition: background-color 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.date-picker-day:hover           { background: var(--accent-soft); color: var(--accent); }
.date-picker-day.outside         { color: var(--text-muted); opacity: 0.55; }
.date-picker-day.today           { border-color: var(--accent); }
.date-picker-day.selected,
.date-picker-day.selected:hover  { background: var(--accent-fill); color: #ffffff; border-color: var(--accent-fill); }
.date-picker-day.disabled,
.date-picker-day:disabled        { opacity: 0.3; cursor: not-allowed; pointer-events: none; }

.date-picker-footer {
    display: flex;
    justify-content: space-between;
    gap: 8px;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid var(--border-subtle);
}
.date-picker-action {
    background: transparent;
    border: none;
    color: var(--accent);
    font-family: inherit;
    font-weight: 600;
    font-size: 12.5px;
    cursor: pointer;
    padding: 4px 10px;
    border-radius: 4px;
    transition: background-color 0.12s ease;
}
.date-picker-action:hover { background: var(--accent-soft); }

.date-picker-backdrop {
    position: fixed;
    inset: 0;
    z-index: 20;
    background: transparent;
}

/* Filet de sécurité pour un éventuel champ natif : au moins la fenêtre du système
   suit le thème et l'icône ne reste pas noire sur fond sombre. */
input[type="date"],
input[type="time"],
input[type="datetime-local"] {
    min-width: 160px;
    font-variant-numeric: tabular-nums;
    color-scheme: light;
}
[data-theme="dark"] input[type="date"],
[data-theme="dark"] input[type="time"],
[data-theme="dark"] input[type="datetime-local"] { color-scheme: dark; }

input[type="date"]::-webkit-calendar-picker-indicator,
input[type="time"]::-webkit-calendar-picker-indicator,
input[type="datetime-local"]::-webkit-calendar-picker-indicator {
    cursor: pointer;
    opacity: 0.55;
    transition: opacity 0.12s ease;
}
input[type="date"]:hover::-webkit-calendar-picker-indicator,
input[type="time"]:hover::-webkit-calendar-picker-indicator,
input[type="datetime-local"]:hover::-webkit-calendar-picker-indicator { opacity: 0.85; }
[data-theme="dark"] input[type="date"]::-webkit-calendar-picker-indicator,
[data-theme="dark"] input[type="time"]::-webkit-calendar-picker-indicator,
[data-theme="dark"] input[type="datetime-local"]::-webkit-calendar-picker-indicator { filter: invert(1); }

/* ============================================================
   Champ fichier — STYLE_GUIDE §5.15
   Même raison d'être que le sélecteur de date plus haut : le bouton natif d'un
   « input[type=file] » ne se thème pas, change de dessin d'un navigateur à
   l'autre et parle la LANGUE DU SYSTÈME — « Choose File » / « No file chosen »
   au milieu d'une interface française. On masque donc le champ natif et on
   habille le <label> qui l'enveloppe : cliquer le label ouvre le sélecteur, sans
   une ligne de JavaScript.
   ============================================================ */
.champ-fichier {
    position: relative; /* contient le champ natif rendu invisible ci-dessous */
    display: inline-flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
}
/* Le champ reste focusable et annoncé par un lecteur d'écran : on le rend
   invisible, on ne le retire pas avec « display: none ». */
.champ-fichier input[type="file"] {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    border: 0;
    overflow: hidden;
    white-space: nowrap;
    clip-path: inset(50%);
}
/* Dessin de `.btn-secondary` — un dépôt de fichier n'est pas l'action principale
   d'un écran, il ne prend donc pas le dégradé. */
.champ-fichier-bouton {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    white-space: nowrap;
    padding: 8px 16px;
    background: var(--bg-elevated);
    color: var(--text-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font: 500 13px/1 'Inter', system-ui, sans-serif;
    cursor: pointer;
    transition: border-color var(--transition), color var(--transition), background-color var(--transition);
}
.champ-fichier:hover .champ-fichier-bouton { border-color: var(--text-secondary); color: var(--text-primary); }
/* Le champ étant invisible, l'anneau de focus doit se poser sur le faux bouton :
   sans ça, un parcours au clavier passe sur un contrôle qui ne se voit pas. */
.champ-fichier input[type="file"]:focus-visible + .champ-fichier-bouton {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-soft);
}
.champ-fichier input[type="file"]:disabled + .champ-fichier-bouton {
    cursor: not-allowed;
    color: var(--text-muted);
    border-color: var(--border-subtle);
    background: var(--bg-glass);
}

/* Filet de sécurité pour un champ fichier natif résiduel (même rôle que les
   règles « input[type=date] » plus haut) : au minimum nos couleurs et notre
   police, jamais le gris système. */
input[type="file"] {
    font-family: inherit;
    font-size: 13px;
    color: var(--text-secondary);
    cursor: pointer;
}
input[type="file"]::file-selector-button {
    margin-right: 10px;
    padding: 6px 13px;
    background: var(--bg-elevated);
    color: var(--text-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font: 500 13px/1 'Inter', system-ui, sans-serif;
    cursor: pointer;
    transition: border-color var(--transition), color var(--transition), background-color var(--transition);
}
input[type="file"]:hover:not(:disabled)::file-selector-button { border-color: var(--text-secondary); color: var(--text-primary); }
input[type="file"]:disabled::file-selector-button {
    cursor: not-allowed;
    color: var(--text-muted);
    border-color: var(--border-subtle);
    background: var(--bg-glass);
}

/* ============================================================
   Buttons — STYLE_GUIDE §5.15
   Quatre variantes, et rien d'autre : primaire (dégradé), secondaire (contour),
   pastille (petite action en ligne) et icône. Chacune accepte `disabled`.
   ============================================================ */
.btn-primary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    padding: 8px 16px;
    border: none;
    border-radius: var(--radius-sm);
    background: var(--accent-gradient);
    color: #ffffff;
    font: 500 13px/1 'Inter', system-ui, sans-serif;
    cursor: pointer;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.btn-primary:hover:not(:disabled)  { transform: translateY(-1px); box-shadow: 0 6px 14px var(--accent-glow), 0 2px 4px rgba(0, 0, 0, 0.06); }
.btn-primary:active:not(:disabled) { transform: translateY(0); }

.btn-secondary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    white-space: nowrap;
    padding: 8px 16px;
    background: var(--bg-elevated);
    color: var(--text-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font: 500 13px/1 'Inter', system-ui, sans-serif;
    cursor: pointer;
    /* Jamais `transition: all` (STYLE_GUIDE §1.7) : on nomme les propriétés. */
    transition: border-color var(--transition), color var(--transition), background-color var(--transition);
}
.btn-secondary:hover:not(:disabled) { border-color: var(--text-secondary); color: var(--text-primary); }

/* Déclinaison compacte des deux boutons — l'action posée dans un en-tête de carte
   (« + Ajouter… ») ne doit pas peser plus lourd que le titre qu'elle accompagne. */
.btn-primary.btn-sm,
.btn-secondary.btn-sm { padding: 5px 11px; font-size: 12.5px; }

/* Pastille — petite action en ligne (dans un tableau, une carte, une barre d'outils).
   Remplace l'ancien « btn-mini » maison. */
.chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    white-space: nowrap;
    padding: 4px 12px;
    font-family: inherit;
    font-size: 12px;
    font-weight: 500;
    /* Hauteur fixée ici : sans ça un <a class="chip"> hérite du line-height 1.6 du
       body et se retrouve plus haut qu'un <button class="chip"> voisin. */
    line-height: 1.25;
    color: var(--text-secondary);
    background: var(--bg-glass);
    border: 1px solid var(--border);
    border-radius: var(--radius-full);
    cursor: pointer;
    transition: color var(--transition), border-color var(--transition), background-color var(--transition);
}
.chip:hover:not(:disabled) {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--accent-soft);
}
/* État « activé » d'une pastille bascule (ex. contact principal, filtre en cours). */
.chip.is-on {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--accent-soft);
}

/* Action textuelle — même rôle que `.date-picker-action` du style guide : pas de
   contour, texte d'accent, fond doux au survol. Utilisée dans les tableaux et les
   entêtes de carte, là où un contour ajouterait du bruit. */
.btn-link {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    border: none;
    background: transparent;
    padding: 3px 8px;
    margin: -3px 0;
    font-family: inherit;
    font-weight: 600;
    font-size: 12.5px;
    color: var(--accent);
    border-radius: 4px;
    cursor: pointer;
    white-space: nowrap;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.btn-link:hover:not(:disabled) { background: var(--accent-soft); }

/* Un bouton désactivé doit SE VOIR comme désactivé : sans ça, un « btn-primary »
   inactif gardait sa couleur vive et invitait au clic. `pointer-events: none`
   garantit en plus qu'aucun état de survol ne se déclenche (STYLE_GUIDE §5.15). */
.btn-secondary:disabled,
.chip:disabled,
.btn-link:disabled,
.btn-icon:disabled {
    cursor: not-allowed;
    opacity: 0.5;
    pointer-events: none;
    transform: none !important;
}
/* Le primaire perd son dégradé : un fond neutre dit « indisponible » mieux qu'une
   opacité, qui laisserait deviner un bouton d'action bien vivant. */
.btn-primary:disabled {
    cursor: not-allowed;
    pointer-events: none;
    transform: none !important;
    background: var(--bg-tertiary);
    color: var(--text-muted);
    box-shadow: none;
    opacity: 1;
}
.btn-secondary:disabled {
    color: var(--text-muted);
    border-color: var(--border-subtle);
    background: var(--bg-glass);
}
.chip:disabled {
    color: var(--text-muted);
    border-color: var(--border-subtle);
    background: transparent;
}

/* ============================================================
   List
   ============================================================ */
.list { list-style: none; padding: 0; margin: 0; }
.list-item {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 16px 18px;
    border-bottom: 1px solid var(--border-subtle);
    transition: background-color 0.12s ease;
}
.list-item:last-child { border-bottom: none; }
.list-item:hover      { background: var(--bg-glass-hover); }
.list-item-body  { flex: 1; min-width: 0; }
.list-item-title {
    font-weight: 600; font-size: 15px; font-family: inherit;
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.list-item-sub {
    font-size: 13px;
    color: var(--text-secondary);
    margin-top: 4px;
    line-height: 1.5;
}

.project-item-head {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 4px;
}
.project-number {
    font: 600 11px 'JetBrains Mono', 'Fira Code', monospace;
    letter-spacing: 0.04em;
    color: var(--text-muted);
}

/* ============================================================
   Table
   ============================================================ */
.table-scroll {
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    overflow: auto;              /* scrolls horizontally and vertically as needed */
    max-height: 640px;
}
.table {
    width: 100%;
    min-width: 720px;            /* keep columns readable; the wrapper scrolls when narrower */
    border-collapse: separate;
    border-spacing: 0;
    font-size: 14px;
    table-layout: fixed;
}
.table thead th {
    position: sticky;            /* header stays put while the rows scroll */
    top: 0;
    z-index: 1;
    background: var(--bg-tertiary);
    text-align: left;
    padding: 11px 14px;
    font-weight: 500;
    font-size: 11px;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
}
/* Clickable, sortable column headers — styled to read like the header label itself.
   Shared by the projects list (.table) and every detail table (.data-table). */
.table thead th .th-sort,
.data-table thead th .th-sort {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0;
    padding: 0;
    background: none;
    border: 0;
    font: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
    color: inherit;
    cursor: pointer;
    user-select: none;
    transition: color 0.15s ease;
}
.table thead th .th-sort:hover,
.data-table thead th .th-sort:hover { color: var(--text-primary); }
.table thead th .th-sort:focus-visible,
.data-table thead th .th-sort:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 4px;
}
.table thead th:not([aria-sort="none"]) .th-sort,
.data-table thead th:not([aria-sort="none"]) .th-sort { color: var(--text-primary); }
.sort-arrow {
    font-size: 10px;
    line-height: 1;
    opacity: 0.4;
    transition: opacity 0.15s ease, color 0.15s ease;
}
.sort-arrow.is-active {
    opacity: 1;
    color: var(--accent);
}
.table tbody td {
    padding: 12px 14px;
    color: var(--text-primary);
    border-bottom: 1px solid var(--border-subtle);
    vertical-align: middle;
}
.table tbody tr:last-child td { border-bottom: none; }
.table tbody tr:hover         { background: var(--bg-glass-hover); }

/* Column widths — applied to header and body so the two aligned tables match.
   Every column (including Projet, col 2) gets a width so none collapses to 0 when
   the table is narrow; table-layout:fixed then shrinks them proportionally. */
.table th:nth-child(1), .table td:nth-child(1) { width: 130px; }
.table th:nth-child(2), .table td:nth-child(2) { width: 260px; }
.table th:nth-child(3), .table td:nth-child(3) { width: 190px; }
.table th:nth-child(4), .table td:nth-child(4) { width: 160px; }
.table th:nth-child(5), .table td:nth-child(5) { width: 120px; }
.table th:nth-child(6), .table td:nth-child(6) { width: 130px; }

.cell-number {
    font-family: 'JetBrains Mono', 'Fira Code', monospace;
    font-size: 12px;
    letter-spacing: 0.02em;
    color: var(--text-muted);
    white-space: nowrap;
}
.cell-title {
    font-weight: 600;
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.cell-sub {
    font-size: 12.5px;
    color: var(--text-secondary);
    margin-top: 2px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.cell-action { text-align: right; white-space: nowrap; }
.btn-row { padding: 6px 12px; }
/* Troncature « … » générique pour les colonnes texte (Contact, Emplacement) afin que
   les valeurs longues n'augmentent pas la hauteur des lignes — la valeur complète reste
   visible au survol via l'attribut title. */
.cell-ellipsis {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ============================================================
   Pagination
   ============================================================ */
.table-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
}
.table-footer-info { font-size: 13px; color: var(--text-muted); font-variant-numeric: tabular-nums; }

.pagination { display: inline-flex; align-items: center; gap: 4px; }
.pagination-btn {
    min-width: 32px;
    height: 32px;
    padding: 0 8px;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    font-weight: 500;
    font-size: 13px;
    font-variant-numeric: tabular-nums;
    cursor: pointer;
    transition: var(--transition);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.pagination-btn:hover:not(:disabled):not(.active) {
    border-color: var(--border);
    color: var(--text-primary);
    background: var(--bg-glass-hover);
}
.pagination-btn.active {
    background: var(--accent-fill);
    border-color: var(--accent-fill);
    color: #ffffff;
    cursor: default;
}
.pagination-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.pagination-ellipsis { color: var(--text-muted); padding: 0 6px; user-select: none; }

/* ============================================================
   Tags
   ============================================================ */
.tag {
    display: inline-block;
    padding: 3px 8px;
    background: var(--accent-soft);
    color: var(--accent);
    font-weight: 600;
    font-size: 10px;
    line-height: 1;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    border-radius: var(--radius-full);
    white-space: nowrap;
}
/* `tag-success` prend le vert FONCÉ, comme `.pill-ok` plus bas : le vert de marque
   (#22c55e) posé en TEXTE sur son propre fond pâle ne donnait que 2,0:1 — illisible.
   C'était la seule des quatre déclinaisons sans variante sombre, d'où l'oubli. */
.tag.tag-success { color: #137638; background: rgba(34, 197, 94, 0.14); }
/* Le jeton, pas une copie : la valeur écrite en dur ici était l'ancien --text-secondary,
   et elle serait restée figée au premier réglage du gris. */
.tag.tag-info    { color: var(--text-secondary); background: var(--bg-tertiary); }
.tag.warn        { color: #a64c08; background: rgba(245, 158, 11, 0.16); }
.tag.error       { color: #b91c1c; background: rgba(239, 68, 68, 0.14); }
[data-theme="dark"] .tag.tag-success { color: #4ade80; }
[data-theme="dark"] .tag.warn  { color: #fbbf24; }
[data-theme="dark"] .tag.error { color: #f87171; }

/* ============================================================
   Cards / details
   ============================================================ */
.card {
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: 18px 20px;
}
/* En-tête de carte : titre à gauche, action (ex. « + Nouvelle soumission ») à droite,
   avec de l'air autour du bouton pour qu'il ne colle ni au titre ni au corps. */
.card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
    margin-bottom: 14px;
}
.card-head .btn-primary,
.card-head .btn-secondary,
.card-head .btn-link { margin-left: auto; }
.detail-description { font-size: 15px; line-height: 1.6; color: var(--text-primary); }

/* Lignes de tableau cliquables (ouvrent le détail) — voir DataTable RowHref. */
.data-table tbody tr.row-link { cursor: pointer; transition: background-color 0.12s ease; }
.data-table tbody tr.row-link:hover { background: var(--bg-glass-hover); }

/* ── Files d'attente (bande de cartes au-dessus d'une grille) ─────────────────
   Partagé par /soumissions (approbation · relance) et /leads (à contacter ·
   à relancer) : ce sont des FILES, pas des chapitres — on les balaye du regard,
   on n'y lit pas ligne à ligne. Empilées pleine largeur, elles poussaient la
   grille de la page hors écran ; en bande, la grille reste visible sans défiler.
   auto-fit plutôt qu'un « repeat(n, …) » figé : quand une seule file a du
   contenu, elle occupe la largeur au lieu de laisser un trou. */
.files-attente {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: 14px;
    align-items: start;
}

/* Version compacte de la carte : moins d'air qu'une carte de page, parce que
   plusieurs d'entre elles partagent la largeur. */
.file-card { padding: 14px 16px; }

/* La note du bandeau ne tient plus à droite du titre dans une colonne étroite :
   elle passe dessous, en petit. */
.file-head {
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    margin-bottom: 10px;
}
.file-titre { font-size: 15px; letter-spacing: -0.01em; }
.file-note { font-size: 11.5px; line-height: 1.35; color: var(--text-muted); }

.file-liste { list-style: none; margin: 0; padding: 0; }
/* Deux temps par dossier : QUI sur la première ligne, COMBIEN et QUAND en gris
   sur la seconde. Un filet sépare les dossiers — sans lui, les deux lignes d'un
   même dossier se confondent avec celles du suivant. */
.file-ligne {
    display: flex;
    flex-direction: column;
    gap: 1px;
    padding: 7px 0;
    border-bottom: 1px solid var(--border-subtle);
}
.file-ligne:first-child { padding-top: 0; }
.file-ligne:last-child { padding-bottom: 0; border-bottom: 0; }

.file-tete { display: flex; align-items: center; gap: 8px; min-width: 0; font-size: 13px; }
/* Le nom du client cède le premier : le numéro et la pastille ne doivent jamais
   être coupés, ce sont eux qui identifient le dossier. */
.file-client {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--text-secondary);
}
.file-meta {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    font-size: 12px;
    color: var(--text-muted);
}
.file-montant { color: var(--text-secondary); font-variant-numeric: tabular-nums; }

/* Une pastille de file reste lisible mais tient moins de place que dans une
   grille pleine largeur. */
.file-tete .pill { padding: 1px 8px; font-size: 11px; }

/* ── Funnel de vente (tableau de bord) : cône Lead → Soumission → Commande ────────
   Les paliers sont centrés et se rétrécissent, formant un cône. Chaque barre est
   un trapèze (clip-path) pour que les bords « rentrent » vers l'étage suivant. */
.funnel { display: flex; flex-direction: column; align-items: center; gap: 4px; max-width: 560px; margin: 0 auto; }
.funnel-stage { display: flex; flex-direction: column; align-items: center; width: 100%; }
.funnel-bar {
    height: 62px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 0 18px;
    color: #ffffff;
    text-align: center;
    text-decoration: none;
    min-width: 150px;
    clip-path: polygon(0 0, 100% 0, 86% 100%, 14% 100%);
    transition: width 0.3s ease, filter 0.15s ease;
}
a.funnel-bar:hover { filter: brightness(1.06); }
.funnel-bar.stage-lead       { background: linear-gradient(135deg, #6366f1, #8b5cf6); }
.funnel-bar.stage-soumission { background: linear-gradient(135deg, #0ea5e9, #06b6d4); }
.funnel-bar.stage-commande   { background: #3366ff; }
.funnel-count { font-weight: 700; font-size: 22px; line-height: 1.05; font-variant-numeric: tabular-nums; }
.funnel-stage-label { font-size: 11px; font-weight: 500; letter-spacing: 0.04em; text-transform: uppercase; opacity: 0.92; }
.funnel-meta { font-size: 12.5px; color: var(--text-secondary); text-align: center; margin: 3px 0 6px; }
.funnel-meta strong { color: var(--text-primary); }
.funnel-arrow { display: block; color: var(--text-muted); font-size: 14px; line-height: 1; }

/* ── Retour à la liste (en-tête des pages de détail) ─────────────────────────── */
.back-link {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: 13px; font-weight: 500; font-family: inherit;
    color: var(--text-secondary); text-decoration: none;
    margin-bottom: 12px; transition: color 0.12s ease;
}
.back-link:hover { color: var(--accent); }

/* ── Import d'un lead depuis « Nouvelle soumission » ─────────────────────────── */
.lead-import {
    display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
    padding: 14px 16px; margin-bottom: 16px;
    background: var(--accent-soft); border: 1px solid var(--border); border-radius: var(--radius-md);
}
.lead-import-txt { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 220px; }
.lead-import-txt strong { font-size: 14px; color: var(--text-primary); }
.lead-import-txt span { font-size: 12.5px; color: var(--text-secondary); }
.lead-import .input { max-width: 320px; }

/* ── Carte « Coordonnées & besoin » d'un lead (visuel moderne) ───────────────── */
.lead-identite { display: flex; align-items: center; gap: 14px; margin-bottom: 18px; }
.lead-avatar {
    flex: none; width: 52px; height: 52px; border-radius: 50%;
    display: grid; place-items: center;
    background: var(--accent-gradient); color: #fff;
    font-weight: 700; font-size: 18px; letter-spacing: 0.02em;
}
.lead-nom { font-weight: 650; font-size: 17px; letter-spacing: -0.01em; color: var(--text-primary); }
.lead-entreprise { font-size: 13px; color: var(--text-secondary); }
.lead-coords { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 10px; }
.lead-coord {
    display: flex; align-items: center; gap: 11px;
    padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px;
    background: var(--bg-glass); text-decoration: none; transition: border-color 0.12s ease, background 0.12s ease;
}
a.lead-coord:hover { border-color: var(--accent); background: var(--bg-glass-hover); }
.lead-coord.is-vide { opacity: 0.55; pointer-events: none; }
.lead-coord-ico {
    flex: none; width: 34px; height: 34px; border-radius: 9px;
    display: grid; place-items: center;
    background: var(--accent-soft); color: var(--accent);
}
.lead-coord-txt { display: flex; flex-direction: column; min-width: 0; }
.lead-coord-lbl { font-size: 10.5px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--text-muted); }
.lead-coord-val { font-size: 13.5px; color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lead-besoin {
    margin-top: 16px; padding: 14px 16px;
    border-radius: 12px; border: 1px solid var(--border);
    background: var(--accent-wash, var(--bg-glass));
}
.lead-besoin-lbl { font-size: 11px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--accent); margin-bottom: 5px; }
.lead-besoin-txt { font-size: 14.5px; line-height: 1.55; color: var(--text-primary); }
.lead-besoin-notes { font-size: 13px; color: var(--text-secondary); margin-top: 8px; }

/* Actions d'un lead : trois boutons à largeur égale (un tiers chacun). */
.actions-trois { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.actions-trois > * { width: 100%; justify-content: center; text-align: center; }
@media (max-width: 560px) { .actions-trois { grid-template-columns: 1fr; } }

.breadcrumbs {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    color: var(--text-muted);
}
.breadcrumbs a { color: var(--text-secondary); transition: color 0.12s ease; }
.breadcrumbs a:hover { color: var(--accent); }
.breadcrumbs-sep { color: var(--border); }

.detail-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 1px;
    background: var(--border-subtle);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    overflow: hidden;
}
.detail-field {
    background: var(--bg-secondary);
    padding: 14px 18px;
}
.detail-field dt {
    font-weight: 500; font-size: 11px; font-family: inherit;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 4px;
}
.detail-field dd {
    font-weight: 500; font-size: 14px; font-family: inherit;
    color: var(--text-primary);
    /* Les valeurs longues sans espaces (courriel, URL, adresse) se replient dans la
       case au lieu de déborder horizontalement. */
    overflow-wrap: anywhere;
}
.detail-field dd a { color: var(--accent); text-decoration: none; }
.detail-field dd a:hover { text-decoration: underline; }

/* ============================================================
   Empty state
   ============================================================ */
.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 8px;
    padding: 48px 24px;
    color: var(--text-secondary);
}
.empty-state-icon {
    width: 72px;
    height: 72px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--accent-soft);
    color: var(--accent);
    margin-bottom: 4px;
}
.empty-state-title { font-weight: 600; font-size: 17px; font-family: inherit; color: var(--text-primary); letter-spacing: -0.01em; }
.empty-state-body  { font-size: 13.5px; line-height: 1.55; max-width: 360px; color: var(--text-muted); margin-bottom: 8px; }

/* ---- Blazor error UI ---- */
#blazor-error-ui {
    display: none;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 1000;
    padding: 12px 24px;
    background: #fef2f2;
    color: #b91c1c;
    border-top: 1px solid rgba(239, 68, 68, 0.3);
    font-size: 13px;
}
#blazor-error-ui .dismiss { cursor: pointer; float: right; }

@media (max-width: 600px) {
    .page-header { flex-direction: column; align-items: stretch; }
    .search-field { min-width: 0; width: 100%; }
    .list-item { flex-direction: column; align-items: stretch; }
}

/* ============================================================
   Project detail — tabs, KPIs, people, data tables
   ============================================================ */
.section-title {
    font-weight: 600; font-size: 16px; font-family: inherit;
    letter-spacing: -0.01em;
    color: var(--text-primary);
    margin: 26px 0 12px;
}

/* ---- Tabs ---- */
.tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 2px;
    border-bottom: 1px solid var(--border);
    /* Espace sous les onglets réduit (au-dessus des barres d'outils) — interface plus compacte. */
    margin: 16px 0 12px;
}
.tab {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    background: none;
    border: 0;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    padding: 10px 14px;
    font-weight: 500; font-size: 14px; font-family: inherit;
    color: var(--text-muted);
    cursor: pointer;
    transition: color 0.15s ease, border-color 0.15s ease;
}
.tab:hover { color: var(--text-primary); }
.tab.is-active { color: var(--accent); border-bottom-color: var(--accent); }
.tab-count {
    font-size: 11px;
    font-weight: 600;
    padding: 1px 7px;
    border-radius: var(--radius-full);
    background: var(--bg-tertiary);
    color: var(--text-muted);
}
.tab.is-active .tab-count { background: var(--accent-soft); color: var(--accent); }

/* ---- KPI cards ---- */
.kpi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 12px;
    margin-bottom: 6px;
}
.kpi-card {
    display: flex;
    flex-direction: column;
    gap: 4px;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: 16px 18px;
}
.kpi-label { font-weight: 500; font-size: 11px; font-family: inherit; letter-spacing: 0.05em; text-transform: uppercase; color: var(--text-muted); }
.kpi-value { font-weight: 600; font-size: 22px; font-family: inherit; letter-spacing: -0.02em; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.kpi-value.neg { color: #dc2626; }
[data-theme="dark"] .kpi-value.neg { color: #f87171; }
.kpi-sub { font-size: 12px; color: var(--text-muted); }
/* Tuile KPI cliquable (ex. « Leads actifs » → /leads). */
a.kpi-card { text-decoration: none; color: inherit; transition: border-color 0.12s ease, background 0.12s ease; }
a.kpi-card:hover { border-color: var(--accent); background: var(--bg-glass-hover); }

/* ---- People ---- */
.person-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 12px;
}
.person-card {
    display: flex;
    flex-direction: column;
    gap: 3px;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: 14px 16px;
}
.person-role { font-weight: 500; font-size: 11px; font-family: inherit; letter-spacing: 0.05em; text-transform: uppercase; color: var(--text-muted); }
.person-name { font-weight: 600; font-size: 15px; font-family: inherit; color: var(--text-primary); margin-bottom: 3px; }
.person-line { font-size: 13px; color: var(--text-secondary); }
a.person-line:hover { color: var(--accent); }
.person-line.muted, .muted { color: var(--text-muted); }

/* ---- Data tables (budget, transactions, orders, reports, rates) ---- */
.data-scroll {
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    overflow: auto;
}
/* Les longues tables utilisent ~toute la hauteur d'écran restante (au lieu d'un plafond fixe à 560px)
   pour voir beaucoup plus de lignes sans rogner l'en-tête de page. Plancher pour les petits écrans. */
.data-scroll.tall { max-height: calc(100vh - 240px); min-height: 360px; }
.data-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
    white-space: nowrap;
}
/* Une table large défile DANS sa carte : le corps de page, lui, ne part jamais de côté. */
.table-scroll-x { overflow-x: auto; }
.data-table thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--bg-tertiary);
    text-align: left;
    padding: 10px 14px;
    font-weight: 600; font-size: 11px; font-family: inherit;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-muted);
    border-bottom: 1px solid var(--border);
}
.data-table tbody td {
    padding: 9px 14px;
    color: var(--text-primary);
    border-bottom: 1px solid var(--border-subtle);
    vertical-align: top;
}
.data-table tbody tr:hover { background: var(--bg-glass-hover); }
.data-table tfoot td {
    position: sticky;
    bottom: 0;
    background: var(--bg-tertiary);
    padding: 10px 14px;
    font-weight: 600;
    color: var(--text-primary);
    border-top: 1px solid var(--border);
    font-variant-numeric: tabular-nums;
}
.data-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.data-table .mono { font-family: 'JetBrains Mono', 'Fira Code', monospace; font-size: 12px; color: var(--text-secondary); }
.data-table .neg { color: #dc2626; }
[data-theme="dark"] .data-table .neg { color: #f87171; }
.data-table td.num.neg, .data-table .kpi-value.neg { color: #dc2626; }
/* économie (Écart positif : Budget ≥ Facturé) — vert */
.data-table .pos { color: #16a34a; }
[data-theme="dark"] .data-table .pos { color: #4ade80; }

/* (L'ancienne pastille d'affichage « heures » du kit de départ vivait ici. Elle
   portait le même nom `.chip` que le bouton-pastille du style guide et l'écrasait
   dans la cascade ; elle n'était plus utilisée nulle part — supprimée.) */

/* Document link button in transaction / order tables */
.file-link {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 4px 10px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-elevated);
    color: var(--text-secondary);
    font-weight: 500; font-size: 12px; font-family: inherit;
    white-space: nowrap;
    transition: border-color 0.12s ease, color 0.12s ease;
}
.file-link:hover { border-color: var(--accent); color: var(--accent); }
.file-link-empty { color: var(--text-muted); }

/* ---- Onglet Avenant : tableau maître-détail extensible ---- */
/* Le bouton « Voir détails » / « Masquer » de chaque ligne parent utilise `.btn-link`
   (défini une seule fois dans la section Buttons). */
/* Ligne d'en-tête des sous-lignes (petite légende). */
.data-table tbody tr.avenant-sub-head td {
    background: var(--bg-tertiary);
    padding-left: 32px;
    font-weight: 600; font-size: 10px; font-family: inherit;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-muted);
}
/* Sous-lignes de documents : fond subtil + indentation à gauche pour lire comme du détail imbriqué. */
.data-table tbody tr.avenant-sub td { background: var(--bg-glass); }
.data-table tbody tr.avenant-sub td:first-child { padding-left: 32px; }
.data-table tbody tr.avenant-sub:hover { background: transparent; }

.detail-grid.compact { grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); margin-bottom: 14px; }
.detail-card + .data-scroll { margin-top: 0; }

/* ---- DataTable: filter row + empty state ---- */
.data-table-wrap { display: flex; flex-direction: column; gap: 12px; }
.table-filter { min-width: 0; width: 100%; max-width: 380px; }
.table-filter .search-input { padding-right: 70px; }
.table-filter-count {
    position: absolute;
    right: 12px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 12px;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
    pointer-events: none;
}
.data-table .empty-row { text-align: center; color: var(--text-muted); padding: 22px; }

/* ---- View toggle (Tableau / Graphique) ---- */
.view-toggle {
    display: inline-flex;
    gap: 2px;
    padding: 2px;
    margin-bottom: 14px;
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
}
.view-btn {
    background: none;
    border: 0;
    padding: 6px 16px;
    font-weight: 500; font-size: 13px; font-family: inherit;
    color: var(--text-muted);
    border-radius: calc(var(--radius-md) - 3px);
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
}
.view-btn:hover { color: var(--text-primary); }
.view-btn.is-active { background: var(--accent-fill); color: #fff; }

/* ---- Budget treemap ---- */
.treemap { display: flex; flex-direction: column; gap: 12px; }
.treemap-crumbs { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 13px; }
.treemap-crumb {
    background: none;
    border: 0;
    padding: 2px 4px;
    font-weight: 600; font-size: 13px; font-family: inherit;
    color: var(--text-secondary);
    cursor: pointer;
}
.treemap-crumb:hover { color: var(--accent); }
.treemap-crumb.is-active { color: var(--text-primary); cursor: default; }
.treemap-crumb-sep { color: var(--text-muted); }
.treemap-hint { margin-left: auto; color: var(--text-muted); font-size: 12px; }
.treemap-crumbs { justify-content: space-between; }
.treemap-title { font-weight: 500; font-size: 13px; font-family: inherit; color: var(--text-secondary); }
.treemap-legend { display: flex; gap: 14px; flex-wrap: wrap; }
.legend-item { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-muted); }
.legend-dot { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }
/* #2 — indicateurs cliquables (boutons de tri) du graphique d'écart au budget. */
.legend-btn { border: 1px solid var(--border, #d7dde3); background: var(--surface, #fff); border-radius: 999px; padding: 3px 10px; cursor: pointer; line-height: 1.4; transition: background .12s, border-color .12s, color .12s; }
.legend-btn:hover { border-color: var(--accent, #0a7a45); color: var(--text-secondary); }
.legend-btn.is-active { border-color: var(--accent, #0a7a45); background: rgba(10, 122, 69, .10); color: var(--text-secondary); font-weight: 600; }

/* #6 — niveau « facture » (2e imbrication) du résumé de contrat : léger retrait + fond plus pâle. */
.suivi-sub-2 > td:first-child { padding-left: 28px; }
.suivi-sub-2 { background: rgba(125, 125, 125, .04); }

/* #4 — édition en ligne de la DP dans le suivi d'heures. */
.dp-edit { display: inline-flex; align-items: center; gap: 4px; }
.dp-input { width: 72px; padding: 2px 6px; text-align: right; }
.dp-edit-btn { margin-left: 6px; opacity: .55; }
.dp-edit-btn:hover { opacity: 1; }

/* ---- Budget bar chart (facturé vs budget, par activité) ---- */
.budget-bars { display: flex; flex-direction: column; gap: 14px; }
.bars-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.bars-title { font-weight: 500; font-size: 13px; font-family: inherit; color: var(--text-secondary); max-width: 560px; }
.bars-legend { display: flex; gap: 14px; flex-wrap: wrap; }
.bars-body { display: flex; gap: 14px; align-items: flex-start; }
.bars-list { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.bar-row {
    display: grid;
    grid-template-columns: 220px 1fr 156px;
    align-items: center;
    gap: 14px;
    padding: 5px 8px;
    border-radius: 7px;
    cursor: pointer;
    transition: background 0.12s ease;
}
.bar-row:hover { background: var(--bg-glass-hover); }
.bar-row.is-selected { background: var(--accent-soft); }
.bar-label { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.bar-code { font-family: 'JetBrains Mono', 'Fira Code', monospace; font-size: 12px; color: var(--text-muted); }
.bar-desc { font-size: 12.5px; color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bar-track {
    position: relative;
    height: 22px;
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    border-radius: 5px;
    overflow: hidden;
}
.bar-fill { position: absolute; left: 0; top: 0; height: 100%; border-radius: 4px 0 0 4px; transition: width 0.2s ease; }
.bar-budget-line { position: absolute; left: 50%; top: 0; bottom: 0; width: 2px; background: var(--text-secondary); opacity: 0.7; }
.bar-meta { text-align: right; display: flex; flex-direction: column; gap: 1px; }
.bar-pct { font-weight: 700; font-size: 13px; font-family: inherit; font-variant-numeric: tabular-nums; }
.bar-ecart { font-size: 11.5px; font-variant-numeric: tabular-nums; }
.bar-ecart.over { color: #dc2626; }
.bar-ecart.under { color: var(--text-muted); }
[data-theme="dark"] .bar-ecart.over { color: #f87171; }

/* Detail panel beside the bars — reuses the figures styling, stays in view while scrolling. */
.bars-detail {
    position: sticky;
    top: calc(var(--appbar-h) + 12px);
    flex: 0 0 250px;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: 14px 16px;
}

@media (max-width: 760px) {
    .bars-body { flex-direction: column; }
    .bars-detail { position: static; flex-basis: auto; width: 100%; }
    .bar-row { grid-template-columns: 110px 1fr 120px; gap: 8px; }
}

.treemap-body { display: flex; gap: 14px; align-items: flex-start; }
.treemap-svg {
    flex: 1 1 auto;
    width: 100%;
    height: auto;
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: var(--bg-secondary);
    overflow: visible;
}
.treemap-tile { cursor: pointer; }
.treemap-tile rect { transition: opacity 0.12s ease; }
.treemap-tile:hover rect { opacity: 0.86; }
.treemap-tile rect.is-selected { stroke: var(--text-primary); stroke-width: 3; }
.treemap-label { font: 600 13px 'Inter', sans-serif; pointer-events: none; }
.treemap-amount { font: 500 12px 'Inter', sans-serif; pointer-events: none; opacity: 0.92; font-variant-numeric: tabular-nums; }
.treemap-dev { font: 700 12px 'Inter', sans-serif; pointer-events: none; }
.treemap-state { font-weight: 600; font-size: 13px; font-family: inherit; margin-bottom: 12px; }

.treemap-detail {
    flex: 0 0 250px;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: 14px 16px;
}
.treemap-detail-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; }
.treemap-detail-close { background: none; border: 0; color: var(--text-muted); cursor: pointer; font-size: 14px; }
.treemap-detail-close:hover { color: var(--text-primary); }
.treemap-detail-title { font-weight: 600; font-size: 14px; font-family: inherit; color: var(--text-primary); margin-bottom: 12px; line-height: 1.4; }
.treemap-figures { display: flex; flex-direction: column; gap: 8px; }
.treemap-figures > div { display: flex; justify-content: space-between; gap: 12px; font-size: 13px; }
.treemap-figures dt { color: var(--text-muted); }
.treemap-figures dd { color: var(--text-primary); font-variant-numeric: tabular-nums; font-weight: 500; }
.treemap-figures dd.neg { color: #dc2626; }
[data-theme="dark"] .treemap-figures dd.neg { color: #f87171; }
.treemap-figures dd.pos { color: #16a34a; }
[data-theme="dark"] .treemap-figures dd.pos { color: #4ade80; }

@media (max-width: 720px) {
    .treemap-body { flex-direction: column; }
    .treemap-detail { flex-basis: auto; width: 100%; }
}

/* ============================================================
   Forms (new project, new rates, new report)
   ============================================================ */
.header-tools { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.header-actions { display: flex; gap: 10px; align-items: center; }

/* ---- Projects list filter bar ---- */
.filter-bar {
    display: flex;
    align-items: center;
    gap: 18px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}
.filter-check { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-secondary); cursor: pointer; user-select: none; }
.filter-check input { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; }
.filter-years { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.filter-label { font-size: 13px; color: var(--text-muted); }
/* Les pastilles de filtre utilisent `.chip` / `.chip.is-on` (section Buttons) :
   une seule pastille dans toute l'app, celle du style guide. */
.filter-count { margin-left: auto; font-size: 13px; color: var(--text-muted); font-variant-numeric: tabular-nums; }

.tab-toolbar { display: flex; justify-content: flex-end; margin-bottom: 14px; }
.toolbar-locked { font-size: 13px; color: var(--text-muted); display: inline-flex; align-items: center; gap: 6px; }

.form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 14px;
    margin-bottom: 4px;
}
.form-grid.tight { grid-template-columns: repeat(auto-fill, minmax(155px, 1fr)); gap: 10px; }
.form-field { display: flex; flex-direction: column; gap: 5px; }
.form-field.span-2 { grid-column: span 2; }
.form-field label { font-weight: 500; font-size: 12px; font-family: inherit; color: var(--text-secondary); }
.form-field .req { color: #dc2626; }
[data-theme="dark"] .form-field .req { color: #f87171; }

.form-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 10px;
    margin-top: 18px;
}
.form-running-total { margin-right: auto; color: var(--text-secondary); font-size: 13px; }
.form-running-total strong { color: var(--text-primary); font-variant-numeric: tabular-nums; }

.form-card { margin-bottom: 18px; }
.form-card-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.form-card-head h3 { font-weight: 600; font-size: 16px; font-family: inherit; color: var(--text-primary); }
.form-card-close { background: none; border: 0; color: var(--text-muted); cursor: pointer; font-size: 15px; }
.form-card-close:hover { color: var(--text-primary); }
.form-subhead { font-weight: 600; font-size: 12px; font-family: inherit; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-muted); margin: 18px 0 10px; }

.form-banner {
    padding: 11px 14px;
    border-radius: var(--radius-sm);
    font-size: 13.5px;
    margin-bottom: 14px;
}
.form-banner.success { background: var(--accent-soft); color: var(--accent); border: 1px solid var(--accent); }
.form-banner.error {
    background: rgba(239, 68, 68, 0.1);
    color: #dc2626;
    border: 1px solid rgba(239, 68, 68, 0.4);
}
[data-theme="dark"] .form-banner.error { color: #f87171; }

.form-hint { color: var(--text-muted); font-size: 13px; margin-bottom: 12px; }

/* ---- Editable budget-entry table (new project) ---- */
.entry-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.entry-table thead th {
    text-align: left;
    padding: 9px 12px;
    font-weight: 600; font-size: 11px; font-family: inherit;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-muted);
    background: var(--bg-tertiary);
    border-bottom: 1px solid var(--border);
}
.entry-table thead th.num { text-align: right; }
.entry-table tbody td { padding: 6px 10px; border-bottom: 1px solid var(--border-subtle); vertical-align: middle; }
.entry-table tbody td .input { padding: 7px 9px; }
.entry-table .mono-input { font-family: 'JetBrains Mono', 'Fira Code', monospace; }
.entry-table .num-input { text-align: right; font-variant-numeric: tabular-nums; }
.entry-table .empty-row { text-align: center; color: var(--text-muted); padding: 20px; }
.entry-table tfoot td {
    padding: 10px 12px;
    font-weight: 600;
    color: var(--text-primary);
    background: var(--bg-tertiary);
    border-top: 1px solid var(--border);
    font-variant-numeric: tabular-nums;
}
.entry-table tfoot td.num { text-align: right; }
/* Le « ✕ » de suppression d'une ligne est un bouton-icône `.btn-icon danger compact`
   (section Buttons). */

/* ── Pastilles de statut + listes ───────────────────────────────────────────── */
.pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 10px;
    border-radius: var(--radius-full, 999px);
    background: var(--accent-soft);
    color: var(--accent);
    font-weight: 600; font-size: 12px; font-family: inherit;
}
.pill-ok    { background: rgba(34, 197, 94, 0.14);  color: #137638; }
.pill-warn  { background: rgba(234, 179, 8, 0.16);  color: #945a06; }
/* Couleur distincte par statut de soumission :
   Brouillon = jaune · Envoyée = bleu · Acceptée = vert (pill-ok) ·
   Refusée ET Expirée = rouge (le dossier est mort, il faut agir) ·
   Convertie en commande = violet. */
.pill-jaune  { background: rgba(250, 204, 21, 0.22); color: #854d0e; }
.pill-bleu   { background: rgba(59, 130, 246, 0.16); color: #1d4ed8; }
.pill-rouge  { background: rgba(239, 68, 68, 0.15);  color: #b91c1c; }
.pill-violet { background: rgba(139, 92, 246, 0.16); color: #6d28d9; }
[data-theme="dark"] .pill-ok     { color: #4ade80; }
[data-theme="dark"] .pill-warn   { color: #fbbf24; }
[data-theme="dark"] .pill-jaune  { color: #facc15; }
[data-theme="dark"] .pill-bleu   { color: #60a5fa; }
[data-theme="dark"] .pill-rouge  { color: #f87171; }
[data-theme="dark"] .pill-violet { color: #a78bfa; }

.clean-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.clean-list-row { display: flex; align-items: center; gap: 10px; font-size: 13.5px; color: var(--text-secondary); }

/* ── Listes de totaux et blocs de fiche ──────────────────────────────────────
   Ces deux-là étaient recopiés dans le CSS scoped de chaque fiche. Ils montent
   ici parce que la fiche commande est désormais faite de PLUSIEURS composants
   (entête, lignes, cycle de vie…) : une règle scoped à la page ne les atteindrait
   plus. Les autres fiches gardent leur copie locale, qui l'emporte — rien ne
   bouge chez elles. */
.totaux-liste { list-style: none; margin: 0; padding: 0; }
.totaux-liste li {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 7px 0;
    border-bottom: 1px solid var(--border-subtle);
    font-size: 13.5px;
}
.totaux-liste li span { color: var(--text-secondary); }
.totaux-liste li strong { font-variant-numeric: tabular-nums; text-align: right; }
.totaux-liste li.total {
    border-bottom: none;
    border-top: 2px solid var(--accent);
    margin-top: 4px;
    padding-top: 10px;
    font-size: 16px;
}
.totaux-liste li.total strong { color: var(--accent); }

.commande-bloc { border-top: 1px solid var(--border); padding-top: 14px; }
.commande-bloc .stitle { font-size: 14px; font-weight: 600; color: var(--text-primary); }

/* ── Production : barre d'avancement + pointage rapide ──────────────────────── */
.prod-bar {
    display: inline-block;
    width: 90px;
    height: 8px;
    border-radius: var(--radius-full, 999px);
    background: var(--border-subtle);
    overflow: hidden;
    vertical-align: middle;
    flex: none;
}
.prod-bar.lg { width: 160px; height: 10px; }
.prod-bar-fill {
    display: block;
    height: 100%;
    border-radius: inherit;
    background: #3366ff;
    transition: width 0.25s ease;
}

.pointage { display: inline-flex; align-items: center; gap: 6px; justify-content: flex-end; }
.pointage-btns { display: inline-flex; align-items: center; gap: 4px; }
/* Champ pour fixer la quantité faite exacte d'une étape de production. */
.input.prod-set { width: 58px; min-width: 0; padding: 4px 6px; font-size: 12px; text-align: right; font-variant-numeric: tabular-nums; }
/* Le profileur d'une ligne, sur la vue plancher — la machine qui fait la pièce. */
.input.prod-poste { width: auto; min-width: 130px; padding: 4px 6px; font-size: 12px; }
/* Les boutons de pointage utilisent la pastille `.chip` du style guide (section Buttons). */
.pointage-btns .chip { padding: 4px 9px; }

/* ============================================================
   Configuration — barre latérale groupée
   Idiome maison : les écrans de configuration se choisissent dans
   une colonne collante, groupée par domaine — pas une rangée d'onglets qui
   passerait à la ligne quand un écran s'ajoute, ni une longue page à défiler.
   ============================================================ */
.config-layout {
    display: grid;
    grid-template-columns: 232px minmax(0, 1fr);
    gap: 28px;
    align-items: start;
}

.config-nav {
    display: grid;
    gap: 18px;
    position: sticky;
    top: calc(var(--appbar-h) + 20px);   /* la barre d'app est collante : s'en écarter */
}
.config-nav-group { display: grid; gap: 2px; }
.config-nav-title {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
    padding: 0 10px 6px;
}
.config-nav-item {
    appearance: none;
    /* Flex plutôt que bloc : le libellé à gauche, le compteur à droite quand il y en a
       un (fiche commande). Sans compteur — les écrans de configuration — c'est un
       no-op : le texte reste calé à gauche. */
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    background: none;
    border: none;
    border-left: 2px solid transparent;
    padding: 8px 12px;
    font: inherit;
    font-weight: 600;
    font-size: 13.5px;
    color: var(--text-secondary);
    text-align: left;
    cursor: pointer;
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    transition: color 0.12s ease, background-color 0.12s ease, border-color 0.12s ease;
}
.config-nav-item:hover { color: var(--text-primary); background: var(--bg-glass-hover); }
.config-nav-item.is-active {
    color: var(--accent);
    border-left-color: var(--accent);
    background: var(--bg-glass-hover);
}
/* Un lien vers un autre écran de réglage se présente comme les onglets — même
   colonne, même geste ; seul l'atterrissage diffère. */
a.config-nav-item { display: block; }

/* Le panneau ne doit jamais pousser la grille : les tableaux larges défilent chez eux. */
.config-panel { min-width: 0; }

/* Sous 900 px la barre repasse au-dessus du contenu, en rangée défilante — mieux
   qu'une colonne de 232 px qui mangerait la moitié d'un écran de portable. */
@media (max-width: 900px) {
    .config-layout { grid-template-columns: minmax(0, 1fr); gap: 18px; }
    .config-nav {
        position: static;
        grid-auto-flow: column;
        grid-auto-columns: max-content;
        gap: 20px;
        overflow-x: auto;
        padding-bottom: 6px;
        border-bottom: 1px solid var(--border);
    }
    .config-nav-group { grid-auto-flow: column; grid-auto-columns: max-content; gap: 4px; align-items: center; }
    .config-nav-title { padding: 0 6px 0 0; }
    .config-nav-item { border-left: none; border-bottom: 2px solid transparent; border-radius: var(--radius-sm); white-space: nowrap; }
    .config-nav-item.is-active { border-left-color: transparent; border-bottom-color: var(--accent); }
}

/* Interrupteur de section : une case cochée à hauteur de texte (norme maison). */
.config-check { display: flex; align-items: center; gap: 10px; padding: 6px 0; }
.config-check input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--accent); }

/* ── Zone de danger (idiome maison) : l'action irréversible a SA couleur, son
   onglet à part et sa carte teintée — impossible de la confondre avec un réglage. */
.config-nav-danger { color: var(--status-danger-texte); }
.config-nav-danger:hover { color: var(--status-danger-texte); }
.config-nav-danger.is-active { color: var(--status-danger-texte); border-left-color: var(--status-danger); }
@media (max-width: 900px) {
    .config-nav-danger.is-active { border-left-color: transparent; border-bottom-color: var(--status-danger); }
}

.danger-zone {
    border-color: rgba(239, 68, 68, 0.35);
    background:
        linear-gradient(180deg, rgba(239, 68, 68, 0.05) 0%, rgba(239, 68, 68, 0) 120px),
        var(--bg-secondary);
}
.danger-zone .form-card-head h3 { display: flex; align-items: center; gap: 8px; color: var(--status-danger-texte); }
.danger-ico { flex-shrink: 0; }

.btn-danger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    padding: 8px 16px;
    border: none;
    border-radius: var(--radius-sm);
    background: var(--status-danger);
    color: #ffffff;
    font: 500 13px/1 'Inter', system-ui, sans-serif;
    cursor: pointer;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
    transition: transform 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease;
}
.btn-danger:hover:not(:disabled)  { transform: translateY(-1px); box-shadow: 0 6px 14px rgba(239, 68, 68, 0.35), 0 2px 4px rgba(0, 0, 0, 0.06); }
.btn-danger:active:not(:disabled) { transform: translateY(0); }
.btn-danger:disabled { opacity: 0.45; cursor: default; }

/* ============================================================
   Cycle de vie d'une commande — le rail des phases et le fil des jalons
   Idiome maison : une commande ne se lit pas comme un dossier posé à côté d'un
   registre d'événements, elle se lit comme un PARCOURS. Le rail dit où on en est ;
   le fil dit ce qui est arrivé, dans l'ordre. Une demande de changement y prend
   exactement la même forme qu'un envoi en production — c'est la même chose : un
   moment de la vie de la commande.
   ============================================================ */
.cycle-rail {
    display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
    list-style: none; margin: 0 0 18px; padding: 0;
}
.cycle-rail li { display: flex; align-items: center; gap: 6px; }
.cycle-rail li::after { content: '›'; color: var(--text-muted); font-size: 15px; line-height: 1; }
.cycle-rail li:last-child::after { content: none; }
.cycle-phase-nom {
    display: inline-block; padding: 5px 12px; white-space: nowrap;
    border: 1px solid var(--border); border-radius: var(--radius-full);
    background: var(--bg-tertiary); color: var(--text-muted);
    font-size: 12.5px; line-height: 1.3;
}
.cycle-phase.is-done .cycle-phase-nom { color: var(--text-secondary); }
.cycle-phase.is-active .cycle-phase-nom {
    background: var(--accent-fill); border-color: transparent;
    color: #ffffff; font-weight: 600;
}

.cycle-fil { list-style: none; margin: 0; padding: 0; }
.cycle-jalon { position: relative; display: flex; gap: 12px; padding-bottom: 16px; }
/* Le trait qui relie les jalons : il part SOUS la puce et s'arrête au dernier. */
.cycle-jalon::before {
    content: ''; position: absolute; left: 5px; top: 18px; bottom: 0;
    width: 2px; background: var(--border);
}
.cycle-jalon:last-child { padding-bottom: 0; }
.cycle-jalon:last-child::before { content: none; }
.cycle-puce {
    position: relative; z-index: 1; flex: none;
    width: 12px; height: 12px; margin-top: 4px;
    border: 2px solid var(--border); border-radius: var(--radius-full);
    background: var(--bg-secondary);
}
.cycle-jalon.etat-fait    .cycle-puce { background: var(--status-success); border-color: var(--status-success); }
.cycle-jalon.etat-encours .cycle-puce {
    background: var(--status-warning); border-color: var(--status-warning);
    box-shadow: 0 0 0 4px rgba(245, 158, 11, 0.18);
}
.cycle-jalon.etat-barre   .cycle-puce { background: var(--status-danger); border-color: var(--status-danger); }

.cycle-corps { flex: 1; min-width: 0; }
.cycle-tete { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: 13.5px; }
/* Ce qui n'est pas encore arrivé se lit en retrait — sinon le fil crie autant pour
   ce qui reste à faire que pour ce qui est fait. */
.cycle-jalon.etat-attendu .cycle-tete strong { color: var(--text-muted); font-weight: 500; }
.cycle-detail {
    margin: 4px 0 0; font-size: 13px; line-height: 1.5;
    color: var(--text-secondary); white-space: pre-wrap;
}
.cycle-decision { margin-top: 10px; }

/* ── Les autorisations d'un changement en production ──────────────────────────
   Trois signatures avant qu'on puisse seulement proposer « Accepter ». Le bloc
   est encadré de rouge sans être alarmiste : ce n'est pas une erreur, c'est un
   processus qui coûte cher, et l'encadré dit « arrête-toi et lis ». */
.autorisations {
    border: 1px solid var(--status-danger);
    border-radius: 10px;
    padding: 12px 14px;
    margin-bottom: 12px;
    background: var(--bg-glass);
}
.autorisations-tete { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 8px; }
.autorisations-pourquoi { margin: 0 0 12px; font-size: 13px; line-height: 1.55; }

/* Une autorisation par palier. Le filet de gauche passe au vert dès qu'elle est donnée :
   l'avancement se lit d'un coup d'œil, sans compter les pastilles. */
.autorisation {
    border-left: 3px solid var(--border);
    padding: 8px 0 8px 12px;
}
.autorisation + .autorisation { border-top: 1px solid var(--border-subtle); }
.autorisation.est-donne { border-left-color: var(--status-success); }
.autorisation-tete { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; font-size: 13.5px; }

/* Le choix des composantes visées par un changement — une case par ligne, pas un
   <select multiple> : à trois composantes on veut les lire, pas les faire défiler. */
.cases-lignes { display: grid; gap: 4px; margin-top: 4px; }
.case-ligne {
    display: flex; align-items: center; gap: 8px;
    font-size: 13.5px; font-weight: 400; cursor: pointer;
}

/* ── Grille repliée par projet ────────────────────────────────────────────────
   Une ligne de GROUPE n'est pas une ligne de données : elle rassemble. Elle se
   distingue donc par un fond et un filet à gauche, jamais par du gras seul —
   à côté de vingt rangées, le gras ne se voit plus. */
.data-table tr.row-groupe > td {
    background: var(--bg-tertiary);
    border-left: 3px solid var(--accent);
    padding: 7px 10px;
}
.data-table tr.row-groupe.est-ouvert > td { border-bottom-color: transparent; }

.groupe-tete { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; }

/* Un vrai <button> : le chevron se prend au clavier comme à la souris. */
.groupe-bouton {
    display: inline-flex; align-items: center; gap: 8px;
    background: none; border: 0; padding: 4px 2px; margin: -4px 0;
    font: inherit; font-size: 13px; color: var(--text-primary); cursor: pointer;
}
.groupe-bouton:hover .groupe-libelle { text-decoration: underline; }
.groupe-caret { width: 12px; font-size: 11px; color: var(--text-muted); }
.groupe-libelle { font-weight: 600; }
.groupe-compte {
    border-radius: 999px; padding: 2px 8px; font-size: 11.5px; font-weight: 500;
    background: var(--bg-secondary); color: var(--text-muted);
}
.groupe-lien { font-size: 12px; }

/* Le résumé part à droite : c'est la colonne que l'œil descend pour comparer. */
.groupe-resume { margin-left: auto; }
.groupe-infos { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 6px; font-size: 12.5px; }
.groupe-cumul { font-variant-numeric: tabular-nums; font-weight: 600; }

/* Une ligne dépliée est EN RETRAIT sous son groupe — sans le décalage, le repli
   ne se lit plus et la grille redevient plate. */
.data-table tr.row-groupee > td:first-child { padding-left: 26px; position: relative; }
.data-table tr.row-groupee > td:first-child::before {
    content: ''; position: absolute; left: 12px; top: 0; bottom: 0;
    border-left: 1px solid var(--border);
}

/* L'interrupteur, à côté du filtre. */
.table-groupe-bascule {
    display: inline-flex; align-items: center; gap: 7px;
    margin: 0 0 10px; font-size: 12.5px; color: var(--text-muted); cursor: pointer;
}
.table-groupe-bascule input { cursor: pointer; }
